From 24a29f48db722082e89020832629c910062f574a Mon Sep 17 00:00:00 2001 From: Janez Date: Mon, 17 May 2021 15:46:39 +0200 Subject: [PATCH 001/226] Add notice to README.md --- .travis.yml | 9 +++------ README.md | 47 +++++++++++++++++++++++++++-------------------- 2 files changed, 30 insertions(+), 26 deletions(-) diff --git a/.travis.yml b/.travis.yml index 04ac2054..479da89a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -7,11 +7,11 @@ notifications: slack: rooms: - secure: "FId7MhkC2Fq8T9ETn5XrWw1STQusuhR7MbOz/YaCPLAvxvo4pPMyGKVu+1urrbvS9eW+o15xqL0dZow2/JG+6vxPgQIyHBcJT0LYfLROrHC22DhR2oydPO0Y4wejxWwcj4LzAXrI/09zynbX6tWphMM0MVbLRKL+WpJRVhAsCHB2FXHZxF2uT6774J+7dEpY2gtW676ShO4gU7DmD/bEOgasyvDqtpGtM4bxEQJubJr4iaUlxvGlQ8CJyBXfBxcviL5ufMjJxGmuDYHzKu2pxN1v6adfRA53CrgSlb2JIx+ubNx/xGJQN+XeGrnA6aRU15CE/6iC8qZ6CW5FBfcCESp6/JPpVeom3WHbYoXZBQbAOXDuLg+zHxF5N4kwSuZLapOcfIm7wppVlrSbY6cUZ5cNUnbVCfml+1BGC6R1++80wOaBG6g/IkHsbo3ZMtqibutg2BDEYoJeFq0GORySYPp5MTt2+iuKngLjtY4z9q2RWF+0e9/5rcYkUysUT7M0pP9SmKnI3Xvyxl853KY4xH7IiN+hZ4qoAGw4yQKJggPtUka9zihCxnxDyDOKnf6XVcZrPFucW2k2qwwZI9BMX5thNi2sB/3pAcA0kRC7yOGwLWLY21sTObB5QpDKJKeDYK1n9iss+xyIV2OoD7vwTw+sIeFFTTxyWA50AIdtmYU=" - + before_deploy: - cp $TRAVIS_BUILD_DIR/EDSSharp/bin/Release/EDSSharp.* $TRAVIS_BUILD_DIR/EDSEditorGUI/bin/Release/ - cd $TRAVIS_BUILD_DIR/EDSEditorGUI/bin/Release/ -- zip -r $TRAVIS_BUILD_DIR/build/OpenEDSEditor-latest.zip * +- zip -r $TRAVIS_BUILD_DIR/build/CANopenEditor-latest.zip * - cd $TRAVIS_BUILD_DIR deploy: @@ -23,7 +23,4 @@ deploy: directory: $TRAVIS_BUILD_DIR/build/ on: - branch: xdd - - - \ No newline at end of file + branch: master diff --git a/README.md b/README.md index 71c3e448..0d2ca1e0 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,10 @@ +CANopenEditor +============= +CANopen Object Dictionary Editor + - Imports: CANopen electronic data sheets in EDS or XDD format. + - Exports: CANopen electronic data sheets in EDS or XDD format, documentation, CANopenNode C source files. + +This is a fork from https://github.com/robincornelius/libedssharp, author Robin Cornelius. Join us on slack -------- @@ -13,43 +20,43 @@ EDSSharp A C# CanOpen EDS (Electronic Data Sheet) library and GUI editor -This application is designed to load/save/edit and create EDS/DCF/XDC file for -CanOpen and also to generate the object dictionary for CanOpenNode +This application is designed to load/save/edit and create EDS/DCF/XDC file for +CanOpen and also to generate the object dictionary for CanOpenNode CO_OD.c and CO_OD.h) to aid development of CanOpenNode devices. EDS (Electronic Data Sheet) files are text files that define CanOpen Devices. -DCF (Device Configuration File) files are text files that define configured -CanOpenDevices XDD files are an XML version of EDS files +DCF (Device Configuration File) files are text files that define configured +CanOpenDevices XDD files are an XML version of EDS files -EDS/DCF are fully defined in the DSP306 standard by the can open standards +EDS/DCF are fully defined in the DSP306 standard by the can open standards body CiA. -The EDS editor on its own is useful without the CanOpenNode specific export and -as of the 0.6-XDD-alpha version the editor can also load/save XDD files. +The EDS editor on its own is useful without the CanOpenNode specific export and +as of the 0.6-XDD-alpha version the editor can also load/save XDD files. The GUI also shows PDO mappings and can generate reports of multiple devices that are loaded into the software. The core library can be used without the GUI to implement eds/xdd loading/saving and parsing etc in other projects. -Please consider this code experimental and beta quality. +Please consider this code experimental and beta quality. It is a work in progress and is rapidly changing. -Every attempt has been made to comply with the revelant DSP306 and other -standards and esd files from multile sources have been tested for loading and +Every attempt has been made to comply with the revelant DSP306 and other +standards and esd files from multile sources have been tested for loading and saving as been (at times) validated for errors using EDS conformance tools. -With many thanks to the following contributors for spotting my mistakes and +With many thanks to the following contributors for spotting my mistakes and improving the code - * s-fuchs - * martinwag + * s-fuchs + * martinwag * trojanobelix * many others... Releases -------- -If you would like to try a pre compiled version, then head over to the +If you would like to try a pre compiled version, then head over to the [releases page!](https://github.com/robincornelius/libedssharp/releases) If you want to try the latest and greatest version from the development tip then it can be found here @@ -89,7 +96,7 @@ GUI * Delete exisiting OD entries * Create new Devices * Add default profiles -* Create profiles that can be added to any project (just save the device xml file to the profiles/ +* Create profiles that can be added to any project (just save the device xml file to the profiles/ directory, only include the minimum number of objects that you want to auto insert) This will auto add to insert menu * Edit Device and File Info sections * Set RX/TX PDO mappings easily from dropdown lists of avaiable objects @@ -100,7 +107,7 @@ GUI * View/edit actual object values for device configuring/DCF files * Support for loading XDD files (CanOpen offical XML) * Support for saving XDD files (CanOpen offical XML) -* Some module info is displayed in GUI showing avaiable modules (eds) and +* Some module info is displayed in GUI showing avaiable modules (eds) and configured modules (dcf) and what OD entries they reference. Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be. @@ -109,19 +116,19 @@ TODO ---- * Ensure and validate all XDD is loading/save correctly (Looking good so far) -* Add extra Gui fields for accessing extra XDD paramaters not in EDS +* Add extra Gui fields for accessing extra XDD paramaters not in EDS (all common ones are done, a few special/edge cases remain) * Look at XDC files and see if we can save config changes and allow editing and - network setup here in the app, partial support is implemented by supporting + network setup here in the app, partial support is implemented by supporting DCF files - + BUGS ---- If you find any, please open a bug report on github and attach any files you have created/opened etc. - + Pictures -------- From 280417fbdd112850fd84d9f4eaec45d28be27568 Mon Sep 17 00:00:00 2001 From: Janez Date: Mon, 17 May 2021 15:50:43 +0200 Subject: [PATCH 002/226] Update .travis.yml --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 479da89a..bd206953 100644 --- a/.travis.yml +++ b/.travis.yml @@ -23,4 +23,4 @@ deploy: directory: $TRAVIS_BUILD_DIR/build/ on: - branch: master + branch: main From 442980335b81497b1b5660bdb6fdd90d0eeef7c8 Mon Sep 17 00:00:00 2001 From: Carsten Frank Date: Fri, 21 May 2021 08:16:24 +0200 Subject: [PATCH 003/226] Add possibillity to control storage class of variables --- libEDSsharp/CanOpenNodeExporter_V4.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 39e524e1..d073d092 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -424,10 +424,10 @@ OD data declaration of all groups { if (ODStorage_t.Count > 0) { - file.WriteLine($"extern {odname}_{group}_t {odname}_{group};"); + file.WriteLine($"extern ATTRIBUTE_{group} {odname}_{group}_t {odname}_{group};"); } } - file.WriteLine($"extern OD_t *{odname};"); + file.WriteLine($"extern ATTRIBUTE_OD OD_t *{odname};"); file.WriteLine(string.Format(@" @@ -493,7 +493,7 @@ OD data initialization of all groups { if (ODStorage.Count > 0) { - file.WriteLine($"{odname}_{group}_t {odname}_{group} = {{"); + file.WriteLine($"ATTRIMUTE_{group} {odname}_{group}_t {odname}_{group} = {{"); file.WriteLine($" {string.Join(",\n ", ODStorage[group])}"); file.WriteLine($"}};\n"); } @@ -521,7 +521,7 @@ typedef struct {{ /******************************************************************************* Object dictionary *******************************************************************************/ -static OD_entry_t {0}List[] = {{ +static ATTRIBUTE_OD OD_entry_t {0}List[] = {{ {1}, {{0x0000, 0x00, 0, NULL, NULL}} }}; From 16aa40a8c4771ce806dc4cf8d9ac6deeb804d2fe Mon Sep 17 00:00:00 2001 From: Carsten Frank Date: Fri, 21 May 2021 08:19:27 +0200 Subject: [PATCH 004/226] Spelling error --- libEDSsharp/CanOpenNodeExporter_V4.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index d073d092..ed1ad7e3 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -493,7 +493,7 @@ OD data initialization of all groups { if (ODStorage.Count > 0) { - file.WriteLine($"ATTRIMUTE_{group} {odname}_{group}_t {odname}_{group} = {{"); + file.WriteLine($"ATTRIBUTE_{group} {odname}_{group}_t {odname}_{group} = {{"); file.WriteLine($" {string.Join(",\n ", ODStorage[group])}"); file.WriteLine($"}};\n"); } From 8fba901547adb56968269a52deb5899c73bf221c Mon Sep 17 00:00:00 2001 From: Carsten Frank Date: Fri, 21 May 2021 16:08:00 +0200 Subject: [PATCH 005/226] Initialization code for CO_config_t structure. Only nessesary if CO_MULTIPLE_OD is defined. --- libEDSsharp/CanOpenNodeExporter_V4.cs | 143 ++++++++++++++++++++++++-- 1 file changed, 137 insertions(+), 6 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 39e524e1..69bda9c2 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -43,7 +43,22 @@ public class CanOpenNodeExporter_V4 : IExporter private List ODDefines; private List ODDefinesLong; private Dictionary ODCnt; - + UInt16 CNT_NMT=0; + UInt16 CNT_HB_CONS=0; + UInt16 CNT_EM=0; + UInt16 CNT_SDO_SRV=0; + UInt16 CNT_SDO_CLI=0; + UInt16 CNT_TIME=0; + UInt16 CNT_SYNC=0; + UInt16 CNT_RPDO=0; + UInt16 CNT_TPDO=0; + UInt16 CNT_LEDS=0; + UInt16 CNT_GFC=0; + UInt16 CNT_SRDO=0; + UInt16 CNT_LSS_SLV=0; + UInt16 CNT_LSS_MST=0; + UInt16 CNT_GTWA=0; + UInt16 CNT_TRACE=0; /// /// export the current data set in the CanOpen Node format V4 /// @@ -59,7 +74,7 @@ public void export(string folderpath, string filename, string gitVersion, EDSsha Prepare(eds); Export_h(folderpath, filename, gitVersion, eds); - Export_c(folderpath, filename, gitVersion); + Export_c(folderpath, filename, gitVersion, eds); } #region Prepare @@ -83,12 +98,34 @@ private void Prepare(EDSsharp eds) List mappingErrors = eds.VerifyPDOMapping(); if (mappingErrors.Count > 0) Warnings.AddWarning($"Errors in PDO mappings:\r\n " + string.Join("\r\n ", mappingErrors), Warnings.warning_class.WARNING_BUILD); - foreach (ODentry od in eds.ods.Values) { if (od.prop.CO_disabled == true) continue; - + // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. + // Count objects for initialization of CO_config_t object. + if (od.Index==0x1017) + CNT_NMT++; + if (od.Index==0x1016) + CNT_HB_CONS=(UInt16)(od.subobjects.Count-1); + if (od.Index==0x1014 || od.Index==0x1015) + CNT_EM++; + if (od.Index>=0x1200 && od.Index<0x1280) + CNT_SDO_SRV++; + if (od.Index>=0x1280 && od.Index<0x1300) + CNT_SDO_CLI++; + if (od.Index==0x1012) + CNT_TIME++; + if (od.Index==0x1005) + CNT_SYNC++; + if (od.Index>=0x1400 && od.Index<0x1500) + CNT_RPDO++; + if (od.Index>=0x1800 && od.Index<0x1900) + CNT_TPDO++; + if (od.Index==0x1300) + CNT_GFC++; + if (od.Index>=0x1301 && od.Index<0x1380) + CNT_SRDO++; string indexH = $"{od.Index:X4}"; string cName = Make_cname(od.parameter_name); string varName = $"{indexH}_{cName}"; @@ -142,6 +179,25 @@ private void Prepare(EDSsharp eds) ODCnt.Add(od.prop.CO_countLabel, 1); } } + CNT_SRDO=(UInt16)(CNT_SRDO/2); + // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. + if (ODCnt.Count==0) { + ODCnt.Add("CNT_HB_CONS", CNT_HB_CONS); + ODCnt.Add("CNT_NMT", CNT_NMT); + ODCnt.Add("CNT_EM", CNT_EM); + ODCnt.Add("CNT_SDO_SRV", CNT_SDO_SRV); + ODCnt.Add("CNT_SDO_CLI", CNT_SDO_CLI); + ODCnt.Add("CNT_TIME", CNT_TIME); + ODCnt.Add("CNT_SYNC", CNT_SYNC); + ODCnt.Add("CNT_RPDO", CNT_RPDO); + ODCnt.Add("CNT_TPDO", CNT_TPDO); + ODCnt.Add("CNT_GFC", CNT_GFC); + ODCnt.Add("CNT_SRDO", CNT_SRDO); + ODCnt.Add("CNT_LSS_SLV", CNT_LSS_SLV); + ODCnt.Add("CNT_LSS_MST", CNT_LSS_MST); + ODCnt.Add("CNT_GTWA", CNT_GTWA); + ODCnt.Add("CNT_TRACE", CNT_TRACE); + } } /// @@ -449,13 +505,20 @@ Object dictionary entries - shortcuts with names file.Close(); } + + string FirstLower(string s) + { + if(string.IsNullOrEmpty(s)) + return s; + return s[0].ToString().ToLower() + s.Substring(1); + } /// /// Export the c file /// /// /// /// - private void Export_c(string folderpath, string filename, string gitVersion) + private void Export_c(string folderpath, string filename, string gitVersion, EDSsharp eds) { if (filename == "") @@ -484,8 +547,76 @@ libedssharp Object Dictionary Editor v{0} #if CO_VERSION_MAJOR < 4 #error This Object dictionary is compatible with CANopenNode V4.0 and above! #endif", gitVersion, filename)); - file.WriteLine(@" +/******************************************************************************* + OD config structure +*******************************************************************************/ +#ifdef CO_MULTIPLE_OD"); + + string xxENTRY_H1017 = eds.ods.ContainsKey(0x1017) ? ($"{odname}_ENTRY_H1017_{FirstLower(eds.ods[0x1017].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1016 = eds.ods.ContainsKey(0x1016) ? ($"{odname}_ENTRY_H1016_{FirstLower(eds.ods[0x1016].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1001 = eds.ods.ContainsKey(0x1001) ? ($"{odname}_ENTRY_H1001_{FirstLower(eds.ods[0x1001].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1014 = eds.ods.ContainsKey(0x1014) ? ($"{odname}_ENTRY_H1014_{FirstLower(eds.ods[0x1014].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1015 = eds.ods.ContainsKey(0x1015) ? ($"{odname}_ENTRY_H1015_{FirstLower(eds.ods[0x1015].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1003 = eds.ods.ContainsKey(0x1003) ? ($"{odname}_ENTRY_H1003_{FirstLower(eds.ods[0x1003].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1200 = eds.ods.ContainsKey(0x1200) ? ($"{odname}_ENTRY_H1200_{FirstLower(eds.ods[0x1200].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1280 = eds.ods.ContainsKey(0x1280) ? ($"{odname}_ENTRY_H1280_{FirstLower(eds.ods[0x1280].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1012 = eds.ods.ContainsKey(0x1012) ? ($"{odname}_ENTRY_H1012_{FirstLower(eds.ods[0x1012].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1005 = eds.ods.ContainsKey(0x1005) ? ($"{odname}_ENTRY_H1005_{FirstLower(eds.ods[0x1005].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1006 = eds.ods.ContainsKey(0x1006) ? ($"{odname}_ENTRY_H1006_{FirstLower(eds.ods[0x1006].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1007 = eds.ods.ContainsKey(0x1007) ? ($"{odname}_ENTRY_H1007_{FirstLower(eds.ods[0x1007].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1019 = eds.ods.ContainsKey(0x1019) ? ($"{odname}_ENTRY_H1019_{FirstLower(eds.ods[0x1019].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1400 = eds.ods.ContainsKey(0x1400) ? ($"{odname}_ENTRY_H1400_{FirstLower(eds.ods[0x1400].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1600 = eds.ods.ContainsKey(0x1600) ? ($"{odname}_ENTRY_H1600_{FirstLower(eds.ods[0x1600].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1800 = eds.ods.ContainsKey(0x1800) ? ($"{odname}_ENTRY_H1800_{FirstLower(eds.ods[0x1800].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1A00 = eds.ods.ContainsKey(0x1A00) ? ($"{odname}_ENTRY_H1A00_{FirstLower(eds.ods[0x1A00].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1300 = eds.ods.ContainsKey(0x1300) ? ($"{odname}_ENTRY_H1300_{FirstLower(eds.ods[0x1300].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1301 = eds.ods.ContainsKey(0x1301) ? ($"{odname}_ENTRY_H1301_{FirstLower(eds.ods[0x1301].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H1381 = eds.ods.ContainsKey(0x1381) ? ($"{odname}_ENTRY_H1381_{FirstLower(eds.ods[0x1381].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H13FE = eds.ods.ContainsKey(0x13FE) ? ($"{odname}_ENTRY_H13FE_{FirstLower(eds.ods[0x13FE].parameter_name.Replace(" ",""))}"):("NULL"); + string xxENTRY_H13FF = eds.ods.ContainsKey(0x13FF) ? ($"{odname}_ENTRY_H13FF_{FirstLower(eds.ods[0x13FF].parameter_name.Replace(" ",""))}"):("NULL"); + file.WriteLine($"const CO_config_t {odname}_config = {{"); + file.WriteLine($@" .CNT_NMT={CNT_NMT}, + .ENTRY_H1017={xxENTRY_H1016}, + .CNT_HB_CONS={CNT_HB_CONS}, + .ENTRY_H1016={xxENTRY_H1016}, + .CNT_EM={CNT_EM}, + .ENTRY_H1001={xxENTRY_H1001}, + .ENTRY_H1014={xxENTRY_H1014}, + .ENTRY_H1015={xxENTRY_H1015}, + .ENTRY_H1003={xxENTRY_H1003}, + .CNT_SDO_SRV={CNT_SDO_SRV}, + .ENTRY_H1200={xxENTRY_H1200}, + .CNT_SDO_CLI={CNT_SDO_CLI}, + .ENTRY_H1280={xxENTRY_H1280}, + .CNT_TIME={CNT_TIME}, + .ENTRY_H1012={xxENTRY_H1012}, + .CNT_SYNC={CNT_SYNC}, + .ENTRY_H1005={xxENTRY_H1005}, + .ENTRY_H1006={xxENTRY_H1006}, + .ENTRY_H1007={xxENTRY_H1007}, + .ENTRY_H1019={xxENTRY_H1019}, + .CNT_RPDO={CNT_RPDO}, + .ENTRY_H1400={xxENTRY_H1400}, + .ENTRY_H1600={xxENTRY_H1600}, + .CNT_TPDO={CNT_TPDO}, + .ENTRY_H1800={xxENTRY_H1800}, + .ENTRY_H1A00={xxENTRY_H1A00}, + .CNT_LEDS={CNT_LEDS}, + .CNT_GFC={CNT_GFC}, + .ENTRY_H1300={xxENTRY_H1300}, + .CNT_SRDO={CNT_SRDO}, + .ENTRY_H1301={xxENTRY_H1301}, + .ENTRY_H1381={xxENTRY_H1381}, + .ENTRY_H13FE={xxENTRY_H13FE}, + .ENTRY_H13FF={xxENTRY_H13FF}, + .CNT_LSS_SLV={CNT_LSS_SLV}, + .CNT_LSS_MST={CNT_LSS_MST}, + .CNT_GTWA={CNT_GTWA}, + .CNT_TRACE={CNT_TRACE}" + ); + file.WriteLine(@"} +#endif /******************************************************************************* OD data initialization of all groups *******************************************************************************/"); From 2b825de333cef667c96551c9affb9e3629539ab5 Mon Sep 17 00:00:00 2001 From: Carsten Frank Date: Fri, 28 May 2021 17:14:53 +0200 Subject: [PATCH 006/226] C MACRO for initializattion of CO_config_t --- libEDSsharp/CanOpenNodeExporter_V4.cs | 155 +++++++++++++------------- 1 file changed, 75 insertions(+), 80 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 69bda9c2..14d0276a 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -108,7 +108,7 @@ private void Prepare(EDSsharp eds) CNT_NMT++; if (od.Index==0x1016) CNT_HB_CONS=(UInt16)(od.subobjects.Count-1); - if (od.Index==0x1014 || od.Index==0x1015) + if ((od.Index==0x1014 || od.Index==0x1015) && CNT_EM==0) CNT_EM++; if (od.Index>=0x1200 && od.Index<0x1280) CNT_SDO_SRV++; @@ -460,9 +460,78 @@ Counters of OD objects { file.WriteLine($"#define {odname}_CNT_{kvp.Key} {kvp.Value}"); } - - file.WriteLine(@" - + file.WriteLine(@" +/******************************************************************************* + OD config structure +*******************************************************************************/ +#ifdef CO_MULTIPLE_OD +#include ""CANopen.h"""); + + string xxENTRY_H1017 = eds.ods.ContainsKey(0x1017) ? ($"{odname}_ENTRY_H1017_{Make_cname(eds.ods[0x1017].parameter_name)}"):("NULL"); + string xxENTRY_H1016 = eds.ods.ContainsKey(0x1016) ? ($"{odname}_ENTRY_H1016_{Make_cname(eds.ods[0x1016].parameter_name)}"):("NULL"); + string xxENTRY_H1001 = eds.ods.ContainsKey(0x1001) ? ($"{odname}_ENTRY_H1001_{Make_cname(eds.ods[0x1001].parameter_name)}"):("NULL"); + string xxENTRY_H1014 = eds.ods.ContainsKey(0x1014) ? ($"{odname}_ENTRY_H1014_{Make_cname(eds.ods[0x1014].parameter_name)}"):("NULL"); + string xxENTRY_H1015 = eds.ods.ContainsKey(0x1015) ? ($"{odname}_ENTRY_H1015_{Make_cname(eds.ods[0x1015].parameter_name)}"):("NULL"); + string xxENTRY_H1003 = eds.ods.ContainsKey(0x1003) ? ($"{odname}_ENTRY_H1003_{Make_cname(eds.ods[0x1003].parameter_name)}"):("NULL"); + string xxENTRY_H1200 = eds.ods.ContainsKey(0x1200) ? ($"{odname}_ENTRY_H1200_{Make_cname(eds.ods[0x1200].parameter_name)}"):("NULL"); + string xxENTRY_H1280 = eds.ods.ContainsKey(0x1280) ? ($"{odname}_ENTRY_H1280_{Make_cname(eds.ods[0x1280].parameter_name)}"):("NULL"); + string xxENTRY_H1012 = eds.ods.ContainsKey(0x1012) ? ($"{odname}_ENTRY_H1012_{Make_cname(eds.ods[0x1012].parameter_name)}"):("NULL"); + string xxENTRY_H1005 = eds.ods.ContainsKey(0x1005) ? ($"{odname}_ENTRY_H1005_{Make_cname(eds.ods[0x1005].parameter_name)}"):("NULL"); + string xxENTRY_H1006 = eds.ods.ContainsKey(0x1006) ? ($"{odname}_ENTRY_H1006_{Make_cname(eds.ods[0x1006].parameter_name)}"):("NULL"); + string xxENTRY_H1007 = eds.ods.ContainsKey(0x1007) ? ($"{odname}_ENTRY_H1007_{Make_cname(eds.ods[0x1007].parameter_name)}"):("NULL"); + string xxENTRY_H1019 = eds.ods.ContainsKey(0x1019) ? ($"{odname}_ENTRY_H1019_{Make_cname(eds.ods[0x1019].parameter_name)}"):("NULL"); + string xxENTRY_H1400 = eds.ods.ContainsKey(0x1400) ? ($"{odname}_ENTRY_H1400_{Make_cname(eds.ods[0x1400].parameter_name)}"):("NULL"); + string xxENTRY_H1600 = eds.ods.ContainsKey(0x1600) ? ($"{odname}_ENTRY_H1600_{Make_cname(eds.ods[0x1600].parameter_name)}"):("NULL"); + string xxENTRY_H1800 = eds.ods.ContainsKey(0x1800) ? ($"{odname}_ENTRY_H1800_{Make_cname(eds.ods[0x1800].parameter_name)}"):("NULL"); + string xxENTRY_H1A00 = eds.ods.ContainsKey(0x1A00) ? ($"{odname}_ENTRY_H1A00_{Make_cname(eds.ods[0x1A00].parameter_name)}"):("NULL"); + string xxENTRY_H1300 = eds.ods.ContainsKey(0x1300) ? ($"{odname}_ENTRY_H1300_{Make_cname(eds.ods[0x1300].parameter_name)}"):("NULL"); + string xxENTRY_H1301 = eds.ods.ContainsKey(0x1301) ? ($"{odname}_ENTRY_H1301_{Make_cname(eds.ods[0x1301].parameter_name)}"):("NULL"); + string xxENTRY_H1381 = eds.ods.ContainsKey(0x1381) ? ($"{odname}_ENTRY_H1381_{Make_cname(eds.ods[0x1381].parameter_name)}"):("NULL"); + string xxENTRY_H13FE = eds.ods.ContainsKey(0x13FE) ? ($"{odname}_ENTRY_H13FE_{Make_cname(eds.ods[0x13FE].parameter_name)}"):("NULL"); + string xxENTRY_H13FF = eds.ods.ContainsKey(0x13FF) ? ($"{odname}_ENTRY_H13FF_{Make_cname(eds.ods[0x13FF].parameter_name)}"):("NULL"); + file.WriteLine($"#define {odname}_INIT_CONFIG(config) {{\\"); + file.WriteLine($@" (config).CNT_NMT={CNT_NMT};\ + (config).ENTRY_H1017={xxENTRY_H1017};\ + (config).CNT_HB_CONS={CNT_HB_CONS};\ + (config).ENTRY_H1016={xxENTRY_H1016};\ + (config).CNT_EM={CNT_EM};\ + (config).ENTRY_H1001={xxENTRY_H1001};\ + (config).ENTRY_H1014={xxENTRY_H1014};\ + (config).ENTRY_H1015={xxENTRY_H1015};\ + (config).ENTRY_H1003={xxENTRY_H1003};\ + (config).CNT_SDO_SRV={CNT_SDO_SRV};\ + (config).ENTRY_H1200={xxENTRY_H1200};\ + (config).CNT_SDO_CLI={CNT_SDO_CLI};\ + (config).ENTRY_H1280={xxENTRY_H1280};\ + (config).CNT_TIME={CNT_TIME};\ + (config).ENTRY_H1012={xxENTRY_H1012};\ + (config).CNT_SYNC={CNT_SYNC};\ + (config).ENTRY_H1005={xxENTRY_H1005};\ + (config).ENTRY_H1006={xxENTRY_H1006};\ + (config).ENTRY_H1007={xxENTRY_H1007};\ + (config).ENTRY_H1019={xxENTRY_H1019};\ + (config).CNT_RPDO={CNT_RPDO};\ + (config).ENTRY_H1400={xxENTRY_H1400};\ + (config).ENTRY_H1600={xxENTRY_H1600};\ + (config).CNT_TPDO={CNT_TPDO};\ + (config).ENTRY_H1800={xxENTRY_H1800};\ + (config).ENTRY_H1A00={xxENTRY_H1A00};\ + (config).CNT_LEDS={CNT_LEDS};\ + (config).CNT_GFC={CNT_GFC};\ + (config).ENTRY_H1300={xxENTRY_H1300};\ + (config).CNT_SRDO={CNT_SRDO};\ + (config).ENTRY_H1301={xxENTRY_H1301};\ + (config).ENTRY_H1381={xxENTRY_H1381};\ + (config).ENTRY_H13FE={xxENTRY_H13FE};\ + (config).ENTRY_H13FF={xxENTRY_H13FF};\ + (config).CNT_LSS_SLV={CNT_LSS_SLV};\ + (config).CNT_LSS_MST={CNT_LSS_MST};\ + (config).CNT_GTWA={CNT_GTWA};\ + (config).CNT_TRACE={CNT_TRACE};\ +}}" + ); + file.WriteLine(@" +#endif /******************************************************************************* OD data declaration of all groups *******************************************************************************/"); @@ -506,12 +575,6 @@ Object dictionary entries - shortcuts with names } - string FirstLower(string s) - { - if(string.IsNullOrEmpty(s)) - return s; - return s[0].ToString().ToLower() + s.Substring(1); - } /// /// Export the c file /// @@ -547,76 +610,8 @@ libedssharp Object Dictionary Editor v{0} #if CO_VERSION_MAJOR < 4 #error This Object dictionary is compatible with CANopenNode V4.0 and above! #endif", gitVersion, filename)); - file.WriteLine(@" -/******************************************************************************* - OD config structure -*******************************************************************************/ -#ifdef CO_MULTIPLE_OD"); - - string xxENTRY_H1017 = eds.ods.ContainsKey(0x1017) ? ($"{odname}_ENTRY_H1017_{FirstLower(eds.ods[0x1017].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1016 = eds.ods.ContainsKey(0x1016) ? ($"{odname}_ENTRY_H1016_{FirstLower(eds.ods[0x1016].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1001 = eds.ods.ContainsKey(0x1001) ? ($"{odname}_ENTRY_H1001_{FirstLower(eds.ods[0x1001].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1014 = eds.ods.ContainsKey(0x1014) ? ($"{odname}_ENTRY_H1014_{FirstLower(eds.ods[0x1014].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1015 = eds.ods.ContainsKey(0x1015) ? ($"{odname}_ENTRY_H1015_{FirstLower(eds.ods[0x1015].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1003 = eds.ods.ContainsKey(0x1003) ? ($"{odname}_ENTRY_H1003_{FirstLower(eds.ods[0x1003].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1200 = eds.ods.ContainsKey(0x1200) ? ($"{odname}_ENTRY_H1200_{FirstLower(eds.ods[0x1200].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1280 = eds.ods.ContainsKey(0x1280) ? ($"{odname}_ENTRY_H1280_{FirstLower(eds.ods[0x1280].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1012 = eds.ods.ContainsKey(0x1012) ? ($"{odname}_ENTRY_H1012_{FirstLower(eds.ods[0x1012].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1005 = eds.ods.ContainsKey(0x1005) ? ($"{odname}_ENTRY_H1005_{FirstLower(eds.ods[0x1005].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1006 = eds.ods.ContainsKey(0x1006) ? ($"{odname}_ENTRY_H1006_{FirstLower(eds.ods[0x1006].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1007 = eds.ods.ContainsKey(0x1007) ? ($"{odname}_ENTRY_H1007_{FirstLower(eds.ods[0x1007].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1019 = eds.ods.ContainsKey(0x1019) ? ($"{odname}_ENTRY_H1019_{FirstLower(eds.ods[0x1019].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1400 = eds.ods.ContainsKey(0x1400) ? ($"{odname}_ENTRY_H1400_{FirstLower(eds.ods[0x1400].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1600 = eds.ods.ContainsKey(0x1600) ? ($"{odname}_ENTRY_H1600_{FirstLower(eds.ods[0x1600].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1800 = eds.ods.ContainsKey(0x1800) ? ($"{odname}_ENTRY_H1800_{FirstLower(eds.ods[0x1800].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1A00 = eds.ods.ContainsKey(0x1A00) ? ($"{odname}_ENTRY_H1A00_{FirstLower(eds.ods[0x1A00].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1300 = eds.ods.ContainsKey(0x1300) ? ($"{odname}_ENTRY_H1300_{FirstLower(eds.ods[0x1300].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1301 = eds.ods.ContainsKey(0x1301) ? ($"{odname}_ENTRY_H1301_{FirstLower(eds.ods[0x1301].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H1381 = eds.ods.ContainsKey(0x1381) ? ($"{odname}_ENTRY_H1381_{FirstLower(eds.ods[0x1381].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H13FE = eds.ods.ContainsKey(0x13FE) ? ($"{odname}_ENTRY_H13FE_{FirstLower(eds.ods[0x13FE].parameter_name.Replace(" ",""))}"):("NULL"); - string xxENTRY_H13FF = eds.ods.ContainsKey(0x13FF) ? ($"{odname}_ENTRY_H13FF_{FirstLower(eds.ods[0x13FF].parameter_name.Replace(" ",""))}"):("NULL"); - file.WriteLine($"const CO_config_t {odname}_config = {{"); - file.WriteLine($@" .CNT_NMT={CNT_NMT}, - .ENTRY_H1017={xxENTRY_H1016}, - .CNT_HB_CONS={CNT_HB_CONS}, - .ENTRY_H1016={xxENTRY_H1016}, - .CNT_EM={CNT_EM}, - .ENTRY_H1001={xxENTRY_H1001}, - .ENTRY_H1014={xxENTRY_H1014}, - .ENTRY_H1015={xxENTRY_H1015}, - .ENTRY_H1003={xxENTRY_H1003}, - .CNT_SDO_SRV={CNT_SDO_SRV}, - .ENTRY_H1200={xxENTRY_H1200}, - .CNT_SDO_CLI={CNT_SDO_CLI}, - .ENTRY_H1280={xxENTRY_H1280}, - .CNT_TIME={CNT_TIME}, - .ENTRY_H1012={xxENTRY_H1012}, - .CNT_SYNC={CNT_SYNC}, - .ENTRY_H1005={xxENTRY_H1005}, - .ENTRY_H1006={xxENTRY_H1006}, - .ENTRY_H1007={xxENTRY_H1007}, - .ENTRY_H1019={xxENTRY_H1019}, - .CNT_RPDO={CNT_RPDO}, - .ENTRY_H1400={xxENTRY_H1400}, - .ENTRY_H1600={xxENTRY_H1600}, - .CNT_TPDO={CNT_TPDO}, - .ENTRY_H1800={xxENTRY_H1800}, - .ENTRY_H1A00={xxENTRY_H1A00}, - .CNT_LEDS={CNT_LEDS}, - .CNT_GFC={CNT_GFC}, - .ENTRY_H1300={xxENTRY_H1300}, - .CNT_SRDO={CNT_SRDO}, - .ENTRY_H1301={xxENTRY_H1301}, - .ENTRY_H1381={xxENTRY_H1381}, - .ENTRY_H13FE={xxENTRY_H13FE}, - .ENTRY_H13FF={xxENTRY_H13FF}, - .CNT_LSS_SLV={CNT_LSS_SLV}, - .CNT_LSS_MST={CNT_LSS_MST}, - .CNT_GTWA={CNT_GTWA}, - .CNT_TRACE={CNT_TRACE}" - ); - file.WriteLine(@"} -#endif + + file.WriteLine(@" /******************************************************************************* OD data initialization of all groups *******************************************************************************/"); From a5fefbcca2c31f588e84aa8108172f45103b734d Mon Sep 17 00:00:00 2001 From: Carsten Frank Date: Mon, 31 May 2021 14:43:20 +0200 Subject: [PATCH 007/226] Fix HB producer count --- libEDSsharp/CanOpenNodeExporter_V4.cs | 34 +++++++++++++++------------ 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 14d0276a..cbecfed9 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -59,6 +59,7 @@ public class CanOpenNodeExporter_V4 : IExporter UInt16 CNT_LSS_MST=0; UInt16 CNT_GTWA=0; UInt16 CNT_TRACE=0; + UInt16 CNT_PROD=0; /// /// export the current data set in the CanOpen Node format V4 /// @@ -126,6 +127,8 @@ private void Prepare(EDSsharp eds) CNT_GFC++; if (od.Index>=0x1301 && od.Index<0x1380) CNT_SRDO++; + if (od.Index==0x1014) + CNT_PROD++; string indexH = $"{od.Index:X4}"; string cName = Make_cname(od.parameter_name); string varName = $"{indexH}_{cName}"; @@ -182,21 +185,22 @@ private void Prepare(EDSsharp eds) CNT_SRDO=(UInt16)(CNT_SRDO/2); // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. if (ODCnt.Count==0) { - ODCnt.Add("CNT_HB_CONS", CNT_HB_CONS); - ODCnt.Add("CNT_NMT", CNT_NMT); - ODCnt.Add("CNT_EM", CNT_EM); - ODCnt.Add("CNT_SDO_SRV", CNT_SDO_SRV); - ODCnt.Add("CNT_SDO_CLI", CNT_SDO_CLI); - ODCnt.Add("CNT_TIME", CNT_TIME); - ODCnt.Add("CNT_SYNC", CNT_SYNC); - ODCnt.Add("CNT_RPDO", CNT_RPDO); - ODCnt.Add("CNT_TPDO", CNT_TPDO); - ODCnt.Add("CNT_GFC", CNT_GFC); - ODCnt.Add("CNT_SRDO", CNT_SRDO); - ODCnt.Add("CNT_LSS_SLV", CNT_LSS_SLV); - ODCnt.Add("CNT_LSS_MST", CNT_LSS_MST); - ODCnt.Add("CNT_GTWA", CNT_GTWA); - ODCnt.Add("CNT_TRACE", CNT_TRACE); + ODCnt.Add("HB_CONS", CNT_HB_CONS); + ODCnt.Add("NMT", CNT_NMT); + ODCnt.Add("EM", CNT_EM); + ODCnt.Add("SDO_SRV", CNT_SDO_SRV); + ODCnt.Add("SDO_CLI", CNT_SDO_CLI); + ODCnt.Add("TIME", CNT_TIME); + ODCnt.Add("SYNC", CNT_SYNC); + ODCnt.Add("RPDO", CNT_RPDO); + ODCnt.Add("TPDO", CNT_TPDO); + ODCnt.Add("GFC", CNT_GFC); + ODCnt.Add("SRDO", CNT_SRDO); + ODCnt.Add("LSS_SLV", CNT_LSS_SLV); + ODCnt.Add("LSS_MST", CNT_LSS_MST); + ODCnt.Add("GTWA", CNT_GTWA); + ODCnt.Add("TRACE", CNT_TRACE); + ODCnt.Add("HB_PROD", CNT_PROD); } } From f9df417fe62a68fd15cd8a019d62090a74ccc361 Mon Sep 17 00:00:00 2001 From: Janez Date: Tue, 22 Jun 2021 19:45:16 +0200 Subject: [PATCH 008/226] Rename attribute for OD storage class and add default definitions. --- libEDSsharp/CanOpenNodeExporter_V4.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index ed1ad7e3..d7896cb3 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -424,10 +424,16 @@ OD data declaration of all groups { if (ODStorage_t.Count > 0) { - file.WriteLine($"extern ATTRIBUTE_{group} {odname}_{group}_t {odname}_{group};"); + file.WriteLine($"#ifndef {odname}_ATTR_{group}"); + file.WriteLine($"#define {odname}_ATTR_{group}"); + file.WriteLine($"#endif"); + file.WriteLine($"extern {odname}_ATTR_{group} {odname}_{group}_t {odname}_{group};\n"); } } - file.WriteLine($"extern ATTRIBUTE_OD OD_t *{odname};"); + file.WriteLine($"#ifndef {odname}_ATTR_OD"); + file.WriteLine($"#define {odname}_ATTR_OD"); + file.WriteLine($"#endif"); + file.WriteLine($"extern {odname}_ATTR_OD OD_t *{odname};"); file.WriteLine(string.Format(@" @@ -493,7 +499,7 @@ OD data initialization of all groups { if (ODStorage.Count > 0) { - file.WriteLine($"ATTRIBUTE_{group} {odname}_{group}_t {odname}_{group} = {{"); + file.WriteLine($"{odname}_ATTR_{group} {odname}_{group}_t {odname}_{group} = {{"); file.WriteLine($" {string.Join(",\n ", ODStorage[group])}"); file.WriteLine($"}};\n"); } @@ -521,7 +527,7 @@ typedef struct {{ /******************************************************************************* Object dictionary *******************************************************************************/ -static ATTRIBUTE_OD OD_entry_t {0}List[] = {{ +static {0}_ATTR_OD OD_entry_t {0}List[] = {{ {1}, {{0x0000, 0x00, 0, NULL, NULL}} }}; From 09a7cbf3c8f3b798c8083a3974068633d60e215f Mon Sep 17 00:00:00 2001 From: Janez Date: Tue, 22 Jun 2021 19:46:39 +0200 Subject: [PATCH 009/226] Remove duplicated "v" from git version and update readme.md --- EDSEditorGUI/Form1.cs | 2 +- README.md | 27 +++++++++++++-------------- libEDSsharp/CanOpenNodeExporter.cs | 2 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 4 ++-- libEDSsharp/CanOpenXDD_1_1.cs | 4 ++-- libEDSsharp/DocumentationGen.cs | 2 +- 6 files changed, 20 insertions(+), 21 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 51a41a9d..aaf75f57 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -721,7 +721,7 @@ private void ODEditor_MainForm_Load(object sender, EventArgs e) { gitVersion = "Unknown"; } - this.Text += "v" + gitVersion; + this.Text += gitVersion; this.gitVersion = gitVersion; //First lets create an appdata folder diff --git a/README.md b/README.md index 0d2ca1e0..f743fbc3 100644 --- a/README.md +++ b/README.md @@ -1,10 +1,20 @@ CANopenEditor ============= -CANopen Object Dictionary Editor +CANopenEditor is a fork from https://github.com/robincornelius/libedssharp, author Robin Cornelius. +Its homepage is https://github.com/CANopenNode/CANopenEditor + +CANopen Object Dictionary Editor: - Imports: CANopen electronic data sheets in EDS or XDD format. - Exports: CANopen electronic data sheets in EDS or XDD format, documentation, CANopenNode C source files. + - GUI editor for CANopen Object Dictionary, Device information, etc. + +CANopen is the internationally standardized (EN 50325-4) ([CiA301](http://can-cia.org/standardization/technical-documents)) higher-layer protocol for embedded control system built on top of CAN. For more information on CANopen see http://www.can-cia.org/ + +[CANopenNode](https://github.com/CANopenNode/CANopenNode) is free and open source CANopen Stack -This is a fork from https://github.com/robincornelius/libedssharp, author Robin Cornelius. +This is the `main` branch with sources. For binaries see the `build` branch. + +---- Join us on slack -------- @@ -53,17 +63,6 @@ improving the code * trojanobelix * many others... -Releases --------- - -If you would like to try a pre compiled version, then head over to the -[releases page!](https://github.com/robincornelius/libedssharp/releases) - -If you want to try the latest and greatest version from the development tip then it can be found here -[latest auto build!](https://github.com/robincornelius/libedssharp/raw/gh-pages/build/OpenEDSEditor-latest.zip) this version is auto built on travis-ci using mono 6.10.0 for the last build log please see [build log](https://travis-ci.org/github/robincornelius/libedssharp) - -Current Features - Library ------- @@ -135,4 +134,4 @@ Pictures ![alt tag](pic1.jpg) ![alt tag](pic2.jpg) ![alt tag](pic3.jpg) -![alt tag](pic4.jpg) \ No newline at end of file +![alt tag](pic4.jpg) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 119676a2..e12e8a79 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -397,7 +397,7 @@ private void addHeader(StreamWriter file) CANopen Object Dictionary definition for CANopenNode v1 to v2 This file was automatically generated with - libedssharp Object Dictionary Editor v{0} + libedssharp Object Dictionary Editor {0} https://github.com/CANopenNode/CANopenNode https://github.com/robincornelius/libedssharp diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index d7896cb3..74d9f659 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -360,7 +360,7 @@ private void Export_h(string folderpath, string filename, string gitVersion, EDS CANopen Object Dictionary definition for CANopenNode V4 This file was automatically generated with - libedssharp Object Dictionary Editor v{0} + libedssharp Object Dictionary Editor {0} https://github.com/CANopenNode/CANopenNode https://github.com/robincornelius/libedssharp @@ -475,7 +475,7 @@ private void Export_c(string folderpath, string filename, string gitVersion) CANopen Object Dictionary definition for CANopenNode V4 This file was automatically generated with - libedssharp Object Dictionary Editor v{0} + libedssharp Object Dictionary Editor {0} https://github.com/CANopenNode/CANopenNode https://github.com/robincornelius/libedssharp diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 7daeea77..2cc1bb20 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -115,7 +115,7 @@ public void WriteMultiXML(string file, List edss, string gitVersion, b XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true, NewLineChars = "\n" }); writer.WriteStartDocument(); writer.WriteComment(string.Format("CANopen Project file in custom format. It contains multiple standard CANopen device description files.", gitVersion)); - writer.WriteComment(string.Format("File is generated with libedssharp Object Dictionary Editor v{0}, URL: https://github.com/robincornelius/libedssharp", gitVersion)); + writer.WriteComment(string.Format("File is generated with libedssharp Object Dictionary Editor {0}, URL: https://github.com/robincornelius/libedssharp", gitVersion)); writer.WriteComment("File includes additional custom properties for CANopenNode, CANopen protocol stack, URL: https://github.com/CANopenNode/CANopenNode"); serializer.Serialize(writer, oep); writer.WriteEndDocument(); @@ -140,7 +140,7 @@ public void WriteXML(string file, EDSsharp eds, string gitVersion, bool deviceCo stream.NewLine = "\n"; XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true, NewLineChars = "\n" }); writer.WriteStartDocument(); - writer.WriteComment(string.Format("File is generated with libedssharp Object Dictionary Editor v{0}, URL: https://github.com/robincornelius/libedssharp", gitVersion)); + writer.WriteComment(string.Format("File is generated with libedssharp Object Dictionary Editor {0}, URL: https://github.com/robincornelius/libedssharp", gitVersion)); if (!stripped) writer.WriteComment("File includes additional custom properties for CANopenNode, CANopen protocol stack, URL: https://github.com/CANopenNode/CANopenNode"); serializer.Serialize(writer, dev); diff --git a/libEDSsharp/DocumentationGen.cs b/libEDSsharp/DocumentationGen.cs index aeab6879..d7879f6d 100644 --- a/libEDSsharp/DocumentationGen.cs +++ b/libEDSsharp/DocumentationGen.cs @@ -176,7 +176,7 @@ public void genmddoc(string filepath, EDSsharp eds, string gitVersion) | Modified | {6,-30} | | Modified By | {7,-30} | -This file was automatically generated with [libedssharp](https://github.com/robincornelius/libedssharp) Object Dictionary Editor v{8} +This file was automatically generated with [libedssharp](https://github.com/robincornelius/libedssharp) Object Dictionary Editor {8} [TOC] ", From 626ce51dd0ab02ac13b1b86a23640ef5c0aaf0a3 Mon Sep 17 00:00:00 2001 From: Janez Date: Wed, 23 Jun 2021 15:11:30 +0200 Subject: [PATCH 010/226] Fixed mixed whitespaces --- libEDSsharp/CanOpenNodeExporter_V4.cs | 264 +++++++++++++------------- 1 file changed, 131 insertions(+), 133 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index c3275aff..348a9a3d 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -43,23 +43,23 @@ public class CanOpenNodeExporter_V4 : IExporter private List ODDefines; private List ODDefinesLong; private Dictionary ODCnt; - UInt16 CNT_NMT=0; - UInt16 CNT_HB_CONS=0; - UInt16 CNT_EM=0; - UInt16 CNT_SDO_SRV=0; - UInt16 CNT_SDO_CLI=0; - UInt16 CNT_TIME=0; - UInt16 CNT_SYNC=0; - UInt16 CNT_RPDO=0; - UInt16 CNT_TPDO=0; - UInt16 CNT_LEDS=0; - UInt16 CNT_GFC=0; - UInt16 CNT_SRDO=0; - UInt16 CNT_LSS_SLV=0; - UInt16 CNT_LSS_MST=0; - UInt16 CNT_GTWA=0; - UInt16 CNT_TRACE=0; - UInt16 CNT_PROD=0; + UInt16 CNT_NMT = 0; + UInt16 CNT_HB_CONS = 0; + UInt16 CNT_EM = 0; + UInt16 CNT_SDO_SRV = 0; + UInt16 CNT_SDO_CLI = 0; + UInt16 CNT_TIME = 0; + UInt16 CNT_SYNC = 0; + UInt16 CNT_RPDO = 0; + UInt16 CNT_TPDO = 0; + UInt16 CNT_LEDS = 0; + UInt16 CNT_GFC = 0; + UInt16 CNT_SRDO = 0; + UInt16 CNT_LSS_SLV = 0; + UInt16 CNT_LSS_MST = 0; + UInt16 CNT_GTWA = 0; + UInt16 CNT_TRACE = 0; + /// /// export the current data set in the CanOpen Node format V4 /// @@ -103,32 +103,30 @@ private void Prepare(EDSsharp eds) { if (od.prop.CO_disabled == true) continue; - // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. - // Count objects for initialization of CO_config_t object. - if (od.Index==0x1017) - CNT_NMT++; - if (od.Index==0x1016) - CNT_HB_CONS=(UInt16)(od.subobjects.Count-1); - if ((od.Index==0x1014 || od.Index==0x1015) && CNT_EM==0) - CNT_EM++; - if (od.Index>=0x1200 && od.Index<0x1280) - CNT_SDO_SRV++; - if (od.Index>=0x1280 && od.Index<0x1300) - CNT_SDO_CLI++; - if (od.Index==0x1012) - CNT_TIME++; - if (od.Index==0x1005) - CNT_SYNC++; - if (od.Index>=0x1400 && od.Index<0x1500) - CNT_RPDO++; - if (od.Index>=0x1800 && od.Index<0x1900) - CNT_TPDO++; - if (od.Index==0x1300) - CNT_GFC++; - if (od.Index>=0x1301 && od.Index<0x1380) - CNT_SRDO++; - if (od.Index==0x1014) - CNT_PROD++; + // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. + // Count objects for initialization of CO_config_t object. + if (od.Index==0x1017) + CNT_NMT++; + if (od.Index==0x1016) + CNT_HB_CONS=(UInt16)(od.subobjects.Count-1); + if ((od.Index==0x1014 || od.Index==0x1015) && CNT_EM==0) + CNT_EM++; + if (od.Index>=0x1200 && od.Index<0x1280) + CNT_SDO_SRV++; + if (od.Index>=0x1280 && od.Index<0x1300) + CNT_SDO_CLI++; + if (od.Index==0x1012) + CNT_TIME++; + if (od.Index==0x1005) + CNT_SYNC++; + if (od.Index>=0x1400 && od.Index<0x1500) + CNT_RPDO++; + if (od.Index>=0x1800 && od.Index<0x1900) + CNT_TPDO++; + if (od.Index==0x1300) + CNT_GFC++; + if (od.Index>=0x1301 && od.Index<0x1380) + CNT_SRDO++; string indexH = $"{od.Index:X4}"; string cName = Make_cname(od.parameter_name); string varName = $"{indexH}_{cName}"; @@ -182,26 +180,25 @@ private void Prepare(EDSsharp eds) ODCnt.Add(od.prop.CO_countLabel, 1); } } - CNT_SRDO=(UInt16)(CNT_SRDO/2); - // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. - if (ODCnt.Count==0) { - ODCnt.Add("HB_CONS", CNT_HB_CONS); - ODCnt.Add("NMT", CNT_NMT); - ODCnt.Add("EM", CNT_EM); - ODCnt.Add("SDO_SRV", CNT_SDO_SRV); - ODCnt.Add("SDO_CLI", CNT_SDO_CLI); - ODCnt.Add("TIME", CNT_TIME); - ODCnt.Add("SYNC", CNT_SYNC); - ODCnt.Add("RPDO", CNT_RPDO); - ODCnt.Add("TPDO", CNT_TPDO); - ODCnt.Add("GFC", CNT_GFC); - ODCnt.Add("SRDO", CNT_SRDO); - ODCnt.Add("LSS_SLV", CNT_LSS_SLV); - ODCnt.Add("LSS_MST", CNT_LSS_MST); - ODCnt.Add("GTWA", CNT_GTWA); - ODCnt.Add("TRACE", CNT_TRACE); - ODCnt.Add("HB_PROD", CNT_PROD); - } + CNT_SRDO=(UInt16)(CNT_SRDO/2); + // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. + if (ODCnt.Count==0) { + ODCnt.Add("HB_CONS", CNT_HB_CONS); + ODCnt.Add("NMT", CNT_NMT); + ODCnt.Add("EM", CNT_EM); + ODCnt.Add("SDO_SRV", CNT_SDO_SRV); + ODCnt.Add("SDO_CLI", CNT_SDO_CLI); + ODCnt.Add("TIME", CNT_TIME); + ODCnt.Add("SYNC", CNT_SYNC); + ODCnt.Add("RPDO", CNT_RPDO); + ODCnt.Add("TPDO", CNT_TPDO); + ODCnt.Add("GFC", CNT_GFC); + ODCnt.Add("SRDO", CNT_SRDO); + ODCnt.Add("LSS_SLV", CNT_LSS_SLV); + ODCnt.Add("LSS_MST", CNT_LSS_MST); + ODCnt.Add("GTWA", CNT_GTWA); + ODCnt.Add("TRACE", CNT_TRACE); + } } /// @@ -464,78 +461,79 @@ Counters of OD objects { file.WriteLine($"#define {odname}_CNT_{kvp.Key} {kvp.Value}"); } - file.WriteLine(@" + file.WriteLine(@" + /******************************************************************************* OD config structure -*******************************************************************************/ -#ifdef CO_MULTIPLE_OD -#include ""CANopen.h"""); - - string xxENTRY_H1017 = eds.ods.ContainsKey(0x1017) ? ($"{odname}_ENTRY_H1017_{Make_cname(eds.ods[0x1017].parameter_name)}"):("NULL"); - string xxENTRY_H1016 = eds.ods.ContainsKey(0x1016) ? ($"{odname}_ENTRY_H1016_{Make_cname(eds.ods[0x1016].parameter_name)}"):("NULL"); - string xxENTRY_H1001 = eds.ods.ContainsKey(0x1001) ? ($"{odname}_ENTRY_H1001_{Make_cname(eds.ods[0x1001].parameter_name)}"):("NULL"); - string xxENTRY_H1014 = eds.ods.ContainsKey(0x1014) ? ($"{odname}_ENTRY_H1014_{Make_cname(eds.ods[0x1014].parameter_name)}"):("NULL"); - string xxENTRY_H1015 = eds.ods.ContainsKey(0x1015) ? ($"{odname}_ENTRY_H1015_{Make_cname(eds.ods[0x1015].parameter_name)}"):("NULL"); - string xxENTRY_H1003 = eds.ods.ContainsKey(0x1003) ? ($"{odname}_ENTRY_H1003_{Make_cname(eds.ods[0x1003].parameter_name)}"):("NULL"); - string xxENTRY_H1200 = eds.ods.ContainsKey(0x1200) ? ($"{odname}_ENTRY_H1200_{Make_cname(eds.ods[0x1200].parameter_name)}"):("NULL"); - string xxENTRY_H1280 = eds.ods.ContainsKey(0x1280) ? ($"{odname}_ENTRY_H1280_{Make_cname(eds.ods[0x1280].parameter_name)}"):("NULL"); - string xxENTRY_H1012 = eds.ods.ContainsKey(0x1012) ? ($"{odname}_ENTRY_H1012_{Make_cname(eds.ods[0x1012].parameter_name)}"):("NULL"); - string xxENTRY_H1005 = eds.ods.ContainsKey(0x1005) ? ($"{odname}_ENTRY_H1005_{Make_cname(eds.ods[0x1005].parameter_name)}"):("NULL"); - string xxENTRY_H1006 = eds.ods.ContainsKey(0x1006) ? ($"{odname}_ENTRY_H1006_{Make_cname(eds.ods[0x1006].parameter_name)}"):("NULL"); - string xxENTRY_H1007 = eds.ods.ContainsKey(0x1007) ? ($"{odname}_ENTRY_H1007_{Make_cname(eds.ods[0x1007].parameter_name)}"):("NULL"); - string xxENTRY_H1019 = eds.ods.ContainsKey(0x1019) ? ($"{odname}_ENTRY_H1019_{Make_cname(eds.ods[0x1019].parameter_name)}"):("NULL"); - string xxENTRY_H1400 = eds.ods.ContainsKey(0x1400) ? ($"{odname}_ENTRY_H1400_{Make_cname(eds.ods[0x1400].parameter_name)}"):("NULL"); - string xxENTRY_H1600 = eds.ods.ContainsKey(0x1600) ? ($"{odname}_ENTRY_H1600_{Make_cname(eds.ods[0x1600].parameter_name)}"):("NULL"); - string xxENTRY_H1800 = eds.ods.ContainsKey(0x1800) ? ($"{odname}_ENTRY_H1800_{Make_cname(eds.ods[0x1800].parameter_name)}"):("NULL"); - string xxENTRY_H1A00 = eds.ods.ContainsKey(0x1A00) ? ($"{odname}_ENTRY_H1A00_{Make_cname(eds.ods[0x1A00].parameter_name)}"):("NULL"); - string xxENTRY_H1300 = eds.ods.ContainsKey(0x1300) ? ($"{odname}_ENTRY_H1300_{Make_cname(eds.ods[0x1300].parameter_name)}"):("NULL"); - string xxENTRY_H1301 = eds.ods.ContainsKey(0x1301) ? ($"{odname}_ENTRY_H1301_{Make_cname(eds.ods[0x1301].parameter_name)}"):("NULL"); - string xxENTRY_H1381 = eds.ods.ContainsKey(0x1381) ? ($"{odname}_ENTRY_H1381_{Make_cname(eds.ods[0x1381].parameter_name)}"):("NULL"); - string xxENTRY_H13FE = eds.ods.ContainsKey(0x13FE) ? ($"{odname}_ENTRY_H13FE_{Make_cname(eds.ods[0x13FE].parameter_name)}"):("NULL"); - string xxENTRY_H13FF = eds.ods.ContainsKey(0x13FF) ? ($"{odname}_ENTRY_H13FF_{Make_cname(eds.ods[0x13FF].parameter_name)}"):("NULL"); - file.WriteLine($"#define {odname}_INIT_CONFIG(config) {{\\"); - file.WriteLine($@" (config).CNT_NMT={CNT_NMT};\ - (config).ENTRY_H1017={xxENTRY_H1017};\ - (config).CNT_HB_CONS={CNT_HB_CONS};\ - (config).ENTRY_H1016={xxENTRY_H1016};\ - (config).CNT_EM={CNT_EM};\ - (config).ENTRY_H1001={xxENTRY_H1001};\ - (config).ENTRY_H1014={xxENTRY_H1014};\ - (config).ENTRY_H1015={xxENTRY_H1015};\ - (config).ENTRY_H1003={xxENTRY_H1003};\ - (config).CNT_SDO_SRV={CNT_SDO_SRV};\ - (config).ENTRY_H1200={xxENTRY_H1200};\ - (config).CNT_SDO_CLI={CNT_SDO_CLI};\ - (config).ENTRY_H1280={xxENTRY_H1280};\ - (config).CNT_TIME={CNT_TIME};\ - (config).ENTRY_H1012={xxENTRY_H1012};\ - (config).CNT_SYNC={CNT_SYNC};\ - (config).ENTRY_H1005={xxENTRY_H1005};\ - (config).ENTRY_H1006={xxENTRY_H1006};\ - (config).ENTRY_H1007={xxENTRY_H1007};\ - (config).ENTRY_H1019={xxENTRY_H1019};\ - (config).CNT_RPDO={CNT_RPDO};\ - (config).ENTRY_H1400={xxENTRY_H1400};\ - (config).ENTRY_H1600={xxENTRY_H1600};\ - (config).CNT_TPDO={CNT_TPDO};\ - (config).ENTRY_H1800={xxENTRY_H1800};\ - (config).ENTRY_H1A00={xxENTRY_H1A00};\ - (config).CNT_LEDS={CNT_LEDS};\ - (config).CNT_GFC={CNT_GFC};\ - (config).ENTRY_H1300={xxENTRY_H1300};\ - (config).CNT_SRDO={CNT_SRDO};\ - (config).ENTRY_H1301={xxENTRY_H1301};\ - (config).ENTRY_H1381={xxENTRY_H1381};\ - (config).ENTRY_H13FE={xxENTRY_H13FE};\ - (config).ENTRY_H13FF={xxENTRY_H13FF};\ - (config).CNT_LSS_SLV={CNT_LSS_SLV};\ - (config).CNT_LSS_MST={CNT_LSS_MST};\ - (config).CNT_GTWA={CNT_GTWA};\ - (config).CNT_TRACE={CNT_TRACE};\ -}}" - ); - file.WriteLine(@" -#endif +*******************************************************************************/"); + string xxENTRY_H1017 = eds.ods.ContainsKey(0x1017) ? ($"{odname}_ENTRY_H1017_{Make_cname(eds.ods[0x1017].parameter_name)}"):("NULL"); + string xxENTRY_H1016 = eds.ods.ContainsKey(0x1016) ? ($"{odname}_ENTRY_H1016_{Make_cname(eds.ods[0x1016].parameter_name)}"):("NULL"); + string xxENTRY_H1001 = eds.ods.ContainsKey(0x1001) ? ($"{odname}_ENTRY_H1001_{Make_cname(eds.ods[0x1001].parameter_name)}"):("NULL"); + string xxENTRY_H1014 = eds.ods.ContainsKey(0x1014) ? ($"{odname}_ENTRY_H1014_{Make_cname(eds.ods[0x1014].parameter_name)}"):("NULL"); + string xxENTRY_H1015 = eds.ods.ContainsKey(0x1015) ? ($"{odname}_ENTRY_H1015_{Make_cname(eds.ods[0x1015].parameter_name)}"):("NULL"); + string xxENTRY_H1003 = eds.ods.ContainsKey(0x1003) ? ($"{odname}_ENTRY_H1003_{Make_cname(eds.ods[0x1003].parameter_name)}"):("NULL"); + string xxENTRY_H1200 = eds.ods.ContainsKey(0x1200) ? ($"{odname}_ENTRY_H1200_{Make_cname(eds.ods[0x1200].parameter_name)}"):("NULL"); + string xxENTRY_H1280 = eds.ods.ContainsKey(0x1280) ? ($"{odname}_ENTRY_H1280_{Make_cname(eds.ods[0x1280].parameter_name)}"):("NULL"); + string xxENTRY_H1012 = eds.ods.ContainsKey(0x1012) ? ($"{odname}_ENTRY_H1012_{Make_cname(eds.ods[0x1012].parameter_name)}"):("NULL"); + string xxENTRY_H1005 = eds.ods.ContainsKey(0x1005) ? ($"{odname}_ENTRY_H1005_{Make_cname(eds.ods[0x1005].parameter_name)}"):("NULL"); + string xxENTRY_H1006 = eds.ods.ContainsKey(0x1006) ? ($"{odname}_ENTRY_H1006_{Make_cname(eds.ods[0x1006].parameter_name)}"):("NULL"); + string xxENTRY_H1007 = eds.ods.ContainsKey(0x1007) ? ($"{odname}_ENTRY_H1007_{Make_cname(eds.ods[0x1007].parameter_name)}"):("NULL"); + string xxENTRY_H1019 = eds.ods.ContainsKey(0x1019) ? ($"{odname}_ENTRY_H1019_{Make_cname(eds.ods[0x1019].parameter_name)}"):("NULL"); + string xxENTRY_H1400 = eds.ods.ContainsKey(0x1400) ? ($"{odname}_ENTRY_H1400_{Make_cname(eds.ods[0x1400].parameter_name)}"):("NULL"); + string xxENTRY_H1600 = eds.ods.ContainsKey(0x1600) ? ($"{odname}_ENTRY_H1600_{Make_cname(eds.ods[0x1600].parameter_name)}"):("NULL"); + string xxENTRY_H1800 = eds.ods.ContainsKey(0x1800) ? ($"{odname}_ENTRY_H1800_{Make_cname(eds.ods[0x1800].parameter_name)}"):("NULL"); + string xxENTRY_H1A00 = eds.ods.ContainsKey(0x1A00) ? ($"{odname}_ENTRY_H1A00_{Make_cname(eds.ods[0x1A00].parameter_name)}"):("NULL"); + string xxENTRY_H1300 = eds.ods.ContainsKey(0x1300) ? ($"{odname}_ENTRY_H1300_{Make_cname(eds.ods[0x1300].parameter_name)}"):("NULL"); + string xxENTRY_H1301 = eds.ods.ContainsKey(0x1301) ? ($"{odname}_ENTRY_H1301_{Make_cname(eds.ods[0x1301].parameter_name)}"):("NULL"); + string xxENTRY_H1381 = eds.ods.ContainsKey(0x1381) ? ($"{odname}_ENTRY_H1381_{Make_cname(eds.ods[0x1381].parameter_name)}"):("NULL"); + string xxENTRY_H13FE = eds.ods.ContainsKey(0x13FE) ? ($"{odname}_ENTRY_H13FE_{Make_cname(eds.ods[0x13FE].parameter_name)}"):("NULL"); + string xxENTRY_H13FF = eds.ods.ContainsKey(0x13FF) ? ($"{odname}_ENTRY_H13FF_{Make_cname(eds.ods[0x13FF].parameter_name)}"):("NULL"); + + file.WriteLine($@"#ifdef CO_MULTIPLE_OD +#define {odname}_INIT_CONFIG(config) {{\ + (config).CNT_NMT = {CNT_NMT};\ + (config).ENTRY_H1017 = {xxENTRY_H1017};\ + (config).CNT_HB_CONS = {CNT_HB_CONS};\ + (config).ENTRY_H1016 = {xxENTRY_H1016};\ + (config).CNT_EM = {CNT_EM};\ + (config).ENTRY_H1001 = {xxENTRY_H1001};\ + (config).ENTRY_H1014 = {xxENTRY_H1014};\ + (config).ENTRY_H1015 = {xxENTRY_H1015};\ + (config).ENTRY_H1003 = {xxENTRY_H1003};\ + (config).CNT_SDO_SRV = {CNT_SDO_SRV};\ + (config).ENTRY_H1200 = {xxENTRY_H1200};\ + (config).CNT_SDO_CLI = {CNT_SDO_CLI};\ + (config).ENTRY_H1280 = {xxENTRY_H1280};\ + (config).CNT_TIME = {CNT_TIME};\ + (config).ENTRY_H1012 = {xxENTRY_H1012};\ + (config).CNT_SYNC = {CNT_SYNC};\ + (config).ENTRY_H1005 = {xxENTRY_H1005};\ + (config).ENTRY_H1006 = {xxENTRY_H1006};\ + (config).ENTRY_H1007 = {xxENTRY_H1007};\ + (config).ENTRY_H1019 = {xxENTRY_H1019};\ + (config).CNT_RPDO = {CNT_RPDO};\ + (config).ENTRY_H1400 = {xxENTRY_H1400};\ + (config).ENTRY_H1600 = {xxENTRY_H1600};\ + (config).CNT_TPDO = {CNT_TPDO};\ + (config).ENTRY_H1800 = {xxENTRY_H1800};\ + (config).ENTRY_H1A00 = {xxENTRY_H1A00};\ + (config).CNT_LEDS = {CNT_LEDS};\ + (config).CNT_GFC = {CNT_GFC};\ + (config).ENTRY_H1300 = {xxENTRY_H1300};\ + (config).CNT_SRDO = {CNT_SRDO};\ + (config).ENTRY_H1301 = {xxENTRY_H1301};\ + (config).ENTRY_H1381 = {xxENTRY_H1381};\ + (config).ENTRY_H13FE = {xxENTRY_H13FE};\ + (config).ENTRY_H13FF = {xxENTRY_H13FF};\ + (config).CNT_LSS_SLV = {CNT_LSS_SLV};\ + (config).CNT_LSS_MST = {CNT_LSS_MST};\ + (config).CNT_GTWA = {CNT_GTWA};\ + (config).CNT_TRACE = {CNT_TRACE};\ +}} +#endif"); + + file.WriteLine(@" + /******************************************************************************* OD data declaration of all groups *******************************************************************************/"); From d365995cf52cdf6ba7d069384c758bbe010f0fbf Mon Sep 17 00:00:00 2001 From: Janez Date: Sat, 26 Jun 2021 13:07:16 +0200 Subject: [PATCH 011/226] Change homepage, update CANopenNode_v4 exporter - Project homepage changed from https://github.com/robincornelius/libedssharp to https://github.com/CANopenNode/CANopenEditor - CANopenNode_v4 exporter: - Add macros for array sizes - Fix CNT_HB_CONS - "OD config structure" in OD.h reorganized - data.cType always initialized in Get_dataProperties() --- libEDSsharp/CanOpenNodeExporter.cs | 5 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 184 ++++++++++++-------------- libEDSsharp/CanOpenXDD_1_1.cs | 4 +- libEDSsharp/DocumentationGen.cs | 2 +- 4 files changed, 89 insertions(+), 106 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index e12e8a79..35dc25e4 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -396,11 +396,10 @@ private void addHeader(StreamWriter file) @"/******************************************************************************* CANopen Object Dictionary definition for CANopenNode v1 to v2 - This file was automatically generated with - libedssharp Object Dictionary Editor {0} + This file was automatically generated by CANopenEditor {0} https://github.com/CANopenNode/CANopenNode - https://github.com/robincornelius/libedssharp + https://github.com/CANopenNode/CANopenEditor DON'T EDIT THIS FILE MANUALLY !!!! *******************************************************************************/", this.gitVersion)); diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 348a9a3d..99515750 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -43,6 +43,8 @@ public class CanOpenNodeExporter_V4 : IExporter private List ODDefines; private List ODDefinesLong; private Dictionary ODCnt; + private Dictionary ODArrSize; + UInt16 CNT_NMT = 0; UInt16 CNT_HB_CONS = 0; UInt16 CNT_EM = 0; @@ -52,13 +54,8 @@ public class CanOpenNodeExporter_V4 : IExporter UInt16 CNT_SYNC = 0; UInt16 CNT_RPDO = 0; UInt16 CNT_TPDO = 0; - UInt16 CNT_LEDS = 0; UInt16 CNT_GFC = 0; UInt16 CNT_SRDO = 0; - UInt16 CNT_LSS_SLV = 0; - UInt16 CNT_LSS_MST = 0; - UInt16 CNT_GTWA = 0; - UInt16 CNT_TRACE = 0; /// /// export the current data set in the CanOpen Node format V4 @@ -95,6 +92,7 @@ private void Prepare(EDSsharp eds) ODDefines = new List(); ODDefinesLong = new List(); ODCnt = new Dictionary(); + ODArrSize = new Dictionary(); List mappingErrors = eds.VerifyPDOMapping(); if (mappingErrors.Count > 0) @@ -108,7 +106,7 @@ private void Prepare(EDSsharp eds) if (od.Index==0x1017) CNT_NMT++; if (od.Index==0x1016) - CNT_HB_CONS=(UInt16)(od.subobjects.Count-1); + CNT_HB_CONS++; if ((od.Index==0x1014 || od.Index==0x1015) && CNT_EM==0) CNT_EM++; if (od.Index>=0x1200 && od.Index<0x1280) @@ -194,10 +192,6 @@ private void Prepare(EDSsharp eds) ODCnt.Add("TPDO", CNT_TPDO); ODCnt.Add("GFC", CNT_GFC); ODCnt.Add("SRDO", CNT_SRDO); - ODCnt.Add("LSS_SLV", CNT_LSS_SLV); - ODCnt.Add("LSS_MST", CNT_LSS_MST); - ODCnt.Add("GTWA", CNT_GTWA); - ODCnt.Add("TRACE", CNT_TRACE); } } @@ -251,6 +245,9 @@ private int Prepare_arr(ODentry od, string indexH, string varName, string group) return 0; } + // add size of array + ODArrSize.Add(indexH, subEntriesCount - 1); + // prepare and verify each sub element string cValue0 = ""; DataProperties dataElem = new DataProperties(); @@ -308,7 +305,7 @@ private int Prepare_arr(ODentry od, string indexH, string varName, string group) } if (dataElem.cValue != null) { - ODStorage_t[group].Add($"{dataElem.cType} x{varName}[{subEntriesCount - 1}]{dataElem.cTypeArray};"); + ODStorage_t[group].Add($"{dataElem.cType} x{varName}[{odname}_CNT_ARR_{indexH}]{dataElem.cTypeArray};"); ODStorage[group].Add($".x{varName} = {{{string.Join(", ", ODStorageValues)}}}"); dataPtr = $"&{odname}_{group}.x{varName}[0]{dataElem.cTypeArray0}"; } @@ -416,11 +413,10 @@ private void Export_h(string folderpath, string filename, string gitVersion, EDS @"/******************************************************************************* CANopen Object Dictionary definition for CANopenNode V4 - This file was automatically generated with - libedssharp Object Dictionary Editor {0} + This file was automatically generated by CANopenEditor {0} https://github.com/CANopenNode/CANopenNode - https://github.com/robincornelius/libedssharp + https://github.com/CANopenNode/CANopenEditor DON'T EDIT THIS FILE MANUALLY !!!! ******************************************************************************** @@ -461,76 +457,16 @@ Counters of OD objects { file.WriteLine($"#define {odname}_CNT_{kvp.Key} {kvp.Value}"); } - file.WriteLine(@" + + file.WriteLine(string.Format(@" /******************************************************************************* - OD config structure -*******************************************************************************/"); - string xxENTRY_H1017 = eds.ods.ContainsKey(0x1017) ? ($"{odname}_ENTRY_H1017_{Make_cname(eds.ods[0x1017].parameter_name)}"):("NULL"); - string xxENTRY_H1016 = eds.ods.ContainsKey(0x1016) ? ($"{odname}_ENTRY_H1016_{Make_cname(eds.ods[0x1016].parameter_name)}"):("NULL"); - string xxENTRY_H1001 = eds.ods.ContainsKey(0x1001) ? ($"{odname}_ENTRY_H1001_{Make_cname(eds.ods[0x1001].parameter_name)}"):("NULL"); - string xxENTRY_H1014 = eds.ods.ContainsKey(0x1014) ? ($"{odname}_ENTRY_H1014_{Make_cname(eds.ods[0x1014].parameter_name)}"):("NULL"); - string xxENTRY_H1015 = eds.ods.ContainsKey(0x1015) ? ($"{odname}_ENTRY_H1015_{Make_cname(eds.ods[0x1015].parameter_name)}"):("NULL"); - string xxENTRY_H1003 = eds.ods.ContainsKey(0x1003) ? ($"{odname}_ENTRY_H1003_{Make_cname(eds.ods[0x1003].parameter_name)}"):("NULL"); - string xxENTRY_H1200 = eds.ods.ContainsKey(0x1200) ? ($"{odname}_ENTRY_H1200_{Make_cname(eds.ods[0x1200].parameter_name)}"):("NULL"); - string xxENTRY_H1280 = eds.ods.ContainsKey(0x1280) ? ($"{odname}_ENTRY_H1280_{Make_cname(eds.ods[0x1280].parameter_name)}"):("NULL"); - string xxENTRY_H1012 = eds.ods.ContainsKey(0x1012) ? ($"{odname}_ENTRY_H1012_{Make_cname(eds.ods[0x1012].parameter_name)}"):("NULL"); - string xxENTRY_H1005 = eds.ods.ContainsKey(0x1005) ? ($"{odname}_ENTRY_H1005_{Make_cname(eds.ods[0x1005].parameter_name)}"):("NULL"); - string xxENTRY_H1006 = eds.ods.ContainsKey(0x1006) ? ($"{odname}_ENTRY_H1006_{Make_cname(eds.ods[0x1006].parameter_name)}"):("NULL"); - string xxENTRY_H1007 = eds.ods.ContainsKey(0x1007) ? ($"{odname}_ENTRY_H1007_{Make_cname(eds.ods[0x1007].parameter_name)}"):("NULL"); - string xxENTRY_H1019 = eds.ods.ContainsKey(0x1019) ? ($"{odname}_ENTRY_H1019_{Make_cname(eds.ods[0x1019].parameter_name)}"):("NULL"); - string xxENTRY_H1400 = eds.ods.ContainsKey(0x1400) ? ($"{odname}_ENTRY_H1400_{Make_cname(eds.ods[0x1400].parameter_name)}"):("NULL"); - string xxENTRY_H1600 = eds.ods.ContainsKey(0x1600) ? ($"{odname}_ENTRY_H1600_{Make_cname(eds.ods[0x1600].parameter_name)}"):("NULL"); - string xxENTRY_H1800 = eds.ods.ContainsKey(0x1800) ? ($"{odname}_ENTRY_H1800_{Make_cname(eds.ods[0x1800].parameter_name)}"):("NULL"); - string xxENTRY_H1A00 = eds.ods.ContainsKey(0x1A00) ? ($"{odname}_ENTRY_H1A00_{Make_cname(eds.ods[0x1A00].parameter_name)}"):("NULL"); - string xxENTRY_H1300 = eds.ods.ContainsKey(0x1300) ? ($"{odname}_ENTRY_H1300_{Make_cname(eds.ods[0x1300].parameter_name)}"):("NULL"); - string xxENTRY_H1301 = eds.ods.ContainsKey(0x1301) ? ($"{odname}_ENTRY_H1301_{Make_cname(eds.ods[0x1301].parameter_name)}"):("NULL"); - string xxENTRY_H1381 = eds.ods.ContainsKey(0x1381) ? ($"{odname}_ENTRY_H1381_{Make_cname(eds.ods[0x1381].parameter_name)}"):("NULL"); - string xxENTRY_H13FE = eds.ods.ContainsKey(0x13FE) ? ($"{odname}_ENTRY_H13FE_{Make_cname(eds.ods[0x13FE].parameter_name)}"):("NULL"); - string xxENTRY_H13FF = eds.ods.ContainsKey(0x13FF) ? ($"{odname}_ENTRY_H13FF_{Make_cname(eds.ods[0x13FF].parameter_name)}"):("NULL"); - - file.WriteLine($@"#ifdef CO_MULTIPLE_OD -#define {odname}_INIT_CONFIG(config) {{\ - (config).CNT_NMT = {CNT_NMT};\ - (config).ENTRY_H1017 = {xxENTRY_H1017};\ - (config).CNT_HB_CONS = {CNT_HB_CONS};\ - (config).ENTRY_H1016 = {xxENTRY_H1016};\ - (config).CNT_EM = {CNT_EM};\ - (config).ENTRY_H1001 = {xxENTRY_H1001};\ - (config).ENTRY_H1014 = {xxENTRY_H1014};\ - (config).ENTRY_H1015 = {xxENTRY_H1015};\ - (config).ENTRY_H1003 = {xxENTRY_H1003};\ - (config).CNT_SDO_SRV = {CNT_SDO_SRV};\ - (config).ENTRY_H1200 = {xxENTRY_H1200};\ - (config).CNT_SDO_CLI = {CNT_SDO_CLI};\ - (config).ENTRY_H1280 = {xxENTRY_H1280};\ - (config).CNT_TIME = {CNT_TIME};\ - (config).ENTRY_H1012 = {xxENTRY_H1012};\ - (config).CNT_SYNC = {CNT_SYNC};\ - (config).ENTRY_H1005 = {xxENTRY_H1005};\ - (config).ENTRY_H1006 = {xxENTRY_H1006};\ - (config).ENTRY_H1007 = {xxENTRY_H1007};\ - (config).ENTRY_H1019 = {xxENTRY_H1019};\ - (config).CNT_RPDO = {CNT_RPDO};\ - (config).ENTRY_H1400 = {xxENTRY_H1400};\ - (config).ENTRY_H1600 = {xxENTRY_H1600};\ - (config).CNT_TPDO = {CNT_TPDO};\ - (config).ENTRY_H1800 = {xxENTRY_H1800};\ - (config).ENTRY_H1A00 = {xxENTRY_H1A00};\ - (config).CNT_LEDS = {CNT_LEDS};\ - (config).CNT_GFC = {CNT_GFC};\ - (config).ENTRY_H1300 = {xxENTRY_H1300};\ - (config).CNT_SRDO = {CNT_SRDO};\ - (config).ENTRY_H1301 = {xxENTRY_H1301};\ - (config).ENTRY_H1381 = {xxENTRY_H1381};\ - (config).ENTRY_H13FE = {xxENTRY_H13FE};\ - (config).ENTRY_H13FF = {xxENTRY_H13FF};\ - (config).CNT_LSS_SLV = {CNT_LSS_SLV};\ - (config).CNT_LSS_MST = {CNT_LSS_MST};\ - (config).CNT_GTWA = {CNT_GTWA};\ - (config).CNT_TRACE = {CNT_TRACE};\ -}} -#endif"); + Sizes of OD arrays +*******************************************************************************/")); + foreach (KeyValuePair kvp in ODArrSize) + { + file.WriteLine($"#define {odname}_CNT_ARR_{kvp.Key} {kvp.Value}"); + } file.WriteLine(@" @@ -574,10 +510,60 @@ Object dictionary entries - shortcuts /******************************************************************************* Object dictionary entries - shortcuts with names *******************************************************************************/ -{1} +{0}", string.Join("\n", ODDefinesLong))); -#endif /* {0}_H */", - odname, string.Join("\n", ODDefinesLong))); + file.WriteLine($@" + +/******************************************************************************* + OD config structure +*******************************************************************************/ +#ifdef CO_MULTIPLE_OD +#define {odname}_INIT_CONFIG(config) {{\ + (config).CNT_NMT = {(ODCnt.ContainsKey("NMT") ? odname + "_CNT_NMT" : "0")};\ + (config).ENTRY_H1017 = {(eds.ods.ContainsKey(0x1017) ? odname + "_ENTRY_H1017" : "NULL")};\ + (config).CNT_HB_CONS = {(ODCnt.ContainsKey("HB_CONS") ? odname + "_CNT_HB_CONS" : "0")};\ + (config).CNT_ARR_1016 = {(eds.ods.ContainsKey(0x1016) ? odname + "_CNT_ARR_1016" : "0")};\ + (config).ENTRY_H1016 = {(eds.ods.ContainsKey(0x1016) ? odname + "_ENTRY_H1016" : "NULL")};\ + (config).CNT_EM = {(ODCnt.ContainsKey("EM") ? odname + "_CNT_EM" : "0")};\ + (config).ENTRY_H1001 = {(eds.ods.ContainsKey(0x1001) ? odname + "_ENTRY_H1001" : "NULL")};\ + (config).ENTRY_H1014 = {(eds.ods.ContainsKey(0x1014) ? odname + "_ENTRY_H1014" : "NULL")};\ + (config).ENTRY_H1015 = {(eds.ods.ContainsKey(0x1015) ? odname + "_ENTRY_H1015" : "NULL")};\ + (config).CNT_ARR_1003 = {(eds.ods.ContainsKey(0x1003) ? odname + "_CNT_ARR_1003" : "0")};\ + (config).ENTRY_H1003 = {(eds.ods.ContainsKey(0x1003) ? odname + "_ENTRY_H1003" : "NULL")};\ + (config).CNT_SDO_SRV = {(ODCnt.ContainsKey("SDO_SRV") ? odname + "_CNT_SDO_SRV" : "0")};\ + (config).ENTRY_H1200 = {(eds.ods.ContainsKey(0x1200) ? odname + "_ENTRY_H1200" : "NULL")};\ + (config).CNT_SDO_CLI = {(ODCnt.ContainsKey("SDO_CLI") ? odname + "_CNT_SDO_CLI" : "0")};\ + (config).ENTRY_H1280 = {(eds.ods.ContainsKey(0x1280) ? odname + "_ENTRY_H1280" : "NULL")};\ + (config).CNT_TIME = {(ODCnt.ContainsKey("TIME") ? odname + "_CNT_TIME" : "0")};\ + (config).ENTRY_H1012 = {(eds.ods.ContainsKey(0x1012) ? odname + "_ENTRY_H1012" : "NULL")};\ + (config).CNT_SYNC = {(ODCnt.ContainsKey("SYNC") ? odname + "_CNT_SYNC" : "0")};\ + (config).ENTRY_H1005 = {(eds.ods.ContainsKey(0x1005) ? odname + "_ENTRY_H1005" : "NULL")};\ + (config).ENTRY_H1006 = {(eds.ods.ContainsKey(0x1006) ? odname + "_ENTRY_H1006" : "NULL")};\ + (config).ENTRY_H1007 = {(eds.ods.ContainsKey(0x1007) ? odname + "_ENTRY_H1007" : "NULL")};\ + (config).ENTRY_H1019 = {(eds.ods.ContainsKey(0x1019) ? odname + "_ENTRY_H1019" : "NULL")};\ + (config).CNT_RPDO = {(ODCnt.ContainsKey("RPDO") ? odname + "_CNT_RPDO" : "0")};\ + (config).ENTRY_H1400 = {(eds.ods.ContainsKey(0x1400) ? odname + "_ENTRY_H1400" : "NULL")};\ + (config).ENTRY_H1600 = {(eds.ods.ContainsKey(0x1600) ? odname + "_ENTRY_H1600" : "NULL")};\ + (config).CNT_TPDO = {(ODCnt.ContainsKey("TPDO") ? odname + "_CNT_TPDO" : "0")};\ + (config).ENTRY_H1800 = {(eds.ods.ContainsKey(0x1800) ? odname + "_ENTRY_H1800" : "NULL")};\ + (config).ENTRY_H1A00 = {(eds.ods.ContainsKey(0x1A00) ? odname + "_ENTRY_H1A00" : "NULL")};\ + (config).CNT_LEDS = 0;\ + (config).CNT_GFC = {(ODCnt.ContainsKey("GFC") ? odname + "_CNT_GFC" : "0")};\ + (config).ENTRY_H1300 = {(eds.ods.ContainsKey(0x1300) ? odname + "_ENTRY_H1300" : "NULL")};\ + (config).CNT_SRDO = {(ODCnt.ContainsKey("SRDO") ? odname + "_CNT_SRDO" : "0")};\ + (config).ENTRY_H1301 = {(eds.ods.ContainsKey(0x1301) ? odname + "_ENTRY_H1301" : "NULL")};\ + (config).ENTRY_H1381 = {(eds.ods.ContainsKey(0x1381) ? odname + "_ENTRY_H1381" : "NULL")};\ + (config).ENTRY_H13FE = {(eds.ods.ContainsKey(0x13FE) ? odname + "_ENTRY_H13FE" : "NULL")};\ + (config).ENTRY_H13FF = {(eds.ods.ContainsKey(0x13FF) ? odname + "_ENTRY_H13FF" : "NULL")};\ + (config).CNT_LSS_SLV = 0;\ + (config).CNT_LSS_MST = 0;\ + (config).CNT_GTWA = 0;\ + (config).CNT_TRACE = 0;\ +}} +#endif"); + + file.WriteLine(string.Format(@" +#endif /* {0}_H */", odname)); file.Close(); } @@ -602,11 +588,10 @@ private void Export_c(string folderpath, string filename, string gitVersion, EDS @"/******************************************************************************* CANopen Object Dictionary definition for CANopenNode V4 - This file was automatically generated with - libedssharp Object Dictionary Editor {0} + This file was automatically generated by CANopenEditor {0} https://github.com/CANopenNode/CANopenNode - https://github.com/robincornelius/libedssharp + https://github.com/CANopenNode/CANopenEditor DON'T EDIT THIS FILE MANUALLY, UNLESS YOU KNOW WHAT YOU ARE DOING !!!! *******************************************************************************/ @@ -748,7 +733,6 @@ private class DataProperties private DataProperties Get_dataProperties(DataType dataType, string defaultvalue, UInt32 stringLength, string indexH) { DataProperties data = new DataProperties(); - int nobase = 10; bool valueDefined = true; if (defaultvalue == null || defaultvalue == "") @@ -794,99 +778,99 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue { case DataType.BOOLEAN: data.length = 1; + data.cType = "bool_t"; if (valueDefined) { - data.cType = "bool_t"; data.cValue = (defaultvalue.ToLower() == "false" || defaultvalue == "0") ? "false" : "true"; } break; case DataType.INTEGER8: data.length = 1; + data.cType = "int8_t"; if (valueDefined) { - data.cType = "int8_t"; data.cValue = $"{Convert.ToSByte(defaultvalue, nobase)}"; } break; case DataType.INTEGER16: data.length = 2; + data.cType = "int16_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "int16_t"; data.cValue = $"{Convert.ToInt16(defaultvalue, nobase)}"; } break; case DataType.INTEGER32: data.length = 4; + data.cType = "int32_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "int32_t"; data.cValue = $"{Convert.ToInt32(defaultvalue, nobase)}"; } break; case DataType.INTEGER64: data.length = 8; + data.cType = "int64_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "int64_t"; data.cValue = $"{Convert.ToInt64(defaultvalue, nobase)}"; } break; case DataType.UNSIGNED8: data.length = 1; + data.cType = "uint8_t"; if (valueDefined) { - data.cType = "uint8_t"; data.cValue = String.Format("0x{0:X2}", Convert.ToByte(defaultvalue, nobase)); } break; case DataType.UNSIGNED16: data.length = 2; + data.cType = "uint16_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "uint16_t"; data.cValue = String.Format("0x{0:X4}", Convert.ToUInt16(defaultvalue, nobase)); } break; case DataType.UNSIGNED32: data.length = 4; + data.cType = "uint32_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "uint32_t"; data.cValue = String.Format("0x{0:X8}", Convert.ToUInt32(defaultvalue, nobase)); } break; case DataType.UNSIGNED64: data.length = 8; + data.cType = "uint64_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "uint64_t"; data.cValue = String.Format("0x{0:X16}", Convert.ToUInt64(defaultvalue, nobase)); } break; case DataType.REAL32: data.length = 4; + data.cType = "float32_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "float32_t"; data.cValue = defaultvalue; } break; case DataType.REAL64: data.length = 8; + data.cType = "float64_t"; data.cTypeMultibyte = true; if (valueDefined) { - data.cType = "float64_t"; data.cValue = defaultvalue; } break; diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 2cc1bb20..cd010a0f 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -115,7 +115,7 @@ public void WriteMultiXML(string file, List edss, string gitVersion, b XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true, NewLineChars = "\n" }); writer.WriteStartDocument(); writer.WriteComment(string.Format("CANopen Project file in custom format. It contains multiple standard CANopen device description files.", gitVersion)); - writer.WriteComment(string.Format("File is generated with libedssharp Object Dictionary Editor {0}, URL: https://github.com/robincornelius/libedssharp", gitVersion)); + writer.WriteComment(string.Format("File is generated by CANopenEditor {0}, URL: https://github.com/CANopenNode/CANopenEditor", gitVersion)); writer.WriteComment("File includes additional custom properties for CANopenNode, CANopen protocol stack, URL: https://github.com/CANopenNode/CANopenNode"); serializer.Serialize(writer, oep); writer.WriteEndDocument(); @@ -140,7 +140,7 @@ public void WriteXML(string file, EDSsharp eds, string gitVersion, bool deviceCo stream.NewLine = "\n"; XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true, NewLineChars = "\n" }); writer.WriteStartDocument(); - writer.WriteComment(string.Format("File is generated with libedssharp Object Dictionary Editor {0}, URL: https://github.com/robincornelius/libedssharp", gitVersion)); + writer.WriteComment(string.Format("File is generated by CANopenEditor {0}, URL: https://github.com/CANopenNode/CANopenEditor", gitVersion)); if (!stripped) writer.WriteComment("File includes additional custom properties for CANopenNode, CANopen protocol stack, URL: https://github.com/CANopenNode/CANopenNode"); serializer.Serialize(writer, dev); diff --git a/libEDSsharp/DocumentationGen.cs b/libEDSsharp/DocumentationGen.cs index d7879f6d..e36f4ebb 100644 --- a/libEDSsharp/DocumentationGen.cs +++ b/libEDSsharp/DocumentationGen.cs @@ -176,7 +176,7 @@ public void genmddoc(string filepath, EDSsharp eds, string gitVersion) | Modified | {6,-30} | | Modified By | {7,-30} | -This file was automatically generated with [libedssharp](https://github.com/robincornelius/libedssharp) Object Dictionary Editor {8} +This file was automatically generated by [CANopenEditor](https://github.com/CANopenNode/CANopenEditor) {8} [TOC] ", From a13c233b9ca3c1d6769a86605feb4e98276fd074 Mon Sep 17 00:00:00 2001 From: Janez Date: Sat, 26 Jun 2021 13:27:32 +0200 Subject: [PATCH 012/226] Update DS301_profile.xpd, object 1003 Remove default values from object 1003 and increase subindexes to 16 Change homepage of CANopenEditor to https://github.com/CANopenNode/CANopenEditor --- EDSEditorGUI/Profiles/DS301_profile.xpd | 59 +++++++++++++++++++------ README.md | 2 +- 2 files changed, 46 insertions(+), 15 deletions(-) diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 5e402278..690bc4b2 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -1,5 +1,5 @@ - + @@ -15,7 +15,7 @@ CANopen - + @@ -45,7 +45,7 @@ - + @@ -663,47 +663,70 @@ - - - - - - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * bit 31: set to 0 @@ -2254,13 +2277,13 @@ CANopen - + - + @@ -2270,6 +2293,14 @@ + + + + + + + + diff --git a/README.md b/README.md index f743fbc3..955547d4 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ CANopen is the internationally standardized (EN 50325-4) ([CiA301](http://can-ci [CANopenNode](https://github.com/CANopenNode/CANopenNode) is free and open source CANopen Stack -This is the `main` branch with sources. For binaries see the `build` branch. +This is the `main` branch with sources. For binaries see the `build` branch or download latest [CANopenEditor-build.zip](https://github.com/CANopenNode/CANopenEditor/archive/refs/heads/build.zip). ---- From fc4785706bcfc5529006d60237a5a8f4b17f73cf Mon Sep 17 00:00:00 2001 From: Oli Jeal Date: Tue, 29 Jun 2021 19:04:46 +0100 Subject: [PATCH 013/226] Various PDO fixes --- EDSEditorGUI/DevicePDOView2.cs | 8 +++++++- libEDSsharp/PDOHelper.cs | 17 +++++++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 5dc88cfe..f0edade9 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -755,14 +755,20 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) MessageBox.Show(string.Format("Invalid RXPDO Communication parameters index 0x{0:x4}", config)); return; } - } + } UInt16 inhibit = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_inhibit.Text); UInt16 eventtimer = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_eventtimer.Text); + UInt32 COB = libEDSsharp.EDSsharp.ConvertToUInt32(textBox_cob.Text); byte syncstart = libEDSsharp.EDSsharp.ConvertToByte(textBox_syncstart.Text); byte transmissiontype = libEDSsharp.EDSsharp.ConvertToByte(textBox_type.Text); selectedslot.ConfigurationIndex = config; + selectedslot.COB = COB; + selectedslot.inhibit = inhibit; + selectedslot.eventtimer = eventtimer; + selectedslot.syncstart = syncstart; + selectedslot.transmissiontype = transmissiontype; try { diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index ea993ba7..3850c502 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -84,6 +84,9 @@ public bool invalid public PDOSlot() { + configloc = "PERSIST_COMM"; + mappingloc = "PERSIST_COMM"; + transmissiontype = 254; Mapping = new List(); } @@ -308,6 +311,7 @@ public void buildmappingsfromlists() ODentry sub = new ODentry("max sub-index", (ushort)slot.ConfigurationIndex, 0); sub.defaultvalue = "6"; sub.datatype = DataType.UNSIGNED8; + sub.accesstype = EDSsharp.AccessType.ro; config.addsubobject(0x00,sub); config.accesstype = slot.configAccessType; @@ -318,50 +322,60 @@ public void buildmappingsfromlists() { config.parameter_name = "TPDO communication parameter"; + config.prop.CO_countLabel = "TPDO"; sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = slot.COB.ToHexString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); sub = new ODentry("inhibit time", (ushort)slot.ConfigurationIndex, 3); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.inhibit.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x03, sub); sub = new ODentry("compatibility entry", (ushort)slot.ConfigurationIndex, 4); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = "0"; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x04, sub); sub = new ODentry("event timer", (ushort)slot.ConfigurationIndex, 5); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.eventtimer.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x05, sub); sub = new ODentry("SYNC start value", (ushort)slot.ConfigurationIndex, 6); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.syncstart.ToString(); ; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x06, sub); } else { config.parameter_name = "RPDO communication parameter"; + config.prop.CO_countLabel = "RPDO"; sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = slot.COB.ToHexString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); } @@ -383,6 +397,7 @@ public void buildmappingsfromlists() sub = new ODentry("Number of mapped objects", (ushort)slot.MappingIndex, 0); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.Mapping.Count().ToString(); + sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(0x00, sub); byte mappingcount = 1; @@ -391,6 +406,7 @@ public void buildmappingsfromlists() sub = new ODentry(String.Format("Mapped object {0:x}",mappingcount), (ushort)slot.MappingIndex, mappingcount); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = string.Format("0x{0:x4}{1:x2}{2:x2}", mapslot.Index, mapslot.Subindex, mapslot.Sizeofdatatype()); + sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(mappingcount, sub); mappingcount++; @@ -422,6 +438,7 @@ public void addPDOslot(UInt16 configindex) PDOSlot newslot = new PDOSlot(); newslot.ConfigurationIndex = configindex; + newslot.COB = 0x180; //Fixme need a better default??? pdoslots.Add(newslot); From 2b0dbd1b78484b6d7c85523673df9b6f9eac41c1 Mon Sep 17 00:00:00 2001 From: Bennett Date: Tue, 20 Jul 2021 14:28:33 -0400 Subject: [PATCH 014/226] Added a test file for CanOpenNodeExporter_V4. The method Make_cname in CanOpenNodeExporter_V4 was failing and no tests existed. The test created was replicated from the method make_cname in CanOpenNodeExporter. To create the test CanOpenNodeExporter_V4.Make_cname was changed from private to protected. --- Tests/ExporterTestsV4.cs | 24 ++++++++++++++++++++++++ Tests/Tests.csproj | 1 + libEDSsharp/CanOpenNodeExporter_V4.cs | 2 +- 3 files changed, 26 insertions(+), 1 deletion(-) create mode 100644 Tests/ExporterTestsV4.cs diff --git a/Tests/ExporterTestsV4.cs b/Tests/ExporterTestsV4.cs new file mode 100644 index 00000000..519ff1a1 --- /dev/null +++ b/Tests/ExporterTestsV4.cs @@ -0,0 +1,24 @@ +using System; +using Xunit; +using libEDSsharp; + +namespace Tests +{ + public class ExporterTestsV4 : CanOpenNodeExporter_V4 + { + [Fact] + public void Test_cname_conversion() + { + + if (Make_cname("axle 0 wheel right controlword") != "axle0WheelRightControlword") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("mapped object 4") != "mappedObject4") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("COB ID used by RPDO") != "COB_IDUsedByRPDO") + throw (new Exception("Make_cname Conversion error")); + + } + } +} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index e9292524..64cf6f23 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -67,6 +67,7 @@ + diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 99515750..b5bb2b59 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -664,7 +664,7 @@ Object dictionary /// /// string, name to convert /// string - private static string Make_cname(string name) + protected static string Make_cname(string name) { if (name == null || name == "") return ""; From b25324c539a02ee4b09fb4b762cf00b65d259489 Mon Sep 17 00:00:00 2001 From: Bennett Date: Tue, 20 Jul 2021 17:25:20 -0400 Subject: [PATCH 015/226] Added string to test that caused an exception in Make_cname(). The string that failed when running 'Export CanOpenNode...' in the EDSEditor was added to the test for CanOpenNodeExporter_V4.Make_cname. Other strings were also added that tests conditions that Make_cname should handle. The exception was caused by an array out-of-bounds error. --- Tests/ExporterTestsV4.cs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/Tests/ExporterTestsV4.cs b/Tests/ExporterTestsV4.cs index 519ff1a1..46cc1cb8 100644 --- a/Tests/ExporterTestsV4.cs +++ b/Tests/ExporterTestsV4.cs @@ -7,9 +7,8 @@ namespace Tests public class ExporterTestsV4 : CanOpenNodeExporter_V4 { [Fact] - public void Test_cname_conversion() + public void Test_Make_cname_conversion() { - if (Make_cname("axle 0 wheel right controlword") != "axle0WheelRightControlword") throw (new Exception("Make_cname Conversion error")); @@ -19,6 +18,18 @@ public void Test_cname_conversion() if (Make_cname("COB ID used by RPDO") != "COB_IDUsedByRPDO") throw (new Exception("Make_cname Conversion error")); + if (Make_cname("A/D unit offset value (filtered)") != "A_DUnitOffsetValueFiltered") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("80 test string") != "_80TestString") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("Eighty test string") != "eightyTestString") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("A") != "a") + throw (new Exception("Make_cname Conversion error")); + } } } From f701092c63d8d57746bf1351186bf4ba91675e8e Mon Sep 17 00:00:00 2001 From: Bennett Date: Wed, 21 Jul 2021 11:20:00 -0400 Subject: [PATCH 016/226] Fixed a bug in the CanOpenNodeExporter_V4.Make_cname. The method would fail on a array out-of-bounds exception. This was do to and empty string that was added to the tokens list. It was fixed by removing all empty strings from the tokens list as was done in CanOpenNodeExporter.make_cname. The conditions in the test for this method all failed. The method was modified to pass the conditions in the test. --- libEDSsharp/CanOpenNodeExporter_V4.cs | 43 +++++++++++++++++---------- 1 file changed, 27 insertions(+), 16 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index b5bb2b59..463ceb52 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License using System.Text; using System.Text.RegularExpressions; using System.IO; +using System.Linq; namespace libEDSsharp { @@ -669,42 +670,52 @@ protected static string Make_cname(string name) if (name == null || name == "") return ""; - // split string to tokens, separated by non-word characters - string[] tokens = Regex.Split(name.Replace('-', '_'), @"[\W]+"); + // split string to tokens, separated by non-word characters. Remove any empty strings + var tokens = Regex.Split(name.Replace('-', '_'), @"[\W]+").Where(s => s != String.Empty); string output = ""; char prev = ' '; foreach (string tok in tokens) { - if (tok.Length == 0) - continue; - char first = tok[0]; - if (Char.IsDigit(first) || Char.IsDigit(prev) || (Char.IsUpper(prev) && Char.IsUpper(first))) + if (Char.IsUpper(prev) && Char.IsUpper(first)) { - // add underscore, if tok starts with digit or we have two upper-case words - output += "_" + tok; + // add underscore, if we have two upper-case words + output += "_"; } - else if (output.Length > 0) + + if (tok.Length > 1 && Char.IsLetter(first)) { - // all tokens except the first start with uppercse letter + // all tokens except the first start with uppercase letter output += Char.ToUpper(first) + tok.Substring(1); } - else if (Char.IsLower(tok[1])) - { - // first token start with lower-case letter, except whole word is uppercase - output += Char.ToLower(first) + tok.Substring(1); - } else { - // use token as is + // use token as is and handle what the start of the output looks like outside of the loop output += tok; } prev = tok[tok.Length - 1]; } + if (Char.IsDigit(output[0])) + { + // output that starts with a digit needs a starting underscore + output = "_" + output; + } + else if (output.Length > 1) + { + // output that doesnt start with all-cap-words should have word start with a lower case character + if (Char.IsLetter(output[0]) && Char.IsLower(output[1])) + output = Char.ToLower(output[0]) + output.Substring(1); + } + else + { + // single character output + output = output.ToLower(); + } + return output; } From a6765f9573abf6f72c4d3ffce635938dbe9a034d Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Wed, 23 Mar 2022 17:48:16 +0100 Subject: [PATCH 017/226] fixed the export of array of strings Switch the length definition of length of the 2d array before fix: VISIBLE_STRING arrayOfStrings[lengthOfString][NumberOfStrings]; after fix: VISIBLE_STRING arrayOfStrings[NumberOfStrings][lengthOfString]; --- libEDSsharp/CanOpenNodeExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 35dc25e4..1c0746bf 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -382,7 +382,7 @@ protected string print_h_entry(ODentry od) specialarraylength = string.Format("[{0}]", maxlength); } - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}{specialarraylength}[{od.Nosubindexes - 1}];"); + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{od.Nosubindexes - 1}]{specialarraylength};"); } } } From 71ca376f6f47264424ecf74a9762411978037430 Mon Sep 17 00:00:00 2001 From: Bert Regelink Date: Wed, 1 Jun 2022 10:12:58 +0200 Subject: [PATCH 018/226] Create dotnet.yml --- .github/workflows/dotnet.yml | 39 ++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) create mode 100644 .github/workflows/dotnet.yml diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml new file mode 100644 index 00000000..a72ac2e3 --- /dev/null +++ b/.github/workflows/dotnet.yml @@ -0,0 +1,39 @@ +name: .NET + +on: + push: + branches: [ main ] + pull_request: + branches: [ main ] + +jobs: + build: + + runs-on: windows-2019 +# runs-on: windows-latest # error MSB3644: The reference assemblies for .NETFramework,Version=v4.5 were not found. +# runs-on: ubuntu-latest # Error: setup-msbuild can only be run on Windows runners + steps: + - name: Checkout + uses: actions/checkout@v3 + - name: Setup .NET + uses: microsoft/setup-msbuild@v1.1 +# uses: actions/setup-dotnet@v2 +# with: +# dotnet-version: 5.0.x +# - name: Restore dependencies +# run: dotnet restore + - name: Add Packages + run: | + nuget install EDSEditorGUI/packages.config -OutputDirectory packages +# nuget install Tests/packages.config -OutputDirectory packages + - name: Build +# run: make all # builds the Debug configuration + run: msbuild EDSEditorGUI /property:Configuration=Release +# run: dotnet build --no-restore +# - name: Test +# run: dotnet test --no-build --verbosity normal + - name: Upload Artifact + uses: actions/upload-artifact@v3 + with: + name: EDSEditor + path: EDSEditorGUI\bin\Release\ From e6d7adcedb0d9bfc74075aa78e071f618f0a0ba5 Mon Sep 17 00:00:00 2001 From: Bert Regelink Date: Tue, 7 Jun 2022 09:10:25 +0200 Subject: [PATCH 019/226] Add 0 to attributes when empty --- libEDSsharp/CanOpenNodeExporter_V4.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 99515750..ada3ef6d 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -1110,6 +1110,8 @@ private string Get_attributes(ODentry od, bool cTypeMultibyte, bool cTypeString) if (cTypeString) attributes.Add("ODA_STR"); + if (attributes.Count == 0) attributes.Add("0"); + return string.Join(" | ", attributes); } #endregion From 7cda81c17f1c65e5a55c7ce495027c3612c442e6 Mon Sep 17 00:00:00 2001 From: Bert Regelink Date: Tue, 7 Jun 2022 10:10:43 +0200 Subject: [PATCH 020/226] Fixed typo in PDOHelper.cs (1600 --> 0x1600) --- libEDSsharp/PDOHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index ea993ba7..b111e9a4 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -408,7 +408,7 @@ public void buildmappingsfromlists() public void addPDOslot(UInt16 configindex) { //quick range check, it must be a config index for an RXPDO or a TXPDO - if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=1600) && (configindex<0x1800))) + if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=0x1600) && (configindex<0x1800))) return; foreach(PDOSlot slot in pdoslots) From 81932e1d142fdafc0feef77c2cb1bd27f4e1247f Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 27 Jun 2022 15:29:47 +0200 Subject: [PATCH 021/226] PDOHelper.cs:411 if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=1600) && (configindex<0x1800))) 1600 was in decimal. Must be in hex: if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=0x1600) && (configindex<0x1800))) --- libEDSsharp/PDOHelper.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index ea993ba7..b111e9a4 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -408,7 +408,7 @@ public void buildmappingsfromlists() public void addPDOslot(UInt16 configindex) { //quick range check, it must be a config index for an RXPDO or a TXPDO - if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=1600) && (configindex<0x1800))) + if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=0x1600) && (configindex<0x1800))) return; foreach(PDOSlot slot in pdoslots) From e47910771cb3bbe5e9753937c556dad8f1ac5a71 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 18 Jul 2022 10:07:37 +0200 Subject: [PATCH 022/226] Framework 4.8 Add some comments Boundaries for PDO review more clearly stated --- EDSEditorGUI/App.config | 42 +- EDSEditorGUI/EDSEditorGUI.csproj | 575 +- EDSEditorGUI/Properties/Resources.Designer.cs | 506 +- EDSEditorGUI/Properties/Settings.Designer.cs | 100 +- EDSEditorGUI/packages.config | 6 +- EDSSharp/App.config | 12 +- EDSSharp/EDSSharp.csproj | 115 +- Tests/Tests.csproj | 229 +- Tests/packages.config | 22 +- libEDSsharp/PDOHelper.cs | 2 +- libEDSsharp/eds.cs | 6460 ++++++++--------- libEDSsharp/libEDSsharp.csproj | 125 +- 12 files changed, 4099 insertions(+), 4095 deletions(-) diff --git a/EDSEditorGUI/App.config b/EDSEditorGUI/App.config index 2c3d682e..f0b21cff 100644 --- a/EDSEditorGUI/App.config +++ b/EDSEditorGUI/App.config @@ -1,21 +1,21 @@ - - - - -
- - - - - - - - - 0 - - - 65535 - - - - \ No newline at end of file + + + + +
+ + + + + + + + + 0 + + + 65535 + + + + diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 6bb52bc3..9c39d01f 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -1,294 +1,295 @@ - - - - - Debug - AnyCPU - {13D2D8ED-242B-4283-BF14-AA79FE875F7C} - WinExe - Properties - ODEditor - EDSEditor - v4.5 - 512 - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - Index_8287_16x.ico - - - app.manifest - - - - False - True - .\Microsoft.mshtml.dll - - - ..\packages\SourceGrid.4.4.0\lib\net35\SourceGrid.dll - - - - - - - - - - - - - - - UserControl - - - DeviceInfoView.cs - - - UserControl - - - DeviceODView.cs - - - UserControl - - - DevicePDOView2.cs - - - UserControl - - - DeviceView.cs - - - Form - - - Form1.cs - - - Component - - - UserControl - - - ModuleInfo.cs - - - UserControl - - - Form - - - InsertObjects.cs - - - Form - - - NewIndex.cs - - - Form - - - NewItem.cs - - - Form - - - Preferences.cs - - - - - Form - - - ReportView.cs - - - Component - - - Form - - - Warnings.cs - - - DeviceInfoView.cs - - - DeviceODView.cs - - - DevicePDOView2.cs - - - DeviceView.cs - - - Form1.cs - - - ModuleInfo.cs - - - MyTabUserControl.cs - - - InsertObjects.cs - - - NewIndex.cs - - - NewItem.cs - - - Preferences.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - ReportView.cs - - - Warnings.cs - - - - - PreserveNewest - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - - - - - False - Microsoft .NET Framework 4.5 %28x86 and x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - - PreserveNewest - - - PreserveNewest - - - Always - - - - - - - - - - - - - PreserveNewest - - - - - - - - - - - - - - - - - - git describe --tags --long --dirty > "$(ProjectDir)version.txt" || exit 0 - + + + + + Debug + AnyCPU + {13D2D8ED-242B-4283-BF14-AA79FE875F7C} + WinExe + Properties + ODEditor + EDSEditor + v4.8 + 512 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + false + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + Index_8287_16x.ico + + + app.manifest + + + + False + True + .\Microsoft.mshtml.dll + + + ..\packages\SourceGrid.4.4.0\lib\net35\SourceGrid.dll + + + + + + + + + + + + + + + UserControl + + + DeviceInfoView.cs + + + UserControl + + + DeviceODView.cs + + + UserControl + + + DevicePDOView2.cs + + + UserControl + + + DeviceView.cs + + + Form + + + Form1.cs + + + Component + + + UserControl + + + ModuleInfo.cs + + + UserControl + + + Form + + + InsertObjects.cs + + + Form + + + NewIndex.cs + + + Form + + + NewItem.cs + + + Form + + + Preferences.cs + + + + + Form + + + ReportView.cs + + + Component + + + Form + + + Warnings.cs + + + DeviceInfoView.cs + + + DeviceODView.cs + + + DevicePDOView2.cs + + + DeviceView.cs + + + Form1.cs + + + ModuleInfo.cs + + + MyTabUserControl.cs + + + InsertObjects.cs + + + NewIndex.cs + + + NewItem.cs + + + Preferences.cs + + + ResXFileCodeGenerator + Resources.Designer.cs + Designer + + + True + Resources.resx + True + + + ReportView.cs + + + Warnings.cs + + + + + PreserveNewest + + + SettingsSingleFileGenerator + Settings.Designer.cs + + + True + Settings.settings + True + + + + + + + + {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} + libEDSsharp + + + + + False + Microsoft .NET Framework 4.5 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + + PreserveNewest + + + PreserveNewest + + + Always + + + + + + + + + + + + + PreserveNewest + + + + + + + + + + + + + + + + + + git describe --tags --long --dirty > "$(ProjectDir)version.txt" || exit 0 + + --> \ No newline at end of file diff --git a/EDSEditorGUI/Properties/Resources.Designer.cs b/EDSEditorGUI/Properties/Resources.Designer.cs index f972f369..734f92bf 100644 --- a/EDSEditorGUI/Properties/Resources.Designer.cs +++ b/EDSEditorGUI/Properties/Resources.Designer.cs @@ -1,253 +1,253 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace ODEditor.Properties { - using System; - - - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ODEditor.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap _305_Close_16x16_72 { - get { - object obj = ResourceManager.GetObject("_305_Close_16x16_72", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap action_add_16xLG { - get { - object obj = ResourceManager.GetObject("action_add_16xLG", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Close_6519 { - get { - object obj = ResourceManager.GetObject("Close_6519", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Compile_191 { - get { - object obj = ResourceManager.GetObject("Compile_191", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap DriverTemplate_32x { - get { - object obj = ResourceManager.GetObject("DriverTemplate_32x", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap EventLog_5735 { - get { - object obj = ResourceManager.GetObject("EventLog_5735", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap ExporttoScript_9881 { - get { - object obj = ResourceManager.GetObject("ExporttoScript_9881", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap GenerateAll { - get { - object obj = ResourceManager.GetObject("GenerateAll", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap GenericVSEditor_9905 { - get { - object obj = ResourceManager.GetObject("GenericVSEditor_9905", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Index_8287_16x { - get { - object obj = ResourceManager.GetObject("Index_8287_16x", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap InsertColumn_5626 { - get { - object obj = ResourceManager.GetObject("InsertColumn_5626", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap ListBox_686 { - get { - object obj = ResourceManager.GetObject("ListBox_686", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap NewFile_6276 { - get { - object obj = ResourceManager.GetObject("NewFile_6276", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Open_6529 { - get { - object obj = ResourceManager.GetObject("Open_6529", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Print_11009 { - get { - object obj = ResourceManager.GetObject("Print_11009", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap PrintPreviewControl_698 { - get { - object obj = ResourceManager.GetObject("PrintPreviewControl_698", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap PrintSetup_11011 { - get { - object obj = ResourceManager.GetObject("PrintSetup_11011", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Remove_16xLG { - get { - object obj = ResourceManager.GetObject("Remove_16xLG", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Looks up a localized resource of type System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Save_6530 { - get { - object obj = ResourceManager.GetObject("Save_6530", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace ODEditor.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ODEditor.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap _305_Close_16x16_72 { + get { + object obj = ResourceManager.GetObject("_305_Close_16x16_72", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap action_add_16xLG { + get { + object obj = ResourceManager.GetObject("action_add_16xLG", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Close_6519 { + get { + object obj = ResourceManager.GetObject("Close_6519", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Compile_191 { + get { + object obj = ResourceManager.GetObject("Compile_191", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap DriverTemplate_32x { + get { + object obj = ResourceManager.GetObject("DriverTemplate_32x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap EventLog_5735 { + get { + object obj = ResourceManager.GetObject("EventLog_5735", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ExporttoScript_9881 { + get { + object obj = ResourceManager.GetObject("ExporttoScript_9881", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap GenerateAll { + get { + object obj = ResourceManager.GetObject("GenerateAll", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap GenericVSEditor_9905 { + get { + object obj = ResourceManager.GetObject("GenericVSEditor_9905", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Index_8287_16x { + get { + object obj = ResourceManager.GetObject("Index_8287_16x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap InsertColumn_5626 { + get { + object obj = ResourceManager.GetObject("InsertColumn_5626", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ListBox_686 { + get { + object obj = ResourceManager.GetObject("ListBox_686", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap NewFile_6276 { + get { + object obj = ResourceManager.GetObject("NewFile_6276", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Open_6529 { + get { + object obj = ResourceManager.GetObject("Open_6529", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Print_11009 { + get { + object obj = ResourceManager.GetObject("Print_11009", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap PrintPreviewControl_698 { + get { + object obj = ResourceManager.GetObject("PrintPreviewControl_698", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap PrintSetup_11011 { + get { + object obj = ResourceManager.GetObject("PrintSetup_11011", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Remove_16xLG { + get { + object obj = ResourceManager.GetObject("Remove_16xLG", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Save_6530 { + get { + object obj = ResourceManager.GetObject("Save_6530", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/EDSEditorGUI/Properties/Settings.Designer.cs b/EDSEditorGUI/Properties/Settings.Designer.cs index 5343ba09..b669499a 100644 --- a/EDSEditorGUI/Properties/Settings.Designer.cs +++ b/EDSEditorGUI/Properties/Settings.Designer.cs @@ -1,50 +1,50 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace ODEditor.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "15.9.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0")] - public int ExporterType { - get { - return ((int)(this["ExporterType"])); - } - set { - this["ExporterType"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("65535")] - public uint WarningMask { - get { - return ((uint)(this["WarningMask"])); - } - set { - this["WarningMask"] = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace ODEditor.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int ExporterType { + get { + return ((int)(this["ExporterType"])); + } + set { + this["ExporterType"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("65535")] + public uint WarningMask { + get { + return ((uint)(this["WarningMask"])); + } + set { + this["WarningMask"] = value; + } + } + } +} diff --git a/EDSEditorGUI/packages.config b/EDSEditorGUI/packages.config index 42c98a77..372049a3 100644 --- a/EDSEditorGUI/packages.config +++ b/EDSEditorGUI/packages.config @@ -1,4 +1,4 @@ - - - + + + \ No newline at end of file diff --git a/EDSSharp/App.config b/EDSSharp/App.config index 7eb8d24f..8a99d30d 100644 --- a/EDSSharp/App.config +++ b/EDSSharp/App.config @@ -1,6 +1,6 @@ - - - - - - + + + + + + diff --git a/EDSSharp/EDSSharp.csproj b/EDSSharp/EDSSharp.csproj index 47e3a120..e0b139bb 100644 --- a/EDSSharp/EDSSharp.csproj +++ b/EDSSharp/EDSSharp.csproj @@ -1,58 +1,59 @@ - - - - - Debug - AnyCPU - {8B7A7545-6257-44BF-8868-F429E1B72C77} - Exe - EDSSharp - EDSSharp - v4.6.1 - 512 - true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - - - - - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - - - + + + + + Debug + AnyCPU + {8B7A7545-6257-44BF-8868-F429E1B72C77} + Exe + EDSSharp + EDSSharp + v4.8 + 512 + true + + + + AnyCPU + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + AnyCPU + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + + + + + + + + + + + + + + + + + {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} + libEDSsharp + + + \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index e9292524..951c20cd 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,121 +1,122 @@ - - - - - - - Debug - AnyCPU - {2A479BF3-7628-409B-8A29-9314C308445E} - Library - Properties - Tests - Tests - v4.5.2 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll - - - ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll - - - ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll - - - ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll - - - - - - - - - - - - - - - - - - - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - - - - - - - - - - - - - False - - - False - - - False - - - False - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - + + + + + + + Debug + AnyCPU + {2A479BF3-7628-409B-8A29-9314C308445E} + Library + Properties + Tests + Tests + v4.8 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll + + + ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll + + + ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll + + + ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll + + + + + + + + + + + + + + + + + + + + {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} + libEDSsharp + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + --> \ No newline at end of file diff --git a/Tests/packages.config b/Tests/packages.config index 29f19a85..d777ea05 100644 --- a/Tests/packages.config +++ b/Tests/packages.config @@ -1,12 +1,12 @@ - - - - - - - - - - - + + + + + + + + + + + \ No newline at end of file diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index b111e9a4..0ac0304e 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -408,7 +408,7 @@ public void buildmappingsfromlists() public void addPDOslot(UInt16 configindex) { //quick range check, it must be a config index for an RXPDO or a TXPDO - if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=0x1600) && (configindex<0x1800))) + if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=0x1600) && (configindex<0x1800))) // true if not in range 0x1400...0x15FF OR 0x1800...0x19FF return; foreach(PDOSlot slot in pdoslots) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 5f845a5c..fc8a8041 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1,3231 +1,3231 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text.RegularExpressions; -using System.Globalization; -using System.Reflection; -using CanOpenXSD_1_1; - -namespace libEDSsharp -{ - - - public enum DataType - { - UNKNOWN = 0, - BOOLEAN = 1, - INTEGER8 = 2, - INTEGER16 = 3, - INTEGER32 = 4, - UNSIGNED8 = 5, - UNSIGNED16 = 6, - UNSIGNED32 = 7, - REAL32 = 8, - VISIBLE_STRING = 9, - OCTET_STRING = 0x0A, - UNICODE_STRING = 0x0B, - TIME_OF_DAY = 0x0C, - TIME_DIFFERENCE = 0x0D, - DOMAIN = 0x0F, - INTEGER24 = 0x10, - REAL64 = 0x11, - INTEGER40 = 0x12, - INTEGER48 = 0x13, - INTEGER56 = 0x14, - INTEGER64 = 0x15, - UNSIGNED24 = 0x16, - UNSIGNED40 = 0x18, - UNSIGNED48 = 0x19, - UNSIGNED56 = 0x1A, - UNSIGNED64 = 0x1B, - - PDO_COMMUNICATION_PARAMETER = 0x20, //PDO_CommPar - PDO_MAPPING = 0x21, //PDO_Mapping - SDO_PARAMETER = 0x22, - IDENTITY = 0x23, - - } - - public enum ObjectType - { - UNKNOWN = -1, - NULL = 0, - DOMAIN =2, - DEFTYPE=5, - DEFSTRUCT=6, - VAR = 7, - ARRAY = 8, - REC = 9, - } - - public enum PDOMappingType - { - no=0, - optional=1, - RPDO=2, - TPDO=3, - @default=4, - } - - public enum AccessSDO - { - no, - ro, - wo, - rw - } - - public enum AccessPDO - { - no, - t, - r, - tr - } - - public enum AccessSRDO - { - no = 0, - tx = 1, - rx = 2, - trx = 3 - } - - /// - /// Custom properties for OD entry or sub-entry, which are saved into xdd file v1.1 - /// - public class CustomProperties - { - public bool CO_disabled = false; // If true, object is completelly skipped by CANopenNode exporters, etc. - public string CO_countLabel = ""; - public string CO_storageGroup = "RAM"; - public bool CO_flagsPDO = false; - public AccessSRDO CO_accessSRDO = AccessSRDO.no; - public UInt32 CO_stringLengthMin = 0; - - public CustomProperties Clone() - { - return new CustomProperties - { - CO_disabled = CO_disabled, - CO_countLabel = CO_countLabel, - CO_storageGroup = CO_storageGroup, - CO_flagsPDO = CO_flagsPDO, - CO_accessSRDO = CO_accessSRDO, - CO_stringLengthMin = CO_stringLengthMin - }; - } - - public void OdeXdd(property[] properties) - { - if (properties != null) - { - foreach (property prop in properties) - { - switch (prop.name) - { - case "CO_disabled": CO_disabled = prop.value == "true"; break; - case "CO_countLabel": CO_countLabel = prop.value ?? ""; break; - case "CO_storageGroup": CO_storageGroup = prop.value ?? ""; break; - case "CO_flagsPDO": CO_flagsPDO = prop.value == "true"; break; - case "CO_accessSRDO": - try { CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), prop.value); } - catch (Exception) { CO_accessSRDO = AccessSRDO.no; } - break; - case "CO_stringLengthMin": - try { CO_stringLengthMin = Convert.ToUInt16(prop.value); } - catch (Exception) { CO_stringLengthMin = 0; } - break; - } - } - } - } - - public property[] OdeXdd() - { - var props = new List(); - - if (CO_disabled) - props.Add(new property { name = "CO_disabled", value = "true" }); - if (CO_countLabel != "") - props.Add(new property { name = "CO_countLabel", value = CO_countLabel }); - if (CO_storageGroup != "RAM") - props.Add(new property { name = "CO_storageGroup", value = CO_storageGroup }); - if (CO_flagsPDO) - props.Add(new property { name = "CO_flagsPDO", value = "true" }); - - return props.ToArray(); - } - - public property[] SubOdeXdd() - { - var props = new List(); - - if (CO_accessSRDO != AccessSRDO.no) - props.Add(new property { name = "CO_accessSRDO", value = CO_accessSRDO.ToString() }); - if (CO_stringLengthMin != 0) - props.Add(new property { name = "CO_stringLengthMin", value = CO_stringLengthMin.ToString() }); - - return props.ToArray(); - } - } - - /// - /// List of multiple CO_storageGroup strings available in project - /// - public class CO_storageGroups : List - { - public CO_storageGroups() - { - Add("RAM"); // default value - } - - public new void Add(string item) - { - if (!Contains(item)) - { - base.Add(item); - } - } - } - - public class EdsExport : Attribute - { - public UInt16 maxlength; - public bool commentonly=false; - - //mehmeh - public EdsExport() - { - } - - public EdsExport(UInt16 maxlength) - { - this.maxlength = maxlength; - } - - public bool IsReadOnly() - { - return commentonly; - } - - - } - - public class DcfExport : EdsExport - { - } - - public class InfoSection - { - protected Dictionary section; - - protected string infoheader; - protected string edssection; - - public enum Filetype - { - File_EDS, - File_DCF - } - - public virtual void Parse(Dictionary section,string sectionname) - { - - this.section = section; - - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - if(Attribute.IsDefined(f, typeof(EdsExport))) - GetField(f.Name, f.Name); - - if (Attribute.IsDefined(f, typeof(DcfExport))) - GetField(f.Name, f.Name); - } - - } - - public bool GetField(string name, string varname) - { - FieldInfo f = null; - - try - { - foreach (var element in section) - { - if (String.Equals(element.Key, name, StringComparison.OrdinalIgnoreCase)) - { - - name = element.Key; - Type tx = this.GetType(); - - f = tx.GetField(varname); - object var = null; - - switch (f.FieldType.Name) - { - case "String": - var = section[name]; - break; - - case "UInt32": - var = Convert.ToUInt32(section[name], EDSsharp.Getbase(section[name])); - break; - - case "Int16": - var = Convert.ToInt16(section[name], EDSsharp.Getbase(section[name])); - break; - - case "UInt16": - var = Convert.ToUInt16(section[name], EDSsharp.Getbase(section[name])); - break; - - case "Byte": - var = Convert.ToByte(section[name], EDSsharp.Getbase(section[name])); - break; - - case "Boolean": - var = section[name] == "1"; //because Convert is Awesome - break; - - default: - Console.WriteLine(String.Format("Unhanded variable {0} for {1}", f.FieldType.Name, varname)); - break; - } - - if (var != null) - { - tx.GetField(varname).SetValue(this, var); - return true; - } - } - } - } - catch (Exception e) - { - if (e is OverflowException) - { - Warnings.warning_list.Add(string.Format("Warning parsing {0} tried to fit {1} into {2}", name, section[name], f.FieldType.Name)); - } - } - - return false; - } - - public override string ToString() - { - string msg; - - msg = $"*****************************************************{Environment.NewLine}"; - msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; - msg += $"*****************************************************{Environment.NewLine}"; - - Type tx = this.GetType(); - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - msg += $"{f.Name,-28}: {f.GetValue(this).ToString()}{Environment.NewLine}"; - } - - return msg; - } - - public void Write(StreamWriter writer, Filetype ft) - { - writer.WriteLine("[" + edssection + "]"); - Type tx = this.GetType(); - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - - if ((ft==Filetype.File_EDS) && (!Attribute.IsDefined(f, typeof(EdsExport)))) - continue; - - if ((ft == Filetype.File_DCF) && (!(Attribute.IsDefined(f, typeof(DcfExport)) || Attribute.IsDefined(f, typeof(EdsExport))))) - continue; - - if (f.GetValue(this) == null) - continue; - - EdsExport ex = (EdsExport)f.GetCustomAttribute(typeof(EdsExport)); - - bool comment = ex.IsReadOnly(); - - if (f.FieldType.Name == "Boolean") - { - writer.WriteLine(string.Format("{2}{0}={1}", f.Name, ((bool)f.GetValue(this)) == true ? 1 : 0,comment==true?";":"")); - } - else - { - writer.WriteLine(string.Format("{2}{0}={1}", f.Name, f.GetValue(this).ToString(), comment == true ? ";" : "")); - } - } - - writer.WriteLine(""); - - } - - } - - - public class MandatoryObjects : SupportedObjects - { - public MandatoryObjects() - : base() - { - infoheader = "Mandatory Objects"; - edssection = "MandatoryObjects"; - } - - public MandatoryObjects(Dictionary section) - : this() - { - Parse(section); - } - } - - public class OptionalObjects : SupportedObjects - { - public OptionalObjects() - : base() - { - infoheader = "Optional Objects"; - edssection = "OptionalObjects"; - } - - public OptionalObjects(Dictionary section) - : this() - { - Parse(section); - } - } - - public class ManufacturerObjects : SupportedObjects - { - public ManufacturerObjects() : base() - { - infoheader = "Manufacturer Objects"; - edssection = "ManufacturerObjects"; - } - - public ManufacturerObjects(Dictionary section) - : this() - { - Parse(section); - } - } - - public class TypeDefinitions : SupportedObjects - { - public TypeDefinitions() : base() - { - infoheader = "Type Definitions"; - edssection = "TypeDefinitions"; - } - - public TypeDefinitions(Dictionary section) - { - Parse(section); - } - - } - - public class SupportedObjects - { - - public Dictionary objectlist; - public string infoheader; - public string edssection = "Supported Objects"; - public string countmsg = "SupportedObjects"; - - public SupportedObjects() - { - objectlist = new Dictionary(); - } - - public virtual void Parse(Dictionary section) - { - objectlist = new Dictionary(); - foreach(KeyValuePair kvp in section) - { - if(kvp.Key.ToLower()=="supportedobjects") - continue; - - if (kvp.Key.ToLower() == "nrofentries") - continue; - - int count = Convert.ToInt16(kvp.Key, EDSsharp.Getbase(kvp.Key)); - int target = Convert.ToInt16(kvp.Value, EDSsharp.Getbase(kvp.Value)); - objectlist.Add(count, target); - } - } - - public override string ToString() - { - string msg; - - msg = $"*****************************************************{Environment.NewLine}"; - msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; - msg += $"*****************************************************{Environment.NewLine}"; - msg += $"}}{Environment.NewLine}{countmsg} = {objectlist.Count}{Environment.NewLine}"; - foreach(KeyValuePair kvp in objectlist) - { - msg += $"{kvp.Key,-5}: {kvp.Value:x4}{Environment.NewLine}"; - } - - return msg; - - } - - public void Write(StreamWriter writer) - { - writer.WriteLine("[" + edssection + "]"); - writer.WriteLine(string.Format("{0}={1}", countmsg,objectlist.Count)); - foreach (KeyValuePair kvp in objectlist) - { - writer.WriteLine(string.Format("{0}=0x{1:X4}", kvp.Key, kvp.Value)); - } - - writer.WriteLine(""); - } - - } - - public class Comments - { - - public List comments = new List(); - public string infoheader = "Comments"; - public string edssection = "Comments"; - - public Comments() - { - - } - - public Comments(Dictionary section) - { - Parse(section); - } - - public virtual void Parse(Dictionary section) - { - comments = new List(); - foreach (KeyValuePair kvp in section) - { - if (kvp.Key == "Lines") - continue; - - comments.Add(kvp.Value); - - } - } - - public override string ToString() - { - string msg; - - msg = $"*****************************************************{Environment.NewLine}"; - msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; - msg += $"*****************************************************{Environment.NewLine}"; - msg += $"{Environment.NewLine}Lines = {comments.Count}{Environment.NewLine}"; - foreach (string s in comments) - { - msg += $"{s}{Environment.NewLine}"; - } - - return msg; - - } - - public void Write(StreamWriter writer) - { - if(comments == null) - { - comments = new List(); - } - - writer.WriteLine("[" + edssection + "]"); - - writer.WriteLine(string.Format("Lines={0}", comments.Count)); - - int count = 1; - foreach (string s in comments) - { - writer.WriteLine(string.Format("Line{0}={1}", count, s)); - count++; - } - - writer.WriteLine(""); - } - } - - - public class Dummyusage : InfoSection - { - [EdsExport] - public bool Dummy0001; - [EdsExport] - public bool Dummy0002; - [EdsExport] - public bool Dummy0003; - [EdsExport] - public bool Dummy0004; - [EdsExport] - public bool Dummy0005; - [EdsExport] - public bool Dummy0006; - [EdsExport] - public bool Dummy0007; - - - public Dummyusage() - { - infoheader = "CAN OPEN Dummy Usage"; - edssection = "DummyUsage"; - } - - public Dummyusage(Dictionary section) : this() - { - Parse(section,edssection); - } - } - - public class FileInfo : InfoSection - { - // Only for internal usage, use Path.GetFileName(eds.projectFilename) instead. - [EdsExport] - public string FileName=""; - [EdsExport] - public string FileVersion=""; - [EdsExport] - public byte FileRevision;//=1 - - [DcfExport] - public string LastEDS = ""; - - public byte EDSVersionMajor;//=4.0 - - public byte EDSVersionMinor;//=4.0 - [EdsExport] - public string EDSVersion=""; - - [EdsExport(maxlength=243)] - public string Description="";//= //max 243 characters - - public DateTime CreationDateTime;// - [EdsExport] - public string CreationTime=""; - [EdsExport] - public string CreationDate=""; - - [EdsExport(maxlength = 245)] - public string CreatedBy = "";//=CANFestival //max245 - - public DateTime ModificationDateTime;// - - [EdsExport] - public string ModificationTime=""; - [EdsExport] - public string ModificationDate=""; - - [EdsExport(maxlength = 244)] - public string ModifiedBy="";//=CANFestival //max244 - - //Folder CO_OD.c and CO_OD.h will be exported into - public string exportFolder = ""; - - - public FileInfo(Dictionary section) : this() - { - Parse(section,edssection); - } - - public FileInfo() - { - infoheader = "CAN OPEN FileInfo"; - edssection = "FileInfo"; - } - - - override public void Parse(Dictionary section, string sectionname) - { - - base.Parse(section,edssection); - - string dtcombined = ""; - try - { - if (section.ContainsKey("CreationTime") && section.ContainsKey("CreationDate")) - { - dtcombined = section["CreationTime"].Replace(" ","") + " " + section["CreationDate"]; - CreationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - } - } - catch(Exception e) - { - if (e is System.FormatException) - { - Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for CreationTime, not in DS306 format", dtcombined,sectionname)); - } - } - - try - { - if (section.ContainsKey("ModificationTime") && section.ContainsKey("ModificationTime")) - { - dtcombined = section["ModificationTime"].Replace(" ", "") + " " + section["ModificationDate"]; - ModificationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - } - } - catch (Exception e) - { - if (e is System.FormatException) - { - Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for ModificationTime, not in DS306 format", dtcombined, sectionname)); - } - } - - - try - { - if (section.ContainsKey("EDSVersion")) - { - string[] bits = section["EDSVersion"].Split('.'); - if (bits.Length >= 1) - EDSVersionMajor = Convert.ToByte(bits[0]); - if (bits.Length >= 2) - EDSVersionMinor = Convert.ToByte(bits[1]); - //EDSVersion = String.Format("{0}.{1}", EDSVersionMajor, EDSVersionMinor); - } - } - catch - { - Warnings.warning_list.Add(String.Format("Unable to parse EDS version {0}", section["EDSVersion"])); - } - - } - } - - public class DeviceInfo : InfoSection - { - - [EdsExport] - public string VendorName=""; - [EdsExport] - public string VendorNumber=""; - - [EdsExport] - public string ProductName=""; - [EdsExport] - public string ProductNumber=""; - [EdsExport] - public UInt32 RevisionNumber; - - [EdsExport] - public bool BaudRate_10 = true; - [EdsExport] - public bool BaudRate_20 = true; - [EdsExport] - public bool BaudRate_50 = true; - [EdsExport] - public bool BaudRate_125 = true; - [EdsExport] - public bool BaudRate_250 = true; - [EdsExport] - public bool BaudRate_500 = true; - [EdsExport] - public bool BaudRate_800 = true; - [EdsExport] - public bool BaudRate_1000 = true; - - public bool BaudRate_auto = false; - - [EdsExport] - public bool SimpleBootUpMaster; - [EdsExport] - public bool SimpleBootUpSlave; - - [EdsExport] - public byte Granularity = 8; - [EdsExport] - public bool DynamicChannelsSupported; - - [EdsExport] - public byte CompactPDO; - - [EdsExport] - public bool GroupMessaging; - - [EdsExport] - public UInt16 NrOfRXPDO; - - [EdsExport] - public UInt16 NrOfTXPDO; - - [EdsExport] - public bool LSS_Supported; - - public bool LSS_Master; - - public DeviceInfo() - { - infoheader = "CAN OPEN DeviceInfo"; - edssection = "DeviceInfo"; - } - - public DeviceInfo(Dictionary section) : this() - { - Parse(section,edssection); - } - } - - - public class DeviceCommissioning : InfoSection - { - - public DeviceCommissioning() - { - infoheader = "CAN OPEN DeviceCommissioning"; - edssection = "DeviceCommissioning"; - } - - public DeviceCommissioning(Dictionary section) : this() - { - Parse(section,edssection); - } - - [DcfExport] - public byte NodeId = 0; - - [DcfExport(maxlength = 246)] - public string NodeName = ""; //Max 246 characters - - [DcfExport] - public UInt16 BaudRate; - - [DcfExport] - public UInt32 NetNumber; - - [DcfExport(maxlength = 243)] - public string NetworkName = ""; //Max 243 characters - - [DcfExport] - public bool CANopenManager; //1 = CANopen manager, 0 or missing = not the manager - - [DcfExport] - public UInt32 LSS_SerialNumber; - - } - - public class SupportedModules : InfoSection - { - [EdsExport] - public UInt16 NrOfEntries; - - public SupportedModules() - { - infoheader = "CAN OPEN Supported Modules"; - edssection = "SupportedModules"; - } - - public SupportedModules(Dictionary section) : this() - { - Parse(section,edssection); - } - - - } - - public class ConnectedModules : SupportedObjects - { - [EdsExport] - public UInt16 NrOfEntries - { - get { return (UInt16)connectedmodulelist.Count; } - } - - public Dictionary connectedmodulelist; - - public ConnectedModules() - { - infoheader = "CAN OPEN Connected Modules"; - edssection = "ConnectedModules"; - countmsg = "NrOfEntries"; - connectedmodulelist = new Dictionary(); - } - - public ConnectedModules(Dictionary section) : this() - { - Parse(section); - - - foreach(KeyValuePair kvp in this.objectlist) - { - - - UInt16 K = (UInt16)kvp.Value; - UInt16 V = (UInt16)kvp.Key; - - connectedmodulelist.Add(K, V); - - - } - - } - - } - - public class MxFixedObjects : SupportedObjects - { - [EdsExport] - public UInt16 NrOfEntries - { - get { return (UInt16)connectedmodulelist.Count; } - } - - public Dictionary connectedmodulelist; - - private int _moduleindex; - - public int Moduleindex - { - get { return _moduleindex; } - set { _moduleindex = value; edssection = String.Format("M{0}FixedObjects",value); } - } - - public MxFixedObjects(UInt16 modindex) - { - infoheader = "CAN OPEN Module Fixed Objects"; - this.Moduleindex = modindex; - countmsg = "NrOfEntries"; - connectedmodulelist = new Dictionary(); - } - - public MxFixedObjects(Dictionary section, UInt16 modindex) : this(modindex) - { - Parse(section); - - foreach (KeyValuePair kvp in this.objectlist) - { - connectedmodulelist.Add((UInt16)kvp.Value, (UInt16)kvp.Key); - } - } - - } - - - - public class ModuleInfo : InfoSection - { - [EdsExport(maxlength = 248)] - public string ProductName; - - [EdsExport] - public byte ProductVersion; - - [EdsExport] - public byte ProductRevision; - - [EdsExport] - public string OrderCode; - - UInt16 moduleindex = 0; - - public ModuleInfo(UInt16 moduleindex) - { - this.moduleindex = moduleindex; - infoheader = "CAN OPEN Module Info " + moduleindex.ToString(); - edssection = string.Format("M{0}{1}", moduleindex, "ModuleInfo"); - } - - public ModuleInfo(Dictionary section, UInt16 moduleindex) : this (moduleindex) - { - Parse(section,edssection); - } - } - - - public class ModuleComments : Comments - { - - UInt16 moduleindex; - - public ModuleComments(UInt16 moduleindex) - { - this.moduleindex = moduleindex; - infoheader = "CAN OPEN Module Comments " + moduleindex.ToString(); - edssection = string.Format("M{0}{1}", moduleindex, "Comments"); - } - - public ModuleComments(Dictionary section,UInt16 moduleindex) : this (moduleindex) - { - Parse(section); - } - - - } - - public class ModuleSubExtends : SupportedObjects - { - - UInt16 moduleindex; - - public ModuleSubExtends(UInt16 moduleindex) - : base() - { - this.moduleindex = moduleindex; - infoheader = "CAN OPEN ModuleSubExtends "+moduleindex.ToString(); - edssection = string.Format("M{0}{1}", moduleindex, "SubExtends"); - } - - public ModuleSubExtends(Dictionary section, UInt16 moduleindex) - : this(moduleindex) - { - Parse(section); - } - - } - - public class ODentry - { - private UInt16 _index; - - /// - /// The index of the object in the Object Dictionary - /// This cannot be set for child objects, if you read a child object you get the parents index - /// - [EdsExport] - public UInt16 Index - { - get - { - if (parent != null) - return parent.Index; - else - return _index; - } - set - { - if(value==0) - { - - //throw (new Exception("Object index must be set")); - } - - if(parent == null) - { - _index = value; - } - else - { - - //throw (new Exception("Typing to set index of a subobject")); - } - - } - } - - [EdsExport] - public string parameter_name = ""; - - [DcfExport] - public string denotation = ""; - - [EdsExport] - public ObjectType objecttype = ObjectType.UNKNOWN; - [EdsExport] - public DataType datatype = DataType.UNKNOWN; - [EdsExport] - public EDSsharp.AccessType accesstype = EDSsharp.AccessType.UNKNOWN; - - [EdsExport] - public string defaultvalue = ""; - - [EdsExport] - public string LowLimit = ""; - - [EdsExport] - public string HighLimit = ""; - - [DcfExport] - public string actualvalue = ""; - - [EdsExport] - public Byte ObjFlags = 0; - - [EdsExport] - public byte CompactSubObj = 0; - - [EdsExport] - public bool PDOMapping - { - get - { - return PDOtype != PDOMappingType.no; - } - } - - //FIXME Count "If several modules are gathered to form a new Sub-Index, - //then the number is 0, followed by semicolon and the - //number of bits that are created per module to build a new - //Sub-Index" - - [EdsExport] - public byte count = 0; - - [EdsExport] - public byte ObjExtend = 0; - - public PDOMappingType PDOtype = PDOMappingType.no; - - public string Label = ""; - public string Description = ""; - public SortedDictionary subobjects = new SortedDictionary(); - public ODentry parent = null; - - public CustomProperties prop = new CustomProperties(); - - //XDD Extensions// - public string uniqueID; - - /// - /// Used when writing out objects to know if we are writing the normal or the module parts out - /// Two module parts subext and fixed are available. - /// - public enum Odtype - { - NORMAL, - SUBEXT, - FIXED, - } - - /// - /// Empty object constructor - /// - public ODentry() - { - - } - - /// - /// ODentry constructor for a simple VAR type - /// - /// Name of Object Dictionary Entry - /// Index of object in object dictionary - /// Type of this objects data - /// Default value (always set as a string) - /// Allowed CANopen access permissions - /// Allowed PDO mapping options - public ODentry(string parameter_name,UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping) - { - this.parameter_name = parameter_name; - this.Index = index; - this.objecttype = ObjectType.VAR; - this.datatype = datatype; - this.defaultvalue = defaultvalue; - - - if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) - this.accesstype = accesstype; - else - throw new ParameterException("AccessType invalid"); - - this.PDOtype = PDOMapping; - - } - - /// - /// ODConstructor useful for subobjects - /// - /// - /// NOT USED - /// - /// - /// - /// - /// - public ODentry(string parameter_name, UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping, ODentry parent) - { - this.parent = parent; - this.parameter_name = parameter_name; - this.objecttype = ObjectType.VAR; - this.datatype = datatype; - this.defaultvalue = defaultvalue; - this.Index = index; - - if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) - this.accesstype = accesstype; - else - throw new ParameterException("AccessType invalid"); - - this.PDOtype = PDOMapping; - } - - - /// - /// ODEntry constructor for array subobjects - /// - /// - /// - /// - public ODentry(string parameter_name,UInt16 index, byte nosubindex) - { - this.parameter_name = parameter_name; - this.objecttype = ObjectType.ARRAY; - this.Index = index; - //this.nosubindexes = nosubindex; - this.objecttype = ObjectType.VAR; - } - - /// - /// Make a deep clone of this ODentry - /// - /// - public ODentry Clone(ODentry newParent = null) - { - ODentry newOd = new ODentry - { - parent = newParent, - parameter_name = parameter_name, - denotation = denotation, - objecttype = objecttype, - datatype = datatype, - accesstype = accesstype, - PDOtype = PDOtype, - defaultvalue = defaultvalue, - LowLimit = LowLimit, - HighLimit = HighLimit, - actualvalue = actualvalue, - Label = Label, - Description = Description, - subobjects = new SortedDictionary(), - prop = prop.Clone() - }; - - foreach (KeyValuePair kvp in subobjects) - newOd.subobjects.Add(kvp.Key, kvp.Value.Clone(newOd)); - - return newOd; - } - - /// - /// Provide a simple string representation of the object, only parameters index, no subindexes/subindex parameter name and data type are included - /// Useful for debug and also appears in debugger when you inspect this object - /// - /// string summary of object - public override string ToString() - { - if (subobjects.Count > 0) - { - return String.Format("{0:x4}[{1}] : {2} : {3}", Index, subobjects.Count, parameter_name, datatype); - - } - else - { - return String.Format("{0:x4}/{1} : {2} : {3}", Index, Subindex, parameter_name, datatype); - } - } - - public string ObjectTypeString() - { - switch (objecttype) - { - default: - case ObjectType.VAR: return "VAR"; - case ObjectType.ARRAY: return "ARRAY"; - case ObjectType.REC: return "RECORD"; - } - } - - public void ObjectTypeString(string objectType) - { - switch (objectType) - { - default: - case "VAR": this.objecttype = ObjectType.VAR; break; - case "ARRAY": this.objecttype = ObjectType.ARRAY; break; - case "REC": - case "RECORD": this.objecttype = ObjectType.REC; break; - } - } - - public AccessSDO AccessSDO() - { - EDSsharp.AccessType accType = accesstype; - if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) - accType = parent.accesstype; - - switch (accType) - { - default: - return libEDSsharp.AccessSDO.no; - case EDSsharp.AccessType.ro: - case EDSsharp.AccessType.@const: - return libEDSsharp.AccessSDO.ro; - case EDSsharp.AccessType.wo: - return libEDSsharp.AccessSDO.wo; - case EDSsharp.AccessType.rw: - case EDSsharp.AccessType.rwr: - case EDSsharp.AccessType.rww: - return libEDSsharp.AccessSDO.rw; - } - } - - public void AccessSDO(AccessSDO accessSDO, AccessPDO accessPDO) - { - switch (accessSDO) - { - default: - accesstype = EDSsharp.AccessType.UNKNOWN; - break; - case libEDSsharp.AccessSDO.ro: - accesstype = EDSsharp.AccessType.ro; - break; - case libEDSsharp.AccessSDO.wo: - accesstype = EDSsharp.AccessType.wo; - break; - case libEDSsharp.AccessSDO.rw: - if (accessPDO == libEDSsharp.AccessPDO.r) - accesstype = EDSsharp.AccessType.rwr; - else if (accessPDO == libEDSsharp.AccessPDO.t) - accesstype = EDSsharp.AccessType.rww; - else - accesstype = EDSsharp.AccessType.rw; - break; - } - } - - public AccessPDO AccessPDO() - { - EDSsharp.AccessType accType = accesstype; - if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) - accType = parent.accesstype; - - if (PDOtype == PDOMappingType.RPDO || accType == EDSsharp.AccessType.rwr) - return libEDSsharp.AccessPDO.r; - else if (PDOtype == PDOMappingType.TPDO || accType == EDSsharp.AccessType.rww) - return libEDSsharp.AccessPDO.t; - if (PDOtype == PDOMappingType.optional || PDOtype == PDOMappingType.@default) - return libEDSsharp.AccessPDO.tr; - else - return libEDSsharp.AccessPDO.no; - } - - public void AccessPDO(AccessPDO accessPDO) - { - switch (accessPDO) - { - default: - PDOtype = PDOMappingType.no; - break; - case libEDSsharp.AccessPDO.r: - PDOtype = PDOMappingType.RPDO; - break; - case libEDSsharp.AccessPDO.t: - PDOtype = PDOMappingType.TPDO; - break; - case libEDSsharp.AccessPDO.tr: - PDOtype = PDOMappingType.optional; - break; - } - } - - /// - /// Duplicate current sub entry and add it to parent - /// - /// true on successfull addition - public ODentry AddSubEntry() - { - ODentry baseObject = parent == null ? this : parent; - - if (baseObject.objecttype == ObjectType.VAR) - return null; - - ODentry lastSubOd = baseObject.subobjects.Values.Last(); - ODentry originalOd = null; - ODentry newOd; - UInt16 maxSubIndex = 1; - UInt16 lastSubIndex = 1; - - // create new or clone existing sub od - if (lastSubOd == null || lastSubOd.Subindex < 1) - { - newOd = new ODentry - { - parent = baseObject, - parameter_name = "item", - objecttype = ObjectType.VAR, - datatype = DataType.UNSIGNED32 - }; - } - else - { - originalOd = (parent != null && this.Subindex > 0) ? this : lastSubOd; - newOd = originalOd.Clone(originalOd.parent); - maxSubIndex = EDSsharp.ConvertToUInt16(baseObject.subobjects[0].defaultvalue); - lastSubIndex = lastSubOd.Subindex; - } - - // insert new sub od - SortedDictionary newSubObjects = new SortedDictionary(); - UInt16 newSubIndex = 0; - foreach (ODentry subOd in baseObject.subobjects.Values) - { - if (subOd.Subindex > newSubIndex) - newSubIndex = subOd.Subindex; - - newSubObjects.Add(newSubIndex++, subOd); - - if (originalOd == subOd) - newSubObjects.Add(newSubIndex++, newOd); - } - if (originalOd == null) - newSubObjects.Add(newSubIndex++, newOd); - - baseObject.subobjects = newSubObjects; - - // Write maxSubIndex to first sub index - if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && baseObject.subobjects.Count > 0) - { - baseObject.subobjects[0].defaultvalue = string.Format("0x{0:X2}", newSubIndex - 1); - } - - return newOd; - } - - /// - /// Remove current sub entry - /// - /// Renumber subentries - /// true on successfull removal - public bool RemoveSubEntry(bool renumber) - { - if (parent != null && (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.REC)) - { - UInt16 maxSubIndex = EDSsharp.ConvertToUInt16(parent.subobjects[0].defaultvalue); - UInt16 lastSubIndex = parent.subobjects.Values.Last().Subindex; - - parent.subobjects.Remove(Subindex); - - if (renumber) - { - SortedDictionary newSubObjects = new SortedDictionary(); - UInt16 subIndex = 0; - foreach (ODentry subOd in parent.subobjects.Values) - newSubObjects.Add(subIndex++, subOd); - parent.subobjects = newSubObjects; - } - - // Write maxSubIndex to first sub index - if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && parent.subobjects.Count > 0) - { - parent.subobjects[0].defaultvalue = string.Format("0x{0:X2}", parent.subobjects.Values.Last().Subindex); - } - - return true; - } - return false; - } - - /// - /// If data type is an octet string we must remove all spaces when writing out to a EDS/DCF file - /// - /// Value to be processed - /// value if not octet string or value with spaces removed if octet string - public string Formatoctetstring(string value) - { - DataType dt = datatype; - if (dt == DataType.UNKNOWN && this.parent != null) - dt = parent.datatype; - - string ret = value; - - if (dt == DataType.OCTET_STRING) - { - ret = value.Replace(" ", ""); - } - - return ret; - } - - /// - /// Write out this Object dictionary entry to an EDS/DCF file using correct formatting - /// - /// Handle to the stream writer to write to - /// File type being written - /// - public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odtype.NORMAL, int module=0) - { - - string fixedmodheader = ""; - - if (odt == Odtype.FIXED) - { - fixedmodheader = string.Format("M{0}Fixed", module); - } - - if(odt == Odtype.SUBEXT) - { - fixedmodheader = string.Format("M{0}SubExt", module); - } - - if (parent != null) - { - writer.WriteLine(string.Format("[{0}{1:X}sub{2:X}]", fixedmodheader,Index, Subindex)); - } - else - { - writer.WriteLine(string.Format("[{0}{1:X}]",fixedmodheader,Index)); - } - - writer.WriteLine(string.Format("ParameterName={0}", parameter_name)); - - if(ft == InfoSection.Filetype.File_DCF) - { - writer.WriteLine(string.Format("Denotation={0}", denotation)); - } - - writer.WriteLine(string.Format("ObjectType=0x{0:X}", (int)objecttype)); - writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); - - if (objecttype == ObjectType.ARRAY) - { - writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); - } - - if (objecttype == ObjectType.REC) - { - writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); - } - - if (objecttype == ObjectType.VAR) - { - DataType dt = datatype; - if (dt == DataType.UNKNOWN && this.parent != null) - dt = parent.datatype; - writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); - writer.WriteLine(string.Format("AccessType={0}", accesstype.ToString())); - - - if(HighLimit != null && HighLimit != "") - { - writer.WriteLine(string.Format("HighLimit={0}", Formatoctetstring(HighLimit))); - } - - if (LowLimit != null && LowLimit != "") - { - writer.WriteLine(string.Format("LowLimit={0}", Formatoctetstring(LowLimit))); - } - - writer.WriteLine(string.Format("DefaultValue={0}", Formatoctetstring(defaultvalue))); - - //TODO If the ObjectType is domain (0x2) the value of the object may be stored in a file,UploadFile and DownloadFile - if (ft == InfoSection.Filetype.File_DCF) - { - writer.WriteLine(string.Format("ParameterValue={0}", Formatoctetstring(actualvalue))); - } - - writer.WriteLine(string.Format("PDOMapping={0}", PDOMapping==true?1:0)); - - if (prop.CO_flagsPDO == true) - { - writer.WriteLine(";TPDODetectCos=1"); - } - - - } - - //Count is for modules in the [MxSubExtxxxx] - //Should we export this on EDS only, or DCF or both? - if (odt == Odtype.SUBEXT ) - { - writer.WriteLine(string.Format("Count={0}", count)); - writer.WriteLine(string.Format("ObjExtend={0}", ObjExtend)); - } - - //ObjectFlags is always optional (Page 15, DSP306) and used for DCF writing to nodes - //also recommended not to write if it is already 0 - if (ObjFlags != 0) - { - writer.WriteLine(string.Format("ObjFlags={0}", ObjFlags)); - } - - writer.WriteLine(""); - } - - /// - /// Returns a c compatible string that represents the name of the object, - is replaced with _ - /// words separated by a space are replaced with _ for a separator eg ONE TWO becomes ONE_TWO - /// - /// - public string Paramater_cname() - { - string cname = parameter_name.Replace("-", "_"); - - cname = Regex.Replace(cname, @"([A-Z]) ([A-Z])", "$1_$2"); - cname = cname.Replace(" ", ""); - - return cname; - } - - /// - /// Return the size in bytes for the given CANopen datatype of this object, eg the size of what ever the datatype field is set to - /// - /// no of bytes - public int Sizeofdatatype() - { - DataType dt = datatype; - - if (dt == DataType.UNKNOWN && this.parent != null) - dt = parent.datatype; - - switch (dt) - { - case DataType.BOOLEAN: - return 1; - - case DataType.UNSIGNED8: - case DataType.INTEGER8: - return 8; - - case DataType.VISIBLE_STRING: - case DataType.OCTET_STRING: - return Lengthofstring*8; - - case DataType.INTEGER16: - case DataType.UNSIGNED16: - case DataType.UNICODE_STRING: - return 16; //FIXME is this corret for UNICODE_STRING seems dodgy? - - case DataType.UNSIGNED24: - case DataType.INTEGER24: - return 24; - - case DataType.INTEGER32: - case DataType.UNSIGNED32: - case DataType.REAL32: - return 32; - - case DataType.INTEGER40: - case DataType.UNSIGNED40: - return 40; - - case DataType.INTEGER48: - case DataType.UNSIGNED48: - case DataType.TIME_DIFFERENCE: - case DataType.TIME_OF_DAY: - return 48; - - case DataType.INTEGER56: - case DataType.UNSIGNED56: - return 56; - - case DataType.INTEGER64: - case DataType.UNSIGNED64: - case DataType.REAL64: - return 64; - - case DataType.DOMAIN: - return 0; - - default: //FIXME - return 0; - - } - } - - - /// - /// This is the no of subindexes present in the object, it is NOT the maximum subobject index - /// - [EdsExport] - public int Nosubindexes - { - get - { - return subobjects.Count; - } - } - - //warning eds files with gaps in subobject lists have been seen in the wild - //this function tries to get the array index based on sub number not array number - //it may return null - //This needs expanding to be used globally through the application ;-( - public ODentry Getsubobject(UInt16 no) - { - if (subobjects.ContainsKey(no)) - return subobjects[no]; - return null; - } - - public string Getsubobjectdefaultvalue(UInt16 no) - { - if (subobjects.ContainsKey(no)) - return subobjects[no].defaultvalue; - else - return ""; - } - - public bool Containssubindex(UInt16 no) - { - if (subobjects.ContainsKey(no)) - return true; - - return false; - } - - public byte Getmaxsubindex() - { - //Although subindex 0 should contain the max subindex value - //we don't enforce that anywhere in this lib, we should have a setter function - //that sets it to the highest subobject found. - if (objecttype == ObjectType.ARRAY || objecttype == ObjectType.REC) - if (Containssubindex(0)) - { - return EDSsharp.ConvertToByte(Getsubobjectdefaultvalue(0)); - } - - return 0; - } - - public int Lengthofstring - { - get - { - string defaultvalue = this.defaultvalue; - if (defaultvalue == null) - return 0; - - switch (this.datatype) - { - case DataType.VISIBLE_STRING: - { - return defaultvalue.Unescape().Length; - } - - case DataType.OCTET_STRING: - { - return Regex.Replace(defaultvalue, @"\s", "").Length / 2; - } - - case DataType.UNICODE_STRING: - { - return Regex.Replace(defaultvalue, @"\s", "").Length / 4; - } - default: - { - return 0; - } - } - } - } - - public UInt16 Subindex - { - get - { - if(this.parent!=null) - { - return parent.Findsubindex(this); - } - return 0; - - } - } - - public UInt16 Findsubindex(ODentry od) - { - foreach(KeyValuePairkvp in subobjects ) - { - if (kvp.Value == od) - return kvp.Key; - } - - return 0; - - } - - /// - /// Add an existing entry as a subobject of this OD - /// - /// - /// - public void addsubobject(byte index, ODentry sub) - { - sub.parent = this; - this.subobjects.Add(index, sub); - } - - } - - public class Module - { - - public ModuleInfo mi; - public ModuleComments mc; - public ModuleSubExtends mse; - public MxFixedObjects mxfo; - public SortedDictionary modulefixedobjects; - public SortedDictionary modulesubext; - - public UInt16 moduleindex; - - public Module(UInt16 moduleindex) - { - - this.moduleindex = moduleindex; - - mi = new ModuleInfo(moduleindex); - mc = new ModuleComments(moduleindex); - mse = new ModuleSubExtends(moduleindex); - mxfo = new MxFixedObjects(moduleindex); - modulefixedobjects = new SortedDictionary(); - modulesubext = new SortedDictionary(); - } - - - - } - - public class EDSsharp - { - - public enum AccessType - { - rw = 0, - ro = 1, - wo = 2, - rwr = 3, - rww = 4, - @const = 5, - UNKNOWN - } - - public const AccessType AccessType_Min = AccessType.rw; - public const AccessType AccessType_Max = AccessType.@const; - - - // File name of the opened project. Multiple file types are possible - // for opened project file, but project is always saved as xdd_v1.1 - // Filename within the FileInfo structure has only limited usage. - public string projectFilename = ""; - // File name, when project is opened in xdd_v1.1 or project is saved - public string xddfilename_1_1 = ""; - // File names for exported files - public string xddfilenameStripped = ""; - public string edsfilename = ""; - public string dcffilename = ""; - public string ODfilename = ""; - public string ODfileVersion = ""; - public string mdfilename = ""; - public string xmlfilename = ""; // old format - public string xddfilename_1_0 = ""; // old format - - //This is memorized, when XDD v1.1 is opened. It keeps all elements - //from original XDD file, which are not handled by libedesharp, so - //they will be preserved, when the file will be saved. - //Object dictionary parameters are not stored here. - public ISO15745ProfileContainer xddTemplate = null; - - //property to indicate unsaved data; - private bool _dirty; - public bool Dirty - { - get - { - return _dirty; - } - set - { - _dirty = value; - OnDataDirty?.Invoke(_dirty, this); - } - } - - protected Dictionary> eds; - protected Dictionary sectionlinenos; - public SortedDictionary ods; - public SortedDictionary dummy_ods; - - public CO_storageGroups CO_storageGroups = new CO_storageGroups(); - - public FileInfo fi; - public DeviceInfo di; - public MandatoryObjects md; - public OptionalObjects oo; - public ManufacturerObjects mo; - public Comments c; - public Dummyusage du; - public DeviceCommissioning dc; - - public TypeDefinitions td; - - public SupportedModules sm; - public ConnectedModules cm; - - // public Dictionary mi; - // public Dictionary mc; - // public Dictionary mse; - // public Dictionary mxfo; - // public SortedDictionary> modulefixedobjects; - // public SortedDictionary> modulesubext; - - public Dictionary modules; - - public UInt16 NodeId = 0; - - public delegate void DataDirty(bool dirty, EDSsharp sender); - public event DataDirty OnDataDirty; - - public EDSsharp() - { - - - eds = new Dictionary>(); - ods = new SortedDictionary(); - dummy_ods = new SortedDictionary(); - - fi = new FileInfo(); - di = new DeviceInfo(); - du = new Dummyusage(); - md = new MandatoryObjects(); - oo = new OptionalObjects(); - mo = new ManufacturerObjects(); - dc = new DeviceCommissioning(); - c = new Comments(); - sm = new SupportedModules(); - cm = new ConnectedModules(); - td = new TypeDefinitions(); - - - //mi = new Dictionary(); - //mc = new Dictionary(); - //mse = new Dictionary(); - //mxfo = new Dictionary (); - //modulefixedobjects = new SortedDictionary>(); - //modulesubext = new SortedDictionary>(); - - modules = new Dictionary(); - - - //FIXME no way for the Major/Minor to make it to EDSVersion - fi.EDSVersionMajor = 4; - fi.EDSVersionMinor = 0; - - fi.FileVersion = "1"; - fi.FileRevision = 1; - - fi.CreationDateTime = DateTime.Now; - fi.ModificationDateTime = DateTime.Now; - - du.Dummy0001 = false; - du.Dummy0002 = true; - du.Dummy0003 = true; - du.Dummy0004 = true; - du.Dummy0005 = true; - du.Dummy0006 = true; - du.Dummy0007 = true; - - ODentry od = new ODentry(); - - dummy_ods.Add(0x002, new ODentry("Dummy Int8", 0x002, DataType.INTEGER8, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x003, new ODentry("Dummy Int16", 0x003, DataType.INTEGER16, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x004, new ODentry("Dummy Int32", 0x004, DataType.INTEGER32, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x005, new ODentry("Dummy UInt8", 0x005, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x006, new ODentry("Dummy UInt16", 0x006, DataType.UNSIGNED16, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x007, new ODentry("Dummy UInt32", 0x007, DataType.UNSIGNED32, "0", AccessType.ro, PDOMappingType.optional, null)); - - } - - protected string sectionname = ""; - - /// - /// Verify PDO mapping parameters in Object Dictionary. Every mapped OD entry must exist and mapping must be allowed - /// - /// List of error strings, empty if no errors found. - public List VerifyPDOMapping() - { - List mappingErrors = new List(); - - foreach (KeyValuePair kvp in ods) - { - int indexPdo = kvp.Key; - if (!((indexPdo >= 0x1600 && indexPdo < 0x1800) || (indexPdo >= 0x1A00 && indexPdo < 0x1C00))) - continue; - - string PDO = indexPdo < 0x1800 ? "RPDO" : "TPDO"; - - ODentry odPdo = kvp.Value; - for (byte subIdxPdo = 1; subIdxPdo < odPdo.subobjects.Count; subIdxPdo++) - { - UInt32 mapVal; - try { mapVal = (UInt32)new System.ComponentModel.UInt32Converter().ConvertFromString(odPdo.subobjects[subIdxPdo].defaultvalue); } - catch (Exception) { continue; } - - UInt16 mapIdx = (UInt16)(mapVal >> 16); - UInt16 mapSub = (UInt16)((mapVal >> 8) & 0xFF); - - if (mapIdx < 0x1000) - continue; - - bool missing = true; - AccessPDO accessPDO = AccessPDO.no; - if (ods.ContainsKey(mapIdx)) - { - ODentry od = ods[mapIdx]; - if (!od.prop.CO_disabled) - { - if (od.objecttype == ObjectType.VAR) - { - missing = false; - accessPDO = od.AccessPDO(); - } - else if (od.subobjects.ContainsKey(mapSub)) - { - missing = false; - accessPDO = od.subobjects[mapSub].AccessPDO(); - } - } - } - if (missing) - mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: missing OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); - else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.t) || (PDO == "TPDO" && accessPDO == AccessPDO.r)) - mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: not mappable OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); - } - } - - return mappingErrors; - } - - public void Parseline(string linex,int no) - { - - string key = ""; - string value = ""; - - string line = linex.TrimStart(';'); - bool custom_extension = false; - - if (linex == null || linex == "") - return; - - if (linex[0] == ';') - custom_extension = true; - - - //extract sections - { - string pat = @"^\[([a-z0-9]+)\]"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(line); - if (m.Success) - { - Group g = m.Groups[1]; - sectionname = g.ToString(); - - if (!eds.ContainsKey(sectionname)) - { - eds.Add(sectionname, new Dictionary()); - } - else - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {0} : Duplicate section [{1}] ", no,sectionname)); - } - } - } - - //extract keyvalues - { - //Bug #70 Eat whitespace! - string pat = @"^([a-z0-9_]+)[ ]*=[ ]*(.*)"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(line); - if (m.Success) - { - key = m.Groups[1].ToString(); - value = m.Groups[2].ToString(); - value = value.TrimEnd(' ','\t','\n','\r'); - - //not sure how we actually get here with out a section being in the dictionary already.. - //suspect this is dead code. - if (!eds.ContainsKey(sectionname)) - { - eds.Add(sectionname, new Dictionary()); - } - - if (custom_extension == false) - { - try - { - eds[sectionname].Add(key, value); - } - catch(Exception) - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate key \"{0}\" value \"{1}\" in section [{2}]", key,value,sectionname, no)); - } - } - else - //Only allow our own extensions to populate the key/value pair - { - if (key == "StorageLocation" || key== "TPDODetectCos") - { - try - { - eds[sectionname].Add(key, value); - } - catch(Exception) - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate custom key \"{0}\" value \"{1}\" in section [{2}]", key, value, sectionname, no)); - } - } - } - } - } - } - - public void ParseEDSentry(KeyValuePair> kvp) - { - string section = kvp.Key; - - string pat = @"^(M[0-9a-fA-F]+(Fixed|SubExt))?([a-fA-F0-9]+)(sub)?([0-9a-fA-F]*)$"; - - Regex r = new Regex(pat); - Match m = r.Match(section); - if (m.Success) - { - - SortedDictionary target = this.ods; - - //** MODULE DCF SUPPORT - - string pat2 = @"^M([0-9a-fA-F]+)(Fixed|SubExt)([0-9a-fA-F]+)"; - Regex r2 = new Regex(pat2, RegexOptions.IgnoreCase); - Match m2 = r2.Match(m.Groups[0].ToString()); - - if (m2.Success) - { - - UInt16 modindex = Convert.ToUInt16(m2.Groups[1].Value); - UInt16 odindex = Convert.ToUInt16(m2.Groups[3].Value); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - if (m2.Groups[2].ToString() == "SubExt") - { - target = modules[modindex].modulesubext; - - } - else - { - target = modules[modindex].modulefixedobjects; - } - } - - - ODentry od = new ODentry - { - //Indexes in the EDS are always in hex format without the pre 0x - Index = Convert.ToUInt16(m.Groups[3].ToString(), 16) - }; - - //Parameter name, mandatory always - if (!kvp.Value.ContainsKey("ParameterName")) - throw new ParameterException("Missing required field ParameterName on" + section); - od.parameter_name = kvp.Value["ParameterName"]; - - //Object type, assumed to be VAR unless specified - if (kvp.Value.ContainsKey("ObjectType")) - { - int type = Convert.ToInt16(kvp.Value["ObjectType"], Getbase(kvp.Value["ObjectType"])); - od.objecttype = (ObjectType)type; - } - else - { - od.objecttype = ObjectType.VAR; - } - - if(kvp.Value.ContainsKey("CompactSubObj")) - { - od.CompactSubObj = Convert.ToByte(kvp.Value["CompactSubObj"],Getbase(kvp.Value["CompactSubObj"])); - } - - if(kvp.Value.ContainsKey("ObjFlags")) - { - od.ObjFlags = Convert.ToByte(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); - } - else - { - od.ObjFlags = 0; - } - - //Access Type - if(kvp.Value.ContainsKey("StorageLocation")) - { - od.prop.CO_storageGroup = kvp.Value["StorageLocation"]; - } - - if (kvp.Value.ContainsKey("TPDODetectCos")) - { - string test = kvp.Value["TPDODetectCos"].ToLower(); - if (test == "1" || test == "true") - { - od.prop.CO_flagsPDO = true; - } - else - od.prop.CO_flagsPDO = false; - } - - if (kvp.Value.ContainsKey("Count")) - { - od.count = Convert.ToByte(kvp.Value["Count"]); - } - - if (kvp.Value.ContainsKey("ObjExtend")) - { - od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); - } - - - if (od.objecttype == ObjectType.VAR) - { - - if (kvp.Value.ContainsKey("CompactSubObj")) - throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); - - if (kvp.Value.ContainsKey("ParameterValue")) - { - od.actualvalue = kvp.Value["ParameterValue"]; - } - - if (kvp.Value.ContainsKey("HighLimit")) - { - od.HighLimit = kvp.Value["HighLimit"]; - } - - if (kvp.Value.ContainsKey("LowLimit")) - { - od.LowLimit = kvp.Value["LowLimit"]; - } - - if (kvp.Value.ContainsKey("Denotation")) - { - od.denotation = kvp.Value["Denotation"]; - } - - if (m.Groups[5].Length != 0) - { - //FIXME are subindexes in hex always? - UInt16 subindex = Convert.ToUInt16(m.Groups[5].ToString(),16); - od.parent = target[od.Index]; - target[od.Index].subobjects.Add(subindex, od); - } - - if (!kvp.Value.ContainsKey("DataType")) - throw new ParameterException("Missing required field DataType on" + section); - od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); - - if (!kvp.Value.ContainsKey("AccessType")) - throw new ParameterException("Missing required AccessType on" + section); - - string accesstype = kvp.Value["AccessType"].ToLower(); - - if (Enum.IsDefined(typeof(AccessType), accesstype)) - { - od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); - } - else - { - throw new ParameterException("Unknown AccessType on" + section); - } - - if (kvp.Value.ContainsKey("DefaultValue")) - od.defaultvalue = kvp.Value["DefaultValue"]; - - od.PDOtype = PDOMappingType.no; - if (kvp.Value.ContainsKey("PDOMapping")) - { - - bool pdo = Convert.ToInt16(kvp.Value["PDOMapping"],Getbase(kvp.Value["PDOMapping"])) == 1; - if (pdo == true) - od.PDOtype = PDOMappingType.optional; - } - - } - - - if(od.objecttype == ObjectType.REC|| od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) - { - - if (od.CompactSubObj != 0) - { - if (!kvp.Value.ContainsKey("DataType")) - throw new ParameterException("Missing required field DataType on" + section); - od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); - - if (!kvp.Value.ContainsKey("AccessType")) - throw new ParameterException("Missing required AccessType on" + section); - string accesstype = kvp.Value["AccessType"]; - if (Enum.IsDefined(typeof(AccessType), accesstype)) - { - od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); - } - else - { - throw new ParameterException("Unknown AccessType on" + section); - } - - //now we generate CompactSubObj number of var objects below this parent - - if(od.CompactSubObj>=0xfe) - { - od.CompactSubObj = 0xfe; - } - - ODentry subi = new ODentry("NrOfObjects", od.Index, DataType.UNSIGNED8, String.Format("0x{0:x2}",od.CompactSubObj), AccessType.ro, PDOMappingType.no, od); - od.subobjects.Add(0x00, subi); - - for (int x=1; x<= od.CompactSubObj; x++) - { - string parameter_name = string.Format("{0}{1:x2}", od.parameter_name, x ); - ODentry sub = new ODentry(parameter_name, od.Index, od.datatype, od.defaultvalue, od.accesstype, od.PDOtype, od); - - if (kvp.Value.ContainsKey("HighLimit")) - sub.HighLimit = kvp.Value["HighLimit"]; - - if (kvp.Value.ContainsKey("LowLimit")) - sub.HighLimit = kvp.Value["LowLimit"]; - - od.subobjects.Add((ushort)(x ), sub); - } - - } - else - { - if (!kvp.Value.ContainsKey("SubNumber")) - throw new ParameterException("Missing SubNumber on Array for" + section); - - - - } - } - - if(od.objecttype == ObjectType.DOMAIN) - { - od.datatype = DataType.DOMAIN; - od.accesstype = AccessType.rw; - - if (kvp.Value.ContainsKey("DefaultValue")) - od.defaultvalue = kvp.Value["DefaultValue"]; - - } - - //Only add top level to this list - if (m.Groups[5].Length == 0) - { - target.Add(od.Index, od); - } - } - - } - - public void Loadfile(string filename) - { - - projectFilename = filename; - - if (Path.GetExtension(filename).ToLower() == ".eds") - { - edsfilename = filename; - } - - if (Path.GetExtension(filename).ToLower() == ".dcf") - { - dcffilename = filename; - } - - //try - { - int lineno = 1; - foreach (string linex in File.ReadLines(filename)) - { - Parseline(linex,lineno); - lineno++; - } - - di = new DeviceInfo(eds["DeviceInfo"]); - - foreach (KeyValuePair> kvp in eds) - { - ParseEDSentry(kvp); - } - - fi = new FileInfo(eds["FileInfo"]); - if(eds.ContainsKey("DummyUsage")) - du = new Dummyusage(eds["DummyUsage"]); - - md = new MandatoryObjects(eds["MandatoryObjects"]); - - if(eds.ContainsKey("OptionalObjects")) - oo = new OptionalObjects(eds["OptionalObjects"]); - - if(eds.ContainsKey("ManufacturerObjects")) - mo = new ManufacturerObjects(eds["ManufacturerObjects"]); - - if (eds.ContainsKey("TypeDefinitions")) - td = new TypeDefinitions(eds["TypeDefinitions"]); - - //Only DCF not EDS files - dc = new DeviceCommissioning(); - if(eds.ContainsKey("DeviceCommissioning")) - { - dc.Parse(eds["DeviceCommissioning"],"DeviceCommissioning"); - edsfilename = fi.LastEDS; - } - - c = new Comments(); - - if (eds.ContainsKey("Comments")) - c.Parse(eds["Comments"]); - - //Modules - - //FIXME - //we don't parse or support [MxFixedObjects] with MxFixedxxxx and MxFixedxxxxsubx - - if (eds.ContainsKey("SupportedModules")) - { - sm = new SupportedModules(eds["SupportedModules"]); - - //find MxModuleInfo - - foreach (string s in eds.Keys) - { - String pat = @"^M([0-9]+)ModuleInfo"; - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleInfo mi = new ModuleInfo(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mi = mi; - - } - - - pat = @"^M([0-9]+)Comments"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleComments mc = new ModuleComments(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mc = mc; - - } - - pat = @"^M([0-9]+)SubExtends"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleSubExtends mse = new ModuleSubExtends(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mse = mse; - } - - - //DCF only - pat = @"^M([0-9]+)FixedObjects"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - MxFixedObjects mxf = new MxFixedObjects(eds[s],modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mxfo = mxf; - - } - } - } - - - if (eds.ContainsKey("ConnectedModules")) - { - cm = new ConnectedModules(eds["ConnectedModules"]); - } - - //COMPACT PDO - - if (di.CompactPDO != 0) - { - - for (UInt16 index = 0x1400; index < 0x1600; index++) - { - ApplycompactPDO(index); - } - - for (UInt16 index = 0x1800; index < 0x1A00;index ++) - { - ApplycompactPDO(index); - } - } - - ApplyimplicitPDO(); - } - // catch(Exception e) - //{ - // Console.WriteLine("** ALL GONE WRONG **" + e.ToString()); - // } - } - - public void ApplycompactPDO(UInt16 index) - { - if (ods.ContainsKey(index)) - { - if ((!ods[index].Containssubindex(1)) && ((this.di.CompactPDO & 0x01) == 0)) - { - //Fill in cob ID - //FIX ME i'm really sure this is not correct, what default values should be used??? - string cob = string.Format("0x180+$NODEID"); - ODentry subod = new ODentry("COB-ID", index, DataType.UNSIGNED32, cob, AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x05, subod); - - } - - if ((!ods[index].Containssubindex(2)) && ((this.di.CompactPDO & 0x02) == 0)) - { - //Fill in type - - ODentry subod = new ODentry("Type", index, DataType.UNSIGNED8, "0xff", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x02, subod); - } - - if ((!ods[index].Containssubindex(3)) && ((this.di.CompactPDO & 0x04) == 0)) - { - //Fill in inhibit - - ODentry subod = new ODentry("Inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x03, subod); - } - - //NOT FOR RX PDO - if (index < 0x1800) - return; - - if ((!ods[index].Containssubindex(4)) && ((this.di.CompactPDO & 0x08) == 0)) - { - //Fill in compatibility entry - - ODentry subod = new ODentry("Compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x04, subod); - } - - if ((!ods[index].Containssubindex(5)) && ((this.di.CompactPDO & 0x10) == 0)) - { - //Fill in event timer - - ODentry subod = new ODentry("Event Timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x05, subod); - } - } - } - - /// - /// This function scans the PDO list and compares it to NrOfRXPDO and NrOfTXPDO - /// if these do not match in count then implicit PDOs are present and they are - /// filled in with default values from the lowest possible index - /// - public void ApplyimplicitPDO() - { - UInt16 totalnorxpdos = di.NrOfRXPDO; - UInt16 totalnotxpdos = di.NrOfTXPDO; - - UpdatePDOcount(); - - UInt16 noexplicitrxpdos = di.NrOfRXPDO; - UInt16 noexplicittxpdos = di.NrOfTXPDO; - - //this is how many PDOS need generating on the fly - UInt16 noimplictrxpdos = (UInt16) (totalnorxpdos - noexplicitrxpdos); - UInt16 noimplicttxpdos = (UInt16) (totalnotxpdos - noexplicittxpdos); - - for(UInt16 index = 0x1400; (index < 0x1600) && (noimplictrxpdos > 0) ;index++) - { - if(!ods.ContainsKey(index)) - { - CreateRXPDO(index); - noimplictrxpdos--; - } - } - - for (UInt16 index = 0x1800; (index < 0x1A00) && (noimplicttxpdos > 0); index++) - { - if (!ods.ContainsKey(index)) - { - CreateTXPDO(index); - noimplicttxpdos--; - } - } - - UpdatePDOcount(); - - } - - public void Savefile(string filename, InfoSection.Filetype ft) - { - if(ft==InfoSection.Filetype.File_EDS) - this.edsfilename = filename; - - if (ft == InfoSection.Filetype.File_DCF) - { - this.dcffilename = filename; - fi.LastEDS = edsfilename; - } - - UpdatePDOcount(); - - //generate date times in DS306 format; h:mmtt MM-dd-yyyy - - fi.CreationDate = fi.CreationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); - fi.CreationTime = fi.CreationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); - - fi.ModificationDate = fi.ModificationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); - fi.ModificationTime = fi.ModificationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); - - fi.FileName = Path.GetFileName(filename); - - fi.EDSVersion = "4.0"; - fi.EDSVersionMajor = 4; - fi.EDSVersionMinor = 0; - +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Text.RegularExpressions; +using System.Globalization; +using System.Reflection; +using CanOpenXSD_1_1; + +namespace libEDSsharp +{ + + + public enum DataType + { + UNKNOWN = 0, + BOOLEAN = 1, + INTEGER8 = 2, + INTEGER16 = 3, + INTEGER32 = 4, + UNSIGNED8 = 5, + UNSIGNED16 = 6, + UNSIGNED32 = 7, + REAL32 = 8, + VISIBLE_STRING = 9, + OCTET_STRING = 0x0A, + UNICODE_STRING = 0x0B, + TIME_OF_DAY = 0x0C, + TIME_DIFFERENCE = 0x0D, + DOMAIN = 0x0F, + INTEGER24 = 0x10, + REAL64 = 0x11, + INTEGER40 = 0x12, + INTEGER48 = 0x13, + INTEGER56 = 0x14, + INTEGER64 = 0x15, + UNSIGNED24 = 0x16, + UNSIGNED40 = 0x18, + UNSIGNED48 = 0x19, + UNSIGNED56 = 0x1A, + UNSIGNED64 = 0x1B, + + PDO_COMMUNICATION_PARAMETER = 0x20, //PDO_CommPar + PDO_MAPPING = 0x21, //PDO_Mapping + SDO_PARAMETER = 0x22, + IDENTITY = 0x23, + + } + + public enum ObjectType + { + UNKNOWN = -1, + NULL = 0, + DOMAIN =2, + DEFTYPE=5, + DEFSTRUCT=6, + VAR = 7, + ARRAY = 8, + REC = 9, + } + + public enum PDOMappingType + { + no=0, + optional=1, + RPDO=2, + TPDO=3, + @default=4, + } + + public enum AccessSDO + { + no, + ro, + wo, + rw + } + + public enum AccessPDO + { + no, + t, + r, + tr + } + + public enum AccessSRDO + { + no = 0, + tx = 1, + rx = 2, + trx = 3 + } + + /// + /// Custom properties for OD entry or sub-entry, which are saved into xdd file v1.1 + /// + public class CustomProperties + { + public bool CO_disabled = false; // If true, object is completelly skipped by CANopenNode exporters, etc. + public string CO_countLabel = ""; + public string CO_storageGroup = "RAM"; + public bool CO_flagsPDO = false; + public AccessSRDO CO_accessSRDO = AccessSRDO.no; + public UInt32 CO_stringLengthMin = 0; + + public CustomProperties Clone() + { + return new CustomProperties + { + CO_disabled = CO_disabled, + CO_countLabel = CO_countLabel, + CO_storageGroup = CO_storageGroup, + CO_flagsPDO = CO_flagsPDO, + CO_accessSRDO = CO_accessSRDO, + CO_stringLengthMin = CO_stringLengthMin + }; + } + + public void OdeXdd(property[] properties) + { + if (properties != null) + { + foreach (property prop in properties) + { + switch (prop.name) + { + case "CO_disabled": CO_disabled = prop.value == "true"; break; + case "CO_countLabel": CO_countLabel = prop.value ?? ""; break; + case "CO_storageGroup": CO_storageGroup = prop.value ?? ""; break; + case "CO_flagsPDO": CO_flagsPDO = prop.value == "true"; break; + case "CO_accessSRDO": + try { CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), prop.value); } + catch (Exception) { CO_accessSRDO = AccessSRDO.no; } + break; + case "CO_stringLengthMin": + try { CO_stringLengthMin = Convert.ToUInt16(prop.value); } + catch (Exception) { CO_stringLengthMin = 0; } + break; + } + } + } + } + + public property[] OdeXdd() + { + var props = new List(); + + if (CO_disabled) + props.Add(new property { name = "CO_disabled", value = "true" }); + if (CO_countLabel != "") + props.Add(new property { name = "CO_countLabel", value = CO_countLabel }); + if (CO_storageGroup != "RAM") + props.Add(new property { name = "CO_storageGroup", value = CO_storageGroup }); + if (CO_flagsPDO) + props.Add(new property { name = "CO_flagsPDO", value = "true" }); + + return props.ToArray(); + } + + public property[] SubOdeXdd() + { + var props = new List(); + + if (CO_accessSRDO != AccessSRDO.no) + props.Add(new property { name = "CO_accessSRDO", value = CO_accessSRDO.ToString() }); + if (CO_stringLengthMin != 0) + props.Add(new property { name = "CO_stringLengthMin", value = CO_stringLengthMin.ToString() }); + + return props.ToArray(); + } + } + + /// + /// List of multiple CO_storageGroup strings available in project + /// + public class CO_storageGroups : List + { + public CO_storageGroups() + { + Add("RAM"); // default value + } + + public new void Add(string item) + { + if (!Contains(item)) + { + base.Add(item); + } + } + } + + public class EdsExport : Attribute + { + public UInt16 maxlength; + public bool commentonly=false; + + //mehmeh + public EdsExport() + { + } + + public EdsExport(UInt16 maxlength) + { + this.maxlength = maxlength; + } + + public bool IsReadOnly() + { + return commentonly; + } + + + } + + public class DcfExport : EdsExport + { + } + + public class InfoSection + { + protected Dictionary section; + + protected string infoheader; + protected string edssection; + + public enum Filetype + { + File_EDS, + File_DCF + } + + public virtual void Parse(Dictionary section,string sectionname) + { + + this.section = section; + + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + if(Attribute.IsDefined(f, typeof(EdsExport))) + GetField(f.Name, f.Name); + + if (Attribute.IsDefined(f, typeof(DcfExport))) + GetField(f.Name, f.Name); + } + + } + + public bool GetField(string name, string varname) + { + FieldInfo f = null; + + try + { + foreach (var element in section) + { + if (String.Equals(element.Key, name, StringComparison.OrdinalIgnoreCase)) + { + + name = element.Key; + Type tx = this.GetType(); + + f = tx.GetField(varname); + object var = null; + + switch (f.FieldType.Name) + { + case "String": + var = section[name]; + break; + + case "UInt32": + var = Convert.ToUInt32(section[name], EDSsharp.Getbase(section[name])); + break; + + case "Int16": + var = Convert.ToInt16(section[name], EDSsharp.Getbase(section[name])); + break; + + case "UInt16": + var = Convert.ToUInt16(section[name], EDSsharp.Getbase(section[name])); + break; + + case "Byte": + var = Convert.ToByte(section[name], EDSsharp.Getbase(section[name])); + break; + + case "Boolean": + var = section[name] == "1"; //because Convert is Awesome + break; + + default: + Console.WriteLine(String.Format("Unhanded variable {0} for {1}", f.FieldType.Name, varname)); + break; + } + + if (var != null) + { + tx.GetField(varname).SetValue(this, var); + return true; + } + } + } + } + catch (Exception e) + { + if (e is OverflowException) + { + Warnings.warning_list.Add(string.Format("Warning parsing {0} tried to fit {1} into {2}", name, section[name], f.FieldType.Name)); + } + } + + return false; + } + + public override string ToString() + { + string msg; + + msg = $"*****************************************************{Environment.NewLine}"; + msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; + msg += $"*****************************************************{Environment.NewLine}"; + + Type tx = this.GetType(); + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + msg += $"{f.Name,-28}: {f.GetValue(this).ToString()}{Environment.NewLine}"; + } + + return msg; + } + + public void Write(StreamWriter writer, Filetype ft) + { + writer.WriteLine("[" + edssection + "]"); + Type tx = this.GetType(); + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + + if ((ft==Filetype.File_EDS) && (!Attribute.IsDefined(f, typeof(EdsExport)))) + continue; + + if ((ft == Filetype.File_DCF) && (!(Attribute.IsDefined(f, typeof(DcfExport)) || Attribute.IsDefined(f, typeof(EdsExport))))) + continue; + + if (f.GetValue(this) == null) + continue; + + EdsExport ex = (EdsExport)f.GetCustomAttribute(typeof(EdsExport)); + + bool comment = ex.IsReadOnly(); + + if (f.FieldType.Name == "Boolean") + { + writer.WriteLine(string.Format("{2}{0}={1}", f.Name, ((bool)f.GetValue(this)) == true ? 1 : 0,comment==true?";":"")); + } + else + { + writer.WriteLine(string.Format("{2}{0}={1}", f.Name, f.GetValue(this).ToString(), comment == true ? ";" : "")); + } + } + + writer.WriteLine(""); + + } + + } + + + public class MandatoryObjects : SupportedObjects + { + public MandatoryObjects() + : base() + { + infoheader = "Mandatory Objects"; + edssection = "MandatoryObjects"; + } + + public MandatoryObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public class OptionalObjects : SupportedObjects + { + public OptionalObjects() + : base() + { + infoheader = "Optional Objects"; + edssection = "OptionalObjects"; + } + + public OptionalObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public class ManufacturerObjects : SupportedObjects + { + public ManufacturerObjects() : base() + { + infoheader = "Manufacturer Objects"; + edssection = "ManufacturerObjects"; + } + + public ManufacturerObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public class TypeDefinitions : SupportedObjects + { + public TypeDefinitions() : base() + { + infoheader = "Type Definitions"; + edssection = "TypeDefinitions"; + } + + public TypeDefinitions(Dictionary section) + { + Parse(section); + } + + } + + public class SupportedObjects + { + + public Dictionary objectlist; + public string infoheader; + public string edssection = "Supported Objects"; + public string countmsg = "SupportedObjects"; + + public SupportedObjects() + { + objectlist = new Dictionary(); + } + + public virtual void Parse(Dictionary section) + { + objectlist = new Dictionary(); + foreach(KeyValuePair kvp in section) + { + if(kvp.Key.ToLower()=="supportedobjects") + continue; + + if (kvp.Key.ToLower() == "nrofentries") + continue; + + int count = Convert.ToInt16(kvp.Key, EDSsharp.Getbase(kvp.Key)); + int target = Convert.ToInt16(kvp.Value, EDSsharp.Getbase(kvp.Value)); + objectlist.Add(count, target); + } + } + + public override string ToString() + { + string msg; + + msg = $"*****************************************************{Environment.NewLine}"; + msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; + msg += $"*****************************************************{Environment.NewLine}"; + msg += $"}}{Environment.NewLine}{countmsg} = {objectlist.Count}{Environment.NewLine}"; + foreach(KeyValuePair kvp in objectlist) + { + msg += $"{kvp.Key,-5}: {kvp.Value:x4}{Environment.NewLine}"; + } + + return msg; + + } + + public void Write(StreamWriter writer) + { + writer.WriteLine("[" + edssection + "]"); + writer.WriteLine(string.Format("{0}={1}", countmsg,objectlist.Count)); + foreach (KeyValuePair kvp in objectlist) + { + writer.WriteLine(string.Format("{0}=0x{1:X4}", kvp.Key, kvp.Value)); + } + + writer.WriteLine(""); + } + + } + + public class Comments + { + + public List comments = new List(); + public string infoheader = "Comments"; + public string edssection = "Comments"; + + public Comments() + { + + } + + public Comments(Dictionary section) + { + Parse(section); + } + + public virtual void Parse(Dictionary section) + { + comments = new List(); + foreach (KeyValuePair kvp in section) + { + if (kvp.Key == "Lines") + continue; + + comments.Add(kvp.Value); + + } + } + + public override string ToString() + { + string msg; + + msg = $"*****************************************************{Environment.NewLine}"; + msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; + msg += $"*****************************************************{Environment.NewLine}"; + msg += $"{Environment.NewLine}Lines = {comments.Count}{Environment.NewLine}"; + foreach (string s in comments) + { + msg += $"{s}{Environment.NewLine}"; + } + + return msg; + + } + + public void Write(StreamWriter writer) + { + if(comments == null) + { + comments = new List(); + } + + writer.WriteLine("[" + edssection + "]"); + + writer.WriteLine(string.Format("Lines={0}", comments.Count)); + + int count = 1; + foreach (string s in comments) + { + writer.WriteLine(string.Format("Line{0}={1}", count, s)); + count++; + } + + writer.WriteLine(""); + } + } + + + public class Dummyusage : InfoSection + { + [EdsExport] + public bool Dummy0001; + [EdsExport] + public bool Dummy0002; + [EdsExport] + public bool Dummy0003; + [EdsExport] + public bool Dummy0004; + [EdsExport] + public bool Dummy0005; + [EdsExport] + public bool Dummy0006; + [EdsExport] + public bool Dummy0007; + + + public Dummyusage() + { + infoheader = "CAN OPEN Dummy Usage"; + edssection = "DummyUsage"; + } + + public Dummyusage(Dictionary section) : this() + { + Parse(section,edssection); + } + } + + public class FileInfo : InfoSection + { + // Only for internal usage, use Path.GetFileName(eds.projectFilename) instead. + [EdsExport] + public string FileName=""; + [EdsExport] + public string FileVersion=""; + [EdsExport] + public byte FileRevision;//=1 + + [DcfExport] + public string LastEDS = ""; + + public byte EDSVersionMajor;//=4.0 + + public byte EDSVersionMinor;//=4.0 + [EdsExport] + public string EDSVersion=""; + + [EdsExport(maxlength=243)] + public string Description="";//= //max 243 characters + + public DateTime CreationDateTime;// + [EdsExport] + public string CreationTime=""; + [EdsExport] + public string CreationDate=""; + + [EdsExport(maxlength = 245)] + public string CreatedBy = "";//=CANFestival //max245 + + public DateTime ModificationDateTime;// + + [EdsExport] + public string ModificationTime=""; + [EdsExport] + public string ModificationDate=""; + + [EdsExport(maxlength = 244)] + public string ModifiedBy="";//=CANFestival //max244 + + //Folder CO_OD.c and CO_OD.h will be exported into + public string exportFolder = ""; + + + public FileInfo(Dictionary section) : this() + { + Parse(section,edssection); + } + + public FileInfo() + { + infoheader = "CAN OPEN FileInfo"; + edssection = "FileInfo"; + } + + + override public void Parse(Dictionary section, string sectionname) + { + + base.Parse(section,edssection); + + string dtcombined = ""; + try + { + if (section.ContainsKey("CreationTime") && section.ContainsKey("CreationDate")) + { + dtcombined = section["CreationTime"].Replace(" ","") + " " + section["CreationDate"]; + CreationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + } + } + catch(Exception e) + { + if (e is System.FormatException) + { + Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for CreationTime, not in DS306 format", dtcombined,sectionname)); + } + } + + try + { + if (section.ContainsKey("ModificationTime") && section.ContainsKey("ModificationTime")) + { + dtcombined = section["ModificationTime"].Replace(" ", "") + " " + section["ModificationDate"]; + ModificationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + } + } + catch (Exception e) + { + if (e is System.FormatException) + { + Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for ModificationTime, not in DS306 format", dtcombined, sectionname)); + } + } + + + try + { + if (section.ContainsKey("EDSVersion")) + { + string[] bits = section["EDSVersion"].Split('.'); + if (bits.Length >= 1) + EDSVersionMajor = Convert.ToByte(bits[0]); + if (bits.Length >= 2) + EDSVersionMinor = Convert.ToByte(bits[1]); + //EDSVersion = String.Format("{0}.{1}", EDSVersionMajor, EDSVersionMinor); + } + } + catch + { + Warnings.warning_list.Add(String.Format("Unable to parse EDS version {0}", section["EDSVersion"])); + } + + } + } + + public class DeviceInfo : InfoSection + { + + [EdsExport] + public string VendorName=""; + [EdsExport] + public string VendorNumber=""; + + [EdsExport] + public string ProductName=""; + [EdsExport] + public string ProductNumber=""; + [EdsExport] + public UInt32 RevisionNumber; + + [EdsExport] + public bool BaudRate_10 = true; + [EdsExport] + public bool BaudRate_20 = true; + [EdsExport] + public bool BaudRate_50 = true; + [EdsExport] + public bool BaudRate_125 = true; + [EdsExport] + public bool BaudRate_250 = true; + [EdsExport] + public bool BaudRate_500 = true; + [EdsExport] + public bool BaudRate_800 = true; + [EdsExport] + public bool BaudRate_1000 = true; + + public bool BaudRate_auto = false; + + [EdsExport] + public bool SimpleBootUpMaster; + [EdsExport] + public bool SimpleBootUpSlave; + + [EdsExport] + public byte Granularity = 8; + [EdsExport] + public bool DynamicChannelsSupported; + + [EdsExport] + public byte CompactPDO; + + [EdsExport] + public bool GroupMessaging; + + [EdsExport] + public UInt16 NrOfRXPDO; + + [EdsExport] + public UInt16 NrOfTXPDO; + + [EdsExport] + public bool LSS_Supported; + + public bool LSS_Master; + + public DeviceInfo() + { + infoheader = "CAN OPEN DeviceInfo"; + edssection = "DeviceInfo"; + } + + public DeviceInfo(Dictionary section) : this() + { + Parse(section,edssection); + } + } + + + public class DeviceCommissioning : InfoSection + { + + public DeviceCommissioning() + { + infoheader = "CAN OPEN DeviceCommissioning"; + edssection = "DeviceCommissioning"; + } + + public DeviceCommissioning(Dictionary section) : this() + { + Parse(section,edssection); + } + + [DcfExport] + public byte NodeId = 0; + + [DcfExport(maxlength = 246)] + public string NodeName = ""; //Max 246 characters + + [DcfExport] + public UInt16 BaudRate; + + [DcfExport] + public UInt32 NetNumber; + + [DcfExport(maxlength = 243)] + public string NetworkName = ""; //Max 243 characters + + [DcfExport] + public bool CANopenManager; //1 = CANopen manager, 0 or missing = not the manager + + [DcfExport] + public UInt32 LSS_SerialNumber; + + } + + public class SupportedModules : InfoSection + { + [EdsExport] + public UInt16 NrOfEntries; + + public SupportedModules() + { + infoheader = "CAN OPEN Supported Modules"; + edssection = "SupportedModules"; + } + + public SupportedModules(Dictionary section) : this() + { + Parse(section,edssection); + } + + + } + + public class ConnectedModules : SupportedObjects + { + [EdsExport] + public UInt16 NrOfEntries + { + get { return (UInt16)connectedmodulelist.Count; } + } + + public Dictionary connectedmodulelist; + + public ConnectedModules() + { + infoheader = "CAN OPEN Connected Modules"; + edssection = "ConnectedModules"; + countmsg = "NrOfEntries"; + connectedmodulelist = new Dictionary(); + } + + public ConnectedModules(Dictionary section) : this() + { + Parse(section); + + + foreach(KeyValuePair kvp in this.objectlist) + { + + + UInt16 K = (UInt16)kvp.Value; + UInt16 V = (UInt16)kvp.Key; + + connectedmodulelist.Add(K, V); + + + } + + } + + } + + public class MxFixedObjects : SupportedObjects + { + [EdsExport] + public UInt16 NrOfEntries + { + get { return (UInt16)connectedmodulelist.Count; } + } + + public Dictionary connectedmodulelist; + + private int _moduleindex; + + public int Moduleindex + { + get { return _moduleindex; } + set { _moduleindex = value; edssection = String.Format("M{0}FixedObjects",value); } + } + + public MxFixedObjects(UInt16 modindex) + { + infoheader = "CAN OPEN Module Fixed Objects"; + this.Moduleindex = modindex; + countmsg = "NrOfEntries"; + connectedmodulelist = new Dictionary(); + } + + public MxFixedObjects(Dictionary section, UInt16 modindex) : this(modindex) + { + Parse(section); + + foreach (KeyValuePair kvp in this.objectlist) + { + connectedmodulelist.Add((UInt16)kvp.Value, (UInt16)kvp.Key); + } + } + + } + + + + public class ModuleInfo : InfoSection + { + [EdsExport(maxlength = 248)] + public string ProductName; + + [EdsExport] + public byte ProductVersion; + + [EdsExport] + public byte ProductRevision; + + [EdsExport] + public string OrderCode; + + UInt16 moduleindex = 0; + + public ModuleInfo(UInt16 moduleindex) + { + this.moduleindex = moduleindex; + infoheader = "CAN OPEN Module Info " + moduleindex.ToString(); + edssection = string.Format("M{0}{1}", moduleindex, "ModuleInfo"); + } + + public ModuleInfo(Dictionary section, UInt16 moduleindex) : this (moduleindex) + { + Parse(section,edssection); + } + } + + + public class ModuleComments : Comments + { + + UInt16 moduleindex; + + public ModuleComments(UInt16 moduleindex) + { + this.moduleindex = moduleindex; + infoheader = "CAN OPEN Module Comments " + moduleindex.ToString(); + edssection = string.Format("M{0}{1}", moduleindex, "Comments"); + } + + public ModuleComments(Dictionary section,UInt16 moduleindex) : this (moduleindex) + { + Parse(section); + } + + + } + + public class ModuleSubExtends : SupportedObjects + { + + UInt16 moduleindex; + + public ModuleSubExtends(UInt16 moduleindex) + : base() + { + this.moduleindex = moduleindex; + infoheader = "CAN OPEN ModuleSubExtends "+moduleindex.ToString(); + edssection = string.Format("M{0}{1}", moduleindex, "SubExtends"); + } + + public ModuleSubExtends(Dictionary section, UInt16 moduleindex) + : this(moduleindex) + { + Parse(section); + } + + } + + public class ODentry + { + private UInt16 _index; + + /// + /// The index of the object in the Object Dictionary + /// This cannot be set for child objects, if you read a child object you get the parents index + /// + [EdsExport] + public UInt16 Index + { + get + { + if (parent != null) + return parent.Index; + else + return _index; + } + set + { + if(value==0) + { + + //throw (new Exception("Object index must be set")); + } + + if(parent == null) + { + _index = value; + } + else + { + + //throw (new Exception("Typing to set index of a subobject")); + } + + } + } + + [EdsExport] + public string parameter_name = ""; + + [DcfExport] + public string denotation = ""; + + [EdsExport] + public ObjectType objecttype = ObjectType.UNKNOWN; + [EdsExport] + public DataType datatype = DataType.UNKNOWN; + [EdsExport] + public EDSsharp.AccessType accesstype = EDSsharp.AccessType.UNKNOWN; + + [EdsExport] + public string defaultvalue = ""; + + [EdsExport] + public string LowLimit = ""; + + [EdsExport] + public string HighLimit = ""; + + [DcfExport] + public string actualvalue = ""; + + [EdsExport] + public Byte ObjFlags = 0; + + [EdsExport] + public byte CompactSubObj = 0; + + [EdsExport] + public bool PDOMapping + { + get + { + return PDOtype != PDOMappingType.no; + } + } + + //FIXME Count "If several modules are gathered to form a new Sub-Index, + //then the number is 0, followed by semicolon and the + //number of bits that are created per module to build a new + //Sub-Index" + + [EdsExport] + public byte count = 0; + + [EdsExport] + public byte ObjExtend = 0; + + public PDOMappingType PDOtype = PDOMappingType.no; + + public string Label = ""; + public string Description = ""; + public SortedDictionary subobjects = new SortedDictionary(); + public ODentry parent = null; + + public CustomProperties prop = new CustomProperties(); + + //XDD Extensions// + public string uniqueID; + + /// + /// Used when writing out objects to know if we are writing the normal or the module parts out + /// Two module parts subext and fixed are available. + /// + public enum Odtype + { + NORMAL, + SUBEXT, + FIXED, + } + + /// + /// Empty object constructor + /// + public ODentry() + { + + } + + /// + /// ODentry constructor for a simple VAR type + /// + /// Name of Object Dictionary Entry + /// Index of object in object dictionary + /// Type of this objects data + /// Default value (always set as a string) + /// Allowed CANopen access permissions + /// Allowed PDO mapping options + public ODentry(string parameter_name,UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping) + { + this.parameter_name = parameter_name; + this.Index = index; + this.objecttype = ObjectType.VAR; + this.datatype = datatype; + this.defaultvalue = defaultvalue; + + + if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) + this.accesstype = accesstype; + else + throw new ParameterException("AccessType invalid"); + + this.PDOtype = PDOMapping; + + } + + /// + /// ODConstructor useful for subobjects + /// + /// + /// NOT USED + /// + /// + /// + /// + /// + public ODentry(string parameter_name, UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping, ODentry parent) + { + this.parent = parent; + this.parameter_name = parameter_name; + this.objecttype = ObjectType.VAR; + this.datatype = datatype; + this.defaultvalue = defaultvalue; + this.Index = index; + + if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) + this.accesstype = accesstype; + else + throw new ParameterException("AccessType invalid"); + + this.PDOtype = PDOMapping; + } + + + /// + /// ODEntry constructor for array subobjects + /// + /// + /// + /// + public ODentry(string parameter_name,UInt16 index, byte nosubindex) + { + this.parameter_name = parameter_name; + this.objecttype = ObjectType.ARRAY; + this.Index = index; + //this.nosubindexes = nosubindex; + this.objecttype = ObjectType.VAR; + } + + /// + /// Make a deep clone of this ODentry + /// + /// + public ODentry Clone(ODentry newParent = null) + { + ODentry newOd = new ODentry + { + parent = newParent, + parameter_name = parameter_name, + denotation = denotation, + objecttype = objecttype, + datatype = datatype, + accesstype = accesstype, + PDOtype = PDOtype, + defaultvalue = defaultvalue, + LowLimit = LowLimit, + HighLimit = HighLimit, + actualvalue = actualvalue, + Label = Label, + Description = Description, + subobjects = new SortedDictionary(), + prop = prop.Clone() + }; + + foreach (KeyValuePair kvp in subobjects) + newOd.subobjects.Add(kvp.Key, kvp.Value.Clone(newOd)); + + return newOd; + } + + /// + /// Provide a simple string representation of the object, only parameters index, no subindexes/subindex parameter name and data type are included + /// Useful for debug and also appears in debugger when you inspect this object + /// + /// string summary of object + public override string ToString() + { + if (subobjects.Count > 0) + { + return String.Format("{0:x4}[{1}] : {2} : {3}", Index, subobjects.Count, parameter_name, datatype); + + } + else + { + return String.Format("{0:x4}/{1} : {2} : {3}", Index, Subindex, parameter_name, datatype); + } + } + + public string ObjectTypeString() + { + switch (objecttype) + { + default: + case ObjectType.VAR: return "VAR"; + case ObjectType.ARRAY: return "ARRAY"; + case ObjectType.REC: return "RECORD"; + } + } + + public void ObjectTypeString(string objectType) + { + switch (objectType) + { + default: + case "VAR": this.objecttype = ObjectType.VAR; break; + case "ARRAY": this.objecttype = ObjectType.ARRAY; break; + case "REC": + case "RECORD": this.objecttype = ObjectType.REC; break; + } + } + + public AccessSDO AccessSDO() + { + EDSsharp.AccessType accType = accesstype; + if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) + accType = parent.accesstype; + + switch (accType) + { + default: + return libEDSsharp.AccessSDO.no; + case EDSsharp.AccessType.ro: + case EDSsharp.AccessType.@const: + return libEDSsharp.AccessSDO.ro; + case EDSsharp.AccessType.wo: + return libEDSsharp.AccessSDO.wo; + case EDSsharp.AccessType.rw: + case EDSsharp.AccessType.rwr: + case EDSsharp.AccessType.rww: + return libEDSsharp.AccessSDO.rw; + } + } + + public void AccessSDO(AccessSDO accessSDO, AccessPDO accessPDO) + { + switch (accessSDO) + { + default: + accesstype = EDSsharp.AccessType.UNKNOWN; + break; + case libEDSsharp.AccessSDO.ro: + accesstype = EDSsharp.AccessType.ro; + break; + case libEDSsharp.AccessSDO.wo: + accesstype = EDSsharp.AccessType.wo; + break; + case libEDSsharp.AccessSDO.rw: + if (accessPDO == libEDSsharp.AccessPDO.r) + accesstype = EDSsharp.AccessType.rwr; + else if (accessPDO == libEDSsharp.AccessPDO.t) + accesstype = EDSsharp.AccessType.rww; + else + accesstype = EDSsharp.AccessType.rw; + break; + } + } + + public AccessPDO AccessPDO() + { + EDSsharp.AccessType accType = accesstype; + if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) + accType = parent.accesstype; + + if (PDOtype == PDOMappingType.RPDO || accType == EDSsharp.AccessType.rwr) + return libEDSsharp.AccessPDO.r; + else if (PDOtype == PDOMappingType.TPDO || accType == EDSsharp.AccessType.rww) + return libEDSsharp.AccessPDO.t; + if (PDOtype == PDOMappingType.optional || PDOtype == PDOMappingType.@default) + return libEDSsharp.AccessPDO.tr; + else + return libEDSsharp.AccessPDO.no; + } + + public void AccessPDO(AccessPDO accessPDO) + { + switch (accessPDO) + { + default: + PDOtype = PDOMappingType.no; + break; + case libEDSsharp.AccessPDO.r: + PDOtype = PDOMappingType.RPDO; + break; + case libEDSsharp.AccessPDO.t: + PDOtype = PDOMappingType.TPDO; + break; + case libEDSsharp.AccessPDO.tr: + PDOtype = PDOMappingType.optional; + break; + } + } + + /// + /// Duplicate current sub entry and add it to parent + /// + /// true on successfull addition + public ODentry AddSubEntry() + { + ODentry baseObject = parent == null ? this : parent; + + if (baseObject.objecttype == ObjectType.VAR) + return null; + + ODentry lastSubOd = baseObject.subobjects.Values.Last(); + ODentry originalOd = null; + ODentry newOd; + UInt16 maxSubIndex = 1; + UInt16 lastSubIndex = 1; + + // create new or clone existing sub od + if (lastSubOd == null || lastSubOd.Subindex < 1) + { + newOd = new ODentry + { + parent = baseObject, + parameter_name = "item", + objecttype = ObjectType.VAR, + datatype = DataType.UNSIGNED32 + }; + } + else + { + originalOd = (parent != null && this.Subindex > 0) ? this : lastSubOd; + newOd = originalOd.Clone(originalOd.parent); + maxSubIndex = EDSsharp.ConvertToUInt16(baseObject.subobjects[0].defaultvalue); + lastSubIndex = lastSubOd.Subindex; + } + + // insert new sub od + SortedDictionary newSubObjects = new SortedDictionary(); + UInt16 newSubIndex = 0; + foreach (ODentry subOd in baseObject.subobjects.Values) + { + if (subOd.Subindex > newSubIndex) + newSubIndex = subOd.Subindex; + + newSubObjects.Add(newSubIndex++, subOd); + + if (originalOd == subOd) + newSubObjects.Add(newSubIndex++, newOd); + } + if (originalOd == null) + newSubObjects.Add(newSubIndex++, newOd); + + baseObject.subobjects = newSubObjects; + + // Write maxSubIndex to first sub index + if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && baseObject.subobjects.Count > 0) + { + baseObject.subobjects[0].defaultvalue = string.Format("0x{0:X2}", newSubIndex - 1); + } + + return newOd; + } + + /// + /// Remove current sub entry + /// + /// Renumber subentries + /// true on successfull removal + public bool RemoveSubEntry(bool renumber) + { + if (parent != null && (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.REC)) + { + UInt16 maxSubIndex = EDSsharp.ConvertToUInt16(parent.subobjects[0].defaultvalue); + UInt16 lastSubIndex = parent.subobjects.Values.Last().Subindex; + + parent.subobjects.Remove(Subindex); + + if (renumber) + { + SortedDictionary newSubObjects = new SortedDictionary(); + UInt16 subIndex = 0; + foreach (ODentry subOd in parent.subobjects.Values) + newSubObjects.Add(subIndex++, subOd); + parent.subobjects = newSubObjects; + } + + // Write maxSubIndex to first sub index + if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && parent.subobjects.Count > 0) + { + parent.subobjects[0].defaultvalue = string.Format("0x{0:X2}", parent.subobjects.Values.Last().Subindex); + } + + return true; + } + return false; + } + + /// + /// If data type is an octet string we must remove all spaces when writing out to a EDS/DCF file + /// + /// Value to be processed + /// value if not octet string or value with spaces removed if octet string + public string Formatoctetstring(string value) + { + DataType dt = datatype; + if (dt == DataType.UNKNOWN && this.parent != null) + dt = parent.datatype; + + string ret = value; + + if (dt == DataType.OCTET_STRING) + { + ret = value.Replace(" ", ""); + } + + return ret; + } + + /// + /// Write out this Object dictionary entry to an EDS/DCF file using correct formatting + /// + /// Handle to the stream writer to write to + /// File type being written + /// + public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odtype.NORMAL, int module=0) + { + + string fixedmodheader = ""; + + if (odt == Odtype.FIXED) + { + fixedmodheader = string.Format("M{0}Fixed", module); + } + + if(odt == Odtype.SUBEXT) + { + fixedmodheader = string.Format("M{0}SubExt", module); + } + + if (parent != null) + { + writer.WriteLine(string.Format("[{0}{1:X}sub{2:X}]", fixedmodheader,Index, Subindex)); + } + else + { + writer.WriteLine(string.Format("[{0}{1:X}]",fixedmodheader,Index)); + } + + writer.WriteLine(string.Format("ParameterName={0}", parameter_name)); + + if(ft == InfoSection.Filetype.File_DCF) + { + writer.WriteLine(string.Format("Denotation={0}", denotation)); + } + + writer.WriteLine(string.Format("ObjectType=0x{0:X}", (int)objecttype)); + writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); + + if (objecttype == ObjectType.ARRAY) + { + writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); + } + + if (objecttype == ObjectType.REC) + { + writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); + } + + if (objecttype == ObjectType.VAR) + { + DataType dt = datatype; + if (dt == DataType.UNKNOWN && this.parent != null) + dt = parent.datatype; + writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); + writer.WriteLine(string.Format("AccessType={0}", accesstype.ToString())); + + + if(HighLimit != null && HighLimit != "") + { + writer.WriteLine(string.Format("HighLimit={0}", Formatoctetstring(HighLimit))); + } + + if (LowLimit != null && LowLimit != "") + { + writer.WriteLine(string.Format("LowLimit={0}", Formatoctetstring(LowLimit))); + } + + writer.WriteLine(string.Format("DefaultValue={0}", Formatoctetstring(defaultvalue))); + + //TODO If the ObjectType is domain (0x2) the value of the object may be stored in a file,UploadFile and DownloadFile + if (ft == InfoSection.Filetype.File_DCF) + { + writer.WriteLine(string.Format("ParameterValue={0}", Formatoctetstring(actualvalue))); + } + + writer.WriteLine(string.Format("PDOMapping={0}", PDOMapping==true?1:0)); + + if (prop.CO_flagsPDO == true) + { + writer.WriteLine(";TPDODetectCos=1"); + } + + + } + + //Count is for modules in the [MxSubExtxxxx] + //Should we export this on EDS only, or DCF or both? + if (odt == Odtype.SUBEXT ) + { + writer.WriteLine(string.Format("Count={0}", count)); + writer.WriteLine(string.Format("ObjExtend={0}", ObjExtend)); + } + + //ObjectFlags is always optional (Page 15, DSP306) and used for DCF writing to nodes + //also recommended not to write if it is already 0 + if (ObjFlags != 0) + { + writer.WriteLine(string.Format("ObjFlags={0}", ObjFlags)); + } + + writer.WriteLine(""); + } + + /// + /// Returns a c compatible string that represents the name of the object, - is replaced with _ + /// words separated by a space are replaced with _ for a separator eg ONE TWO becomes ONE_TWO + /// + /// + public string Paramater_cname() + { + string cname = parameter_name.Replace("-", "_"); + + cname = Regex.Replace(cname, @"([A-Z]) ([A-Z])", "$1_$2"); + cname = cname.Replace(" ", ""); + + return cname; + } + + /// + /// Return the size in bytes for the given CANopen datatype of this object, eg the size of what ever the datatype field is set to + /// + /// no of bytes + public int Sizeofdatatype() + { + DataType dt = datatype; + + if (dt == DataType.UNKNOWN && this.parent != null) + dt = parent.datatype; + + switch (dt) + { + case DataType.BOOLEAN: + return 1; + + case DataType.UNSIGNED8: + case DataType.INTEGER8: + return 8; + + case DataType.VISIBLE_STRING: + case DataType.OCTET_STRING: + return Lengthofstring*8; + + case DataType.INTEGER16: + case DataType.UNSIGNED16: + case DataType.UNICODE_STRING: + return 16; //FIXME is this corret for UNICODE_STRING seems dodgy? + + case DataType.UNSIGNED24: + case DataType.INTEGER24: + return 24; + + case DataType.INTEGER32: + case DataType.UNSIGNED32: + case DataType.REAL32: + return 32; + + case DataType.INTEGER40: + case DataType.UNSIGNED40: + return 40; + + case DataType.INTEGER48: + case DataType.UNSIGNED48: + case DataType.TIME_DIFFERENCE: + case DataType.TIME_OF_DAY: + return 48; + + case DataType.INTEGER56: + case DataType.UNSIGNED56: + return 56; + + case DataType.INTEGER64: + case DataType.UNSIGNED64: + case DataType.REAL64: + return 64; + + case DataType.DOMAIN: + return 0; + + default: //FIXME + return 0; + + } + } + + + /// + /// This is the no of subindexes present in the object, it is NOT the maximum subobject index + /// + [EdsExport] + public int Nosubindexes + { + get + { + return subobjects.Count; + } + } + + //warning eds files with gaps in subobject lists have been seen in the wild + //this function tries to get the array index based on sub number not array number + //it may return null + //This needs expanding to be used globally through the application ;-( + public ODentry Getsubobject(UInt16 no) + { + if (subobjects.ContainsKey(no)) + return subobjects[no]; + return null; + } + + public string Getsubobjectdefaultvalue(UInt16 no) + { + if (subobjects.ContainsKey(no)) + return subobjects[no].defaultvalue; + else + return ""; + } + + public bool Containssubindex(UInt16 no) + { + if (subobjects.ContainsKey(no)) + return true; + + return false; + } + + public byte Getmaxsubindex() + { + //Although subindex 0 should contain the max subindex value + //we don't enforce that anywhere in this lib, we should have a setter function + //that sets it to the highest subobject found. + if (objecttype == ObjectType.ARRAY || objecttype == ObjectType.REC) + if (Containssubindex(0)) + { + return EDSsharp.ConvertToByte(Getsubobjectdefaultvalue(0)); + } + + return 0; + } + + public int Lengthofstring + { + get + { + string defaultvalue = this.defaultvalue; + if (defaultvalue == null) + return 0; + + switch (this.datatype) + { + case DataType.VISIBLE_STRING: + { + return defaultvalue.Unescape().Length; + } + + case DataType.OCTET_STRING: + { + return Regex.Replace(defaultvalue, @"\s", "").Length / 2; + } + + case DataType.UNICODE_STRING: + { + return Regex.Replace(defaultvalue, @"\s", "").Length / 4; + } + default: + { + return 0; + } + } + } + } + + public UInt16 Subindex + { + get + { + if(this.parent!=null) + { + return parent.Findsubindex(this); + } + return 0; + + } + } + + public UInt16 Findsubindex(ODentry od) + { + foreach(KeyValuePairkvp in subobjects ) + { + if (kvp.Value == od) + return kvp.Key; + } + + return 0; + + } + + /// + /// Add an existing entry as a subobject of this OD + /// + /// + /// + public void addsubobject(byte index, ODentry sub) + { + sub.parent = this; + this.subobjects.Add(index, sub); + } + + } + + public class Module + { + + public ModuleInfo mi; + public ModuleComments mc; + public ModuleSubExtends mse; + public MxFixedObjects mxfo; + public SortedDictionary modulefixedobjects; + public SortedDictionary modulesubext; + + public UInt16 moduleindex; + + public Module(UInt16 moduleindex) + { + + this.moduleindex = moduleindex; + + mi = new ModuleInfo(moduleindex); + mc = new ModuleComments(moduleindex); + mse = new ModuleSubExtends(moduleindex); + mxfo = new MxFixedObjects(moduleindex); + modulefixedobjects = new SortedDictionary(); + modulesubext = new SortedDictionary(); + } + + + + } + + public class EDSsharp + { + + public enum AccessType + { + rw = 0, + ro = 1, + wo = 2, + rwr = 3, + rww = 4, + @const = 5, + UNKNOWN + } + + public const AccessType AccessType_Min = AccessType.rw; + public const AccessType AccessType_Max = AccessType.@const; + + + // File name of the opened project. Multiple file types are possible + // for opened project file, but project is always saved as xdd_v1.1 + // Filename within the FileInfo structure has only limited usage. + public string projectFilename = ""; + // File name, when project is opened in xdd_v1.1 or project is saved + public string xddfilename_1_1 = ""; + // File names for exported files + public string xddfilenameStripped = ""; + public string edsfilename = ""; + public string dcffilename = ""; + public string ODfilename = ""; + public string ODfileVersion = ""; + public string mdfilename = ""; + public string xmlfilename = ""; // old format + public string xddfilename_1_0 = ""; // old format + + //This is memorized, when XDD v1.1 is opened. It keeps all elements + //from original XDD file, which are not handled by libedesharp, so + //they will be preserved, when the file will be saved. + //Object dictionary parameters are not stored here. + public ISO15745ProfileContainer xddTemplate = null; + + //property to indicate unsaved data; + private bool _dirty; + public bool Dirty + { + get + { + return _dirty; + } + set + { + _dirty = value; + OnDataDirty?.Invoke(_dirty, this); + } + } + + protected Dictionary> eds; + protected Dictionary sectionlinenos; + public SortedDictionary ods; + public SortedDictionary dummy_ods; + + public CO_storageGroups CO_storageGroups = new CO_storageGroups(); + + public FileInfo fi; + public DeviceInfo di; + public MandatoryObjects md; + public OptionalObjects oo; + public ManufacturerObjects mo; + public Comments c; + public Dummyusage du; + public DeviceCommissioning dc; + + public TypeDefinitions td; + + public SupportedModules sm; + public ConnectedModules cm; + + // public Dictionary mi; + // public Dictionary mc; + // public Dictionary mse; + // public Dictionary mxfo; + // public SortedDictionary> modulefixedobjects; + // public SortedDictionary> modulesubext; + + public Dictionary modules; + + public UInt16 NodeId = 0; + + public delegate void DataDirty(bool dirty, EDSsharp sender); + public event DataDirty OnDataDirty; + + public EDSsharp() + { + + + eds = new Dictionary>(); + ods = new SortedDictionary(); + dummy_ods = new SortedDictionary(); + + fi = new FileInfo(); + di = new DeviceInfo(); + du = new Dummyusage(); + md = new MandatoryObjects(); + oo = new OptionalObjects(); + mo = new ManufacturerObjects(); + dc = new DeviceCommissioning(); + c = new Comments(); + sm = new SupportedModules(); + cm = new ConnectedModules(); + td = new TypeDefinitions(); + + + //mi = new Dictionary(); + //mc = new Dictionary(); + //mse = new Dictionary(); + //mxfo = new Dictionary (); + //modulefixedobjects = new SortedDictionary>(); + //modulesubext = new SortedDictionary>(); + + modules = new Dictionary(); + + + //FIXME no way for the Major/Minor to make it to EDSVersion + fi.EDSVersionMajor = 4; + fi.EDSVersionMinor = 0; + + fi.FileVersion = "1"; + fi.FileRevision = 1; + + fi.CreationDateTime = DateTime.Now; + fi.ModificationDateTime = DateTime.Now; + + du.Dummy0001 = false; + du.Dummy0002 = true; + du.Dummy0003 = true; + du.Dummy0004 = true; + du.Dummy0005 = true; + du.Dummy0006 = true; + du.Dummy0007 = true; + + ODentry od = new ODentry(); + + dummy_ods.Add(0x002, new ODentry("Dummy Int8", 0x002, DataType.INTEGER8, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x003, new ODentry("Dummy Int16", 0x003, DataType.INTEGER16, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x004, new ODentry("Dummy Int32", 0x004, DataType.INTEGER32, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x005, new ODentry("Dummy UInt8", 0x005, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x006, new ODentry("Dummy UInt16", 0x006, DataType.UNSIGNED16, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x007, new ODentry("Dummy UInt32", 0x007, DataType.UNSIGNED32, "0", AccessType.ro, PDOMappingType.optional, null)); + + } + + protected string sectionname = ""; + + /// + /// Verify PDO mapping parameters in Object Dictionary. Every mapped OD entry must exist and mapping must be allowed + /// + /// List of error strings, empty if no errors found. + public List VerifyPDOMapping() + { + List mappingErrors = new List(); + + foreach (KeyValuePair kvp in ods) + { + int indexPdo = kvp.Key; + if (!((indexPdo >= 0x1600 && indexPdo < 0x1800) || (indexPdo >= 0x1A00 && indexPdo < 0x1C00))) + continue; + + string PDO = indexPdo < 0x1800 ? "RPDO" : "TPDO"; + + ODentry odPdo = kvp.Value; + for (byte subIdxPdo = 1; subIdxPdo < odPdo.subobjects.Count; subIdxPdo++) + { + UInt32 mapVal; + try { mapVal = (UInt32)new System.ComponentModel.UInt32Converter().ConvertFromString(odPdo.subobjects[subIdxPdo].defaultvalue); } + catch (Exception) { continue; } + + UInt16 mapIdx = (UInt16)(mapVal >> 16); + UInt16 mapSub = (UInt16)((mapVal >> 8) & 0xFF); + + if (mapIdx < 0x1000) + continue; + + bool missing = true; + AccessPDO accessPDO = AccessPDO.no; + if (ods.ContainsKey(mapIdx)) + { + ODentry od = ods[mapIdx]; + if (!od.prop.CO_disabled) + { + if (od.objecttype == ObjectType.VAR) + { + missing = false; + accessPDO = od.AccessPDO(); + } + else if (od.subobjects.ContainsKey(mapSub)) + { + missing = false; + accessPDO = od.subobjects[mapSub].AccessPDO(); + } + } + } + if (missing) + mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: missing OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); + else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.t) || (PDO == "TPDO" && accessPDO == AccessPDO.r)) + mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: not mappable OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); + } + } + + return mappingErrors; + } + + public void Parseline(string linex,int no) + { + + string key = ""; + string value = ""; + + string line = linex.TrimStart(';'); + bool custom_extension = false; + + if (linex == null || linex == "") + return; + + if (linex[0] == ';') + custom_extension = true; + + + //extract sections + { + string pat = @"^\[([a-z0-9]+)\]"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(line); + if (m.Success) + { + Group g = m.Groups[1]; + sectionname = g.ToString(); + + if (!eds.ContainsKey(sectionname)) + { + eds.Add(sectionname, new Dictionary()); + } + else + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {0} : Duplicate section [{1}] ", no,sectionname)); + } + } + } + + //extract keyvalues + { + //Bug #70 Eat whitespace! + string pat = @"^([a-z0-9_]+)[ ]*=[ ]*(.*)"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(line); + if (m.Success) + { + key = m.Groups[1].ToString(); + value = m.Groups[2].ToString(); + value = value.TrimEnd(' ','\t','\n','\r'); + + //not sure how we actually get here with out a section being in the dictionary already.. + //suspect this is dead code. + if (!eds.ContainsKey(sectionname)) + { + eds.Add(sectionname, new Dictionary()); + } + + if (custom_extension == false) + { + try + { + eds[sectionname].Add(key, value); + } + catch(Exception) + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate key \"{0}\" value \"{1}\" in section [{2}]", key,value,sectionname, no)); + } + } + else + //Only allow our own extensions to populate the key/value pair + { + if (key == "StorageLocation" || key== "TPDODetectCos") + { + try + { + eds[sectionname].Add(key, value); + } + catch(Exception) + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate custom key \"{0}\" value \"{1}\" in section [{2}]", key, value, sectionname, no)); + } + } + } + } + } + } + + public void ParseEDSentry(KeyValuePair> kvp) + { + string section = kvp.Key; + + string pat = @"^(M[0-9a-fA-F]+(Fixed|SubExt))?([a-fA-F0-9]+)(sub)?([0-9a-fA-F]*)$"; + + Regex r = new Regex(pat); + Match m = r.Match(section); + if (m.Success) + { + + SortedDictionary target = this.ods; + + //** MODULE DCF SUPPORT + + string pat2 = @"^M([0-9a-fA-F]+)(Fixed|SubExt)([0-9a-fA-F]+)"; + Regex r2 = new Regex(pat2, RegexOptions.IgnoreCase); + Match m2 = r2.Match(m.Groups[0].ToString()); + + if (m2.Success) + { + + UInt16 modindex = Convert.ToUInt16(m2.Groups[1].Value); + UInt16 odindex = Convert.ToUInt16(m2.Groups[3].Value); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + if (m2.Groups[2].ToString() == "SubExt") + { + target = modules[modindex].modulesubext; + + } + else + { + target = modules[modindex].modulefixedobjects; + } + } + + + ODentry od = new ODentry + { + //Indexes in the EDS are always in hex format without the pre 0x + Index = Convert.ToUInt16(m.Groups[3].ToString(), 16) + }; + + //Parameter name, mandatory always + if (!kvp.Value.ContainsKey("ParameterName")) + throw new ParameterException("Missing required field ParameterName on" + section); + od.parameter_name = kvp.Value["ParameterName"]; + + //Object type, assumed to be VAR unless specified + if (kvp.Value.ContainsKey("ObjectType")) + { + int type = Convert.ToInt16(kvp.Value["ObjectType"], Getbase(kvp.Value["ObjectType"])); + od.objecttype = (ObjectType)type; + } + else + { + od.objecttype = ObjectType.VAR; + } + + if(kvp.Value.ContainsKey("CompactSubObj")) + { + od.CompactSubObj = Convert.ToByte(kvp.Value["CompactSubObj"],Getbase(kvp.Value["CompactSubObj"])); + } + + if(kvp.Value.ContainsKey("ObjFlags")) + { + od.ObjFlags = Convert.ToByte(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); + } + else + { + od.ObjFlags = 0; + } + + //Access Type + if(kvp.Value.ContainsKey("StorageLocation")) + { + od.prop.CO_storageGroup = kvp.Value["StorageLocation"]; + } + + if (kvp.Value.ContainsKey("TPDODetectCos")) + { + string test = kvp.Value["TPDODetectCos"].ToLower(); + if (test == "1" || test == "true") + { + od.prop.CO_flagsPDO = true; + } + else + od.prop.CO_flagsPDO = false; + } + + if (kvp.Value.ContainsKey("Count")) + { + od.count = Convert.ToByte(kvp.Value["Count"]); + } + + if (kvp.Value.ContainsKey("ObjExtend")) + { + od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); + } + + + if (od.objecttype == ObjectType.VAR) + { + + if (kvp.Value.ContainsKey("CompactSubObj")) + throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); + + if (kvp.Value.ContainsKey("ParameterValue")) + { + od.actualvalue = kvp.Value["ParameterValue"]; + } + + if (kvp.Value.ContainsKey("HighLimit")) + { + od.HighLimit = kvp.Value["HighLimit"]; + } + + if (kvp.Value.ContainsKey("LowLimit")) + { + od.LowLimit = kvp.Value["LowLimit"]; + } + + if (kvp.Value.ContainsKey("Denotation")) + { + od.denotation = kvp.Value["Denotation"]; + } + + if (m.Groups[5].Length != 0) + { + //FIXME are subindexes in hex always? + UInt16 subindex = Convert.ToUInt16(m.Groups[5].ToString(),16); + od.parent = target[od.Index]; + target[od.Index].subobjects.Add(subindex, od); + } + + if (!kvp.Value.ContainsKey("DataType")) + throw new ParameterException("Missing required field DataType on" + section); + od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); + + if (!kvp.Value.ContainsKey("AccessType")) + throw new ParameterException("Missing required AccessType on" + section); + + string accesstype = kvp.Value["AccessType"].ToLower(); + + if (Enum.IsDefined(typeof(AccessType), accesstype)) + { + od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); + } + else + { + throw new ParameterException("Unknown AccessType on" + section); + } + + if (kvp.Value.ContainsKey("DefaultValue")) + od.defaultvalue = kvp.Value["DefaultValue"]; + + od.PDOtype = PDOMappingType.no; + if (kvp.Value.ContainsKey("PDOMapping")) + { + + bool pdo = Convert.ToInt16(kvp.Value["PDOMapping"],Getbase(kvp.Value["PDOMapping"])) == 1; + if (pdo == true) + od.PDOtype = PDOMappingType.optional; + } + + } + + + if(od.objecttype == ObjectType.REC|| od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) + { + + if (od.CompactSubObj != 0) + { + if (!kvp.Value.ContainsKey("DataType")) + throw new ParameterException("Missing required field DataType on" + section); + od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); + + if (!kvp.Value.ContainsKey("AccessType")) + throw new ParameterException("Missing required AccessType on" + section); + string accesstype = kvp.Value["AccessType"]; + if (Enum.IsDefined(typeof(AccessType), accesstype)) + { + od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); + } + else + { + throw new ParameterException("Unknown AccessType on" + section); + } + + //now we generate CompactSubObj number of var objects below this parent + + if(od.CompactSubObj>=0xfe) + { + od.CompactSubObj = 0xfe; + } + + ODentry subi = new ODentry("NrOfObjects", od.Index, DataType.UNSIGNED8, String.Format("0x{0:x2}",od.CompactSubObj), AccessType.ro, PDOMappingType.no, od); + od.subobjects.Add(0x00, subi); + + for (int x=1; x<= od.CompactSubObj; x++) + { + string parameter_name = string.Format("{0}{1:x2}", od.parameter_name, x ); + ODentry sub = new ODentry(parameter_name, od.Index, od.datatype, od.defaultvalue, od.accesstype, od.PDOtype, od); + + if (kvp.Value.ContainsKey("HighLimit")) + sub.HighLimit = kvp.Value["HighLimit"]; + + if (kvp.Value.ContainsKey("LowLimit")) + sub.HighLimit = kvp.Value["LowLimit"]; + + od.subobjects.Add((ushort)(x ), sub); + } + + } + else + { + if (!kvp.Value.ContainsKey("SubNumber")) + throw new ParameterException("Missing SubNumber on Array for" + section); + + + + } + } + + if(od.objecttype == ObjectType.DOMAIN) + { + od.datatype = DataType.DOMAIN; + od.accesstype = AccessType.rw; + + if (kvp.Value.ContainsKey("DefaultValue")) + od.defaultvalue = kvp.Value["DefaultValue"]; + + } + + //Only add top level to this list + if (m.Groups[5].Length == 0) + { + target.Add(od.Index, od); + } + } + + } + + public void Loadfile(string filename) + { + + projectFilename = filename; + + if (Path.GetExtension(filename).ToLower() == ".eds") + { + edsfilename = filename; + } + + if (Path.GetExtension(filename).ToLower() == ".dcf") + { + dcffilename = filename; + } + + //try + { + int lineno = 1; + foreach (string linex in File.ReadLines(filename)) + { + Parseline(linex,lineno); + lineno++; + } + + di = new DeviceInfo(eds["DeviceInfo"]); + + foreach (KeyValuePair> kvp in eds) + { + ParseEDSentry(kvp); + } + + fi = new FileInfo(eds["FileInfo"]); + if(eds.ContainsKey("DummyUsage")) + du = new Dummyusage(eds["DummyUsage"]); + + md = new MandatoryObjects(eds["MandatoryObjects"]); + + if(eds.ContainsKey("OptionalObjects")) + oo = new OptionalObjects(eds["OptionalObjects"]); + + if(eds.ContainsKey("ManufacturerObjects")) + mo = new ManufacturerObjects(eds["ManufacturerObjects"]); + + if (eds.ContainsKey("TypeDefinitions")) + td = new TypeDefinitions(eds["TypeDefinitions"]); + + //Only DCF not EDS files + dc = new DeviceCommissioning(); + if(eds.ContainsKey("DeviceCommissioning")) + { + dc.Parse(eds["DeviceCommissioning"],"DeviceCommissioning"); + edsfilename = fi.LastEDS; + } + + c = new Comments(); + + if (eds.ContainsKey("Comments")) + c.Parse(eds["Comments"]); + + //Modules + + //FIXME + //we don't parse or support [MxFixedObjects] with MxFixedxxxx and MxFixedxxxxsubx + + if (eds.ContainsKey("SupportedModules")) + { + sm = new SupportedModules(eds["SupportedModules"]); + + //find MxModuleInfo + + foreach (string s in eds.Keys) + { + String pat = @"^M([0-9]+)ModuleInfo"; + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleInfo mi = new ModuleInfo(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mi = mi; + + } + + + pat = @"^M([0-9]+)Comments"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleComments mc = new ModuleComments(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mc = mc; + + } + + pat = @"^M([0-9]+)SubExtends"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleSubExtends mse = new ModuleSubExtends(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mse = mse; + } + + + //DCF only + pat = @"^M([0-9]+)FixedObjects"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + MxFixedObjects mxf = new MxFixedObjects(eds[s],modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mxfo = mxf; + + } + } + } + + + if (eds.ContainsKey("ConnectedModules")) + { + cm = new ConnectedModules(eds["ConnectedModules"]); + } + + //COMPACT PDO + + if (di.CompactPDO != 0) + { + + for (UInt16 index = 0x1400; index < 0x1600; index++) + { + ApplycompactPDO(index); + } + + for (UInt16 index = 0x1800; index < 0x1A00;index ++) + { + ApplycompactPDO(index); + } + } + + ApplyimplicitPDO(); + } + // catch(Exception e) + //{ + // Console.WriteLine("** ALL GONE WRONG **" + e.ToString()); + // } + } + + public void ApplycompactPDO(UInt16 index) + { + if (ods.ContainsKey(index)) + { + if ((!ods[index].Containssubindex(1)) && ((this.di.CompactPDO & 0x01) == 0)) + { + //Fill in cob ID + //FIX ME i'm really sure this is not correct, what default values should be used??? + string cob = string.Format("0x180+$NODEID"); + ODentry subod = new ODentry("COB-ID", index, DataType.UNSIGNED32, cob, AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x05, subod); + + } + + if ((!ods[index].Containssubindex(2)) && ((this.di.CompactPDO & 0x02) == 0)) + { + //Fill in type + + ODentry subod = new ODentry("Type", index, DataType.UNSIGNED8, "0xff", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x02, subod); + } + + if ((!ods[index].Containssubindex(3)) && ((this.di.CompactPDO & 0x04) == 0)) + { + //Fill in inhibit + + ODentry subod = new ODentry("Inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x03, subod); + } + + //NOT FOR RX PDO + if (index < 0x1800) + return; + + if ((!ods[index].Containssubindex(4)) && ((this.di.CompactPDO & 0x08) == 0)) + { + //Fill in compatibility entry + + ODentry subod = new ODentry("Compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x04, subod); + } + + if ((!ods[index].Containssubindex(5)) && ((this.di.CompactPDO & 0x10) == 0)) + { + //Fill in event timer + + ODentry subod = new ODentry("Event Timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x05, subod); + } + } + } + + /// + /// This function scans the PDO list and compares it to NrOfRXPDO and NrOfTXPDO + /// if these do not match in count then implicit PDOs are present and they are + /// filled in with default values from the lowest possible index + /// + public void ApplyimplicitPDO() + { + UInt16 totalnorxpdos = di.NrOfRXPDO; + UInt16 totalnotxpdos = di.NrOfTXPDO; + + UpdatePDOcount(); + + UInt16 noexplicitrxpdos = di.NrOfRXPDO; + UInt16 noexplicittxpdos = di.NrOfTXPDO; + + //this is how many PDOS need generating on the fly + UInt16 noimplictrxpdos = (UInt16) (totalnorxpdos - noexplicitrxpdos); + UInt16 noimplicttxpdos = (UInt16) (totalnotxpdos - noexplicittxpdos); + + for(UInt16 index = 0x1400; (index < 0x1600) && (noimplictrxpdos > 0) ;index++) + { + if(!ods.ContainsKey(index)) + { + CreateRXPDO(index); + noimplictrxpdos--; + } + } + + for (UInt16 index = 0x1800; (index < 0x1A00) && (noimplicttxpdos > 0); index++) + { + if (!ods.ContainsKey(index)) + { + CreateTXPDO(index); + noimplicttxpdos--; + } + } + + UpdatePDOcount(); + + } + + public void Savefile(string filename, InfoSection.Filetype ft) + { + if(ft==InfoSection.Filetype.File_EDS) + this.edsfilename = filename; + + if (ft == InfoSection.Filetype.File_DCF) + { + this.dcffilename = filename; + fi.LastEDS = edsfilename; + } + + UpdatePDOcount(); + + //generate date times in DS306 format; h:mmtt MM-dd-yyyy + + fi.CreationDate = fi.CreationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); + fi.CreationTime = fi.CreationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); + + fi.ModificationDate = fi.ModificationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); + fi.ModificationTime = fi.ModificationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); + + fi.FileName = Path.GetFileName(filename); + + fi.EDSVersion = "4.0"; + fi.EDSVersionMajor = 4; + fi.EDSVersionMinor = 0; + StreamWriter writer = File.CreateText(filename); - writer.NewLine = "\n"; - fi.Write(writer,ft); - di.Write(writer,ft); - du.Write(writer,ft); - c.Write(writer); - - if(ft == InfoSection.Filetype.File_DCF) - { - dc.Write(writer,ft); - } - - //regenerate the object lists - md.objectlist.Clear(); - mo.objectlist.Clear(); - oo.objectlist.Clear(); - - foreach (KeyValuePair kvp in ods) - { - ODentry entry = kvp.Value; - - if (entry.prop.CO_disabled == true) - continue; - - if (entry.Index == 0x1000 || entry.Index == 0x1001 || entry.Index == 0x1018) - { - md.objectlist.Add(md.objectlist.Count + 1, entry.Index); - } - else - if (entry.Index >= 0x2000 && entry.Index < 0x6000) - { - mo.objectlist.Add(mo.objectlist.Count + 1, entry.Index); - } - else - { - oo.objectlist.Add(oo.objectlist.Count + 1, entry.Index); - } - } - - md.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (md.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - oo.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (oo.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - mo.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (mo.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - //modules - - if (sm.NrOfEntries > 0) - { - sm.Write(writer, ft); - - for (UInt16 moduleid = 1; moduleid <= sm.NrOfEntries; moduleid++) - { - - modules[moduleid].mi.Write(writer, ft); - - modules[moduleid].mc.Write(writer); - - modules[moduleid].mse.Write(writer); - - - foreach (KeyValuePair kvp2 in modules[moduleid].modulesubext) - { - ODentry od = kvp2.Value; - od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); - - } - - modules[moduleid].mxfo.Write(writer); - - foreach (KeyValuePair kvp3 in modules[moduleid].modulefixedobjects) - { - ODentry od = kvp3.Value; - od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); - - foreach (KeyValuePair kvp4 in od.subobjects) - { - ODentry subod = kvp4.Value; - subod.Write(writer, ft, ODentry.Odtype.FIXED, moduleid); - } - } - } - } - - if (ft == InfoSection.Filetype.File_DCF) - { - if (cm.NrOfEntries > 0) - { - cm.Write(writer); - } - } - - writer.Close(); - - } - - public DataType Getdatatype(ODentry od) - { - - if (od.objecttype == ObjectType.VAR) - { - return od.datatype; - } - - if (od.objecttype == ObjectType.ARRAY) - { - ODentry sub2 = ods[od.Index]; - - //FIX ME !!! INCONSISTANT setup of the datatype for arrays when loading xml and eds!! - - DataType t = sub2.datatype; - - if (sub2.Getsubobject(1) != null) - { - t = sub2.Getsubobject(1).datatype; - if (t == DataType.UNKNOWN) - t = sub2.datatype; - } - - return t; - } - - //Warning, REC types need to be handled else where as the specific - //implementation of a REC type depends on the exporter being used - - return DataType.UNKNOWN; - - } - - - static public byte ConvertToByte(string defaultvalue) - { - if (defaultvalue == null || defaultvalue == "") - return 0; - - return (Convert.ToByte(defaultvalue, Getbase(defaultvalue))); - } - - static public UInt16 ConvertToUInt16(byte [] bytes) - { - - UInt16 value = 0; - - value = (UInt16) ((bytes[0] << 8) | bytes[1]); - - return value; - - } - - static public UInt16 ConvertToUInt16(string defaultvalue) - { - if (defaultvalue == null || defaultvalue == "" ) - return 0; - - return (Convert.ToUInt16(defaultvalue, Getbase(defaultvalue))); - } - - static public UInt32 ConvertToUInt32(string defaultvalue) - { - if (defaultvalue == null || defaultvalue == "" ) - return 0; - - return (Convert.ToUInt32(defaultvalue, Getbase(defaultvalue))); - } - - static public int Getbase(string defaultvalue) - { - - if (defaultvalue == null || defaultvalue == "") - return 10; - - int nobase = 10; - - String pat = @"^0[xX][0-9a-fA-F]+"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 16; - } - - pat = @"^0[0-9]+"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 8; - } - - - return nobase; - } - - public void UpdatePDOcount() - { - di.NrOfRXPDO = 0; - di.NrOfTXPDO = 0; - foreach(KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if(od.prop.CO_disabled == false && od.Index >= 0x1400 && od.Index < 0x1600) - di.NrOfRXPDO++; - - if(od.prop.CO_disabled == false && od.Index >= 0x1800 && od.Index < 0x1A00) - di.NrOfTXPDO++; - - } - - } - - //Split on + , replace $NODEID with concrete value and add together - public UInt32 GetNodeID(string input, out bool nodeidpresent) - { - - if (input == null || input == "") - { - nodeidpresent = false; - return 0; - } - - input = input.ToUpper(); - - if(input.Contains("$NODEID")) - nodeidpresent = true; - else - nodeidpresent = false; - - try - { - if (dc.NodeId == 0) - { - input = input.Replace("$NODEID", ""); - input = input.Replace("+", ""); - input = input.Replace(" ", ""); - return Convert.ToUInt32(input, Getbase(input)); - } - - input = input.Replace("$NODEID", String.Format("0x{0}", dc.NodeId)); - - string[] bits = input.Split('+'); - - if(bits.Length==1) - { - //nothing to parse here just return the value - return Convert.ToUInt32(input, Getbase(input)); - } - - if (bits.Length != 2) - { - throw new FormatException("cannot parse " + input + "\nExpecting N+$NODEID or $NODEID+N"); - } - - UInt32 b1 = Convert.ToUInt32(bits[0], Getbase(bits[0])); - UInt32 b2 = Convert.ToUInt32(bits[1], Getbase(bits[1])); - - return (UInt32)(b1 + b2); - } - catch(Exception e) - { - Warnings.warning_list.Add(String.Format("Error parsing node id {0} nodes, {1}", input,e.ToString())); - } - - return 0; - } - - - public bool tryGetODEntry(UInt16 index, out ODentry od) - { - od = null; - if(ods.ContainsKey(index)) - { - od = ods[index]; - return true; - } - - if(dummy_ods.ContainsKey(index)) - { - od = dummy_ods[index]; - return true; - } - - return false; - } - - //RX COM 0x1400 - //RX Map 0x1600 - //TX COM 0x1800 - //TX MAP 0x1a00 - - //call this with the comm param index not the mapping - public bool CreatePDO(bool rx,UInt16 index) - { - //check if we are creating an RX PDO it is a valid index - if (rx && (index < 0x1400 || index > 0x15ff)) - return false; - - //check if we are creating an PDO TX it is a valid index - if (!rx & (index < 0x1800 || index > 0x19ff)) - return false; - - //Check it does not already exist - if (ods.ContainsKey(index)) - return false; - - //check the associated mapping index does not exist - if (ods.ContainsKey((UInt16)(index+0x200))) - return false; - - ODentry od_comparam; - ODentry od_mapping; - - if (rx) - { - od_comparam = new ODentry("RPDO communication parameter", index, 0) - { - Description = @"0x1400 - 0x15FF RPDO communication parameter -max sub-index - -COB - ID - bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set - bit 11 - 29: set to 0 for 11 bit COB - ID - bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO - bit 31: 0(1) - node uses(does NOT use) PDO - -Transmission type - value = 0 - 240: receiving is synchronous, process after next reception of SYNC object - value = 241 - 253: not used - value = 254: manufacturer specific - value = 255: asynchronous" - }; - - od_mapping = new ODentry("RPDO mapping parameter", (UInt16)(index + 0x200), 0) - { - Description = @"0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) -Number of mapped objects - -mapped object (subindex 1...8) - bit 0 - 7: data length in bits - bit 8 - 15: subindex from OD - bit 16 - 31: index from OD" - }; - - - } - else - { - od_comparam = new ODentry("TPDO communication parameter", index, 0) - { - Description = @"0x1800 - 0x19FF TPDO communication parameter -max sub-index - -COB - ID - bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set - bit 11 - 29: set to 0 for 11 bit COB - ID - bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO - bit 31: 0(1) - node uses(does NOT use) PDO - -Transmission type - value = 0: transmitting is synchronous, specification in device profile - value = 1 - 240: transmitting is synchronous after every N - th SYNC object - value = 241 - 251: not used - value = 252 - 253: Transmitted only on reception of Remote Transmission Request - value = 254: manufacturer specific - value = 255: asynchronous, specification in device profile - -inhibit time - bit 0 - 15: Minimum time between transmissions of the PDO in 100µs.Zero disables functionality. - -event timer - bit 0-15: Time between periodic transmissions of the PDO in ms.Zero disables functionality. - -SYNC start value - value = 0: Counter of the SYNC message shall not be processed. - value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message." - }; - - - od_mapping = new ODentry("TPDO mapping parameter", (UInt16)(index + 0x200), 0) - { - Description = @"0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). -Number of mapped objects - -mapped object (subindex 1...8) - bit 0 - 7: data length in bits - bit 8 - 15: subindex from OD - bit 16 - 31: index from OD" - }; - } - - od_comparam.objecttype = ObjectType.REC; - od_comparam.prop.CO_storageGroup = "ROM"; - od_comparam.accesstype = AccessType.ro; - od_comparam.PDOtype = PDOMappingType.no; - - ODentry sub; - - - if(rx) - { - sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "2", AccessType.ro, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(0, sub); - sub = new ODentry("COB-ID used by RPDO", index, DataType.UNSIGNED32, "$NODEID+0x200", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(1, sub); - sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(2, sub); - - } - else - { - sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "6", AccessType.ro, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(0, sub); - sub = new ODentry("COB-ID used by TPDO", index, DataType.UNSIGNED32, "$NODEID+0x180", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(1, sub); - sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(2, sub); - sub = new ODentry("inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(3, sub); - //sub = new ODentry("compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); - //od_comparam.subobjects.Add(4, sub); - sub = new ODentry("event timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(5, sub); - sub = new ODentry("SYNC start value", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(6, sub); - - } - - od_mapping.objecttype = ObjectType.REC; - od_mapping.prop.CO_storageGroup = "ROM"; - od_mapping.accesstype = AccessType.rw; //Same as default but inconsistent with ROM above - od_mapping.PDOtype = PDOMappingType.no; - - sub = new ODentry("Number of mapped objects", (UInt16)(index + 0x200), DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, od_mapping); - od_mapping.subobjects.Add(0, sub); - - for (int p=1;p<=8;p++) - { - sub = new ODentry(string.Format("mapped object {0}",p), (UInt16)(index+0x200), DataType.UNSIGNED32, "0x00000000", AccessType.ro, PDOMappingType.no, od_mapping); - od_mapping.subobjects.Add((byte)p, sub); - } - - ods.Add(index, od_comparam); - ods.Add((UInt16)(index + 0x200), od_mapping); - - return true; - } - - public bool CreateTXPDO(UInt16 index) - { - return CreatePDO(false, index); - } - - public bool CreateRXPDO(UInt16 index) - { - return CreatePDO(true, index); - } - - public ODentry Getobject(UInt16 no) - { - - if(no>=0x002 && no<=0x007) - { - return dummy_ods[no]; - } - - if (ods.ContainsKey(no)) - { - return ods[no]; - } - - return null; - - } - - - public ODentry Getobject(string uniqueID) - { - foreach(KeyValuePair e in ods) - { - if (e.Value.uniqueID == uniqueID) - return e.Value; - - if(e.Value.subobjects!=null && e.Value.subobjects.Count>0) - { - foreach(KeyValuePair sube in e.Value.subobjects) - { - if (sube.Value.uniqueID == uniqueID) - return sube.Value; - } - - } - - - } - - return null; - } - - public int GetNoEnabledObjects(bool includesub=false) - { - int enabledcount = 0; - foreach (ODentry od in ods.Values) - { - if (od.prop.CO_disabled == false) - { - enabledcount++; - - if(includesub) - { - foreach(ODentry sub in od.subobjects.Values) - { - if (od.prop.CO_disabled == false) - { - enabledcount++; - } - } - - } - } - } - - return enabledcount; - - } - - - - } - - public class ParameterException : Exception - { - public ParameterException(String message) - : base(message) - { - - } - } - - - - } + writer.NewLine = "\n"; + fi.Write(writer,ft); + di.Write(writer,ft); + du.Write(writer,ft); + c.Write(writer); + + if(ft == InfoSection.Filetype.File_DCF) + { + dc.Write(writer,ft); + } + + //regenerate the object lists + md.objectlist.Clear(); + mo.objectlist.Clear(); + oo.objectlist.Clear(); + + foreach (KeyValuePair kvp in ods) + { + ODentry entry = kvp.Value; + + if (entry.prop.CO_disabled == true) + continue; + + if (entry.Index == 0x1000 || entry.Index == 0x1001 || entry.Index == 0x1018) + { + md.objectlist.Add(md.objectlist.Count + 1, entry.Index); + } + else + if (entry.Index >= 0x2000 && entry.Index < 0x6000) + { + mo.objectlist.Add(mo.objectlist.Count + 1, entry.Index); + } + else + { + oo.objectlist.Add(oo.objectlist.Count + 1, entry.Index); + } + } + + md.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (md.objectlist.ContainsValue(od.Index)) + { + od.Write(writer,ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer,ft); + } + } + } + + oo.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (oo.objectlist.ContainsValue(od.Index)) + { + od.Write(writer,ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer,ft); + } + } + } + + mo.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (mo.objectlist.ContainsValue(od.Index)) + { + od.Write(writer,ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer,ft); + } + } + } + + //modules + + if (sm.NrOfEntries > 0) + { + sm.Write(writer, ft); + + for (UInt16 moduleid = 1; moduleid <= sm.NrOfEntries; moduleid++) + { + + modules[moduleid].mi.Write(writer, ft); + + modules[moduleid].mc.Write(writer); + + modules[moduleid].mse.Write(writer); + + + foreach (KeyValuePair kvp2 in modules[moduleid].modulesubext) + { + ODentry od = kvp2.Value; + od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); + + } + + modules[moduleid].mxfo.Write(writer); + + foreach (KeyValuePair kvp3 in modules[moduleid].modulefixedobjects) + { + ODentry od = kvp3.Value; + od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); + + foreach (KeyValuePair kvp4 in od.subobjects) + { + ODentry subod = kvp4.Value; + subod.Write(writer, ft, ODentry.Odtype.FIXED, moduleid); + } + } + } + } + + if (ft == InfoSection.Filetype.File_DCF) + { + if (cm.NrOfEntries > 0) + { + cm.Write(writer); + } + } + + writer.Close(); + + } + + public DataType Getdatatype(ODentry od) + { + + if (od.objecttype == ObjectType.VAR) + { + return od.datatype; + } + + if (od.objecttype == ObjectType.ARRAY) + { + ODentry sub2 = ods[od.Index]; + + //FIX ME !!! INCONSISTANT setup of the datatype for arrays when loading xml and eds!! + + DataType t = sub2.datatype; + + if (sub2.Getsubobject(1) != null) + { + t = sub2.Getsubobject(1).datatype; + if (t == DataType.UNKNOWN) + t = sub2.datatype; + } + + return t; + } + + //Warning, REC types need to be handled else where as the specific + //implementation of a REC type depends on the exporter being used + + return DataType.UNKNOWN; + + } + + + static public byte ConvertToByte(string defaultvalue) + { + if (defaultvalue == null || defaultvalue == "") + return 0; + + return (Convert.ToByte(defaultvalue, Getbase(defaultvalue))); + } + + static public UInt16 ConvertToUInt16(byte [] bytes) + { + + UInt16 value = 0; + + value = (UInt16) ((bytes[0] << 8) | bytes[1]); + + return value; + + } + + static public UInt16 ConvertToUInt16(string defaultvalue) + { + if (defaultvalue == null || defaultvalue == "" ) + return 0; + + return (Convert.ToUInt16(defaultvalue, Getbase(defaultvalue))); + } + + static public UInt32 ConvertToUInt32(string defaultvalue) + { + if (defaultvalue == null || defaultvalue == "" ) + return 0; + + return (Convert.ToUInt32(defaultvalue, Getbase(defaultvalue))); + } + + static public int Getbase(string defaultvalue) + { + + if (defaultvalue == null || defaultvalue == "") + return 10; + + int nobase = 10; + + String pat = @"^0[xX][0-9a-fA-F]+"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 16; + } + + pat = @"^0[0-9]+"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 8; + } + + + return nobase; + } + + public void UpdatePDOcount() + { + di.NrOfRXPDO = 0; + di.NrOfTXPDO = 0; + foreach(KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if(od.prop.CO_disabled == false && od.Index >= 0x1400 && od.Index < 0x1600) + di.NrOfRXPDO++; + + if(od.prop.CO_disabled == false && od.Index >= 0x1800 && od.Index < 0x1A00) + di.NrOfTXPDO++; + + } + + } + + //Split on + , replace $NODEID with concrete value and add together + public UInt32 GetNodeID(string input, out bool nodeidpresent) + { + + if (input == null || input == "") + { + nodeidpresent = false; + return 0; + } + + input = input.ToUpper(); + + if(input.Contains("$NODEID")) + nodeidpresent = true; + else + nodeidpresent = false; + + try + { + if (dc.NodeId == 0) + { + input = input.Replace("$NODEID", ""); + input = input.Replace("+", ""); + input = input.Replace(" ", ""); + return Convert.ToUInt32(input, Getbase(input)); + } + + input = input.Replace("$NODEID", String.Format("0x{0}", dc.NodeId)); + + string[] bits = input.Split('+'); + + if(bits.Length==1) + { + //nothing to parse here just return the value + return Convert.ToUInt32(input, Getbase(input)); + } + + if (bits.Length != 2) + { + throw new FormatException("cannot parse " + input + "\nExpecting N+$NODEID or $NODEID+N"); + } + + UInt32 b1 = Convert.ToUInt32(bits[0], Getbase(bits[0])); + UInt32 b2 = Convert.ToUInt32(bits[1], Getbase(bits[1])); + + return (UInt32)(b1 + b2); + } + catch(Exception e) + { + Warnings.warning_list.Add(String.Format("Error parsing node id {0} nodes, {1}", input,e.ToString())); + } + + return 0; + } + + + public bool tryGetODEntry(UInt16 index, out ODentry od) + { + od = null; + if(ods.ContainsKey(index)) + { + od = ods[index]; + return true; + } + + if(dummy_ods.ContainsKey(index)) + { + od = dummy_ods[index]; + return true; + } + + return false; + } + + //RX COM 0x1400 + //RX Map 0x1600 + //TX COM 0x1800 + //TX MAP 0x1a00 + + //call this with the comm param index not the mapping + public bool CreatePDO(bool rx,UInt16 index) + { + //check if we are creating an RX PDO it is a valid index + if (rx && (index < 0x1400 || index >= 0x1600)) + return false; + + //check if we are creating an PDO TX it is a valid index + if (!rx & (index < 0x1800 || index >= 0x1A00)) + return false; + + //Check it does not already exist + if (ods.ContainsKey(index)) + return false; + + //check the associated mapping index does not exist + if (ods.ContainsKey((UInt16)(index+0x200))) + return false; + + ODentry od_comparam; + ODentry od_mapping; + + if (rx) + { + od_comparam = new ODentry("RPDO communication parameter", index, 0) + { + Description = @"0x1400 - 0x15FF RPDO communication parameter +max sub-index + +COB - ID + bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set + bit 11 - 29: set to 0 for 11 bit COB - ID + bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO + bit 31: 0(1) - node uses(does NOT use) PDO + +Transmission type + value = 0 - 240: receiving is synchronous, process after next reception of SYNC object + value = 241 - 253: not used + value = 254: manufacturer specific + value = 255: asynchronous" + }; + + od_mapping = new ODentry("RPDO mapping parameter", (UInt16)(index + 0x200), 0) + { + Description = @"0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) +Number of mapped objects + +mapped object (subindex 1...8) + bit 0 - 7: data length in bits + bit 8 - 15: subindex from OD + bit 16 - 31: index from OD" + }; + + + } + else + { + od_comparam = new ODentry("TPDO communication parameter", index, 0) + { + Description = @"0x1800 - 0x19FF TPDO communication parameter +max sub-index + +COB - ID + bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set + bit 11 - 29: set to 0 for 11 bit COB - ID + bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO + bit 31: 0(1) - node uses(does NOT use) PDO + +Transmission type + value = 0: transmitting is synchronous, specification in device profile + value = 1 - 240: transmitting is synchronous after every N - th SYNC object + value = 241 - 251: not used + value = 252 - 253: Transmitted only on reception of Remote Transmission Request + value = 254: manufacturer specific + value = 255: asynchronous, specification in device profile + +inhibit time + bit 0 - 15: Minimum time between transmissions of the PDO in 100µs.Zero disables functionality. + +event timer + bit 0-15: Time between periodic transmissions of the PDO in ms.Zero disables functionality. + +SYNC start value + value = 0: Counter of the SYNC message shall not be processed. + value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message." + }; + + + od_mapping = new ODentry("TPDO mapping parameter", (UInt16)(index + 0x200), 0) + { + Description = @"0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). +Number of mapped objects + +mapped object (subindex 1...8) + bit 0 - 7: data length in bits + bit 8 - 15: subindex from OD + bit 16 - 31: index from OD" + }; + } + + od_comparam.objecttype = ObjectType.REC; + od_comparam.prop.CO_storageGroup = "ROM"; + od_comparam.accesstype = AccessType.ro; + od_comparam.PDOtype = PDOMappingType.no; + + ODentry sub; + + + if(rx) + { + sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "2", AccessType.ro, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(0, sub); + sub = new ODentry("COB-ID used by RPDO", index, DataType.UNSIGNED32, "$NODEID+0x200", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(1, sub); + sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(2, sub); + + } + else + { + sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "6", AccessType.ro, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(0, sub); + sub = new ODentry("COB-ID used by TPDO", index, DataType.UNSIGNED32, "$NODEID+0x180", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(1, sub); + sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(2, sub); + sub = new ODentry("inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(3, sub); + //sub = new ODentry("compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); + //od_comparam.subobjects.Add(4, sub); + sub = new ODentry("event timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(5, sub); + sub = new ODentry("SYNC start value", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(6, sub); + + } + + od_mapping.objecttype = ObjectType.REC; + od_mapping.prop.CO_storageGroup = "ROM"; + od_mapping.accesstype = AccessType.rw; //Same as default but inconsistent with ROM above + od_mapping.PDOtype = PDOMappingType.no; + + sub = new ODentry("Number of mapped objects", (UInt16)(index + 0x200), DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, od_mapping); + od_mapping.subobjects.Add(0, sub); + + for (int p=1;p<=8;p++) + { + sub = new ODentry(string.Format("mapped object {0}",p), (UInt16)(index+0x200), DataType.UNSIGNED32, "0x00000000", AccessType.ro, PDOMappingType.no, od_mapping); + od_mapping.subobjects.Add((byte)p, sub); + } + + ods.Add(index, od_comparam); + ods.Add((UInt16)(index + 0x200), od_mapping); + + return true; + } + + public bool CreateTXPDO(UInt16 index) + { + return CreatePDO(false, index); + } + + public bool CreateRXPDO(UInt16 index) + { + return CreatePDO(true, index); + } + + public ODentry Getobject(UInt16 no) + { + + if(no>=0x002 && no<=0x007) + { + return dummy_ods[no]; + } + + if (ods.ContainsKey(no)) + { + return ods[no]; + } + + return null; + + } + + + public ODentry Getobject(string uniqueID) + { + foreach(KeyValuePair e in ods) + { + if (e.Value.uniqueID == uniqueID) + return e.Value; + + if(e.Value.subobjects!=null && e.Value.subobjects.Count>0) + { + foreach(KeyValuePair sube in e.Value.subobjects) + { + if (sube.Value.uniqueID == uniqueID) + return sube.Value; + } + + } + + + } + + return null; + } + + public int GetNoEnabledObjects(bool includesub=false) + { + int enabledcount = 0; + foreach (ODentry od in ods.Values) + { + if (od.prop.CO_disabled == false) + { + enabledcount++; + + if(includesub) + { + foreach(ODentry sub in od.subobjects.Values) + { + if (od.prop.CO_disabled == false) + { + enabledcount++; + } + } + + } + } + } + + return enabledcount; + + } + + + + } + + public class ParameterException : Exception + { + public ParameterException(String message) + : base(message) + { + + } + } + + + + } diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 7a666898..a2e5882c 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -1,69 +1,70 @@ - - - - - Debug - AnyCPU - {CC0FA4B1-2BFC-43B3-8C56-B428DF2D24E7} - Library - Properties - libEDSsharp - libEDSsharp - v4.5 - 512 - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - docs\libEDSsharp.xml - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + Debug + AnyCPU + {CC0FA4B1-2BFC-43B3-8C56-B428DF2D24E7} + Library + Properties + libEDSsharp + libEDSsharp + v4.8 + 512 + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + docs\libEDSsharp.xml + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + --> \ No newline at end of file From 797e2dd4e03cb1f92a80f88cb60ae06c166f5907 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 18 Jul 2022 10:45:39 +0200 Subject: [PATCH 023/226] - corrected range to find maxRXmappingsOD/maxTXmapping - wrong use of maxRXmappingsOD/maxTXmapping: setting the "od" variable to maxXXmappingsOD, e.g. od = maxRXmappingsOD; doesn't work because the member list creation still uses kvp.Value.subobjects, which is not the maximum number of members. So instead using foreach (KeyValuePair kvp2 in kvp.Value.subobjects) It should be something like foreach (KeyValuePair kvp2 in od.subobjects) Because "od" is set to the max[TX/RX]mappingsOD --- libEDSsharp/CanOpenNodeExporter.cs | 3338 ++++++++++++++-------------- 1 file changed, 1669 insertions(+), 1669 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 35dc25e4..2cf20c01 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -1,1091 +1,1091 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius - based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are - Copyright(c) 2010 - 2016 Janez Paternoster -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.IO; - -namespace libEDSsharp -{ - - public class CanOpenNodeExporter : IExporter - { - - private string folderpath; - private string gitVersion; - protected EDSsharp eds; - - private int enabledcount = 0; - - Dictionary acceptable_canopen_names = new Dictionary(); - - //Used for array tracking - Dictionary au = new Dictionary(); - List openings = new List(); - List closings = new List(); - - private byte maxRXmappingsize = 0; - private byte maxTXmappingsize = 0; - ODentry maxRXmappingsOD=null; - ODentry maxTXmappingsOD=null; - - public void prepareCanOpenNames() - { - acceptable_canopen_names.Add(0x101800, "identity"); - - acceptable_canopen_names.Add(0x140000, "RPDOCommunicationParameter"); - acceptable_canopen_names.Add(0x160000, "RPDOMappingParameter"); - acceptable_canopen_names.Add(0x180000, "TPDOCommunicationParameter"); - acceptable_canopen_names.Add(0x1a0000, "TPDOMappingParameter"); - - acceptable_canopen_names.Add(0x100500, "COB_ID_SYNCMessage"); - - - - acceptable_canopen_names.Add(0x101801, "vendorID"); - acceptable_canopen_names.Add(0x101802, "productCode"); - acceptable_canopen_names.Add(0x101803, "revisionNumber"); - acceptable_canopen_names.Add(0x101804, "serialNumber"); - - acceptable_canopen_names.Add(0x120000, "SDOServerParameter"); - acceptable_canopen_names.Add(0x120001, "COB_IDClientToServer"); - acceptable_canopen_names.Add(0x120002, "COB_IDServerToClient"); - - acceptable_canopen_names.Add(0x128000, "SDOClientParameter"); - acceptable_canopen_names.Add(0x128001, "COB_IDClientToServer"); - acceptable_canopen_names.Add(0x128002, "COB_IDServerToClient"); - - acceptable_canopen_names.Add(0x102900, "errorBehavior"); - - } - - - public void export(string folderpath, string filename, string gitVersion, EDSsharp eds,string odname) - { - this.folderpath = folderpath; - this.gitVersion = gitVersion; - this.eds = eds; - - - enabledcount = eds.GetNoEnabledObjects(); - - prepareCanOpenNames(); - - countPDOS(); - - - fixcompatentry(); - - prewalkArrays(); - - export_h(filename); - export_c(filename); - - } - - private void fixcompatentry() - { - // Handle the TPDO communication parameters in a special way, because of - // sizeof(OD_TPDOCommunicationParameter_t) != sizeof(CO_TPDOCommPar_t) in CANopen.c - // the existing CO_TPDOCommPar_t has a compatibility entry so we must export one regardless - // of if its in the OD or not - - for (UInt16 idx = 0x1800; idx < 0x1900; idx++) - { - if (eds.ods.ContainsKey(idx)) - { - ODentry od = eds.ods[idx]; - - if (!od.Containssubindex(0x04)) - { - ODentry compatibility = new ODentry("compatibility entry", idx, DataType.UNSIGNED8, "0", EDSsharp.AccessType.ro, PDOMappingType.no, od); - od.subobjects.Add(0x04, compatibility); - } - } - } - - } - - private void specialarraysearch(UInt16 start, UInt16 end) - { - UInt16 lowest = 0xffff; - UInt16 highest = 0x0000; - - foreach (KeyValuePair kvp in eds.ods) - { - - if (kvp.Value.prop.CO_disabled == true) - continue; - - if (kvp.Key >= start && kvp.Key <= end) - { - if (kvp.Key > highest) - highest = kvp.Key; - - if (kvp.Key < lowest) - lowest = kvp.Key; - } - } - - if(lowest!=0xffff && highest!=0x0000) - { - openings.Add(lowest); - closings.Add(highest); - - Console.WriteLine(string.Format("New special array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); - } - } - - protected void prewalkArrays() - { - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - if (od.prop.CO_disabled == true) - continue; - - string name = make_cname(od.parameter_name,od); - if (au.ContainsKey(name)) - { - au[name]++; - } - else - { - au[name] = 1; - } - } - - - //Handle special arrays - - specialarraysearch(0x1301, 0x1340); - specialarraysearch(0x1381, 0x13C0); - - - //SDO Client parameters - specialarraysearch(0x1200, 0x127F); - //SDO Server Parameters - specialarraysearch(0x1280, 0x12FF); - - //PDO Mappings and configs - specialarraysearch(0x1400, 0x15FF); - specialarraysearch(0x1600, 0x17FF); - specialarraysearch(0x1800, 0x19FF); - specialarraysearch(0x1A00, 0x1BFF); - - //now find opening and closing points for these arrays - foreach (KeyValuePair kvp in au) - { - if ( kvp.Value > 1) - { - string targetname = kvp.Key; - UInt16 lowest=0xffff; - UInt16 highest=0x0000; - foreach (KeyValuePair kvp2 in eds.ods) - { - - string name = make_cname(kvp2.Value.parameter_name,kvp2.Value); - if(name==targetname) - { - if (kvp2.Key > highest) - highest = kvp2.Key; - - if (kvp2.Key < lowest) - lowest = kvp2.Key; - } - - } - - if (!openings.Contains(lowest)) - { - openings.Add(lowest); - closings.Add(highest); - Console.WriteLine(string.Format("New array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); - } - - } - - } - - //Find maximum no entries in a mapping config to define an appropriate array - maxRXmappingsize = 0; - maxTXmappingsize = 0; - - for (ushort x=0x1600;x<0x1800;x++) - { - if(eds.ods.ContainsKey(x)) - { - byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); - - if(maxcount > maxRXmappingsize) - { - maxRXmappingsize = maxcount; - maxRXmappingsOD = eds.ods[x]; - } - } - } - - for (ushort x = 0x1a00; x < 0x1c00; x++) - { - if (eds.ods.ContainsKey(x)) - { - byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); - - if (maxcount > maxTXmappingsize) - { - maxTXmappingsize = maxcount; - maxTXmappingsOD = eds.ods[x]; - } - } - } - } - - string lastname = ""; - - private string print_h_bylocation(string location) - { - - StringBuilder sb = new StringBuilder(); - - lastname = ""; - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) - continue; - - sb.Append(print_h_entry(od)); - - } - - return sb.ToString(); - } - - - protected string print_h_entry(ODentry od) - { - StringBuilder sb = new StringBuilder(); - - if (od.Nosubindexes == 0) - { - string specialarraylength = ""; - if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) - { - - if (od.Lengthofstring == 0) - { - Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex),Warnings.warning_class.WARNING_STRING); - specialarraylength = "[1]"; - } - else - { - specialarraylength = string.Format("[{0}]", od.Lengthofstring); - } - } - - sb.AppendLine($"/*{od.Index:X4} */ {od.datatype.ToString(),-14} {make_cname(od.parameter_name,od)}{specialarraylength};"); - } - else - { - //fixme why is this not od.datatype? - DataType t = eds.Getdatatype(od); - - //If it not a defined type, and it probably is not for a REC, we must generate a name, this is - //related to the previous code that generated the actual structures. - - string objecttypewords = ""; - - switch (od.objecttype) - { - - case ObjectType.REC: - objecttypewords = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); - break; - case ObjectType.ARRAY: - objecttypewords = t.ToString(); //this case is handled by the logic in eds.getdatatype(); - break; - default: - objecttypewords = t.ToString(); - break; - } - - string name = make_cname(od.parameter_name,od); - if (au[name] > 1) - { - if (lastname == name) - return ""; - - lastname = name; - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{au[name]}];"); - } - else - { - //Don't put sub indexes on record type in h file unless there are multiples of the same - //in which case its not handled here, we need a special case for the predefined special - //values that arrayspecial() checks for, to generate 1 element arrays if needed - if (od.objecttype == ObjectType.REC) - { - if (arrayspecial(od.Index, true)) - { - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[1];"); - } - else - { - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)};"); - } - } - else - { - string specialarraylength = ""; - - if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) - { - int maxlength = 0; - foreach (ODentry sub in od.subobjects.Values) - { - if (sub.Lengthofstring> maxlength) - maxlength = sub.Lengthofstring; - } - - if (maxlength == 0) - { - Warnings.AddWarning(string.Format(" Object children of 0x{0:X4} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index),Warnings.warning_class.WARNING_STRING); - maxlength = 1; - } - - - specialarraylength = string.Format("[{0}]", maxlength); - } - - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}{specialarraylength}[{od.Nosubindexes - 1}];"); - } - } - } - - return sb.ToString(); - } - - private void addHeader(StreamWriter file) - { - file.WriteLine(string.Format( -@"/******************************************************************************* - CANopen Object Dictionary definition for CANopenNode v1 to v2 - - This file was automatically generated by CANopenEditor {0} - - https://github.com/CANopenNode/CANopenNode - https://github.com/CANopenNode/CANopenEditor - - DON'T EDIT THIS FILE MANUALLY !!!! -*******************************************************************************/", this.gitVersion)); - } - - private void export_h(string filename) - { - if (filename == "") - filename = "CO_OD"; - - StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".h"); - - file.WriteLine("// clang-format off"); - addHeader(file); - - file.WriteLine("#ifndef CO_OD_H_"); - file.WriteLine("#define CO_OD_H_"); - file.WriteLine(""); - - file.WriteLine(@"/******************************************************************************* - CANopen DATA TYPES -*******************************************************************************/ - typedef bool_t BOOLEAN; - typedef uint8_t UNSIGNED8; - typedef uint16_t UNSIGNED16; - typedef uint32_t UNSIGNED32; - typedef uint64_t UNSIGNED64; - typedef int8_t INTEGER8; - typedef int16_t INTEGER16; - typedef int32_t INTEGER32; - typedef int64_t INTEGER64; - typedef float32_t REAL32; - typedef float64_t REAL64; - typedef char_t VISIBLE_STRING; - typedef oChar_t OCTET_STRING; - - #ifdef DOMAIN - #undef DOMAIN - #endif - - typedef domain_t DOMAIN; - -"); - - file.WriteLine("/*******************************************************************************"); - file.WriteLine(" FILE INFO:"); - file.WriteLine(string.Format(" FileName: {0}", Path.GetFileName(eds.projectFilename))); - file.WriteLine(string.Format(" FileVersion: {0}", eds.fi.FileVersion)); - file.WriteLine(string.Format(" CreationTime: {0}", eds.fi.CreationTime)); - file.WriteLine(string.Format(" CreationDate: {0}", eds.fi.CreationDate)); - file.WriteLine(string.Format(" CreatedBy: {0}", eds.fi.CreatedBy)); - file.WriteLine("*******************************************************************************/"); - file.WriteLine(""); - file.WriteLine(""); - - file.WriteLine("/*******************************************************************************"); - file.WriteLine(" DEVICE INFO:"); - file.WriteLine(string.Format(" VendorName: {0}", eds.di.VendorName)); - file.WriteLine(string.Format(" VendorNumber: {0}", eds.di.VendorNumber)); - file.WriteLine(string.Format(" ProductName: {0}", eds.di.ProductName)); - file.WriteLine(string.Format(" ProductNumber: {0}", eds.di.ProductNumber)); - file.WriteLine("*******************************************************************************/"); - file.WriteLine(""); - file.WriteLine(""); - - file.WriteLine(@"/******************************************************************************* - FEATURES -*******************************************************************************/"); - - file.WriteLine(string.Format(" #define CO_NO_SYNC {0} //Associated objects: 1005-1007", noSYNC)); - - file.WriteLine(string.Format(" #define CO_NO_EMERGENCY {0} //Associated objects: 1014, 1015", noEMCY)); - - file.WriteLine(string.Format(" #define CO_NO_TIME {0} //Associated objects: 1012, 1013", noTIME)); - - file.WriteLine(string.Format(" #define CO_NO_SDO_SERVER {0} //Associated objects: 1200-127F", noSDOservers)); - file.WriteLine(string.Format(" #define CO_NO_SDO_CLIENT {0} //Associated objects: 1280-12FF", noSDOclients)); - - file.WriteLine(string.Format(" #define CO_NO_GFC {0} //Associated objects: 1300", noGFC)); - file.WriteLine(string.Format(" #define CO_NO_SRDO {0} //Associated objects: 1301-1341, 1381-13C0", noSRDO)); - - int lssServer = 0; - if (eds.di.LSS_Supported == true) - { - lssServer = 1; - } - file.WriteLine(string.Format(" #define CO_NO_LSS_SERVER {0} //LSS Slave", lssServer)); - int lssClient = 0; - if (eds.di.LSS_Master == true) - { - lssClient = 1; - } - file.WriteLine(string.Format(" #define CO_NO_LSS_CLIENT {0} //LSS Master", lssClient)); - - file.WriteLine(string.Format(" #define CO_NO_RPDO {0} //Associated objects: 14xx, 16xx", noRXpdos)); - file.WriteLine(string.Format(" #define CO_NO_TPDO {0} //Associated objects: 18xx, 1Axx", noTXpdos)); - - bool ismaster = false; - if(eds.ods.ContainsKey(0x1f80)) - { - ODentry master = eds.ods[0x1f80]; - - // we could do with a cut down function that returns a value rather than a string - string meh = formatvaluewithdatatype(master.defaultvalue, master.datatype); - meh = meh.Replace("L", ""); - - UInt32 NMTStartup = Convert.ToUInt32(meh, 16); - if ((NMTStartup & 0x01) == 0x01) - ismaster = true; - } - - file.WriteLine(string.Format(" #define CO_NO_NMT_MASTER {0}", ismaster==true?1:0)); - file.WriteLine(string.Format(" #define CO_NO_TRACE 0")); - file.WriteLine(""); - file.WriteLine(""); - file.WriteLine(@"/******************************************************************************* - OBJECT DICTIONARY -*******************************************************************************/"); - - file.WriteLine(string.Format(" #define CO_OD_NoOfElements {0}", enabledcount)); - file.WriteLine(""); - file.WriteLine(""); - - file.WriteLine(@"/******************************************************************************* - TYPE DEFINITIONS FOR RECORDS -*******************************************************************************/"); - - //We need to identify all the record types used and generate a struct for each one - //FIXME the original CANopenNode exporter said how many items used this struct in the comments - +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius + based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are + Copyright(c) 2010 - 2016 Janez Paternoster +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.IO; + +namespace libEDSsharp +{ + + public class CanOpenNodeExporter : IExporter + { + + private string folderpath; + private string gitVersion; + protected EDSsharp eds; + + private int enabledcount = 0; + + Dictionary acceptable_canopen_names = new Dictionary(); + + //Used for array tracking + Dictionary au = new Dictionary(); + List openings = new List(); + List closings = new List(); + + private byte maxRXmappingsize = 0; + private byte maxTXmappingsize = 0; + ODentry maxRXmappingsOD=null; + ODentry maxTXmappingsOD=null; + + public void prepareCanOpenNames() + { + acceptable_canopen_names.Add(0x101800, "identity"); + + acceptable_canopen_names.Add(0x140000, "RPDOCommunicationParameter"); + acceptable_canopen_names.Add(0x160000, "RPDOMappingParameter"); + acceptable_canopen_names.Add(0x180000, "TPDOCommunicationParameter"); + acceptable_canopen_names.Add(0x1a0000, "TPDOMappingParameter"); + + acceptable_canopen_names.Add(0x100500, "COB_ID_SYNCMessage"); + + + + acceptable_canopen_names.Add(0x101801, "vendorID"); + acceptable_canopen_names.Add(0x101802, "productCode"); + acceptable_canopen_names.Add(0x101803, "revisionNumber"); + acceptable_canopen_names.Add(0x101804, "serialNumber"); + + acceptable_canopen_names.Add(0x120000, "SDOServerParameter"); + acceptable_canopen_names.Add(0x120001, "COB_IDClientToServer"); + acceptable_canopen_names.Add(0x120002, "COB_IDServerToClient"); + + acceptable_canopen_names.Add(0x128000, "SDOClientParameter"); + acceptable_canopen_names.Add(0x128001, "COB_IDClientToServer"); + acceptable_canopen_names.Add(0x128002, "COB_IDServerToClient"); + + acceptable_canopen_names.Add(0x102900, "errorBehavior"); + + } + + + public void export(string folderpath, string filename, string gitVersion, EDSsharp eds,string odname) + { + this.folderpath = folderpath; + this.gitVersion = gitVersion; + this.eds = eds; + + + enabledcount = eds.GetNoEnabledObjects(); + + prepareCanOpenNames(); + + countPDOS(); + + + fixcompatentry(); + + prewalkArrays(); + + export_h(filename); + export_c(filename); + + } + + private void fixcompatentry() + { + // Handle the TPDO communication parameters in a special way, because of + // sizeof(OD_TPDOCommunicationParameter_t) != sizeof(CO_TPDOCommPar_t) in CANopen.c + // the existing CO_TPDOCommPar_t has a compatibility entry so we must export one regardless + // of if its in the OD or not + + for (UInt16 idx = 0x1800; idx < 0x1900; idx++) + { + if (eds.ods.ContainsKey(idx)) + { + ODentry od = eds.ods[idx]; + + if (!od.Containssubindex(0x04)) + { + ODentry compatibility = new ODentry("compatibility entry", idx, DataType.UNSIGNED8, "0", EDSsharp.AccessType.ro, PDOMappingType.no, od); + od.subobjects.Add(0x04, compatibility); + } + } + } + + } + + private void specialarraysearch(UInt16 start, UInt16 end) + { + UInt16 lowest = 0xffff; + UInt16 highest = 0x0000; + + foreach (KeyValuePair kvp in eds.ods) + { + + if (kvp.Value.prop.CO_disabled == true) + continue; + + if (kvp.Key >= start && kvp.Key <= end) + { + if (kvp.Key > highest) + highest = kvp.Key; + + if (kvp.Key < lowest) + lowest = kvp.Key; + } + } + + if(lowest!=0xffff && highest!=0x0000) + { + openings.Add(lowest); + closings.Add(highest); + + Console.WriteLine(string.Format("New special array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); + } + } + + protected void prewalkArrays() + { + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + if (od.prop.CO_disabled == true) + continue; + + string name = make_cname(od.parameter_name,od); + if (au.ContainsKey(name)) + { + au[name]++; + } + else + { + au[name] = 1; + } + } + + + //Handle special arrays + + specialarraysearch(0x1301, 0x1340); + specialarraysearch(0x1381, 0x13C0); + + + //SDO Client parameters + specialarraysearch(0x1200, 0x127F); + //SDO Server Parameters + specialarraysearch(0x1280, 0x12FF); + + //PDO Mappings and configs + specialarraysearch(0x1400, 0x15FF); + specialarraysearch(0x1600, 0x17FF); + specialarraysearch(0x1800, 0x19FF); + specialarraysearch(0x1A00, 0x1BFF); + + //now find opening and closing points for these arrays + foreach (KeyValuePair kvp in au) + { + if ( kvp.Value > 1) + { + string targetname = kvp.Key; + UInt16 lowest=0xffff; + UInt16 highest=0x0000; + foreach (KeyValuePair kvp2 in eds.ods) + { + + string name = make_cname(kvp2.Value.parameter_name,kvp2.Value); + if(name==targetname) + { + if (kvp2.Key > highest) + highest = kvp2.Key; + + if (kvp2.Key < lowest) + lowest = kvp2.Key; + } + + } + + if (!openings.Contains(lowest)) + { + openings.Add(lowest); + closings.Add(highest); + Console.WriteLine(string.Format("New array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); + } + + } + + } + + //Find maximum no entries in a mapping config to define an appropriate array + maxRXmappingsize = 0; + maxTXmappingsize = 0; + + for (ushort x=0x1600;x<0x1800;x++) + { + if(eds.ods.ContainsKey(x)) + { + byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); + + if(maxcount > maxRXmappingsize) + { + maxRXmappingsize = maxcount; + maxRXmappingsOD = eds.ods[x]; + } + } + } + + for (ushort x = 0x1a00; x < 0x1c00; x++) + { + if (eds.ods.ContainsKey(x)) + { + byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); + + if (maxcount > maxTXmappingsize) + { + maxTXmappingsize = maxcount; + maxTXmappingsOD = eds.ods[x]; + } + } + } + } + + string lastname = ""; + + private string print_h_bylocation(string location) + { + + StringBuilder sb = new StringBuilder(); + + lastname = ""; + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) + continue; + + sb.Append(print_h_entry(od)); + + } + + return sb.ToString(); + } + + + protected string print_h_entry(ODentry od) + { + StringBuilder sb = new StringBuilder(); + + if (od.Nosubindexes == 0) + { + string specialarraylength = ""; + if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) + { + + if (od.Lengthofstring == 0) + { + Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex),Warnings.warning_class.WARNING_STRING); + specialarraylength = "[1]"; + } + else + { + specialarraylength = string.Format("[{0}]", od.Lengthofstring); + } + } + + sb.AppendLine($"/*{od.Index:X4} */ {od.datatype.ToString(),-14} {make_cname(od.parameter_name,od)}{specialarraylength};"); + } + else + { + //fixme why is this not od.datatype? + DataType t = eds.Getdatatype(od); + + //If it not a defined type, and it probably is not for a REC, we must generate a name, this is + //related to the previous code that generated the actual structures. + + string objecttypewords = ""; + + switch (od.objecttype) + { + + case ObjectType.REC: + objecttypewords = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); + break; + case ObjectType.ARRAY: + objecttypewords = t.ToString(); //this case is handled by the logic in eds.getdatatype(); + break; + default: + objecttypewords = t.ToString(); + break; + } + + string name = make_cname(od.parameter_name,od); + if (au[name] > 1) + { + if (lastname == name) + return ""; + + lastname = name; + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{au[name]}];"); + } + else + { + //Don't put sub indexes on record type in h file unless there are multiples of the same + //in which case its not handled here, we need a special case for the predefined special + //values that arrayspecial() checks for, to generate 1 element arrays if needed + if (od.objecttype == ObjectType.REC) + { + if (arrayspecial(od.Index, true)) + { + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[1];"); + } + else + { + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)};"); + } + } + else + { + string specialarraylength = ""; + + if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) + { + int maxlength = 0; + foreach (ODentry sub in od.subobjects.Values) + { + if (sub.Lengthofstring> maxlength) + maxlength = sub.Lengthofstring; + } + + if (maxlength == 0) + { + Warnings.AddWarning(string.Format(" Object children of 0x{0:X4} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index),Warnings.warning_class.WARNING_STRING); + maxlength = 1; + } + + + specialarraylength = string.Format("[{0}]", maxlength); + } + + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}{specialarraylength}[{od.Nosubindexes - 1}];"); + } + } + } + + return sb.ToString(); + } + + private void addHeader(StreamWriter file) + { + file.WriteLine(string.Format( +@"/******************************************************************************* + CANopen Object Dictionary definition for CANopenNode v1 to v2 + + This file was automatically generated by CANopenEditor {0} + + https://github.com/CANopenNode/CANopenNode + https://github.com/CANopenNode/CANopenEditor + + DON'T EDIT THIS FILE MANUALLY !!!! +*******************************************************************************/", this.gitVersion)); + } + + private void export_h(string filename) + { + if (filename == "") + filename = "CO_OD"; + + StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".h"); + + file.WriteLine("// clang-format off"); + addHeader(file); + + file.WriteLine("#ifndef CO_OD_H_"); + file.WriteLine("#define CO_OD_H_"); + file.WriteLine(""); + + file.WriteLine(@"/******************************************************************************* + CANopen DATA TYPES +*******************************************************************************/ + typedef bool_t BOOLEAN; + typedef uint8_t UNSIGNED8; + typedef uint16_t UNSIGNED16; + typedef uint32_t UNSIGNED32; + typedef uint64_t UNSIGNED64; + typedef int8_t INTEGER8; + typedef int16_t INTEGER16; + typedef int32_t INTEGER32; + typedef int64_t INTEGER64; + typedef float32_t REAL32; + typedef float64_t REAL64; + typedef char_t VISIBLE_STRING; + typedef oChar_t OCTET_STRING; + + #ifdef DOMAIN + #undef DOMAIN + #endif + + typedef domain_t DOMAIN; + +"); + + file.WriteLine("/*******************************************************************************"); + file.WriteLine(" FILE INFO:"); + file.WriteLine(string.Format(" FileName: {0}", Path.GetFileName(eds.projectFilename))); + file.WriteLine(string.Format(" FileVersion: {0}", eds.fi.FileVersion)); + file.WriteLine(string.Format(" CreationTime: {0}", eds.fi.CreationTime)); + file.WriteLine(string.Format(" CreationDate: {0}", eds.fi.CreationDate)); + file.WriteLine(string.Format(" CreatedBy: {0}", eds.fi.CreatedBy)); + file.WriteLine("*******************************************************************************/"); + file.WriteLine(""); + file.WriteLine(""); + + file.WriteLine("/*******************************************************************************"); + file.WriteLine(" DEVICE INFO:"); + file.WriteLine(string.Format(" VendorName: {0}", eds.di.VendorName)); + file.WriteLine(string.Format(" VendorNumber: {0}", eds.di.VendorNumber)); + file.WriteLine(string.Format(" ProductName: {0}", eds.di.ProductName)); + file.WriteLine(string.Format(" ProductNumber: {0}", eds.di.ProductNumber)); + file.WriteLine("*******************************************************************************/"); + file.WriteLine(""); + file.WriteLine(""); + + file.WriteLine(@"/******************************************************************************* + FEATURES +*******************************************************************************/"); + + file.WriteLine(string.Format(" #define CO_NO_SYNC {0} //Associated objects: 1005-1007", noSYNC)); + + file.WriteLine(string.Format(" #define CO_NO_EMERGENCY {0} //Associated objects: 1014, 1015", noEMCY)); + + file.WriteLine(string.Format(" #define CO_NO_TIME {0} //Associated objects: 1012, 1013", noTIME)); + + file.WriteLine(string.Format(" #define CO_NO_SDO_SERVER {0} //Associated objects: 1200-127F", noSDOservers)); + file.WriteLine(string.Format(" #define CO_NO_SDO_CLIENT {0} //Associated objects: 1280-12FF", noSDOclients)); + + file.WriteLine(string.Format(" #define CO_NO_GFC {0} //Associated objects: 1300", noGFC)); + file.WriteLine(string.Format(" #define CO_NO_SRDO {0} //Associated objects: 1301-1341, 1381-13C0", noSRDO)); + + int lssServer = 0; + if (eds.di.LSS_Supported == true) + { + lssServer = 1; + } + file.WriteLine(string.Format(" #define CO_NO_LSS_SERVER {0} //LSS Slave", lssServer)); + int lssClient = 0; + if (eds.di.LSS_Master == true) + { + lssClient = 1; + } + file.WriteLine(string.Format(" #define CO_NO_LSS_CLIENT {0} //LSS Master", lssClient)); + + file.WriteLine(string.Format(" #define CO_NO_RPDO {0} //Associated objects: 14xx, 16xx", noRXpdos)); + file.WriteLine(string.Format(" #define CO_NO_TPDO {0} //Associated objects: 18xx, 1Axx", noTXpdos)); + + bool ismaster = false; + if(eds.ods.ContainsKey(0x1f80)) + { + ODentry master = eds.ods[0x1f80]; + + // we could do with a cut down function that returns a value rather than a string + string meh = formatvaluewithdatatype(master.defaultvalue, master.datatype); + meh = meh.Replace("L", ""); + + UInt32 NMTStartup = Convert.ToUInt32(meh, 16); + if ((NMTStartup & 0x01) == 0x01) + ismaster = true; + } + + file.WriteLine(string.Format(" #define CO_NO_NMT_MASTER {0}", ismaster==true?1:0)); + file.WriteLine(string.Format(" #define CO_NO_TRACE 0")); + file.WriteLine(""); + file.WriteLine(""); + file.WriteLine(@"/******************************************************************************* + OBJECT DICTIONARY +*******************************************************************************/"); + + file.WriteLine(string.Format(" #define CO_OD_NoOfElements {0}", enabledcount)); + file.WriteLine(""); + file.WriteLine(""); + + file.WriteLine(@"/******************************************************************************* + TYPE DEFINITIONS FOR RECORDS +*******************************************************************************/"); + + //We need to identify all the record types used and generate a struct for each one + //FIXME the original CANopenNode exporter said how many items used this struct in the comments + List structnamelist = new List(); /* make sure, we have all storage groups */ eds.CO_storageGroups.Add("ROM"); - eds.CO_storageGroups.Add("EEPROM"); - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - /* make sure, we have all storage groups */ - eds.CO_storageGroups.Add(od.prop.CO_storageGroup); - - if (od.objecttype != ObjectType.REC) - continue; - - string structname = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); - - if (structnamelist.Contains(structname)) - continue; - - structnamelist.Add(structname); - - // we need to search the mappings to find the largest or this will not generate correctly - // as can opennode only has 1 structure defined for all mappings see #220 - - if (kvp.Key>0x1600 || kvp.Key<0x1800) - { - //switch the OD entry to the largest - od = maxRXmappingsOD; - } - - if (kvp.Key > 0x1A00 || kvp.Key < 0x1C00) - { - //switch the OD entry to the largest - od = maxTXmappingsOD; - } - - List structmemberlist = new List(); - - file.WriteLine(string.Format("/*{0:X4} */ typedef struct {{", kvp.Key)); - foreach (KeyValuePair kvp2 in kvp.Value.subobjects) - { - string paramaterarrlen = ""; - ODentry subod = kvp2.Value; - - string proposedname = make_cname(subod.parameter_name,subod); - - int suffix=1; - while (structmemberlist.Contains(proposedname)) - { - Warnings.AddWarning(string.Format("STRUCT WARNING; in 0x{0:X4}/{1:X2} Duplicate struct entry name, it has been auto numbered",subod.Index,subod.Subindex),Warnings.warning_class.WARNING_STRUCT); - proposedname = make_cname(subod.parameter_name,subod) + suffix.ToString(); - suffix++; - } - - structmemberlist.Add(proposedname); - - if (subod.datatype==DataType.VISIBLE_STRING || subod.datatype==DataType.OCTET_STRING) - { - paramaterarrlen = String.Format("[{0}]", subod.Lengthofstring); - } - - file.WriteLine(string.Format(" {0,-15}{1}{2};", subod.datatype.ToString(), proposedname,paramaterarrlen)); - - } - - file.WriteLine(string.Format(" }} {0};", structname)); - - } - - - - file.WriteLine(@" -/******************************************************************************* - TYPE DEFINITIONS FOR OBJECT DICTIONARY INDEXES - - some of those are redundant with CO_SDO.h CO_ObjDicId_t -*******************************************************************************/"); - - //FIXME how can we get rid of that redundancy? - - foreach (KeyValuePair kvp in eds.ods) - { - - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true) - continue; - - DataType t = eds.Getdatatype(od); - - - switch (od.objecttype) - { - default: - { - file.WriteLine(string.Format("/*{0:X4} */", od.Index)); - file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); - - file.WriteLine(""); - } - break; - - case ObjectType.ARRAY: - case ObjectType.REC: - { - file.WriteLine(string.Format("/*{0:X4} */", od.Index)); - file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); - - file.WriteLine(""); - - //sub indexes - file.WriteLine(string.Format(" #define {0,-51} 0", string.Format("OD_{0:X4}_0_{1}_maxSubIndex", od.Index, make_cname(od.parameter_name,od)))); - - List ODSIs = new List(); - - string ODSIout = ""; - - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry sub = kvp2.Value; - - if (kvp2.Key == 0) - continue; - - string ODSI = string.Format("{0}", string.Format("OD_{0:X4}_{1}_{2}_{3}", od.Index, kvp2.Key, make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); - - if (ODSIs.Contains(ODSI)) - { - continue; - } - - ODSIs.Add(ODSI); - - ODSIout += ($" #define {ODSI,-51} {kvp2.Key}{Environment.NewLine}"); - } - - file.Write(ODSIout); - file.WriteLine(""); - } - break; - } - } - - file.WriteLine(@"/******************************************************************************* - STRUCTURES FOR VARIABLES IN DIFFERENT MEMORY LOCATIONS -*******************************************************************************/ -#define CO_OD_FIRST_LAST_WORD 0x55 //Any value from 0x01 to 0xFE. If changed, EEPROM will be reinitialized. -"); - foreach (string location in eds.CO_storageGroups) - { - if (location == "Unused") - { - continue; - } - - file.Write("/***** Structure for "); - file.Write(location); - file.WriteLine(" variables ********************************************/"); - file.Write("struct sCO_OD_"); - file.Write(location); - file.Write(@"{ - UNSIGNED32 FirstWord; - -"); - - file.Write(print_h_bylocation(location)); - - file.WriteLine(@" - UNSIGNED32 LastWord; -}; -"); - } - - file.WriteLine(@"/***** Declaration of Object Dictionary variables *****************************/"); - - foreach (string location in eds.CO_storageGroups) - { - if (location == "Unused") - { - continue; - } - - file.Write("extern struct sCO_OD_"); - file.Write(location); - file.Write(" CO_OD_"); - file.Write(location); - file.WriteLine(@"; -"); - } - -file.WriteLine(@"/******************************************************************************* - ALIASES FOR OBJECT DICTIONARY VARIABLES -*******************************************************************************/"); - - List constructed_rec_types = new List(); - - foreach (KeyValuePair kvp in eds.ods) - { - - - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true) - continue; - - string loc = "CO_OD_" + od.prop.CO_storageGroup; - - DataType t = eds.Getdatatype(od); - - - switch (od.objecttype) - { - default: - { - file.WriteLine(string.Format("/*{0:X4}, Data Type: {1} */", od.Index, t.ToString())); - file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", make_cname(od.parameter_name,od)), loc, make_cname(od.parameter_name,od))); - - DataType dt = od.datatype; - - if (dt == DataType.OCTET_STRING || dt == DataType.VISIBLE_STRING) - { - file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_stringLength", make_cname(od.parameter_name,od)), od.Lengthofstring)); - } - file.WriteLine(""); - } - break; - - case ObjectType.ARRAY: - { - DataType dt = od.datatype; - - file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}, Array[{2}] */", od.Index, t.ToString(), od.Nosubindexes - 1)); - file.WriteLine(string.Format(" #define OD_{0,-48} {1}.{2}", make_cname(od.parameter_name,od), loc, make_cname(od.parameter_name,od))); - file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_arrayLength", make_cname(od.parameter_name,od)), od.Nosubindexes - 1)); - - - List ODAs = new List(); - - string ODAout = ""; - - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry sub = kvp2.Value; - - if (kvp2.Key == 0) - continue; - - string ODA = string.Format("{0}", string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); - - if (ODAs.Contains(ODA)) - { - continue; - } - - ODAs.Add(ODA); - - //Arrays do not have a size in the raw CO objects, Records do - //so offset by one - if (od.objecttype == ObjectType.ARRAY) - { - ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key - 1}{Environment.NewLine}"); - } - else - { - ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key}{Environment.NewLine}"); - } - } - - file.Write(ODAout); - file.WriteLine(""); - } - break; - - case ObjectType.REC: - { - string rectype = make_cname(od.parameter_name,od); - - if (!constructed_rec_types.Contains(rectype)) - { - file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}_t */", od.Index, rectype)); - file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", rectype), loc, rectype)); - constructed_rec_types.Add(rectype); - file.WriteLine(""); - } - - } - break; - } - } - file.WriteLine("#endif"); - file.WriteLine("// clang-format on"); - file.Close(); - - } - - private void export_c(string filename) - { - if (filename == "") - filename = "CO_OD"; - StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".c"); - - file.WriteLine("// clang-format off"); - addHeader(file); - file.WriteLine(@"// For CANopenNode V2 users, C macro `CO_VERSION_MAJOR=2` has to be added to project options -#ifndef CO_VERSION_MAJOR - #include ""CO_driver.h"" - #include """ + filename + @".h"" - #include ""CO_SDO.h"" -#elif CO_VERSION_MAJOR < 4 - #include ""301/CO_driver.h"" - #include """ + filename + @".h"" - #include ""301/CO_SDOserver.h"" -#else - #error This Object dictionary is not compatible with CANopenNode v4.0 and up! -#endif - -/******************************************************************************* - DEFINITION AND INITIALIZATION OF OBJECT DICTIONARY VARIABLES -*******************************************************************************/ - -"); - foreach (string location in eds.CO_storageGroups) - { - if (location == "Unused") - { - continue; - } - - file.Write("/***** Definition for "); - file.Write(location); - file.WriteLine(" variables *******************************************/"); - file.Write("struct sCO_OD_"); - file.Write(location); - file.Write(" CO_OD_"); - file.Write(location); - file.Write(@" = { - CO_OD_FIRST_LAST_WORD, - -"); - - file.Write(export_OD_def_array(location)); - - file.WriteLine(@" - CO_OD_FIRST_LAST_WORD, -}; - -"); - } - - - file.WriteLine(@" - -/******************************************************************************* - STRUCTURES FOR RECORD TYPE OBJECTS -*******************************************************************************/ - -"); - - file.Write(export_record_types()); - - file.Write(@"/******************************************************************************* - OBJECT DICTIONARY -*******************************************************************************/ -const CO_OD_entry_t CO_OD[CO_OD_NoOfElements] = { -"); - - file.Write(write_od()); - - file.WriteLine("};"); - file.WriteLine("// clang-format on"); - - file.Close(); - } - - bool arrayspecialcase = false; - int arrayspecialcasecount = 0; - - string write_od() - { - - StringBuilder returndata = new StringBuilder(); - - foreach (KeyValuePair kvp in eds.ods) - { - - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true) - continue; - - returndata.Append(write_od_line(od)); - - - } - - return returndata.ToString(); - } - - protected string write_od_line(ODentry od) - { - StringBuilder sb = new StringBuilder(); - - string loc = "CO_OD_" + od.prop.CO_storageGroup; - - byte flags = getflags(od); - - int datasize = od.objecttype == ObjectType.REC ? 0 : (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); - - string array = ""; - - //only needed for array objects - if (od.objecttype == ObjectType.ARRAY && od.Nosubindexes > 0) - array = string.Format("[0]"); - - - if (arrayspecial(od.Index, true)) - { - arrayspecialcase = true; - arrayspecialcasecount = 0; - } - - if (arrayspecialcase) - { - array = string.Format("[{0}]", arrayspecialcasecount); - arrayspecialcasecount++; - } - - //Arrays and Recs have 1 less subindex than actually present in the od.subobjects - int nosubindexs = od.Nosubindexes; - if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.REC) - { - if (nosubindexs > 0) - nosubindexs--; - } - - //Arrays really should obey the max subindex parameter not the physical number of elements - if (od.objecttype == ObjectType.ARRAY) - { - if ((od.Getmaxsubindex() != nosubindexs)) - { - if (od.Index != 0x1003 && od.Index != 0x1011)//ignore 0x1003, it is a special case as per CANopen specs, and ignore 0x1011 CANopenNode uses special sub indexes for eeprom resets - { - Warnings.AddWarning(String.Format("Subindex discrepancy on object 0x{0:X4} arraysize: {1} vs max sub-index: {2}", od.Index, nosubindexs, od.Getmaxsubindex())); - } - - //0x1003 is a special case for CANopenNode - //SubIndex 0 will probably be 0 for no errors - //so we cannot read that to determine max subindex size, which is required to set up CANopenNode so we leave it alone here - //as its already set to subod.count - if (od.Index != 0x1003) - { - nosubindexs = od.Getmaxsubindex(); - } - } - } - - string pdata; //CO_OD_entry_t pData generator - - if (od.objecttype == ObjectType.REC) - { - - pdata = string.Format("&OD_record{0:X4}", od.Index); - } - else - { - pdata = string.Format("&{0}.{1}{2}", loc, make_cname(od.parameter_name,od), array); - } - - if ((od.objecttype == ObjectType.VAR || od.objecttype == ObjectType.ARRAY) && od.datatype == DataType.DOMAIN) - { - //NB domain MUST have a data pointer of 0, can open node requires this and makes checks - //against null to determine this is a DOMAIN type. - pdata = "0"; - } - - sb.AppendLine($"{{0x{od.Index:X4}, 0x{nosubindexs:X2}, 0x{flags:X2}, {datasize,2:#0}, (void*){pdata}}},"); - - if (arrayspecial(od.Index, false)) - { - arrayspecialcase = false; - } - - return sb.ToString(); - } - - /// - /// Get the CANopenNode specific flags, these flags are used internally in CANopenNode to determine details about the object variable - /// - /// An odentry to access - /// byte containing the flag value - public byte getflags(ODentry od) - { - byte flags = 0; - byte mapping = 0; //mapping flags, if pdo is enabled - - //aways return 0 for REC objects as CO_OD_getDataPointer() uses this to pickup the details - if (od.objecttype == ObjectType.REC) - return 0; - - switch((od.parent == null ? od : od.parent).prop.CO_storageGroup.ToUpper()) - { - case "ROM": - flags = 0x01; - break; - - case "RAM": - flags = 0x02; - break; - - case "EEPROM": - default: - flags = 0x03; - break; - } - - /* some exceptions for rwr/rww. Those are entries that are always r/w via SDO transfer, - * but can only be read -or- written via PDO */ - if (od.accesstype == EDSsharp.AccessType.ro - || od.accesstype == EDSsharp.AccessType.rw - || od.accesstype == EDSsharp.AccessType.rwr - || od.accesstype == EDSsharp.AccessType.rww - || od.accesstype == EDSsharp.AccessType.@const) - { - /* SDO server may read from the variable */ - flags |= 0x04; - - if (od.accesstype != EDSsharp.AccessType.rww) - { - /* Variable is mappable for TPDO */ - mapping |= 0x20; - } - } - if (od.accesstype == EDSsharp.AccessType.wo - || od.accesstype == EDSsharp.AccessType.rw - || od.accesstype == EDSsharp.AccessType.rwr - || od.accesstype == EDSsharp.AccessType.rww) - { - /* SDO server may write to the variable */ - flags |= 0x08; - - if (od.accesstype != EDSsharp.AccessType.rwr) - { - /* Variable is mappable for RPDO */ - mapping |= 0x10; - } - } - + eds.CO_storageGroups.Add("EEPROM"); + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + /* make sure, we have all storage groups */ + eds.CO_storageGroups.Add(od.prop.CO_storageGroup); + + if (od.objecttype != ObjectType.REC) + continue; + + string structname = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); + + if (structnamelist.Contains(structname)) + continue; + + structnamelist.Add(structname); + + // we need to search the mappings to find the largest or this will not generate correctly + // as can opennode only has 1 structure defined for all mappings see #220 + + if (kvp.Key>=0x1600 && kvp.Key<0x1800) + { + //switch the OD entry to the largest + od = maxRXmappingsOD; + } + + if (kvp.Key >= 0x1A00 && kvp.Key < 0x1C00) + { + //switch the OD entry to the largest + od = maxTXmappingsOD; + } + + List structmemberlist = new List(); + + file.WriteLine(string.Format("/*{0:X4} */ typedef struct {{", kvp.Key)); + foreach (KeyValuePair kvp2 in od.subobjects) // kvp.Value.subobjects) + { + string paramaterarrlen = ""; + ODentry subod = kvp2.Value; + + string proposedname = make_cname(subod.parameter_name,subod); + + int suffix=1; + while (structmemberlist.Contains(proposedname)) + { + Warnings.AddWarning(string.Format("STRUCT WARNING; in 0x{0:X4}/{1:X2} Duplicate struct entry name, it has been auto numbered",subod.Index,subod.Subindex),Warnings.warning_class.WARNING_STRUCT); + proposedname = make_cname(subod.parameter_name,subod) + suffix.ToString(); + suffix++; + } + + structmemberlist.Add(proposedname); + + if (subod.datatype==DataType.VISIBLE_STRING || subod.datatype==DataType.OCTET_STRING) + { + paramaterarrlen = String.Format("[{0}]", subod.Lengthofstring); + } + + file.WriteLine(string.Format(" {0,-15}{1}{2};", subod.datatype.ToString(), proposedname,paramaterarrlen)); + + } + + file.WriteLine(string.Format(" }} {0};", structname)); + + } + + + + file.WriteLine(@" +/******************************************************************************* + TYPE DEFINITIONS FOR OBJECT DICTIONARY INDEXES + + some of those are redundant with CO_SDO.h CO_ObjDicId_t +*******************************************************************************/"); + + //FIXME how can we get rid of that redundancy? + + foreach (KeyValuePair kvp in eds.ods) + { + + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true) + continue; + + DataType t = eds.Getdatatype(od); + + + switch (od.objecttype) + { + default: + { + file.WriteLine(string.Format("/*{0:X4} */", od.Index)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); + + file.WriteLine(""); + } + break; + + case ObjectType.ARRAY: + case ObjectType.REC: + { + file.WriteLine(string.Format("/*{0:X4} */", od.Index)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); + + file.WriteLine(""); + + //sub indexes + file.WriteLine(string.Format(" #define {0,-51} 0", string.Format("OD_{0:X4}_0_{1}_maxSubIndex", od.Index, make_cname(od.parameter_name,od)))); + + List ODSIs = new List(); + + string ODSIout = ""; + + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry sub = kvp2.Value; + + if (kvp2.Key == 0) + continue; + + string ODSI = string.Format("{0}", string.Format("OD_{0:X4}_{1}_{2}_{3}", od.Index, kvp2.Key, make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); + + if (ODSIs.Contains(ODSI)) + { + continue; + } + + ODSIs.Add(ODSI); + + ODSIout += ($" #define {ODSI,-51} {kvp2.Key}{Environment.NewLine}"); + } + + file.Write(ODSIout); + file.WriteLine(""); + } + break; + } + } + + file.WriteLine(@"/******************************************************************************* + STRUCTURES FOR VARIABLES IN DIFFERENT MEMORY LOCATIONS +*******************************************************************************/ +#define CO_OD_FIRST_LAST_WORD 0x55 //Any value from 0x01 to 0xFE. If changed, EEPROM will be reinitialized. +"); + foreach (string location in eds.CO_storageGroups) + { + if (location == "Unused") + { + continue; + } + + file.Write("/***** Structure for "); + file.Write(location); + file.WriteLine(" variables ********************************************/"); + file.Write("struct sCO_OD_"); + file.Write(location); + file.Write(@"{ + UNSIGNED32 FirstWord; + +"); + + file.Write(print_h_bylocation(location)); + + file.WriteLine(@" + UNSIGNED32 LastWord; +}; +"); + } + + file.WriteLine(@"/***** Declaration of Object Dictionary variables *****************************/"); + + foreach (string location in eds.CO_storageGroups) + { + if (location == "Unused") + { + continue; + } + + file.Write("extern struct sCO_OD_"); + file.Write(location); + file.Write(" CO_OD_"); + file.Write(location); + file.WriteLine(@"; +"); + } + +file.WriteLine(@"/******************************************************************************* + ALIASES FOR OBJECT DICTIONARY VARIABLES +*******************************************************************************/"); + + List constructed_rec_types = new List(); + + foreach (KeyValuePair kvp in eds.ods) + { + + + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true) + continue; + + string loc = "CO_OD_" + od.prop.CO_storageGroup; + + DataType t = eds.Getdatatype(od); + + + switch (od.objecttype) + { + default: + { + file.WriteLine(string.Format("/*{0:X4}, Data Type: {1} */", od.Index, t.ToString())); + file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", make_cname(od.parameter_name,od)), loc, make_cname(od.parameter_name,od))); + + DataType dt = od.datatype; + + if (dt == DataType.OCTET_STRING || dt == DataType.VISIBLE_STRING) + { + file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_stringLength", make_cname(od.parameter_name,od)), od.Lengthofstring)); + } + file.WriteLine(""); + } + break; + + case ObjectType.ARRAY: + { + DataType dt = od.datatype; + + file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}, Array[{2}] */", od.Index, t.ToString(), od.Nosubindexes - 1)); + file.WriteLine(string.Format(" #define OD_{0,-48} {1}.{2}", make_cname(od.parameter_name,od), loc, make_cname(od.parameter_name,od))); + file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_arrayLength", make_cname(od.parameter_name,od)), od.Nosubindexes - 1)); + + + List ODAs = new List(); + + string ODAout = ""; + + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry sub = kvp2.Value; + + if (kvp2.Key == 0) + continue; + + string ODA = string.Format("{0}", string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); + + if (ODAs.Contains(ODA)) + { + continue; + } + + ODAs.Add(ODA); + + //Arrays do not have a size in the raw CO objects, Records do + //so offset by one + if (od.objecttype == ObjectType.ARRAY) + { + ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key - 1}{Environment.NewLine}"); + } + else + { + ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key}{Environment.NewLine}"); + } + } + + file.Write(ODAout); + file.WriteLine(""); + } + break; + + case ObjectType.REC: + { + string rectype = make_cname(od.parameter_name,od); + + if (!constructed_rec_types.Contains(rectype)) + { + file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}_t */", od.Index, rectype)); + file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", rectype), loc, rectype)); + constructed_rec_types.Add(rectype); + file.WriteLine(""); + } + + } + break; + } + } + file.WriteLine("#endif"); + file.WriteLine("// clang-format on"); + file.Close(); + + } + + private void export_c(string filename) + { + if (filename == "") + filename = "CO_OD"; + StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".c"); + + file.WriteLine("// clang-format off"); + addHeader(file); + file.WriteLine(@"// For CANopenNode V2 users, C macro `CO_VERSION_MAJOR=2` has to be added to project options +#ifndef CO_VERSION_MAJOR + #include ""CO_driver.h"" + #include """ + filename + @".h"" + #include ""CO_SDO.h"" +#elif CO_VERSION_MAJOR < 4 + #include ""301/CO_driver.h"" + #include """ + filename + @".h"" + #include ""301/CO_SDOserver.h"" +#else + #error This Object dictionary is not compatible with CANopenNode v4.0 and up! +#endif + +/******************************************************************************* + DEFINITION AND INITIALIZATION OF OBJECT DICTIONARY VARIABLES +*******************************************************************************/ + +"); + foreach (string location in eds.CO_storageGroups) + { + if (location == "Unused") + { + continue; + } + + file.Write("/***** Definition for "); + file.Write(location); + file.WriteLine(" variables *******************************************/"); + file.Write("struct sCO_OD_"); + file.Write(location); + file.Write(" CO_OD_"); + file.Write(location); + file.Write(@" = { + CO_OD_FIRST_LAST_WORD, + +"); + + file.Write(export_OD_def_array(location)); + + file.WriteLine(@" + CO_OD_FIRST_LAST_WORD, +}; + +"); + } + + + file.WriteLine(@" + +/******************************************************************************* + STRUCTURES FOR RECORD TYPE OBJECTS +*******************************************************************************/ + +"); + + file.Write(export_record_types()); + + file.Write(@"/******************************************************************************* + OBJECT DICTIONARY +*******************************************************************************/ +const CO_OD_entry_t CO_OD[CO_OD_NoOfElements] = { +"); + + file.Write(write_od()); + + file.WriteLine("};"); + file.WriteLine("// clang-format on"); + + file.Close(); + } + + bool arrayspecialcase = false; + int arrayspecialcasecount = 0; + + string write_od() + { + + StringBuilder returndata = new StringBuilder(); + + foreach (KeyValuePair kvp in eds.ods) + { + + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true) + continue; + + returndata.Append(write_od_line(od)); + + + } + + return returndata.ToString(); + } + + protected string write_od_line(ODentry od) + { + StringBuilder sb = new StringBuilder(); + + string loc = "CO_OD_" + od.prop.CO_storageGroup; + + byte flags = getflags(od); + + int datasize = od.objecttype == ObjectType.REC ? 0 : (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); + + string array = ""; + + //only needed for array objects + if (od.objecttype == ObjectType.ARRAY && od.Nosubindexes > 0) + array = string.Format("[0]"); + + + if (arrayspecial(od.Index, true)) + { + arrayspecialcase = true; + arrayspecialcasecount = 0; + } + + if (arrayspecialcase) + { + array = string.Format("[{0}]", arrayspecialcasecount); + arrayspecialcasecount++; + } + + //Arrays and Recs have 1 less subindex than actually present in the od.subobjects + int nosubindexs = od.Nosubindexes; + if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.REC) + { + if (nosubindexs > 0) + nosubindexs--; + } + + //Arrays really should obey the max subindex parameter not the physical number of elements + if (od.objecttype == ObjectType.ARRAY) + { + if ((od.Getmaxsubindex() != nosubindexs)) + { + if (od.Index != 0x1003 && od.Index != 0x1011)//ignore 0x1003, it is a special case as per CANopen specs, and ignore 0x1011 CANopenNode uses special sub indexes for eeprom resets + { + Warnings.AddWarning(String.Format("Subindex discrepancy on object 0x{0:X4} arraysize: {1} vs max sub-index: {2}", od.Index, nosubindexs, od.Getmaxsubindex())); + } + + //0x1003 is a special case for CANopenNode + //SubIndex 0 will probably be 0 for no errors + //so we cannot read that to determine max subindex size, which is required to set up CANopenNode so we leave it alone here + //as its already set to subod.count + if (od.Index != 0x1003) + { + nosubindexs = od.Getmaxsubindex(); + } + } + } + + string pdata; //CO_OD_entry_t pData generator + + if (od.objecttype == ObjectType.REC) + { + + pdata = string.Format("&OD_record{0:X4}", od.Index); + } + else + { + pdata = string.Format("&{0}.{1}{2}", loc, make_cname(od.parameter_name,od), array); + } + + if ((od.objecttype == ObjectType.VAR || od.objecttype == ObjectType.ARRAY) && od.datatype == DataType.DOMAIN) + { + //NB domain MUST have a data pointer of 0, can open node requires this and makes checks + //against null to determine this is a DOMAIN type. + pdata = "0"; + } + + sb.AppendLine($"{{0x{od.Index:X4}, 0x{nosubindexs:X2}, 0x{flags:X2}, {datasize,2:#0}, (void*){pdata}}},"); + + if (arrayspecial(od.Index, false)) + { + arrayspecialcase = false; + } + + return sb.ToString(); + } + + /// + /// Get the CANopenNode specific flags, these flags are used internally in CANopenNode to determine details about the object variable + /// + /// An odentry to access + /// byte containing the flag value + public byte getflags(ODentry od) + { + byte flags = 0; + byte mapping = 0; //mapping flags, if pdo is enabled + + //aways return 0 for REC objects as CO_OD_getDataPointer() uses this to pickup the details + if (od.objecttype == ObjectType.REC) + return 0; + + switch((od.parent == null ? od : od.parent).prop.CO_storageGroup.ToUpper()) + { + case "ROM": + flags = 0x01; + break; + + case "RAM": + flags = 0x02; + break; + + case "EEPROM": + default: + flags = 0x03; + break; + } + + /* some exceptions for rwr/rww. Those are entries that are always r/w via SDO transfer, + * but can only be read -or- written via PDO */ + if (od.accesstype == EDSsharp.AccessType.ro + || od.accesstype == EDSsharp.AccessType.rw + || od.accesstype == EDSsharp.AccessType.rwr + || od.accesstype == EDSsharp.AccessType.rww + || od.accesstype == EDSsharp.AccessType.@const) + { + /* SDO server may read from the variable */ + flags |= 0x04; + + if (od.accesstype != EDSsharp.AccessType.rww) + { + /* Variable is mappable for TPDO */ + mapping |= 0x20; + } + } + if (od.accesstype == EDSsharp.AccessType.wo + || od.accesstype == EDSsharp.AccessType.rw + || od.accesstype == EDSsharp.AccessType.rwr + || od.accesstype == EDSsharp.AccessType.rww) + { + /* SDO server may write to the variable */ + flags |= 0x08; + + if (od.accesstype != EDSsharp.AccessType.rwr) + { + /* Variable is mappable for RPDO */ + mapping |= 0x10; + } + } + if (od.Index == 0x1003) { - /* SDO server may write to the variable */ + /* SDO server may write to the variable */ flags |= 0x08; - } - + } + switch (od.PDOtype) { case libEDSsharp.PDOMappingType.RPDO: mapping |= 0x10; break; @@ -1093,591 +1093,591 @@ public byte getflags(ODentry od) case libEDSsharp.PDOMappingType.optional: mapping |= 0x30; break; } - if (od.PDOMapping) - { - flags |= mapping; - } - - if(od.prop.CO_flagsPDO) - { - /* If variable is mapped to any PDO, then is automatically send, if variable its value */ - flags |=0x40; - } - - int datasize = (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); - - if (datasize > 1) - { - if (od.datatype == DataType.VISIBLE_STRING || - od.datatype == DataType.OCTET_STRING) - { - //#149 VISIBLE_STRING and OCTET_STRING are an arrays of 8 bit values, either VISIBLE_CHAR or UNSIGNED8 - //and therefor are NOT multi-byte - } - else - { - /* variable is a multi-byte value */ - flags |= 0x80; - } - } - - return flags; - } - - string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring=false) - { - try - { - int nobase = 10; - bool nodeidreplace = false; - - if (defaultvalue == null || defaultvalue == "") - { - //No default value, we better supply one for sensible data types - if (dt == DataType.VISIBLE_STRING || - dt == DataType.OCTET_STRING || - dt == DataType.UNKNOWN || - dt == DataType.UNICODE_STRING) - { - - if (fixstring == true) - return "'X'"; - - return ""; - } - - Console.WriteLine("Warning assuming a 0 default"); - defaultvalue = "0"; - } - - if (defaultvalue.Contains("$NODEID")) - { - defaultvalue = defaultvalue.Replace("$NODEID", ""); - defaultvalue = defaultvalue.Replace("+", ""); - nodeidreplace = true; - } - - String pat = @"^0[xX][0-9a-fA-FL]+"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 16; - defaultvalue = defaultvalue.Replace("L", ""); - } - - pat = @"^0[0-7]+"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 8; - } - - if (nodeidreplace) - { - UInt32 data = Convert.ToUInt32(defaultvalue, nobase); - data += eds.NodeId; - defaultvalue = string.Format("0x{0:X}", data); - nobase = 16; - } - - - switch (dt) - { - case DataType.UNSIGNED24: - case DataType.UNSIGNED32: - return String.Format("0x{0:X4}L", Convert.ToUInt32(defaultvalue, nobase)); - - case DataType.INTEGER24: - case DataType.INTEGER32: - return String.Format("0x{0:X4}L", Convert.ToInt32(defaultvalue, nobase)); - - case DataType.REAL32: - case DataType.REAL64: - return (String.Format("{0}", defaultvalue)); - - - //fix me this looks wrong - case DataType.UNICODE_STRING: - return (String.Format("'{0}'", defaultvalue)); - - case DataType.VISIBLE_STRING: - { - - ASCIIEncoding a = new ASCIIEncoding(); - string unescape = StringUnescape.Unescape(defaultvalue); - char[] chars = unescape.ToCharArray(); - - string array = "{"; - - foreach (char c in chars) - { - - array += "'" + StringUnescape.Escape(c) + "', "; - } - - array = array.Substring(0, array.Length - 2); - - array += "}"; - return array; - - } - - - case DataType.OCTET_STRING: - { - string[] bits = defaultvalue.Split(' '); - string octet = "{"; - foreach (string s in bits) - { - octet += formatvaluewithdatatype(s, DataType.UNSIGNED8); - - if (!object.ReferenceEquals(s, bits.Last())) - { - octet += ", "; - } - } - octet += "}"; - return octet; - } - - case DataType.INTEGER8: - return String.Format("0x{0:X1}", Convert.ToSByte(defaultvalue, nobase)); - - case DataType.INTEGER16: - return String.Format("0x{0:X2}", Convert.ToInt16(defaultvalue, nobase)); - - case DataType.UNSIGNED8: - return String.Format("0x{0:X1}L", Convert.ToByte(defaultvalue, nobase)); - - case DataType.UNSIGNED16: - return String.Format("0x{0:X2}", Convert.ToUInt16(defaultvalue, nobase)); - - case DataType.INTEGER64: - return String.Format("0x{0:X8}L", Convert.ToInt64(defaultvalue, nobase)); - - case DataType.UNSIGNED64: - return String.Format("0x{0:X8}L", Convert.ToUInt64(defaultvalue, nobase)); - - case DataType.TIME_DIFFERENCE: - case DataType.TIME_OF_DAY: - return String.Format("{{{0}}}", Convert.ToUInt64(defaultvalue, nobase)); - - default: - return (String.Format("{0:X}", defaultvalue)); - - } - } - catch(Exception) - { - Warnings.AddWarning(String.Format("Error converting value {0} to type {1}", defaultvalue, dt.ToString()),Warnings.warning_class.WARNING_BUILD); - return ""; - } - } - - public static string ParseString(string input) - { - var provider = new Microsoft.CSharp.CSharpCodeProvider(); - var parameters = new System.CodeDom.Compiler.CompilerParameters() - { - GenerateExecutable = false, - GenerateInMemory = true, - }; - - var code = @" - namespace Tmp - { - public class TmpClass - { - public static string GetValue() - { - return """ + input + @"""; - } - } - }"; - - var compileResult = provider.CompileAssemblyFromSource(parameters, code); - - if (compileResult.Errors.HasErrors) - { - throw new ArgumentException(compileResult.Errors.Cast().First(e => !e.IsWarning).ErrorText); - } - - var asmb = compileResult.CompiledAssembly; - var method = asmb.GetType("Tmp.TmpClass").GetMethod("GetValue"); - - return method.Invoke(null, null) as string; - } - - protected string make_cname(string name,ODentry entry) - { - if (name == null) - return null; - - if (name == "") - return ""; - - Regex splitter = new Regex(@"[\W]+"); - - //string[] bits = Regex.Split(name,@"[\W]+"); - var bits = splitter.Split(name).Where(s => s != String.Empty); - - string output = ""; - - char lastchar = ' '; - foreach (string s in bits) - { - if(Char.IsUpper(lastchar) && Char.IsUpper(s.First())) - output+="_"; - - if (s.Length > 1) - { - output += char.ToUpper(s[0]) + s.Substring(1); - } - else - { - output += s; - } - - if(output.Length>0) - lastchar = output.Last(); - - } - - if (output.Length > 1) - { - if (Char.IsLower(output[1])) - output = Char.ToLower(output[0]) + output.Substring(1); - } - else - output = output.ToLower(); //single character - - - UInt32 key = (UInt32)((entry.Index << 8) + entry.Subindex ); - - if ((entry.Index >= 0x1200) && (entry.Index < 0x1280)) - key = (UInt32)((0x1200 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1280) && (entry.Index < 0x1300)) - key = (UInt32)((0x1280 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1400) && (entry.Index < 0x1600)) - key = (UInt32)((0x1400 <<8) + entry.Subindex); - - if ((entry.Index >= 0x1600) && (entry.Index < 0x1800)) - key = (UInt32)((0x1600 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1800) && (entry.Index < 0x1a00)) - key = (UInt32)((0x1800 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1a00) && (entry.Index < 0x1c00)) - key = (UInt32)((0x1a00 << 8) + entry.Subindex); - - if (acceptable_canopen_names.ContainsKey(key) && !(entry.parent != null && entry.Subindex == 0)) - { - string newname = acceptable_canopen_names[key]; - if (output != newname) - Warnings.AddWarning(string.Format("Warning: index 0x{0:X4}/{1:X2} correcting name for CanOpenNode compatibility from {2} to {3}", entry.Index, entry.Subindex, output, newname),Warnings.warning_class.WARNING_RENAME); - output = newname; - } - - return output; - } - - /// - /// Export the record type objects in the CO_OD.c file - /// - /// string - protected string export_record_types() - { - StringBuilder returndata = new StringBuilder(); - - bool arrayopen = false; - int arrayindex = 0; - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - if (od.objecttype != ObjectType.REC) - continue; - - if (od.prop.CO_disabled == true) - continue; - - int count = od.subobjects.Count; //don't include index - - if(od.Index>=0x1400 && od.Index<0x1600) - { - //what is this doing for us? - //count = 3; //CANopenNode Fudging. Its only 3 parameters for RX PDOS in the c code despite being a PDO_COMMUNICATION_PARAMETER - } - - returndata.AppendLine($"/*0x{od.Index:X4}*/ const CO_OD_entryRecord_t OD_record{od.Index:X4}[{count}] = {{"); - - string arrayaccess = ""; - - if (arrayspecial(od.Index, true) || arrayopen) - { - arrayaccess = string.Format("[{0}]",arrayindex); - arrayindex++; - arrayopen = true; - } - - foreach (KeyValuePair kvpsub in od.subobjects) - { - returndata.Append(export_one_record_type(kvpsub.Value,arrayaccess)); - } - - if (arrayspecial(od.Index, false)) - { - arrayindex=0; - arrayopen = false; - } - - returndata.AppendLine($"}};{Environment.NewLine}"); - } - - return returndata.ToString(); - } - - /// - /// Exports a sub object line in a record object - /// - /// sub ODentry object to export - /// string forming current array level or empty string for none - /// string forming one line of CO_OD.c record objects - protected string export_one_record_type(ODentry sub,string arrayaccess) - { - - if (sub == null || sub.parent == null) - return ""; - - StringBuilder sb = new StringBuilder(); - - string cname = make_cname(sub.parent.parameter_name,sub.parent); - - string subcname = make_cname(sub.parameter_name,sub); - int datasize = (int)Math.Ceiling((double)sub.Sizeofdatatype() / (double)8.0); - - if (sub.datatype != DataType.DOMAIN) - { - sb.AppendLine($" {{(void*)&{"CO_OD_" + sub.parent.prop.CO_storageGroup}.{cname}{arrayaccess}.{subcname}, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); - } - else - { - //Domain type MUST have its data pointer set to 0 for CANopenNode - sb.AppendLine($" {{(void*)0, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); - } - - return sb.ToString(); - } - - - int noTXpdos = 0; - int noRXpdos = 0; - int noSDOclients = 0; - int noSDOservers = 0; - int distTXpdo = 0; - int distRXpdo = 0; - int noSYNC = 0; - int noEMCY = 0; - int noTIME = 0; - int noGFC = 0; - int noSRDO = 0; - - void countPDOS() - { - noRXpdos = 0; - noTXpdos = 0; - - //feature tests for default CanOpenNode build - //if you have a custom CanOpen.c then you may not require all these features - - //check the SYNC feature - int checkfeature = 0; - if (eds.ods.ContainsKey(0x1005)) - checkfeature++; - if (eds.ods.ContainsKey(0x1006)) - checkfeature++; - if (eds.ods.ContainsKey(0x1007)) - checkfeature++; - if (eds.ods.ContainsKey(0x1019)) - checkfeature++; - if (checkfeature == 4) - { - noSYNC = 1; - } - else - { - Warnings.AddWarning("BUILD WARNING, required objects for SYNC are not present 0x1005,0x1006,0x1007,0x1019",Warnings.warning_class.WARNING_BUILD); - } - - //EMCY - checkfeature = 0; - if (eds.ods.ContainsKey(0x1003)) - checkfeature++; - if (eds.ods.ContainsKey(0x1014)) - checkfeature++; - if (eds.ods.ContainsKey(0x1015)) - checkfeature++; - if (checkfeature == 3) - { - noEMCY = 1; - } - else - { - Warnings.AddWarning("BUILD WARNING, required objects for EMCY are not present 0x1003,0x1014,0x1015",Warnings.warning_class.WARNING_BUILD); - } - - //TIME - if (eds.ods.ContainsKey(0x1012)) - { - noTIME = 1; - } - else - { - //TIME is optional - } - - //NMT CLIENT - checkfeature = 0; - if (eds.ods.ContainsKey(0x1f80)) - checkfeature++; - if (eds.ods.ContainsKey(0x1029)) - checkfeature++; - if (eds.ods.ContainsKey(0x1017)) - checkfeature++; - if (eds.ods.ContainsKey(0x1001)) - checkfeature++; - if (checkfeature == 4) - { - //NMT Client is not optional - } - else - { - Warnings.AddWarning("BUILD WARNING, required objects for NMT Client are not present 0x1f80,0x1029,0x1017,0x1001",Warnings.warning_class.WARNING_BUILD); - } - - foreach (KeyValuePair kvp in eds.ods) - { - UInt16 index = kvp.Key; - - if (kvp.Value.prop.CO_disabled == true) - continue; - - if (index >= 0x1400 && index < 0x1600) - { - noRXpdos++; - distRXpdo = index - 0x1400; - } - - if (index >= 0x1800 && index < 0x1A00) - { - noTXpdos++; - distTXpdo = index - 0x1800; - } - - if((index & 0xFF80) == 0x1200) - { - noSDOservers++; - } - - if ((index & 0xFF80) == 0x1280) - { - noSDOclients++; - } - - if (index == 0x1300) - noGFC = 1; - - if (index >= 0x1301 && index <= 0x1340) - noSRDO++; - } - } - - bool arrayspecial(UInt16 index, bool open) - { - - if (open) - { - - if (openings.Contains(index)) - return true; - } - else - { - - if (closings.Contains(index)) - return true; - } - - return false; - } - - - string export_OD_def_array(string location) - { - - StringBuilder sb = new StringBuilder(); - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) - continue; - - if (od.Nosubindexes == 0) - { - sb.AppendLine($"/*{od.Index:X4}*/ {formatvaluewithdatatype(od.defaultvalue, od.datatype,true)},"); - } - else - { - if (arrayspecial(od.Index, true)) - { - sb.AppendFormat("/*{0:X4}*/ {{{{", od.Index); - } - else - { - sb.AppendFormat("/*{0:X4}*/ {{", od.Index); - } - - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry sub = kvp2.Value; - - DataType dt = sub.datatype; - - if ((od.objecttype==ObjectType.ARRAY) && kvp2.Key == 0) - continue; - - sb.Append(formatvaluewithdatatype(sub.defaultvalue, dt,true)); - - if (od.subobjects.Keys.Last() != kvp2.Key) - sb.Append(", "); - } - - if (arrayspecial(od.Index, false)) - { - sb.AppendLine("}},"); - } - else - { - sb.AppendLine("},"); - } - } - } - - return sb.ToString(); - } - } - - - - - - -} + if (od.PDOMapping) + { + flags |= mapping; + } + + if(od.prop.CO_flagsPDO) + { + /* If variable is mapped to any PDO, then is automatically send, if variable its value */ + flags |=0x40; + } + + int datasize = (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); + + if (datasize > 1) + { + if (od.datatype == DataType.VISIBLE_STRING || + od.datatype == DataType.OCTET_STRING) + { + //#149 VISIBLE_STRING and OCTET_STRING are an arrays of 8 bit values, either VISIBLE_CHAR or UNSIGNED8 + //and therefor are NOT multi-byte + } + else + { + /* variable is a multi-byte value */ + flags |= 0x80; + } + } + + return flags; + } + + string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring=false) + { + try + { + int nobase = 10; + bool nodeidreplace = false; + + if (defaultvalue == null || defaultvalue == "") + { + //No default value, we better supply one for sensible data types + if (dt == DataType.VISIBLE_STRING || + dt == DataType.OCTET_STRING || + dt == DataType.UNKNOWN || + dt == DataType.UNICODE_STRING) + { + + if (fixstring == true) + return "'X'"; + + return ""; + } + + Console.WriteLine("Warning assuming a 0 default"); + defaultvalue = "0"; + } + + if (defaultvalue.Contains("$NODEID")) + { + defaultvalue = defaultvalue.Replace("$NODEID", ""); + defaultvalue = defaultvalue.Replace("+", ""); + nodeidreplace = true; + } + + String pat = @"^0[xX][0-9a-fA-FL]+"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 16; + defaultvalue = defaultvalue.Replace("L", ""); + } + + pat = @"^0[0-7]+"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 8; + } + + if (nodeidreplace) + { + UInt32 data = Convert.ToUInt32(defaultvalue, nobase); + data += eds.NodeId; + defaultvalue = string.Format("0x{0:X}", data); + nobase = 16; + } + + + switch (dt) + { + case DataType.UNSIGNED24: + case DataType.UNSIGNED32: + return String.Format("0x{0:X4}L", Convert.ToUInt32(defaultvalue, nobase)); + + case DataType.INTEGER24: + case DataType.INTEGER32: + return String.Format("0x{0:X4}L", Convert.ToInt32(defaultvalue, nobase)); + + case DataType.REAL32: + case DataType.REAL64: + return (String.Format("{0}", defaultvalue)); + + + //fix me this looks wrong + case DataType.UNICODE_STRING: + return (String.Format("'{0}'", defaultvalue)); + + case DataType.VISIBLE_STRING: + { + + ASCIIEncoding a = new ASCIIEncoding(); + string unescape = StringUnescape.Unescape(defaultvalue); + char[] chars = unescape.ToCharArray(); + + string array = "{"; + + foreach (char c in chars) + { + + array += "'" + StringUnescape.Escape(c) + "', "; + } + + array = array.Substring(0, array.Length - 2); + + array += "}"; + return array; + + } + + + case DataType.OCTET_STRING: + { + string[] bits = defaultvalue.Split(' '); + string octet = "{"; + foreach (string s in bits) + { + octet += formatvaluewithdatatype(s, DataType.UNSIGNED8); + + if (!object.ReferenceEquals(s, bits.Last())) + { + octet += ", "; + } + } + octet += "}"; + return octet; + } + + case DataType.INTEGER8: + return String.Format("0x{0:X1}", Convert.ToSByte(defaultvalue, nobase)); + + case DataType.INTEGER16: + return String.Format("0x{0:X2}", Convert.ToInt16(defaultvalue, nobase)); + + case DataType.UNSIGNED8: + return String.Format("0x{0:X1}L", Convert.ToByte(defaultvalue, nobase)); + + case DataType.UNSIGNED16: + return String.Format("0x{0:X2}", Convert.ToUInt16(defaultvalue, nobase)); + + case DataType.INTEGER64: + return String.Format("0x{0:X8}L", Convert.ToInt64(defaultvalue, nobase)); + + case DataType.UNSIGNED64: + return String.Format("0x{0:X8}L", Convert.ToUInt64(defaultvalue, nobase)); + + case DataType.TIME_DIFFERENCE: + case DataType.TIME_OF_DAY: + return String.Format("{{{0}}}", Convert.ToUInt64(defaultvalue, nobase)); + + default: + return (String.Format("{0:X}", defaultvalue)); + + } + } + catch(Exception) + { + Warnings.AddWarning(String.Format("Error converting value {0} to type {1}", defaultvalue, dt.ToString()),Warnings.warning_class.WARNING_BUILD); + return ""; + } + } + + public static string ParseString(string input) + { + var provider = new Microsoft.CSharp.CSharpCodeProvider(); + var parameters = new System.CodeDom.Compiler.CompilerParameters() + { + GenerateExecutable = false, + GenerateInMemory = true, + }; + + var code = @" + namespace Tmp + { + public class TmpClass + { + public static string GetValue() + { + return """ + input + @"""; + } + } + }"; + + var compileResult = provider.CompileAssemblyFromSource(parameters, code); + + if (compileResult.Errors.HasErrors) + { + throw new ArgumentException(compileResult.Errors.Cast().First(e => !e.IsWarning).ErrorText); + } + + var asmb = compileResult.CompiledAssembly; + var method = asmb.GetType("Tmp.TmpClass").GetMethod("GetValue"); + + return method.Invoke(null, null) as string; + } + + protected string make_cname(string name,ODentry entry) + { + if (name == null) + return null; + + if (name == "") + return ""; + + Regex splitter = new Regex(@"[\W]+"); + + //string[] bits = Regex.Split(name,@"[\W]+"); + var bits = splitter.Split(name).Where(s => s != String.Empty); + + string output = ""; + + char lastchar = ' '; + foreach (string s in bits) + { + if(Char.IsUpper(lastchar) && Char.IsUpper(s.First())) + output+="_"; + + if (s.Length > 1) + { + output += char.ToUpper(s[0]) + s.Substring(1); + } + else + { + output += s; + } + + if(output.Length>0) + lastchar = output.Last(); + + } + + if (output.Length > 1) + { + if (Char.IsLower(output[1])) + output = Char.ToLower(output[0]) + output.Substring(1); + } + else + output = output.ToLower(); //single character + + + UInt32 key = (UInt32)((entry.Index << 8) + entry.Subindex ); + + if ((entry.Index >= 0x1200) && (entry.Index < 0x1280)) + key = (UInt32)((0x1200 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1280) && (entry.Index < 0x1300)) + key = (UInt32)((0x1280 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1400) && (entry.Index < 0x1600)) + key = (UInt32)((0x1400 <<8) + entry.Subindex); + + if ((entry.Index >= 0x1600) && (entry.Index < 0x1800)) + key = (UInt32)((0x1600 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1800) && (entry.Index < 0x1a00)) + key = (UInt32)((0x1800 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1a00) && (entry.Index < 0x1c00)) + key = (UInt32)((0x1a00 << 8) + entry.Subindex); + + if (acceptable_canopen_names.ContainsKey(key) && !(entry.parent != null && entry.Subindex == 0)) + { + string newname = acceptable_canopen_names[key]; + if (output != newname) + Warnings.AddWarning(string.Format("Warning: index 0x{0:X4}/{1:X2} correcting name for CanOpenNode compatibility from {2} to {3}", entry.Index, entry.Subindex, output, newname),Warnings.warning_class.WARNING_RENAME); + output = newname; + } + + return output; + } + + /// + /// Export the record type objects in the CO_OD.c file + /// + /// string + protected string export_record_types() + { + StringBuilder returndata = new StringBuilder(); + + bool arrayopen = false; + int arrayindex = 0; + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + if (od.objecttype != ObjectType.REC) + continue; + + if (od.prop.CO_disabled == true) + continue; + + int count = od.subobjects.Count; //don't include index + + if(od.Index>=0x1400 && od.Index<0x1600) + { + //what is this doing for us? + //count = 3; //CANopenNode Fudging. Its only 3 parameters for RX PDOS in the c code despite being a PDO_COMMUNICATION_PARAMETER + } + + returndata.AppendLine($"/*0x{od.Index:X4}*/ const CO_OD_entryRecord_t OD_record{od.Index:X4}[{count}] = {{"); + + string arrayaccess = ""; + + if (arrayspecial(od.Index, true) || arrayopen) + { + arrayaccess = string.Format("[{0}]",arrayindex); + arrayindex++; + arrayopen = true; + } + + foreach (KeyValuePair kvpsub in od.subobjects) + { + returndata.Append(export_one_record_type(kvpsub.Value,arrayaccess)); + } + + if (arrayspecial(od.Index, false)) + { + arrayindex=0; + arrayopen = false; + } + + returndata.AppendLine($"}};{Environment.NewLine}"); + } + + return returndata.ToString(); + } + + /// + /// Exports a sub object line in a record object + /// + /// sub ODentry object to export + /// string forming current array level or empty string for none + /// string forming one line of CO_OD.c record objects + protected string export_one_record_type(ODentry sub,string arrayaccess) + { + + if (sub == null || sub.parent == null) + return ""; + + StringBuilder sb = new StringBuilder(); + + string cname = make_cname(sub.parent.parameter_name,sub.parent); + + string subcname = make_cname(sub.parameter_name,sub); + int datasize = (int)Math.Ceiling((double)sub.Sizeofdatatype() / (double)8.0); + + if (sub.datatype != DataType.DOMAIN) + { + sb.AppendLine($" {{(void*)&{"CO_OD_" + sub.parent.prop.CO_storageGroup}.{cname}{arrayaccess}.{subcname}, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); + } + else + { + //Domain type MUST have its data pointer set to 0 for CANopenNode + sb.AppendLine($" {{(void*)0, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); + } + + return sb.ToString(); + } + + + int noTXpdos = 0; + int noRXpdos = 0; + int noSDOclients = 0; + int noSDOservers = 0; + int distTXpdo = 0; + int distRXpdo = 0; + int noSYNC = 0; + int noEMCY = 0; + int noTIME = 0; + int noGFC = 0; + int noSRDO = 0; + + void countPDOS() + { + noRXpdos = 0; + noTXpdos = 0; + + //feature tests for default CanOpenNode build + //if you have a custom CanOpen.c then you may not require all these features + + //check the SYNC feature + int checkfeature = 0; + if (eds.ods.ContainsKey(0x1005)) + checkfeature++; + if (eds.ods.ContainsKey(0x1006)) + checkfeature++; + if (eds.ods.ContainsKey(0x1007)) + checkfeature++; + if (eds.ods.ContainsKey(0x1019)) + checkfeature++; + if (checkfeature == 4) + { + noSYNC = 1; + } + else + { + Warnings.AddWarning("BUILD WARNING, required objects for SYNC are not present 0x1005,0x1006,0x1007,0x1019",Warnings.warning_class.WARNING_BUILD); + } + + //EMCY + checkfeature = 0; + if (eds.ods.ContainsKey(0x1003)) + checkfeature++; + if (eds.ods.ContainsKey(0x1014)) + checkfeature++; + if (eds.ods.ContainsKey(0x1015)) + checkfeature++; + if (checkfeature == 3) + { + noEMCY = 1; + } + else + { + Warnings.AddWarning("BUILD WARNING, required objects for EMCY are not present 0x1003,0x1014,0x1015",Warnings.warning_class.WARNING_BUILD); + } + + //TIME + if (eds.ods.ContainsKey(0x1012)) + { + noTIME = 1; + } + else + { + //TIME is optional + } + + //NMT CLIENT + checkfeature = 0; + if (eds.ods.ContainsKey(0x1f80)) + checkfeature++; + if (eds.ods.ContainsKey(0x1029)) + checkfeature++; + if (eds.ods.ContainsKey(0x1017)) + checkfeature++; + if (eds.ods.ContainsKey(0x1001)) + checkfeature++; + if (checkfeature == 4) + { + //NMT Client is not optional + } + else + { + Warnings.AddWarning("BUILD WARNING, required objects for NMT Client are not present 0x1f80,0x1029,0x1017,0x1001",Warnings.warning_class.WARNING_BUILD); + } + + foreach (KeyValuePair kvp in eds.ods) + { + UInt16 index = kvp.Key; + + if (kvp.Value.prop.CO_disabled == true) + continue; + + if (index >= 0x1400 && index < 0x1600) + { + noRXpdos++; + distRXpdo = index - 0x1400; + } + + if (index >= 0x1800 && index < 0x1A00) + { + noTXpdos++; + distTXpdo = index - 0x1800; + } + + if((index & 0xFF80) == 0x1200) + { + noSDOservers++; + } + + if ((index & 0xFF80) == 0x1280) + { + noSDOclients++; + } + + if (index == 0x1300) + noGFC = 1; + + if (index >= 0x1301 && index <= 0x1340) + noSRDO++; + } + } + + bool arrayspecial(UInt16 index, bool open) + { + + if (open) + { + + if (openings.Contains(index)) + return true; + } + else + { + + if (closings.Contains(index)) + return true; + } + + return false; + } + + + string export_OD_def_array(string location) + { + + StringBuilder sb = new StringBuilder(); + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) + continue; + + if (od.Nosubindexes == 0) + { + sb.AppendLine($"/*{od.Index:X4}*/ {formatvaluewithdatatype(od.defaultvalue, od.datatype,true)},"); + } + else + { + if (arrayspecial(od.Index, true)) + { + sb.AppendFormat("/*{0:X4}*/ {{{{", od.Index); + } + else + { + sb.AppendFormat("/*{0:X4}*/ {{", od.Index); + } + + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry sub = kvp2.Value; + + DataType dt = sub.datatype; + + if ((od.objecttype==ObjectType.ARRAY) && kvp2.Key == 0) + continue; + + sb.Append(formatvaluewithdatatype(sub.defaultvalue, dt,true)); + + if (od.subobjects.Keys.Last() != kvp2.Key) + sb.Append(", "); + } + + if (arrayspecial(od.Index, false)) + { + sb.AppendLine("}},"); + } + else + { + sb.AppendLine("},"); + } + } + } + + return sb.ToString(); + } + } + + + + + + +} From 47efa9e83a554f61e6b085406205085d38e46a75 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 08:29:30 +0200 Subject: [PATCH 024/226] - Initialization value corrected to "false" (xml reader sets only supported baud rates to "true" and leaves unsupported ones unchanged) --- libEDSsharp/eds.cs | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index fc8a8041..ac626de3 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -747,21 +747,21 @@ public class DeviceInfo : InfoSection public UInt32 RevisionNumber; [EdsExport] - public bool BaudRate_10 = true; + public bool BaudRate_10 = false; [EdsExport] - public bool BaudRate_20 = true; + public bool BaudRate_20 = false; [EdsExport] - public bool BaudRate_50 = true; + public bool BaudRate_50 = false; [EdsExport] - public bool BaudRate_125 = true; + public bool BaudRate_125 = false; [EdsExport] - public bool BaudRate_250 = true; + public bool BaudRate_250 = false; [EdsExport] - public bool BaudRate_500 = true; + public bool BaudRate_500 = false; [EdsExport] - public bool BaudRate_800 = true; + public bool BaudRate_800 = false; [EdsExport] - public bool BaudRate_1000 = true; + public bool BaudRate_1000 = false; public bool BaudRate_auto = false; @@ -2870,7 +2870,7 @@ static public int Getbase(string defaultvalue) nobase = 16; } - pat = @"^0[0-9]+"; + pat = @"^0[0-9]+"; r = new Regex(pat, RegexOptions.IgnoreCase); m = r.Match(defaultvalue); if (m.Success) From 9f41fc7b784dcc37ed9a647966f0732479cffd0f Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 08:33:11 +0200 Subject: [PATCH 025/226] - add inititialization --- EDSEditorGUI/DevicePDOView2.cs | 154 +++++++++++++++++---------------- 1 file changed, 80 insertions(+), 74 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 5dc88cfe..bbf0808b 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -22,9 +22,9 @@ public partial class DevicePDOView2 : MyTabUserControl StringCollection TXchoices = new StringCollection(); string[] srray; - PDOSlot selectedslot = null; - - CellBackColorAlternate viewNormal = new CellBackColorAlternate(Color.Khaki, Color.DarkKhaki); + PDOSlot selectedslot = null; + + CellBackColorAlternate viewNormal = new CellBackColorAlternate(Color.Khaki, Color.DarkKhaki); CellBackColorAlternate viewEmpty = new CellBackColorAlternate(Color.Gray, Color.Gray); CellBackColorAlternate viewCOB = new CellBackColorAlternate(Color.LightBlue, Color.Blue); @@ -51,23 +51,23 @@ public DevicePDOView2() grid1.Columns[1].Width = 45; grid1.Columns[2].Width = 50; - for (int x=0;x<64;x++) + for (int x = 0; x < 64; x++) { - grid1[0, 3+x] = new MyHeader(string.Format("{0}",x)); + grid1[0, 3 + x] = new MyHeader(string.Format("{0}", x)); } for (int x = 0; x < 8; x++) { - grid1[1, 3 + x*8] = new MyHeader(string.Format("Byte {0}", x)); + grid1[1, 3 + x * 8] = new MyHeader(string.Format("Byte {0}", x)); grid1[1, 3 + x * 8].ColumnSpan = 8; grid1[1, 3 + x * 8].View.BackColor = Color.Red; } - grid1.Rows[0].Height = 30; - - + grid1.Rows[0].Height = 30; + + contextMenuStrip_removeitem.ItemClicked += ContextMenuStrip_removeitem_ItemClicked; Invalidated += DevicePDOView2_Invalidated; @@ -97,14 +97,14 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte switch (e.ClickedItem.Tag) { - case "remove": - location.slot.Mapping.Remove(location.entry); - + case "remove": + location.slot.Mapping.Remove(location.entry); + break; - case "insert": - ODentry od = new ODentry(); - location.slot.Mapping.Insert(location.ordinal, eds.dummy_ods[0x002]); + case "insert": + ODentry od = new ODentry(); + location.slot.Mapping.Insert(location.ordinal, eds.dummy_ods[0x002]); break; } @@ -118,9 +118,9 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte private void Vcc_ValueChangedEvent(object sender, EventArgs e) { - SourceGrid.CellContext cell = (SourceGrid.CellContext)sender; - - // "0x3100/05/BUTTONS2" + SourceGrid.CellContext cell = (SourceGrid.CellContext)sender; + + // "0x3100/05/BUTTONS2" string[] bits = cell.Value.ToString().Split('/'); UInt16 newindex = EDSsharp.ConvertToUInt16(bits[0]); @@ -133,12 +133,12 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) PDOlocator location = (PDOlocator)((SourceGrid.Cells.Cell)cell.Cell).Tag; PDOSlot slot = location.slot; - ODentry newentry = null; - + ODentry newentry = null; + if (eds.tryGetODEntry(newindex, out newentry)) { if (newsubindex != 0) - newentry = newentry.subobjects[newsubindex]; + newentry = newentry.subobjects[newsubindex]; } else { @@ -160,7 +160,7 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) UpdatePDOinfo(); } - SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P , out int foundrow,out int foundcol) + SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P, out int foundrow, out int foundcol) { int y = 0; int y2 = 0; @@ -204,21 +204,21 @@ private void Grid1_Click(object sender, EventArgs e) MouseEventArgs ma = (MouseEventArgs)e; int foundrow, foundcol; - SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(ma.Location,out foundrow, out foundcol); + SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(ma.Location, out foundrow, out foundcol); grid1.Selection.ResetSelection(false); grid1.Selection.SelectRow(foundrow, true); - if(ma.Button==MouseButtons.Right) + if (ma.Button == MouseButtons.Right) { RightClickPoint = ma.Location; //Show context menu - contextMenuStrip_removeitem.Show(grid1,ma.Location); + contextMenuStrip_removeitem.Show(grid1, ma.Location); } - else if(foundrow>1) //don't select headers or bits + else if (foundrow > 1) //don't select headers or bits { var obj = grid1.Rows[foundrow]; - if(obj.Tag!=null) + if (obj.Tag != null) { PDOSlot slot = (PDOSlot)obj.Tag; @@ -239,10 +239,10 @@ private void Grid1_Click(object sender, EventArgs e) button_savepdochanges.Enabled = true; //Is invalid bit set - checkBox_invalidpdo.Checked = slot.invalid; - - - + checkBox_invalidpdo.Checked = slot.invalid; + + + } } @@ -261,9 +261,9 @@ public void Init(bool isTX) } } - public libEDSsharp.EDSsharp eds; - - + public libEDSsharp.EDSsharp eds; + + public void addPDOchoices() { @@ -340,7 +340,7 @@ public void updateslotdisplay() } - public void UpdatePDOinfo(bool updatechoices=true) + public void UpdatePDOinfo(bool updatechoices = true) { updateslotdisplay(); @@ -348,13 +348,13 @@ public void UpdatePDOinfo(bool updatechoices=true) if (eds == null) return; - if(updatechoices) + if (updatechoices) addPDOchoices(); - if(grid1.RowsCount>2) - grid1.Rows.RemoveRange(2, grid1.RowsCount - 2); - - + if (grid1.RowsCount > 2) + grid1.Rows.RemoveRange(2, grid1.RowsCount - 2); + + TXchoices.Clear(); foreach (ODentry od in eds.dummy_ods.Values) @@ -417,10 +417,10 @@ public void UpdatePDOinfo(bool updatechoices=true) continue; grid1.Redim(grid1.RowsCount + 1, grid1.ColumnsCount); - grid1.Rows[grid1.RowsCount-1].Tag = slot; - grid1.Rows[row+2].Height = 30; + grid1.Rows[grid1.RowsCount - 1].Tag = slot; + grid1.Rows[row + 2].Height = 30; - grid1[row+2,0] = new SourceGrid.Cells.Cell(String.Format("{0}", row + 1), typeof(string)); + grid1[row + 2, 0] = new SourceGrid.Cells.Cell(String.Format("{0}", row + 1), typeof(string)); grid1[row + 2, 1] = new SourceGrid.Cells.Cell(String.Format("{0:x}", slot.COB), typeof(string)); grid1[row + 2, 2] = new SourceGrid.Cells.Cell(String.Format("{0:x}", slot.ConfigurationIndex), typeof(string)); @@ -432,11 +432,11 @@ public void UpdatePDOinfo(bool updatechoices=true) int ordinal = 0; foreach (ODentry entry in slot.Mapping) { - { + { string target = slot.getTargetName(entry); - grid1[row+2, bitoff+3] = new SourceGrid.Cells.Cell(target, comboStandard); + grid1[row + 2, bitoff + 3] = new SourceGrid.Cells.Cell(target, comboStandard); grid1[row + 2, bitoff + 3].ColumnSpan = entry.Sizeofdatatype(); - grid1[row+2, bitoff+3].View = viewNormal; + grid1[row + 2, bitoff + 3].View = viewNormal; PDOlocator location = new PDOlocator(); location.slot = slot; @@ -458,7 +458,7 @@ public void UpdatePDOinfo(bool updatechoices=true) } //Pad out with an empty combo - if(bitoff<64) + if (bitoff < 64) { grid1[row + 2, bitoff + 3] = new SourceGrid.Cells.Cell("Empty", comboStandard); int colspan = 64 - bitoff; @@ -491,8 +491,8 @@ private void ComboStandard_Changed(object sender, EventArgs e) } public void redrawtable() - { - + { + } private class MyHeader : SourceGrid.Cells.ColumnHeader @@ -506,7 +506,7 @@ public MyHeader(object value) : base(value) view.BackColor = Color.Red; string text = value.ToString(); - if(text=="0"||text=="8"||text=="16"||text=="24"||text=="32"||text=="40"||text=="48"||text=="56") + if (text == "0" || text == "8" || text == "16" || text == "24" || text == "32" || text == "40" || text == "48" || text == "56") { view.ForeColor = Color.Red; } @@ -526,7 +526,7 @@ private class PDOlocator public override string ToString() { string msg; - msg = String.Format("Ordinal {0} , slot {1} entry {2}", ordinal, slot.ToString(), entry==null?"NULL":entry.ToString()); + msg = String.Format("Ordinal {0} , slot {1} entry {2}", ordinal, slot.ToString(), entry == null ? "NULL" : entry.ToString()); return msg; } @@ -547,7 +547,7 @@ private void button_down_Click(object sender, EventArgs e) Console.WriteLine("New Width " + newwidth.ToString()); - for(int x=0;x<64;x++) + for (int x = 0; x < 64; x++) { grid1.Columns[x + 3].Width = newwidth; } @@ -601,14 +601,14 @@ protected override void PrepareView(SourceGrid.CellContext context) } private void listView_TXPDO_ItemDrag(object sender, ItemDragEventArgs e) - { - - + { + + List entries = new List(); - foreach(ListViewItem item in listView_TXPDO.SelectedItems) + foreach (ListViewItem item in listView_TXPDO.SelectedItems) { - if(item.Tag.GetType() == typeof(ODentry)) + if (item.Tag.GetType() == typeof(ODentry)) entries.Add((ODentry)item.Tag); } @@ -616,18 +616,18 @@ private void listView_TXPDO_ItemDrag(object sender, ItemDragEventArgs e) data.SetData(entries.ToArray()); listView_TXPDO.DoDragDrop(data, DragDropEffects.Copy); - } - - - + } + + + private void grid1_DragOver(object sender, DragEventArgs e) { Point p = grid1.PointToClient(new Point(e.X, e.Y)); int foundrow, foundcol; - SourceGrid.Cells.Cell cell = (SourceGrid.Cells.Cell)getItemAtGridPoint(p,out foundrow,out foundcol); + SourceGrid.Cells.Cell cell = (SourceGrid.Cells.Cell)getItemAtGridPoint(p, out foundrow, out foundcol); - if(cell==null || cell.Tag==null) + if (cell == null || cell.Tag == null) { e.Effect = DragDropEffects.None; } @@ -648,7 +648,7 @@ private void grid1_DragDrop(object sender, DragEventArgs e) SourceGrid.Cells.Cell cell = (SourceGrid.Cells.Cell)getItemAtGridPoint(p, out foundrow, out foundcol); - ODentry[] entries = (ODentry[]) e.Data.GetData(typeof(ODentry[])); + ODentry[] entries = (ODentry[])e.Data.GetData(typeof(ODentry[])); PDOlocator location = (PDOlocator)cell.Tag; if (location == null || entries == null) @@ -656,7 +656,7 @@ private void grid1_DragDrop(object sender, DragEventArgs e) foreach (ODentry entry in entries) { - location.slot.insertMapping(location.ordinal, entry); + location.slot.insertMapping(location.ordinal, entry); } helper.buildmappingsfromlists(); @@ -680,8 +680,8 @@ public override void OnValueChanged(CellContext sender, EventArgs e) handler?.Invoke(sender, e); base.OnValueChanged(sender, e); - } - + } + } private void button_deletePDO_Click(object sender, EventArgs e) @@ -689,7 +689,7 @@ private void button_deletePDO_Click(object sender, EventArgs e) if (selectedslot == null) return; - if (MessageBox.Show(string.Format("Are you sure you wish to delete the entire PDO 0x{0:x4}/0x{1:x4}",selectedslot.ConfigurationIndex,selectedslot.MappingIndex), "Are you sure", MessageBoxButtons.YesNo) == DialogResult.Yes) + if (MessageBox.Show(string.Format("Are you sure you wish to delete the entire PDO 0x{0:x4}/0x{1:x4}", selectedslot.ConfigurationIndex, selectedslot.MappingIndex), "Are you sure", MessageBoxButtons.YesNo) == DialogResult.Yes) { helper.pdoslots.Remove(selectedslot); @@ -740,9 +740,9 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) UInt16 config = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_slot.Text); - if(!isTXPDO) + if (!isTXPDO) { - if(config<0x1400 | config >= 0x1600) + if (config < 0x1400 | config >= 0x1600) { MessageBox.Show(string.Format("Invalid TXPDO Communication parameters index 0x{0:x4}", config)); return; @@ -755,20 +755,26 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) MessageBox.Show(string.Format("Invalid RXPDO Communication parameters index 0x{0:x4}", config)); return; } - } - + } + UInt16 inhibit = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_inhibit.Text); UInt16 eventtimer = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_eventtimer.Text); + UInt32 COB = libEDSsharp.EDSsharp.ConvertToUInt32(textBox_cob.Text); byte syncstart = libEDSsharp.EDSsharp.ConvertToByte(textBox_syncstart.Text); byte transmissiontype = libEDSsharp.EDSsharp.ConvertToByte(textBox_type.Text); selectedslot.ConfigurationIndex = config; + selectedslot.COB = COB; + selectedslot.inhibit = inhibit; + selectedslot.eventtimer = eventtimer; + selectedslot.syncstart = syncstart; + selectedslot.transmissiontype = transmissiontype; try { helper.buildmappingsfromlists(); } - catch(Exception ex) + catch (Exception ex) { MessageBox.Show(ex.ToString()); } @@ -779,4 +785,4 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) } -} +} \ No newline at end of file From ba4548ed778b994217fd122a824f89a6bffd25e5 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 08:50:32 +0200 Subject: [PATCH 026/226] - add access initialization --- libEDSsharp/PDOHelper.cs | 84 ++++++++++++++++++++++++---------------- 1 file changed, 51 insertions(+), 33 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 0ac0304e..5271452d 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -16,33 +16,34 @@ public class PDOSlot public ushort ConfigurationIndex { get { return _ConfigurationIndex; } - set { + set + { - if(value==0) + if (value == 0) { _ConfigurationIndex = 0; _MappingIndex = 0; return; } - if ( ((value >= 0x1400) && (value < 0x1600)) || ((value >=0x1800) && (value <0x1a00)) ) + if (((value >= 0x1400) && (value < 0x1600)) || ((value >= 0x1800) && (value < 0x1a00))) { _ConfigurationIndex = value; _MappingIndex = (UInt16)(_ConfigurationIndex + (UInt16)0x200); } else { throw new ArgumentOutOfRangeException("Configuration Index", "Must be between 0x1400 and 0x17FF"); - } - - + } + + } } public ushort MappingIndex { get { return _MappingIndex; } - } - + } + public EDSsharp.AccessType mappingAccessType; public EDSsharp.AccessType configAccessType; public string mappingloc; @@ -73,8 +74,8 @@ public bool invalid else COB = COB & 0x0FFFFFFF; } - } - + } + public List Mapping = new List(); public UInt16 inhibit; @@ -84,6 +85,9 @@ public bool invalid public PDOSlot() { + configloc = "PERSIST_COMM"; + mappingloc = "PERSIST_COMM"; + transmissiontype = 254; Mapping = new List(); } @@ -129,7 +133,7 @@ public string getTargetName(ODentry od) public void insertMapping(int ordinal, ODentry entry) { int size = 0; - foreach(ODentry e in Mapping) + foreach (ODentry e in Mapping) { size += e.Sizeofdatatype(); } @@ -137,7 +141,7 @@ public void insertMapping(int ordinal, ODentry entry) if (size + entry.Sizeofdatatype() > 64) return; - Mapping.Insert(ordinal,entry); + Mapping.Insert(ordinal, entry); } } @@ -158,8 +162,8 @@ public PDOHelper(EDSsharp eds) public void build_PDOlists() { //List odl = new List(); - build_PDOlist(0x1800,pdoslots); - build_PDOlist(0x1400,pdoslots); + build_PDOlist(0x1800, pdoslots); + build_PDOlist(0x1400, pdoslots); } @@ -187,15 +191,15 @@ public void build_PDOlist(UInt16 startcob, List slots) slot.COB = eds.GetNodeID(od.subobjects[1].defaultvalue, out nodeidpresent); if (od.Containssubindex(2)) - slot.transmissiontype = EDSsharp.ConvertToByte(od.Getsubobject(2).defaultvalue); - + slot.transmissiontype = EDSsharp.ConvertToByte(od.Getsubobject(2).defaultvalue); + if (od.Containssubindex(3)) slot.inhibit = EDSsharp.ConvertToUInt16(od.Getsubobject(3).defaultvalue); if (od.Containssubindex(5)) slot.eventtimer = EDSsharp.ConvertToUInt16(od.Getsubobject(5).defaultvalue); - if (od.Containssubindex(6)) + if (od.Containssubindex(6)) slot.syncstart = EDSsharp.ConvertToByte(od.Getsubobject(6).defaultvalue); slot.ConfigurationIndex = idx; @@ -209,7 +213,7 @@ public void build_PDOlist(UInt16 startcob, List slots) //Look at mappings ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); - if(mapping==null) + if (mapping == null) { Console.WriteLine(string.Format("No mapping for index 0x{0:x4} should be at 0x{1:x4}", idx, idx + 0x200)); continue; @@ -220,7 +224,7 @@ public void build_PDOlist(UInt16 startcob, List slots) slot.mappingAccessType = od.accesstype; slot.mappingloc = od.prop.CO_storageGroup; - for (ushort subindex= 1; subindex<= mapping.Getmaxsubindex();subindex++) + for (ushort subindex = 1; subindex <= mapping.Getmaxsubindex(); subindex++) { ODentry sub = mapping.Getsubobject(subindex); if (sub == null) @@ -291,13 +295,13 @@ public void build_PDOlist(UInt16 startcob, List slots) ///
public void buildmappingsfromlists() { - for(ushort x=0x1400;x<0x1c00;x++) + for (ushort x = 0x1400; x < 0x1c00; x++) { if (eds.ods.ContainsKey(x)) eds.ods.Remove(x); } - foreach(PDOSlot slot in pdoslots) + foreach (PDOSlot slot in pdoslots) { ODentry config = new ODentry(); @@ -308,7 +312,8 @@ public void buildmappingsfromlists() ODentry sub = new ODentry("max sub-index", (ushort)slot.ConfigurationIndex, 0); sub.defaultvalue = "6"; sub.datatype = DataType.UNSIGNED8; - config.addsubobject(0x00,sub); + sub.accesstype = EDSsharp.AccessType.ro; + config.addsubobject(0x00, sub); config.accesstype = slot.configAccessType; config.prop.CO_storageGroup = slot.configloc; @@ -318,61 +323,71 @@ public void buildmappingsfromlists() { config.parameter_name = "TPDO communication parameter"; + config.prop.CO_countLabel = "TPDO"; sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = slot.COB.ToHexString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); sub = new ODentry("inhibit time", (ushort)slot.ConfigurationIndex, 3); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.inhibit.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x03, sub); sub = new ODentry("compatibility entry", (ushort)slot.ConfigurationIndex, 4); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = "0"; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x04, sub); sub = new ODentry("event timer", (ushort)slot.ConfigurationIndex, 5); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.eventtimer.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x05, sub); sub = new ODentry("SYNC start value", (ushort)slot.ConfigurationIndex, 6); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.syncstart.ToString(); ; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x06, sub); } else { config.parameter_name = "RPDO communication parameter"; + config.prop.CO_countLabel = "RPDO"; sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = slot.COB.ToHexString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); } - eds.ods.Add(slot.ConfigurationIndex,config); + eds.ods.Add(slot.ConfigurationIndex, config); ODentry mapping = new ODentry(); mapping.Index = slot.MappingIndex; mapping.datatype = DataType.PDO_MAPPING; mapping.objecttype = ObjectType.REC; - if(slot.isTXPDO()) + if (slot.isTXPDO()) mapping.parameter_name = "TPDO mapping parameter"; else mapping.parameter_name = "RPDO mapping parameter"; @@ -383,21 +398,23 @@ public void buildmappingsfromlists() sub = new ODentry("Number of mapped objects", (ushort)slot.MappingIndex, 0); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.Mapping.Count().ToString(); + sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(0x00, sub); byte mappingcount = 1; foreach (ODentry mapslot in slot.Mapping) { - sub = new ODentry(String.Format("Mapped object {0:x}",mappingcount), (ushort)slot.MappingIndex, mappingcount); + sub = new ODentry(String.Format("Mapped object {0:x}", mappingcount), (ushort)slot.MappingIndex, mappingcount); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = string.Format("0x{0:x4}{1:x2}{2:x2}", mapslot.Index, mapslot.Subindex, mapslot.Sizeofdatatype()); + sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(mappingcount, sub); mappingcount++; } - eds.ods.Add(slot.MappingIndex,mapping); - + eds.ods.Add(slot.MappingIndex, mapping); + } } @@ -408,10 +425,10 @@ public void buildmappingsfromlists() public void addPDOslot(UInt16 configindex) { //quick range check, it must be a config index for an RXPDO or a TXPDO - if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=0x1600) && (configindex<0x1800))) // true if not in range 0x1400...0x15FF OR 0x1800...0x19FF + if ((configindex < 0x1400) || (configindex >= 0x1a00) || ((configindex >= 0x1600) && (configindex < 0x1800))) // true if not in range 0x1400...0x15FF OR 0x1800...0x19FF return; - foreach(PDOSlot slot in pdoslots) + foreach (PDOSlot slot in pdoslots) { if (slot.ConfigurationIndex == configindex) return; @@ -422,6 +439,7 @@ public void addPDOslot(UInt16 configindex) PDOSlot newslot = new PDOSlot(); newslot.ConfigurationIndex = configindex; + newslot.COB = 0x180; //Fixme need a better default??? pdoslots.Add(newslot); @@ -440,10 +458,10 @@ public UInt16 findPDOslotgap(bool isTXPDO) if (isTXPDO) startindex = 0x1800; - for(UInt16 index = startindex; index<(startindex+0x200);index++) + for (UInt16 index = startindex; index < (startindex + 0x200); index++) { bool found = false; - foreach(PDOSlot slot in pdoslots) + foreach (PDOSlot slot in pdoslots) { if (slot.ConfigurationIndex == index) { @@ -452,7 +470,7 @@ public UInt16 findPDOslotgap(bool isTXPDO) } } - if(found==false) + if (found == false) { return index; } @@ -462,4 +480,4 @@ public UInt16 findPDOslotgap(bool isTXPDO) return 0x0000; } } -} +} \ No newline at end of file From b41e3904e046e8f8d8704b5977de873adc6f5b38 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 08:54:32 +0200 Subject: [PATCH 027/226] - Initialization value corrected to "false" (xml reader sets only supported baud rates to "true" and leaves unsupported ones unchanged) # Conflicts: # libEDSsharp/eds.cs --- libEDSsharp/eds.cs | 6460 ++++++++++++++++++++++---------------------- 1 file changed, 3230 insertions(+), 3230 deletions(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 5f845a5c..a3722158 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1,3231 +1,3231 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.IO; -using System.Text.RegularExpressions; -using System.Globalization; -using System.Reflection; -using CanOpenXSD_1_1; - -namespace libEDSsharp -{ - - - public enum DataType - { - UNKNOWN = 0, - BOOLEAN = 1, - INTEGER8 = 2, - INTEGER16 = 3, - INTEGER32 = 4, - UNSIGNED8 = 5, - UNSIGNED16 = 6, - UNSIGNED32 = 7, - REAL32 = 8, - VISIBLE_STRING = 9, - OCTET_STRING = 0x0A, - UNICODE_STRING = 0x0B, - TIME_OF_DAY = 0x0C, - TIME_DIFFERENCE = 0x0D, - DOMAIN = 0x0F, - INTEGER24 = 0x10, - REAL64 = 0x11, - INTEGER40 = 0x12, - INTEGER48 = 0x13, - INTEGER56 = 0x14, - INTEGER64 = 0x15, - UNSIGNED24 = 0x16, - UNSIGNED40 = 0x18, - UNSIGNED48 = 0x19, - UNSIGNED56 = 0x1A, - UNSIGNED64 = 0x1B, - - PDO_COMMUNICATION_PARAMETER = 0x20, //PDO_CommPar - PDO_MAPPING = 0x21, //PDO_Mapping - SDO_PARAMETER = 0x22, - IDENTITY = 0x23, - - } - - public enum ObjectType - { - UNKNOWN = -1, - NULL = 0, - DOMAIN =2, - DEFTYPE=5, - DEFSTRUCT=6, - VAR = 7, - ARRAY = 8, - REC = 9, - } - - public enum PDOMappingType - { - no=0, - optional=1, - RPDO=2, - TPDO=3, - @default=4, - } - - public enum AccessSDO - { - no, - ro, - wo, - rw - } - - public enum AccessPDO - { - no, - t, - r, - tr - } - - public enum AccessSRDO - { - no = 0, - tx = 1, - rx = 2, - trx = 3 - } - - /// - /// Custom properties for OD entry or sub-entry, which are saved into xdd file v1.1 - /// - public class CustomProperties - { - public bool CO_disabled = false; // If true, object is completelly skipped by CANopenNode exporters, etc. - public string CO_countLabel = ""; - public string CO_storageGroup = "RAM"; - public bool CO_flagsPDO = false; - public AccessSRDO CO_accessSRDO = AccessSRDO.no; - public UInt32 CO_stringLengthMin = 0; - - public CustomProperties Clone() - { - return new CustomProperties - { - CO_disabled = CO_disabled, - CO_countLabel = CO_countLabel, - CO_storageGroup = CO_storageGroup, - CO_flagsPDO = CO_flagsPDO, - CO_accessSRDO = CO_accessSRDO, - CO_stringLengthMin = CO_stringLengthMin - }; - } - - public void OdeXdd(property[] properties) - { - if (properties != null) - { - foreach (property prop in properties) - { - switch (prop.name) - { - case "CO_disabled": CO_disabled = prop.value == "true"; break; - case "CO_countLabel": CO_countLabel = prop.value ?? ""; break; - case "CO_storageGroup": CO_storageGroup = prop.value ?? ""; break; - case "CO_flagsPDO": CO_flagsPDO = prop.value == "true"; break; - case "CO_accessSRDO": - try { CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), prop.value); } - catch (Exception) { CO_accessSRDO = AccessSRDO.no; } - break; - case "CO_stringLengthMin": - try { CO_stringLengthMin = Convert.ToUInt16(prop.value); } - catch (Exception) { CO_stringLengthMin = 0; } - break; - } - } - } - } - - public property[] OdeXdd() - { - var props = new List(); - - if (CO_disabled) - props.Add(new property { name = "CO_disabled", value = "true" }); - if (CO_countLabel != "") - props.Add(new property { name = "CO_countLabel", value = CO_countLabel }); - if (CO_storageGroup != "RAM") - props.Add(new property { name = "CO_storageGroup", value = CO_storageGroup }); - if (CO_flagsPDO) - props.Add(new property { name = "CO_flagsPDO", value = "true" }); - - return props.ToArray(); - } - - public property[] SubOdeXdd() - { - var props = new List(); - - if (CO_accessSRDO != AccessSRDO.no) - props.Add(new property { name = "CO_accessSRDO", value = CO_accessSRDO.ToString() }); - if (CO_stringLengthMin != 0) - props.Add(new property { name = "CO_stringLengthMin", value = CO_stringLengthMin.ToString() }); - - return props.ToArray(); - } - } - - /// - /// List of multiple CO_storageGroup strings available in project - /// - public class CO_storageGroups : List - { - public CO_storageGroups() - { - Add("RAM"); // default value - } - - public new void Add(string item) - { - if (!Contains(item)) - { - base.Add(item); - } - } - } - - public class EdsExport : Attribute - { - public UInt16 maxlength; - public bool commentonly=false; - - //mehmeh - public EdsExport() - { - } - - public EdsExport(UInt16 maxlength) - { - this.maxlength = maxlength; - } - - public bool IsReadOnly() - { - return commentonly; - } - - - } - - public class DcfExport : EdsExport - { - } - - public class InfoSection - { - protected Dictionary section; - - protected string infoheader; - protected string edssection; - - public enum Filetype - { - File_EDS, - File_DCF - } - - public virtual void Parse(Dictionary section,string sectionname) - { - - this.section = section; - - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - if(Attribute.IsDefined(f, typeof(EdsExport))) - GetField(f.Name, f.Name); - - if (Attribute.IsDefined(f, typeof(DcfExport))) - GetField(f.Name, f.Name); - } - - } - - public bool GetField(string name, string varname) - { - FieldInfo f = null; - - try - { - foreach (var element in section) - { - if (String.Equals(element.Key, name, StringComparison.OrdinalIgnoreCase)) - { - - name = element.Key; - Type tx = this.GetType(); - - f = tx.GetField(varname); - object var = null; - - switch (f.FieldType.Name) - { - case "String": - var = section[name]; - break; - - case "UInt32": - var = Convert.ToUInt32(section[name], EDSsharp.Getbase(section[name])); - break; - - case "Int16": - var = Convert.ToInt16(section[name], EDSsharp.Getbase(section[name])); - break; - - case "UInt16": - var = Convert.ToUInt16(section[name], EDSsharp.Getbase(section[name])); - break; - - case "Byte": - var = Convert.ToByte(section[name], EDSsharp.Getbase(section[name])); - break; - - case "Boolean": - var = section[name] == "1"; //because Convert is Awesome - break; - - default: - Console.WriteLine(String.Format("Unhanded variable {0} for {1}", f.FieldType.Name, varname)); - break; - } - - if (var != null) - { - tx.GetField(varname).SetValue(this, var); - return true; - } - } - } - } - catch (Exception e) - { - if (e is OverflowException) - { - Warnings.warning_list.Add(string.Format("Warning parsing {0} tried to fit {1} into {2}", name, section[name], f.FieldType.Name)); - } - } - - return false; - } - - public override string ToString() - { - string msg; - - msg = $"*****************************************************{Environment.NewLine}"; - msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; - msg += $"*****************************************************{Environment.NewLine}"; - - Type tx = this.GetType(); - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - msg += $"{f.Name,-28}: {f.GetValue(this).ToString()}{Environment.NewLine}"; - } - - return msg; - } - - public void Write(StreamWriter writer, Filetype ft) - { - writer.WriteLine("[" + edssection + "]"); - Type tx = this.GetType(); - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - - if ((ft==Filetype.File_EDS) && (!Attribute.IsDefined(f, typeof(EdsExport)))) - continue; - - if ((ft == Filetype.File_DCF) && (!(Attribute.IsDefined(f, typeof(DcfExport)) || Attribute.IsDefined(f, typeof(EdsExport))))) - continue; - - if (f.GetValue(this) == null) - continue; - - EdsExport ex = (EdsExport)f.GetCustomAttribute(typeof(EdsExport)); - - bool comment = ex.IsReadOnly(); - - if (f.FieldType.Name == "Boolean") - { - writer.WriteLine(string.Format("{2}{0}={1}", f.Name, ((bool)f.GetValue(this)) == true ? 1 : 0,comment==true?";":"")); - } - else - { - writer.WriteLine(string.Format("{2}{0}={1}", f.Name, f.GetValue(this).ToString(), comment == true ? ";" : "")); - } - } - - writer.WriteLine(""); - - } - - } - - - public class MandatoryObjects : SupportedObjects - { - public MandatoryObjects() - : base() - { - infoheader = "Mandatory Objects"; - edssection = "MandatoryObjects"; - } - - public MandatoryObjects(Dictionary section) - : this() - { - Parse(section); - } - } - - public class OptionalObjects : SupportedObjects - { - public OptionalObjects() - : base() - { - infoheader = "Optional Objects"; - edssection = "OptionalObjects"; - } - - public OptionalObjects(Dictionary section) - : this() - { - Parse(section); - } - } - - public class ManufacturerObjects : SupportedObjects - { - public ManufacturerObjects() : base() - { - infoheader = "Manufacturer Objects"; - edssection = "ManufacturerObjects"; - } - - public ManufacturerObjects(Dictionary section) - : this() - { - Parse(section); - } - } - - public class TypeDefinitions : SupportedObjects - { - public TypeDefinitions() : base() - { - infoheader = "Type Definitions"; - edssection = "TypeDefinitions"; - } - - public TypeDefinitions(Dictionary section) - { - Parse(section); - } - - } - - public class SupportedObjects - { - - public Dictionary objectlist; - public string infoheader; - public string edssection = "Supported Objects"; - public string countmsg = "SupportedObjects"; - - public SupportedObjects() - { - objectlist = new Dictionary(); - } - - public virtual void Parse(Dictionary section) - { - objectlist = new Dictionary(); - foreach(KeyValuePair kvp in section) - { - if(kvp.Key.ToLower()=="supportedobjects") - continue; - - if (kvp.Key.ToLower() == "nrofentries") - continue; - - int count = Convert.ToInt16(kvp.Key, EDSsharp.Getbase(kvp.Key)); - int target = Convert.ToInt16(kvp.Value, EDSsharp.Getbase(kvp.Value)); - objectlist.Add(count, target); - } - } - - public override string ToString() - { - string msg; - - msg = $"*****************************************************{Environment.NewLine}"; - msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; - msg += $"*****************************************************{Environment.NewLine}"; - msg += $"}}{Environment.NewLine}{countmsg} = {objectlist.Count}{Environment.NewLine}"; - foreach(KeyValuePair kvp in objectlist) - { - msg += $"{kvp.Key,-5}: {kvp.Value:x4}{Environment.NewLine}"; - } - - return msg; - - } - - public void Write(StreamWriter writer) - { - writer.WriteLine("[" + edssection + "]"); - writer.WriteLine(string.Format("{0}={1}", countmsg,objectlist.Count)); - foreach (KeyValuePair kvp in objectlist) - { - writer.WriteLine(string.Format("{0}=0x{1:X4}", kvp.Key, kvp.Value)); - } - - writer.WriteLine(""); - } - - } - - public class Comments - { - - public List comments = new List(); - public string infoheader = "Comments"; - public string edssection = "Comments"; - - public Comments() - { - - } - - public Comments(Dictionary section) - { - Parse(section); - } - - public virtual void Parse(Dictionary section) - { - comments = new List(); - foreach (KeyValuePair kvp in section) - { - if (kvp.Key == "Lines") - continue; - - comments.Add(kvp.Value); - - } - } - - public override string ToString() - { - string msg; - - msg = $"*****************************************************{Environment.NewLine}"; - msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; - msg += $"*****************************************************{Environment.NewLine}"; - msg += $"{Environment.NewLine}Lines = {comments.Count}{Environment.NewLine}"; - foreach (string s in comments) - { - msg += $"{s}{Environment.NewLine}"; - } - - return msg; - - } - - public void Write(StreamWriter writer) - { - if(comments == null) - { - comments = new List(); - } - - writer.WriteLine("[" + edssection + "]"); - - writer.WriteLine(string.Format("Lines={0}", comments.Count)); - - int count = 1; - foreach (string s in comments) - { - writer.WriteLine(string.Format("Line{0}={1}", count, s)); - count++; - } - - writer.WriteLine(""); - } - } - - - public class Dummyusage : InfoSection - { - [EdsExport] - public bool Dummy0001; - [EdsExport] - public bool Dummy0002; - [EdsExport] - public bool Dummy0003; - [EdsExport] - public bool Dummy0004; - [EdsExport] - public bool Dummy0005; - [EdsExport] - public bool Dummy0006; - [EdsExport] - public bool Dummy0007; - - - public Dummyusage() - { - infoheader = "CAN OPEN Dummy Usage"; - edssection = "DummyUsage"; - } - - public Dummyusage(Dictionary section) : this() - { - Parse(section,edssection); - } - } - - public class FileInfo : InfoSection - { - // Only for internal usage, use Path.GetFileName(eds.projectFilename) instead. - [EdsExport] - public string FileName=""; - [EdsExport] - public string FileVersion=""; - [EdsExport] - public byte FileRevision;//=1 - - [DcfExport] - public string LastEDS = ""; - - public byte EDSVersionMajor;//=4.0 - - public byte EDSVersionMinor;//=4.0 - [EdsExport] - public string EDSVersion=""; - - [EdsExport(maxlength=243)] - public string Description="";//= //max 243 characters - - public DateTime CreationDateTime;// - [EdsExport] - public string CreationTime=""; - [EdsExport] - public string CreationDate=""; - - [EdsExport(maxlength = 245)] - public string CreatedBy = "";//=CANFestival //max245 - - public DateTime ModificationDateTime;// - - [EdsExport] - public string ModificationTime=""; - [EdsExport] - public string ModificationDate=""; - - [EdsExport(maxlength = 244)] - public string ModifiedBy="";//=CANFestival //max244 - - //Folder CO_OD.c and CO_OD.h will be exported into - public string exportFolder = ""; - - - public FileInfo(Dictionary section) : this() - { - Parse(section,edssection); - } - - public FileInfo() - { - infoheader = "CAN OPEN FileInfo"; - edssection = "FileInfo"; - } - - - override public void Parse(Dictionary section, string sectionname) - { - - base.Parse(section,edssection); - - string dtcombined = ""; - try - { - if (section.ContainsKey("CreationTime") && section.ContainsKey("CreationDate")) - { - dtcombined = section["CreationTime"].Replace(" ","") + " " + section["CreationDate"]; - CreationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - } - } - catch(Exception e) - { - if (e is System.FormatException) - { - Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for CreationTime, not in DS306 format", dtcombined,sectionname)); - } - } - - try - { - if (section.ContainsKey("ModificationTime") && section.ContainsKey("ModificationTime")) - { - dtcombined = section["ModificationTime"].Replace(" ", "") + " " + section["ModificationDate"]; - ModificationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - } - } - catch (Exception e) - { - if (e is System.FormatException) - { - Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for ModificationTime, not in DS306 format", dtcombined, sectionname)); - } - } - - - try - { - if (section.ContainsKey("EDSVersion")) - { - string[] bits = section["EDSVersion"].Split('.'); - if (bits.Length >= 1) - EDSVersionMajor = Convert.ToByte(bits[0]); - if (bits.Length >= 2) - EDSVersionMinor = Convert.ToByte(bits[1]); - //EDSVersion = String.Format("{0}.{1}", EDSVersionMajor, EDSVersionMinor); - } - } - catch - { - Warnings.warning_list.Add(String.Format("Unable to parse EDS version {0}", section["EDSVersion"])); - } - - } - } - - public class DeviceInfo : InfoSection - { - - [EdsExport] - public string VendorName=""; - [EdsExport] - public string VendorNumber=""; - - [EdsExport] - public string ProductName=""; - [EdsExport] - public string ProductNumber=""; - [EdsExport] - public UInt32 RevisionNumber; - - [EdsExport] - public bool BaudRate_10 = true; - [EdsExport] - public bool BaudRate_20 = true; - [EdsExport] - public bool BaudRate_50 = true; - [EdsExport] - public bool BaudRate_125 = true; - [EdsExport] - public bool BaudRate_250 = true; - [EdsExport] - public bool BaudRate_500 = true; - [EdsExport] - public bool BaudRate_800 = true; - [EdsExport] - public bool BaudRate_1000 = true; - - public bool BaudRate_auto = false; - - [EdsExport] - public bool SimpleBootUpMaster; - [EdsExport] - public bool SimpleBootUpSlave; - - [EdsExport] - public byte Granularity = 8; - [EdsExport] - public bool DynamicChannelsSupported; - - [EdsExport] - public byte CompactPDO; - - [EdsExport] - public bool GroupMessaging; - - [EdsExport] - public UInt16 NrOfRXPDO; - - [EdsExport] - public UInt16 NrOfTXPDO; - - [EdsExport] - public bool LSS_Supported; - - public bool LSS_Master; - - public DeviceInfo() - { - infoheader = "CAN OPEN DeviceInfo"; - edssection = "DeviceInfo"; - } - - public DeviceInfo(Dictionary section) : this() - { - Parse(section,edssection); - } - } - - - public class DeviceCommissioning : InfoSection - { - - public DeviceCommissioning() - { - infoheader = "CAN OPEN DeviceCommissioning"; - edssection = "DeviceCommissioning"; - } - - public DeviceCommissioning(Dictionary section) : this() - { - Parse(section,edssection); - } - - [DcfExport] - public byte NodeId = 0; - - [DcfExport(maxlength = 246)] - public string NodeName = ""; //Max 246 characters - - [DcfExport] - public UInt16 BaudRate; - - [DcfExport] - public UInt32 NetNumber; - - [DcfExport(maxlength = 243)] - public string NetworkName = ""; //Max 243 characters - - [DcfExport] - public bool CANopenManager; //1 = CANopen manager, 0 or missing = not the manager - - [DcfExport] - public UInt32 LSS_SerialNumber; - - } - - public class SupportedModules : InfoSection - { - [EdsExport] - public UInt16 NrOfEntries; - - public SupportedModules() - { - infoheader = "CAN OPEN Supported Modules"; - edssection = "SupportedModules"; - } - - public SupportedModules(Dictionary section) : this() - { - Parse(section,edssection); - } - - - } - - public class ConnectedModules : SupportedObjects - { - [EdsExport] - public UInt16 NrOfEntries - { - get { return (UInt16)connectedmodulelist.Count; } - } - - public Dictionary connectedmodulelist; - - public ConnectedModules() - { - infoheader = "CAN OPEN Connected Modules"; - edssection = "ConnectedModules"; - countmsg = "NrOfEntries"; - connectedmodulelist = new Dictionary(); - } - - public ConnectedModules(Dictionary section) : this() - { - Parse(section); - - - foreach(KeyValuePair kvp in this.objectlist) - { - - - UInt16 K = (UInt16)kvp.Value; - UInt16 V = (UInt16)kvp.Key; - - connectedmodulelist.Add(K, V); - - - } - - } - - } - - public class MxFixedObjects : SupportedObjects - { - [EdsExport] - public UInt16 NrOfEntries - { - get { return (UInt16)connectedmodulelist.Count; } - } - - public Dictionary connectedmodulelist; - - private int _moduleindex; - - public int Moduleindex - { - get { return _moduleindex; } - set { _moduleindex = value; edssection = String.Format("M{0}FixedObjects",value); } - } - - public MxFixedObjects(UInt16 modindex) - { - infoheader = "CAN OPEN Module Fixed Objects"; - this.Moduleindex = modindex; - countmsg = "NrOfEntries"; - connectedmodulelist = new Dictionary(); - } - - public MxFixedObjects(Dictionary section, UInt16 modindex) : this(modindex) - { - Parse(section); - - foreach (KeyValuePair kvp in this.objectlist) - { - connectedmodulelist.Add((UInt16)kvp.Value, (UInt16)kvp.Key); - } - } - - } - - - - public class ModuleInfo : InfoSection - { - [EdsExport(maxlength = 248)] - public string ProductName; - - [EdsExport] - public byte ProductVersion; - - [EdsExport] - public byte ProductRevision; - - [EdsExport] - public string OrderCode; - - UInt16 moduleindex = 0; - - public ModuleInfo(UInt16 moduleindex) - { - this.moduleindex = moduleindex; - infoheader = "CAN OPEN Module Info " + moduleindex.ToString(); - edssection = string.Format("M{0}{1}", moduleindex, "ModuleInfo"); - } - - public ModuleInfo(Dictionary section, UInt16 moduleindex) : this (moduleindex) - { - Parse(section,edssection); - } - } - - - public class ModuleComments : Comments - { - - UInt16 moduleindex; - - public ModuleComments(UInt16 moduleindex) - { - this.moduleindex = moduleindex; - infoheader = "CAN OPEN Module Comments " + moduleindex.ToString(); - edssection = string.Format("M{0}{1}", moduleindex, "Comments"); - } - - public ModuleComments(Dictionary section,UInt16 moduleindex) : this (moduleindex) - { - Parse(section); - } - - - } - - public class ModuleSubExtends : SupportedObjects - { - - UInt16 moduleindex; - - public ModuleSubExtends(UInt16 moduleindex) - : base() - { - this.moduleindex = moduleindex; - infoheader = "CAN OPEN ModuleSubExtends "+moduleindex.ToString(); - edssection = string.Format("M{0}{1}", moduleindex, "SubExtends"); - } - - public ModuleSubExtends(Dictionary section, UInt16 moduleindex) - : this(moduleindex) - { - Parse(section); - } - - } - - public class ODentry - { - private UInt16 _index; - - /// - /// The index of the object in the Object Dictionary - /// This cannot be set for child objects, if you read a child object you get the parents index - /// - [EdsExport] - public UInt16 Index - { - get - { - if (parent != null) - return parent.Index; - else - return _index; - } - set - { - if(value==0) - { - - //throw (new Exception("Object index must be set")); - } - - if(parent == null) - { - _index = value; - } - else - { - - //throw (new Exception("Typing to set index of a subobject")); - } - - } - } - - [EdsExport] - public string parameter_name = ""; - - [DcfExport] - public string denotation = ""; - - [EdsExport] - public ObjectType objecttype = ObjectType.UNKNOWN; - [EdsExport] - public DataType datatype = DataType.UNKNOWN; - [EdsExport] - public EDSsharp.AccessType accesstype = EDSsharp.AccessType.UNKNOWN; - - [EdsExport] - public string defaultvalue = ""; - - [EdsExport] - public string LowLimit = ""; - - [EdsExport] - public string HighLimit = ""; - - [DcfExport] - public string actualvalue = ""; - - [EdsExport] - public Byte ObjFlags = 0; - - [EdsExport] - public byte CompactSubObj = 0; - - [EdsExport] - public bool PDOMapping - { - get - { - return PDOtype != PDOMappingType.no; - } - } - - //FIXME Count "If several modules are gathered to form a new Sub-Index, - //then the number is 0, followed by semicolon and the - //number of bits that are created per module to build a new - //Sub-Index" - - [EdsExport] - public byte count = 0; - - [EdsExport] - public byte ObjExtend = 0; - - public PDOMappingType PDOtype = PDOMappingType.no; - - public string Label = ""; - public string Description = ""; - public SortedDictionary subobjects = new SortedDictionary(); - public ODentry parent = null; - - public CustomProperties prop = new CustomProperties(); - - //XDD Extensions// - public string uniqueID; - - /// - /// Used when writing out objects to know if we are writing the normal or the module parts out - /// Two module parts subext and fixed are available. - /// - public enum Odtype - { - NORMAL, - SUBEXT, - FIXED, - } - - /// - /// Empty object constructor - /// - public ODentry() - { - - } - - /// - /// ODentry constructor for a simple VAR type - /// - /// Name of Object Dictionary Entry - /// Index of object in object dictionary - /// Type of this objects data - /// Default value (always set as a string) - /// Allowed CANopen access permissions - /// Allowed PDO mapping options - public ODentry(string parameter_name,UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping) - { - this.parameter_name = parameter_name; - this.Index = index; - this.objecttype = ObjectType.VAR; - this.datatype = datatype; - this.defaultvalue = defaultvalue; - - - if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) - this.accesstype = accesstype; - else - throw new ParameterException("AccessType invalid"); - - this.PDOtype = PDOMapping; - - } - - /// - /// ODConstructor useful for subobjects - /// - /// - /// NOT USED - /// - /// - /// - /// - /// - public ODentry(string parameter_name, UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping, ODentry parent) - { - this.parent = parent; - this.parameter_name = parameter_name; - this.objecttype = ObjectType.VAR; - this.datatype = datatype; - this.defaultvalue = defaultvalue; - this.Index = index; - - if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) - this.accesstype = accesstype; - else - throw new ParameterException("AccessType invalid"); - - this.PDOtype = PDOMapping; - } - - - /// - /// ODEntry constructor for array subobjects - /// - /// - /// - /// - public ODentry(string parameter_name,UInt16 index, byte nosubindex) - { - this.parameter_name = parameter_name; - this.objecttype = ObjectType.ARRAY; - this.Index = index; - //this.nosubindexes = nosubindex; - this.objecttype = ObjectType.VAR; - } - - /// - /// Make a deep clone of this ODentry - /// - /// - public ODentry Clone(ODentry newParent = null) - { - ODentry newOd = new ODentry - { - parent = newParent, - parameter_name = parameter_name, - denotation = denotation, - objecttype = objecttype, - datatype = datatype, - accesstype = accesstype, - PDOtype = PDOtype, - defaultvalue = defaultvalue, - LowLimit = LowLimit, - HighLimit = HighLimit, - actualvalue = actualvalue, - Label = Label, - Description = Description, - subobjects = new SortedDictionary(), - prop = prop.Clone() - }; - - foreach (KeyValuePair kvp in subobjects) - newOd.subobjects.Add(kvp.Key, kvp.Value.Clone(newOd)); - - return newOd; - } - - /// - /// Provide a simple string representation of the object, only parameters index, no subindexes/subindex parameter name and data type are included - /// Useful for debug and also appears in debugger when you inspect this object - /// - /// string summary of object - public override string ToString() - { - if (subobjects.Count > 0) - { - return String.Format("{0:x4}[{1}] : {2} : {3}", Index, subobjects.Count, parameter_name, datatype); - - } - else - { - return String.Format("{0:x4}/{1} : {2} : {3}", Index, Subindex, parameter_name, datatype); - } - } - - public string ObjectTypeString() - { - switch (objecttype) - { - default: - case ObjectType.VAR: return "VAR"; - case ObjectType.ARRAY: return "ARRAY"; - case ObjectType.REC: return "RECORD"; - } - } - - public void ObjectTypeString(string objectType) - { - switch (objectType) - { - default: - case "VAR": this.objecttype = ObjectType.VAR; break; - case "ARRAY": this.objecttype = ObjectType.ARRAY; break; - case "REC": - case "RECORD": this.objecttype = ObjectType.REC; break; - } - } - - public AccessSDO AccessSDO() - { - EDSsharp.AccessType accType = accesstype; - if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) - accType = parent.accesstype; - - switch (accType) - { - default: - return libEDSsharp.AccessSDO.no; - case EDSsharp.AccessType.ro: - case EDSsharp.AccessType.@const: - return libEDSsharp.AccessSDO.ro; - case EDSsharp.AccessType.wo: - return libEDSsharp.AccessSDO.wo; - case EDSsharp.AccessType.rw: - case EDSsharp.AccessType.rwr: - case EDSsharp.AccessType.rww: - return libEDSsharp.AccessSDO.rw; - } - } - - public void AccessSDO(AccessSDO accessSDO, AccessPDO accessPDO) - { - switch (accessSDO) - { - default: - accesstype = EDSsharp.AccessType.UNKNOWN; - break; - case libEDSsharp.AccessSDO.ro: - accesstype = EDSsharp.AccessType.ro; - break; - case libEDSsharp.AccessSDO.wo: - accesstype = EDSsharp.AccessType.wo; - break; - case libEDSsharp.AccessSDO.rw: - if (accessPDO == libEDSsharp.AccessPDO.r) - accesstype = EDSsharp.AccessType.rwr; - else if (accessPDO == libEDSsharp.AccessPDO.t) - accesstype = EDSsharp.AccessType.rww; - else - accesstype = EDSsharp.AccessType.rw; - break; - } - } - - public AccessPDO AccessPDO() - { - EDSsharp.AccessType accType = accesstype; - if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) - accType = parent.accesstype; - - if (PDOtype == PDOMappingType.RPDO || accType == EDSsharp.AccessType.rwr) - return libEDSsharp.AccessPDO.r; - else if (PDOtype == PDOMappingType.TPDO || accType == EDSsharp.AccessType.rww) - return libEDSsharp.AccessPDO.t; - if (PDOtype == PDOMappingType.optional || PDOtype == PDOMappingType.@default) - return libEDSsharp.AccessPDO.tr; - else - return libEDSsharp.AccessPDO.no; - } - - public void AccessPDO(AccessPDO accessPDO) - { - switch (accessPDO) - { - default: - PDOtype = PDOMappingType.no; - break; - case libEDSsharp.AccessPDO.r: - PDOtype = PDOMappingType.RPDO; - break; - case libEDSsharp.AccessPDO.t: - PDOtype = PDOMappingType.TPDO; - break; - case libEDSsharp.AccessPDO.tr: - PDOtype = PDOMappingType.optional; - break; - } - } - - /// - /// Duplicate current sub entry and add it to parent - /// - /// true on successfull addition - public ODentry AddSubEntry() - { - ODentry baseObject = parent == null ? this : parent; - - if (baseObject.objecttype == ObjectType.VAR) - return null; - - ODentry lastSubOd = baseObject.subobjects.Values.Last(); - ODentry originalOd = null; - ODentry newOd; - UInt16 maxSubIndex = 1; - UInt16 lastSubIndex = 1; - - // create new or clone existing sub od - if (lastSubOd == null || lastSubOd.Subindex < 1) - { - newOd = new ODentry - { - parent = baseObject, - parameter_name = "item", - objecttype = ObjectType.VAR, - datatype = DataType.UNSIGNED32 - }; - } - else - { - originalOd = (parent != null && this.Subindex > 0) ? this : lastSubOd; - newOd = originalOd.Clone(originalOd.parent); - maxSubIndex = EDSsharp.ConvertToUInt16(baseObject.subobjects[0].defaultvalue); - lastSubIndex = lastSubOd.Subindex; - } - - // insert new sub od - SortedDictionary newSubObjects = new SortedDictionary(); - UInt16 newSubIndex = 0; - foreach (ODentry subOd in baseObject.subobjects.Values) - { - if (subOd.Subindex > newSubIndex) - newSubIndex = subOd.Subindex; - - newSubObjects.Add(newSubIndex++, subOd); - - if (originalOd == subOd) - newSubObjects.Add(newSubIndex++, newOd); - } - if (originalOd == null) - newSubObjects.Add(newSubIndex++, newOd); - - baseObject.subobjects = newSubObjects; - - // Write maxSubIndex to first sub index - if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && baseObject.subobjects.Count > 0) - { - baseObject.subobjects[0].defaultvalue = string.Format("0x{0:X2}", newSubIndex - 1); - } - - return newOd; - } - - /// - /// Remove current sub entry - /// - /// Renumber subentries - /// true on successfull removal - public bool RemoveSubEntry(bool renumber) - { - if (parent != null && (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.REC)) - { - UInt16 maxSubIndex = EDSsharp.ConvertToUInt16(parent.subobjects[0].defaultvalue); - UInt16 lastSubIndex = parent.subobjects.Values.Last().Subindex; - - parent.subobjects.Remove(Subindex); - - if (renumber) - { - SortedDictionary newSubObjects = new SortedDictionary(); - UInt16 subIndex = 0; - foreach (ODentry subOd in parent.subobjects.Values) - newSubObjects.Add(subIndex++, subOd); - parent.subobjects = newSubObjects; - } - - // Write maxSubIndex to first sub index - if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && parent.subobjects.Count > 0) - { - parent.subobjects[0].defaultvalue = string.Format("0x{0:X2}", parent.subobjects.Values.Last().Subindex); - } - - return true; - } - return false; - } - - /// - /// If data type is an octet string we must remove all spaces when writing out to a EDS/DCF file - /// - /// Value to be processed - /// value if not octet string or value with spaces removed if octet string - public string Formatoctetstring(string value) - { - DataType dt = datatype; - if (dt == DataType.UNKNOWN && this.parent != null) - dt = parent.datatype; - - string ret = value; - - if (dt == DataType.OCTET_STRING) - { - ret = value.Replace(" ", ""); - } - - return ret; - } - - /// - /// Write out this Object dictionary entry to an EDS/DCF file using correct formatting - /// - /// Handle to the stream writer to write to - /// File type being written - /// - public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odtype.NORMAL, int module=0) - { - - string fixedmodheader = ""; - - if (odt == Odtype.FIXED) - { - fixedmodheader = string.Format("M{0}Fixed", module); - } - - if(odt == Odtype.SUBEXT) - { - fixedmodheader = string.Format("M{0}SubExt", module); - } - - if (parent != null) - { - writer.WriteLine(string.Format("[{0}{1:X}sub{2:X}]", fixedmodheader,Index, Subindex)); - } - else - { - writer.WriteLine(string.Format("[{0}{1:X}]",fixedmodheader,Index)); - } - - writer.WriteLine(string.Format("ParameterName={0}", parameter_name)); - - if(ft == InfoSection.Filetype.File_DCF) - { - writer.WriteLine(string.Format("Denotation={0}", denotation)); - } - - writer.WriteLine(string.Format("ObjectType=0x{0:X}", (int)objecttype)); - writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); - - if (objecttype == ObjectType.ARRAY) - { - writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); - } - - if (objecttype == ObjectType.REC) - { - writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); - } - - if (objecttype == ObjectType.VAR) - { - DataType dt = datatype; - if (dt == DataType.UNKNOWN && this.parent != null) - dt = parent.datatype; - writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); - writer.WriteLine(string.Format("AccessType={0}", accesstype.ToString())); - - - if(HighLimit != null && HighLimit != "") - { - writer.WriteLine(string.Format("HighLimit={0}", Formatoctetstring(HighLimit))); - } - - if (LowLimit != null && LowLimit != "") - { - writer.WriteLine(string.Format("LowLimit={0}", Formatoctetstring(LowLimit))); - } - - writer.WriteLine(string.Format("DefaultValue={0}", Formatoctetstring(defaultvalue))); - - //TODO If the ObjectType is domain (0x2) the value of the object may be stored in a file,UploadFile and DownloadFile - if (ft == InfoSection.Filetype.File_DCF) - { - writer.WriteLine(string.Format("ParameterValue={0}", Formatoctetstring(actualvalue))); - } - - writer.WriteLine(string.Format("PDOMapping={0}", PDOMapping==true?1:0)); - - if (prop.CO_flagsPDO == true) - { - writer.WriteLine(";TPDODetectCos=1"); - } - - - } - - //Count is for modules in the [MxSubExtxxxx] - //Should we export this on EDS only, or DCF or both? - if (odt == Odtype.SUBEXT ) - { - writer.WriteLine(string.Format("Count={0}", count)); - writer.WriteLine(string.Format("ObjExtend={0}", ObjExtend)); - } - - //ObjectFlags is always optional (Page 15, DSP306) and used for DCF writing to nodes - //also recommended not to write if it is already 0 - if (ObjFlags != 0) - { - writer.WriteLine(string.Format("ObjFlags={0}", ObjFlags)); - } - - writer.WriteLine(""); - } - - /// - /// Returns a c compatible string that represents the name of the object, - is replaced with _ - /// words separated by a space are replaced with _ for a separator eg ONE TWO becomes ONE_TWO - /// - /// - public string Paramater_cname() - { - string cname = parameter_name.Replace("-", "_"); - - cname = Regex.Replace(cname, @"([A-Z]) ([A-Z])", "$1_$2"); - cname = cname.Replace(" ", ""); - - return cname; - } - - /// - /// Return the size in bytes for the given CANopen datatype of this object, eg the size of what ever the datatype field is set to - /// - /// no of bytes - public int Sizeofdatatype() - { - DataType dt = datatype; - - if (dt == DataType.UNKNOWN && this.parent != null) - dt = parent.datatype; - - switch (dt) - { - case DataType.BOOLEAN: - return 1; - - case DataType.UNSIGNED8: - case DataType.INTEGER8: - return 8; - - case DataType.VISIBLE_STRING: - case DataType.OCTET_STRING: - return Lengthofstring*8; - - case DataType.INTEGER16: - case DataType.UNSIGNED16: - case DataType.UNICODE_STRING: - return 16; //FIXME is this corret for UNICODE_STRING seems dodgy? - - case DataType.UNSIGNED24: - case DataType.INTEGER24: - return 24; - - case DataType.INTEGER32: - case DataType.UNSIGNED32: - case DataType.REAL32: - return 32; - - case DataType.INTEGER40: - case DataType.UNSIGNED40: - return 40; - - case DataType.INTEGER48: - case DataType.UNSIGNED48: - case DataType.TIME_DIFFERENCE: - case DataType.TIME_OF_DAY: - return 48; - - case DataType.INTEGER56: - case DataType.UNSIGNED56: - return 56; - - case DataType.INTEGER64: - case DataType.UNSIGNED64: - case DataType.REAL64: - return 64; - - case DataType.DOMAIN: - return 0; - - default: //FIXME - return 0; - - } - } - - - /// - /// This is the no of subindexes present in the object, it is NOT the maximum subobject index - /// - [EdsExport] - public int Nosubindexes - { - get - { - return subobjects.Count; - } - } - - //warning eds files with gaps in subobject lists have been seen in the wild - //this function tries to get the array index based on sub number not array number - //it may return null - //This needs expanding to be used globally through the application ;-( - public ODentry Getsubobject(UInt16 no) - { - if (subobjects.ContainsKey(no)) - return subobjects[no]; - return null; - } - - public string Getsubobjectdefaultvalue(UInt16 no) - { - if (subobjects.ContainsKey(no)) - return subobjects[no].defaultvalue; - else - return ""; - } - - public bool Containssubindex(UInt16 no) - { - if (subobjects.ContainsKey(no)) - return true; - - return false; - } - - public byte Getmaxsubindex() - { - //Although subindex 0 should contain the max subindex value - //we don't enforce that anywhere in this lib, we should have a setter function - //that sets it to the highest subobject found. - if (objecttype == ObjectType.ARRAY || objecttype == ObjectType.REC) - if (Containssubindex(0)) - { - return EDSsharp.ConvertToByte(Getsubobjectdefaultvalue(0)); - } - - return 0; - } - - public int Lengthofstring - { - get - { - string defaultvalue = this.defaultvalue; - if (defaultvalue == null) - return 0; - - switch (this.datatype) - { - case DataType.VISIBLE_STRING: - { - return defaultvalue.Unescape().Length; - } - - case DataType.OCTET_STRING: - { - return Regex.Replace(defaultvalue, @"\s", "").Length / 2; - } - - case DataType.UNICODE_STRING: - { - return Regex.Replace(defaultvalue, @"\s", "").Length / 4; - } - default: - { - return 0; - } - } - } - } - - public UInt16 Subindex - { - get - { - if(this.parent!=null) - { - return parent.Findsubindex(this); - } - return 0; - - } - } - - public UInt16 Findsubindex(ODentry od) - { - foreach(KeyValuePairkvp in subobjects ) - { - if (kvp.Value == od) - return kvp.Key; - } - - return 0; - - } - - /// - /// Add an existing entry as a subobject of this OD - /// - /// - /// - public void addsubobject(byte index, ODentry sub) - { - sub.parent = this; - this.subobjects.Add(index, sub); - } - - } - - public class Module - { - - public ModuleInfo mi; - public ModuleComments mc; - public ModuleSubExtends mse; - public MxFixedObjects mxfo; - public SortedDictionary modulefixedobjects; - public SortedDictionary modulesubext; - - public UInt16 moduleindex; - - public Module(UInt16 moduleindex) - { - - this.moduleindex = moduleindex; - - mi = new ModuleInfo(moduleindex); - mc = new ModuleComments(moduleindex); - mse = new ModuleSubExtends(moduleindex); - mxfo = new MxFixedObjects(moduleindex); - modulefixedobjects = new SortedDictionary(); - modulesubext = new SortedDictionary(); - } - - - - } - - public class EDSsharp - { - - public enum AccessType - { - rw = 0, - ro = 1, - wo = 2, - rwr = 3, - rww = 4, - @const = 5, - UNKNOWN - } - - public const AccessType AccessType_Min = AccessType.rw; - public const AccessType AccessType_Max = AccessType.@const; - - - // File name of the opened project. Multiple file types are possible - // for opened project file, but project is always saved as xdd_v1.1 - // Filename within the FileInfo structure has only limited usage. - public string projectFilename = ""; - // File name, when project is opened in xdd_v1.1 or project is saved - public string xddfilename_1_1 = ""; - // File names for exported files - public string xddfilenameStripped = ""; - public string edsfilename = ""; - public string dcffilename = ""; - public string ODfilename = ""; - public string ODfileVersion = ""; - public string mdfilename = ""; - public string xmlfilename = ""; // old format - public string xddfilename_1_0 = ""; // old format - - //This is memorized, when XDD v1.1 is opened. It keeps all elements - //from original XDD file, which are not handled by libedesharp, so - //they will be preserved, when the file will be saved. - //Object dictionary parameters are not stored here. - public ISO15745ProfileContainer xddTemplate = null; - - //property to indicate unsaved data; - private bool _dirty; - public bool Dirty - { - get - { - return _dirty; - } - set - { - _dirty = value; - OnDataDirty?.Invoke(_dirty, this); - } - } - - protected Dictionary> eds; - protected Dictionary sectionlinenos; - public SortedDictionary ods; - public SortedDictionary dummy_ods; - - public CO_storageGroups CO_storageGroups = new CO_storageGroups(); - - public FileInfo fi; - public DeviceInfo di; - public MandatoryObjects md; - public OptionalObjects oo; - public ManufacturerObjects mo; - public Comments c; - public Dummyusage du; - public DeviceCommissioning dc; - - public TypeDefinitions td; - - public SupportedModules sm; - public ConnectedModules cm; - - // public Dictionary mi; - // public Dictionary mc; - // public Dictionary mse; - // public Dictionary mxfo; - // public SortedDictionary> modulefixedobjects; - // public SortedDictionary> modulesubext; - - public Dictionary modules; - - public UInt16 NodeId = 0; - - public delegate void DataDirty(bool dirty, EDSsharp sender); - public event DataDirty OnDataDirty; - - public EDSsharp() - { - - - eds = new Dictionary>(); - ods = new SortedDictionary(); - dummy_ods = new SortedDictionary(); - - fi = new FileInfo(); - di = new DeviceInfo(); - du = new Dummyusage(); - md = new MandatoryObjects(); - oo = new OptionalObjects(); - mo = new ManufacturerObjects(); - dc = new DeviceCommissioning(); - c = new Comments(); - sm = new SupportedModules(); - cm = new ConnectedModules(); - td = new TypeDefinitions(); - - - //mi = new Dictionary(); - //mc = new Dictionary(); - //mse = new Dictionary(); - //mxfo = new Dictionary (); - //modulefixedobjects = new SortedDictionary>(); - //modulesubext = new SortedDictionary>(); - - modules = new Dictionary(); - - - //FIXME no way for the Major/Minor to make it to EDSVersion - fi.EDSVersionMajor = 4; - fi.EDSVersionMinor = 0; - - fi.FileVersion = "1"; - fi.FileRevision = 1; - - fi.CreationDateTime = DateTime.Now; - fi.ModificationDateTime = DateTime.Now; - - du.Dummy0001 = false; - du.Dummy0002 = true; - du.Dummy0003 = true; - du.Dummy0004 = true; - du.Dummy0005 = true; - du.Dummy0006 = true; - du.Dummy0007 = true; - - ODentry od = new ODentry(); - - dummy_ods.Add(0x002, new ODentry("Dummy Int8", 0x002, DataType.INTEGER8, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x003, new ODentry("Dummy Int16", 0x003, DataType.INTEGER16, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x004, new ODentry("Dummy Int32", 0x004, DataType.INTEGER32, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x005, new ODentry("Dummy UInt8", 0x005, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x006, new ODentry("Dummy UInt16", 0x006, DataType.UNSIGNED16, "0", AccessType.ro, PDOMappingType.optional, null)); - dummy_ods.Add(0x007, new ODentry("Dummy UInt32", 0x007, DataType.UNSIGNED32, "0", AccessType.ro, PDOMappingType.optional, null)); - - } - - protected string sectionname = ""; - - /// - /// Verify PDO mapping parameters in Object Dictionary. Every mapped OD entry must exist and mapping must be allowed - /// - /// List of error strings, empty if no errors found. - public List VerifyPDOMapping() - { - List mappingErrors = new List(); - - foreach (KeyValuePair kvp in ods) - { - int indexPdo = kvp.Key; - if (!((indexPdo >= 0x1600 && indexPdo < 0x1800) || (indexPdo >= 0x1A00 && indexPdo < 0x1C00))) - continue; - - string PDO = indexPdo < 0x1800 ? "RPDO" : "TPDO"; - - ODentry odPdo = kvp.Value; - for (byte subIdxPdo = 1; subIdxPdo < odPdo.subobjects.Count; subIdxPdo++) - { - UInt32 mapVal; - try { mapVal = (UInt32)new System.ComponentModel.UInt32Converter().ConvertFromString(odPdo.subobjects[subIdxPdo].defaultvalue); } - catch (Exception) { continue; } - - UInt16 mapIdx = (UInt16)(mapVal >> 16); - UInt16 mapSub = (UInt16)((mapVal >> 8) & 0xFF); - - if (mapIdx < 0x1000) - continue; - - bool missing = true; - AccessPDO accessPDO = AccessPDO.no; - if (ods.ContainsKey(mapIdx)) - { - ODentry od = ods[mapIdx]; - if (!od.prop.CO_disabled) - { - if (od.objecttype == ObjectType.VAR) - { - missing = false; - accessPDO = od.AccessPDO(); - } - else if (od.subobjects.ContainsKey(mapSub)) - { - missing = false; - accessPDO = od.subobjects[mapSub].AccessPDO(); - } - } - } - if (missing) - mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: missing OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); - else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.t) || (PDO == "TPDO" && accessPDO == AccessPDO.r)) - mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: not mappable OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); - } - } - - return mappingErrors; - } - - public void Parseline(string linex,int no) - { - - string key = ""; - string value = ""; - - string line = linex.TrimStart(';'); - bool custom_extension = false; - - if (linex == null || linex == "") - return; - - if (linex[0] == ';') - custom_extension = true; - - - //extract sections - { - string pat = @"^\[([a-z0-9]+)\]"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(line); - if (m.Success) - { - Group g = m.Groups[1]; - sectionname = g.ToString(); - - if (!eds.ContainsKey(sectionname)) - { - eds.Add(sectionname, new Dictionary()); - } - else - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {0} : Duplicate section [{1}] ", no,sectionname)); - } - } - } - - //extract keyvalues - { - //Bug #70 Eat whitespace! - string pat = @"^([a-z0-9_]+)[ ]*=[ ]*(.*)"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(line); - if (m.Success) - { - key = m.Groups[1].ToString(); - value = m.Groups[2].ToString(); - value = value.TrimEnd(' ','\t','\n','\r'); - - //not sure how we actually get here with out a section being in the dictionary already.. - //suspect this is dead code. - if (!eds.ContainsKey(sectionname)) - { - eds.Add(sectionname, new Dictionary()); - } - - if (custom_extension == false) - { - try - { - eds[sectionname].Add(key, value); - } - catch(Exception) - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate key \"{0}\" value \"{1}\" in section [{2}]", key,value,sectionname, no)); - } - } - else - //Only allow our own extensions to populate the key/value pair - { - if (key == "StorageLocation" || key== "TPDODetectCos") - { - try - { - eds[sectionname].Add(key, value); - } - catch(Exception) - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate custom key \"{0}\" value \"{1}\" in section [{2}]", key, value, sectionname, no)); - } - } - } - } - } - } - - public void ParseEDSentry(KeyValuePair> kvp) - { - string section = kvp.Key; - - string pat = @"^(M[0-9a-fA-F]+(Fixed|SubExt))?([a-fA-F0-9]+)(sub)?([0-9a-fA-F]*)$"; - - Regex r = new Regex(pat); - Match m = r.Match(section); - if (m.Success) - { - - SortedDictionary target = this.ods; - - //** MODULE DCF SUPPORT - - string pat2 = @"^M([0-9a-fA-F]+)(Fixed|SubExt)([0-9a-fA-F]+)"; - Regex r2 = new Regex(pat2, RegexOptions.IgnoreCase); - Match m2 = r2.Match(m.Groups[0].ToString()); - - if (m2.Success) - { - - UInt16 modindex = Convert.ToUInt16(m2.Groups[1].Value); - UInt16 odindex = Convert.ToUInt16(m2.Groups[3].Value); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - if (m2.Groups[2].ToString() == "SubExt") - { - target = modules[modindex].modulesubext; - - } - else - { - target = modules[modindex].modulefixedobjects; - } - } - - - ODentry od = new ODentry - { - //Indexes in the EDS are always in hex format without the pre 0x - Index = Convert.ToUInt16(m.Groups[3].ToString(), 16) - }; - - //Parameter name, mandatory always - if (!kvp.Value.ContainsKey("ParameterName")) - throw new ParameterException("Missing required field ParameterName on" + section); - od.parameter_name = kvp.Value["ParameterName"]; - - //Object type, assumed to be VAR unless specified - if (kvp.Value.ContainsKey("ObjectType")) - { - int type = Convert.ToInt16(kvp.Value["ObjectType"], Getbase(kvp.Value["ObjectType"])); - od.objecttype = (ObjectType)type; - } - else - { - od.objecttype = ObjectType.VAR; - } - - if(kvp.Value.ContainsKey("CompactSubObj")) - { - od.CompactSubObj = Convert.ToByte(kvp.Value["CompactSubObj"],Getbase(kvp.Value["CompactSubObj"])); - } - - if(kvp.Value.ContainsKey("ObjFlags")) - { - od.ObjFlags = Convert.ToByte(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); - } - else - { - od.ObjFlags = 0; - } - - //Access Type - if(kvp.Value.ContainsKey("StorageLocation")) - { - od.prop.CO_storageGroup = kvp.Value["StorageLocation"]; - } - - if (kvp.Value.ContainsKey("TPDODetectCos")) - { - string test = kvp.Value["TPDODetectCos"].ToLower(); - if (test == "1" || test == "true") - { - od.prop.CO_flagsPDO = true; - } - else - od.prop.CO_flagsPDO = false; - } - - if (kvp.Value.ContainsKey("Count")) - { - od.count = Convert.ToByte(kvp.Value["Count"]); - } - - if (kvp.Value.ContainsKey("ObjExtend")) - { - od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); - } - - - if (od.objecttype == ObjectType.VAR) - { - - if (kvp.Value.ContainsKey("CompactSubObj")) - throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); - - if (kvp.Value.ContainsKey("ParameterValue")) - { - od.actualvalue = kvp.Value["ParameterValue"]; - } - - if (kvp.Value.ContainsKey("HighLimit")) - { - od.HighLimit = kvp.Value["HighLimit"]; - } - - if (kvp.Value.ContainsKey("LowLimit")) - { - od.LowLimit = kvp.Value["LowLimit"]; - } - - if (kvp.Value.ContainsKey("Denotation")) - { - od.denotation = kvp.Value["Denotation"]; - } - - if (m.Groups[5].Length != 0) - { - //FIXME are subindexes in hex always? - UInt16 subindex = Convert.ToUInt16(m.Groups[5].ToString(),16); - od.parent = target[od.Index]; - target[od.Index].subobjects.Add(subindex, od); - } - - if (!kvp.Value.ContainsKey("DataType")) - throw new ParameterException("Missing required field DataType on" + section); - od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); - - if (!kvp.Value.ContainsKey("AccessType")) - throw new ParameterException("Missing required AccessType on" + section); - - string accesstype = kvp.Value["AccessType"].ToLower(); - - if (Enum.IsDefined(typeof(AccessType), accesstype)) - { - od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); - } - else - { - throw new ParameterException("Unknown AccessType on" + section); - } - - if (kvp.Value.ContainsKey("DefaultValue")) - od.defaultvalue = kvp.Value["DefaultValue"]; - - od.PDOtype = PDOMappingType.no; - if (kvp.Value.ContainsKey("PDOMapping")) - { - - bool pdo = Convert.ToInt16(kvp.Value["PDOMapping"],Getbase(kvp.Value["PDOMapping"])) == 1; - if (pdo == true) - od.PDOtype = PDOMappingType.optional; - } - - } - - - if(od.objecttype == ObjectType.REC|| od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) - { - - if (od.CompactSubObj != 0) - { - if (!kvp.Value.ContainsKey("DataType")) - throw new ParameterException("Missing required field DataType on" + section); - od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); - - if (!kvp.Value.ContainsKey("AccessType")) - throw new ParameterException("Missing required AccessType on" + section); - string accesstype = kvp.Value["AccessType"]; - if (Enum.IsDefined(typeof(AccessType), accesstype)) - { - od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); - } - else - { - throw new ParameterException("Unknown AccessType on" + section); - } - - //now we generate CompactSubObj number of var objects below this parent - - if(od.CompactSubObj>=0xfe) - { - od.CompactSubObj = 0xfe; - } - - ODentry subi = new ODentry("NrOfObjects", od.Index, DataType.UNSIGNED8, String.Format("0x{0:x2}",od.CompactSubObj), AccessType.ro, PDOMappingType.no, od); - od.subobjects.Add(0x00, subi); - - for (int x=1; x<= od.CompactSubObj; x++) - { - string parameter_name = string.Format("{0}{1:x2}", od.parameter_name, x ); - ODentry sub = new ODentry(parameter_name, od.Index, od.datatype, od.defaultvalue, od.accesstype, od.PDOtype, od); - - if (kvp.Value.ContainsKey("HighLimit")) - sub.HighLimit = kvp.Value["HighLimit"]; - - if (kvp.Value.ContainsKey("LowLimit")) - sub.HighLimit = kvp.Value["LowLimit"]; - - od.subobjects.Add((ushort)(x ), sub); - } - - } - else - { - if (!kvp.Value.ContainsKey("SubNumber")) - throw new ParameterException("Missing SubNumber on Array for" + section); - - - - } - } - - if(od.objecttype == ObjectType.DOMAIN) - { - od.datatype = DataType.DOMAIN; - od.accesstype = AccessType.rw; - - if (kvp.Value.ContainsKey("DefaultValue")) - od.defaultvalue = kvp.Value["DefaultValue"]; - - } - - //Only add top level to this list - if (m.Groups[5].Length == 0) - { - target.Add(od.Index, od); - } - } - - } - - public void Loadfile(string filename) - { - - projectFilename = filename; - - if (Path.GetExtension(filename).ToLower() == ".eds") - { - edsfilename = filename; - } - - if (Path.GetExtension(filename).ToLower() == ".dcf") - { - dcffilename = filename; - } - - //try - { - int lineno = 1; - foreach (string linex in File.ReadLines(filename)) - { - Parseline(linex,lineno); - lineno++; - } - - di = new DeviceInfo(eds["DeviceInfo"]); - - foreach (KeyValuePair> kvp in eds) - { - ParseEDSentry(kvp); - } - - fi = new FileInfo(eds["FileInfo"]); - if(eds.ContainsKey("DummyUsage")) - du = new Dummyusage(eds["DummyUsage"]); - - md = new MandatoryObjects(eds["MandatoryObjects"]); - - if(eds.ContainsKey("OptionalObjects")) - oo = new OptionalObjects(eds["OptionalObjects"]); - - if(eds.ContainsKey("ManufacturerObjects")) - mo = new ManufacturerObjects(eds["ManufacturerObjects"]); - - if (eds.ContainsKey("TypeDefinitions")) - td = new TypeDefinitions(eds["TypeDefinitions"]); - - //Only DCF not EDS files - dc = new DeviceCommissioning(); - if(eds.ContainsKey("DeviceCommissioning")) - { - dc.Parse(eds["DeviceCommissioning"],"DeviceCommissioning"); - edsfilename = fi.LastEDS; - } - - c = new Comments(); - - if (eds.ContainsKey("Comments")) - c.Parse(eds["Comments"]); - - //Modules - - //FIXME - //we don't parse or support [MxFixedObjects] with MxFixedxxxx and MxFixedxxxxsubx - - if (eds.ContainsKey("SupportedModules")) - { - sm = new SupportedModules(eds["SupportedModules"]); - - //find MxModuleInfo - - foreach (string s in eds.Keys) - { - String pat = @"^M([0-9]+)ModuleInfo"; - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleInfo mi = new ModuleInfo(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mi = mi; - - } - - - pat = @"^M([0-9]+)Comments"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleComments mc = new ModuleComments(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mc = mc; - - } - - pat = @"^M([0-9]+)SubExtends"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleSubExtends mse = new ModuleSubExtends(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mse = mse; - } - - - //DCF only - pat = @"^M([0-9]+)FixedObjects"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - MxFixedObjects mxf = new MxFixedObjects(eds[s],modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mxfo = mxf; - - } - } - } - - - if (eds.ContainsKey("ConnectedModules")) - { - cm = new ConnectedModules(eds["ConnectedModules"]); - } - - //COMPACT PDO - - if (di.CompactPDO != 0) - { - - for (UInt16 index = 0x1400; index < 0x1600; index++) - { - ApplycompactPDO(index); - } - - for (UInt16 index = 0x1800; index < 0x1A00;index ++) - { - ApplycompactPDO(index); - } - } - - ApplyimplicitPDO(); - } - // catch(Exception e) - //{ - // Console.WriteLine("** ALL GONE WRONG **" + e.ToString()); - // } - } - - public void ApplycompactPDO(UInt16 index) - { - if (ods.ContainsKey(index)) - { - if ((!ods[index].Containssubindex(1)) && ((this.di.CompactPDO & 0x01) == 0)) - { - //Fill in cob ID - //FIX ME i'm really sure this is not correct, what default values should be used??? - string cob = string.Format("0x180+$NODEID"); - ODentry subod = new ODentry("COB-ID", index, DataType.UNSIGNED32, cob, AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x05, subod); - - } - - if ((!ods[index].Containssubindex(2)) && ((this.di.CompactPDO & 0x02) == 0)) - { - //Fill in type - - ODentry subod = new ODentry("Type", index, DataType.UNSIGNED8, "0xff", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x02, subod); - } - - if ((!ods[index].Containssubindex(3)) && ((this.di.CompactPDO & 0x04) == 0)) - { - //Fill in inhibit - - ODentry subod = new ODentry("Inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x03, subod); - } - - //NOT FOR RX PDO - if (index < 0x1800) - return; - - if ((!ods[index].Containssubindex(4)) && ((this.di.CompactPDO & 0x08) == 0)) - { - //Fill in compatibility entry - - ODentry subod = new ODentry("Compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x04, subod); - } - - if ((!ods[index].Containssubindex(5)) && ((this.di.CompactPDO & 0x10) == 0)) - { - //Fill in event timer - - ODentry subod = new ODentry("Event Timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x05, subod); - } - } - } - - /// - /// This function scans the PDO list and compares it to NrOfRXPDO and NrOfTXPDO - /// if these do not match in count then implicit PDOs are present and they are - /// filled in with default values from the lowest possible index - /// - public void ApplyimplicitPDO() - { - UInt16 totalnorxpdos = di.NrOfRXPDO; - UInt16 totalnotxpdos = di.NrOfTXPDO; - - UpdatePDOcount(); - - UInt16 noexplicitrxpdos = di.NrOfRXPDO; - UInt16 noexplicittxpdos = di.NrOfTXPDO; - - //this is how many PDOS need generating on the fly - UInt16 noimplictrxpdos = (UInt16) (totalnorxpdos - noexplicitrxpdos); - UInt16 noimplicttxpdos = (UInt16) (totalnotxpdos - noexplicittxpdos); - - for(UInt16 index = 0x1400; (index < 0x1600) && (noimplictrxpdos > 0) ;index++) - { - if(!ods.ContainsKey(index)) - { - CreateRXPDO(index); - noimplictrxpdos--; - } - } - - for (UInt16 index = 0x1800; (index < 0x1A00) && (noimplicttxpdos > 0); index++) - { - if (!ods.ContainsKey(index)) - { - CreateTXPDO(index); - noimplicttxpdos--; - } - } - - UpdatePDOcount(); - - } - - public void Savefile(string filename, InfoSection.Filetype ft) - { - if(ft==InfoSection.Filetype.File_EDS) - this.edsfilename = filename; - - if (ft == InfoSection.Filetype.File_DCF) - { - this.dcffilename = filename; - fi.LastEDS = edsfilename; - } - - UpdatePDOcount(); - - //generate date times in DS306 format; h:mmtt MM-dd-yyyy - - fi.CreationDate = fi.CreationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); - fi.CreationTime = fi.CreationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); - - fi.ModificationDate = fi.ModificationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); - fi.ModificationTime = fi.ModificationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); - - fi.FileName = Path.GetFileName(filename); - - fi.EDSVersion = "4.0"; - fi.EDSVersionMajor = 4; - fi.EDSVersionMinor = 0; - +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.IO; +using System.Text.RegularExpressions; +using System.Globalization; +using System.Reflection; +using CanOpenXSD_1_1; + +namespace libEDSsharp +{ + + + public enum DataType + { + UNKNOWN = 0, + BOOLEAN = 1, + INTEGER8 = 2, + INTEGER16 = 3, + INTEGER32 = 4, + UNSIGNED8 = 5, + UNSIGNED16 = 6, + UNSIGNED32 = 7, + REAL32 = 8, + VISIBLE_STRING = 9, + OCTET_STRING = 0x0A, + UNICODE_STRING = 0x0B, + TIME_OF_DAY = 0x0C, + TIME_DIFFERENCE = 0x0D, + DOMAIN = 0x0F, + INTEGER24 = 0x10, + REAL64 = 0x11, + INTEGER40 = 0x12, + INTEGER48 = 0x13, + INTEGER56 = 0x14, + INTEGER64 = 0x15, + UNSIGNED24 = 0x16, + UNSIGNED40 = 0x18, + UNSIGNED48 = 0x19, + UNSIGNED56 = 0x1A, + UNSIGNED64 = 0x1B, + + PDO_COMMUNICATION_PARAMETER = 0x20, //PDO_CommPar + PDO_MAPPING = 0x21, //PDO_Mapping + SDO_PARAMETER = 0x22, + IDENTITY = 0x23, + + } + + public enum ObjectType + { + UNKNOWN = -1, + NULL = 0, + DOMAIN =2, + DEFTYPE=5, + DEFSTRUCT=6, + VAR = 7, + ARRAY = 8, + REC = 9, + } + + public enum PDOMappingType + { + no=0, + optional=1, + RPDO=2, + TPDO=3, + @default=4, + } + + public enum AccessSDO + { + no, + ro, + wo, + rw + } + + public enum AccessPDO + { + no, + t, + r, + tr + } + + public enum AccessSRDO + { + no = 0, + tx = 1, + rx = 2, + trx = 3 + } + + /// + /// Custom properties for OD entry or sub-entry, which are saved into xdd file v1.1 + /// + public class CustomProperties + { + public bool CO_disabled = false; // If true, object is completelly skipped by CANopenNode exporters, etc. + public string CO_countLabel = ""; + public string CO_storageGroup = "RAM"; + public bool CO_flagsPDO = false; + public AccessSRDO CO_accessSRDO = AccessSRDO.no; + public UInt32 CO_stringLengthMin = 0; + + public CustomProperties Clone() + { + return new CustomProperties + { + CO_disabled = CO_disabled, + CO_countLabel = CO_countLabel, + CO_storageGroup = CO_storageGroup, + CO_flagsPDO = CO_flagsPDO, + CO_accessSRDO = CO_accessSRDO, + CO_stringLengthMin = CO_stringLengthMin + }; + } + + public void OdeXdd(property[] properties) + { + if (properties != null) + { + foreach (property prop in properties) + { + switch (prop.name) + { + case "CO_disabled": CO_disabled = prop.value == "true"; break; + case "CO_countLabel": CO_countLabel = prop.value ?? ""; break; + case "CO_storageGroup": CO_storageGroup = prop.value ?? ""; break; + case "CO_flagsPDO": CO_flagsPDO = prop.value == "true"; break; + case "CO_accessSRDO": + try { CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), prop.value); } + catch (Exception) { CO_accessSRDO = AccessSRDO.no; } + break; + case "CO_stringLengthMin": + try { CO_stringLengthMin = Convert.ToUInt16(prop.value); } + catch (Exception) { CO_stringLengthMin = 0; } + break; + } + } + } + } + + public property[] OdeXdd() + { + var props = new List(); + + if (CO_disabled) + props.Add(new property { name = "CO_disabled", value = "true" }); + if (CO_countLabel != "") + props.Add(new property { name = "CO_countLabel", value = CO_countLabel }); + if (CO_storageGroup != "RAM") + props.Add(new property { name = "CO_storageGroup", value = CO_storageGroup }); + if (CO_flagsPDO) + props.Add(new property { name = "CO_flagsPDO", value = "true" }); + + return props.ToArray(); + } + + public property[] SubOdeXdd() + { + var props = new List(); + + if (CO_accessSRDO != AccessSRDO.no) + props.Add(new property { name = "CO_accessSRDO", value = CO_accessSRDO.ToString() }); + if (CO_stringLengthMin != 0) + props.Add(new property { name = "CO_stringLengthMin", value = CO_stringLengthMin.ToString() }); + + return props.ToArray(); + } + } + + /// + /// List of multiple CO_storageGroup strings available in project + /// + public class CO_storageGroups : List + { + public CO_storageGroups() + { + Add("RAM"); // default value + } + + public new void Add(string item) + { + if (!Contains(item)) + { + base.Add(item); + } + } + } + + public class EdsExport : Attribute + { + public UInt16 maxlength; + public bool commentonly=false; + + //mehmeh + public EdsExport() + { + } + + public EdsExport(UInt16 maxlength) + { + this.maxlength = maxlength; + } + + public bool IsReadOnly() + { + return commentonly; + } + + + } + + public class DcfExport : EdsExport + { + } + + public class InfoSection + { + protected Dictionary section; + + protected string infoheader; + protected string edssection; + + public enum Filetype + { + File_EDS, + File_DCF + } + + public virtual void Parse(Dictionary section,string sectionname) + { + + this.section = section; + + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + if(Attribute.IsDefined(f, typeof(EdsExport))) + GetField(f.Name, f.Name); + + if (Attribute.IsDefined(f, typeof(DcfExport))) + GetField(f.Name, f.Name); + } + + } + + public bool GetField(string name, string varname) + { + FieldInfo f = null; + + try + { + foreach (var element in section) + { + if (String.Equals(element.Key, name, StringComparison.OrdinalIgnoreCase)) + { + + name = element.Key; + Type tx = this.GetType(); + + f = tx.GetField(varname); + object var = null; + + switch (f.FieldType.Name) + { + case "String": + var = section[name]; + break; + + case "UInt32": + var = Convert.ToUInt32(section[name], EDSsharp.Getbase(section[name])); + break; + + case "Int16": + var = Convert.ToInt16(section[name], EDSsharp.Getbase(section[name])); + break; + + case "UInt16": + var = Convert.ToUInt16(section[name], EDSsharp.Getbase(section[name])); + break; + + case "Byte": + var = Convert.ToByte(section[name], EDSsharp.Getbase(section[name])); + break; + + case "Boolean": + var = section[name] == "1"; //because Convert is Awesome + break; + + default: + Console.WriteLine(String.Format("Unhanded variable {0} for {1}", f.FieldType.Name, varname)); + break; + } + + if (var != null) + { + tx.GetField(varname).SetValue(this, var); + return true; + } + } + } + } + catch (Exception e) + { + if (e is OverflowException) + { + Warnings.warning_list.Add(string.Format("Warning parsing {0} tried to fit {1} into {2}", name, section[name], f.FieldType.Name)); + } + } + + return false; + } + + public override string ToString() + { + string msg; + + msg = $"*****************************************************{Environment.NewLine}"; + msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; + msg += $"*****************************************************{Environment.NewLine}"; + + Type tx = this.GetType(); + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + msg += $"{f.Name,-28}: {f.GetValue(this).ToString()}{Environment.NewLine}"; + } + + return msg; + } + + public void Write(StreamWriter writer, Filetype ft) + { + writer.WriteLine("[" + edssection + "]"); + Type tx = this.GetType(); + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + + if ((ft==Filetype.File_EDS) && (!Attribute.IsDefined(f, typeof(EdsExport)))) + continue; + + if ((ft == Filetype.File_DCF) && (!(Attribute.IsDefined(f, typeof(DcfExport)) || Attribute.IsDefined(f, typeof(EdsExport))))) + continue; + + if (f.GetValue(this) == null) + continue; + + EdsExport ex = (EdsExport)f.GetCustomAttribute(typeof(EdsExport)); + + bool comment = ex.IsReadOnly(); + + if (f.FieldType.Name == "Boolean") + { + writer.WriteLine(string.Format("{2}{0}={1}", f.Name, ((bool)f.GetValue(this)) == true ? 1 : 0,comment==true?";":"")); + } + else + { + writer.WriteLine(string.Format("{2}{0}={1}", f.Name, f.GetValue(this).ToString(), comment == true ? ";" : "")); + } + } + + writer.WriteLine(""); + + } + + } + + + public class MandatoryObjects : SupportedObjects + { + public MandatoryObjects() + : base() + { + infoheader = "Mandatory Objects"; + edssection = "MandatoryObjects"; + } + + public MandatoryObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public class OptionalObjects : SupportedObjects + { + public OptionalObjects() + : base() + { + infoheader = "Optional Objects"; + edssection = "OptionalObjects"; + } + + public OptionalObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public class ManufacturerObjects : SupportedObjects + { + public ManufacturerObjects() : base() + { + infoheader = "Manufacturer Objects"; + edssection = "ManufacturerObjects"; + } + + public ManufacturerObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public class TypeDefinitions : SupportedObjects + { + public TypeDefinitions() : base() + { + infoheader = "Type Definitions"; + edssection = "TypeDefinitions"; + } + + public TypeDefinitions(Dictionary section) + { + Parse(section); + } + + } + + public class SupportedObjects + { + + public Dictionary objectlist; + public string infoheader; + public string edssection = "Supported Objects"; + public string countmsg = "SupportedObjects"; + + public SupportedObjects() + { + objectlist = new Dictionary(); + } + + public virtual void Parse(Dictionary section) + { + objectlist = new Dictionary(); + foreach(KeyValuePair kvp in section) + { + if(kvp.Key.ToLower()=="supportedobjects") + continue; + + if (kvp.Key.ToLower() == "nrofentries") + continue; + + int count = Convert.ToInt16(kvp.Key, EDSsharp.Getbase(kvp.Key)); + int target = Convert.ToInt16(kvp.Value, EDSsharp.Getbase(kvp.Value)); + objectlist.Add(count, target); + } + } + + public override string ToString() + { + string msg; + + msg = $"*****************************************************{Environment.NewLine}"; + msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; + msg += $"*****************************************************{Environment.NewLine}"; + msg += $"}}{Environment.NewLine}{countmsg} = {objectlist.Count}{Environment.NewLine}"; + foreach(KeyValuePair kvp in objectlist) + { + msg += $"{kvp.Key,-5}: {kvp.Value:x4}{Environment.NewLine}"; + } + + return msg; + + } + + public void Write(StreamWriter writer) + { + writer.WriteLine("[" + edssection + "]"); + writer.WriteLine(string.Format("{0}={1}", countmsg,objectlist.Count)); + foreach (KeyValuePair kvp in objectlist) + { + writer.WriteLine(string.Format("{0}=0x{1:X4}", kvp.Key, kvp.Value)); + } + + writer.WriteLine(""); + } + + } + + public class Comments + { + + public List comments = new List(); + public string infoheader = "Comments"; + public string edssection = "Comments"; + + public Comments() + { + + } + + public Comments(Dictionary section) + { + Parse(section); + } + + public virtual void Parse(Dictionary section) + { + comments = new List(); + foreach (KeyValuePair kvp in section) + { + if (kvp.Key == "Lines") + continue; + + comments.Add(kvp.Value); + + } + } + + public override string ToString() + { + string msg; + + msg = $"*****************************************************{Environment.NewLine}"; + msg += $"*{String.Format("{0," + ((51 + infoheader.Length) / 2).ToString() + "}", infoheader),-51}*{Environment.NewLine}"; + msg += $"*****************************************************{Environment.NewLine}"; + msg += $"{Environment.NewLine}Lines = {comments.Count}{Environment.NewLine}"; + foreach (string s in comments) + { + msg += $"{s}{Environment.NewLine}"; + } + + return msg; + + } + + public void Write(StreamWriter writer) + { + if(comments == null) + { + comments = new List(); + } + + writer.WriteLine("[" + edssection + "]"); + + writer.WriteLine(string.Format("Lines={0}", comments.Count)); + + int count = 1; + foreach (string s in comments) + { + writer.WriteLine(string.Format("Line{0}={1}", count, s)); + count++; + } + + writer.WriteLine(""); + } + } + + + public class Dummyusage : InfoSection + { + [EdsExport] + public bool Dummy0001; + [EdsExport] + public bool Dummy0002; + [EdsExport] + public bool Dummy0003; + [EdsExport] + public bool Dummy0004; + [EdsExport] + public bool Dummy0005; + [EdsExport] + public bool Dummy0006; + [EdsExport] + public bool Dummy0007; + + + public Dummyusage() + { + infoheader = "CAN OPEN Dummy Usage"; + edssection = "DummyUsage"; + } + + public Dummyusage(Dictionary section) : this() + { + Parse(section,edssection); + } + } + + public class FileInfo : InfoSection + { + // Only for internal usage, use Path.GetFileName(eds.projectFilename) instead. + [EdsExport] + public string FileName=""; + [EdsExport] + public string FileVersion=""; + [EdsExport] + public byte FileRevision;//=1 + + [DcfExport] + public string LastEDS = ""; + + public byte EDSVersionMajor;//=4.0 + + public byte EDSVersionMinor;//=4.0 + [EdsExport] + public string EDSVersion=""; + + [EdsExport(maxlength=243)] + public string Description="";//= //max 243 characters + + public DateTime CreationDateTime;// + [EdsExport] + public string CreationTime=""; + [EdsExport] + public string CreationDate=""; + + [EdsExport(maxlength = 245)] + public string CreatedBy = "";//=CANFestival //max245 + + public DateTime ModificationDateTime;// + + [EdsExport] + public string ModificationTime=""; + [EdsExport] + public string ModificationDate=""; + + [EdsExport(maxlength = 244)] + public string ModifiedBy="";//=CANFestival //max244 + + //Folder CO_OD.c and CO_OD.h will be exported into + public string exportFolder = ""; + + + public FileInfo(Dictionary section) : this() + { + Parse(section,edssection); + } + + public FileInfo() + { + infoheader = "CAN OPEN FileInfo"; + edssection = "FileInfo"; + } + + + override public void Parse(Dictionary section, string sectionname) + { + + base.Parse(section,edssection); + + string dtcombined = ""; + try + { + if (section.ContainsKey("CreationTime") && section.ContainsKey("CreationDate")) + { + dtcombined = section["CreationTime"].Replace(" ","") + " " + section["CreationDate"]; + CreationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + } + } + catch(Exception e) + { + if (e is System.FormatException) + { + Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for CreationTime, not in DS306 format", dtcombined,sectionname)); + } + } + + try + { + if (section.ContainsKey("ModificationTime") && section.ContainsKey("ModificationTime")) + { + dtcombined = section["ModificationTime"].Replace(" ", "") + " " + section["ModificationDate"]; + ModificationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + } + } + catch (Exception e) + { + if (e is System.FormatException) + { + Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for ModificationTime, not in DS306 format", dtcombined, sectionname)); + } + } + + + try + { + if (section.ContainsKey("EDSVersion")) + { + string[] bits = section["EDSVersion"].Split('.'); + if (bits.Length >= 1) + EDSVersionMajor = Convert.ToByte(bits[0]); + if (bits.Length >= 2) + EDSVersionMinor = Convert.ToByte(bits[1]); + //EDSVersion = String.Format("{0}.{1}", EDSVersionMajor, EDSVersionMinor); + } + } + catch + { + Warnings.warning_list.Add(String.Format("Unable to parse EDS version {0}", section["EDSVersion"])); + } + + } + } + + public class DeviceInfo : InfoSection + { + + [EdsExport] + public string VendorName=""; + [EdsExport] + public string VendorNumber=""; + + [EdsExport] + public string ProductName=""; + [EdsExport] + public string ProductNumber=""; + [EdsExport] + public UInt32 RevisionNumber; + + [EdsExport] + public bool BaudRate_10 = false; + [EdsExport] + public bool BaudRate_20 = false; + [EdsExport] + public bool BaudRate_50 = false; + [EdsExport] + public bool BaudRate_125 = false; + [EdsExport] + public bool BaudRate_250 = false; + [EdsExport] + public bool BaudRate_500 = false; + [EdsExport] + public bool BaudRate_800 = false; + [EdsExport] + public bool BaudRate_1000 = false; + + public bool BaudRate_auto = false; + + [EdsExport] + public bool SimpleBootUpMaster; + [EdsExport] + public bool SimpleBootUpSlave; + + [EdsExport] + public byte Granularity = 8; + [EdsExport] + public bool DynamicChannelsSupported; + + [EdsExport] + public byte CompactPDO; + + [EdsExport] + public bool GroupMessaging; + + [EdsExport] + public UInt16 NrOfRXPDO; + + [EdsExport] + public UInt16 NrOfTXPDO; + + [EdsExport] + public bool LSS_Supported; + + public bool LSS_Master; + + public DeviceInfo() + { + infoheader = "CAN OPEN DeviceInfo"; + edssection = "DeviceInfo"; + } + + public DeviceInfo(Dictionary section) : this() + { + Parse(section,edssection); + } + } + + + public class DeviceCommissioning : InfoSection + { + + public DeviceCommissioning() + { + infoheader = "CAN OPEN DeviceCommissioning"; + edssection = "DeviceCommissioning"; + } + + public DeviceCommissioning(Dictionary section) : this() + { + Parse(section,edssection); + } + + [DcfExport] + public byte NodeId = 0; + + [DcfExport(maxlength = 246)] + public string NodeName = ""; //Max 246 characters + + [DcfExport] + public UInt16 BaudRate; + + [DcfExport] + public UInt32 NetNumber; + + [DcfExport(maxlength = 243)] + public string NetworkName = ""; //Max 243 characters + + [DcfExport] + public bool CANopenManager; //1 = CANopen manager, 0 or missing = not the manager + + [DcfExport] + public UInt32 LSS_SerialNumber; + + } + + public class SupportedModules : InfoSection + { + [EdsExport] + public UInt16 NrOfEntries; + + public SupportedModules() + { + infoheader = "CAN OPEN Supported Modules"; + edssection = "SupportedModules"; + } + + public SupportedModules(Dictionary section) : this() + { + Parse(section,edssection); + } + + + } + + public class ConnectedModules : SupportedObjects + { + [EdsExport] + public UInt16 NrOfEntries + { + get { return (UInt16)connectedmodulelist.Count; } + } + + public Dictionary connectedmodulelist; + + public ConnectedModules() + { + infoheader = "CAN OPEN Connected Modules"; + edssection = "ConnectedModules"; + countmsg = "NrOfEntries"; + connectedmodulelist = new Dictionary(); + } + + public ConnectedModules(Dictionary section) : this() + { + Parse(section); + + + foreach(KeyValuePair kvp in this.objectlist) + { + + + UInt16 K = (UInt16)kvp.Value; + UInt16 V = (UInt16)kvp.Key; + + connectedmodulelist.Add(K, V); + + + } + + } + + } + + public class MxFixedObjects : SupportedObjects + { + [EdsExport] + public UInt16 NrOfEntries + { + get { return (UInt16)connectedmodulelist.Count; } + } + + public Dictionary connectedmodulelist; + + private int _moduleindex; + + public int Moduleindex + { + get { return _moduleindex; } + set { _moduleindex = value; edssection = String.Format("M{0}FixedObjects",value); } + } + + public MxFixedObjects(UInt16 modindex) + { + infoheader = "CAN OPEN Module Fixed Objects"; + this.Moduleindex = modindex; + countmsg = "NrOfEntries"; + connectedmodulelist = new Dictionary(); + } + + public MxFixedObjects(Dictionary section, UInt16 modindex) : this(modindex) + { + Parse(section); + + foreach (KeyValuePair kvp in this.objectlist) + { + connectedmodulelist.Add((UInt16)kvp.Value, (UInt16)kvp.Key); + } + } + + } + + + + public class ModuleInfo : InfoSection + { + [EdsExport(maxlength = 248)] + public string ProductName; + + [EdsExport] + public byte ProductVersion; + + [EdsExport] + public byte ProductRevision; + + [EdsExport] + public string OrderCode; + + UInt16 moduleindex = 0; + + public ModuleInfo(UInt16 moduleindex) + { + this.moduleindex = moduleindex; + infoheader = "CAN OPEN Module Info " + moduleindex.ToString(); + edssection = string.Format("M{0}{1}", moduleindex, "ModuleInfo"); + } + + public ModuleInfo(Dictionary section, UInt16 moduleindex) : this (moduleindex) + { + Parse(section,edssection); + } + } + + + public class ModuleComments : Comments + { + + UInt16 moduleindex; + + public ModuleComments(UInt16 moduleindex) + { + this.moduleindex = moduleindex; + infoheader = "CAN OPEN Module Comments " + moduleindex.ToString(); + edssection = string.Format("M{0}{1}", moduleindex, "Comments"); + } + + public ModuleComments(Dictionary section,UInt16 moduleindex) : this (moduleindex) + { + Parse(section); + } + + + } + + public class ModuleSubExtends : SupportedObjects + { + + UInt16 moduleindex; + + public ModuleSubExtends(UInt16 moduleindex) + : base() + { + this.moduleindex = moduleindex; + infoheader = "CAN OPEN ModuleSubExtends "+moduleindex.ToString(); + edssection = string.Format("M{0}{1}", moduleindex, "SubExtends"); + } + + public ModuleSubExtends(Dictionary section, UInt16 moduleindex) + : this(moduleindex) + { + Parse(section); + } + + } + + public class ODentry + { + private UInt16 _index; + + /// + /// The index of the object in the Object Dictionary + /// This cannot be set for child objects, if you read a child object you get the parents index + /// + [EdsExport] + public UInt16 Index + { + get + { + if (parent != null) + return parent.Index; + else + return _index; + } + set + { + if(value==0) + { + + //throw (new Exception("Object index must be set")); + } + + if(parent == null) + { + _index = value; + } + else + { + + //throw (new Exception("Typing to set index of a subobject")); + } + + } + } + + [EdsExport] + public string parameter_name = ""; + + [DcfExport] + public string denotation = ""; + + [EdsExport] + public ObjectType objecttype = ObjectType.UNKNOWN; + [EdsExport] + public DataType datatype = DataType.UNKNOWN; + [EdsExport] + public EDSsharp.AccessType accesstype = EDSsharp.AccessType.UNKNOWN; + + [EdsExport] + public string defaultvalue = ""; + + [EdsExport] + public string LowLimit = ""; + + [EdsExport] + public string HighLimit = ""; + + [DcfExport] + public string actualvalue = ""; + + [EdsExport] + public Byte ObjFlags = 0; + + [EdsExport] + public byte CompactSubObj = 0; + + [EdsExport] + public bool PDOMapping + { + get + { + return PDOtype != PDOMappingType.no; + } + } + + //FIXME Count "If several modules are gathered to form a new Sub-Index, + //then the number is 0, followed by semicolon and the + //number of bits that are created per module to build a new + //Sub-Index" + + [EdsExport] + public byte count = 0; + + [EdsExport] + public byte ObjExtend = 0; + + public PDOMappingType PDOtype = PDOMappingType.no; + + public string Label = ""; + public string Description = ""; + public SortedDictionary subobjects = new SortedDictionary(); + public ODentry parent = null; + + public CustomProperties prop = new CustomProperties(); + + //XDD Extensions// + public string uniqueID; + + /// + /// Used when writing out objects to know if we are writing the normal or the module parts out + /// Two module parts subext and fixed are available. + /// + public enum Odtype + { + NORMAL, + SUBEXT, + FIXED, + } + + /// + /// Empty object constructor + /// + public ODentry() + { + + } + + /// + /// ODentry constructor for a simple VAR type + /// + /// Name of Object Dictionary Entry + /// Index of object in object dictionary + /// Type of this objects data + /// Default value (always set as a string) + /// Allowed CANopen access permissions + /// Allowed PDO mapping options + public ODentry(string parameter_name,UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping) + { + this.parameter_name = parameter_name; + this.Index = index; + this.objecttype = ObjectType.VAR; + this.datatype = datatype; + this.defaultvalue = defaultvalue; + + + if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) + this.accesstype = accesstype; + else + throw new ParameterException("AccessType invalid"); + + this.PDOtype = PDOMapping; + + } + + /// + /// ODConstructor useful for subobjects + /// + /// + /// NOT USED + /// + /// + /// + /// + /// + public ODentry(string parameter_name, UInt16 index, DataType datatype, string defaultvalue, EDSsharp.AccessType accesstype, PDOMappingType PDOMapping, ODentry parent) + { + this.parent = parent; + this.parameter_name = parameter_name; + this.objecttype = ObjectType.VAR; + this.datatype = datatype; + this.defaultvalue = defaultvalue; + this.Index = index; + + if (accesstype >= EDSsharp.AccessType_Min && accesstype <= EDSsharp.AccessType_Max) + this.accesstype = accesstype; + else + throw new ParameterException("AccessType invalid"); + + this.PDOtype = PDOMapping; + } + + + /// + /// ODEntry constructor for array subobjects + /// + /// + /// + /// + public ODentry(string parameter_name,UInt16 index, byte nosubindex) + { + this.parameter_name = parameter_name; + this.objecttype = ObjectType.ARRAY; + this.Index = index; + //this.nosubindexes = nosubindex; + this.objecttype = ObjectType.VAR; + } + + /// + /// Make a deep clone of this ODentry + /// + /// + public ODentry Clone(ODentry newParent = null) + { + ODentry newOd = new ODentry + { + parent = newParent, + parameter_name = parameter_name, + denotation = denotation, + objecttype = objecttype, + datatype = datatype, + accesstype = accesstype, + PDOtype = PDOtype, + defaultvalue = defaultvalue, + LowLimit = LowLimit, + HighLimit = HighLimit, + actualvalue = actualvalue, + Label = Label, + Description = Description, + subobjects = new SortedDictionary(), + prop = prop.Clone() + }; + + foreach (KeyValuePair kvp in subobjects) + newOd.subobjects.Add(kvp.Key, kvp.Value.Clone(newOd)); + + return newOd; + } + + /// + /// Provide a simple string representation of the object, only parameters index, no subindexes/subindex parameter name and data type are included + /// Useful for debug and also appears in debugger when you inspect this object + /// + /// string summary of object + public override string ToString() + { + if (subobjects.Count > 0) + { + return String.Format("{0:x4}[{1}] : {2} : {3}", Index, subobjects.Count, parameter_name, datatype); + + } + else + { + return String.Format("{0:x4}/{1} : {2} : {3}", Index, Subindex, parameter_name, datatype); + } + } + + public string ObjectTypeString() + { + switch (objecttype) + { + default: + case ObjectType.VAR: return "VAR"; + case ObjectType.ARRAY: return "ARRAY"; + case ObjectType.REC: return "RECORD"; + } + } + + public void ObjectTypeString(string objectType) + { + switch (objectType) + { + default: + case "VAR": this.objecttype = ObjectType.VAR; break; + case "ARRAY": this.objecttype = ObjectType.ARRAY; break; + case "REC": + case "RECORD": this.objecttype = ObjectType.REC; break; + } + } + + public AccessSDO AccessSDO() + { + EDSsharp.AccessType accType = accesstype; + if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) + accType = parent.accesstype; + + switch (accType) + { + default: + return libEDSsharp.AccessSDO.no; + case EDSsharp.AccessType.ro: + case EDSsharp.AccessType.@const: + return libEDSsharp.AccessSDO.ro; + case EDSsharp.AccessType.wo: + return libEDSsharp.AccessSDO.wo; + case EDSsharp.AccessType.rw: + case EDSsharp.AccessType.rwr: + case EDSsharp.AccessType.rww: + return libEDSsharp.AccessSDO.rw; + } + } + + public void AccessSDO(AccessSDO accessSDO, AccessPDO accessPDO) + { + switch (accessSDO) + { + default: + accesstype = EDSsharp.AccessType.UNKNOWN; + break; + case libEDSsharp.AccessSDO.ro: + accesstype = EDSsharp.AccessType.ro; + break; + case libEDSsharp.AccessSDO.wo: + accesstype = EDSsharp.AccessType.wo; + break; + case libEDSsharp.AccessSDO.rw: + if (accessPDO == libEDSsharp.AccessPDO.r) + accesstype = EDSsharp.AccessType.rwr; + else if (accessPDO == libEDSsharp.AccessPDO.t) + accesstype = EDSsharp.AccessType.rww; + else + accesstype = EDSsharp.AccessType.rw; + break; + } + } + + public AccessPDO AccessPDO() + { + EDSsharp.AccessType accType = accesstype; + if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) + accType = parent.accesstype; + + if (PDOtype == PDOMappingType.RPDO || accType == EDSsharp.AccessType.rwr) + return libEDSsharp.AccessPDO.r; + else if (PDOtype == PDOMappingType.TPDO || accType == EDSsharp.AccessType.rww) + return libEDSsharp.AccessPDO.t; + if (PDOtype == PDOMappingType.optional || PDOtype == PDOMappingType.@default) + return libEDSsharp.AccessPDO.tr; + else + return libEDSsharp.AccessPDO.no; + } + + public void AccessPDO(AccessPDO accessPDO) + { + switch (accessPDO) + { + default: + PDOtype = PDOMappingType.no; + break; + case libEDSsharp.AccessPDO.r: + PDOtype = PDOMappingType.RPDO; + break; + case libEDSsharp.AccessPDO.t: + PDOtype = PDOMappingType.TPDO; + break; + case libEDSsharp.AccessPDO.tr: + PDOtype = PDOMappingType.optional; + break; + } + } + + /// + /// Duplicate current sub entry and add it to parent + /// + /// true on successfull addition + public ODentry AddSubEntry() + { + ODentry baseObject = parent == null ? this : parent; + + if (baseObject.objecttype == ObjectType.VAR) + return null; + + ODentry lastSubOd = baseObject.subobjects.Values.Last(); + ODentry originalOd = null; + ODentry newOd; + UInt16 maxSubIndex = 1; + UInt16 lastSubIndex = 1; + + // create new or clone existing sub od + if (lastSubOd == null || lastSubOd.Subindex < 1) + { + newOd = new ODentry + { + parent = baseObject, + parameter_name = "item", + objecttype = ObjectType.VAR, + datatype = DataType.UNSIGNED32 + }; + } + else + { + originalOd = (parent != null && this.Subindex > 0) ? this : lastSubOd; + newOd = originalOd.Clone(originalOd.parent); + maxSubIndex = EDSsharp.ConvertToUInt16(baseObject.subobjects[0].defaultvalue); + lastSubIndex = lastSubOd.Subindex; + } + + // insert new sub od + SortedDictionary newSubObjects = new SortedDictionary(); + UInt16 newSubIndex = 0; + foreach (ODentry subOd in baseObject.subobjects.Values) + { + if (subOd.Subindex > newSubIndex) + newSubIndex = subOd.Subindex; + + newSubObjects.Add(newSubIndex++, subOd); + + if (originalOd == subOd) + newSubObjects.Add(newSubIndex++, newOd); + } + if (originalOd == null) + newSubObjects.Add(newSubIndex++, newOd); + + baseObject.subobjects = newSubObjects; + + // Write maxSubIndex to first sub index + if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && baseObject.subobjects.Count > 0) + { + baseObject.subobjects[0].defaultvalue = string.Format("0x{0:X2}", newSubIndex - 1); + } + + return newOd; + } + + /// + /// Remove current sub entry + /// + /// Renumber subentries + /// true on successfull removal + public bool RemoveSubEntry(bool renumber) + { + if (parent != null && (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.REC)) + { + UInt16 maxSubIndex = EDSsharp.ConvertToUInt16(parent.subobjects[0].defaultvalue); + UInt16 lastSubIndex = parent.subobjects.Values.Last().Subindex; + + parent.subobjects.Remove(Subindex); + + if (renumber) + { + SortedDictionary newSubObjects = new SortedDictionary(); + UInt16 subIndex = 0; + foreach (ODentry subOd in parent.subobjects.Values) + newSubObjects.Add(subIndex++, subOd); + parent.subobjects = newSubObjects; + } + + // Write maxSubIndex to first sub index + if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && parent.subobjects.Count > 0) + { + parent.subobjects[0].defaultvalue = string.Format("0x{0:X2}", parent.subobjects.Values.Last().Subindex); + } + + return true; + } + return false; + } + + /// + /// If data type is an octet string we must remove all spaces when writing out to a EDS/DCF file + /// + /// Value to be processed + /// value if not octet string or value with spaces removed if octet string + public string Formatoctetstring(string value) + { + DataType dt = datatype; + if (dt == DataType.UNKNOWN && this.parent != null) + dt = parent.datatype; + + string ret = value; + + if (dt == DataType.OCTET_STRING) + { + ret = value.Replace(" ", ""); + } + + return ret; + } + + /// + /// Write out this Object dictionary entry to an EDS/DCF file using correct formatting + /// + /// Handle to the stream writer to write to + /// File type being written + /// + public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odtype.NORMAL, int module=0) + { + + string fixedmodheader = ""; + + if (odt == Odtype.FIXED) + { + fixedmodheader = string.Format("M{0}Fixed", module); + } + + if(odt == Odtype.SUBEXT) + { + fixedmodheader = string.Format("M{0}SubExt", module); + } + + if (parent != null) + { + writer.WriteLine(string.Format("[{0}{1:X}sub{2:X}]", fixedmodheader,Index, Subindex)); + } + else + { + writer.WriteLine(string.Format("[{0}{1:X}]",fixedmodheader,Index)); + } + + writer.WriteLine(string.Format("ParameterName={0}", parameter_name)); + + if(ft == InfoSection.Filetype.File_DCF) + { + writer.WriteLine(string.Format("Denotation={0}", denotation)); + } + + writer.WriteLine(string.Format("ObjectType=0x{0:X}", (int)objecttype)); + writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); + + if (objecttype == ObjectType.ARRAY) + { + writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); + } + + if (objecttype == ObjectType.REC) + { + writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); + } + + if (objecttype == ObjectType.VAR) + { + DataType dt = datatype; + if (dt == DataType.UNKNOWN && this.parent != null) + dt = parent.datatype; + writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); + writer.WriteLine(string.Format("AccessType={0}", accesstype.ToString())); + + + if(HighLimit != null && HighLimit != "") + { + writer.WriteLine(string.Format("HighLimit={0}", Formatoctetstring(HighLimit))); + } + + if (LowLimit != null && LowLimit != "") + { + writer.WriteLine(string.Format("LowLimit={0}", Formatoctetstring(LowLimit))); + } + + writer.WriteLine(string.Format("DefaultValue={0}", Formatoctetstring(defaultvalue))); + + //TODO If the ObjectType is domain (0x2) the value of the object may be stored in a file,UploadFile and DownloadFile + if (ft == InfoSection.Filetype.File_DCF) + { + writer.WriteLine(string.Format("ParameterValue={0}", Formatoctetstring(actualvalue))); + } + + writer.WriteLine(string.Format("PDOMapping={0}", PDOMapping==true?1:0)); + + if (prop.CO_flagsPDO == true) + { + writer.WriteLine(";TPDODetectCos=1"); + } + + + } + + //Count is for modules in the [MxSubExtxxxx] + //Should we export this on EDS only, or DCF or both? + if (odt == Odtype.SUBEXT ) + { + writer.WriteLine(string.Format("Count={0}", count)); + writer.WriteLine(string.Format("ObjExtend={0}", ObjExtend)); + } + + //ObjectFlags is always optional (Page 15, DSP306) and used for DCF writing to nodes + //also recommended not to write if it is already 0 + if (ObjFlags != 0) + { + writer.WriteLine(string.Format("ObjFlags={0}", ObjFlags)); + } + + writer.WriteLine(""); + } + + /// + /// Returns a c compatible string that represents the name of the object, - is replaced with _ + /// words separated by a space are replaced with _ for a separator eg ONE TWO becomes ONE_TWO + /// + /// + public string Paramater_cname() + { + string cname = parameter_name.Replace("-", "_"); + + cname = Regex.Replace(cname, @"([A-Z]) ([A-Z])", "$1_$2"); + cname = cname.Replace(" ", ""); + + return cname; + } + + /// + /// Return the size in bytes for the given CANopen datatype of this object, eg the size of what ever the datatype field is set to + /// + /// no of bytes + public int Sizeofdatatype() + { + DataType dt = datatype; + + if (dt == DataType.UNKNOWN && this.parent != null) + dt = parent.datatype; + + switch (dt) + { + case DataType.BOOLEAN: + return 1; + + case DataType.UNSIGNED8: + case DataType.INTEGER8: + return 8; + + case DataType.VISIBLE_STRING: + case DataType.OCTET_STRING: + return Lengthofstring*8; + + case DataType.INTEGER16: + case DataType.UNSIGNED16: + case DataType.UNICODE_STRING: + return 16; //FIXME is this corret for UNICODE_STRING seems dodgy? + + case DataType.UNSIGNED24: + case DataType.INTEGER24: + return 24; + + case DataType.INTEGER32: + case DataType.UNSIGNED32: + case DataType.REAL32: + return 32; + + case DataType.INTEGER40: + case DataType.UNSIGNED40: + return 40; + + case DataType.INTEGER48: + case DataType.UNSIGNED48: + case DataType.TIME_DIFFERENCE: + case DataType.TIME_OF_DAY: + return 48; + + case DataType.INTEGER56: + case DataType.UNSIGNED56: + return 56; + + case DataType.INTEGER64: + case DataType.UNSIGNED64: + case DataType.REAL64: + return 64; + + case DataType.DOMAIN: + return 0; + + default: //FIXME + return 0; + + } + } + + + /// + /// This is the no of subindexes present in the object, it is NOT the maximum subobject index + /// + [EdsExport] + public int Nosubindexes + { + get + { + return subobjects.Count; + } + } + + //warning eds files with gaps in subobject lists have been seen in the wild + //this function tries to get the array index based on sub number not array number + //it may return null + //This needs expanding to be used globally through the application ;-( + public ODentry Getsubobject(UInt16 no) + { + if (subobjects.ContainsKey(no)) + return subobjects[no]; + return null; + } + + public string Getsubobjectdefaultvalue(UInt16 no) + { + if (subobjects.ContainsKey(no)) + return subobjects[no].defaultvalue; + else + return ""; + } + + public bool Containssubindex(UInt16 no) + { + if (subobjects.ContainsKey(no)) + return true; + + return false; + } + + public byte Getmaxsubindex() + { + //Although subindex 0 should contain the max subindex value + //we don't enforce that anywhere in this lib, we should have a setter function + //that sets it to the highest subobject found. + if (objecttype == ObjectType.ARRAY || objecttype == ObjectType.REC) + if (Containssubindex(0)) + { + return EDSsharp.ConvertToByte(Getsubobjectdefaultvalue(0)); + } + + return 0; + } + + public int Lengthofstring + { + get + { + string defaultvalue = this.defaultvalue; + if (defaultvalue == null) + return 0; + + switch (this.datatype) + { + case DataType.VISIBLE_STRING: + { + return defaultvalue.Unescape().Length; + } + + case DataType.OCTET_STRING: + { + return Regex.Replace(defaultvalue, @"\s", "").Length / 2; + } + + case DataType.UNICODE_STRING: + { + return Regex.Replace(defaultvalue, @"\s", "").Length / 4; + } + default: + { + return 0; + } + } + } + } + + public UInt16 Subindex + { + get + { + if(this.parent!=null) + { + return parent.Findsubindex(this); + } + return 0; + + } + } + + public UInt16 Findsubindex(ODentry od) + { + foreach(KeyValuePairkvp in subobjects ) + { + if (kvp.Value == od) + return kvp.Key; + } + + return 0; + + } + + /// + /// Add an existing entry as a subobject of this OD + /// + /// + /// + public void addsubobject(byte index, ODentry sub) + { + sub.parent = this; + this.subobjects.Add(index, sub); + } + + } + + public class Module + { + + public ModuleInfo mi; + public ModuleComments mc; + public ModuleSubExtends mse; + public MxFixedObjects mxfo; + public SortedDictionary modulefixedobjects; + public SortedDictionary modulesubext; + + public UInt16 moduleindex; + + public Module(UInt16 moduleindex) + { + + this.moduleindex = moduleindex; + + mi = new ModuleInfo(moduleindex); + mc = new ModuleComments(moduleindex); + mse = new ModuleSubExtends(moduleindex); + mxfo = new MxFixedObjects(moduleindex); + modulefixedobjects = new SortedDictionary(); + modulesubext = new SortedDictionary(); + } + + + + } + + public class EDSsharp + { + + public enum AccessType + { + rw = 0, + ro = 1, + wo = 2, + rwr = 3, + rww = 4, + @const = 5, + UNKNOWN + } + + public const AccessType AccessType_Min = AccessType.rw; + public const AccessType AccessType_Max = AccessType.@const; + + + // File name of the opened project. Multiple file types are possible + // for opened project file, but project is always saved as xdd_v1.1 + // Filename within the FileInfo structure has only limited usage. + public string projectFilename = ""; + // File name, when project is opened in xdd_v1.1 or project is saved + public string xddfilename_1_1 = ""; + // File names for exported files + public string xddfilenameStripped = ""; + public string edsfilename = ""; + public string dcffilename = ""; + public string ODfilename = ""; + public string ODfileVersion = ""; + public string mdfilename = ""; + public string xmlfilename = ""; // old format + public string xddfilename_1_0 = ""; // old format + + //This is memorized, when XDD v1.1 is opened. It keeps all elements + //from original XDD file, which are not handled by libedesharp, so + //they will be preserved, when the file will be saved. + //Object dictionary parameters are not stored here. + public ISO15745ProfileContainer xddTemplate = null; + + //property to indicate unsaved data; + private bool _dirty; + public bool Dirty + { + get + { + return _dirty; + } + set + { + _dirty = value; + OnDataDirty?.Invoke(_dirty, this); + } + } + + protected Dictionary> eds; + protected Dictionary sectionlinenos; + public SortedDictionary ods; + public SortedDictionary dummy_ods; + + public CO_storageGroups CO_storageGroups = new CO_storageGroups(); + + public FileInfo fi; + public DeviceInfo di; + public MandatoryObjects md; + public OptionalObjects oo; + public ManufacturerObjects mo; + public Comments c; + public Dummyusage du; + public DeviceCommissioning dc; + + public TypeDefinitions td; + + public SupportedModules sm; + public ConnectedModules cm; + + // public Dictionary mi; + // public Dictionary mc; + // public Dictionary mse; + // public Dictionary mxfo; + // public SortedDictionary> modulefixedobjects; + // public SortedDictionary> modulesubext; + + public Dictionary modules; + + public UInt16 NodeId = 0; + + public delegate void DataDirty(bool dirty, EDSsharp sender); + public event DataDirty OnDataDirty; + + public EDSsharp() + { + + + eds = new Dictionary>(); + ods = new SortedDictionary(); + dummy_ods = new SortedDictionary(); + + fi = new FileInfo(); + di = new DeviceInfo(); + du = new Dummyusage(); + md = new MandatoryObjects(); + oo = new OptionalObjects(); + mo = new ManufacturerObjects(); + dc = new DeviceCommissioning(); + c = new Comments(); + sm = new SupportedModules(); + cm = new ConnectedModules(); + td = new TypeDefinitions(); + + + //mi = new Dictionary(); + //mc = new Dictionary(); + //mse = new Dictionary(); + //mxfo = new Dictionary (); + //modulefixedobjects = new SortedDictionary>(); + //modulesubext = new SortedDictionary>(); + + modules = new Dictionary(); + + + //FIXME no way for the Major/Minor to make it to EDSVersion + fi.EDSVersionMajor = 4; + fi.EDSVersionMinor = 0; + + fi.FileVersion = "1"; + fi.FileRevision = 1; + + fi.CreationDateTime = DateTime.Now; + fi.ModificationDateTime = DateTime.Now; + + du.Dummy0001 = false; + du.Dummy0002 = true; + du.Dummy0003 = true; + du.Dummy0004 = true; + du.Dummy0005 = true; + du.Dummy0006 = true; + du.Dummy0007 = true; + + ODentry od = new ODentry(); + + dummy_ods.Add(0x002, new ODentry("Dummy Int8", 0x002, DataType.INTEGER8, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x003, new ODentry("Dummy Int16", 0x003, DataType.INTEGER16, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x004, new ODentry("Dummy Int32", 0x004, DataType.INTEGER32, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x005, new ODentry("Dummy UInt8", 0x005, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x006, new ODentry("Dummy UInt16", 0x006, DataType.UNSIGNED16, "0", AccessType.ro, PDOMappingType.optional, null)); + dummy_ods.Add(0x007, new ODentry("Dummy UInt32", 0x007, DataType.UNSIGNED32, "0", AccessType.ro, PDOMappingType.optional, null)); + + } + + protected string sectionname = ""; + + /// + /// Verify PDO mapping parameters in Object Dictionary. Every mapped OD entry must exist and mapping must be allowed + /// + /// List of error strings, empty if no errors found. + public List VerifyPDOMapping() + { + List mappingErrors = new List(); + + foreach (KeyValuePair kvp in ods) + { + int indexPdo = kvp.Key; + if (!((indexPdo >= 0x1600 && indexPdo < 0x1800) || (indexPdo >= 0x1A00 && indexPdo < 0x1C00))) + continue; + + string PDO = indexPdo < 0x1800 ? "RPDO" : "TPDO"; + + ODentry odPdo = kvp.Value; + for (byte subIdxPdo = 1; subIdxPdo < odPdo.subobjects.Count; subIdxPdo++) + { + UInt32 mapVal; + try { mapVal = (UInt32)new System.ComponentModel.UInt32Converter().ConvertFromString(odPdo.subobjects[subIdxPdo].defaultvalue); } + catch (Exception) { continue; } + + UInt16 mapIdx = (UInt16)(mapVal >> 16); + UInt16 mapSub = (UInt16)((mapVal >> 8) & 0xFF); + + if (mapIdx < 0x1000) + continue; + + bool missing = true; + AccessPDO accessPDO = AccessPDO.no; + if (ods.ContainsKey(mapIdx)) + { + ODentry od = ods[mapIdx]; + if (!od.prop.CO_disabled) + { + if (od.objecttype == ObjectType.VAR) + { + missing = false; + accessPDO = od.AccessPDO(); + } + else if (od.subobjects.ContainsKey(mapSub)) + { + missing = false; + accessPDO = od.subobjects[mapSub].AccessPDO(); + } + } + } + if (missing) + mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: missing OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); + else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.t) || (PDO == "TPDO" && accessPDO == AccessPDO.r)) + mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: not mappable OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); + } + } + + return mappingErrors; + } + + public void Parseline(string linex,int no) + { + + string key = ""; + string value = ""; + + string line = linex.TrimStart(';'); + bool custom_extension = false; + + if (linex == null || linex == "") + return; + + if (linex[0] == ';') + custom_extension = true; + + + //extract sections + { + string pat = @"^\[([a-z0-9]+)\]"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(line); + if (m.Success) + { + Group g = m.Groups[1]; + sectionname = g.ToString(); + + if (!eds.ContainsKey(sectionname)) + { + eds.Add(sectionname, new Dictionary()); + } + else + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {0} : Duplicate section [{1}] ", no,sectionname)); + } + } + } + + //extract keyvalues + { + //Bug #70 Eat whitespace! + string pat = @"^([a-z0-9_]+)[ ]*=[ ]*(.*)"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(line); + if (m.Success) + { + key = m.Groups[1].ToString(); + value = m.Groups[2].ToString(); + value = value.TrimEnd(' ','\t','\n','\r'); + + //not sure how we actually get here with out a section being in the dictionary already.. + //suspect this is dead code. + if (!eds.ContainsKey(sectionname)) + { + eds.Add(sectionname, new Dictionary()); + } + + if (custom_extension == false) + { + try + { + eds[sectionname].Add(key, value); + } + catch(Exception) + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate key \"{0}\" value \"{1}\" in section [{2}]", key,value,sectionname, no)); + } + } + else + //Only allow our own extensions to populate the key/value pair + { + if (key == "StorageLocation" || key== "TPDODetectCos") + { + try + { + eds[sectionname].Add(key, value); + } + catch(Exception) + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate custom key \"{0}\" value \"{1}\" in section [{2}]", key, value, sectionname, no)); + } + } + } + } + } + } + + public void ParseEDSentry(KeyValuePair> kvp) + { + string section = kvp.Key; + + string pat = @"^(M[0-9a-fA-F]+(Fixed|SubExt))?([a-fA-F0-9]+)(sub)?([0-9a-fA-F]*)$"; + + Regex r = new Regex(pat); + Match m = r.Match(section); + if (m.Success) + { + + SortedDictionary target = this.ods; + + //** MODULE DCF SUPPORT + + string pat2 = @"^M([0-9a-fA-F]+)(Fixed|SubExt)([0-9a-fA-F]+)"; + Regex r2 = new Regex(pat2, RegexOptions.IgnoreCase); + Match m2 = r2.Match(m.Groups[0].ToString()); + + if (m2.Success) + { + + UInt16 modindex = Convert.ToUInt16(m2.Groups[1].Value); + UInt16 odindex = Convert.ToUInt16(m2.Groups[3].Value); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + if (m2.Groups[2].ToString() == "SubExt") + { + target = modules[modindex].modulesubext; + + } + else + { + target = modules[modindex].modulefixedobjects; + } + } + + + ODentry od = new ODentry + { + //Indexes in the EDS are always in hex format without the pre 0x + Index = Convert.ToUInt16(m.Groups[3].ToString(), 16) + }; + + //Parameter name, mandatory always + if (!kvp.Value.ContainsKey("ParameterName")) + throw new ParameterException("Missing required field ParameterName on" + section); + od.parameter_name = kvp.Value["ParameterName"]; + + //Object type, assumed to be VAR unless specified + if (kvp.Value.ContainsKey("ObjectType")) + { + int type = Convert.ToInt16(kvp.Value["ObjectType"], Getbase(kvp.Value["ObjectType"])); + od.objecttype = (ObjectType)type; + } + else + { + od.objecttype = ObjectType.VAR; + } + + if(kvp.Value.ContainsKey("CompactSubObj")) + { + od.CompactSubObj = Convert.ToByte(kvp.Value["CompactSubObj"],Getbase(kvp.Value["CompactSubObj"])); + } + + if(kvp.Value.ContainsKey("ObjFlags")) + { + od.ObjFlags = Convert.ToByte(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); + } + else + { + od.ObjFlags = 0; + } + + //Access Type + if(kvp.Value.ContainsKey("StorageLocation")) + { + od.prop.CO_storageGroup = kvp.Value["StorageLocation"]; + } + + if (kvp.Value.ContainsKey("TPDODetectCos")) + { + string test = kvp.Value["TPDODetectCos"].ToLower(); + if (test == "1" || test == "true") + { + od.prop.CO_flagsPDO = true; + } + else + od.prop.CO_flagsPDO = false; + } + + if (kvp.Value.ContainsKey("Count")) + { + od.count = Convert.ToByte(kvp.Value["Count"]); + } + + if (kvp.Value.ContainsKey("ObjExtend")) + { + od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); + } + + + if (od.objecttype == ObjectType.VAR) + { + + if (kvp.Value.ContainsKey("CompactSubObj")) + throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); + + if (kvp.Value.ContainsKey("ParameterValue")) + { + od.actualvalue = kvp.Value["ParameterValue"]; + } + + if (kvp.Value.ContainsKey("HighLimit")) + { + od.HighLimit = kvp.Value["HighLimit"]; + } + + if (kvp.Value.ContainsKey("LowLimit")) + { + od.LowLimit = kvp.Value["LowLimit"]; + } + + if (kvp.Value.ContainsKey("Denotation")) + { + od.denotation = kvp.Value["Denotation"]; + } + + if (m.Groups[5].Length != 0) + { + //FIXME are subindexes in hex always? + UInt16 subindex = Convert.ToUInt16(m.Groups[5].ToString(),16); + od.parent = target[od.Index]; + target[od.Index].subobjects.Add(subindex, od); + } + + if (!kvp.Value.ContainsKey("DataType")) + throw new ParameterException("Missing required field DataType on" + section); + od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); + + if (!kvp.Value.ContainsKey("AccessType")) + throw new ParameterException("Missing required AccessType on" + section); + + string accesstype = kvp.Value["AccessType"].ToLower(); + + if (Enum.IsDefined(typeof(AccessType), accesstype)) + { + od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); + } + else + { + throw new ParameterException("Unknown AccessType on" + section); + } + + if (kvp.Value.ContainsKey("DefaultValue")) + od.defaultvalue = kvp.Value["DefaultValue"]; + + od.PDOtype = PDOMappingType.no; + if (kvp.Value.ContainsKey("PDOMapping")) + { + + bool pdo = Convert.ToInt16(kvp.Value["PDOMapping"],Getbase(kvp.Value["PDOMapping"])) == 1; + if (pdo == true) + od.PDOtype = PDOMappingType.optional; + } + + } + + + if(od.objecttype == ObjectType.REC|| od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) + { + + if (od.CompactSubObj != 0) + { + if (!kvp.Value.ContainsKey("DataType")) + throw new ParameterException("Missing required field DataType on" + section); + od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); + + if (!kvp.Value.ContainsKey("AccessType")) + throw new ParameterException("Missing required AccessType on" + section); + string accesstype = kvp.Value["AccessType"]; + if (Enum.IsDefined(typeof(AccessType), accesstype)) + { + od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); + } + else + { + throw new ParameterException("Unknown AccessType on" + section); + } + + //now we generate CompactSubObj number of var objects below this parent + + if(od.CompactSubObj>=0xfe) + { + od.CompactSubObj = 0xfe; + } + + ODentry subi = new ODentry("NrOfObjects", od.Index, DataType.UNSIGNED8, String.Format("0x{0:x2}",od.CompactSubObj), AccessType.ro, PDOMappingType.no, od); + od.subobjects.Add(0x00, subi); + + for (int x=1; x<= od.CompactSubObj; x++) + { + string parameter_name = string.Format("{0}{1:x2}", od.parameter_name, x ); + ODentry sub = new ODentry(parameter_name, od.Index, od.datatype, od.defaultvalue, od.accesstype, od.PDOtype, od); + + if (kvp.Value.ContainsKey("HighLimit")) + sub.HighLimit = kvp.Value["HighLimit"]; + + if (kvp.Value.ContainsKey("LowLimit")) + sub.HighLimit = kvp.Value["LowLimit"]; + + od.subobjects.Add((ushort)(x ), sub); + } + + } + else + { + if (!kvp.Value.ContainsKey("SubNumber")) + throw new ParameterException("Missing SubNumber on Array for" + section); + + + + } + } + + if(od.objecttype == ObjectType.DOMAIN) + { + od.datatype = DataType.DOMAIN; + od.accesstype = AccessType.rw; + + if (kvp.Value.ContainsKey("DefaultValue")) + od.defaultvalue = kvp.Value["DefaultValue"]; + + } + + //Only add top level to this list + if (m.Groups[5].Length == 0) + { + target.Add(od.Index, od); + } + } + + } + + public void Loadfile(string filename) + { + + projectFilename = filename; + + if (Path.GetExtension(filename).ToLower() == ".eds") + { + edsfilename = filename; + } + + if (Path.GetExtension(filename).ToLower() == ".dcf") + { + dcffilename = filename; + } + + //try + { + int lineno = 1; + foreach (string linex in File.ReadLines(filename)) + { + Parseline(linex,lineno); + lineno++; + } + + di = new DeviceInfo(eds["DeviceInfo"]); + + foreach (KeyValuePair> kvp in eds) + { + ParseEDSentry(kvp); + } + + fi = new FileInfo(eds["FileInfo"]); + if(eds.ContainsKey("DummyUsage")) + du = new Dummyusage(eds["DummyUsage"]); + + md = new MandatoryObjects(eds["MandatoryObjects"]); + + if(eds.ContainsKey("OptionalObjects")) + oo = new OptionalObjects(eds["OptionalObjects"]); + + if(eds.ContainsKey("ManufacturerObjects")) + mo = new ManufacturerObjects(eds["ManufacturerObjects"]); + + if (eds.ContainsKey("TypeDefinitions")) + td = new TypeDefinitions(eds["TypeDefinitions"]); + + //Only DCF not EDS files + dc = new DeviceCommissioning(); + if(eds.ContainsKey("DeviceCommissioning")) + { + dc.Parse(eds["DeviceCommissioning"],"DeviceCommissioning"); + edsfilename = fi.LastEDS; + } + + c = new Comments(); + + if (eds.ContainsKey("Comments")) + c.Parse(eds["Comments"]); + + //Modules + + //FIXME + //we don't parse or support [MxFixedObjects] with MxFixedxxxx and MxFixedxxxxsubx + + if (eds.ContainsKey("SupportedModules")) + { + sm = new SupportedModules(eds["SupportedModules"]); + + //find MxModuleInfo + + foreach (string s in eds.Keys) + { + String pat = @"^M([0-9]+)ModuleInfo"; + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleInfo mi = new ModuleInfo(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mi = mi; + + } + + + pat = @"^M([0-9]+)Comments"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleComments mc = new ModuleComments(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mc = mc; + + } + + pat = @"^M([0-9]+)SubExtends"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleSubExtends mse = new ModuleSubExtends(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mse = mse; + } + + + //DCF only + pat = @"^M([0-9]+)FixedObjects"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + MxFixedObjects mxf = new MxFixedObjects(eds[s],modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mxfo = mxf; + + } + } + } + + + if (eds.ContainsKey("ConnectedModules")) + { + cm = new ConnectedModules(eds["ConnectedModules"]); + } + + //COMPACT PDO + + if (di.CompactPDO != 0) + { + + for (UInt16 index = 0x1400; index < 0x1600; index++) + { + ApplycompactPDO(index); + } + + for (UInt16 index = 0x1800; index < 0x1A00;index ++) + { + ApplycompactPDO(index); + } + } + + ApplyimplicitPDO(); + } + // catch(Exception e) + //{ + // Console.WriteLine("** ALL GONE WRONG **" + e.ToString()); + // } + } + + public void ApplycompactPDO(UInt16 index) + { + if (ods.ContainsKey(index)) + { + if ((!ods[index].Containssubindex(1)) && ((this.di.CompactPDO & 0x01) == 0)) + { + //Fill in cob ID + //FIX ME i'm really sure this is not correct, what default values should be used??? + string cob = string.Format("0x180+$NODEID"); + ODentry subod = new ODentry("COB-ID", index, DataType.UNSIGNED32, cob, AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x05, subod); + + } + + if ((!ods[index].Containssubindex(2)) && ((this.di.CompactPDO & 0x02) == 0)) + { + //Fill in type + + ODentry subod = new ODentry("Type", index, DataType.UNSIGNED8, "0xff", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x02, subod); + } + + if ((!ods[index].Containssubindex(3)) && ((this.di.CompactPDO & 0x04) == 0)) + { + //Fill in inhibit + + ODentry subod = new ODentry("Inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x03, subod); + } + + //NOT FOR RX PDO + if (index < 0x1800) + return; + + if ((!ods[index].Containssubindex(4)) && ((this.di.CompactPDO & 0x08) == 0)) + { + //Fill in compatibility entry + + ODentry subod = new ODentry("Compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x04, subod); + } + + if ((!ods[index].Containssubindex(5)) && ((this.di.CompactPDO & 0x10) == 0)) + { + //Fill in event timer + + ODentry subod = new ODentry("Event Timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x05, subod); + } + } + } + + /// + /// This function scans the PDO list and compares it to NrOfRXPDO and NrOfTXPDO + /// if these do not match in count then implicit PDOs are present and they are + /// filled in with default values from the lowest possible index + /// + public void ApplyimplicitPDO() + { + UInt16 totalnorxpdos = di.NrOfRXPDO; + UInt16 totalnotxpdos = di.NrOfTXPDO; + + UpdatePDOcount(); + + UInt16 noexplicitrxpdos = di.NrOfRXPDO; + UInt16 noexplicittxpdos = di.NrOfTXPDO; + + //this is how many PDOS need generating on the fly + UInt16 noimplictrxpdos = (UInt16) (totalnorxpdos - noexplicitrxpdos); + UInt16 noimplicttxpdos = (UInt16) (totalnotxpdos - noexplicittxpdos); + + for(UInt16 index = 0x1400; (index < 0x1600) && (noimplictrxpdos > 0) ;index++) + { + if(!ods.ContainsKey(index)) + { + CreateRXPDO(index); + noimplictrxpdos--; + } + } + + for (UInt16 index = 0x1800; (index < 0x1A00) && (noimplicttxpdos > 0); index++) + { + if (!ods.ContainsKey(index)) + { + CreateTXPDO(index); + noimplicttxpdos--; + } + } + + UpdatePDOcount(); + + } + + public void Savefile(string filename, InfoSection.Filetype ft) + { + if(ft==InfoSection.Filetype.File_EDS) + this.edsfilename = filename; + + if (ft == InfoSection.Filetype.File_DCF) + { + this.dcffilename = filename; + fi.LastEDS = edsfilename; + } + + UpdatePDOcount(); + + //generate date times in DS306 format; h:mmtt MM-dd-yyyy + + fi.CreationDate = fi.CreationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); + fi.CreationTime = fi.CreationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); + + fi.ModificationDate = fi.ModificationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); + fi.ModificationTime = fi.ModificationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); + + fi.FileName = Path.GetFileName(filename); + + fi.EDSVersion = "4.0"; + fi.EDSVersionMajor = 4; + fi.EDSVersionMinor = 0; + StreamWriter writer = File.CreateText(filename); - writer.NewLine = "\n"; - fi.Write(writer,ft); - di.Write(writer,ft); - du.Write(writer,ft); - c.Write(writer); - - if(ft == InfoSection.Filetype.File_DCF) - { - dc.Write(writer,ft); - } - - //regenerate the object lists - md.objectlist.Clear(); - mo.objectlist.Clear(); - oo.objectlist.Clear(); - - foreach (KeyValuePair kvp in ods) - { - ODentry entry = kvp.Value; - - if (entry.prop.CO_disabled == true) - continue; - - if (entry.Index == 0x1000 || entry.Index == 0x1001 || entry.Index == 0x1018) - { - md.objectlist.Add(md.objectlist.Count + 1, entry.Index); - } - else - if (entry.Index >= 0x2000 && entry.Index < 0x6000) - { - mo.objectlist.Add(mo.objectlist.Count + 1, entry.Index); - } - else - { - oo.objectlist.Add(oo.objectlist.Count + 1, entry.Index); - } - } - - md.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (md.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - oo.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (oo.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - mo.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (mo.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - //modules - - if (sm.NrOfEntries > 0) - { - sm.Write(writer, ft); - - for (UInt16 moduleid = 1; moduleid <= sm.NrOfEntries; moduleid++) - { - - modules[moduleid].mi.Write(writer, ft); - - modules[moduleid].mc.Write(writer); - - modules[moduleid].mse.Write(writer); - - - foreach (KeyValuePair kvp2 in modules[moduleid].modulesubext) - { - ODentry od = kvp2.Value; - od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); - - } - - modules[moduleid].mxfo.Write(writer); - - foreach (KeyValuePair kvp3 in modules[moduleid].modulefixedobjects) - { - ODentry od = kvp3.Value; - od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); - - foreach (KeyValuePair kvp4 in od.subobjects) - { - ODentry subod = kvp4.Value; - subod.Write(writer, ft, ODentry.Odtype.FIXED, moduleid); - } - } - } - } - - if (ft == InfoSection.Filetype.File_DCF) - { - if (cm.NrOfEntries > 0) - { - cm.Write(writer); - } - } - - writer.Close(); - - } - - public DataType Getdatatype(ODentry od) - { - - if (od.objecttype == ObjectType.VAR) - { - return od.datatype; - } - - if (od.objecttype == ObjectType.ARRAY) - { - ODentry sub2 = ods[od.Index]; - - //FIX ME !!! INCONSISTANT setup of the datatype for arrays when loading xml and eds!! - - DataType t = sub2.datatype; - - if (sub2.Getsubobject(1) != null) - { - t = sub2.Getsubobject(1).datatype; - if (t == DataType.UNKNOWN) - t = sub2.datatype; - } - - return t; - } - - //Warning, REC types need to be handled else where as the specific - //implementation of a REC type depends on the exporter being used - - return DataType.UNKNOWN; - - } - - - static public byte ConvertToByte(string defaultvalue) - { - if (defaultvalue == null || defaultvalue == "") - return 0; - - return (Convert.ToByte(defaultvalue, Getbase(defaultvalue))); - } - - static public UInt16 ConvertToUInt16(byte [] bytes) - { - - UInt16 value = 0; - - value = (UInt16) ((bytes[0] << 8) | bytes[1]); - - return value; - - } - - static public UInt16 ConvertToUInt16(string defaultvalue) - { - if (defaultvalue == null || defaultvalue == "" ) - return 0; - - return (Convert.ToUInt16(defaultvalue, Getbase(defaultvalue))); - } - - static public UInt32 ConvertToUInt32(string defaultvalue) - { - if (defaultvalue == null || defaultvalue == "" ) - return 0; - - return (Convert.ToUInt32(defaultvalue, Getbase(defaultvalue))); - } - - static public int Getbase(string defaultvalue) - { - - if (defaultvalue == null || defaultvalue == "") - return 10; - - int nobase = 10; - - String pat = @"^0[xX][0-9a-fA-F]+"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 16; - } - - pat = @"^0[0-9]+"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 8; - } - - - return nobase; - } - - public void UpdatePDOcount() - { - di.NrOfRXPDO = 0; - di.NrOfTXPDO = 0; - foreach(KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if(od.prop.CO_disabled == false && od.Index >= 0x1400 && od.Index < 0x1600) - di.NrOfRXPDO++; - - if(od.prop.CO_disabled == false && od.Index >= 0x1800 && od.Index < 0x1A00) - di.NrOfTXPDO++; - - } - - } - - //Split on + , replace $NODEID with concrete value and add together - public UInt32 GetNodeID(string input, out bool nodeidpresent) - { - - if (input == null || input == "") - { - nodeidpresent = false; - return 0; - } - - input = input.ToUpper(); - - if(input.Contains("$NODEID")) - nodeidpresent = true; - else - nodeidpresent = false; - - try - { - if (dc.NodeId == 0) - { - input = input.Replace("$NODEID", ""); - input = input.Replace("+", ""); - input = input.Replace(" ", ""); - return Convert.ToUInt32(input, Getbase(input)); - } - - input = input.Replace("$NODEID", String.Format("0x{0}", dc.NodeId)); - - string[] bits = input.Split('+'); - - if(bits.Length==1) - { - //nothing to parse here just return the value - return Convert.ToUInt32(input, Getbase(input)); - } - - if (bits.Length != 2) - { - throw new FormatException("cannot parse " + input + "\nExpecting N+$NODEID or $NODEID+N"); - } - - UInt32 b1 = Convert.ToUInt32(bits[0], Getbase(bits[0])); - UInt32 b2 = Convert.ToUInt32(bits[1], Getbase(bits[1])); - - return (UInt32)(b1 + b2); - } - catch(Exception e) - { - Warnings.warning_list.Add(String.Format("Error parsing node id {0} nodes, {1}", input,e.ToString())); - } - - return 0; - } - - - public bool tryGetODEntry(UInt16 index, out ODentry od) - { - od = null; - if(ods.ContainsKey(index)) - { - od = ods[index]; - return true; - } - - if(dummy_ods.ContainsKey(index)) - { - od = dummy_ods[index]; - return true; - } - - return false; - } - - //RX COM 0x1400 - //RX Map 0x1600 - //TX COM 0x1800 - //TX MAP 0x1a00 - - //call this with the comm param index not the mapping - public bool CreatePDO(bool rx,UInt16 index) - { - //check if we are creating an RX PDO it is a valid index - if (rx && (index < 0x1400 || index > 0x15ff)) - return false; - - //check if we are creating an PDO TX it is a valid index - if (!rx & (index < 0x1800 || index > 0x19ff)) - return false; - - //Check it does not already exist - if (ods.ContainsKey(index)) - return false; - - //check the associated mapping index does not exist - if (ods.ContainsKey((UInt16)(index+0x200))) - return false; - - ODentry od_comparam; - ODentry od_mapping; - - if (rx) - { - od_comparam = new ODentry("RPDO communication parameter", index, 0) - { - Description = @"0x1400 - 0x15FF RPDO communication parameter -max sub-index - -COB - ID - bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set - bit 11 - 29: set to 0 for 11 bit COB - ID - bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO - bit 31: 0(1) - node uses(does NOT use) PDO - -Transmission type - value = 0 - 240: receiving is synchronous, process after next reception of SYNC object - value = 241 - 253: not used - value = 254: manufacturer specific - value = 255: asynchronous" - }; - - od_mapping = new ODentry("RPDO mapping parameter", (UInt16)(index + 0x200), 0) - { - Description = @"0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) -Number of mapped objects - -mapped object (subindex 1...8) - bit 0 - 7: data length in bits - bit 8 - 15: subindex from OD - bit 16 - 31: index from OD" - }; - - - } - else - { - od_comparam = new ODentry("TPDO communication parameter", index, 0) - { - Description = @"0x1800 - 0x19FF TPDO communication parameter -max sub-index - -COB - ID - bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set - bit 11 - 29: set to 0 for 11 bit COB - ID - bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO - bit 31: 0(1) - node uses(does NOT use) PDO - -Transmission type - value = 0: transmitting is synchronous, specification in device profile - value = 1 - 240: transmitting is synchronous after every N - th SYNC object - value = 241 - 251: not used - value = 252 - 253: Transmitted only on reception of Remote Transmission Request - value = 254: manufacturer specific - value = 255: asynchronous, specification in device profile - -inhibit time - bit 0 - 15: Minimum time between transmissions of the PDO in 100µs.Zero disables functionality. - -event timer - bit 0-15: Time between periodic transmissions of the PDO in ms.Zero disables functionality. - -SYNC start value - value = 0: Counter of the SYNC message shall not be processed. - value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message." - }; - - - od_mapping = new ODentry("TPDO mapping parameter", (UInt16)(index + 0x200), 0) - { - Description = @"0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). -Number of mapped objects - -mapped object (subindex 1...8) - bit 0 - 7: data length in bits - bit 8 - 15: subindex from OD - bit 16 - 31: index from OD" - }; - } - - od_comparam.objecttype = ObjectType.REC; - od_comparam.prop.CO_storageGroup = "ROM"; - od_comparam.accesstype = AccessType.ro; - od_comparam.PDOtype = PDOMappingType.no; - - ODentry sub; - - - if(rx) - { - sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "2", AccessType.ro, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(0, sub); - sub = new ODentry("COB-ID used by RPDO", index, DataType.UNSIGNED32, "$NODEID+0x200", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(1, sub); - sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(2, sub); - - } - else - { - sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "6", AccessType.ro, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(0, sub); - sub = new ODentry("COB-ID used by TPDO", index, DataType.UNSIGNED32, "$NODEID+0x180", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(1, sub); - sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(2, sub); - sub = new ODentry("inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(3, sub); - //sub = new ODentry("compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); - //od_comparam.subobjects.Add(4, sub); - sub = new ODentry("event timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(5, sub); - sub = new ODentry("SYNC start value", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(6, sub); - - } - - od_mapping.objecttype = ObjectType.REC; - od_mapping.prop.CO_storageGroup = "ROM"; - od_mapping.accesstype = AccessType.rw; //Same as default but inconsistent with ROM above - od_mapping.PDOtype = PDOMappingType.no; - - sub = new ODentry("Number of mapped objects", (UInt16)(index + 0x200), DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, od_mapping); - od_mapping.subobjects.Add(0, sub); - - for (int p=1;p<=8;p++) - { - sub = new ODentry(string.Format("mapped object {0}",p), (UInt16)(index+0x200), DataType.UNSIGNED32, "0x00000000", AccessType.ro, PDOMappingType.no, od_mapping); - od_mapping.subobjects.Add((byte)p, sub); - } - - ods.Add(index, od_comparam); - ods.Add((UInt16)(index + 0x200), od_mapping); - - return true; - } - - public bool CreateTXPDO(UInt16 index) - { - return CreatePDO(false, index); - } - - public bool CreateRXPDO(UInt16 index) - { - return CreatePDO(true, index); - } - - public ODentry Getobject(UInt16 no) - { - - if(no>=0x002 && no<=0x007) - { - return dummy_ods[no]; - } - - if (ods.ContainsKey(no)) - { - return ods[no]; - } - - return null; - - } - - - public ODentry Getobject(string uniqueID) - { - foreach(KeyValuePair e in ods) - { - if (e.Value.uniqueID == uniqueID) - return e.Value; - - if(e.Value.subobjects!=null && e.Value.subobjects.Count>0) - { - foreach(KeyValuePair sube in e.Value.subobjects) - { - if (sube.Value.uniqueID == uniqueID) - return sube.Value; - } - - } - - - } - - return null; - } - - public int GetNoEnabledObjects(bool includesub=false) - { - int enabledcount = 0; - foreach (ODentry od in ods.Values) - { - if (od.prop.CO_disabled == false) - { - enabledcount++; - - if(includesub) - { - foreach(ODentry sub in od.subobjects.Values) - { - if (od.prop.CO_disabled == false) - { - enabledcount++; - } - } - - } - } - } - - return enabledcount; - - } - - - - } - - public class ParameterException : Exception - { - public ParameterException(String message) - : base(message) - { - - } - } - - - - } + writer.NewLine = "\n"; + fi.Write(writer,ft); + di.Write(writer,ft); + du.Write(writer,ft); + c.Write(writer); + + if(ft == InfoSection.Filetype.File_DCF) + { + dc.Write(writer,ft); + } + + //regenerate the object lists + md.objectlist.Clear(); + mo.objectlist.Clear(); + oo.objectlist.Clear(); + + foreach (KeyValuePair kvp in ods) + { + ODentry entry = kvp.Value; + + if (entry.prop.CO_disabled == true) + continue; + + if (entry.Index == 0x1000 || entry.Index == 0x1001 || entry.Index == 0x1018) + { + md.objectlist.Add(md.objectlist.Count + 1, entry.Index); + } + else + if (entry.Index >= 0x2000 && entry.Index < 0x6000) + { + mo.objectlist.Add(mo.objectlist.Count + 1, entry.Index); + } + else + { + oo.objectlist.Add(oo.objectlist.Count + 1, entry.Index); + } + } + + md.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (md.objectlist.ContainsValue(od.Index)) + { + od.Write(writer,ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer,ft); + } + } + } + + oo.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (oo.objectlist.ContainsValue(od.Index)) + { + od.Write(writer,ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer,ft); + } + } + } + + mo.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (mo.objectlist.ContainsValue(od.Index)) + { + od.Write(writer,ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer,ft); + } + } + } + + //modules + + if (sm.NrOfEntries > 0) + { + sm.Write(writer, ft); + + for (UInt16 moduleid = 1; moduleid <= sm.NrOfEntries; moduleid++) + { + + modules[moduleid].mi.Write(writer, ft); + + modules[moduleid].mc.Write(writer); + + modules[moduleid].mse.Write(writer); + + + foreach (KeyValuePair kvp2 in modules[moduleid].modulesubext) + { + ODentry od = kvp2.Value; + od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); + + } + + modules[moduleid].mxfo.Write(writer); + + foreach (KeyValuePair kvp3 in modules[moduleid].modulefixedobjects) + { + ODentry od = kvp3.Value; + od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); + + foreach (KeyValuePair kvp4 in od.subobjects) + { + ODentry subod = kvp4.Value; + subod.Write(writer, ft, ODentry.Odtype.FIXED, moduleid); + } + } + } + } + + if (ft == InfoSection.Filetype.File_DCF) + { + if (cm.NrOfEntries > 0) + { + cm.Write(writer); + } + } + + writer.Close(); + + } + + public DataType Getdatatype(ODentry od) + { + + if (od.objecttype == ObjectType.VAR) + { + return od.datatype; + } + + if (od.objecttype == ObjectType.ARRAY) + { + ODentry sub2 = ods[od.Index]; + + //FIX ME !!! INCONSISTANT setup of the datatype for arrays when loading xml and eds!! + + DataType t = sub2.datatype; + + if (sub2.Getsubobject(1) != null) + { + t = sub2.Getsubobject(1).datatype; + if (t == DataType.UNKNOWN) + t = sub2.datatype; + } + + return t; + } + + //Warning, REC types need to be handled else where as the specific + //implementation of a REC type depends on the exporter being used + + return DataType.UNKNOWN; + + } + + + static public byte ConvertToByte(string defaultvalue) + { + if (defaultvalue == null || defaultvalue == "") + return 0; + + return (Convert.ToByte(defaultvalue, Getbase(defaultvalue))); + } + + static public UInt16 ConvertToUInt16(byte [] bytes) + { + + UInt16 value = 0; + + value = (UInt16) ((bytes[0] << 8) | bytes[1]); + + return value; + + } + + static public UInt16 ConvertToUInt16(string defaultvalue) + { + if (defaultvalue == null || defaultvalue == "" ) + return 0; + + return (Convert.ToUInt16(defaultvalue, Getbase(defaultvalue))); + } + + static public UInt32 ConvertToUInt32(string defaultvalue) + { + if (defaultvalue == null || defaultvalue == "" ) + return 0; + + return (Convert.ToUInt32(defaultvalue, Getbase(defaultvalue))); + } + + static public int Getbase(string defaultvalue) + { + + if (defaultvalue == null || defaultvalue == "") + return 10; + + int nobase = 10; + + String pat = @"^0[xX][0-9a-fA-F]+"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 16; + } + + pat = @"^0[0-9]+"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 8; + } + + + return nobase; + } + + public void UpdatePDOcount() + { + di.NrOfRXPDO = 0; + di.NrOfTXPDO = 0; + foreach(KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if(od.prop.CO_disabled == false && od.Index >= 0x1400 && od.Index < 0x1600) + di.NrOfRXPDO++; + + if(od.prop.CO_disabled == false && od.Index >= 0x1800 && od.Index < 0x1A00) + di.NrOfTXPDO++; + + } + + } + + //Split on + , replace $NODEID with concrete value and add together + public UInt32 GetNodeID(string input, out bool nodeidpresent) + { + + if (input == null || input == "") + { + nodeidpresent = false; + return 0; + } + + input = input.ToUpper(); + + if(input.Contains("$NODEID")) + nodeidpresent = true; + else + nodeidpresent = false; + + try + { + if (dc.NodeId == 0) + { + input = input.Replace("$NODEID", ""); + input = input.Replace("+", ""); + input = input.Replace(" ", ""); + return Convert.ToUInt32(input, Getbase(input)); + } + + input = input.Replace("$NODEID", String.Format("0x{0}", dc.NodeId)); + + string[] bits = input.Split('+'); + + if(bits.Length==1) + { + //nothing to parse here just return the value + return Convert.ToUInt32(input, Getbase(input)); + } + + if (bits.Length != 2) + { + throw new FormatException("cannot parse " + input + "\nExpecting N+$NODEID or $NODEID+N"); + } + + UInt32 b1 = Convert.ToUInt32(bits[0], Getbase(bits[0])); + UInt32 b2 = Convert.ToUInt32(bits[1], Getbase(bits[1])); + + return (UInt32)(b1 + b2); + } + catch(Exception e) + { + Warnings.warning_list.Add(String.Format("Error parsing node id {0} nodes, {1}", input,e.ToString())); + } + + return 0; + } + + + public bool tryGetODEntry(UInt16 index, out ODentry od) + { + od = null; + if(ods.ContainsKey(index)) + { + od = ods[index]; + return true; + } + + if(dummy_ods.ContainsKey(index)) + { + od = dummy_ods[index]; + return true; + } + + return false; + } + + //RX COM 0x1400 + //RX Map 0x1600 + //TX COM 0x1800 + //TX MAP 0x1a00 + + //call this with the comm param index not the mapping + public bool CreatePDO(bool rx,UInt16 index) + { + //check if we are creating an RX PDO it is a valid index + if (rx && (index < 0x1400 || index >= 0x1600)) + return false; + + //check if we are creating an PDO TX it is a valid index + if (!rx & (index < 0x1800 || index >= 0x1A00)) + return false; + + //Check it does not already exist + if (ods.ContainsKey(index)) + return false; + + //check the associated mapping index does not exist + if (ods.ContainsKey((UInt16)(index+0x200))) + return false; + + ODentry od_comparam; + ODentry od_mapping; + + if (rx) + { + od_comparam = new ODentry("RPDO communication parameter", index, 0) + { + Description = @"0x1400 - 0x15FF RPDO communication parameter +max sub-index + +COB - ID + bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set + bit 11 - 29: set to 0 for 11 bit COB - ID + bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO + bit 31: 0(1) - node uses(does NOT use) PDO + +Transmission type + value = 0 - 240: receiving is synchronous, process after next reception of SYNC object + value = 241 - 253: not used + value = 254: manufacturer specific + value = 255: asynchronous" + }; + + od_mapping = new ODentry("RPDO mapping parameter", (UInt16)(index + 0x200), 0) + { + Description = @"0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) +Number of mapped objects + +mapped object (subindex 1...8) + bit 0 - 7: data length in bits + bit 8 - 15: subindex from OD + bit 16 - 31: index from OD" + }; + + + } + else + { + od_comparam = new ODentry("TPDO communication parameter", index, 0) + { + Description = @"0x1800 - 0x19FF TPDO communication parameter +max sub-index + +COB - ID + bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set + bit 11 - 29: set to 0 for 11 bit COB - ID + bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO + bit 31: 0(1) - node uses(does NOT use) PDO + +Transmission type + value = 0: transmitting is synchronous, specification in device profile + value = 1 - 240: transmitting is synchronous after every N - th SYNC object + value = 241 - 251: not used + value = 252 - 253: Transmitted only on reception of Remote Transmission Request + value = 254: manufacturer specific + value = 255: asynchronous, specification in device profile + +inhibit time + bit 0 - 15: Minimum time between transmissions of the PDO in 100µs.Zero disables functionality. + +event timer + bit 0-15: Time between periodic transmissions of the PDO in ms.Zero disables functionality. + +SYNC start value + value = 0: Counter of the SYNC message shall not be processed. + value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message." + }; + + + od_mapping = new ODentry("TPDO mapping parameter", (UInt16)(index + 0x200), 0) + { + Description = @"0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). +Number of mapped objects + +mapped object (subindex 1...8) + bit 0 - 7: data length in bits + bit 8 - 15: subindex from OD + bit 16 - 31: index from OD" + }; + } + + od_comparam.objecttype = ObjectType.REC; + od_comparam.prop.CO_storageGroup = "ROM"; + od_comparam.accesstype = AccessType.ro; + od_comparam.PDOtype = PDOMappingType.no; + + ODentry sub; + + + if(rx) + { + sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "2", AccessType.ro, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(0, sub); + sub = new ODentry("COB-ID used by RPDO", index, DataType.UNSIGNED32, "$NODEID+0x200", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(1, sub); + sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(2, sub); + + } + else + { + sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "6", AccessType.ro, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(0, sub); + sub = new ODentry("COB-ID used by TPDO", index, DataType.UNSIGNED32, "$NODEID+0x180", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(1, sub); + sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(2, sub); + sub = new ODentry("inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(3, sub); + //sub = new ODentry("compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); + //od_comparam.subobjects.Add(4, sub); + sub = new ODentry("event timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(5, sub); + sub = new ODentry("SYNC start value", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(6, sub); + + } + + od_mapping.objecttype = ObjectType.REC; + od_mapping.prop.CO_storageGroup = "ROM"; + od_mapping.accesstype = AccessType.rw; //Same as default but inconsistent with ROM above + od_mapping.PDOtype = PDOMappingType.no; + + sub = new ODentry("Number of mapped objects", (UInt16)(index + 0x200), DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, od_mapping); + od_mapping.subobjects.Add(0, sub); + + for (int p=1;p<=8;p++) + { + sub = new ODentry(string.Format("mapped object {0}",p), (UInt16)(index+0x200), DataType.UNSIGNED32, "0x00000000", AccessType.ro, PDOMappingType.no, od_mapping); + od_mapping.subobjects.Add((byte)p, sub); + } + + ods.Add(index, od_comparam); + ods.Add((UInt16)(index + 0x200), od_mapping); + + return true; + } + + public bool CreateTXPDO(UInt16 index) + { + return CreatePDO(false, index); + } + + public bool CreateRXPDO(UInt16 index) + { + return CreatePDO(true, index); + } + + public ODentry Getobject(UInt16 no) + { + + if(no>=0x002 && no<=0x007) + { + return dummy_ods[no]; + } + + if (ods.ContainsKey(no)) + { + return ods[no]; + } + + return null; + + } + + + public ODentry Getobject(string uniqueID) + { + foreach(KeyValuePair e in ods) + { + if (e.Value.uniqueID == uniqueID) + return e.Value; + + if(e.Value.subobjects!=null && e.Value.subobjects.Count>0) + { + foreach(KeyValuePair sube in e.Value.subobjects) + { + if (sube.Value.uniqueID == uniqueID) + return sube.Value; + } + + } + + + } + + return null; + } + + public int GetNoEnabledObjects(bool includesub=false) + { + int enabledcount = 0; + foreach (ODentry od in ods.Values) + { + if (od.prop.CO_disabled == false) + { + enabledcount++; + + if(includesub) + { + foreach(ODentry sub in od.subobjects.Values) + { + if (od.prop.CO_disabled == false) + { + enabledcount++; + } + } + + } + } + } + + return enabledcount; + + } + + + + } + + public class ParameterException : Exception + { + public ParameterException(String message) + : base(message) + { + + } + } + + + + } From 22cb6a508a51185e090aa34b6fb9b95ee91dcae7 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 09:36:51 +0200 Subject: [PATCH 028/226] - corrected quick range check for RXPDO and TXPDO, corrected typo (1600 => 0x1600) --- libEDSsharp/PDOHelper.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index ea993ba7..f775f79d 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -407,8 +407,8 @@ public void buildmappingsfromlists() /// public void addPDOslot(UInt16 configindex) { - //quick range check, it must be a config index for an RXPDO or a TXPDO - if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=1600) && (configindex<0x1800))) + //quick range check, it must be a config index for an RXPDO or a TXPDO. True if not in range 0x1400...0x15FF OR 0x1800...0x19FF + if ((configindex < 0x1400) || (configindex >= 0x1a00) || ((configindex >= 0x1600) && (configindex < 0x1800))) return; foreach(PDOSlot slot in pdoslots) From 19c1ba53a48b3adc9163acdd0e3899cee40cef47 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 09:51:30 +0200 Subject: [PATCH 029/226] - corrected typo - fix annoying exemption in DeviceODView --- EDSEditorGUI/DeviceInfoView.Designer.cs | 170 ++++++++++++------------ EDSEditorGUI/DeviceInfoView.cs | 28 ++-- EDSEditorGUI/DeviceODView.cs | 1 + 3 files changed, 100 insertions(+), 99 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.Designer.cs b/EDSEditorGUI/DeviceInfoView.Designer.cs index a01cf2df..fd64dba6 100644 --- a/EDSEditorGUI/DeviceInfoView.Designer.cs +++ b/EDSEditorGUI/DeviceInfoView.Designer.cs @@ -70,14 +70,14 @@ private void InitializeComponent() this.label26 = new System.Windows.Forms.Label(); this.groupBox1 = new System.Windows.Forms.GroupBox(); this.checkBox_baud_auto = new System.Windows.Forms.CheckBox(); - this.heckBox_baud_125 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_125 = new System.Windows.Forms.CheckBox(); this.checkBox_baud_10 = new System.Windows.Forms.CheckBox(); - this.heckBox_baud_20 = new System.Windows.Forms.CheckBox(); - this.heckBox_baud_50 = new System.Windows.Forms.CheckBox(); - this.heckBox_baud_250 = new System.Windows.Forms.CheckBox(); - this.heckBox_baud_1000 = new System.Windows.Forms.CheckBox(); - this.heckBox_baud_500 = new System.Windows.Forms.CheckBox(); - this.heckBox_baud_800 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_20 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_50 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_250 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_1000 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_500 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_800 = new System.Windows.Forms.CheckBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); this.textBox_granularity = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); @@ -494,14 +494,14 @@ private void InitializeComponent() // groupBox1 // this.groupBox1.Controls.Add(this.checkBox_baud_auto); - this.groupBox1.Controls.Add(this.heckBox_baud_125); + this.groupBox1.Controls.Add(this.checkBox_baud_125); this.groupBox1.Controls.Add(this.checkBox_baud_10); - this.groupBox1.Controls.Add(this.heckBox_baud_20); - this.groupBox1.Controls.Add(this.heckBox_baud_50); - this.groupBox1.Controls.Add(this.heckBox_baud_250); - this.groupBox1.Controls.Add(this.heckBox_baud_1000); - this.groupBox1.Controls.Add(this.heckBox_baud_500); - this.groupBox1.Controls.Add(this.heckBox_baud_800); + this.groupBox1.Controls.Add(this.checkBox_baud_20); + this.groupBox1.Controls.Add(this.checkBox_baud_50); + this.groupBox1.Controls.Add(this.checkBox_baud_250); + this.groupBox1.Controls.Add(this.checkBox_baud_1000); + this.groupBox1.Controls.Add(this.checkBox_baud_500); + this.groupBox1.Controls.Add(this.checkBox_baud_800); this.groupBox1.Location = new System.Drawing.Point(395, 14); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(120, 192); @@ -521,13 +521,13 @@ private void InitializeComponent() // // heckBox_baud_125 // - this.heckBox_baud_125.AutoSize = true; - this.heckBox_baud_125.Location = new System.Drawing.Point(10, 72); - this.heckBox_baud_125.Name = "heckBox_baud_125"; - this.heckBox_baud_125.Size = new System.Drawing.Size(70, 17); - this.heckBox_baud_125.TabIndex = 3; - this.heckBox_baud_125.Text = "125 kbps"; - this.heckBox_baud_125.UseVisualStyleBackColor = true; + this.checkBox_baud_125.AutoSize = true; + this.checkBox_baud_125.Location = new System.Drawing.Point(10, 72); + this.checkBox_baud_125.Name = "checkBox_baud_125"; + this.checkBox_baud_125.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_125.TabIndex = 3; + this.checkBox_baud_125.Text = "125 kbps"; + this.checkBox_baud_125.UseVisualStyleBackColor = true; // // checkBox_baud_10 // @@ -541,63 +541,63 @@ private void InitializeComponent() // // heckBox_baud_20 // - this.heckBox_baud_20.AutoSize = true; - this.heckBox_baud_20.Location = new System.Drawing.Point(10, 37); - this.heckBox_baud_20.Name = "heckBox_baud_20"; - this.heckBox_baud_20.Size = new System.Drawing.Size(64, 17); - this.heckBox_baud_20.TabIndex = 1; - this.heckBox_baud_20.Text = "20 kbps"; - this.heckBox_baud_20.UseVisualStyleBackColor = true; - // - // heckBox_baud_50 - // - this.heckBox_baud_50.AutoSize = true; - this.heckBox_baud_50.Location = new System.Drawing.Point(10, 54); - this.heckBox_baud_50.Name = "heckBox_baud_50"; - this.heckBox_baud_50.Size = new System.Drawing.Size(64, 17); - this.heckBox_baud_50.TabIndex = 2; - this.heckBox_baud_50.Text = "50 kbps"; - this.heckBox_baud_50.UseVisualStyleBackColor = true; - // - // heckBox_baud_250 - // - this.heckBox_baud_250.AutoSize = true; - this.heckBox_baud_250.Location = new System.Drawing.Point(10, 90); - this.heckBox_baud_250.Name = "heckBox_baud_250"; - this.heckBox_baud_250.Size = new System.Drawing.Size(70, 17); - this.heckBox_baud_250.TabIndex = 4; - this.heckBox_baud_250.Text = "250 kbps"; - this.heckBox_baud_250.UseVisualStyleBackColor = true; - // - // heckBox_baud_1000 - // - this.heckBox_baud_1000.AutoSize = true; - this.heckBox_baud_1000.Location = new System.Drawing.Point(10, 145); - this.heckBox_baud_1000.Name = "heckBox_baud_1000"; - this.heckBox_baud_1000.Size = new System.Drawing.Size(76, 17); - this.heckBox_baud_1000.TabIndex = 7; - this.heckBox_baud_1000.Text = "1000 kbps"; - this.heckBox_baud_1000.UseVisualStyleBackColor = true; - // - // heckBox_baud_500 - // - this.heckBox_baud_500.AutoSize = true; - this.heckBox_baud_500.Location = new System.Drawing.Point(10, 109); - this.heckBox_baud_500.Name = "heckBox_baud_500"; - this.heckBox_baud_500.Size = new System.Drawing.Size(70, 17); - this.heckBox_baud_500.TabIndex = 5; - this.heckBox_baud_500.Text = "500 kbps"; - this.heckBox_baud_500.UseVisualStyleBackColor = true; - // - // heckBox_baud_800 - // - this.heckBox_baud_800.AutoSize = true; - this.heckBox_baud_800.Location = new System.Drawing.Point(10, 127); - this.heckBox_baud_800.Name = "heckBox_baud_800"; - this.heckBox_baud_800.Size = new System.Drawing.Size(70, 17); - this.heckBox_baud_800.TabIndex = 6; - this.heckBox_baud_800.Text = "800 kbps"; - this.heckBox_baud_800.UseVisualStyleBackColor = true; + this.checkBox_baud_20.AutoSize = true; + this.checkBox_baud_20.Location = new System.Drawing.Point(10, 37); + this.checkBox_baud_20.Name = "checkBox_baud_20"; + this.checkBox_baud_20.Size = new System.Drawing.Size(64, 17); + this.checkBox_baud_20.TabIndex = 1; + this.checkBox_baud_20.Text = "20 kbps"; + this.checkBox_baud_20.UseVisualStyleBackColor = true; + // + // checkBox_baud_50 + // + this.checkBox_baud_50.AutoSize = true; + this.checkBox_baud_50.Location = new System.Drawing.Point(10, 54); + this.checkBox_baud_50.Name = "checkBox_baud_50"; + this.checkBox_baud_50.Size = new System.Drawing.Size(64, 17); + this.checkBox_baud_50.TabIndex = 2; + this.checkBox_baud_50.Text = "50 kbps"; + this.checkBox_baud_50.UseVisualStyleBackColor = true; + // + // checkBox_baud_250 + // + this.checkBox_baud_250.AutoSize = true; + this.checkBox_baud_250.Location = new System.Drawing.Point(10, 90); + this.checkBox_baud_250.Name = "checkBox_baud_250"; + this.checkBox_baud_250.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_250.TabIndex = 4; + this.checkBox_baud_250.Text = "250 kbps"; + this.checkBox_baud_250.UseVisualStyleBackColor = true; + // + // checkBox_baud_1000 + // + this.checkBox_baud_1000.AutoSize = true; + this.checkBox_baud_1000.Location = new System.Drawing.Point(10, 145); + this.checkBox_baud_1000.Name = "checkBox_baud_1000"; + this.checkBox_baud_1000.Size = new System.Drawing.Size(76, 17); + this.checkBox_baud_1000.TabIndex = 7; + this.checkBox_baud_1000.Text = "1000 kbps"; + this.checkBox_baud_1000.UseVisualStyleBackColor = true; + // + // checkBox_baud_500 + // + this.checkBox_baud_500.AutoSize = true; + this.checkBox_baud_500.Location = new System.Drawing.Point(10, 109); + this.checkBox_baud_500.Name = "checkBox_baud_500"; + this.checkBox_baud_500.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_500.TabIndex = 5; + this.checkBox_baud_500.Text = "500 kbps"; + this.checkBox_baud_500.UseVisualStyleBackColor = true; + // + // checkBox_baud_800 + // + this.checkBox_baud_800.AutoSize = true; + this.checkBox_baud_800.Location = new System.Drawing.Point(10, 127); + this.checkBox_baud_800.Name = "checkBox_baud_800"; + this.checkBox_baud_800.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_800.TabIndex = 6; + this.checkBox_baud_800.Text = "800 kbps"; + this.checkBox_baud_800.UseVisualStyleBackColor = true; // // groupBox2 // @@ -872,14 +872,14 @@ private void InitializeComponent() private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.CheckBox checkBox_lss; private System.Windows.Forms.GroupBox groupBox1; - private System.Windows.Forms.CheckBox heckBox_baud_125; + private System.Windows.Forms.CheckBox checkBox_baud_125; private System.Windows.Forms.CheckBox checkBox_baud_10; - private System.Windows.Forms.CheckBox heckBox_baud_20; - private System.Windows.Forms.CheckBox heckBox_baud_50; - private System.Windows.Forms.CheckBox heckBox_baud_250; - private System.Windows.Forms.CheckBox heckBox_baud_1000; - private System.Windows.Forms.CheckBox heckBox_baud_500; - private System.Windows.Forms.CheckBox heckBox_baud_800; + private System.Windows.Forms.CheckBox checkBox_baud_20; + private System.Windows.Forms.CheckBox checkBox_baud_50; + private System.Windows.Forms.CheckBox checkBox_baud_250; + private System.Windows.Forms.CheckBox checkBox_baud_1000; + private System.Windows.Forms.CheckBox checkBox_baud_500; + private System.Windows.Forms.CheckBox checkBox_baud_800; private System.Windows.Forms.TextBox textBox_projectFileName; private System.Windows.Forms.TextBox textBox_deviceedsname; private System.Windows.Forms.TextBox textBox_canopennodeFileName; diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 448c33a6..4a9c30ad 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -51,13 +51,13 @@ public void populatedeviceinfo() textBox_modifiedby.Text = eds.fi.ModifiedBy; checkBox_baud_10.Checked = eds.di.BaudRate_10; - heckBox_baud_20.Checked = eds.di.BaudRate_20; - heckBox_baud_50.Checked = eds.di.BaudRate_50; - heckBox_baud_125.Checked = eds.di.BaudRate_125; - heckBox_baud_250.Checked = eds.di.BaudRate_250; - heckBox_baud_500.Checked = eds.di.BaudRate_500; - heckBox_baud_800.Checked = eds.di.BaudRate_800; - heckBox_baud_1000.Checked = eds.di.BaudRate_1000; + checkBox_baud_20.Checked = eds.di.BaudRate_20; + checkBox_baud_50.Checked = eds.di.BaudRate_50; + checkBox_baud_125.Checked = eds.di.BaudRate_125; + checkBox_baud_250.Checked = eds.di.BaudRate_250; + checkBox_baud_500.Checked = eds.di.BaudRate_500; + checkBox_baud_800.Checked = eds.di.BaudRate_800; + checkBox_baud_1000.Checked = eds.di.BaudRate_1000; checkBox_baud_auto.Checked = eds.di.BaudRate_auto; textBox_granularity.Text = eds.di.Granularity.ToString(); @@ -111,13 +111,13 @@ private void button_update_devfile_info_Click(object sender, EventArgs e) eds.fi.ModifiedBy = textBox_modifiedby.Text; eds.di.BaudRate_10 = checkBox_baud_10.Checked; - eds.di.BaudRate_20 = heckBox_baud_20.Checked; - eds.di.BaudRate_50 = heckBox_baud_50.Checked; - eds.di.BaudRate_125 = heckBox_baud_125.Checked; - eds.di.BaudRate_250 = heckBox_baud_250.Checked; - eds.di.BaudRate_500 = heckBox_baud_500.Checked; - eds.di.BaudRate_800 = heckBox_baud_800.Checked; - eds.di.BaudRate_1000 = heckBox_baud_1000.Checked; + eds.di.BaudRate_20 = checkBox_baud_20.Checked; + eds.di.BaudRate_50 = checkBox_baud_50.Checked; + eds.di.BaudRate_125 = checkBox_baud_125.Checked; + eds.di.BaudRate_250 = checkBox_baud_250.Checked; + eds.di.BaudRate_500 = checkBox_baud_500.Checked; + eds.di.BaudRate_800 = checkBox_baud_800.Checked; + eds.di.BaudRate_1000 = checkBox_baud_1000.Checked; eds.di.BaudRate_auto = checkBox_baud_auto.Checked; eds.di.Granularity = Convert.ToByte(textBox_granularity.Text); diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index 3970c1a4..9e1a0a58 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -460,6 +460,7 @@ private void Button_saveChanges_Click(object sender, EventArgs e) // CO_accessSRDO try { + if(comboBox_accessSRDO.SelectedItem != null) od.prop.CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), comboBox_accessSRDO.SelectedItem.ToString()); } catch (Exception) From 48514531f83847606986d6e2acfb59f51b821651 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 13:46:32 +0200 Subject: [PATCH 030/226] - Bugfix for TXPDO and RXPDO mapping view. Dragging and dropping PDOs as well as deleting and adding new PDOs should work now. --- EDSEditorGUI/DevicePDOView2.cs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 5dc88cfe..3b4188be 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -171,7 +171,7 @@ SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P , out int foundrow,out if (P.Y > y && P.Y < y2) { - foundrow = row.Index; + foundrow = row.Index + grid1.VScrollBar.Value; } y = y2; } @@ -185,14 +185,14 @@ SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P , out int foundrow,out if (P.X > x && P.X < x2) { - foundcol = col.Index; + foundcol = col.Index + grid1.HScrollBar.Value; } x = x2; - } - + } + Console.WriteLine(string.Format("Found grid at {0}x{1}", foundcol, foundrow)); - - SourceGrid.Cells.ICellVirtual v = grid1.GetCell(foundrow, foundcol); + + SourceGrid.Cells.ICellVirtual v = grid1.GetCell(foundrow, foundcol); return v; @@ -342,7 +342,11 @@ public void updateslotdisplay() public void UpdatePDOinfo(bool updatechoices=true) { + int savVScrollValue = 0; + if (!updatechoices) + savVScrollValue = grid1.VScrollBar.Value; + updateslotdisplay(); if (eds == null) @@ -481,7 +485,10 @@ public void UpdatePDOinfo(bool updatechoices=true) } row++; - } + } + + if (!updatechoices) + grid1.VScrollBar.Value = savVScrollValue; } private void ComboStandard_Changed(object sender, EventArgs e) From af98cd99c7305a766188f8685a560a5a151ce07d Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 30 Aug 2022 14:00:26 +0200 Subject: [PATCH 031/226] bugfix for exeption when adding new PDO in PDO mapping view --- libEDSsharp/PDOHelper.cs | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index f775f79d..9165d09a 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -420,9 +420,11 @@ public void addPDOslot(UInt16 configindex) bool isTXPDO = configindex >= 0x1800; PDOSlot newslot = new PDOSlot(); - newslot.ConfigurationIndex = configindex; - - newslot.COB = 0x180; //Fixme need a better default??? + newslot.ConfigurationIndex = configindex; + + newslot.COB = 0x180; // Fixme need better defaults??? + newslot.configloc = "RAM"; + newslot.mappingloc = "RAM"; pdoslots.Add(newslot); From adb60e03b855d4dae0023ad688bce5102343897a Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 2 Sep 2022 10:05:05 +0200 Subject: [PATCH 032/226] fix if the subindex is still hex the converter will not know about it so append 0x to keep it correct fix exception if obj is "null" (might occur on click on horizontal scroll bar) OnValueChanged Set LargeChange to a smaller value so that the rows are not skipped correct reg ex pattern to match only octal values (0-7 instead of 0-9) set default for dummy usage to false --- EDSEditorGUI/DevicePDOView2.cs | 5 +++-- libEDSsharp/eds.cs | 14 +++++++------- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index a7e63b0a..58b59a2d 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -38,6 +38,7 @@ public DevicePDOView2() grid1.FixedRows = 2; grid1.SelectionMode = SourceGrid.GridSelectionMode.Row; + grid1.VScrollBar.LargeChange = 5; grid1.Click += Grid1_Click; @@ -126,7 +127,7 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) UInt16 newindex = EDSsharp.ConvertToUInt16(bits[0]); //warning if the subindex is still hex the converter will not know about it //we may need to append 0x to keep it correct - UInt16 newsubindex = EDSsharp.ConvertToUInt16(bits[1]); + UInt16 newsubindex = EDSsharp.ConvertToUInt16("0x" + bits[1]); //bits[2] is the description if we need it @@ -218,7 +219,7 @@ private void Grid1_Click(object sender, EventArgs e) else if (foundrow > 1) //don't select headers or bits { var obj = grid1.Rows[foundrow]; - if (obj.Tag != null) + if (obj!= null && obj.Tag != null) { PDOSlot slot = (PDOSlot)obj.Tag; diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index eb36d18a..19df5bac 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1944,12 +1944,12 @@ public EDSsharp() fi.ModificationDateTime = DateTime.Now; du.Dummy0001 = false; - du.Dummy0002 = true; - du.Dummy0003 = true; - du.Dummy0004 = true; - du.Dummy0005 = true; - du.Dummy0006 = true; - du.Dummy0007 = true; + du.Dummy0002 = false; + du.Dummy0003 = false; + du.Dummy0004 = false; + du.Dummy0005 = false; + du.Dummy0006 = false; + du.Dummy0007 = false; ODentry od = new ODentry(); @@ -2870,7 +2870,7 @@ static public int Getbase(string defaultvalue) nobase = 16; } - pat = @"^0[0-9]+"; + pat = @"^0[0-7]+"; r = new Regex(pat, RegexOptions.IgnoreCase); m = r.Match(defaultvalue); if (m.Success) From 199b3c493b8a4f48ce541763ed14786bbfcdc5bd Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 5 Sep 2022 11:00:48 +0200 Subject: [PATCH 033/226] Enable save button on PDO view only if a slot is selected Fix double extension exporting for CANopenNode (*.h, *.c) Fix for #13 TX PDO Mapping destroys RPDO communication parameter --- EDSEditorGUI/DeviceInfoView.cs | 6 +++--- EDSEditorGUI/DevicePDOView2.cs | 9 +++++---- libEDSsharp/CanOpenNodeExporter.cs | 4 ++-- libEDSsharp/PDOHelper.cs | 16 ++++++++++++++++ 4 files changed, 26 insertions(+), 9 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 4a9c30ad..866f585a 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -124,9 +124,9 @@ private void button_update_devfile_info_Click(object sender, EventArgs e) eds.di.LSS_Supported = checkBox_lss.Checked; eds.di.LSS_Master = checkBox_lssMaster.Checked; - doUpdatePDOs(); - - //These are read only and auto calculated + doUpdatePDOs(); + + //These are read only and auto calculated //textBox_rxpdos.Text = eds.di.NrOfRXPDO.ToString(); //textBox_txpdos.Text = eds.di.NrOfTXPDO.ToString(); diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 58b59a2d..75cabf51 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -67,8 +67,7 @@ public DevicePDOView2() } grid1.Rows[0].Height = 30; - - + contextMenuStrip_removeitem.ItemClicked += ContextMenuStrip_removeitem_ItemClicked; Invalidated += DevicePDOView2_Invalidated; @@ -346,8 +345,10 @@ public void UpdatePDOinfo(bool updatechoices = true) int savVScrollValue = 0; if (!updatechoices) - savVScrollValue = grid1.VScrollBar.Value; - + savVScrollValue = grid1.VScrollBar.Value; + + button_savepdochanges.Enabled = (textBox_slot.Text != ""); + updateslotdisplay(); if (eds == null) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 2cf20c01..36a750fc 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -839,11 +839,11 @@ private void export_c(string filename) file.WriteLine(@"// For CANopenNode V2 users, C macro `CO_VERSION_MAJOR=2` has to be added to project options #ifndef CO_VERSION_MAJOR #include ""CO_driver.h"" - #include """ + filename + @".h"" + #include """ + Path.GetFileNameWithoutExtension(filename) + @".h"" #include ""CO_SDO.h"" #elif CO_VERSION_MAJOR < 4 #include ""301/CO_driver.h"" - #include """ + filename + @".h"" + #include """ + Path.GetFileNameWithoutExtension(filename) + @".h"" #include ""301/CO_SDOserver.h"" #else #error This Object dictionary is not compatible with CANopenNode v4.0 and up! diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index b3c3e9fe..72c38eed 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -84,6 +84,9 @@ public bool invalid public PDOSlot() { + configloc = "PERSIST_COMM"; + mappingloc = "PERSIST_COMM"; + transmissiontype = 254; Mapping = new List(); } @@ -308,6 +311,7 @@ public void buildmappingsfromlists() ODentry sub = new ODentry("max sub-index", (ushort)slot.ConfigurationIndex, 0); sub.defaultvalue = "6"; sub.datatype = DataType.UNSIGNED8; + sub.accesstype = EDSsharp.AccessType.ro; config.addsubobject(0x00,sub); config.accesstype = slot.configAccessType; @@ -318,50 +322,60 @@ public void buildmappingsfromlists() { config.parameter_name = "TPDO communication parameter"; + config.prop.CO_countLabel = "TPDO"; sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = slot.COB.ToHexString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); sub = new ODentry("inhibit time", (ushort)slot.ConfigurationIndex, 3); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.inhibit.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x03, sub); sub = new ODentry("compatibility entry", (ushort)slot.ConfigurationIndex, 4); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = "0"; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x04, sub); sub = new ODentry("event timer", (ushort)slot.ConfigurationIndex, 5); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.eventtimer.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x05, sub); sub = new ODentry("SYNC start value", (ushort)slot.ConfigurationIndex, 6); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.syncstart.ToString(); ; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x06, sub); } else { config.parameter_name = "RPDO communication parameter"; + config.prop.CO_countLabel = "RPDO"; sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = slot.COB.ToHexString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); } @@ -383,6 +397,7 @@ public void buildmappingsfromlists() sub = new ODentry("Number of mapped objects", (ushort)slot.MappingIndex, 0); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.Mapping.Count().ToString(); + sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(0x00, sub); byte mappingcount = 1; @@ -391,6 +406,7 @@ public void buildmappingsfromlists() sub = new ODentry(String.Format("Mapped object {0:x}",mappingcount), (ushort)slot.MappingIndex, mappingcount); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = string.Format("0x{0:x4}{1:x2}{2:x2}", mapslot.Index, mapslot.Subindex, mapslot.Sizeofdatatype()); + sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(mappingcount, sub); mappingcount++; From a6fbf71dec68800161febb3a832fab57ed35ad1e Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 5 Sep 2022 11:02:37 +0200 Subject: [PATCH 034/226] index on bugfix: 199b3c4 Enable save button on PDO view only if a slot is selected From fc382e92e781ae7f8452d6d006cb96ac15e2d0b7 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 6 Sep 2022 09:58:53 +0200 Subject: [PATCH 035/226] save nodeID if present in the OD when creating the PDO list view save description when creating the PDO list view --- libEDSsharp/PDOHelper.cs | 31 +++++++++++++++++++------------ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 72c38eed..246994ed 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -11,8 +11,8 @@ public class PDOSlot { private UInt16 _MappingIndex; - private UInt16 _ConfigurationIndex; - + private UInt16 _ConfigurationIndex; + public bool nodeidpresent; public ushort ConfigurationIndex { get { return _ConfigurationIndex; } @@ -31,7 +31,7 @@ public ushort ConfigurationIndex } else { - throw new ArgumentOutOfRangeException("Configuration Index", "Must be between 0x1400 and 0x17FF"); + throw new ArgumentOutOfRangeException("Configuration Index", "Must be between 0x1400 and 0x17FF "); } @@ -47,6 +47,7 @@ public ushort MappingIndex public EDSsharp.AccessType configAccessType; public string mappingloc; public string configloc; + public uint COB; @@ -71,7 +72,7 @@ public bool invalid if (value == true) COB = COB | 0x80000000; else - COB = COB & 0x0FFFFFFF; + COB = COB & 0xEFFFFFFF; } } @@ -81,14 +82,16 @@ public bool invalid public UInt16 eventtimer; public byte syncstart; public byte transmissiontype; - + public string Description; + public PDOSlot() { configloc = "PERSIST_COMM"; mappingloc = "PERSIST_COMM"; transmissiontype = 254; Mapping = new List(); - } + Description = ""; + } public string getTargetName(ODentry od) { @@ -185,9 +188,7 @@ public void build_PDOlist(UInt16 startcob, List slots) PDOSlot slot = new PDOSlot(); - bool nodeidpresent; - - slot.COB = eds.GetNodeID(od.subobjects[1].defaultvalue, out nodeidpresent); + slot.COB = eds.GetNodeID(od.subobjects[1].defaultvalue, out slot.nodeidpresent); if (od.Containssubindex(2)) slot.transmissiontype = EDSsharp.ConvertToByte(od.Getsubobject(2).defaultvalue); @@ -205,6 +206,7 @@ public void build_PDOlist(UInt16 startcob, List slots) slot.configAccessType = od.accesstype; slot.configloc = od.prop.CO_storageGroup; + slot.Description = od.Description; Console.WriteLine(String.Format("Found PDO Entry {0:x4} {1:x3}", idx, slot.COB)); @@ -316,6 +318,7 @@ public void buildmappingsfromlists() config.accesstype = slot.configAccessType; config.prop.CO_storageGroup = slot.configloc; + config.Description = slot.Description; if (slot.isTXPDO()) @@ -326,7 +329,9 @@ public void buildmappingsfromlists() sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = slot.COB.ToHexString(); + sub.defaultvalue = slot.COB.ToHexString(); + if (slot.nodeidpresent) + sub.defaultvalue += " + $NODEID"; sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -367,8 +372,10 @@ public void buildmappingsfromlists() config.prop.CO_countLabel = "RPDO"; sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); - sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = slot.COB.ToHexString(); + sub.datatype = DataType.UNSIGNED32; + sub.defaultvalue = slot.COB.ToHexString(); + if (slot.nodeidpresent) + sub.defaultvalue += " + $NODEID"; sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); From 26a11e14c58512e9e5f8e2818dfe34900a8a395d Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 6 Sep 2022 14:02:51 +0200 Subject: [PATCH 036/226] correct checking of the accesstype for mapping error (tested with Vector EDScheck) --- libEDSsharp/eds.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 19df5bac..191d9a00 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -2014,7 +2014,7 @@ public List VerifyPDOMapping() } if (missing) mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: missing OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); - else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.t) || (PDO == "TPDO" && accessPDO == AccessPDO.r)) + else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.r) || (PDO == "TPDO" && accessPDO == AccessPDO.t)) mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: not mappable OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); } } From 214615a8a0292fa4ddaca60ee7d478aab995456f Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 9 Sep 2022 12:02:31 +0200 Subject: [PATCH 037/226] fix exception: Add required Sub 1 "Highest sub-index supported", before adding new sub on an empty complex type (ARRAY, RECORD) --- libEDSsharp/eds.cs | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 191d9a00..78e5e113 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1365,10 +1365,23 @@ public ODentry AddSubEntry() if (baseObject.objecttype == ObjectType.VAR) return null; + + ODentry newOd; + + if ((baseObject.Nosubindexes == 0) && ((baseObject.objecttype == ObjectType.ARRAY) || (baseObject.objecttype == ObjectType.REC))) { + baseObject.subobjects.Add(0, new ODentry + { + parent = baseObject, + parameter_name = "Highest sub-index supported", + accesstype = EDSsharp.AccessType.ro, + objecttype = ObjectType.VAR, + datatype = DataType.UNSIGNED8, + defaultvalue = "0x01" + }); + } ODentry lastSubOd = baseObject.subobjects.Values.Last(); ODentry originalOd = null; - ODentry newOd; UInt16 maxSubIndex = 1; UInt16 lastSubIndex = 1; From 65eb20f3c403129708db67ee3146b4cce7060321 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 9 Sep 2022 13:56:37 +0200 Subject: [PATCH 038/226] fix for issue #3 (hopefully) --- EDSEditorGUI/DeviceODView.Designer.cs | 300 +++++++++++++++----------- 1 file changed, 180 insertions(+), 120 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index c9e69923..14bd3856 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -134,6 +134,7 @@ private void InitializeComponent() // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Margin = new System.Windows.Forms.Padding(4); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 @@ -143,8 +144,9 @@ private void InitializeComponent() // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.splitContainer4); - this.splitContainer1.Size = new System.Drawing.Size(1112, 749); - this.splitContainer1.SplitterDistance = 276; + this.splitContainer1.Size = new System.Drawing.Size(1518, 917); + this.splitContainer1.SplitterDistance = 376; + this.splitContainer1.SplitterWidth = 5; this.splitContainer1.TabIndex = 2; this.splitContainer1.TabStop = false; // @@ -153,6 +155,7 @@ private void InitializeComponent() this.splitContainer2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer2.Location = new System.Drawing.Point(0, 0); + this.splitContainer2.Margin = new System.Windows.Forms.Padding(4); this.splitContainer2.Name = "splitContainer2"; this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -163,8 +166,9 @@ private void InitializeComponent() // splitContainer2.Panel2 // this.splitContainer2.Panel2.Controls.Add(this.splitContainer3); - this.splitContainer2.Size = new System.Drawing.Size(276, 749); - this.splitContainer2.SplitterDistance = 248; + this.splitContainer2.Size = new System.Drawing.Size(376, 917); + this.splitContainer2.SplitterDistance = 303; + this.splitContainer2.SplitterWidth = 5; this.splitContainer2.TabIndex = 0; this.splitContainer2.TabStop = false; // @@ -176,11 +180,12 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 2; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(274, 246); + this.tableLayoutPanel1.Size = new System.Drawing.Size(374, 301); this.tableLayoutPanel1.TabIndex = 6; // // listView_communication_objects @@ -191,9 +196,10 @@ private void InitializeComponent() this.listView_communication_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_communication_objects.FullRowSelect = true; this.listView_communication_objects.HideSelection = false; - this.listView_communication_objects.Location = new System.Drawing.Point(3, 23); + this.listView_communication_objects.Location = new System.Drawing.Point(4, 29); + this.listView_communication_objects.Margin = new System.Windows.Forms.Padding(4); this.listView_communication_objects.Name = "listView_communication_objects"; - this.listView_communication_objects.Size = new System.Drawing.Size(268, 220); + this.listView_communication_objects.Size = new System.Drawing.Size(366, 268); this.listView_communication_objects.TabIndex = 0; this.listView_communication_objects.UseCompatibleStateImageBehavior = false; this.listView_communication_objects.View = System.Windows.Forms.View.Details; @@ -213,9 +219,10 @@ private void InitializeComponent() // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(3, 0); + this.label1.Location = new System.Drawing.Point(4, 0); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(176, 13); + this.label1.Size = new System.Drawing.Size(223, 16); this.label1.TabIndex = 3; this.label1.Text = "Communication Specific Parameters"; // @@ -224,6 +231,7 @@ private void InitializeComponent() this.splitContainer3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer3.Location = new System.Drawing.Point(0, 0); + this.splitContainer3.Margin = new System.Windows.Forms.Padding(4); this.splitContainer3.Name = "splitContainer3"; this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -234,8 +242,9 @@ private void InitializeComponent() // splitContainer3.Panel2 // this.splitContainer3.Panel2.Controls.Add(this.tableLayoutPanel3); - this.splitContainer3.Size = new System.Drawing.Size(276, 497); - this.splitContainer3.SplitterDistance = 247; + this.splitContainer3.Size = new System.Drawing.Size(376, 609); + this.splitContainer3.SplitterDistance = 302; + this.splitContainer3.SplitterWidth = 5; this.splitContainer3.TabIndex = 0; this.splitContainer3.TabStop = false; // @@ -247,19 +256,21 @@ private void InitializeComponent() this.tableLayoutPanel2.Controls.Add(this.listView_manufacturer_objects, 0, 1); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(4); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 2; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(274, 245); + this.tableLayoutPanel2.Size = new System.Drawing.Size(374, 300); this.tableLayoutPanel2.TabIndex = 7; // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(3, 0); + this.label2.Location = new System.Drawing.Point(4, 0); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(167, 13); + this.label2.Size = new System.Drawing.Size(208, 16); this.label2.TabIndex = 4; this.label2.Text = "Manufacturer Specific Parameters"; // @@ -271,9 +282,10 @@ private void InitializeComponent() this.listView_manufacturer_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_manufacturer_objects.FullRowSelect = true; this.listView_manufacturer_objects.HideSelection = false; - this.listView_manufacturer_objects.Location = new System.Drawing.Point(3, 23); + this.listView_manufacturer_objects.Location = new System.Drawing.Point(4, 29); + this.listView_manufacturer_objects.Margin = new System.Windows.Forms.Padding(4); this.listView_manufacturer_objects.Name = "listView_manufacturer_objects"; - this.listView_manufacturer_objects.Size = new System.Drawing.Size(268, 219); + this.listView_manufacturer_objects.Size = new System.Drawing.Size(366, 267); this.listView_manufacturer_objects.TabIndex = 0; this.listView_manufacturer_objects.UseCompatibleStateImageBehavior = false; this.listView_manufacturer_objects.View = System.Windows.Forms.View.Details; @@ -298,19 +310,21 @@ private void InitializeComponent() this.tableLayoutPanel3.Controls.Add(this.listView_deviceProfile_objects, 0, 1); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 2; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(274, 244); + this.tableLayoutPanel3.Size = new System.Drawing.Size(374, 300); this.tableLayoutPanel3.TabIndex = 8; // // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(3, 0); + this.label3.Location = new System.Drawing.Point(4, 0); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(170, 13); + this.label3.Size = new System.Drawing.Size(215, 16); this.label3.TabIndex = 5; this.label3.Text = "Device Profile Specific Parameters"; // @@ -322,9 +336,10 @@ private void InitializeComponent() this.listView_deviceProfile_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_deviceProfile_objects.FullRowSelect = true; this.listView_deviceProfile_objects.HideSelection = false; - this.listView_deviceProfile_objects.Location = new System.Drawing.Point(3, 23); + this.listView_deviceProfile_objects.Location = new System.Drawing.Point(4, 29); + this.listView_deviceProfile_objects.Margin = new System.Windows.Forms.Padding(4); this.listView_deviceProfile_objects.Name = "listView_deviceProfile_objects"; - this.listView_deviceProfile_objects.Size = new System.Drawing.Size(268, 218); + this.listView_deviceProfile_objects.Size = new System.Drawing.Size(366, 267); this.listView_deviceProfile_objects.TabIndex = 0; this.listView_deviceProfile_objects.UseCompatibleStateImageBehavior = false; this.listView_deviceProfile_objects.View = System.Windows.Forms.View.Details; @@ -345,6 +360,7 @@ private void InitializeComponent() // this.splitContainer4.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer4.Location = new System.Drawing.Point(0, 0); + this.splitContainer4.Margin = new System.Windows.Forms.Padding(4); this.splitContainer4.Name = "splitContainer4"; this.splitContainer4.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -365,8 +381,9 @@ private void InitializeComponent() this.splitContainer4.Panel2.Controls.Add(this.label6); this.splitContainer4.Panel2.Controls.Add(this.textBox_name); this.splitContainer4.Panel2.Controls.Add(this.textBox_description); - this.splitContainer4.Size = new System.Drawing.Size(832, 749); - this.splitContainer4.SplitterDistance = 227; + this.splitContainer4.Size = new System.Drawing.Size(1137, 917); + this.splitContainer4.SplitterDistance = 277; + this.splitContainer4.SplitterWidth = 5; this.splitContainer4.TabIndex = 28; this.splitContainer4.TabStop = false; // @@ -387,8 +404,9 @@ private void InitializeComponent() this.listView_subObjects.FullRowSelect = true; this.listView_subObjects.HideSelection = false; this.listView_subObjects.Location = new System.Drawing.Point(0, 0); + this.listView_subObjects.Margin = new System.Windows.Forms.Padding(4); this.listView_subObjects.Name = "listView_subObjects"; - this.listView_subObjects.Size = new System.Drawing.Size(829, 224); + this.listView_subObjects.Size = new System.Drawing.Size(1132, 273); this.listView_subObjects.TabIndex = 0; this.listView_subObjects.UseCompatibleStateImageBehavior = false; this.listView_subObjects.View = System.Windows.Forms.View.Details; @@ -437,28 +455,31 @@ private void InitializeComponent() // // textBox_subIndex // - this.textBox_subIndex.Location = new System.Drawing.Point(260, 8); + this.textBox_subIndex.Location = new System.Drawing.Point(347, 10); + this.textBox_subIndex.Margin = new System.Windows.Forms.Padding(4); this.textBox_subIndex.Name = "textBox_subIndex"; this.textBox_subIndex.ReadOnly = true; - this.textBox_subIndex.Size = new System.Drawing.Size(100, 20); + this.textBox_subIndex.Size = new System.Drawing.Size(132, 22); this.textBox_subIndex.TabIndex = 0; this.textBox_subIndex.TabStop = false; // // label23 // this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(199, 11); + this.label23.Location = new System.Drawing.Point(265, 14); + this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(55, 13); + this.label23.Size = new System.Drawing.Size(66, 16); this.label23.TabIndex = 34; this.label23.Text = "Sub Index"; // // textBox_index // - this.textBox_index.Location = new System.Drawing.Point(90, 8); + this.textBox_index.Location = new System.Drawing.Point(120, 10); + this.textBox_index.Margin = new System.Windows.Forms.Padding(4); this.textBox_index.Name = "textBox_index"; this.textBox_index.ReadOnly = true; - this.textBox_index.Size = new System.Drawing.Size(100, 20); + this.textBox_index.Size = new System.Drawing.Size(132, 22); this.textBox_index.TabIndex = 0; this.textBox_index.TabStop = false; // @@ -495,38 +516,41 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.label10); this.groupBox1.Controls.Add(this.label11); this.groupBox1.Controls.Add(this.comboBox_accessPDO); - this.groupBox1.Location = new System.Drawing.Point(11, 326); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2); + this.groupBox1.Location = new System.Drawing.Point(15, 397); + this.groupBox1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2); - this.groupBox1.Size = new System.Drawing.Size(818, 188); + this.groupBox1.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.groupBox1.Size = new System.Drawing.Size(1119, 231); this.groupBox1.TabIndex = 33; this.groupBox1.TabStop = false; this.groupBox1.Text = "Object settings"; // // textBox_stringLengthMin // - this.textBox_stringLengthMin.Location = new System.Drawing.Point(340, 99); + this.textBox_stringLengthMin.Location = new System.Drawing.Point(453, 122); + this.textBox_stringLengthMin.Margin = new System.Windows.Forms.Padding(4); this.textBox_stringLengthMin.Name = "textBox_stringLengthMin"; - this.textBox_stringLengthMin.Size = new System.Drawing.Size(122, 20); + this.textBox_stringLengthMin.Size = new System.Drawing.Size(161, 22); this.textBox_stringLengthMin.TabIndex = 24; this.textBox_stringLengthMin.TextChanged += new System.EventHandler(this.DataDirty); // // label22 // this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(248, 102); + this.label22.Location = new System.Drawing.Point(331, 126); + this.label22.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(75, 13); + this.label22.Size = new System.Drawing.Size(90, 16); this.label22.TabIndex = 39; this.label22.Text = "String Len Min"; // // label20 // this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(482, 21); + this.label20.Location = new System.Drawing.Point(643, 26); + this.label20.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(64, 13); + this.label20.Size = new System.Drawing.Size(78, 16); this.label20.TabIndex = 36; this.label20.Text = "Count Label"; // @@ -534,18 +558,20 @@ private void InitializeComponent() // this.comboBox_countLabel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_countLabel.FormattingEnabled = true; - this.comboBox_countLabel.Location = new System.Drawing.Point(574, 18); + this.comboBox_countLabel.Location = new System.Drawing.Point(765, 22); + this.comboBox_countLabel.Margin = new System.Windows.Forms.Padding(4); this.comboBox_countLabel.Name = "comboBox_countLabel"; - this.comboBox_countLabel.Size = new System.Drawing.Size(122, 21); + this.comboBox_countLabel.Size = new System.Drawing.Size(161, 24); this.comboBox_countLabel.TabIndex = 30; this.comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label19 // this.label19.AutoSize = true; - this.label19.Location = new System.Drawing.Point(13, 129); + this.label19.Location = new System.Drawing.Point(17, 159); + this.label19.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label19.Name = "label19"; - this.label19.Size = new System.Drawing.Size(76, 13); + this.label19.Size = new System.Drawing.Size(94, 16); this.label19.TabIndex = 34; this.label19.Text = "Access SRDO"; // @@ -553,61 +579,68 @@ private void InitializeComponent() // this.comboBox_accessSRDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSRDO.FormattingEnabled = true; - this.comboBox_accessSRDO.Location = new System.Drawing.Point(108, 126); + this.comboBox_accessSRDO.Location = new System.Drawing.Point(144, 155); + this.comboBox_accessSRDO.Margin = new System.Windows.Forms.Padding(4); this.comboBox_accessSRDO.Name = "comboBox_accessSRDO"; - this.comboBox_accessSRDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessSRDO.Size = new System.Drawing.Size(161, 24); this.comboBox_accessSRDO.TabIndex = 14; this.comboBox_accessSRDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_actualValue // this.textBox_actualValue.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_actualValue.Location = new System.Drawing.Point(340, 72); + this.textBox_actualValue.Location = new System.Drawing.Point(453, 89); + this.textBox_actualValue.Margin = new System.Windows.Forms.Padding(4); this.textBox_actualValue.Name = "textBox_actualValue"; - this.textBox_actualValue.Size = new System.Drawing.Size(122, 20); + this.textBox_actualValue.Size = new System.Drawing.Size(161, 22); this.textBox_actualValue.TabIndex = 23; this.textBox_actualValue.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_lowLimit // - this.textBox_lowLimit.Location = new System.Drawing.Point(340, 45); + this.textBox_lowLimit.Location = new System.Drawing.Point(453, 55); + this.textBox_lowLimit.Margin = new System.Windows.Forms.Padding(4); this.textBox_lowLimit.Name = "textBox_lowLimit"; - this.textBox_lowLimit.Size = new System.Drawing.Size(122, 20); + this.textBox_lowLimit.Size = new System.Drawing.Size(161, 22); this.textBox_lowLimit.TabIndex = 22; this.textBox_lowLimit.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_highLimit // - this.textBox_highLimit.Location = new System.Drawing.Point(340, 18); + this.textBox_highLimit.Location = new System.Drawing.Point(453, 22); + this.textBox_highLimit.Margin = new System.Windows.Forms.Padding(4); this.textBox_highLimit.Name = "textBox_highLimit"; - this.textBox_highLimit.Size = new System.Drawing.Size(122, 20); + this.textBox_highLimit.Size = new System.Drawing.Size(161, 22); this.textBox_highLimit.TabIndex = 21; this.textBox_highLimit.TextChanged += new System.EventHandler(this.DataDirty); // // label18 // this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(248, 75); + this.label18.Location = new System.Drawing.Point(331, 92); + this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(67, 13); + this.label18.Size = new System.Drawing.Size(82, 16); this.label18.TabIndex = 32; this.label18.Text = "Actual Value"; // // label17 // this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(248, 48); + this.label17.Location = new System.Drawing.Point(331, 59); + this.label17.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(48, 13); + this.label17.Size = new System.Drawing.Size(58, 16); this.label17.TabIndex = 31; this.label17.Text = "LowLimit"; // // label14 // this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(248, 21); + this.label14.Location = new System.Drawing.Point(331, 26); + this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(50, 13); + this.label14.Size = new System.Drawing.Size(62, 16); this.label14.TabIndex = 30; this.label14.Text = "HighLimit"; // @@ -615,9 +648,10 @@ private void InitializeComponent() // this.button_saveChanges.Image = global::ODEditor.Properties.Resources.Save_6530; this.button_saveChanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_saveChanges.Location = new System.Drawing.Point(485, 138); + this.button_saveChanges.Location = new System.Drawing.Point(647, 170); + this.button_saveChanges.Margin = new System.Windows.Forms.Padding(4); this.button_saveChanges.Name = "button_saveChanges"; - this.button_saveChanges.Size = new System.Drawing.Size(211, 35); + this.button_saveChanges.Size = new System.Drawing.Size(281, 43); this.button_saveChanges.TabIndex = 50; this.button_saveChanges.Text = "Save Changes"; this.button_saveChanges.UseVisualStyleBackColor = true; @@ -626,9 +660,10 @@ private void InitializeComponent() // label16 // this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(482, 48); + this.label16.Location = new System.Drawing.Point(643, 59); + this.label16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(76, 13); + this.label16.Size = new System.Drawing.Size(95, 16); this.label16.TabIndex = 26; this.label16.Text = "Storage Group"; // @@ -636,27 +671,30 @@ private void InitializeComponent() // this.comboBox_storageGroup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_storageGroup.FormattingEnabled = true; - this.comboBox_storageGroup.Location = new System.Drawing.Point(574, 45); + this.comboBox_storageGroup.Location = new System.Drawing.Point(765, 55); + this.comboBox_storageGroup.Margin = new System.Windows.Forms.Padding(4); this.comboBox_storageGroup.Name = "comboBox_storageGroup"; - this.comboBox_storageGroup.Size = new System.Drawing.Size(122, 21); + this.comboBox_storageGroup.Size = new System.Drawing.Size(161, 24); this.comboBox_storageGroup.TabIndex = 31; this.comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label15 // this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(482, 72); + this.label15.Location = new System.Drawing.Point(643, 89); + this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(46, 13); + this.label15.Size = new System.Drawing.Size(58, 16); this.label15.TabIndex = 24; this.label15.Text = "Enabled"; // // checkBox_enabled // this.checkBox_enabled.AutoSize = true; - this.checkBox_enabled.Location = new System.Drawing.Point(574, 72); + this.checkBox_enabled.Location = new System.Drawing.Point(765, 89); + this.checkBox_enabled.Margin = new System.Windows.Forms.Padding(4); this.checkBox_enabled.Name = "checkBox_enabled"; - this.checkBox_enabled.Size = new System.Drawing.Size(15, 14); + this.checkBox_enabled.Size = new System.Drawing.Size(18, 17); this.checkBox_enabled.TabIndex = 32; this.checkBox_enabled.UseVisualStyleBackColor = true; this.checkBox_enabled.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -664,9 +702,10 @@ private void InitializeComponent() // label7 // this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(13, 21); + this.label7.Location = new System.Drawing.Point(17, 26); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(65, 13); + this.label7.Size = new System.Drawing.Size(81, 16); this.label7.TabIndex = 7; this.label7.Text = "Object Type"; // @@ -674,18 +713,20 @@ private void InitializeComponent() // this.comboBox_objectType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_objectType.FormattingEnabled = true; - this.comboBox_objectType.Location = new System.Drawing.Point(108, 18); + this.comboBox_objectType.Location = new System.Drawing.Point(144, 22); + this.comboBox_objectType.Margin = new System.Windows.Forms.Padding(4); this.comboBox_objectType.Name = "comboBox_objectType"; - this.comboBox_objectType.Size = new System.Drawing.Size(122, 21); + this.comboBox_objectType.Size = new System.Drawing.Size(161, 24); this.comboBox_objectType.TabIndex = 10; this.comboBox_objectType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label8 // this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(13, 48); + this.label8.Location = new System.Drawing.Point(17, 59); + this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(57, 13); + this.label8.Size = new System.Drawing.Size(71, 16); this.label8.TabIndex = 9; this.label8.Text = "Data Type"; // @@ -693,36 +734,40 @@ private void InitializeComponent() // this.comboBox_dataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_dataType.FormattingEnabled = true; - this.comboBox_dataType.Location = new System.Drawing.Point(108, 45); + this.comboBox_dataType.Location = new System.Drawing.Point(144, 55); + this.comboBox_dataType.Margin = new System.Windows.Forms.Padding(4); this.comboBox_dataType.Name = "comboBox_dataType"; - this.comboBox_dataType.Size = new System.Drawing.Size(122, 21); + this.comboBox_dataType.Size = new System.Drawing.Size(161, 24); this.comboBox_dataType.TabIndex = 11; this.comboBox_dataType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label_pdoFlags // this.label_pdoFlags.AutoSize = true; - this.label_pdoFlags.Location = new System.Drawing.Point(482, 92); + this.label_pdoFlags.Location = new System.Drawing.Point(643, 113); + this.label_pdoFlags.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label_pdoFlags.Name = "label_pdoFlags"; - this.label_pdoFlags.Size = new System.Drawing.Size(62, 13); + this.label_pdoFlags.Size = new System.Drawing.Size(76, 16); this.label_pdoFlags.TabIndex = 18; this.label_pdoFlags.Text = "TPDO COS"; // // label9 // this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(13, 75); + this.label9.Location = new System.Drawing.Point(17, 92); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(68, 13); + this.label9.Size = new System.Drawing.Size(84, 16); this.label9.TabIndex = 11; this.label9.Text = "Access SDO"; // // checkBox_pdoFlags // this.checkBox_pdoFlags.AutoSize = true; - this.checkBox_pdoFlags.Location = new System.Drawing.Point(574, 92); + this.checkBox_pdoFlags.Location = new System.Drawing.Point(765, 113); + this.checkBox_pdoFlags.Margin = new System.Windows.Forms.Padding(4); this.checkBox_pdoFlags.Name = "checkBox_pdoFlags"; - this.checkBox_pdoFlags.Size = new System.Drawing.Size(15, 14); + this.checkBox_pdoFlags.Size = new System.Drawing.Size(18, 17); this.checkBox_pdoFlags.TabIndex = 34; this.checkBox_pdoFlags.UseVisualStyleBackColor = true; this.checkBox_pdoFlags.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -731,35 +776,39 @@ private void InitializeComponent() // this.comboBox_accessSDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSDO.FormattingEnabled = true; - this.comboBox_accessSDO.Location = new System.Drawing.Point(108, 72); + this.comboBox_accessSDO.Location = new System.Drawing.Point(144, 89); + this.comboBox_accessSDO.Margin = new System.Windows.Forms.Padding(4); this.comboBox_accessSDO.Name = "comboBox_accessSDO"; - this.comboBox_accessSDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessSDO.Size = new System.Drawing.Size(161, 24); this.comboBox_accessSDO.TabIndex = 12; this.comboBox_accessSDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_defaultValue // - this.textBox_defaultValue.Location = new System.Drawing.Point(108, 153); + this.textBox_defaultValue.Location = new System.Drawing.Point(144, 188); + this.textBox_defaultValue.Margin = new System.Windows.Forms.Padding(4); this.textBox_defaultValue.Name = "textBox_defaultValue"; - this.textBox_defaultValue.Size = new System.Drawing.Size(354, 20); + this.textBox_defaultValue.Size = new System.Drawing.Size(471, 22); this.textBox_defaultValue.TabIndex = 20; this.textBox_defaultValue.TextChanged += new System.EventHandler(this.DataDirty); // // label10 // this.label10.AutoSize = true; - this.label10.Location = new System.Drawing.Point(13, 102); + this.label10.Location = new System.Drawing.Point(17, 126); + this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(68, 13); + this.label10.Size = new System.Drawing.Size(84, 16); this.label10.TabIndex = 13; this.label10.Text = "Access PDO"; // // label11 // this.label11.AutoSize = true; - this.label11.Location = new System.Drawing.Point(13, 156); + this.label11.Location = new System.Drawing.Point(17, 192); + this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(70, 13); + this.label11.Size = new System.Drawing.Size(85, 16); this.label11.TabIndex = 15; this.label11.Text = "Default value"; // @@ -767,9 +816,10 @@ private void InitializeComponent() // this.comboBox_accessPDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessPDO.FormattingEnabled = true; - this.comboBox_accessPDO.Location = new System.Drawing.Point(108, 99); + this.comboBox_accessPDO.Location = new System.Drawing.Point(144, 122); + this.comboBox_accessPDO.Margin = new System.Windows.Forms.Padding(4); this.comboBox_accessPDO.Name = "comboBox_accessPDO"; - this.comboBox_accessPDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessPDO.Size = new System.Drawing.Size(161, 24); this.comboBox_accessPDO.TabIndex = 13; this.comboBox_accessPDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // @@ -778,45 +828,50 @@ private void InitializeComponent() this.textBox_denotation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_denotation.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_denotation.Location = new System.Drawing.Point(90, 60); + this.textBox_denotation.Location = new System.Drawing.Point(120, 74); + this.textBox_denotation.Margin = new System.Windows.Forms.Padding(4); this.textBox_denotation.Name = "textBox_denotation"; - this.textBox_denotation.Size = new System.Drawing.Size(739, 20); + this.textBox_denotation.Size = new System.Drawing.Size(1012, 22); this.textBox_denotation.TabIndex = 3; this.textBox_denotation.TextChanged += new System.EventHandler(this.DataDirty); // // label13 // this.label13.AutoSize = true; - this.label13.Location = new System.Drawing.Point(13, 63); + this.label13.Location = new System.Drawing.Point(17, 78); + this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(59, 13); + this.label13.Size = new System.Drawing.Size(72, 16); this.label13.TabIndex = 28; this.label13.Text = "Denotation"; // // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(13, 11); + this.label4.Location = new System.Drawing.Point(17, 14); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(33, 13); + this.label4.Size = new System.Drawing.Size(39, 16); this.label4.TabIndex = 1; this.label4.Text = "Index"; // // label5 // this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(13, 37); + this.label5.Location = new System.Drawing.Point(17, 46); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(35, 13); + this.label5.Size = new System.Drawing.Size(44, 16); this.label5.TabIndex = 2; this.label5.Text = "Name"; // // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(13, 89); + this.label6.Location = new System.Drawing.Point(17, 110); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(60, 13); + this.label6.Size = new System.Drawing.Size(75, 16); this.label6.TabIndex = 3; this.label6.Text = "Description"; // @@ -824,23 +879,27 @@ private void InitializeComponent() // this.textBox_name.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_name.Location = new System.Drawing.Point(90, 34); + this.textBox_name.Location = new System.Drawing.Point(120, 42); + this.textBox_name.Margin = new System.Windows.Forms.Padding(4); this.textBox_name.Name = "textBox_name"; - this.textBox_name.Size = new System.Drawing.Size(739, 20); + this.textBox_name.Size = new System.Drawing.Size(1012, 22); this.textBox_name.TabIndex = 2; this.textBox_name.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_description // + this.textBox_description.AcceptsReturn = true; + this.textBox_description.AcceptsTab = true; this.textBox_description.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_description.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBox_description.Location = new System.Drawing.Point(90, 86); + this.textBox_description.Location = new System.Drawing.Point(120, 106); + this.textBox_description.Margin = new System.Windows.Forms.Padding(4); this.textBox_description.Multiline = true; this.textBox_description.Name = "textBox_description"; this.textBox_description.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBox_description.Size = new System.Drawing.Size(739, 231); + this.textBox_description.Size = new System.Drawing.Size(1012, 279); this.textBox_description.TabIndex = 4; this.textBox_description.TextChanged += new System.EventHandler(this.DataDirty); // @@ -853,12 +912,12 @@ private void InitializeComponent() this.contextMenu_object_deleteObjectToolStripMenuItem, this.contextMenu_object_toggleObjectToolStripMenuItem}); this.contextMenu_object.Name = "contextMenuStrip1"; - this.contextMenu_object.Size = new System.Drawing.Size(121, 108); + this.contextMenu_object.Size = new System.Drawing.Size(136, 108); // // contextMenu_object_addNewObjectToolStripMenuItem // this.contextMenu_object_addNewObjectToolStripMenuItem.Name = "contextMenu_object_addNewObjectToolStripMenuItem"; - this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.contextMenu_object_addNewObjectToolStripMenuItem.Text = "&Clone..."; this.contextMenu_object_addNewObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_clone_ToolStripMenuItem_Click); // @@ -866,7 +925,7 @@ private void InitializeComponent() // this.addToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.addToolStripMenuItem.Name = "addToolStripMenuItem"; - this.addToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.addToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.addToolStripMenuItem.Text = "Add..."; this.addToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_add_ToolStripMenuItem_Click); // @@ -874,14 +933,14 @@ private void InitializeComponent() // this.contextMenu_object_deleteObjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_object_deleteObjectToolStripMenuItem.Name = "contextMenu_object_deleteObjectToolStripMenuItem"; - this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.contextMenu_object_deleteObjectToolStripMenuItem.Text = "&Delete..."; this.contextMenu_object_deleteObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_delete_ToolStripMenuItem_Click); // // contextMenu_object_toggleObjectToolStripMenuItem // this.contextMenu_object_toggleObjectToolStripMenuItem.Name = "contextMenu_object_toggleObjectToolStripMenuItem"; - this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.contextMenu_object_toggleObjectToolStripMenuItem.Text = "&Toggle"; this.contextMenu_object_toggleObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_toggle_ToolStripMenuItem_Click); // @@ -893,13 +952,13 @@ private void InitializeComponent() this.contextMenu_subObject_removeSubItemToolStripMenuItem, this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem}); this.contextMenu_subObject.Name = "contextMenu_array"; - this.contextMenu_subObject.Size = new System.Drawing.Size(183, 82); + this.contextMenu_subObject.Size = new System.Drawing.Size(216, 82); // // contextMenu_subObject_addSubItemToolStripMenuItem // this.contextMenu_subObject_addSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.contextMenu_subObject_addSubItemToolStripMenuItem.Name = "contextMenu_subObject_addSubItemToolStripMenuItem"; - this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); this.contextMenu_subObject_addSubItemToolStripMenuItem.Text = "Add"; this.contextMenu_subObject_addSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_add_ToolStripMenuItem_Click); // @@ -907,7 +966,7 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); this.contextMenu_subObject_removeSubItemToolStripMenuItem.Text = "Remove (shift up)"; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // @@ -915,17 +974,18 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(215, 26); this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Text = "Remove (leave gap)"; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // // DeviceODView // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.splitContainer1); + this.Margin = new System.Windows.Forms.Padding(4); this.Name = "DeviceODView"; - this.Size = new System.Drawing.Size(1112, 749); + this.Size = new System.Drawing.Size(1518, 917); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); From d834fa412cab9aa895c25e3fe0e591771690e248 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 15 Sep 2022 10:24:56 +0200 Subject: [PATCH 039/226] fix for issue #11 --- EDSEditorGUI/Form1.cs | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index aaf75f57..87aeb82c 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -544,11 +544,19 @@ private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) sfd.Filter = "CANopen XDD v1.1 (*.xdd)|*.xdd|" + "CANopen XDC v1.1 (*.xdc)|*.xdc|" - + "CANopen XPD v1.1 (*.xpd)|*.xpd"; + + "CANopen XPD v1.1 (*.xpd)|*.xpd"; + + if (dv.eds.projectFilename == "") + { + sfd.FileName = Path.GetFileNameWithoutExtension(networkfilename); + } + else + { + sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); + sfd.RestoreDirectory = true; + sfd.FileName = Path.GetFileNameWithoutExtension(dv.eds.projectFilename); + } - sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); - sfd.RestoreDirectory = true; - sfd.FileName = Path.GetFileNameWithoutExtension(dv.eds.projectFilename); if (sfd.ShowDialog() == DialogResult.OK) { @@ -898,7 +906,7 @@ private void openNetworkfile(string file) Bridge b = new Bridge(); EDSsharp eds = b.convert(d); - //eds.filename = path; //fixme + //eds.filename = path; //fixme: We need to save the projectfilename or SaveAs will throw an exception tabControl1.TabPages.Add(eds.di.ProductName); From c8eb3f16d0643b2d866cebde7f37f75f7e7cc6ef Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 15 Sep 2022 11:00:56 +0200 Subject: [PATCH 040/226] cherry pick fdb0a09935c881a352cf3fff5f975afb6642275a --- Tests/ExporterTestsV4.cs | 35 ++++ Tests/Tests.csproj | 230 +++++++++++++------------- libEDSsharp/CanOpenNodeExporter_V4.cs | 45 +++-- 3 files changed, 178 insertions(+), 132 deletions(-) create mode 100644 Tests/ExporterTestsV4.cs diff --git a/Tests/ExporterTestsV4.cs b/Tests/ExporterTestsV4.cs new file mode 100644 index 00000000..46cc1cb8 --- /dev/null +++ b/Tests/ExporterTestsV4.cs @@ -0,0 +1,35 @@ +using System; +using Xunit; +using libEDSsharp; + +namespace Tests +{ + public class ExporterTestsV4 : CanOpenNodeExporter_V4 + { + [Fact] + public void Test_Make_cname_conversion() + { + if (Make_cname("axle 0 wheel right controlword") != "axle0WheelRightControlword") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("mapped object 4") != "mappedObject4") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("COB ID used by RPDO") != "COB_IDUsedByRPDO") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("A/D unit offset value (filtered)") != "A_DUnitOffsetValueFiltered") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("80 test string") != "_80TestString") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("Eighty test string") != "eightyTestString") + throw (new Exception("Make_cname Conversion error")); + + if (Make_cname("A") != "a") + throw (new Exception("Make_cname Conversion error")); + + } + } +} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 951c20cd..64cf6f23 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,122 +1,122 @@ - - - - - - - Debug - AnyCPU - {2A479BF3-7628-409B-8A29-9314C308445E} - Library - Properties - Tests - Tests - v4.8 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll - - - ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll - - - ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll - - - ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll - - - - - - - - - - - - - - - - - - - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - - - - - - - - - - - - - False - - - False - - - False - - - False - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - + + + + + + + Debug + AnyCPU + {2A479BF3-7628-409B-8A29-9314C308445E} + Library + Properties + Tests + Tests + v4.5.2 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll + + + ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll + + + ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll + + + ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll + + + + + + + + + + + + + + + + + + + + + {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} + libEDSsharp + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + --> \ No newline at end of file diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 99515750..463ceb52 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License using System.Text; using System.Text.RegularExpressions; using System.IO; +using System.Linq; namespace libEDSsharp { @@ -664,47 +665,57 @@ Object dictionary ///
/// string, name to convert /// string - private static string Make_cname(string name) + protected static string Make_cname(string name) { if (name == null || name == "") return ""; - // split string to tokens, separated by non-word characters - string[] tokens = Regex.Split(name.Replace('-', '_'), @"[\W]+"); + // split string to tokens, separated by non-word characters. Remove any empty strings + var tokens = Regex.Split(name.Replace('-', '_'), @"[\W]+").Where(s => s != String.Empty); string output = ""; char prev = ' '; foreach (string tok in tokens) { - if (tok.Length == 0) - continue; - char first = tok[0]; - if (Char.IsDigit(first) || Char.IsDigit(prev) || (Char.IsUpper(prev) && Char.IsUpper(first))) + if (Char.IsUpper(prev) && Char.IsUpper(first)) { - // add underscore, if tok starts with digit or we have two upper-case words - output += "_" + tok; + // add underscore, if we have two upper-case words + output += "_"; } - else if (output.Length > 0) + + if (tok.Length > 1 && Char.IsLetter(first)) { - // all tokens except the first start with uppercse letter + // all tokens except the first start with uppercase letter output += Char.ToUpper(first) + tok.Substring(1); } - else if (Char.IsLower(tok[1])) - { - // first token start with lower-case letter, except whole word is uppercase - output += Char.ToLower(first) + tok.Substring(1); - } else { - // use token as is + // use token as is and handle what the start of the output looks like outside of the loop output += tok; } prev = tok[tok.Length - 1]; } + if (Char.IsDigit(output[0])) + { + // output that starts with a digit needs a starting underscore + output = "_" + output; + } + else if (output.Length > 1) + { + // output that doesnt start with all-cap-words should have word start with a lower case character + if (Char.IsLetter(output[0]) && Char.IsLower(output[1])) + output = Char.ToLower(output[0]) + output.Substring(1); + } + else + { + // single character output + output = output.ToLower(); + } + return output; } From 973eeb685557841ad506539557143c8934d5c127 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 19 Sep 2022 15:09:18 +0200 Subject: [PATCH 041/226] fixes issue #29 --- Tests/Tests.csproj | 231 +++++++++++++++++++------------------- libEDSsharp/CanOpenXDD.cs | 2 +- 2 files changed, 117 insertions(+), 116 deletions(-) diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 64cf6f23..bef33aff 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,122 +1,123 @@ - - - - - - - Debug - AnyCPU - {2A479BF3-7628-409B-8A29-9314C308445E} - Library - Properties - Tests - Tests - v4.5.2 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll - - - ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll - - - ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll - - - ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll - - - - - - - - - - - - - - - - - - - - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - - - - - - - - - - - - - False - - - False - - - False - - - False - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - + + + + + + + Debug + AnyCPU + {2A479BF3-7628-409B-8A29-9314C308445E} + Library + Properties + Tests + Tests + v4.8 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + + + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + + + pdbonly + true + bin\Release\ + TRACE + prompt + 4 + + + + + ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll + + + ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll + + + ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll + + + ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll + + + + + + + + + + + + + + + + + + + + + {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} + libEDSsharp + + + + + + + + + + + + + False + + + False + + + False + + + False + + + + + + + + + This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. + + + + + + + + --> \ No newline at end of file diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 5ddb0d08..f672961e 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -1114,7 +1114,7 @@ public EDSsharp convert(ISO15745ProfileContainer container) subentry.actualvalue = subobj.actualValue; //FIXME WTF is going on here?? - entry.subobjects.Add(subobj.subIndex[1], subentry); + entry.subobjects.Add(subobj.subIndex[0], subentry); } } From ea8c040021f9dbbaeaaa311c428bb02a42605d00 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 20 Sep 2022 10:39:36 +0200 Subject: [PATCH 042/226] delete redundant code possible fix for issue #34 --- libEDSsharp/CanOpenNodeExporter.cs | 6 ++++-- libEDSsharp/CanOpenNodeExporter_V4.cs | 4 ++-- libEDSsharp/CanOpenXDD.cs | 5 ----- 3 files changed, 6 insertions(+), 9 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 36a750fc..d2dd5e93 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -27,6 +27,8 @@ based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are using System.Threading.Tasks; using System.IO; + + namespace libEDSsharp { @@ -1349,10 +1351,10 @@ protected string make_cname(string name,ODentry entry) if (output.Length > 1) { if (Char.IsLower(output[1])) - output = Char.ToLower(output[0]) + output.Substring(1); + output = Char.ToLowerInvariant(output[0]) + output.Substring(1); } else - output = output.ToLower(); //single character + output = output.ToLowerInvariant(); //single character UInt32 key = (UInt32)((entry.Index << 8) + entry.Subindex ); diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 463ceb52..e5a18ebf 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -708,12 +708,12 @@ protected static string Make_cname(string name) { // output that doesnt start with all-cap-words should have word start with a lower case character if (Char.IsLetter(output[0]) && Char.IsLower(output[1])) - output = Char.ToLower(output[0]) + output.Substring(1); + output = Char.ToLowerInvariant(output[0]) + output.Substring(1); } else { // single character output - output = output.ToLower(); + output = output.ToLowerInvariant(); } return output; diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index f672961e..6edeadde 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -1109,11 +1109,6 @@ public EDSsharp convert(ISO15745ProfileContainer container) subentry.uniqueID = subobj.uniqueIDRef; - subentry.HighLimit = subobj.highLimit; - subentry.LowLimit = subobj.lowLimit; - subentry.actualvalue = subobj.actualValue; - - //FIXME WTF is going on here?? entry.subobjects.Add(subobj.subIndex[0], subentry); } From 9c4107b01f72dbb365bfaa27c2294abe544d0d78 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 28 Sep 2022 10:48:28 +0200 Subject: [PATCH 043/226] enhanced fix for issue #3 --- EDSEditorGUI/DeviceODView.Designer.cs | 301 +++++++++++--------------- 1 file changed, 121 insertions(+), 180 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index 14bd3856..927dd188 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -134,7 +134,6 @@ private void InitializeComponent() // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 0); - this.splitContainer1.Margin = new System.Windows.Forms.Padding(4); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 @@ -144,9 +143,8 @@ private void InitializeComponent() // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.splitContainer4); - this.splitContainer1.Size = new System.Drawing.Size(1518, 917); - this.splitContainer1.SplitterDistance = 376; - this.splitContainer1.SplitterWidth = 5; + this.splitContainer1.Size = new System.Drawing.Size(1138, 745); + this.splitContainer1.SplitterDistance = 281; this.splitContainer1.TabIndex = 2; this.splitContainer1.TabStop = false; // @@ -155,7 +153,6 @@ private void InitializeComponent() this.splitContainer2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer2.Location = new System.Drawing.Point(0, 0); - this.splitContainer2.Margin = new System.Windows.Forms.Padding(4); this.splitContainer2.Name = "splitContainer2"; this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -166,9 +163,8 @@ private void InitializeComponent() // splitContainer2.Panel2 // this.splitContainer2.Panel2.Controls.Add(this.splitContainer3); - this.splitContainer2.Size = new System.Drawing.Size(376, 917); - this.splitContainer2.SplitterDistance = 303; - this.splitContainer2.SplitterWidth = 5; + this.splitContainer2.Size = new System.Drawing.Size(281, 745); + this.splitContainer2.SplitterDistance = 246; this.splitContainer2.TabIndex = 0; this.splitContainer2.TabStop = false; // @@ -180,12 +176,11 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 2; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(374, 301); + this.tableLayoutPanel1.Size = new System.Drawing.Size(279, 244); this.tableLayoutPanel1.TabIndex = 6; // // listView_communication_objects @@ -196,10 +191,9 @@ private void InitializeComponent() this.listView_communication_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_communication_objects.FullRowSelect = true; this.listView_communication_objects.HideSelection = false; - this.listView_communication_objects.Location = new System.Drawing.Point(4, 29); - this.listView_communication_objects.Margin = new System.Windows.Forms.Padding(4); + this.listView_communication_objects.Location = new System.Drawing.Point(3, 23); this.listView_communication_objects.Name = "listView_communication_objects"; - this.listView_communication_objects.Size = new System.Drawing.Size(366, 268); + this.listView_communication_objects.Size = new System.Drawing.Size(273, 218); this.listView_communication_objects.TabIndex = 0; this.listView_communication_objects.UseCompatibleStateImageBehavior = false; this.listView_communication_objects.View = System.Windows.Forms.View.Details; @@ -219,10 +213,9 @@ private void InitializeComponent() // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(4, 0); - this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Location = new System.Drawing.Point(3, 0); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(223, 16); + this.label1.Size = new System.Drawing.Size(176, 13); this.label1.TabIndex = 3; this.label1.Text = "Communication Specific Parameters"; // @@ -231,7 +224,6 @@ private void InitializeComponent() this.splitContainer3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer3.Location = new System.Drawing.Point(0, 0); - this.splitContainer3.Margin = new System.Windows.Forms.Padding(4); this.splitContainer3.Name = "splitContainer3"; this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -242,9 +234,8 @@ private void InitializeComponent() // splitContainer3.Panel2 // this.splitContainer3.Panel2.Controls.Add(this.tableLayoutPanel3); - this.splitContainer3.Size = new System.Drawing.Size(376, 609); - this.splitContainer3.SplitterDistance = 302; - this.splitContainer3.SplitterWidth = 5; + this.splitContainer3.Size = new System.Drawing.Size(281, 495); + this.splitContainer3.SplitterDistance = 245; this.splitContainer3.TabIndex = 0; this.splitContainer3.TabStop = false; // @@ -256,21 +247,19 @@ private void InitializeComponent() this.tableLayoutPanel2.Controls.Add(this.listView_manufacturer_objects, 0, 1); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(4); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 2; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(374, 300); + this.tableLayoutPanel2.Size = new System.Drawing.Size(279, 243); this.tableLayoutPanel2.TabIndex = 7; // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(4, 0); - this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Location = new System.Drawing.Point(3, 0); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(208, 16); + this.label2.Size = new System.Drawing.Size(167, 13); this.label2.TabIndex = 4; this.label2.Text = "Manufacturer Specific Parameters"; // @@ -282,10 +271,9 @@ private void InitializeComponent() this.listView_manufacturer_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_manufacturer_objects.FullRowSelect = true; this.listView_manufacturer_objects.HideSelection = false; - this.listView_manufacturer_objects.Location = new System.Drawing.Point(4, 29); - this.listView_manufacturer_objects.Margin = new System.Windows.Forms.Padding(4); + this.listView_manufacturer_objects.Location = new System.Drawing.Point(3, 23); this.listView_manufacturer_objects.Name = "listView_manufacturer_objects"; - this.listView_manufacturer_objects.Size = new System.Drawing.Size(366, 267); + this.listView_manufacturer_objects.Size = new System.Drawing.Size(273, 217); this.listView_manufacturer_objects.TabIndex = 0; this.listView_manufacturer_objects.UseCompatibleStateImageBehavior = false; this.listView_manufacturer_objects.View = System.Windows.Forms.View.Details; @@ -310,21 +298,19 @@ private void InitializeComponent() this.tableLayoutPanel3.Controls.Add(this.listView_deviceProfile_objects, 0, 1); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 2; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(374, 300); + this.tableLayoutPanel3.Size = new System.Drawing.Size(279, 244); this.tableLayoutPanel3.TabIndex = 8; // // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(4, 0); - this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Location = new System.Drawing.Point(3, 0); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(215, 16); + this.label3.Size = new System.Drawing.Size(170, 13); this.label3.TabIndex = 5; this.label3.Text = "Device Profile Specific Parameters"; // @@ -336,10 +322,9 @@ private void InitializeComponent() this.listView_deviceProfile_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_deviceProfile_objects.FullRowSelect = true; this.listView_deviceProfile_objects.HideSelection = false; - this.listView_deviceProfile_objects.Location = new System.Drawing.Point(4, 29); - this.listView_deviceProfile_objects.Margin = new System.Windows.Forms.Padding(4); + this.listView_deviceProfile_objects.Location = new System.Drawing.Point(3, 23); this.listView_deviceProfile_objects.Name = "listView_deviceProfile_objects"; - this.listView_deviceProfile_objects.Size = new System.Drawing.Size(366, 267); + this.listView_deviceProfile_objects.Size = new System.Drawing.Size(273, 218); this.listView_deviceProfile_objects.TabIndex = 0; this.listView_deviceProfile_objects.UseCompatibleStateImageBehavior = false; this.listView_deviceProfile_objects.View = System.Windows.Forms.View.Details; @@ -360,7 +345,6 @@ private void InitializeComponent() // this.splitContainer4.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer4.Location = new System.Drawing.Point(0, 0); - this.splitContainer4.Margin = new System.Windows.Forms.Padding(4); this.splitContainer4.Name = "splitContainer4"; this.splitContainer4.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -381,9 +365,8 @@ private void InitializeComponent() this.splitContainer4.Panel2.Controls.Add(this.label6); this.splitContainer4.Panel2.Controls.Add(this.textBox_name); this.splitContainer4.Panel2.Controls.Add(this.textBox_description); - this.splitContainer4.Size = new System.Drawing.Size(1137, 917); - this.splitContainer4.SplitterDistance = 277; - this.splitContainer4.SplitterWidth = 5; + this.splitContainer4.Size = new System.Drawing.Size(853, 745); + this.splitContainer4.SplitterDistance = 225; this.splitContainer4.TabIndex = 28; this.splitContainer4.TabStop = false; // @@ -404,9 +387,8 @@ private void InitializeComponent() this.listView_subObjects.FullRowSelect = true; this.listView_subObjects.HideSelection = false; this.listView_subObjects.Location = new System.Drawing.Point(0, 0); - this.listView_subObjects.Margin = new System.Windows.Forms.Padding(4); this.listView_subObjects.Name = "listView_subObjects"; - this.listView_subObjects.Size = new System.Drawing.Size(1132, 273); + this.listView_subObjects.Size = new System.Drawing.Size(850, 223); this.listView_subObjects.TabIndex = 0; this.listView_subObjects.UseCompatibleStateImageBehavior = false; this.listView_subObjects.View = System.Windows.Forms.View.Details; @@ -455,38 +437,33 @@ private void InitializeComponent() // // textBox_subIndex // - this.textBox_subIndex.Location = new System.Drawing.Point(347, 10); - this.textBox_subIndex.Margin = new System.Windows.Forms.Padding(4); + this.textBox_subIndex.Location = new System.Drawing.Point(260, 8); this.textBox_subIndex.Name = "textBox_subIndex"; this.textBox_subIndex.ReadOnly = true; - this.textBox_subIndex.Size = new System.Drawing.Size(132, 22); + this.textBox_subIndex.Size = new System.Drawing.Size(100, 20); this.textBox_subIndex.TabIndex = 0; this.textBox_subIndex.TabStop = false; // // label23 // this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(265, 14); - this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label23.Location = new System.Drawing.Point(199, 11); this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(66, 16); + this.label23.Size = new System.Drawing.Size(55, 13); this.label23.TabIndex = 34; this.label23.Text = "Sub Index"; // // textBox_index // - this.textBox_index.Location = new System.Drawing.Point(120, 10); - this.textBox_index.Margin = new System.Windows.Forms.Padding(4); + this.textBox_index.Location = new System.Drawing.Point(90, 8); this.textBox_index.Name = "textBox_index"; this.textBox_index.ReadOnly = true; - this.textBox_index.Size = new System.Drawing.Size(132, 22); + this.textBox_index.Size = new System.Drawing.Size(100, 20); this.textBox_index.TabIndex = 0; this.textBox_index.TabStop = false; // // groupBox1 // - this.groupBox1.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); this.groupBox1.Controls.Add(this.textBox_stringLengthMin); this.groupBox1.Controls.Add(this.label22); this.groupBox1.Controls.Add(this.label20); @@ -516,41 +493,39 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.label10); this.groupBox1.Controls.Add(this.label11); this.groupBox1.Controls.Add(this.comboBox_accessPDO); - this.groupBox1.Location = new System.Drawing.Point(15, 397); - this.groupBox1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.groupBox1.Location = new System.Drawing.Point(0, 328); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.groupBox1.Size = new System.Drawing.Size(1119, 231); + this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Size = new System.Drawing.Size(853, 188); this.groupBox1.TabIndex = 33; this.groupBox1.TabStop = false; this.groupBox1.Text = "Object settings"; // // textBox_stringLengthMin // - this.textBox_stringLengthMin.Location = new System.Drawing.Point(453, 122); - this.textBox_stringLengthMin.Margin = new System.Windows.Forms.Padding(4); + this.textBox_stringLengthMin.Location = new System.Drawing.Point(340, 99); this.textBox_stringLengthMin.Name = "textBox_stringLengthMin"; - this.textBox_stringLengthMin.Size = new System.Drawing.Size(161, 22); + this.textBox_stringLengthMin.Size = new System.Drawing.Size(122, 20); this.textBox_stringLengthMin.TabIndex = 24; this.textBox_stringLengthMin.TextChanged += new System.EventHandler(this.DataDirty); // // label22 // this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(331, 126); - this.label22.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label22.Location = new System.Drawing.Point(248, 102); this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(90, 16); + this.label22.Size = new System.Drawing.Size(75, 13); this.label22.TabIndex = 39; this.label22.Text = "String Len Min"; // // label20 // this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(643, 26); - this.label20.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label20.Location = new System.Drawing.Point(482, 21); this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(78, 16); + this.label20.Size = new System.Drawing.Size(64, 13); this.label20.TabIndex = 36; this.label20.Text = "Count Label"; // @@ -558,20 +533,18 @@ private void InitializeComponent() // this.comboBox_countLabel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_countLabel.FormattingEnabled = true; - this.comboBox_countLabel.Location = new System.Drawing.Point(765, 22); - this.comboBox_countLabel.Margin = new System.Windows.Forms.Padding(4); + this.comboBox_countLabel.Location = new System.Drawing.Point(574, 18); this.comboBox_countLabel.Name = "comboBox_countLabel"; - this.comboBox_countLabel.Size = new System.Drawing.Size(161, 24); + this.comboBox_countLabel.Size = new System.Drawing.Size(122, 21); this.comboBox_countLabel.TabIndex = 30; this.comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label19 // this.label19.AutoSize = true; - this.label19.Location = new System.Drawing.Point(17, 159); - this.label19.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label19.Location = new System.Drawing.Point(13, 129); this.label19.Name = "label19"; - this.label19.Size = new System.Drawing.Size(94, 16); + this.label19.Size = new System.Drawing.Size(76, 13); this.label19.TabIndex = 34; this.label19.Text = "Access SRDO"; // @@ -579,68 +552,61 @@ private void InitializeComponent() // this.comboBox_accessSRDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSRDO.FormattingEnabled = true; - this.comboBox_accessSRDO.Location = new System.Drawing.Point(144, 155); - this.comboBox_accessSRDO.Margin = new System.Windows.Forms.Padding(4); + this.comboBox_accessSRDO.Location = new System.Drawing.Point(108, 126); this.comboBox_accessSRDO.Name = "comboBox_accessSRDO"; - this.comboBox_accessSRDO.Size = new System.Drawing.Size(161, 24); + this.comboBox_accessSRDO.Size = new System.Drawing.Size(122, 21); this.comboBox_accessSRDO.TabIndex = 14; this.comboBox_accessSRDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_actualValue // this.textBox_actualValue.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_actualValue.Location = new System.Drawing.Point(453, 89); - this.textBox_actualValue.Margin = new System.Windows.Forms.Padding(4); + this.textBox_actualValue.Location = new System.Drawing.Point(340, 72); this.textBox_actualValue.Name = "textBox_actualValue"; - this.textBox_actualValue.Size = new System.Drawing.Size(161, 22); + this.textBox_actualValue.Size = new System.Drawing.Size(122, 20); this.textBox_actualValue.TabIndex = 23; this.textBox_actualValue.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_lowLimit // - this.textBox_lowLimit.Location = new System.Drawing.Point(453, 55); - this.textBox_lowLimit.Margin = new System.Windows.Forms.Padding(4); + this.textBox_lowLimit.Location = new System.Drawing.Point(340, 45); this.textBox_lowLimit.Name = "textBox_lowLimit"; - this.textBox_lowLimit.Size = new System.Drawing.Size(161, 22); + this.textBox_lowLimit.Size = new System.Drawing.Size(122, 20); this.textBox_lowLimit.TabIndex = 22; this.textBox_lowLimit.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_highLimit // - this.textBox_highLimit.Location = new System.Drawing.Point(453, 22); - this.textBox_highLimit.Margin = new System.Windows.Forms.Padding(4); + this.textBox_highLimit.Location = new System.Drawing.Point(340, 18); this.textBox_highLimit.Name = "textBox_highLimit"; - this.textBox_highLimit.Size = new System.Drawing.Size(161, 22); + this.textBox_highLimit.Size = new System.Drawing.Size(122, 20); this.textBox_highLimit.TabIndex = 21; this.textBox_highLimit.TextChanged += new System.EventHandler(this.DataDirty); // // label18 // this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(331, 92); - this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label18.Location = new System.Drawing.Point(248, 75); this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(82, 16); + this.label18.Size = new System.Drawing.Size(67, 13); this.label18.TabIndex = 32; this.label18.Text = "Actual Value"; // // label17 // this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(331, 59); - this.label17.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label17.Location = new System.Drawing.Point(248, 48); this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(58, 16); + this.label17.Size = new System.Drawing.Size(48, 13); this.label17.TabIndex = 31; this.label17.Text = "LowLimit"; // // label14 // this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(331, 26); - this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label14.Location = new System.Drawing.Point(248, 21); this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(62, 16); + this.label14.Size = new System.Drawing.Size(50, 13); this.label14.TabIndex = 30; this.label14.Text = "HighLimit"; // @@ -648,10 +614,9 @@ private void InitializeComponent() // this.button_saveChanges.Image = global::ODEditor.Properties.Resources.Save_6530; this.button_saveChanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_saveChanges.Location = new System.Drawing.Point(647, 170); - this.button_saveChanges.Margin = new System.Windows.Forms.Padding(4); + this.button_saveChanges.Location = new System.Drawing.Point(485, 138); this.button_saveChanges.Name = "button_saveChanges"; - this.button_saveChanges.Size = new System.Drawing.Size(281, 43); + this.button_saveChanges.Size = new System.Drawing.Size(211, 35); this.button_saveChanges.TabIndex = 50; this.button_saveChanges.Text = "Save Changes"; this.button_saveChanges.UseVisualStyleBackColor = true; @@ -660,10 +625,9 @@ private void InitializeComponent() // label16 // this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(643, 59); - this.label16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label16.Location = new System.Drawing.Point(482, 48); this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(95, 16); + this.label16.Size = new System.Drawing.Size(76, 13); this.label16.TabIndex = 26; this.label16.Text = "Storage Group"; // @@ -671,30 +635,27 @@ private void InitializeComponent() // this.comboBox_storageGroup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_storageGroup.FormattingEnabled = true; - this.comboBox_storageGroup.Location = new System.Drawing.Point(765, 55); - this.comboBox_storageGroup.Margin = new System.Windows.Forms.Padding(4); + this.comboBox_storageGroup.Location = new System.Drawing.Point(574, 45); this.comboBox_storageGroup.Name = "comboBox_storageGroup"; - this.comboBox_storageGroup.Size = new System.Drawing.Size(161, 24); + this.comboBox_storageGroup.Size = new System.Drawing.Size(122, 21); this.comboBox_storageGroup.TabIndex = 31; this.comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label15 // this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(643, 89); - this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label15.Location = new System.Drawing.Point(482, 72); this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(58, 16); + this.label15.Size = new System.Drawing.Size(46, 13); this.label15.TabIndex = 24; this.label15.Text = "Enabled"; // // checkBox_enabled // this.checkBox_enabled.AutoSize = true; - this.checkBox_enabled.Location = new System.Drawing.Point(765, 89); - this.checkBox_enabled.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_enabled.Location = new System.Drawing.Point(574, 72); this.checkBox_enabled.Name = "checkBox_enabled"; - this.checkBox_enabled.Size = new System.Drawing.Size(18, 17); + this.checkBox_enabled.Size = new System.Drawing.Size(15, 14); this.checkBox_enabled.TabIndex = 32; this.checkBox_enabled.UseVisualStyleBackColor = true; this.checkBox_enabled.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -702,10 +663,9 @@ private void InitializeComponent() // label7 // this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(17, 26); - this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Location = new System.Drawing.Point(13, 21); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(81, 16); + this.label7.Size = new System.Drawing.Size(65, 13); this.label7.TabIndex = 7; this.label7.Text = "Object Type"; // @@ -713,20 +673,18 @@ private void InitializeComponent() // this.comboBox_objectType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_objectType.FormattingEnabled = true; - this.comboBox_objectType.Location = new System.Drawing.Point(144, 22); - this.comboBox_objectType.Margin = new System.Windows.Forms.Padding(4); + this.comboBox_objectType.Location = new System.Drawing.Point(108, 18); this.comboBox_objectType.Name = "comboBox_objectType"; - this.comboBox_objectType.Size = new System.Drawing.Size(161, 24); + this.comboBox_objectType.Size = new System.Drawing.Size(122, 21); this.comboBox_objectType.TabIndex = 10; this.comboBox_objectType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label8 // this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(17, 59); - this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Location = new System.Drawing.Point(13, 48); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(71, 16); + this.label8.Size = new System.Drawing.Size(57, 13); this.label8.TabIndex = 9; this.label8.Text = "Data Type"; // @@ -734,40 +692,36 @@ private void InitializeComponent() // this.comboBox_dataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_dataType.FormattingEnabled = true; - this.comboBox_dataType.Location = new System.Drawing.Point(144, 55); - this.comboBox_dataType.Margin = new System.Windows.Forms.Padding(4); + this.comboBox_dataType.Location = new System.Drawing.Point(108, 45); this.comboBox_dataType.Name = "comboBox_dataType"; - this.comboBox_dataType.Size = new System.Drawing.Size(161, 24); + this.comboBox_dataType.Size = new System.Drawing.Size(122, 21); this.comboBox_dataType.TabIndex = 11; this.comboBox_dataType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label_pdoFlags // this.label_pdoFlags.AutoSize = true; - this.label_pdoFlags.Location = new System.Drawing.Point(643, 113); - this.label_pdoFlags.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label_pdoFlags.Location = new System.Drawing.Point(482, 92); this.label_pdoFlags.Name = "label_pdoFlags"; - this.label_pdoFlags.Size = new System.Drawing.Size(76, 16); + this.label_pdoFlags.Size = new System.Drawing.Size(62, 13); this.label_pdoFlags.TabIndex = 18; this.label_pdoFlags.Text = "TPDO COS"; // // label9 // this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(17, 92); - this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Location = new System.Drawing.Point(13, 75); this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(84, 16); + this.label9.Size = new System.Drawing.Size(68, 13); this.label9.TabIndex = 11; this.label9.Text = "Access SDO"; // // checkBox_pdoFlags // this.checkBox_pdoFlags.AutoSize = true; - this.checkBox_pdoFlags.Location = new System.Drawing.Point(765, 113); - this.checkBox_pdoFlags.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_pdoFlags.Location = new System.Drawing.Point(574, 92); this.checkBox_pdoFlags.Name = "checkBox_pdoFlags"; - this.checkBox_pdoFlags.Size = new System.Drawing.Size(18, 17); + this.checkBox_pdoFlags.Size = new System.Drawing.Size(15, 14); this.checkBox_pdoFlags.TabIndex = 34; this.checkBox_pdoFlags.UseVisualStyleBackColor = true; this.checkBox_pdoFlags.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -776,39 +730,35 @@ private void InitializeComponent() // this.comboBox_accessSDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSDO.FormattingEnabled = true; - this.comboBox_accessSDO.Location = new System.Drawing.Point(144, 89); - this.comboBox_accessSDO.Margin = new System.Windows.Forms.Padding(4); + this.comboBox_accessSDO.Location = new System.Drawing.Point(108, 72); this.comboBox_accessSDO.Name = "comboBox_accessSDO"; - this.comboBox_accessSDO.Size = new System.Drawing.Size(161, 24); + this.comboBox_accessSDO.Size = new System.Drawing.Size(122, 21); this.comboBox_accessSDO.TabIndex = 12; this.comboBox_accessSDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_defaultValue // - this.textBox_defaultValue.Location = new System.Drawing.Point(144, 188); - this.textBox_defaultValue.Margin = new System.Windows.Forms.Padding(4); + this.textBox_defaultValue.Location = new System.Drawing.Point(108, 153); this.textBox_defaultValue.Name = "textBox_defaultValue"; - this.textBox_defaultValue.Size = new System.Drawing.Size(471, 22); + this.textBox_defaultValue.Size = new System.Drawing.Size(354, 20); this.textBox_defaultValue.TabIndex = 20; this.textBox_defaultValue.TextChanged += new System.EventHandler(this.DataDirty); // // label10 // this.label10.AutoSize = true; - this.label10.Location = new System.Drawing.Point(17, 126); - this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label10.Location = new System.Drawing.Point(13, 102); this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(84, 16); + this.label10.Size = new System.Drawing.Size(68, 13); this.label10.TabIndex = 13; this.label10.Text = "Access PDO"; // // label11 // this.label11.AutoSize = true; - this.label11.Location = new System.Drawing.Point(17, 192); - this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label11.Location = new System.Drawing.Point(13, 156); this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(85, 16); + this.label11.Size = new System.Drawing.Size(70, 13); this.label11.TabIndex = 15; this.label11.Text = "Default value"; // @@ -816,10 +766,9 @@ private void InitializeComponent() // this.comboBox_accessPDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessPDO.FormattingEnabled = true; - this.comboBox_accessPDO.Location = new System.Drawing.Point(144, 122); - this.comboBox_accessPDO.Margin = new System.Windows.Forms.Padding(4); + this.comboBox_accessPDO.Location = new System.Drawing.Point(108, 99); this.comboBox_accessPDO.Name = "comboBox_accessPDO"; - this.comboBox_accessPDO.Size = new System.Drawing.Size(161, 24); + this.comboBox_accessPDO.Size = new System.Drawing.Size(122, 21); this.comboBox_accessPDO.TabIndex = 13; this.comboBox_accessPDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // @@ -828,50 +777,45 @@ private void InitializeComponent() this.textBox_denotation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_denotation.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_denotation.Location = new System.Drawing.Point(120, 74); - this.textBox_denotation.Margin = new System.Windows.Forms.Padding(4); + this.textBox_denotation.Location = new System.Drawing.Point(90, 60); this.textBox_denotation.Name = "textBox_denotation"; - this.textBox_denotation.Size = new System.Drawing.Size(1012, 22); + this.textBox_denotation.Size = new System.Drawing.Size(760, 20); this.textBox_denotation.TabIndex = 3; this.textBox_denotation.TextChanged += new System.EventHandler(this.DataDirty); // // label13 // this.label13.AutoSize = true; - this.label13.Location = new System.Drawing.Point(17, 78); - this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label13.Location = new System.Drawing.Point(13, 63); this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(72, 16); + this.label13.Size = new System.Drawing.Size(59, 13); this.label13.TabIndex = 28; this.label13.Text = "Denotation"; // // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(17, 14); - this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Location = new System.Drawing.Point(13, 11); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(39, 16); + this.label4.Size = new System.Drawing.Size(33, 13); this.label4.TabIndex = 1; this.label4.Text = "Index"; // // label5 // this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(17, 46); - this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Location = new System.Drawing.Point(13, 37); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(44, 16); + this.label5.Size = new System.Drawing.Size(35, 13); this.label5.TabIndex = 2; this.label5.Text = "Name"; // // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(17, 110); - this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Location = new System.Drawing.Point(13, 89); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(75, 16); + this.label6.Size = new System.Drawing.Size(60, 13); this.label6.TabIndex = 3; this.label6.Text = "Description"; // @@ -879,10 +823,9 @@ private void InitializeComponent() // this.textBox_name.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_name.Location = new System.Drawing.Point(120, 42); - this.textBox_name.Margin = new System.Windows.Forms.Padding(4); + this.textBox_name.Location = new System.Drawing.Point(90, 34); this.textBox_name.Name = "textBox_name"; - this.textBox_name.Size = new System.Drawing.Size(1012, 22); + this.textBox_name.Size = new System.Drawing.Size(760, 20); this.textBox_name.TabIndex = 2; this.textBox_name.TextChanged += new System.EventHandler(this.DataDirty); // @@ -894,12 +837,11 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_description.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBox_description.Location = new System.Drawing.Point(120, 106); - this.textBox_description.Margin = new System.Windows.Forms.Padding(4); + this.textBox_description.Location = new System.Drawing.Point(90, 86); this.textBox_description.Multiline = true; this.textBox_description.Name = "textBox_description"; this.textBox_description.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBox_description.Size = new System.Drawing.Size(1012, 279); + this.textBox_description.Size = new System.Drawing.Size(760, 227); this.textBox_description.TabIndex = 4; this.textBox_description.TextChanged += new System.EventHandler(this.DataDirty); // @@ -912,12 +854,12 @@ private void InitializeComponent() this.contextMenu_object_deleteObjectToolStripMenuItem, this.contextMenu_object_toggleObjectToolStripMenuItem}); this.contextMenu_object.Name = "contextMenuStrip1"; - this.contextMenu_object.Size = new System.Drawing.Size(136, 108); + this.contextMenu_object.Size = new System.Drawing.Size(121, 108); // // contextMenu_object_addNewObjectToolStripMenuItem // this.contextMenu_object_addNewObjectToolStripMenuItem.Name = "contextMenu_object_addNewObjectToolStripMenuItem"; - this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.contextMenu_object_addNewObjectToolStripMenuItem.Text = "&Clone..."; this.contextMenu_object_addNewObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_clone_ToolStripMenuItem_Click); // @@ -925,7 +867,7 @@ private void InitializeComponent() // this.addToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.addToolStripMenuItem.Name = "addToolStripMenuItem"; - this.addToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.addToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.addToolStripMenuItem.Text = "Add..."; this.addToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_add_ToolStripMenuItem_Click); // @@ -933,14 +875,14 @@ private void InitializeComponent() // this.contextMenu_object_deleteObjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_object_deleteObjectToolStripMenuItem.Name = "contextMenu_object_deleteObjectToolStripMenuItem"; - this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.contextMenu_object_deleteObjectToolStripMenuItem.Text = "&Delete..."; this.contextMenu_object_deleteObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_delete_ToolStripMenuItem_Click); // // contextMenu_object_toggleObjectToolStripMenuItem // this.contextMenu_object_toggleObjectToolStripMenuItem.Name = "contextMenu_object_toggleObjectToolStripMenuItem"; - this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.contextMenu_object_toggleObjectToolStripMenuItem.Text = "&Toggle"; this.contextMenu_object_toggleObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_toggle_ToolStripMenuItem_Click); // @@ -952,13 +894,13 @@ private void InitializeComponent() this.contextMenu_subObject_removeSubItemToolStripMenuItem, this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem}); this.contextMenu_subObject.Name = "contextMenu_array"; - this.contextMenu_subObject.Size = new System.Drawing.Size(216, 82); + this.contextMenu_subObject.Size = new System.Drawing.Size(183, 82); // // contextMenu_subObject_addSubItemToolStripMenuItem // this.contextMenu_subObject_addSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.contextMenu_subObject_addSubItemToolStripMenuItem.Name = "contextMenu_subObject_addSubItemToolStripMenuItem"; - this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); + this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); this.contextMenu_subObject_addSubItemToolStripMenuItem.Text = "Add"; this.contextMenu_subObject_addSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_add_ToolStripMenuItem_Click); // @@ -966,7 +908,7 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); this.contextMenu_subObject_removeSubItemToolStripMenuItem.Text = "Remove (shift up)"; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // @@ -974,18 +916,17 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(215, 26); + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(182, 26); this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Text = "Remove (leave gap)"; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // // DeviceODView // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.splitContainer1); - this.Margin = new System.Windows.Forms.Padding(4); this.Name = "DeviceODView"; - this.Size = new System.Drawing.Size(1518, 917); + this.Size = new System.Drawing.Size(1138, 745); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); From e6cb85dc10eb7bd8f4566f4c5ac6c510e47be835 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 17 Oct 2022 11:23:42 +0200 Subject: [PATCH 044/226] Bugfix for the exception on whitespace in the passed default value Bugfix for issue #10 RPO Count not updated --- EDSEditorGUI/DeviceODView.cs | 2 +- libEDSsharp/CanOpenNodeExporter.cs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index 9e1a0a58..565402b0 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -143,7 +143,7 @@ public void PopulateObjectLists(EDSsharp eds_target) return; eds = eds_target; - + eds.UpdatePDOcount(); doUpdateDeviceInfo(); doUpdatePDOs(); diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index d2dd5e93..7f8faa3e 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -1179,7 +1179,7 @@ string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring= if (nodeidreplace) { - UInt32 data = Convert.ToUInt32(defaultvalue, nobase); + UInt32 data = Convert.ToUInt32(defaultvalue.Trim(), nobase); data += eds.NodeId; defaultvalue = string.Format("0x{0:X}", data); nobase = 16; From 513ebb9cbf0ac7b258c4a797701dd3b2901b1c06 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 17 Oct 2022 14:17:29 +0200 Subject: [PATCH 045/226] CANOpen spec requires the ObjFlags field to be a 32bit unsigned integer. --- libEDSsharp/eds.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 78e5e113..1dd34ee0 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1076,7 +1076,7 @@ public UInt16 Index public string actualvalue = ""; [EdsExport] - public Byte ObjFlags = 0; + public UInt32 ObjFlags = 0; [EdsExport] public byte CompactSubObj = 0; @@ -2192,7 +2192,7 @@ public void ParseEDSentry(KeyValuePair> kvp) if(kvp.Value.ContainsKey("ObjFlags")) { - od.ObjFlags = Convert.ToByte(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); + od.ObjFlags = Convert.ToUInt32(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); } else { From 5fa09ce12d0f10c8078cd523148435076743f994 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 18 Oct 2022 12:24:43 +0200 Subject: [PATCH 046/226] bugfix wrong foundcol if Hscrollbar.value is not zero in getItemAtGridPoint wordwrap bit-position column header --- EDSEditorGUI/DevicePDOView2.cs | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 75cabf51..99ff06ae 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -179,15 +179,22 @@ SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P, out int foundrow, out int x = 0; int x2 = 0; foundcol = 0; + int outofview = 0; + for (int i = 0; i < grid1.HScrollBar.Value; i++) + { + outofview += grid1.Columns.GetWidth(i); + } + + x2 = -outofview; foreach (GridColumn col in grid1.Columns) { - x2 = x + col.Width; - if (P.X > x && P.X < x2) + + if (P.X > x2) { - foundcol = col.Index + grid1.HScrollBar.Value; + foundcol = col.Index; } - x = x2; + x2 += col.Width; } Console.WriteLine(string.Format("Found grid at {0}x{1}", foundcol, foundrow)); @@ -204,8 +211,8 @@ private void Grid1_Click(object sender, EventArgs e) MouseEventArgs ma = (MouseEventArgs)e; int foundrow, foundcol; - SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(ma.Location, out foundrow, out foundcol); - + SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(ma.Location, out foundrow, out foundcol); + grid1.Selection.ResetSelection(false); grid1.Selection.SelectRow(foundrow, true); @@ -511,6 +518,7 @@ public MyHeader(object value) : base(value) //1 Header Row SourceGrid.Cells.Views.ColumnHeader view = new SourceGrid.Cells.Views.ColumnHeader(); view.Font = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Bold); + view.WordWrap = true; view.TextAlignment = DevAge.Drawing.ContentAlignment.MiddleCenter; view.BackColor = Color.Red; From 16533eec51ec064546272eb47b5302d5220623eb Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 19 Oct 2022 08:00:27 +0200 Subject: [PATCH 047/226] Merge artifacts cleaned --- EDSEditorGUI/DevicePDOView2.cs | 184 ++++++++++++++------------ libEDSsharp/CanOpenNodeExporter_V4.cs | 6 +- libEDSsharp/PDOHelper.cs | 33 +++-- 3 files changed, 126 insertions(+), 97 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 5c4b1983..619cdf19 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -22,9 +22,9 @@ public partial class DevicePDOView2 : MyTabUserControl StringCollection TXchoices = new StringCollection(); string[] srray; - PDOSlot selectedslot = null; - - CellBackColorAlternate viewNormal = new CellBackColorAlternate(Color.Khaki, Color.DarkKhaki); + PDOSlot selectedslot = null; + + CellBackColorAlternate viewNormal = new CellBackColorAlternate(Color.Khaki, Color.DarkKhaki); CellBackColorAlternate viewEmpty = new CellBackColorAlternate(Color.Gray, Color.Gray); CellBackColorAlternate viewCOB = new CellBackColorAlternate(Color.LightBlue, Color.Blue); @@ -52,23 +52,22 @@ public DevicePDOView2() grid1.Columns[1].Width = 45; grid1.Columns[2].Width = 50; - for (int x=0;x<64;x++) + for (int x = 0; x < 64; x++) { - grid1[0, 3+x] = new MyHeader(string.Format("{0}",x)); + grid1[0, 3 + x] = new MyHeader(string.Format("{0}", x)); } for (int x = 0; x < 8; x++) { - grid1[1, 3 + x*8] = new MyHeader(string.Format("Byte {0}", x)); + grid1[1, 3 + x * 8] = new MyHeader(string.Format("Byte {0}", x)); grid1[1, 3 + x * 8].ColumnSpan = 8; grid1[1, 3 + x * 8].View.BackColor = Color.Red; } - grid1.Rows[0].Height = 30; - - + grid1.Rows[0].Height = 30; + contextMenuStrip_removeitem.ItemClicked += ContextMenuStrip_removeitem_ItemClicked; Invalidated += DevicePDOView2_Invalidated; @@ -98,14 +97,14 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte switch (e.ClickedItem.Tag) { - case "remove": - location.slot.Mapping.Remove(location.entry); - + case "remove": + location.slot.Mapping.Remove(location.entry); + break; - case "insert": - ODentry od = new ODentry(); - location.slot.Mapping.Insert(location.ordinal, eds.dummy_ods[0x002]); + case "insert": + ODentry od = new ODentry(); + location.slot.Mapping.Insert(location.ordinal, eds.dummy_ods[0x002]); break; } @@ -119,9 +118,9 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte private void Vcc_ValueChangedEvent(object sender, EventArgs e) { - SourceGrid.CellContext cell = (SourceGrid.CellContext)sender; - - // "0x3100/05/BUTTONS2" + SourceGrid.CellContext cell = (SourceGrid.CellContext)sender; + + // "0x3100/05/BUTTONS2" string[] bits = cell.Value.ToString().Split('/'); UInt16 newindex = EDSsharp.ConvertToUInt16(bits[0]); @@ -134,12 +133,12 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) PDOlocator location = (PDOlocator)((SourceGrid.Cells.Cell)cell.Cell).Tag; PDOSlot slot = location.slot; - ODentry newentry = null; - + ODentry newentry = null; + if (eds.tryGetODEntry(newindex, out newentry)) { if (newsubindex != 0) - newentry = newentry.subobjects[newsubindex]; + newentry = newentry.subobjects[newsubindex]; } else { @@ -161,7 +160,7 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) UpdatePDOinfo(); } - SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P , out int foundrow,out int foundcol) + SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P, out int foundrow, out int foundcol) { int y = 0; int y2 = 0; @@ -177,18 +176,24 @@ SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P , out int foundrow,out y = y2; } - int x = 0; int x2 = 0; foundcol = 0; + int outofview = 0; + for (int i = 0; i < grid1.HScrollBar.Value; i++) + { + outofview += grid1.Columns.GetWidth(i); + } + + x2 = -outofview; foreach (GridColumn col in grid1.Columns) { - x2 = x + col.Width; - if (P.X > x && P.X < x2) + + if (P.X > x2) { - foundcol = col.Index + grid1.HScrollBar.Value; + foundcol = col.Index; } - x = x2; + x2 += col.Width; } Console.WriteLine(string.Format("Found grid at {0}x{1}", foundcol, foundrow)); @@ -205,18 +210,30 @@ private void Grid1_Click(object sender, EventArgs e) MouseEventArgs ma = (MouseEventArgs)e; int foundrow, foundcol; - SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(ma.Location,out foundrow, out foundcol); - + SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(ma.Location, out foundrow, out foundcol); + + + //// DEBUG code: Create ToolTip with col, row and hscroll.value + //ToolTip toolTip1 = new ToolTip(); + //if (ma.Button == MouseButtons.Left) + //{ + // Point loc = new Point(0, 0); + // loc.X = foundcol; + // loc.Y = foundrow; + // // Force the ToolTip text to be displayed whether or not the form is active. + // toolTip1.ShowAlways = true; + // toolTip1.Show(loc.ToString() + ", " + grid1.HScrollBar.Value.ToString(), grid1, ma.Location); + } grid1.Selection.ResetSelection(false); grid1.Selection.SelectRow(foundrow, true); - if(ma.Button==MouseButtons.Right) + if (ma.Button == MouseButtons.Right) { RightClickPoint = ma.Location; //Show context menu - contextMenuStrip_removeitem.Show(grid1,ma.Location); + contextMenuStrip_removeitem.Show(grid1, ma.Location); } - else if(foundrow>1) //don't select headers or bits + else if (foundrow > 1) //don't select headers or bits { var obj = grid1.Rows[foundrow]; if (obj!= null && obj.Tag != null) @@ -240,10 +257,10 @@ private void Grid1_Click(object sender, EventArgs e) button_savepdochanges.Enabled = true; //Is invalid bit set - checkBox_invalidpdo.Checked = slot.invalid; - - - + checkBox_invalidpdo.Checked = slot.invalid; + + + } } @@ -262,9 +279,9 @@ public void Init(bool isTX) } } - public libEDSsharp.EDSsharp eds; - - + public libEDSsharp.EDSsharp eds; + + public void addPDOchoices() { @@ -341,13 +358,13 @@ public void updateslotdisplay() } - public void UpdatePDOinfo(bool updatechoices=true) + public void UpdatePDOinfo(bool updatechoices = true) { int savVScrollValue = 0; if (!updatechoices) - savVScrollValue = grid1.VScrollBar.Value; - + savVScrollValue = grid1.VScrollBar.Value; + button_savepdochanges.Enabled = (textBox_slot.Text != ""); updateslotdisplay(); @@ -355,13 +372,13 @@ public void UpdatePDOinfo(bool updatechoices=true) if (eds == null) return; - if(updatechoices) + if (updatechoices) addPDOchoices(); - if(grid1.RowsCount>2) - grid1.Rows.RemoveRange(2, grid1.RowsCount - 2); - - + if (grid1.RowsCount > 2) + grid1.Rows.RemoveRange(2, grid1.RowsCount - 2); + + TXchoices.Clear(); foreach (ODentry od in eds.dummy_ods.Values) @@ -424,10 +441,10 @@ public void UpdatePDOinfo(bool updatechoices=true) continue; grid1.Redim(grid1.RowsCount + 1, grid1.ColumnsCount); - grid1.Rows[grid1.RowsCount-1].Tag = slot; - grid1.Rows[row+2].Height = 30; + grid1.Rows[grid1.RowsCount - 1].Tag = slot; + grid1.Rows[row + 2].Height = 30; - grid1[row+2,0] = new SourceGrid.Cells.Cell(String.Format("{0}", row + 1), typeof(string)); + grid1[row + 2, 0] = new SourceGrid.Cells.Cell(String.Format("{0}", row + 1), typeof(string)); grid1[row + 2, 1] = new SourceGrid.Cells.Cell(String.Format("{0:x}", slot.COB), typeof(string)); grid1[row + 2, 2] = new SourceGrid.Cells.Cell(String.Format("{0:x}", slot.ConfigurationIndex), typeof(string)); @@ -439,11 +456,11 @@ public void UpdatePDOinfo(bool updatechoices=true) int ordinal = 0; foreach (ODentry entry in slot.Mapping) { - { + { string target = slot.getTargetName(entry); - grid1[row+2, bitoff+3] = new SourceGrid.Cells.Cell(target, comboStandard); + grid1[row + 2, bitoff + 3] = new SourceGrid.Cells.Cell(target, comboStandard); grid1[row + 2, bitoff + 3].ColumnSpan = entry.Sizeofdatatype(); - grid1[row+2, bitoff+3].View = viewNormal; + grid1[row + 2, bitoff + 3].View = viewNormal; PDOlocator location = new PDOlocator(); location.slot = slot; @@ -465,7 +482,7 @@ public void UpdatePDOinfo(bool updatechoices=true) } //Pad out with an empty combo - if(bitoff<64) + if (bitoff < 64) { grid1[row + 2, bitoff + 3] = new SourceGrid.Cells.Cell("Empty", comboStandard); int colspan = 64 - bitoff; @@ -501,8 +518,8 @@ private void ComboStandard_Changed(object sender, EventArgs e) } public void redrawtable() - { - + { + } private class MyHeader : SourceGrid.Cells.ColumnHeader @@ -512,11 +529,12 @@ public MyHeader(object value) : base(value) //1 Header Row SourceGrid.Cells.Views.ColumnHeader view = new SourceGrid.Cells.Views.ColumnHeader(); view.Font = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Bold); + view.WordWrap = true; view.TextAlignment = DevAge.Drawing.ContentAlignment.MiddleCenter; view.BackColor = Color.Red; string text = value.ToString(); - if(text=="0"||text=="8"||text=="16"||text=="24"||text=="32"||text=="40"||text=="48"||text=="56") + if (text == "0" || text == "8" || text == "16" || text == "24" || text == "32" || text == "40" || text == "48" || text == "56") { view.ForeColor = Color.Red; } @@ -536,7 +554,7 @@ private class PDOlocator public override string ToString() { string msg; - msg = String.Format("Ordinal {0} , slot {1} entry {2}", ordinal, slot.ToString(), entry==null?"NULL":entry.ToString()); + msg = String.Format("Ordinal {0} , slot {1} entry {2}", ordinal, slot.ToString(), entry == null ? "NULL" : entry.ToString()); return msg; } @@ -557,7 +575,7 @@ private void button_down_Click(object sender, EventArgs e) Console.WriteLine("New Width " + newwidth.ToString()); - for(int x=0;x<64;x++) + for (int x = 0; x < 64; x++) { grid1.Columns[x + 3].Width = newwidth; } @@ -611,14 +629,14 @@ protected override void PrepareView(SourceGrid.CellContext context) } private void listView_TXPDO_ItemDrag(object sender, ItemDragEventArgs e) - { - - + { + + List entries = new List(); - foreach(ListViewItem item in listView_TXPDO.SelectedItems) + foreach (ListViewItem item in listView_TXPDO.SelectedItems) { - if(item.Tag.GetType() == typeof(ODentry)) + if (item.Tag.GetType() == typeof(ODentry)) entries.Add((ODentry)item.Tag); } @@ -626,18 +644,18 @@ private void listView_TXPDO_ItemDrag(object sender, ItemDragEventArgs e) data.SetData(entries.ToArray()); listView_TXPDO.DoDragDrop(data, DragDropEffects.Copy); - } - - - + } + + + private void grid1_DragOver(object sender, DragEventArgs e) { Point p = grid1.PointToClient(new Point(e.X, e.Y)); int foundrow, foundcol; - SourceGrid.Cells.Cell cell = (SourceGrid.Cells.Cell)getItemAtGridPoint(p,out foundrow,out foundcol); + SourceGrid.Cells.Cell cell = (SourceGrid.Cells.Cell)getItemAtGridPoint(p, out foundrow, out foundcol); - if(cell==null || cell.Tag==null) + if (cell == null || cell.Tag == null) { e.Effect = DragDropEffects.None; } @@ -658,7 +676,7 @@ private void grid1_DragDrop(object sender, DragEventArgs e) SourceGrid.Cells.Cell cell = (SourceGrid.Cells.Cell)getItemAtGridPoint(p, out foundrow, out foundcol); - ODentry[] entries = (ODentry[]) e.Data.GetData(typeof(ODentry[])); + ODentry[] entries = (ODentry[])e.Data.GetData(typeof(ODentry[])); PDOlocator location = (PDOlocator)cell.Tag; if (location == null || entries == null) @@ -666,7 +684,7 @@ private void grid1_DragDrop(object sender, DragEventArgs e) foreach (ODentry entry in entries) { - location.slot.insertMapping(location.ordinal, entry); + location.slot.insertMapping(location.ordinal, entry); } helper.buildmappingsfromlists(); @@ -690,8 +708,8 @@ public override void OnValueChanged(CellContext sender, EventArgs e) handler?.Invoke(sender, e); base.OnValueChanged(sender, e); - } - + } + } private void button_deletePDO_Click(object sender, EventArgs e) @@ -699,7 +717,7 @@ private void button_deletePDO_Click(object sender, EventArgs e) if (selectedslot == null) return; - if (MessageBox.Show(string.Format("Are you sure you wish to delete the entire PDO 0x{0:x4}/0x{1:x4}",selectedslot.ConfigurationIndex,selectedslot.MappingIndex), "Are you sure", MessageBoxButtons.YesNo) == DialogResult.Yes) + if (MessageBox.Show(string.Format("Are you sure you wish to delete the entire PDO 0x{0:x4}/0x{1:x4}", selectedslot.ConfigurationIndex, selectedslot.MappingIndex), "Are you sure", MessageBoxButtons.YesNo) == DialogResult.Yes) { helper.pdoslots.Remove(selectedslot); @@ -750,9 +768,9 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) UInt16 config = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_slot.Text); - if(!isTXPDO) + if (!isTXPDO) { - if(config<0x1400 | config >= 0x1600) + if (config < 0x1400 | config >= 0x1600) { MessageBox.Show(string.Format("Invalid TXPDO Communication parameters index 0x{0:x4}", config)); return; @@ -765,8 +783,8 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) MessageBox.Show(string.Format("Invalid RXPDO Communication parameters index 0x{0:x4}", config)); return; } - } - + } + UInt16 inhibit = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_inhibit.Text); UInt16 eventtimer = libEDSsharp.EDSsharp.ConvertToUInt16(textBox_eventtimer.Text); UInt32 COB = libEDSsharp.EDSsharp.ConvertToUInt32(textBox_cob.Text); @@ -784,7 +802,7 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) { helper.buildmappingsfromlists(); } - catch(Exception ex) + catch (Exception ex) { MessageBox.Show(ex.ToString()); } @@ -792,7 +810,7 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) doUpdateOD(); UpdatePDOinfo(); } - } - -} \ No newline at end of file + } +} + \ No newline at end of file diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index c10104b1..7244a4e0 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -677,7 +677,6 @@ protected static string Make_cname(string name) char prev = ' '; foreach (string tok in tokens) { - char first = tok[0]; if (Char.IsUpper(prev) && Char.IsUpper(first)) @@ -699,6 +698,7 @@ protected static string Make_cname(string name) prev = tok[tok.Length - 1]; } + if (Char.IsDigit(output[0])) { // output that starts with a digit needs a starting underscore @@ -708,12 +708,16 @@ protected static string Make_cname(string name) { // output that doesnt start with all-cap-words should have word start with a lower case character if (Char.IsLetter(output[0]) && Char.IsLower(output[1])) + output = Char.ToLowerInvariant(output[0]) + output.Substring(1); + } else { // single character output + output = output.ToLowerInvariant(); + } return output; diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 56e2b756..0c348289 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -11,7 +11,7 @@ public class PDOSlot { private UInt16 _MappingIndex; - private UInt16 _ConfigurationIndex; + private UInt16 _ConfigurationIndex; public bool nodeidpresent; public ushort ConfigurationIndex { @@ -31,7 +31,7 @@ public ushort ConfigurationIndex } else { - throw new ArgumentOutOfRangeException("Configuration Index", "Must be between 0x1400 and 0x17FF"); + throw new ArgumentOutOfRangeException("Configuration Index", "Must be between 0x1400 and 0x17FF "); } @@ -47,6 +47,7 @@ public ushort MappingIndex public EDSsharp.AccessType configAccessType; public string mappingloc; public string configloc; + public uint COB; @@ -82,7 +83,7 @@ public bool invalid public byte syncstart; public byte transmissiontype; public string Description; - + public PDOSlot() { configloc = "PERSIST_COMM"; @@ -90,7 +91,7 @@ public PDOSlot() transmissiontype = 254; Mapping = new List(); Description = ""; - } + } public string getTargetName(ODentry od) { @@ -328,9 +329,11 @@ public void buildmappingsfromlists() sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = slot.COB.ToHexString(); + + sub.defaultvalue = slot.COB.ToHexString(); if (slot.nodeidpresent) sub.defaultvalue += " + $NODEID"; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -371,10 +374,12 @@ public void buildmappingsfromlists() config.prop.CO_countLabel = "RPDO"; sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); - sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = slot.COB.ToHexString(); + + sub.datatype = DataType.UNSIGNED32; + sub.defaultvalue = slot.COB.ToHexString(); if (slot.nodeidpresent) sub.defaultvalue += " + $NODEID"; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -429,8 +434,10 @@ public void buildmappingsfromlists() /// public void addPDOslot(UInt16 configindex) { - //quick range check, it must be a config index for an RXPDO or a TXPDO. True if not in range 0x1400...0x15FF OR 0x1800...0x19FF - if ((configindex < 0x1400) || (configindex >= 0x1a00) || ((configindex >= 0x1600) && (configindex < 0x1800))) + + //quick range check, it must be a config index for an RXPDO or a TXPDO + if( (configindex<0x1400) || (configindex >= 0x1a00) || ((configindex>=0x1600) && (configindex<0x1800))) + return; foreach(PDOSlot slot in pdoslots) @@ -442,10 +449,10 @@ public void addPDOslot(UInt16 configindex) bool isTXPDO = configindex >= 0x1800; PDOSlot newslot = new PDOSlot(); - newslot.ConfigurationIndex = configindex; - - newslot.COB = 0x180; // Fixme need better defaults??? - newslot.configloc = "RAM"; + newslot.ConfigurationIndex = configindex; + + newslot.COB = 0x180; // Fixme need better defaults??? + newslot.configloc = "RAM"; newslot.mappingloc = "RAM"; pdoslots.Add(newslot); From f9454d9ce32cc4dc8fee793287184a7bf4beeb9e Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 19 Oct 2022 08:10:13 +0200 Subject: [PATCH 048/226] add missed line comment --- EDSEditorGUI/DevicePDOView2.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 619cdf19..2dc6d73a 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -223,7 +223,8 @@ private void Grid1_Click(object sender, EventArgs e) // // Force the ToolTip text to be displayed whether or not the form is active. // toolTip1.ShowAlways = true; // toolTip1.Show(loc.ToString() + ", " + grid1.HScrollBar.Value.ToString(), grid1, ma.Location); - } + //} + grid1.Selection.ResetSelection(false); grid1.Selection.SelectRow(foundrow, true); From 23ba8bf58b445643758f8e9bd7194fcf665c7e9c Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 19 Oct 2022 08:18:36 +0200 Subject: [PATCH 049/226] whitespace removes --- libEDSsharp/CanOpenNodeExporter_V4.cs | 4 ---- libEDSsharp/PDOHelper.cs | 5 ----- 2 files changed, 9 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 7244a4e0..e5a18ebf 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -708,16 +708,12 @@ protected static string Make_cname(string name) { // output that doesnt start with all-cap-words should have word start with a lower case character if (Char.IsLetter(output[0]) && Char.IsLower(output[1])) - output = Char.ToLowerInvariant(output[0]) + output.Substring(1); - } else { // single character output - output = output.ToLowerInvariant(); - } return output; diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 0c348289..0b73e640 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -48,7 +48,6 @@ public ushort MappingIndex public string mappingloc; public string configloc; - public uint COB; public bool isTXPDO() @@ -329,11 +328,9 @@ public void buildmappingsfromlists() sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = slot.COB.ToHexString(); if (slot.nodeidpresent) sub.defaultvalue += " + $NODEID"; - sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -374,12 +371,10 @@ public void buildmappingsfromlists() config.prop.CO_countLabel = "RPDO"; sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); - sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = slot.COB.ToHexString(); if (slot.nodeidpresent) sub.defaultvalue += " + $NODEID"; - sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); From b69c173e161bc818392019515b8c6a5516ac52f5 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 25 Oct 2022 11:00:06 +0200 Subject: [PATCH 050/226] add uncheck button to uncheck all objects in the object list when inserting a profil --- EDSEditorGUI/InsertObjects.Designer.cs | 189 ++++---- EDSEditorGUI/InsertObjects.cs | 14 +- EDSEditorGUI/InsertObjects.resx | 586 ++++++++++++------------- 3 files changed, 408 insertions(+), 381 deletions(-) diff --git a/EDSEditorGUI/InsertObjects.Designer.cs b/EDSEditorGUI/InsertObjects.Designer.cs index 40ed54bd..82a1a0fa 100644 --- a/EDSEditorGUI/InsertObjects.Designer.cs +++ b/EDSEditorGUI/InsertObjects.Designer.cs @@ -28,92 +28,106 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InsertObjects)); - this.label2 = new System.Windows.Forms.Label(); - this.textBox_offsets = new System.Windows.Forms.TextBox(); - this.button_insert = new System.Windows.Forms.Button(); - this.button_cancel = new System.Windows.Forms.Button(); - this.dataGridView = new System.Windows.Forms.DataGridView(); - ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit(); - this.SuspendLayout(); - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(12, 9); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(290, 13); - this.label2.TabIndex = 4; - this.label2.Text = "Index Offset (single or space separated list for multiple insert)"; - // - // textBox_offsets - // - this.textBox_offsets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_offsets.Location = new System.Drawing.Point(12, 25); - this.textBox_offsets.Name = "textBox_offsets"; - this.textBox_offsets.Size = new System.Drawing.Size(432, 20); - this.textBox_offsets.TabIndex = 2; - this.textBox_offsets.Text = "1"; - this.textBox_offsets.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.TextBox_offsets_KeyPress); - this.textBox_offsets.Leave += new System.EventHandler(this.TextBox_offsets_Leave); - // - // button_insert - // - this.button_insert.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.button_insert.Location = new System.Drawing.Point(154, 345); - this.button_insert.Name = "button_insert"; - this.button_insert.Size = new System.Drawing.Size(130, 37); - this.button_insert.TabIndex = 6; - this.button_insert.Text = "Insert"; - this.button_insert.UseVisualStyleBackColor = true; - this.button_insert.Click += new System.EventHandler(this.Button_create_Click); - // - // button_cancel - // - this.button_cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.button_cancel.Location = new System.Drawing.Point(314, 345); - this.button_cancel.Name = "button_cancel"; - this.button_cancel.Size = new System.Drawing.Size(130, 37); - this.button_cancel.TabIndex = 7; - this.button_cancel.Text = "Cancel"; - this.button_cancel.UseVisualStyleBackColor = true; - this.button_cancel.Click += new System.EventHandler(this.Button_cancel_Click); - // - // dataGridView - // - this.dataGridView.AllowUserToAddRows = false; - this.dataGridView.AllowUserToDeleteRows = false; - this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.dataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells; - this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.dataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.dataGridView.Location = new System.Drawing.Point(12, 51); - this.dataGridView.Name = "dataGridView"; - this.dataGridView.Size = new System.Drawing.Size(432, 283); - this.dataGridView.TabIndex = 10; - this.dataGridView.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.DataGridView_ColumnHeaderMouseClick); - this.dataGridView.Leave += new System.EventHandler(this.DataGridView_Leave); - // - // InsertObjects - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(456, 394); - this.Controls.Add(this.dataGridView); - this.Controls.Add(this.button_cancel); - this.Controls.Add(this.button_insert); - this.Controls.Add(this.textBox_offsets); - this.Controls.Add(this.label2); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Name = "InsertObjects"; - this.Text = "Insert OD Objects"; - ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InsertObjects)); + this.label2 = new System.Windows.Forms.Label(); + this.textBox_offsets = new System.Windows.Forms.TextBox(); + this.button_insert = new System.Windows.Forms.Button(); + this.button_cancel = new System.Windows.Forms.Button(); + this.dataGridView = new System.Windows.Forms.DataGridView(); + this.button_uncheck = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit(); + this.SuspendLayout(); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 9); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(290, 13); + this.label2.TabIndex = 4; + this.label2.Text = "Index Offset (single or space separated list for multiple insert)"; + // + // textBox_offsets + // + this.textBox_offsets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox_offsets.Location = new System.Drawing.Point(12, 25); + this.textBox_offsets.Name = "textBox_offsets"; + this.textBox_offsets.Size = new System.Drawing.Size(432, 20); + this.textBox_offsets.TabIndex = 2; + this.textBox_offsets.Text = "1"; + this.textBox_offsets.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.TextBox_offsets_KeyPress); + this.textBox_offsets.Leave += new System.EventHandler(this.TextBox_offsets_Leave); + // + // button_insert + // + this.button_insert.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button_insert.Location = new System.Drawing.Point(154, 345); + this.button_insert.Name = "button_insert"; + this.button_insert.Size = new System.Drawing.Size(130, 37); + this.button_insert.TabIndex = 6; + this.button_insert.Text = "Insert"; + this.button_insert.UseVisualStyleBackColor = true; + this.button_insert.Click += new System.EventHandler(this.Button_create_Click); + // + // button_cancel + // + this.button_cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button_cancel.Location = new System.Drawing.Point(314, 345); + this.button_cancel.Name = "button_cancel"; + this.button_cancel.Size = new System.Drawing.Size(130, 37); + this.button_cancel.TabIndex = 7; + this.button_cancel.Text = "Cancel"; + this.button_cancel.UseVisualStyleBackColor = true; + this.button_cancel.Click += new System.EventHandler(this.Button_cancel_Click); + // + // dataGridView + // + this.dataGridView.AllowUserToAddRows = false; + this.dataGridView.AllowUserToDeleteRows = false; + this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells; + this.dataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells; + this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; + this.dataGridView.Location = new System.Drawing.Point(12, 51); + this.dataGridView.Name = "dataGridView"; + this.dataGridView.Size = new System.Drawing.Size(432, 283); + this.dataGridView.TabIndex = 10; + this.dataGridView.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.DataGridView_ColumnHeaderMouseClick); + this.dataGridView.Leave += new System.EventHandler(this.DataGridView_Leave); + // + // button_uncheck + // + this.button_uncheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.button_uncheck.Location = new System.Drawing.Point(12, 345); + this.button_uncheck.Name = "button_uncheck"; + this.button_uncheck.Size = new System.Drawing.Size(130, 37); + this.button_uncheck.TabIndex = 11; + this.button_uncheck.Text = "Uncheck all"; + this.button_uncheck.UseVisualStyleBackColor = true; + this.button_uncheck.Click += new System.EventHandler(this.button_uncheck_Click); + // + // InsertObjects + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(456, 394); + this.Controls.Add(this.button_uncheck); + this.Controls.Add(this.dataGridView); + this.Controls.Add(this.button_cancel); + this.Controls.Add(this.button_insert); + this.Controls.Add(this.textBox_offsets); + this.Controls.Add(this.label2); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "InsertObjects"; + this.Text = "Insert OD Objects"; + ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + } #endregion @@ -121,6 +135,7 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_offsets; private System.Windows.Forms.Button button_insert; private System.Windows.Forms.Button button_cancel; - private System.Windows.Forms.DataGridView dataGridView; + private System.Windows.Forms.DataGridView dataGridView; + private System.Windows.Forms.Button button_uncheck; } } \ No newline at end of file diff --git a/EDSEditorGUI/InsertObjects.cs b/EDSEditorGUI/InsertObjects.cs index 6cabf04a..8e48b05e 100644 --- a/EDSEditorGUI/InsertObjects.cs +++ b/EDSEditorGUI/InsertObjects.cs @@ -220,6 +220,18 @@ private void DataGridView_Leave(object sender, EventArgs e) { enabled[odIdx++] = (bool)row.Cells[0].Value; } - } + } + + private void button_uncheck_Click(object sender, EventArgs e) + { + int odIdx = 0; + foreach (DataGridViewRow item in dataGridView.Rows) + { + DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)item.Cells[0]; + + cell.Value = false; + enabled[odIdx++] = false; + } + } } } diff --git a/EDSEditorGUI/InsertObjects.resx b/EDSEditorGUI/InsertObjects.resx index 550652ff..0562ff3f 100644 --- a/EDSEditorGUI/InsertObjects.resx +++ b/EDSEditorGUI/InsertObjects.resx @@ -1,294 +1,294 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - AAABAAYAEBAQAAEABAAoAQAAZgAAABAQAAABAAgAaAUAAI4BAAAQEAAAAQAgAGgEAAD2BgAAICAQAAEA - BADoAgAAXgsAACAgAAABAAgAqAgAAEYOAAAgIAAAAQAgAKgQAADuFgAAKAAAABAAAAAgAAAAAQAEAAAA - AACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA - /wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAA//////////D3d/93f/d38Pf3/39/9/fw93 - f/d3/3d/D/f//3//9/8A9///f//38AD3d3d3d3fwAP///3////AAAAAPfwAAAAAAD/9//wAAAAAPd3d/ - AAAAAA9//38AAAAAD3//fwAAAAAPd3d/AAAAAA////8AAP//AACAAAAAgAAAAIAAAACAAAAAgAAAAMAB - AADAAQAAwAEAAP4/AAD4DwAA+A8AAPgPAAD4DwAA+A8AAPgPAAAoAAAAEAAAACAAAAABAAgAAAAAAAAB - AAAAAAAAAAAAAAABAAAAAQAAAAAAAEJCQgDx7/AA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAAMBAQED - AwEBAQMDAQEBAwADAQIBAwMBAgEDAwECAQMAAwEBAQMDAQEBAwMBAQEDAAMDAQMDAwMBAwMDAwEDAwAA - AwEDAwMDAQMDAwMBAwAAAAMBAQEBAQEBAQEBAQMAAAADAwMDAwMBAwMDAwMDAAAAAAAAAAADAQMAAAAA - AAAAAAAAAAMDAwEDAwMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwECAgIBAwAAAAAAAAAAAAMBAgIC - AQMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwMDAwMDAwAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAA - AADAAQAAwAEAAMABAAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAABAAAAAgAAAAAQAgAAAA - AABABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAPb29v9CQkL/QkJC/0JCQv/29vb/9vb2/0JC - Qv9CQkL/QkJC//b29v/29vb/QkJC/0JCQv9CQkL/9vb2/wAAAAD29vb/QkJC//Hv8P9CQkL/9vb2//b2 - 9v9CQkL/8e/w/0JCQv/29vb/9vb2/0JCQv/x7/D/QkJC//b29v8AAAAA9vb2/0JCQv9CQkL/QkJC//b2 - 9v/29vb/QkJC/0JCQv9CQkL/9vb2//b29v9CQkL/QkJC/0JCQv/29vb/AAAAAPb29v/29vb/QkJC//b2 - 9v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2/0JC - Qv/29vb/9vb2//b29v/29vb/QkJC//b29v/29vb/9vb2//b29v9CQkL/9vb2/wAAAAAAAAAAAAAAAPb2 - 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v8AAAAAAAAAAAAA - AAD29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2/0JCQv/29vb/9vb2//b29v8AAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2/0JCQv/x7/D/8e/w//Hv8P9CQkL/9vb2/wAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v9CQkL/8e/w//Hv8P/x7/D/QkJC//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JC - Qv/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAAAADAAQAAwAEAAMAB - AAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAACAAAABAAAAAAQAEAAAAAAAAAgAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8A - AAD/AP8A//8AAP///wAAAAAAAAAAAAAAAAAAAAAAD///////////////////8A////////////////// - //AP93d3f//3d3d///d3d3/wD/d3d3//93d3f//3d3d/8A/3f/d///d/93//93/3f/AP93/3f//3f/d/ - //d/93/wD/d3d3//93d3f//3d3d/8A/3d3d///d3d3//93d3f/AP//d/////93/////3f//wD//3f/// - //d/////93//8AAP93/////3f/////d/8AAAD/d/////93/////3f/AAAA/3d3d3d3d3d3d3d3/wAAAP - 93d3d3d3d3d3d3d/8AAAD///////93////////AAAA////////d////////wAAAAAAAAAA/3f/AAAAAA - AAAAAAAAAAAP93/wAAAAAAAAAAAAAA////d////wAAAAAAAAAAAP///3f///8AAAAAAAAAAAD/d3d3d3 - f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d////3f/AAAAAAAAAAAA/3 - f///93/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d3d3d3f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAA - AAAP////////8AAAAAAAAAAAD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA - AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 - H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//////KAAAACAA - AABAAAAAAQAIAAAAAAAABAAAAAAAAAAAAAAAAQAAAAEAAAAAAABCQkIA8e/wAPb29gAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAMDAwMDAwMDAwMDAwMDAwMD - AwMDAwMDAwMDAwMDAwAAAwMBAQEBAQEDAwMDAQEBAQEBAwMDAwEBAQEBAQMDAAADAwEBAQEBAQMDAwMB - AQEBAQEDAwMDAQEBAQEBAwMAAAMDAQECAgEBAwMDAwEBAgIBAQMDAwMBAQICAQEDAwAAAwMBAQICAQED - AwMDAQECAgEBAwMDAwEBAgIBAQMDAAADAwEBAQEBAQMDAwMBAQEBAQEDAwMDAQEBAQEBAwMAAAMDAQEB - AQEBAwMDAwEBAQEBAQMDAwMBAQEBAQEDAwAAAwMDAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwMDAAAD - AwMDAQEDAwMDAwMDAwEBAwMDAwMDAwMBAQMDAwMAAAAAAwMBAQMDAwMDAwMDAQEDAwMDAwMDAwEBAwMA - AAAAAAADAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwAAAAAAAAMDAQEBAQEBAQEBAQEBAQEBAQEBAQEB - AQMDAAAAAAAAAwMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAwMAAAAAAAADAwMDAwMDAwMDAwMBAQMDAwMD - AwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwEBAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAMDAQED - AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMD - AwEBAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAQEDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAD - AwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAAAAAAAAAAAAAAAAAA - AAAAAwMBAQICAgICAgEBAwMAAAAAAAAAAAAAAAAAAAAAAAADAwEBAgICAgICAQEDAwAAAAAAAAAAAAAA - AAAAAAAAAAMDAQECAgICAgIBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQICAgICAgEBAwMAAAAAAAAA - AAAAAAAAAAAAAAADAwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAA - AAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMD - AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4AAAAGAAAABgAAAAYAA - AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAHgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAf/+B////gf//+A - Af//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//////8oAAAAIAAAAEAA - AAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAD29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAPb2 - 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA - AAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b2 - 9v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b2 - 9v9CQkL/QkJC//Hv8P/x7/D/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JC - Qv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JCQv9CQkL/9vb2//b2 - 9v/29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC//Hv - 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv/29vb/9vb2//b29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b2 - 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/9vb2//b2 - 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/wAAAAAAAAAA9vb2//b2 - 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JC - Qv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/9vb2//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JC - Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b29v/29vb/9vb2//b2 - 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2//b2 - 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b2 - 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b2 - 9v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//Hv8P/x7/D/8e/w//Hv8P/x7/D/8e/w/0JC - Qv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P/x7/D/8e/w//Hv - 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv - 8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA - AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 - H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf////// - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAYAEBAQAAEABAAoAQAAZgAAABAQAAABAAgAaAUAAI4BAAAQEAAAAQAgAGgEAAD2BgAAICAQAAEA + BADoAgAAXgsAACAgAAABAAgAqAgAAEYOAAAgIAAAAQAgAKgQAADuFgAAKAAAABAAAAAgAAAAAQAEAAAA + AACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA + /wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAA//////////D3d/93f/d38Pf3/39/9/fw93 + f/d3/3d/D/f//3//9/8A9///f//38AD3d3d3d3fwAP///3////AAAAAPfwAAAAAAD/9//wAAAAAPd3d/ + AAAAAA9//38AAAAAD3//fwAAAAAPd3d/AAAAAA////8AAP//AACAAAAAgAAAAIAAAACAAAAAgAAAAMAB + AADAAQAAwAEAAP4/AAD4DwAA+A8AAPgPAAD4DwAA+A8AAPgPAAAoAAAAEAAAACAAAAABAAgAAAAAAAAB + AAAAAAAAAAAAAAABAAAAAQAAAAAAAEJCQgDx7/AA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAAMBAQED + AwEBAQMDAQEBAwADAQIBAwMBAgEDAwECAQMAAwEBAQMDAQEBAwMBAQEDAAMDAQMDAwMBAwMDAwEDAwAA + AwEDAwMDAQMDAwMBAwAAAAMBAQEBAQEBAQEBAQMAAAADAwMDAwMBAwMDAwMDAAAAAAAAAAADAQMAAAAA + AAAAAAAAAAMDAwEDAwMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwECAgIBAwAAAAAAAAAAAAMBAgIC + AQMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwMDAwMDAwAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAA + AADAAQAAwAEAAMABAAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAABAAAAAgAAAAAQAgAAAA + AABABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAPb29v9CQkL/QkJC/0JCQv/29vb/9vb2/0JC + Qv9CQkL/QkJC//b29v/29vb/QkJC/0JCQv9CQkL/9vb2/wAAAAD29vb/QkJC//Hv8P9CQkL/9vb2//b2 + 9v9CQkL/8e/w/0JCQv/29vb/9vb2/0JCQv/x7/D/QkJC//b29v8AAAAA9vb2/0JCQv9CQkL/QkJC//b2 + 9v/29vb/QkJC/0JCQv9CQkL/9vb2//b29v9CQkL/QkJC/0JCQv/29vb/AAAAAPb29v/29vb/QkJC//b2 + 9v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2/0JC + Qv/29vb/9vb2//b29v/29vb/QkJC//b29v/29vb/9vb2//b29v9CQkL/9vb2/wAAAAAAAAAAAAAAAPb2 + 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v8AAAAAAAAAAAAA + AAD29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2/0JCQv/29vb/9vb2//b29v8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2/0JCQv/x7/D/8e/w//Hv8P9CQkL/9vb2/wAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v9CQkL/8e/w//Hv8P/x7/D/QkJC//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JC + Qv/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAAAADAAQAAwAEAAMAB + AAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAACAAAABAAAAAAQAEAAAAAAAAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8A + AAD/AP8A//8AAP///wAAAAAAAAAAAAAAAAAAAAAAD///////////////////8A////////////////// + //AP93d3f//3d3d///d3d3/wD/d3d3//93d3f//3d3d/8A/3f/d///d/93//93/3f/AP93/3f//3f/d/ + //d/93/wD/d3d3//93d3f//3d3d/8A/3d3d///d3d3//93d3f/AP//d/////93/////3f//wD//3f/// + //d/////93//8AAP93/////3f/////d/8AAAD/d/////93/////3f/AAAA/3d3d3d3d3d3d3d3/wAAAP + 93d3d3d3d3d3d3d/8AAAD///////93////////AAAA////////d////////wAAAAAAAAAA/3f/AAAAAA + AAAAAAAAAAAP93/wAAAAAAAAAAAAAA////d////wAAAAAAAAAAAP///3f///8AAAAAAAAAAAD/d3d3d3 + f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d////3f/AAAAAAAAAAAA/3 + f///93/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d3d3d3f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAA + AAAP////////8AAAAAAAAAAAD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 + H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//////KAAAACAA + AABAAAAAAQAIAAAAAAAABAAAAAAAAAAAAAAAAQAAAAEAAAAAAABCQkIA8e/wAPb29gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAMDAwMDAwMDAwMDAwMDAwMD + AwMDAwMDAwMDAwMDAwAAAwMBAQEBAQEDAwMDAQEBAQEBAwMDAwEBAQEBAQMDAAADAwEBAQEBAQMDAwMB + AQEBAQEDAwMDAQEBAQEBAwMAAAMDAQECAgEBAwMDAwEBAgIBAQMDAwMBAQICAQEDAwAAAwMBAQICAQED + AwMDAQECAgEBAwMDAwEBAgIBAQMDAAADAwEBAQEBAQMDAwMBAQEBAQEDAwMDAQEBAQEBAwMAAAMDAQEB + AQEBAwMDAwEBAQEBAQMDAwMBAQEBAQEDAwAAAwMDAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwMDAAAD + AwMDAQEDAwMDAwMDAwEBAwMDAwMDAwMBAQMDAwMAAAAAAwMBAQMDAwMDAwMDAQEDAwMDAwMDAwEBAwMA + AAAAAAADAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwAAAAAAAAMDAQEBAQEBAQEBAQEBAQEBAQEBAQEB + AQMDAAAAAAAAAwMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAwMAAAAAAAADAwMDAwMDAwMDAwMBAQMDAwMD + AwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwEBAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAMDAQED + AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMD + AwEBAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAQEDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAD + AwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAAAAAAAAAAAAAAAAAA + AAAAAwMBAQICAgICAgEBAwMAAAAAAAAAAAAAAAAAAAAAAAADAwEBAgICAgICAQEDAwAAAAAAAAAAAAAA + AAAAAAAAAAMDAQECAgICAgIBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQICAgICAgEBAwMAAAAAAAAA + AAAAAAAAAAAAAAADAwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAA + AAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMD + AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4AAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAHgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAf/+B////gf//+A + Af//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//////8oAAAAIAAAAEAA + AAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAD29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAPb2 + 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA + AAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b2 + 9v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b2 + 9v9CQkL/QkJC//Hv8P/x7/D/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JC + Qv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JCQv9CQkL/9vb2//b2 + 9v/29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC//Hv + 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv/29vb/9vb2//b29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b2 + 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/9vb2//b2 + 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/wAAAAAAAAAA9vb2//b2 + 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JC + Qv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/9vb2//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JC + Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b29v/29vb/9vb2//b2 + 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2//b2 + 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b2 + 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b2 + 9v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//Hv8P/x7/D/8e/w//Hv8P/x7/D/8e/w/0JC + Qv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P/x7/D/8e/w//Hv + 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv + 8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 + H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf////// + + \ No newline at end of file From af4d323768b8e065ba6cd7b022a7561671cf507d Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 25 Oct 2022 11:07:34 +0200 Subject: [PATCH 051/226] insert profile DS401 (generic I/O) consistent names for object types (VAR, ARRAY, RECORD,...) CANOPENNODE_LEGACY exporter takes the "CO_disabled" bit into account --- EDSEditorGUI/DeviceODView.cs | 46 +- EDSEditorGUI/EDSEditorGUI.csproj | 1 + EDSEditorGUI/NewIndex.Designer.cs | 4 +- EDSEditorGUI/NewIndex.cs | 2 +- EDSEditorGUI/Profiles/DS401_profile.xpd | 170301 +++++++++++++++++++++ Tests/ExporterTests.cs | 2 +- Tests/Tests.csproj | 46 +- Tests/XDDImportExportTest.cs | 2 +- libEDSsharp/Bridge.cs | 4 +- libEDSsharp/CanOpenNodeExporter.cs | 70 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 8 +- libEDSsharp/CanOpenXDD.cs | 2 +- libEDSsharp/CanOpenXDD_1_1.cs | 4 +- libEDSsharp/DocumentationGen.cs | 2 +- libEDSsharp/PDOHelper.cs | 4 +- libEDSsharp/eds.cs | 45 +- 16 files changed, 170425 insertions(+), 118 deletions(-) create mode 100644 EDSEditorGUI/Profiles/DS401_profile.xpd diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index 565402b0..b6c4ee93 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -48,25 +48,25 @@ public DeviceODView() if (CANopenNodeV4) { - comboBox_dataType.Items.Add("BOOLEAN"); - comboBox_dataType.Items.Add("INTEGER8"); - comboBox_dataType.Items.Add("INTEGER16"); - comboBox_dataType.Items.Add("INTEGER32"); - comboBox_dataType.Items.Add("INTEGER64"); - comboBox_dataType.Items.Add("UNSIGNED8"); - comboBox_dataType.Items.Add("UNSIGNED16"); - comboBox_dataType.Items.Add("UNSIGNED32"); - comboBox_dataType.Items.Add("UNSIGNED64"); - comboBox_dataType.Items.Add("REAL32"); - comboBox_dataType.Items.Add("REAL64"); - comboBox_dataType.Items.Add("VISIBLE_STRING"); - comboBox_dataType.Items.Add("OCTET_STRING"); - comboBox_dataType.Items.Add("UNICODE_STRING"); - comboBox_dataType.Items.Add("DOMAIN"); - - comboBox_objectType.Items.Add("VAR"); - comboBox_objectType.Items.Add("ARRAY"); - comboBox_objectType.Items.Add("RECORD"); + comboBox_dataType.Items.Add(DataType.BOOLEAN.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER8.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER16.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER32.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER64.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED8.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED16.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED32.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED64.ToString()); + comboBox_dataType.Items.Add(DataType.REAL32.ToString()); + comboBox_dataType.Items.Add(DataType.REAL64.ToString()); + comboBox_dataType.Items.Add(DataType.VISIBLE_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.OCTET_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.UNICODE_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.DOMAIN.ToString()); + + comboBox_objectType.Items.Add(ObjectType.VAR.ToString()); + comboBox_objectType.Items.Add(ObjectType.ARRAY.ToString()); + comboBox_objectType.Items.Add(ObjectType.RECORD.ToString()); foreach (AccessSDO foo in Enum.GetValues(typeof(AccessSDO))) comboBox_accessSDO.Items.Add(foo.ToString()); @@ -235,7 +235,7 @@ public void PopulateSubList() lvi.Tag = od; listView_subObjects.Items.Add(lvi); } - else if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.REC) + else if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) { ListViewItem lvi = new ListViewItem(new string[]{ " ", @@ -398,7 +398,7 @@ private void Button_saveChanges_Click(object sender, EventArgs e) od.parameter_name = textBox_name.Text; od.denotation = textBox_denotation.Text; od.Description = textBox_description.Text.Replace("\r\n", "\n"); - od.ObjectTypeString(od.parent == null ? comboBox_objectType.SelectedItem.ToString() : "VAR"); + od.ObjectTypeString(od.parent == null ? comboBox_objectType.SelectedItem.ToString() : "VAR"); if (od.objecttype == ObjectType.VAR) { @@ -570,10 +570,10 @@ private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) { ODentry parent = od.parent == null ? od : od.parent; - if (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.REC) + if (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.RECORD) { contextMenu_subObject_removeSubItemToolStripMenuItem.Enabled = od.Subindex > 0 && od.parent != null; - contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Enabled = parent.objecttype == ObjectType.REC && od.Subindex > 0 && od.parent != null; + contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Enabled = parent.objecttype == ObjectType.RECORD && od.Subindex > 0 && od.parent != null; if (listView_subObjects.FocusedItem.Bounds.Contains(e.Location) == true) { diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 9c39d01f..d7dff2c9 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -212,6 +212,7 @@ PreserveNewest + SettingsSingleFileGenerator Settings.Designer.cs diff --git a/EDSEditorGUI/NewIndex.Designer.cs b/EDSEditorGUI/NewIndex.Designer.cs index bb2a222e..3ca563bb 100644 --- a/EDSEditorGUI/NewIndex.Designer.cs +++ b/EDSEditorGUI/NewIndex.Designer.cs @@ -1,4 +1,6 @@ -namespace ODEditor +using libEDSsharp; + +namespace ODEditor { partial class NewIndex { diff --git a/EDSEditorGUI/NewIndex.cs b/EDSEditorGUI/NewIndex.cs index 892721d1..1c3594f1 100644 --- a/EDSEditorGUI/NewIndex.cs +++ b/EDSEditorGUI/NewIndex.cs @@ -66,7 +66,7 @@ private void Button_create_Click(object sender, EventArgs e) else if (radioButton_array.Checked) objectType = ObjectType.ARRAY; else if (radioButton_record.Checked) - objectType = ObjectType.REC; + objectType = ObjectType.RECORD; else { MessageBox.Show("Please specify the Object Type"); diff --git a/EDSEditorGUI/Profiles/DS401_profile.xpd b/EDSEditorGUI/Profiles/DS401_profile.xpd new file mode 100644 index 00000000..424c3067 --- /dev/null +++ b/EDSEditorGUI/Profiles/DS401_profile.xpd @@ -0,0 +1,170301 @@ + + + + + + + CANopen device profile + 1.1 + + + Device + + 1 + 1 + CANopen + + + + + + + + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CANopen communication network profile + 1.1 + + + CommunicationNetwork + + 1 + 1 + CANopen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/Tests/ExporterTests.cs b/Tests/ExporterTests.cs index f6331c7b..16f53eeb 100644 --- a/Tests/ExporterTests.cs +++ b/Tests/ExporterTests.cs @@ -28,7 +28,7 @@ public void Test_record_objects() ODentry od = new ODentry { - objecttype = ObjectType.REC, + objecttype = ObjectType.RECORD, parameter_name = "Test Record", accesstype = EDSsharp.AccessType.ro, Index = 0x2000 diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 907b64e4..bef33aff 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,26 +1,26 @@ - - - - - - - Debug - AnyCPU - {2A479BF3-7628-409B-8A29-9314C308445E} - Library - Properties - Tests - Tests - v4.5.2 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - + + + + + + + Debug + AnyCPU + {2A479BF3-7628-409B-8A29-9314C308445E} + Library + Properties + Tests + Tests + v4.8 + 512 + {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} + 10.0 + $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) + $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages + False + UnitTest + + diff --git a/Tests/XDDImportExportTest.cs b/Tests/XDDImportExportTest.cs index 1c51ee52..b6b211cf 100644 --- a/Tests/XDDImportExportTest.cs +++ b/Tests/XDDImportExportTest.cs @@ -57,7 +57,7 @@ public void TestImportExportRecord() ODentry od = new ODentry { - objecttype = ObjectType.REC, + objecttype = ObjectType.RECORD, parameter_name = "Test REC", Index = 0x2000 }; diff --git a/libEDSsharp/Bridge.cs b/libEDSsharp/Bridge.cs index 551e96da..56b52ed1 100644 --- a/libEDSsharp/Bridge.cs +++ b/libEDSsharp/Bridge.cs @@ -64,7 +64,7 @@ public Device convert(EDSsharp eds) } } - if (od.objecttype == ObjectType.REC && od.accesstype == EDSsharp.AccessType.UNKNOWN) + if (od.objecttype == ObjectType.RECORD && od.accesstype == EDSsharp.AccessType.UNKNOWN) { ODentry sub = od.Getsubobject(1); if (sub != null) @@ -91,7 +91,7 @@ public Device convert(EDSsharp eds) coo.Description = new Xml2CSharp.Description(); coo.Description.Text = od.Description; - //if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.REC) + //if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) { coo.SubNumber = od.Nosubindexes.ToString(); //-1?? //check me coo.CANopenSubObject = new List(); diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 7f8faa3e..27a7e9bc 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -53,6 +53,7 @@ public class CanOpenNodeExporter : IExporter ODentry maxRXmappingsOD=null; ODentry maxTXmappingsOD=null; + public void prepareCanOpenNames() { acceptable_canopen_names.Add(0x101800, "identity"); @@ -116,7 +117,7 @@ private void fixcompatentry() for (UInt16 idx = 0x1800; idx < 0x1900; idx++) { - if (eds.ods.ContainsKey(idx)) + if (ObjectActive(idx)) { ODentry od = eds.ods[idx]; @@ -160,6 +161,15 @@ private void specialarraysearch(UInt16 start, UInt16 end) } } + public bool ObjectActive(UInt16 index) + { + if (eds.ods.ContainsKey(index)) + { + return !eds.ods[index].prop.CO_disabled; + } + else return false; + } + protected void prewalkArrays() { @@ -238,7 +248,7 @@ protected void prewalkArrays() for (ushort x=0x1600;x<0x1800;x++) { - if(eds.ods.ContainsKey(x)) + if(ObjectActive(x)) { byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); @@ -252,7 +262,7 @@ protected void prewalkArrays() for (ushort x = 0x1a00; x < 0x1c00; x++) { - if (eds.ods.ContainsKey(x)) + if (ObjectActive(x)) { byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); @@ -325,7 +335,7 @@ protected string print_h_entry(ODentry od) switch (od.objecttype) { - case ObjectType.REC: + case ObjectType.RECORD: objecttypewords = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); break; case ObjectType.ARRAY: @@ -350,7 +360,7 @@ protected string print_h_entry(ODentry od) //Don't put sub indexes on record type in h file unless there are multiples of the same //in which case its not handled here, we need a special case for the predefined special //values that arrayspecial() checks for, to generate 1 element arrays if needed - if (od.objecttype == ObjectType.REC) + if (od.objecttype == ObjectType.RECORD) { if (arrayspecial(od.Index, true)) { @@ -500,7 +510,7 @@ CANopen DATA TYPES file.WriteLine(string.Format(" #define CO_NO_TPDO {0} //Associated objects: 18xx, 1Axx", noTXpdos)); bool ismaster = false; - if(eds.ods.ContainsKey(0x1f80)) + if(ObjectActive(0x1f80)) { ODentry master = eds.ods[0x1f80]; @@ -545,7 +555,7 @@ TYPE DEFINITIONS FOR RECORDS /* make sure, we have all storage groups */ eds.CO_storageGroups.Add(od.prop.CO_storageGroup); - if (od.objecttype != ObjectType.REC) + if (od.objecttype != ObjectType.RECORD) continue; string structname = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); @@ -638,7 +648,7 @@ dictionary entries> break; case ObjectType.ARRAY: - case ObjectType.REC: + case ObjectType.RECORD: { file.WriteLine(string.Format("/*{0:X4} */", od.Index)); file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); @@ -808,7 +818,7 @@ ALIASES FOR OBJECT DICTIONARY VARIABLES } break; - case ObjectType.REC: + case ObjectType.RECORD: { string rectype = make_cname(od.parameter_name,od); @@ -941,7 +951,7 @@ protected string write_od_line(ODentry od) byte flags = getflags(od); - int datasize = od.objecttype == ObjectType.REC ? 0 : (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); + int datasize = od.objecttype == ObjectType.RECORD ? 0 : (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); string array = ""; @@ -964,7 +974,7 @@ protected string write_od_line(ODentry od) //Arrays and Recs have 1 less subindex than actually present in the od.subobjects int nosubindexs = od.Nosubindexes; - if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.REC) + if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) { if (nosubindexs > 0) nosubindexs--; @@ -993,7 +1003,7 @@ protected string write_od_line(ODentry od) string pdata; //CO_OD_entry_t pData generator - if (od.objecttype == ObjectType.REC) + if (od.objecttype == ObjectType.RECORD) { pdata = string.Format("&OD_record{0:X4}", od.Index); @@ -1031,7 +1041,7 @@ public byte getflags(ODentry od) byte mapping = 0; //mapping flags, if pdo is enabled //aways return 0 for REC objects as CO_OD_getDataPointer() uses this to pickup the details - if (od.objecttype == ObjectType.REC) + if (od.objecttype == ObjectType.RECORD) return 0; switch((od.parent == null ? od : od.parent).prop.CO_storageGroup.ToUpper()) @@ -1403,7 +1413,7 @@ protected string export_record_types() { ODentry od = kvp.Value; - if (od.objecttype != ObjectType.REC) + if (od.objecttype != ObjectType.RECORD) continue; if (od.prop.CO_disabled == true) @@ -1500,13 +1510,13 @@ void countPDOS() //check the SYNC feature int checkfeature = 0; - if (eds.ods.ContainsKey(0x1005)) + if (ObjectActive(0x1005)) checkfeature++; - if (eds.ods.ContainsKey(0x1006)) + if (ObjectActive(0x1006)) checkfeature++; - if (eds.ods.ContainsKey(0x1007)) + if (ObjectActive(0x1007)) checkfeature++; - if (eds.ods.ContainsKey(0x1019)) + if (ObjectActive(0x1019)) checkfeature++; if (checkfeature == 4) { @@ -1519,11 +1529,11 @@ void countPDOS() //EMCY checkfeature = 0; - if (eds.ods.ContainsKey(0x1003)) + if (ObjectActive(0x1003)) checkfeature++; - if (eds.ods.ContainsKey(0x1014)) + if (ObjectActive(0x1014)) checkfeature++; - if (eds.ods.ContainsKey(0x1015)) + if (ObjectActive(0x1015)) checkfeature++; if (checkfeature == 3) { @@ -1535,7 +1545,7 @@ void countPDOS() } //TIME - if (eds.ods.ContainsKey(0x1012)) + if (ObjectActive(0x1012)) { noTIME = 1; } @@ -1546,14 +1556,14 @@ void countPDOS() //NMT CLIENT checkfeature = 0; - if (eds.ods.ContainsKey(0x1f80)) - checkfeature++; - if (eds.ods.ContainsKey(0x1029)) - checkfeature++; - if (eds.ods.ContainsKey(0x1017)) - checkfeature++; - if (eds.ods.ContainsKey(0x1001)) - checkfeature++; + if (ObjectActive(0x1f80)) + checkfeature ++; + if (ObjectActive(0x1029)) + checkfeature ++; + if (ObjectActive(0x1017)) + checkfeature ++; + if (ObjectActive(0x1001)) + checkfeature ++; if (checkfeature == 4) { //NMT Client is not optional diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index e5a18ebf..132aec00 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -145,17 +145,17 @@ private void Prepare(EDSsharp eds) switch (od.objecttype) { case ObjectType.VAR: - odObjectType = "VAR"; + odObjectType = ObjectType.VAR.ToString(); subEntriesCount = Prepare_var(od, indexH, varName, od.prop.CO_storageGroup); break; case ObjectType.ARRAY: - odObjectType = "ARR"; + odObjectType = ObjectType.ARRAY.ToString(); subEntriesCount = Prepare_arr(od, indexH, varName, od.prop.CO_storageGroup); break; - case ObjectType.REC: - odObjectType = "REC"; + case ObjectType.RECORD: + odObjectType = ObjectType.RECORD.ToString(); subEntriesCount = Prepare_rec(od, indexH, varName, od.prop.CO_storageGroup); break; } diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 6edeadde..ad116a22 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -441,7 +441,7 @@ public ISO15745ProfileContainer convert(EDSsharp eds) } - if (od.objecttype != ObjectType.ARRAY && od.objecttype != ObjectType.REC) + if (od.objecttype != ObjectType.ARRAY && od.objecttype != ObjectType.RECORD) { //#209 don't set data type for array or rec objects, the subobjects hold //the data type diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index cd010a0f..1a6df8e9 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -448,7 +448,7 @@ private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool dev if (deviceCommissioning && od.actualvalue != null && od.actualvalue != "") devPar.actualValue = new actualValue { value = od.actualvalue }; } - else if ((od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.REC) && od.subobjects != null && od.subobjects.Count > 0) + else if ((od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) && od.subobjects != null && od.subobjects.Count > 0) { netObj.subNumber = (byte)od.subobjects.Count; netObj.subNumberSpecified = true; @@ -501,7 +501,7 @@ private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool dev if (deviceCommissioning && subod.actualvalue != null && subod.actualvalue != "") devPar.actualValue = new actualValue { value = subod.actualvalue }; - if (od.objecttype == ObjectType.REC) + if (od.objecttype == ObjectType.RECORD) { devStructSubList.Add(new varDeclaration { diff --git a/libEDSsharp/DocumentationGen.cs b/libEDSsharp/DocumentationGen.cs index e36f4ebb..606cea0d 100644 --- a/libEDSsharp/DocumentationGen.cs +++ b/libEDSsharp/DocumentationGen.cs @@ -258,7 +258,7 @@ private void PrintPdoMd(EDSsharp eds, bool skipDisabled = false) var mappings = new SortedDictionary(); foreach (ODentry od in eds.ods.Values) { - if (od.Index < 0x1400 || od.prop.CO_disabled || od.objecttype != ObjectType.REC || od.subobjects.Count < 3) + if (od.Index < 0x1400 || od.prop.CO_disabled || od.objecttype != ObjectType.RECORD || od.subobjects.Count < 3) continue; else if (od.Index < 0x1600) parameters.Add(od.Index, od); diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index db6e828b..183d95fc 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -308,7 +308,7 @@ public void buildmappingsfromlists() ODentry config = new ODentry(); config.Index = slot.ConfigurationIndex; config.datatype = DataType.PDO_COMMUNICATION_PARAMETER; - config.objecttype = ObjectType.REC; + config.objecttype = ObjectType.RECORD; ODentry sub = new ODentry("max sub-index", (ushort)slot.ConfigurationIndex, 0); sub.defaultvalue = "6"; @@ -391,7 +391,7 @@ public void buildmappingsfromlists() ODentry mapping = new ODentry(); mapping.Index = slot.MappingIndex; mapping.datatype = DataType.PDO_MAPPING; - mapping.objecttype = ObjectType.REC; + mapping.objecttype = ObjectType.RECORD; if(slot.isTXPDO()) mapping.parameter_name = "TPDO mapping parameter"; diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 1dd34ee0..4a202019 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -25,7 +25,8 @@ You should have received a copy of the GNU General Public License using System.Globalization; using System.Reflection; using CanOpenXSD_1_1; - +using System.Runtime.Remoting.Messaging; + namespace libEDSsharp { @@ -75,7 +76,7 @@ public enum ObjectType DEFSTRUCT=6, VAR = 7, ARRAY = 8, - REC = 9, + RECORD = 9, } public enum PDOMappingType @@ -1251,27 +1252,18 @@ public override string ToString() } } + /// + /// Provide a simple string representation of the object type. Returns the string of the ENUM ObjectType.VAR if objecttype is not enumed + /// + /// string representation of object type public string ObjectTypeString() { - switch (objecttype) - { - default: - case ObjectType.VAR: return "VAR"; - case ObjectType.ARRAY: return "ARRAY"; - case ObjectType.REC: return "RECORD"; - } - } + return Enum.IsDefined(typeof(ObjectType), objecttype) ? objecttype.ToString() : ObjectType.VAR.ToString(); + } public void ObjectTypeString(string objectType) { - switch (objectType) - { - default: - case "VAR": this.objecttype = ObjectType.VAR; break; - case "ARRAY": this.objecttype = ObjectType.ARRAY; break; - case "REC": - case "RECORD": this.objecttype = ObjectType.REC; break; - } + this.objecttype = Enum.IsDefined(typeof(ObjectType), objecttype) ? objecttype : ObjectType.VAR; } public AccessSDO AccessSDO() @@ -1368,7 +1360,7 @@ public ODentry AddSubEntry() ODentry newOd; - if ((baseObject.Nosubindexes == 0) && ((baseObject.objecttype == ObjectType.ARRAY) || (baseObject.objecttype == ObjectType.REC))) { + if ((baseObject.Nosubindexes == 0) && ((baseObject.objecttype == ObjectType.ARRAY) || (baseObject.objecttype == ObjectType.RECORD))) { baseObject.subobjects.Add(0, new ODentry { parent = baseObject, @@ -1438,7 +1430,7 @@ public ODentry AddSubEntry() /// true on successfull removal public bool RemoveSubEntry(bool renumber) { - if (parent != null && (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.REC)) + if (parent != null && (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.RECORD)) { UInt16 maxSubIndex = EDSsharp.ConvertToUInt16(parent.subobjects[0].defaultvalue); UInt16 lastSubIndex = parent.subobjects.Values.Last().Subindex; @@ -1531,7 +1523,7 @@ public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odty writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); } - if (objecttype == ObjectType.REC) + if (objecttype == ObjectType.RECORD) { writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); } @@ -1712,12 +1704,13 @@ public bool Containssubindex(UInt16 no) return false; } + public byte Getmaxsubindex() { //Although subindex 0 should contain the max subindex value //we don't enforce that anywhere in this lib, we should have a setter function //that sets it to the highest subobject found. - if (objecttype == ObjectType.ARRAY || objecttype == ObjectType.REC) + if (objecttype == ObjectType.ARRAY || objecttype == ObjectType.RECORD) if (Containssubindex(0)) { return EDSsharp.ConvertToByte(Getsubobjectdefaultvalue(0)); @@ -2294,7 +2287,7 @@ public void ParseEDSentry(KeyValuePair> kvp) } - if(od.objecttype == ObjectType.REC|| od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) + if(od.objecttype == ObjectType.RECORD|| od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) { if (od.CompactSubObj != 0) @@ -2984,7 +2977,7 @@ public bool tryGetODEntry(UInt16 index, out ODentry od) } return false; - } + } //RX COM 0x1400 //RX Map 0x1600 @@ -3091,7 +3084,7 @@ mapped object (subindex 1...8) }; } - od_comparam.objecttype = ObjectType.REC; + od_comparam.objecttype = ObjectType.RECORD; od_comparam.prop.CO_storageGroup = "ROM"; od_comparam.accesstype = AccessType.ro; od_comparam.PDOtype = PDOMappingType.no; @@ -3128,7 +3121,7 @@ mapped object (subindex 1...8) } - od_mapping.objecttype = ObjectType.REC; + od_mapping.objecttype = ObjectType.RECORD; od_mapping.prop.CO_storageGroup = "ROM"; od_mapping.accesstype = AccessType.rw; //Same as default but inconsistent with ROM above od_mapping.PDOtype = PDOMappingType.no; From 06a3bc960e081c86bdc2efd0a1cfcbb0fd85a897 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 27 Oct 2022 13:47:28 +0200 Subject: [PATCH 052/226] - Apply exporter setting immediately (without restart) --- EDSEditorGUI/DeviceODView.cs | 195 ++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 82 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index b6c4ee93..dc0453a5 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -24,8 +24,7 @@ You should have received a copy of the GNU General Public License using System.Windows.Forms; using System.Reflection; using System.Text.RegularExpressions; -using libEDSsharp; - +using libEDSsharp; namespace ODEditor { @@ -36,82 +35,97 @@ public partial class DeviceODView : MyTabUserControl ODentry selectedObject; ODentry lastSelectedObject; ListView selectedList; - bool justUpdating = false; - readonly bool CANopenNodeV4; - + bool justUpdating = false; + bool ExporterOld = false; + bool ExporterV4 = false; + public DeviceODView() { - ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; - CANopenNodeV4 = (type == ExporterFactory.Exporter.CANOPENNODE_V4); - - InitializeComponent(); - - if (CANopenNodeV4) - { - comboBox_dataType.Items.Add(DataType.BOOLEAN.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER8.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER16.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER32.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER64.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED8.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED16.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED32.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED64.ToString()); - comboBox_dataType.Items.Add(DataType.REAL32.ToString()); - comboBox_dataType.Items.Add(DataType.REAL64.ToString()); - comboBox_dataType.Items.Add(DataType.VISIBLE_STRING.ToString()); - comboBox_dataType.Items.Add(DataType.OCTET_STRING.ToString()); - comboBox_dataType.Items.Add(DataType.UNICODE_STRING.ToString()); - comboBox_dataType.Items.Add(DataType.DOMAIN.ToString()); - - comboBox_objectType.Items.Add(ObjectType.VAR.ToString()); - comboBox_objectType.Items.Add(ObjectType.ARRAY.ToString()); - comboBox_objectType.Items.Add(ObjectType.RECORD.ToString()); - - foreach (AccessSDO foo in Enum.GetValues(typeof(AccessSDO))) - comboBox_accessSDO.Items.Add(foo.ToString()); - - foreach (AccessPDO foo in Enum.GetValues(typeof(AccessPDO))) - comboBox_accessPDO.Items.Add(foo.ToString()); - - label_pdoFlags.Visible = false; - checkBox_pdoFlags.Visible = false; - } - else - { - foreach (DataType foo in Enum.GetValues(typeof(DataType))) - comboBox_dataType.Items.Add(foo.ToString()); - foreach (ObjectType foo in Enum.GetValues(typeof(ObjectType))) - comboBox_objectType.Items.Add(foo.ToString()); - foreach (EDSsharp.AccessType foo in Enum.GetValues(typeof(EDSsharp.AccessType))) - comboBox_accessSDO.Items.Add(foo.ToString()); - foreach (PDOMappingType foo in Enum.GetValues(typeof(PDOMappingType))) - comboBox_accessPDO.Items.Add(foo.ToString()); - - //comboBox_accessSDO.Items.Add("0x1003 rw/ro"); - //comboBox_accessSDO.Items.Add("0x1010 const/rw"); - //comboBox_accessSDO.Items.Add("0x1010 const/ro"); - - label_pdoFlags.Visible = true; - checkBox_pdoFlags.Visible = true; - } - - foreach (AccessSRDO foo in Enum.GetValues(typeof(AccessSRDO))) - comboBox_accessSRDO.Items.Add(foo.ToString()); - - // other elements may be added in PopulateObjectLists() - comboBox_countLabel.Items.Add(""); - comboBox_countLabel.Items.Add("Add..."); - comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.ComboBox_countLabel_Add); - comboBox_storageGroup.Items.Add("Add..."); - comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.ComboBox_storageGroup_Add); - - listView_communication_objects.DoubleBuffering(true); - listView_deviceProfile_objects.DoubleBuffering(true); - listView_manufacturer_objects.DoubleBuffering(true); - listView_subObjects.DoubleBuffering(true); - } + InitializeComponent(); + RebuildControls(); + + // other elements may be added in PopulateObjectLists() + comboBox_countLabel.Items.Add(""); + comboBox_countLabel.Items.Add("Add..."); + comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.ComboBox_countLabel_Add); + comboBox_storageGroup.Items.Add("Add..."); + comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.ComboBox_storageGroup_Add); + + listView_communication_objects.DoubleBuffering(true); + listView_deviceProfile_objects.DoubleBuffering(true); + listView_manufacturer_objects.DoubleBuffering(true); + listView_subObjects.DoubleBuffering(true); + } + + + public void RebuildControls() + { + if (ExporterTypeV4()) + { + comboBox_dataType.Items.Clear(); + comboBox_dataType.Items.Add(DataType.BOOLEAN.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER8.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER16.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER32.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER64.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED8.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED16.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED32.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED64.ToString()); + comboBox_dataType.Items.Add(DataType.REAL32.ToString()); + comboBox_dataType.Items.Add(DataType.REAL64.ToString()); + comboBox_dataType.Items.Add(DataType.VISIBLE_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.OCTET_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.UNICODE_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.DOMAIN.ToString()); + + comboBox_objectType.Items.Clear(); + comboBox_objectType.Items.Add(ObjectType.VAR.ToString()); + comboBox_objectType.Items.Add(ObjectType.ARRAY.ToString()); + comboBox_objectType.Items.Add(ObjectType.RECORD.ToString()); + + comboBox_accessSDO.Items.Clear(); + foreach (AccessSDO foo in Enum.GetValues(typeof(AccessSDO))) + comboBox_accessSDO.Items.Add(foo.ToString()); + + comboBox_accessPDO.Items.Clear(); + foreach (AccessPDO foo in Enum.GetValues(typeof(AccessPDO))) + comboBox_accessPDO.Items.Add(foo.ToString()); + + label_pdoFlags.Visible = false; + checkBox_pdoFlags.Visible = false; + } + else + { + comboBox_dataType.Items.Clear(); + foreach (DataType foo in Enum.GetValues(typeof(DataType))) + comboBox_dataType.Items.Add(foo.ToString()); + comboBox_objectType.Items.Clear(); + foreach (ObjectType foo in Enum.GetValues(typeof(ObjectType))) + comboBox_objectType.Items.Add(foo.ToString()); + comboBox_accessSDO.Items.Clear(); + foreach (EDSsharp.AccessType foo in Enum.GetValues(typeof(EDSsharp.AccessType))) + comboBox_accessSDO.Items.Add(foo.ToString()); + comboBox_accessPDO.Items.Clear(); + foreach (PDOMappingType foo in Enum.GetValues(typeof(PDOMappingType))) + comboBox_accessPDO.Items.Add(foo.ToString()); + + label_pdoFlags.Visible = true; + checkBox_pdoFlags.Visible = true; + } + + comboBox_accessSRDO.Items.Clear(); + foreach (AccessSRDO foo in Enum.GetValues(typeof(AccessSRDO))) + comboBox_accessSRDO.Items.Add(foo.ToString()); + + + } + private bool ExporterTypeV4() { + ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; + return (type == ExporterFactory.Exporter.CANOPENNODE_V4); + } + private bool Checkdirty() { if (button_saveChanges.BackColor == Color.Red) @@ -216,9 +230,8 @@ public void PopulateSubList() listView_subObjects.Items.Clear(); if (selectedObject == null) - return; - - ODentry od = selectedObject.parent == null ? selectedObject : selectedObject.parent; + return; + ODentry od = selectedObject.parent ?? selectedObject; if (od.objecttype == ObjectType.VAR) { @@ -268,9 +281,18 @@ public void PopulateSubList() public void PopulateObject() { + + ExporterV4 = ExporterTypeV4(); + if (ExporterOld != ExporterV4) + { + RebuildControls(); + ExporterOld = ExporterV4; + } + justUpdating = true; lastSelectedObject = selectedObject; + if (selectedObject == null) { textBox_index.Text = ""; @@ -308,7 +330,8 @@ public void PopulateObject() ? od.parent.datatype.ToString() : od.datatype.ToString(); ComboBoxSet(comboBox_dataType, dataType); - if (CANopenNodeV4) + + if (ExporterV4) { comboBox_accessSDO.SelectedItem = od.AccessSDO().ToString(); comboBox_accessPDO.SelectedItem = od.AccessPDO().ToString(); @@ -387,7 +410,15 @@ private void DataDirty(object sender, EventArgs e) } private void Button_saveChanges_Click(object sender, EventArgs e) - { + { + + ExporterV4 = ExporterTypeV4(); + if (ExporterOld != ExporterV4) + { + RebuildControls(); + ExporterOld = ExporterV4; + } + if (selectedObject == null) return; @@ -411,7 +442,7 @@ private void Button_saveChanges_Click(object sender, EventArgs e) od.datatype = DataType.UNKNOWN; } - if (CANopenNodeV4) + if (ExporterV4) { AccessSDO accessSDO; try @@ -568,7 +599,7 @@ private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Right) { - ODentry parent = od.parent == null ? od : od.parent; + ODentry parent = od.parent ?? od; if (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.RECORD) { From 8620e2b86d2946aa08e30faac126068983defe9a Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 27 Oct 2022 13:49:32 +0200 Subject: [PATCH 053/226] - Trim whitespace on split and ignore whitespace via regex pattern (Getbase fails) --- libEDSsharp/eds.cs | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 4a202019..2cfe6b1b 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -2867,7 +2867,7 @@ static public int Getbase(string defaultvalue) int nobase = 10; - String pat = @"^0[xX][0-9a-fA-F]+"; + String pat = @"^\s*0[xX][0-9a-fA-F]+\s*$"; Regex r = new Regex(pat, RegexOptions.IgnoreCase); Match m = r.Match(defaultvalue); @@ -2929,14 +2929,12 @@ public UInt32 GetNodeID(string input, out bool nodeidpresent) input = input.Replace("$NODEID", ""); input = input.Replace("+", ""); input = input.Replace(" ", ""); - return Convert.ToUInt32(input, Getbase(input)); + return Convert.ToUInt32(input.Trim(), Getbase(input)); } - - input = input.Replace("$NODEID", String.Format("0x{0}", dc.NodeId)); - - string[] bits = input.Split('+'); - - if(bits.Length==1) + + input = input.Replace("$NODEID", dc.NodeId.ToString()); // dc.NodeID is decimal + string[] bits = Array.ConvertAll(input.Split('+'), p => p.Trim()); // Split and Trim the value + if (bits.Length==1) { //nothing to parse here just return the value return Convert.ToUInt32(input, Getbase(input)); From ab0eab86b739b2750f73dbb47ad9dfff957f9fab Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 7 Nov 2022 13:51:48 +0100 Subject: [PATCH 054/226] change the section name in DCF File to meet the standard (DSP302) (wrong spelling of "Commission") accept both spelling of "DeviceCommissioning/DeviceComissioning" when loading a DCF file (for compatibility to some tools that uses the wrong section name, but the right spelling) --- libEDSsharp/eds.cs | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 2cfe6b1b..70dcd987 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -26,6 +26,7 @@ You should have received a copy of the GNU General Public License using System.Reflection; using CanOpenXSD_1_1; using System.Runtime.Remoting.Messaging; +using System.Net.NetworkInformation; namespace libEDSsharp { @@ -812,7 +813,7 @@ public class DeviceCommissioning : InfoSection public DeviceCommissioning() { infoheader = "CAN OPEN DeviceCommissioning"; - edssection = "DeviceCommissioning"; + edssection = "DeviceComissioning"; } public DeviceCommissioning(Dictionary section) : this() @@ -2410,9 +2411,14 @@ public void Loadfile(string filename) //Only DCF not EDS files dc = new DeviceCommissioning(); - if(eds.ContainsKey("DeviceCommissioning")) - { - dc.Parse(eds["DeviceCommissioning"],"DeviceCommissioning"); + string strSection = ""; + if (eds.ContainsKey("DeviceCommissioning")) // wrong section name as defined in the DSP302, but right spelling (for compabiltiy to some tools) + strSection = "DeviceCommissioning"; + else if (eds.ContainsKey("DeviceComissioning")) // right section name as defined in the DSP302, (wrong spelling) + strSection = "DeviceComissioning"; + + if (strSection != ""){ + dc.Parse(eds[strSection],"DeviceCommissioning"); edsfilename = fi.LastEDS; } From 5445e2c27beaaa8b4e6c80bef73bbe15a38c6b85 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 7 Nov 2022 15:09:48 +0100 Subject: [PATCH 055/226] Background color of the update button to red when a DeviceInfo control has been changed to show changes. --- EDSEditorGUI/DeviceInfoView.cs | 39 ++++++++++++++++++++++++++++++++-- 1 file changed, 37 insertions(+), 2 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 866f585a..7db7782d 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -21,7 +21,9 @@ You should have received a copy of the GNU General Public License using System.Windows.Forms; using libEDSsharp; using System.IO; - +using System.Runtime.CompilerServices; +using System.Drawing; + namespace ODEditor { public partial class DeviceInfoView : MyTabUserControl @@ -89,9 +91,39 @@ public void populatedeviceinfo() textBox_netnum.Text = eds.dc.NetNumber.ToString(); checkBox_canopenmanager.Checked = eds.dc.CANopenManager; textBox_lssserial.Text = eds.dc.LSS_SerialNumber.ToString(); - } + } + + AddOnChangeHandlerToInputControls(this.Controls); + + } + + + void InputControls_OnChange(object sender, EventArgs e) + { + // Do something to indicate the form is dirty like: + button_update_devfile_info.BackColor = System.Drawing.Color.Red; } + void AddOnChangeHandlerToInputControls(ControlCollection ctrl) + { + foreach (Control subctrl in ctrl) + { + if (subctrl is TextBox) + ((TextBox)subctrl).TextChanged += + new EventHandler(InputControls_OnChange); + else if (subctrl is CheckBox) + ((CheckBox)subctrl).CheckedChanged += + new EventHandler(InputControls_OnChange); + else + { + if (subctrl.Controls.Count > 0) + this.AddOnChangeHandlerToInputControls(subctrl.Controls); + } + } + } + + + private void button_update_devfile_info_Click(object sender, EventArgs e) { if (eds == null) @@ -139,6 +171,9 @@ private void button_update_devfile_info_Click(object sender, EventArgs e) eds.dc.LSS_SerialNumber = Convert.ToUInt32(textBox_lssserial.Text); eds.Dirty = true; + button_update_devfile_info.BackColor = SystemColors.ButtonFace; + button_update_devfile_info.UseVisualStyleBackColor = true; + } catch (Exception ex) { From 634dee9f6c0cd11f68106936843153c896b73711 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 7 Nov 2022 15:47:45 +0100 Subject: [PATCH 056/226] corrected objectType RECORD --- EDSEditorGUI/Profiles/DS301_profile_old.xml | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/EDSEditorGUI/Profiles/DS301_profile_old.xml b/EDSEditorGUI/Profiles/DS301_profile_old.xml index 5c7785aa..e3d2ff57 100644 --- a/EDSEditorGUI/Profiles/DS301_profile_old.xml +++ b/EDSEditorGUI/Profiles/DS301_profile_old.xml @@ -119,7 +119,7 @@ bit 24-31: set to 0 bit 0-15: Heartbeat producer time in ms (0 = disable transmission) - + max sub-index Vendor-ID @@ -169,7 +169,7 @@ Value definition for all subindexes: - + 0x1200 SDO server parameter max sub-index @@ -198,7 +198,7 @@ bit 0-7: Node ID (optional) - + 0x1280 - 0x12FF SDO client parameter max sub-index @@ -217,7 +217,7 @@ Node-ID of the SDO server - + 0x1400 - 0x15FF RPDO communication parameter max sub-index @@ -236,7 +236,7 @@ value = 255: asynchronous - + 0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) Number of mapped objects @@ -254,7 +254,7 @@ bit 16-31: index from OD - + 0x1800 - 0x19FF TPDO communication parameter max sub-index @@ -288,7 +288,7 @@ value = 1-240: The SYNC message with the counter value equal to this value sha - + 0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). Number of mapped objects From ba4a1b55b0706a4a47aa393cb827ab54695e4680 Mon Sep 17 00:00:00 2001 From: Barzello Date: Wed, 9 Nov 2022 17:00:01 +0300 Subject: [PATCH 057/226] fixed mappable OD entry Signed-off-by: Barzello --- libEDSsharp/eds.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 1dd34ee0..6653df35 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -2027,7 +2027,7 @@ public List VerifyPDOMapping() } if (missing) mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: missing OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); - else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.r) || (PDO == "TPDO" && accessPDO == AccessPDO.t)) + else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.t) || (PDO == "TPDO" && accessPDO == AccessPDO.r)) mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: not mappable OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); } } From 029e57e273771e8e8d667e2cb1ade25f39ed30c4 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 18 Nov 2022 13:51:27 +0100 Subject: [PATCH 058/226] bugfix of creation ODT_RECORD and ODT_ARRAY --- libEDSsharp/CanOpenNodeExporter_V4.cs | 3 +++ libEDSsharp/docs/libEDSsharp.xml | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 132aec00..0c1968a3 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -168,6 +168,9 @@ private void Prepare(EDSsharp eds) ODDefinesLong.Add($"#define {odname}_ENTRY_H{varName} &{odname}->list[{ODList.Count}]"); // object dictionary + if ((odObjectType == "ARRAY") || (odObjectType) == "RECORD") + odObjectType.Substring(0, 3); + ODList.Add($"{{0x{indexH}, 0x{subEntriesCount:X2}, ODT_{odObjectType}, &{odname}Objs.o_{varName}, NULL}}"); // count labels diff --git a/libEDSsharp/docs/libEDSsharp.xml b/libEDSsharp/docs/libEDSsharp.xml index 065ded74..4aaab1ea 100644 --- a/libEDSsharp/docs/libEDSsharp.xml +++ b/libEDSsharp/docs/libEDSsharp.xml @@ -230,6 +230,12 @@ string summary of object + + + Provide a simple string representation of the object type. Returns the string of the ENUM ObjectType.VAR if objecttype is not enumed + + string representation of object type + Duplicate current sub entry and add it to parent From 6f50f73eed3df694ecd8b931570e86312c1190d7 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 29 Nov 2022 12:53:10 +0100 Subject: [PATCH 059/226] bugfix: Assignment to odObjectType was missing --- libEDSsharp/CanOpenNodeExporter_V4.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 0c1968a3..073eb94b 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -169,7 +169,7 @@ private void Prepare(EDSsharp eds) // object dictionary if ((odObjectType == "ARRAY") || (odObjectType) == "RECORD") - odObjectType.Substring(0, 3); + odObjectType = odObjectType.Substring(0, 3); ODList.Add($"{{0x{indexH}, 0x{subEntriesCount:X2}, ODT_{odObjectType}, &{odname}Objs.o_{varName}, NULL}}"); From a43e0a84622fe4e30a5cd86c12d6c7858a8260f2 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Fri, 2 Dec 2022 14:01:36 +0100 Subject: [PATCH 060/226] Revert "correct checking of the accesstype for mapping error (tested with Vector EDScheck)" This reverts commit 26a11e14c58512e9e5f8e2818dfe34900a8a395d. --- libEDSsharp/eds.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 70dcd987..5f7dc8cc 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -2021,7 +2021,7 @@ public List VerifyPDOMapping() } if (missing) mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: missing OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); - else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.r) || (PDO == "TPDO" && accessPDO == AccessPDO.t)) + else if (accessPDO == AccessPDO.no || (PDO == "RPDO" && accessPDO == AccessPDO.t) || (PDO == "TPDO" && accessPDO == AccessPDO.r)) mappingErrors.Add($"{PDO} 0x{indexPdo:X4},0x{subIdxPdo:X2}: not mappable OD entry 0x{mapIdx:X4},0x{mapSub:X2}"); } } From 89595db37bd4320d45cec478927c7eef7a2d4048 Mon Sep 17 00:00:00 2001 From: Colato Date: Tue, 20 Jul 2021 15:57:41 -0400 Subject: [PATCH 061/226] CanOpenNodeExporter_V4 - added missing counters for labels that are required per docs/objectDictionary.md in CANopenNode (cherry picked from commit 5a6f904f996a10a216a2021ea7d72e48480704f6) --- libEDSsharp/CanOpenNodeExporter_V4.cs | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 073eb94b..46d57a30 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -57,6 +57,10 @@ public class CanOpenNodeExporter_V4 : IExporter UInt16 CNT_TPDO = 0; UInt16 CNT_GFC = 0; UInt16 CNT_SRDO = 0; + UInt16 CNT_STORAGE = 0; + UInt16 CNT_EM_PROD = 0; + UInt16 CNT_SYNC_PROD = 0; + UInt16 CNT_HB_PROD = 0; /// /// export the current data set in the CanOpen Node format V4 @@ -126,6 +130,14 @@ private void Prepare(EDSsharp eds) CNT_GFC++; if (od.Index>=0x1301 && od.Index<0x1380) CNT_SRDO++; + if (od.Index==0x1010) + CNT_STORAGE++; + if (od.Index==0x1014) + CNT_EM_PROD++; + if (od.Index==0x1006) + CNT_SYNC_PROD++; + if (od.Index == 0x1006) + CNT_HB_PROD++; string indexH = $"{od.Index:X4}"; string cName = Make_cname(od.parameter_name); string varName = $"{indexH}_{cName}"; @@ -196,6 +208,10 @@ private void Prepare(EDSsharp eds) ODCnt.Add("TPDO", CNT_TPDO); ODCnt.Add("GFC", CNT_GFC); ODCnt.Add("SRDO", CNT_SRDO); + ODCnt.Add("STORAGE", CNT_STORAGE); + ODCnt.Add("EM_PROD", CNT_EM_PROD); + ODCnt.Add("SYNC_PROD", CNT_SYNC_PROD); + ODCnt.Add("HB_PROD", CNT_HB_PROD); } } @@ -559,6 +575,10 @@ OD config structure (config).ENTRY_H1381 = {(eds.ods.ContainsKey(0x1381) ? odname + "_ENTRY_H1381" : "NULL")};\ (config).ENTRY_H13FE = {(eds.ods.ContainsKey(0x13FE) ? odname + "_ENTRY_H13FE" : "NULL")};\ (config).ENTRY_H13FF = {(eds.ods.ContainsKey(0x13FF) ? odname + "_ENTRY_H13FF" : "NULL")};\ + (config).CNT_GFC = {(ODCnt.ContainsKey("STORAGE") ? odname + "_CNT_STORAGE" : "0")};\ + (config).CNT_GFC = {(ODCnt.ContainsKey("EM_PROD") ? odname + "_EM_PROD" : "0")};\ + (config).CNT_GFC = {(ODCnt.ContainsKey("SYNC_PROD") ? odname + "_SYNC_PROD" : "0")};\ + (config).CNT_GFC = {(ODCnt.ContainsKey("HB_PROD") ? odname + "_HB_PROD" : "0")};\ (config).CNT_LSS_SLV = 0;\ (config).CNT_LSS_MST = 0;\ (config).CNT_GTWA = 0;\ From b99540223e6ed86ca2c45a71ded0c39419c376fb Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 15 Dec 2022 15:36:56 +0100 Subject: [PATCH 062/226] - more bugfix for EDS export (Checkes with CANeds) --- libEDSsharp/eds.cs | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 5f7dc8cc..6d1bc839 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1304,9 +1304,9 @@ public void AccessSDO(AccessSDO accessSDO, AccessPDO accessPDO) break; case libEDSsharp.AccessSDO.rw: if (accessPDO == libEDSsharp.AccessPDO.r) - accesstype = EDSsharp.AccessType.rwr; - else if (accessPDO == libEDSsharp.AccessPDO.t) accesstype = EDSsharp.AccessType.rww; + else if (accessPDO == libEDSsharp.AccessPDO.t) + accesstype = EDSsharp.AccessType.rwr; else accesstype = EDSsharp.AccessType.rw; break; @@ -1319,9 +1319,9 @@ public AccessPDO AccessPDO() if (accType == EDSsharp.AccessType.UNKNOWN && parent != null && parent.objecttype == ObjectType.ARRAY) accType = parent.accesstype; - if (PDOtype == PDOMappingType.RPDO || accType == EDSsharp.AccessType.rwr) + if (PDOtype == PDOMappingType.RPDO || accType == EDSsharp.AccessType.rww) return libEDSsharp.AccessPDO.r; - else if (PDOtype == PDOMappingType.TPDO || accType == EDSsharp.AccessType.rww) + else if (PDOtype == PDOMappingType.TPDO || accType == EDSsharp.AccessType.rwr) return libEDSsharp.AccessPDO.t; if (PDOtype == PDOMappingType.optional || PDOtype == PDOMappingType.@default) return libEDSsharp.AccessPDO.tr; @@ -1534,7 +1534,7 @@ public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odty DataType dt = datatype; if (dt == DataType.UNKNOWN && this.parent != null) dt = parent.datatype; - writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); + writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); writer.WriteLine(string.Format("AccessType={0}", accesstype.ToString())); From 75d9957c0dfc9543dcead89c3e014ea5af1e7381 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 15 Dec 2022 15:38:00 +0100 Subject: [PATCH 063/226] Do not inspect textbox (Update button gets "dirty" on "Save project") --- EDSEditorGUI/DeviceInfoView.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 7db7782d..a1609ea2 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -108,10 +108,11 @@ void AddOnChangeHandlerToInputControls(ControlCollection ctrl) { foreach (Control subctrl in ctrl) { - if (subctrl is TextBox) - ((TextBox)subctrl).TextChanged += - new EventHandler(InputControls_OnChange); - else if (subctrl is CheckBox) + //if (subctrl is TextBox) + // ((TextBox)subctrl).TextChanged += + // new EventHandler(InputControls_OnChange); + //else + if (subctrl is CheckBox) ((CheckBox)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange); else From 415b7ed689c3f43ac47e2ba44193863fc48cb061 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 23 Dec 2022 09:16:27 +0100 Subject: [PATCH 064/226] Possible bugsix for #45 1. Default value of sub 0 is 6 for TPDO and 5 for RPDO (instead of 6 for both). This still violates the Value range 02h to 05 for TPDOs if range is correct in DS301. sub.defaultvalue = slot.isTXPDO()? "6" : "5";// max supported sub index TPDO=6, RPDO=5 according DS301 2. Add missing Sub 5 for RPDO sub = new ODentry("event timer", (ushort)slot.ConfigurationIndex, 5); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.eventtimer.ToString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x05, sub); --- libEDSsharp/PDOHelper.cs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 183d95fc..90d72527 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -311,7 +311,7 @@ public void buildmappingsfromlists() config.objecttype = ObjectType.RECORD; ODentry sub = new ODentry("max sub-index", (ushort)slot.ConfigurationIndex, 0); - sub.defaultvalue = "6"; + sub.defaultvalue = slot.isTXPDO()? "6" : "5";// max supported sub index TPDO=6, RPDO=5 according DS301 sub.datatype = DataType.UNSIGNED8; sub.accesstype = EDSsharp.AccessType.ro; config.addsubobject(0x00,sub); @@ -383,7 +383,13 @@ public void buildmappingsfromlists() sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); sub.accesstype = EDSsharp.AccessType.rw; - config.addsubobject(0x02, sub); + config.addsubobject(0x02, sub); + + sub = new ODentry("event timer", (ushort)slot.ConfigurationIndex, 5); + sub.datatype = DataType.UNSIGNED16; + sub.defaultvalue = slot.eventtimer.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; + config.addsubobject(0x05, sub); } eds.ods.Add(slot.ConfigurationIndex,config); From ca539d311b1ed72dc3205f35ad723b4febe8dcef Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Fri, 23 Dec 2022 23:23:00 +0100 Subject: [PATCH 065/226] Update DeviceView if Tab ObjectDirectory is selected to reflect changes in RX/TX Tab --- EDSEditorGUI/Form1.cs | 12 +++++++- EDSEditorGUI/Properties/Settings.Designer.cs | 2 +- Tests/Tests.csproj | 31 ++++++++++---------- Tests/packages.config | 16 +++++----- libEDSsharp/libEDSsharp.csproj | 2 ++ 5 files changed, 38 insertions(+), 25 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 87aeb82c..405c71b6 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -658,7 +658,17 @@ private void newToolStripMenuItem_Click(object sender, EventArgs e) network.Add(eds); } - + private void TabControl1_Selected(Object sender, TabControlEventArgs e) + { + if(tabControl1.SelectedIndex == 0) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + dv.dispatch_updateOD(); + dv.dispatch_updatePDOinfo(); + dv.eds.UpdatePDOcount(); + dv.dispatch_updatedevice(); + } + } private void tabControl1_ControlsChanged(object sender, ControlEventArgs e) { enablesavemenus(tabControl1.TabCount > 0); diff --git a/EDSEditorGUI/Properties/Settings.Designer.cs b/EDSEditorGUI/Properties/Settings.Designer.cs index b669499a..828c6e10 100644 --- a/EDSEditorGUI/Properties/Settings.Designer.cs +++ b/EDSEditorGUI/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace ODEditor.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.2.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.1.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index bef33aff..77ded76c 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,8 +1,8 @@  - - - + + + Debug AnyCPU @@ -45,14 +45,14 @@ ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll - - ..\packages\xunit.assert.2.4.1\lib\netstandard1.1\xunit.assert.dll + + ..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll - - ..\packages\xunit.extensibility.core.2.4.1\lib\net452\xunit.core.dll + + ..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll - - ..\packages\xunit.extensibility.execution.2.4.1\lib\net452\xunit.execution.desktop.dll + + ..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll @@ -81,7 +81,8 @@ - + + @@ -107,12 +108,12 @@ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - + + + + - + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - - - AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w - LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 - ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACk - CgAAAk1TRnQBSQFMAgEBBAEAAUABAAFAAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo - AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA - AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 - AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA - AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm - AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM - AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA - ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz - AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ - AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM - AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA - AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA - AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ - AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ - AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA - AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm - ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ - Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz - AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA - AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM - AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM - ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM - Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA - AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM - AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ - AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz - AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm - AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw - AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD//8A/wD/AP8AJQAL9AUA - C/QFABD0AQAO9AEAAfQJFAH0BQAB9AkUAfQFAAH0DhQB9AEAAfQMFAH0AQAB9AEUCfQFAAH0ARQJ9AUA - AfQOFAH0AQAC9AEUCfQBFAH0AQAB9AEUAfQDAAb0BAAB9AEUAfQNAAH0AhQH9AEUAeoB8QHqARQB9AEA - AfQCFAn0ARQB9AEAAfQBFAH0BAAB9AMUAfcB9AMAAfQBFAH0BAAB9AH3AxQB7wH0AgAB9AIUAfQEFAL0 - ARQBvAH0AbwBFAH0AQAC9AEUCfQBFAH0AQAB9AEUAfQEAAH0Ae8DFAHsAfQCAAH0ARQB9AMAAfQB7AMU - Ae8B9AMAAfQCFAf0BRQB9AEAAfQCFAn0ARQB9AEAAfQBFAf0Ae8DFAHsAfQBAAH0ARQB9AIAAfQB7AMU - Ae8G9AIUAfQDFAn0AQAC9AEUCfQBFAH0AQAB9AEUAvQKFAHsAvQBFAH0AQAB9AHsChQB9AIUB/QFFAH0 - AQAB9AIUCfQBFAH0AQAB9AEUAvQKFAHsAvQBFAH0AQAB9AHsChQB9AIUAfQFFAf0AQAC9AEUCfQBFAH0 - AQAB9AEUB/QB7wMUAewB9AEAAfQBFAH0AgAB9AHsAxQB7wb0AhQH9AUUAfQBAAH0AhQC9AUUAvQBFAH0 - AQAB9AEUAfQEAAH0Ae8DFAHsAfQCAAH0ARQB9AMAAfQB7AMUAe8B9AMAAfQCFAH0AxQD9AEUAbwB9AG8 - ARQB9AEAAvQBFAL0BRQC9AEUAfQBAAH0ARQB9AQAAfQDFAH3AfQDAAH0ARQB9AQAAfQB9wMUAe8B9AIA - AfQCFAf0ARQB6gHxAeoBFAH0AQAB9AIUCfQBFAH0AQAB9AEUAfQDAAb0BAAB9AEUAfQCAAr0AQAB9A4U - AfQBAAL0ARQJ9AEUAfQBAAH0ARQJ9AUAAfQBFAn0BQAB9A4UAfQBAAH0DBQB9AEAAfQJFAH0BQAB9AkU - AfQFABD0AQAO9AEAC/QFAAv0BQABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/4EA - BP8BAAEfAQABHwIAAYABAQEAAR8BAAEfAgABgAEBAQABHwEAAR8CAAGAAQEBHAEPAR8B/wIAAYABAQEe - AQcBHgEDAgABgAEBAR4BAwEcAQcCAAGAAQEBAAEBARgDAAGAAQECAAEQAwABgAEBAgABEAMAAYABAQEA - AQEBGAMAAYABAQEeAQMBHAEHAgABgAEBAR4BBwEeAQMCAAGAAQEBHAEPARgBAQIAAYABAQEAAR8BAAEf - AgABgAEBAQABHwEAAR8CAAGAAQEBAAEfAQABHws= - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w + LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 + ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACk + CgAAAk1TRnQBSQFMAgEBBAEAAVABAAFQAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA + AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 + AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA + AWYDAAGZAwABzAIAATMDAAIzAgABMwFmAgABMwGZAgABMwHMAgABMwH/AgABZgMAAWYBMwIAAmYCAAFm + AZkCAAFmAcwCAAFmAf8CAAGZAwABmQEzAgABmQFmAgACmQIAAZkBzAIAAZkB/wIAAcwDAAHMATMCAAHM + AWYCAAHMAZkCAALMAgABzAH/AgAB/wFmAgAB/wGZAgAB/wHMAQABMwH/AgAB/wEAATMBAAEzAQABZgEA + ATMBAAGZAQABMwEAAcwBAAEzAQAB/wEAAf8BMwIAAzMBAAIzAWYBAAIzAZkBAAIzAcwBAAIzAf8BAAEz + AWYCAAEzAWYBMwEAATMCZgEAATMBZgGZAQABMwFmAcwBAAEzAWYB/wEAATMBmQIAATMBmQEzAQABMwGZ + AWYBAAEzApkBAAEzAZkBzAEAATMBmQH/AQABMwHMAgABMwHMATMBAAEzAcwBZgEAATMBzAGZAQABMwLM + AQABMwHMAf8BAAEzAf8BMwEAATMB/wFmAQABMwH/AZkBAAEzAf8BzAEAATMC/wEAAWYDAAFmAQABMwEA + AWYBAAFmAQABZgEAAZkBAAFmAQABzAEAAWYBAAH/AQABZgEzAgABZgIzAQABZgEzAWYBAAFmATMBmQEA + AWYBMwHMAQABZgEzAf8BAAJmAgACZgEzAQADZgEAAmYBmQEAAmYBzAEAAWYBmQIAAWYBmQEzAQABZgGZ + AWYBAAFmApkBAAFmAZkBzAEAAWYBmQH/AQABZgHMAgABZgHMATMBAAFmAcwBmQEAAWYCzAEAAWYBzAH/ + AQABZgH/AgABZgH/ATMBAAFmAf8BmQEAAWYB/wHMAQABzAEAAf8BAAH/AQABzAEAApkCAAGZATMBmQEA + AZkBAAGZAQABmQEAAcwBAAGZAwABmQIzAQABmQEAAWYBAAGZATMBzAEAAZkBAAH/AQABmQFmAgABmQFm + ATMBAAGZATMBZgEAAZkBZgGZAQABmQFmAcwBAAGZATMB/wEAApkBMwEAApkBZgEAA5kBAAKZAcwBAAKZ + Af8BAAGZAcwCAAGZAcwBMwEAAWYBzAFmAQABmQHMAZkBAAGZAswBAAGZAcwB/wEAAZkB/wIAAZkB/wEz + AQABmQHMAWYBAAGZAf8BmQEAAZkB/wHMAQABmQL/AQABzAMAAZkBAAEzAQABzAEAAWYBAAHMAQABmQEA + AcwBAAHMAQABmQEzAgABzAIzAQABzAEzAWYBAAHMATMBmQEAAcwBMwHMAQABzAEzAf8BAAHMAWYCAAHM + AWYBMwEAAZkCZgEAAcwBZgGZAQABzAFmAcwBAAGZAWYB/wEAAcwBmQIAAcwBmQEzAQABzAGZAWYBAAHM + ApkBAAHMAZkBzAEAAcwBmQH/AQACzAIAAswBMwEAAswBZgEAAswBmQEAA8wBAALMAf8BAAHMAf8CAAHM + Af8BMwEAAZkB/wFmAQABzAH/AZkBAAHMAf8BzAEAAcwC/wEAAcwBAAEzAQAB/wEAAWYBAAH/AQABmQEA + AcwBMwIAAf8CMwEAAf8BMwFmAQAB/wEzAZkBAAH/ATMBzAEAAf8BMwH/AQAB/wFmAgAB/wFmATMBAAHM + AmYBAAH/AWYBmQEAAf8BZgHMAQABzAFmAf8BAAH/AZkCAAH/AZkBMwEAAf8BmQFmAQAB/wKZAQAB/wGZ + AcwBAAH/AZkB/wEAAf8BzAIAAf8BzAEzAQAB/wHMAWYBAAH/AcwBmQEAAf8CzAEAAf8BzAH/AQAC/wEz + AQABzAH/AWYBAAL/AZkBAAL/AcwBAAJmAf8BAAFmAf8BZgEAAWYC/wEAAf8CZgEAAf8BZgH/AQAC/wFm + AQABIQEAAaUBAANfAQADdwEAA4YBAAOWAQADywEAA7IBAAPXAQAD3QEAA+MBAAPqAQAD8QEAA/gBAAHw + AfsB/wEAAaQCoAEAA4ADAAH/AgAB/wMAAv8BAAH/AwAB/wEAAf8BAAL/AgAD//8A/wD/AP8AJQAL9AUA + C/QFABD0AQAO9AEAAfQJFAH0BQAB9AkUAfQFAAH0DhQB9AEAAfQMFAH0AQAB9AEUCfQFAAH0ARQJ9AUA + AfQOFAH0AQAC9AEUCfQBFAH0AQAB9AEUAfQDAAb0BAAB9AEUAfQNAAH0AhQH9AEUAeoB8QHqARQB9AEA + AfQCFAn0ARQB9AEAAfQBFAH0BAAB9AMUAfcB9AMAAfQBFAH0BAAB9AH3AxQB7wH0AgAB9AIUAfQEFAL0 + ARQBvAH0AbwBFAH0AQAC9AEUCfQBFAH0AQAB9AEUAfQEAAH0Ae8DFAHsAfQCAAH0ARQB9AMAAfQB7AMU + Ae8B9AMAAfQCFAf0BRQB9AEAAfQCFAn0ARQB9AEAAfQBFAf0Ae8DFAHsAfQBAAH0ARQB9AIAAfQB7AMU + Ae8G9AIUAfQDFAn0AQAC9AEUCfQBFAH0AQAB9AEUAvQKFAHsAvQBFAH0AQAB9AHsChQB9AIUB/QFFAH0 + AQAB9AIUCfQBFAH0AQAB9AEUAvQKFAHsAvQBFAH0AQAB9AHsChQB9AIUAfQFFAf0AQAC9AEUCfQBFAH0 + AQAB9AEUB/QB7wMUAewB9AEAAfQBFAH0AgAB9AHsAxQB7wb0AhQH9AUUAfQBAAH0AhQC9AUUAvQBFAH0 + AQAB9AEUAfQEAAH0Ae8DFAHsAfQCAAH0ARQB9AMAAfQB7AMUAe8B9AMAAfQCFAH0AxQD9AEUAbwB9AG8 + ARQB9AEAAvQBFAL0BRQC9AEUAfQBAAH0ARQB9AQAAfQDFAH3AfQDAAH0ARQB9AQAAfQB9wMUAe8B9AIA + AfQCFAf0ARQB6gHxAeoBFAH0AQAB9AIUCfQBFAH0AQAB9AEUAfQDAAb0BAAB9AEUAfQCAAr0AQAB9A4U + AfQBAAL0ARQJ9AEUAfQBAAH0ARQJ9AUAAfQBFAn0BQAB9A4UAfQBAAH0DBQB9AEAAfQJFAH0BQAB9AkU + AfQFABD0AQAO9AEAC/QFAAv0BQABQgFNAT4HAAE+AwABKAMAAUADAAEgAwABAQEAAQEGAAEBFgAD/4EA + BP8BAAEfAQABHwIAAYABAQEAAR8BAAEfAgABgAEBAQABHwEAAR8CAAGAAQEBHAEPAR8B/wIAAYABAQEe + AQcBHgEDAgABgAEBAR4BAwEcAQcCAAGAAQEBAAEBARgDAAGAAQECAAEQAwABgAEBAgABEAMAAYABAQEA + AQEBGAMAAYABAQEeAQMBHAEHAgABgAEBAR4BBwEeAQMCAAGAAQEBHAEPARgBAQIAAYABAQEAAR8BAAEf + AgABgAEBAQABHwEAAR8CAAGAAQEBAAEfAQABHws= + + \ No newline at end of file diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 90d72527..02569280 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -328,10 +328,10 @@ public void buildmappingsfromlists() config.prop.CO_countLabel = "TPDO"; sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); - sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = slot.COB.ToHexString(); + sub.datatype = DataType.UNSIGNED32; if (slot.nodeidpresent) - sub.defaultvalue += " + $NODEID"; + sub.defaultvalue = "$NODEID + "; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. + sub.defaultvalue += slot.COB.ToHexString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -373,9 +373,9 @@ public void buildmappingsfromlists() sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = slot.COB.ToHexString(); if (slot.nodeidpresent) - sub.defaultvalue += " + $NODEID"; + sub.defaultvalue = "$NODEID + "; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. + sub.defaultvalue += slot.COB.ToHexString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 6d1bc839..d6dfa87f 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -2546,7 +2546,7 @@ public void ApplycompactPDO(UInt16 index) { //Fill in cob ID //FIX ME i'm really sure this is not correct, what default values should be used??? - string cob = string.Format("0x180+$NODEID"); + string cob = string.Format("$NODEID + 0x180"); ODentry subod = new ODentry("COB-ID", index, DataType.UNSIGNED32, cob, AccessType.rw, PDOMappingType.no, ods[index]); ods[index].subobjects.Add(0x05, subod); From e7f249f80fd41fb479cde42ae28cf890a1c22294 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 18 Jan 2023 08:12:43 +0100 Subject: [PATCH 067/226] Resize Grid view TX/RX PDO to form size --- EDSEditorGUI/DevicePDOView2.Designer.cs | 776 +++++++++++++----------- EDSEditorGUI/DevicePDOView2.resx | 244 ++++---- 2 files changed, 534 insertions(+), 486 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.Designer.cs b/EDSEditorGUI/DevicePDOView2.Designer.cs index d859394e..7da61e86 100644 --- a/EDSEditorGUI/DevicePDOView2.Designer.cs +++ b/EDSEditorGUI/DevicePDOView2.Designer.cs @@ -28,366 +28,412 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.button_addPDO = new System.Windows.Forms.Button(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.textBox_mapping = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.checkBox_invalidpdo = new System.Windows.Forms.CheckBox(); - this.button_savepdochanges = new System.Windows.Forms.Button(); - this.button_deletePDO = new System.Windows.Forms.Button(); - this.textBox_slot = new System.Windows.Forms.TextBox(); - this.textBox_syncstart = new System.Windows.Forms.TextBox(); - this.textBox_eventtimer = new System.Windows.Forms.TextBox(); - this.textBox_inhibit = new System.Windows.Forms.TextBox(); - this.textBox_type = new System.Windows.Forms.TextBox(); - this.label7 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.label5 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.textBox_cob = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.label_availableobjects = new System.Windows.Forms.Label(); - this.listView_TXPDO = new System.Windows.Forms.ListView(); - this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader15 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader16 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader17 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.grid1 = new SourceGrid.Grid(); - this.button_down = new System.Windows.Forms.Button(); - this.button_up = new System.Windows.Forms.Button(); - this.contextMenuStrip_removeitem = new System.Windows.Forms.ContextMenuStrip(this.components); - this.toolStripMenuItem_removeitem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem_insert = new System.Windows.Forms.ToolStripMenuItem(); - this.groupBox1.SuspendLayout(); - this.contextMenuStrip_removeitem.SuspendLayout(); - this.SuspendLayout(); - // - // button_addPDO - // - this.button_addPDO.Image = global::ODEditor.Properties.Resources.action_add_16xLG; - this.button_addPDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_addPDO.Location = new System.Drawing.Point(884, 26); - this.button_addPDO.Name = "button_addPDO"; - this.button_addPDO.Size = new System.Drawing.Size(117, 27); - this.button_addPDO.TabIndex = 15; - this.button_addPDO.Text = "Add new PDO"; - this.button_addPDO.UseVisualStyleBackColor = true; - this.button_addPDO.Click += new System.EventHandler(this.button_addPDO_Click); - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.textBox_mapping); - this.groupBox1.Controls.Add(this.label1); - this.groupBox1.Controls.Add(this.checkBox_invalidpdo); - this.groupBox1.Controls.Add(this.button_savepdochanges); - this.groupBox1.Controls.Add(this.button_deletePDO); - this.groupBox1.Controls.Add(this.textBox_slot); - this.groupBox1.Controls.Add(this.textBox_syncstart); - this.groupBox1.Controls.Add(this.textBox_eventtimer); - this.groupBox1.Controls.Add(this.textBox_inhibit); - this.groupBox1.Controls.Add(this.textBox_type); - this.groupBox1.Controls.Add(this.label7); - this.groupBox1.Controls.Add(this.label6); - this.groupBox1.Controls.Add(this.label5); - this.groupBox1.Controls.Add(this.label4); - this.groupBox1.Controls.Add(this.textBox_cob); - this.groupBox1.Controls.Add(this.label3); - this.groupBox1.Controls.Add(this.label2); - this.groupBox1.Location = new System.Drawing.Point(528, 15); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(340, 206); - this.groupBox1.TabIndex = 16; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Communication parameters"; - // - // textBox_mapping - // - this.textBox_mapping.Location = new System.Drawing.Point(98, 47); - this.textBox_mapping.Name = "textBox_mapping"; - this.textBox_mapping.ReadOnly = true; - this.textBox_mapping.Size = new System.Drawing.Size(96, 20); - this.textBox_mapping.TabIndex = 9; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(8, 50); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(48, 13); - this.label1.TabIndex = 10; - this.label1.Text = "Mapping"; - // - // checkBox_invalidpdo - // - this.checkBox_invalidpdo.AutoSize = true; - this.checkBox_invalidpdo.Location = new System.Drawing.Point(208, 76); - this.checkBox_invalidpdo.Name = "checkBox_invalidpdo"; - this.checkBox_invalidpdo.Size = new System.Drawing.Size(57, 17); - this.checkBox_invalidpdo.TabIndex = 2; - this.checkBox_invalidpdo.Text = "Invalid"; - this.checkBox_invalidpdo.UseVisualStyleBackColor = true; - this.checkBox_invalidpdo.CheckedChanged += new System.EventHandler(this.checkBox_invalidpdo_CheckedChanged); - // - // button_savepdochanges - // - this.button_savepdochanges.Image = global::ODEditor.Properties.Resources.Save_6530; - this.button_savepdochanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_savepdochanges.Location = new System.Drawing.Point(208, 161); - this.button_savepdochanges.Name = "button_savepdochanges"; - this.button_savepdochanges.Size = new System.Drawing.Size(101, 27); - this.button_savepdochanges.TabIndex = 8; - this.button_savepdochanges.Text = "Save "; - this.button_savepdochanges.UseVisualStyleBackColor = true; - this.button_savepdochanges.Click += new System.EventHandler(this.button_savepdochanges_Click_1); - // - // button_deletePDO - // - this.button_deletePDO.Image = global::ODEditor.Properties.Resources.Remove_16xLG; - this.button_deletePDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_deletePDO.Location = new System.Drawing.Point(208, 128); - this.button_deletePDO.Name = "button_deletePDO"; - this.button_deletePDO.Size = new System.Drawing.Size(101, 27); - this.button_deletePDO.TabIndex = 7; - this.button_deletePDO.Text = "Delete PDO"; - this.button_deletePDO.UseVisualStyleBackColor = true; - this.button_deletePDO.Click += new System.EventHandler(this.button_deletePDO_Click); - // - // textBox_slot - // - this.textBox_slot.Location = new System.Drawing.Point(98, 20); - this.textBox_slot.Name = "textBox_slot"; - this.textBox_slot.Size = new System.Drawing.Size(96, 20); - this.textBox_slot.TabIndex = 0; - // - // textBox_syncstart - // - this.textBox_syncstart.Location = new System.Drawing.Point(98, 181); - this.textBox_syncstart.Name = "textBox_syncstart"; - this.textBox_syncstart.Size = new System.Drawing.Size(96, 20); - this.textBox_syncstart.TabIndex = 6; - // - // textBox_eventtimer - // - this.textBox_eventtimer.Location = new System.Drawing.Point(98, 154); - this.textBox_eventtimer.Name = "textBox_eventtimer"; - this.textBox_eventtimer.Size = new System.Drawing.Size(96, 20); - this.textBox_eventtimer.TabIndex = 5; - // - // textBox_inhibit - // - this.textBox_inhibit.Location = new System.Drawing.Point(98, 128); - this.textBox_inhibit.Name = "textBox_inhibit"; - this.textBox_inhibit.Size = new System.Drawing.Size(96, 20); - this.textBox_inhibit.TabIndex = 4; - // - // textBox_type - // - this.textBox_type.Location = new System.Drawing.Point(98, 101); - this.textBox_type.Name = "textBox_type"; - this.textBox_type.Size = new System.Drawing.Size(96, 20); - this.textBox_type.TabIndex = 3; - // - // label7 - // - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(10, 184); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(54, 13); - this.label7.TabIndex = 6; - this.label7.Text = "Sync start"; - // - // label6 - // - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(10, 131); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(35, 13); - this.label6.TabIndex = 5; - this.label6.Text = "Inhibit"; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(10, 158); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(64, 13); - this.label5.TabIndex = 4; - this.label5.Text = "Event Timer"; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(10, 104); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(31, 13); - this.label4.TabIndex = 3; - this.label4.Text = "Type"; - // - // textBox_cob - // - this.textBox_cob.Location = new System.Drawing.Point(98, 74); - this.textBox_cob.Name = "textBox_cob"; - this.textBox_cob.Size = new System.Drawing.Size(96, 20); - this.textBox_cob.TabIndex = 1; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(10, 77); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(29, 13); - this.label3.TabIndex = 1; - this.label3.Text = "COB"; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(8, 24); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(79, 13); - this.label2.TabIndex = 0; - this.label2.Text = "Communication"; - // - // label_availableobjects - // - this.label_availableobjects.AutoSize = true; - this.label_availableobjects.Location = new System.Drawing.Point(28, 7); - this.label_availableobjects.Name = "label_availableobjects"; - this.label_availableobjects.Size = new System.Drawing.Size(130, 13); - this.label_availableobjects.TabIndex = 18; - this.label_availableobjects.Text = "Available Objects for PDO"; - // - // listView_TXPDO - // - this.listView_TXPDO.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader13, - this.columnHeader15, - this.columnHeader16, - this.columnHeader17, - this.columnHeader1}); - this.listView_TXPDO.FullRowSelect = true; - this.listView_TXPDO.HideSelection = false; - this.listView_TXPDO.Location = new System.Drawing.Point(31, 24); - this.listView_TXPDO.MultiSelect = false; - this.listView_TXPDO.Name = "listView_TXPDO"; - this.listView_TXPDO.Size = new System.Drawing.Size(492, 199); - this.listView_TXPDO.TabIndex = 17; - this.listView_TXPDO.UseCompatibleStateImageBehavior = false; - this.listView_TXPDO.View = System.Windows.Forms.View.Details; - this.listView_TXPDO.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.listView_TXPDO_ItemDrag); - // - // columnHeader13 - // - this.columnHeader13.Text = "Index"; - this.columnHeader13.Width = 55; - // - // columnHeader15 - // - this.columnHeader15.Text = "Sub"; - this.columnHeader15.Width = 40; - // - // columnHeader16 - // - this.columnHeader16.Text = "Name"; - this.columnHeader16.Width = 206; - // - // columnHeader17 - // - this.columnHeader17.Text = "Datatype"; - this.columnHeader17.Width = 183; - // - // columnHeader1 - // - this.columnHeader1.Text = "Bits"; - // - // grid1 - // - this.grid1.AllowDrop = true; - this.grid1.DefaultWidth = 18; - this.grid1.EnableSort = true; - this.grid1.Location = new System.Drawing.Point(30, 244); - this.grid1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.grid1.Name = "grid1"; - this.grid1.OptimizeMode = SourceGrid.CellOptimizeMode.ForRows; - this.grid1.SelectionMode = SourceGrid.GridSelectionMode.Cell; - this.grid1.Size = new System.Drawing.Size(1033, 288); - this.grid1.TabIndex = 21; - this.grid1.TabStop = true; - this.grid1.ToolTipText = ""; - this.grid1.DragDrop += new System.Windows.Forms.DragEventHandler(this.grid1_DragDrop); - this.grid1.DragEnter += new System.Windows.Forms.DragEventHandler(this.grid1_DragEnter); - this.grid1.DragOver += new System.Windows.Forms.DragEventHandler(this.grid1_DragOver); - // - // button_down - // - this.button_down.Location = new System.Drawing.Point(32, 535); - this.button_down.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.button_down.Name = "button_down"; - this.button_down.Size = new System.Drawing.Size(69, 30); - this.button_down.TabIndex = 22; - this.button_down.Text = "Zoom Out"; - this.button_down.UseVisualStyleBackColor = true; - this.button_down.Click += new System.EventHandler(this.button_down_Click); - // - // button_up - // - this.button_up.Location = new System.Drawing.Point(105, 535); - this.button_up.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.button_up.Name = "button_up"; - this.button_up.Size = new System.Drawing.Size(75, 30); - this.button_up.TabIndex = 23; - this.button_up.Text = "Zoom In"; - this.button_up.UseVisualStyleBackColor = true; - this.button_up.Click += new System.EventHandler(this.button_up_Click); - // - // contextMenuStrip_removeitem - // - this.contextMenuStrip_removeitem.ImageScalingSize = new System.Drawing.Size(20, 20); - this.contextMenuStrip_removeitem.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripMenuItem_removeitem, - this.toolStripMenuItem_insert}); - this.contextMenuStrip_removeitem.Name = "contextMenuStrip_removeitem"; - this.contextMenuStrip_removeitem.Size = new System.Drawing.Size(145, 48); - this.contextMenuStrip_removeitem.Text = "Remove Item"; - // - // toolStripMenuItem_removeitem - // - this.toolStripMenuItem_removeitem.Name = "toolStripMenuItem_removeitem"; - this.toolStripMenuItem_removeitem.Size = new System.Drawing.Size(144, 22); - this.toolStripMenuItem_removeitem.Tag = "remove"; - this.toolStripMenuItem_removeitem.Text = "Remove Item"; - // - // toolStripMenuItem_insert - // - this.toolStripMenuItem_insert.Name = "toolStripMenuItem_insert"; - this.toolStripMenuItem_insert.Size = new System.Drawing.Size(144, 22); - this.toolStripMenuItem_insert.Tag = "insert"; - this.toolStripMenuItem_insert.Text = "Insert Item"; - // - // DevicePDOView2 - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoScroll = true; - this.Controls.Add(this.button_up); - this.Controls.Add(this.button_down); - this.Controls.Add(this.grid1); - this.Controls.Add(this.label_availableobjects); - this.Controls.Add(this.listView_TXPDO); - this.Controls.Add(this.button_addPDO); - this.Controls.Add(this.groupBox1); - this.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.Name = "DevicePDOView2"; - this.Size = new System.Drawing.Size(1067, 570); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.contextMenuStrip_removeitem.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - + this.components = new System.ComponentModel.Container(); + this.button_addPDO = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox_mapping = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.checkBox_invalidpdo = new System.Windows.Forms.CheckBox(); + this.button_savepdochanges = new System.Windows.Forms.Button(); + this.button_deletePDO = new System.Windows.Forms.Button(); + this.textBox_slot = new System.Windows.Forms.TextBox(); + this.textBox_syncstart = new System.Windows.Forms.TextBox(); + this.textBox_eventtimer = new System.Windows.Forms.TextBox(); + this.textBox_inhibit = new System.Windows.Forms.TextBox(); + this.textBox_type = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox_cob = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.listView_TXPDO = new System.Windows.Forms.ListView(); + this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader15 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader16 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader17 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.button_up = new System.Windows.Forms.Button(); + this.contextMenuStrip_removeitem = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem_removeitem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem_insert = new System.Windows.Forms.ToolStripMenuItem(); + this.grid1 = new SourceGrid.Grid(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.button_down = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.groupBox1.SuspendLayout(); + this.contextMenuStrip_removeitem.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // button_addPDO + // + this.button_addPDO.Image = global::ODEditor.Properties.Resources.action_add_16xLG; + this.button_addPDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_addPDO.Location = new System.Drawing.Point(912, 101); + this.button_addPDO.Name = "button_addPDO"; + this.button_addPDO.Size = new System.Drawing.Size(101, 27); + this.button_addPDO.TabIndex = 15; + this.button_addPDO.Text = "Add new PDO"; + this.button_addPDO.UseVisualStyleBackColor = true; + this.button_addPDO.Click += new System.EventHandler(this.button_addPDO_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textBox_mapping); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.checkBox_invalidpdo); + this.groupBox1.Controls.Add(this.textBox_slot); + this.groupBox1.Controls.Add(this.textBox_syncstart); + this.groupBox1.Controls.Add(this.textBox_eventtimer); + this.groupBox1.Controls.Add(this.textBox_inhibit); + this.groupBox1.Controls.Add(this.textBox_type); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.textBox_cob); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Location = new System.Drawing.Point(612, 7); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(283, 206); + this.groupBox1.TabIndex = 16; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Communication parameters"; + // + // textBox_mapping + // + this.textBox_mapping.Location = new System.Drawing.Point(98, 47); + this.textBox_mapping.Name = "textBox_mapping"; + this.textBox_mapping.ReadOnly = true; + this.textBox_mapping.Size = new System.Drawing.Size(96, 20); + this.textBox_mapping.TabIndex = 9; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(8, 50); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(48, 13); + this.label1.TabIndex = 10; + this.label1.Text = "Mapping"; + // + // checkBox_invalidpdo + // + this.checkBox_invalidpdo.AutoSize = true; + this.checkBox_invalidpdo.Location = new System.Drawing.Point(214, 183); + this.checkBox_invalidpdo.Name = "checkBox_invalidpdo"; + this.checkBox_invalidpdo.Size = new System.Drawing.Size(57, 17); + this.checkBox_invalidpdo.TabIndex = 2; + this.checkBox_invalidpdo.Text = "Invalid"; + this.checkBox_invalidpdo.UseVisualStyleBackColor = true; + this.checkBox_invalidpdo.CheckedChanged += new System.EventHandler(this.checkBox_invalidpdo_CheckedChanged); + // + // button_savepdochanges + // + this.button_savepdochanges.Image = global::ODEditor.Properties.Resources.Save_6530; + this.button_savepdochanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_savepdochanges.Location = new System.Drawing.Point(912, 177); + this.button_savepdochanges.Name = "button_savepdochanges"; + this.button_savepdochanges.Size = new System.Drawing.Size(101, 27); + this.button_savepdochanges.TabIndex = 8; + this.button_savepdochanges.Text = "Save "; + this.button_savepdochanges.UseVisualStyleBackColor = true; + this.button_savepdochanges.Click += new System.EventHandler(this.button_savepdochanges_Click_1); + // + // button_deletePDO + // + this.button_deletePDO.Image = global::ODEditor.Properties.Resources.Remove_16xLG; + this.button_deletePDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_deletePDO.Location = new System.Drawing.Point(912, 138); + this.button_deletePDO.Name = "button_deletePDO"; + this.button_deletePDO.Size = new System.Drawing.Size(101, 27); + this.button_deletePDO.TabIndex = 7; + this.button_deletePDO.Text = "Delete PDO"; + this.button_deletePDO.UseVisualStyleBackColor = true; + this.button_deletePDO.Click += new System.EventHandler(this.button_deletePDO_Click); + // + // textBox_slot + // + this.textBox_slot.Location = new System.Drawing.Point(98, 20); + this.textBox_slot.Name = "textBox_slot"; + this.textBox_slot.Size = new System.Drawing.Size(96, 20); + this.textBox_slot.TabIndex = 0; + // + // textBox_syncstart + // + this.textBox_syncstart.Location = new System.Drawing.Point(98, 181); + this.textBox_syncstart.Name = "textBox_syncstart"; + this.textBox_syncstart.Size = new System.Drawing.Size(96, 20); + this.textBox_syncstart.TabIndex = 6; + // + // textBox_eventtimer + // + this.textBox_eventtimer.Location = new System.Drawing.Point(98, 154); + this.textBox_eventtimer.Name = "textBox_eventtimer"; + this.textBox_eventtimer.Size = new System.Drawing.Size(96, 20); + this.textBox_eventtimer.TabIndex = 5; + // + // textBox_inhibit + // + this.textBox_inhibit.Location = new System.Drawing.Point(98, 128); + this.textBox_inhibit.Name = "textBox_inhibit"; + this.textBox_inhibit.Size = new System.Drawing.Size(96, 20); + this.textBox_inhibit.TabIndex = 4; + // + // textBox_type + // + this.textBox_type.Location = new System.Drawing.Point(98, 101); + this.textBox_type.Name = "textBox_type"; + this.textBox_type.Size = new System.Drawing.Size(96, 20); + this.textBox_type.TabIndex = 3; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(10, 184); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(54, 13); + this.label7.TabIndex = 6; + this.label7.Text = "Sync start"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(10, 131); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(35, 13); + this.label6.TabIndex = 5; + this.label6.Text = "Inhibit"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(10, 158); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(64, 13); + this.label5.TabIndex = 4; + this.label5.Text = "Event Timer"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(10, 104); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(31, 13); + this.label4.TabIndex = 3; + this.label4.Text = "Type"; + // + // textBox_cob + // + this.textBox_cob.Location = new System.Drawing.Point(98, 74); + this.textBox_cob.Name = "textBox_cob"; + this.textBox_cob.Size = new System.Drawing.Size(96, 20); + this.textBox_cob.TabIndex = 1; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(10, 77); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(29, 13); + this.label3.TabIndex = 1; + this.label3.Text = "COB"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(8, 24); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(79, 13); + this.label2.TabIndex = 0; + this.label2.Text = "Communication"; + // + // listView_TXPDO + // + this.listView_TXPDO.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader13, + this.columnHeader15, + this.columnHeader16, + this.columnHeader17, + this.columnHeader1}); + this.listView_TXPDO.FullRowSelect = true; + this.listView_TXPDO.HideSelection = false; + this.listView_TXPDO.Location = new System.Drawing.Point(6, 19); + this.listView_TXPDO.MultiSelect = false; + this.listView_TXPDO.Name = "listView_TXPDO"; + this.listView_TXPDO.Size = new System.Drawing.Size(587, 182); + this.listView_TXPDO.TabIndex = 17; + this.listView_TXPDO.UseCompatibleStateImageBehavior = false; + this.listView_TXPDO.View = System.Windows.Forms.View.Details; + this.listView_TXPDO.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.listView_TXPDO_ItemDrag); + // + // columnHeader13 + // + this.columnHeader13.Text = "Index"; + this.columnHeader13.Width = 55; + // + // columnHeader15 + // + this.columnHeader15.Text = "Sub"; + this.columnHeader15.Width = 40; + // + // columnHeader16 + // + this.columnHeader16.Text = "Name"; + this.columnHeader16.Width = 206; + // + // columnHeader17 + // + this.columnHeader17.Text = "Datatype"; + this.columnHeader17.Width = 183; + // + // columnHeader1 + // + this.columnHeader1.Text = "Bits"; + // + // button_up + // + this.button_up.Location = new System.Drawing.Point(2, 396); + this.button_up.Margin = new System.Windows.Forms.Padding(2); + this.button_up.Name = "button_up"; + this.button_up.Size = new System.Drawing.Size(85, 30); + this.button_up.TabIndex = 23; + this.button_up.Text = "Zoom In"; + this.button_up.UseVisualStyleBackColor = true; + this.button_up.Click += new System.EventHandler(this.button_up_Click); + // + // contextMenuStrip_removeitem + // + this.contextMenuStrip_removeitem.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip_removeitem.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem_removeitem, + this.toolStripMenuItem_insert}); + this.contextMenuStrip_removeitem.Name = "contextMenuStrip_removeitem"; + this.contextMenuStrip_removeitem.Size = new System.Drawing.Size(145, 48); + this.contextMenuStrip_removeitem.Text = "Remove Item"; + // + // toolStripMenuItem_removeitem + // + this.toolStripMenuItem_removeitem.Name = "toolStripMenuItem_removeitem"; + this.toolStripMenuItem_removeitem.Size = new System.Drawing.Size(144, 22); + this.toolStripMenuItem_removeitem.Tag = "remove"; + this.toolStripMenuItem_removeitem.Text = "Remove Item"; + // + // toolStripMenuItem_insert + // + this.toolStripMenuItem_insert.Name = "toolStripMenuItem_insert"; + this.toolStripMenuItem_insert.Size = new System.Drawing.Size(144, 22); + this.toolStripMenuItem_insert.Tag = "insert"; + this.toolStripMenuItem_insert.Text = "Insert Item"; + // + // grid1 + // + this.grid1.AllowDrop = true; + this.grid1.AutoSize = true; + this.grid1.DefaultWidth = 18; + this.grid1.Dock = System.Windows.Forms.DockStyle.Fill; + this.grid1.EnableSort = true; + this.grid1.Location = new System.Drawing.Point(3, 16); + this.grid1.Margin = new System.Windows.Forms.Padding(2); + this.grid1.Name = "grid1"; + this.grid1.OptimizeMode = SourceGrid.CellOptimizeMode.ForRows; + this.grid1.SelectionMode = SourceGrid.GridSelectionMode.Cell; + this.grid1.Size = new System.Drawing.Size(1312, 369); + this.grid1.TabIndex = 21; + this.grid1.TabStop = true; + this.grid1.ToolTipText = ""; + this.grid1.DragDrop += new System.Windows.Forms.DragEventHandler(this.grid1_DragDrop); + this.grid1.DragEnter += new System.Windows.Forms.DragEventHandler(this.grid1_DragEnter); + this.grid1.DragOver += new System.Windows.Forms.DragEventHandler(this.grid1_DragOver); + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.tableLayoutPanel1.AutoSize = true; + this.tableLayoutPanel1.ColumnCount = 2; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 10.29685F)); + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 89.70316F)); + this.tableLayoutPanel1.Controls.Add(this.button_down, 1, 1); + this.tableLayoutPanel1.Controls.Add(this.button_up, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.groupBox2, 0, 0); + this.tableLayoutPanel1.Location = new System.Drawing.Point(3, 219); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 37F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(1324, 431); + this.tableLayoutPanel1.TabIndex = 26; + // + // button_down + // + this.button_down.Location = new System.Drawing.Point(138, 396); + this.button_down.Margin = new System.Windows.Forms.Padding(2); + this.button_down.Name = "button_down"; + this.button_down.Size = new System.Drawing.Size(102, 31); + this.button_down.TabIndex = 22; + this.button_down.Text = "Zoom Out"; + this.button_down.UseVisualStyleBackColor = true; + this.button_down.Click += new System.EventHandler(this.button_down_Click); + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.AutoSize = true; + this.tableLayoutPanel1.SetColumnSpan(this.groupBox2, 2); + this.groupBox2.Controls.Add(this.grid1); + this.groupBox2.Location = new System.Drawing.Point(3, 3); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(1318, 388); + this.groupBox2.TabIndex = 24; + this.groupBox2.TabStop = false; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.listView_TXPDO); + this.groupBox3.Location = new System.Drawing.Point(5, 7); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(593, 205); + this.groupBox3.TabIndex = 27; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Available Objects for PDO"; + // + // DevicePDOView2 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScroll = true; + this.AutoSize = true; + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.button_addPDO); + this.Controls.Add(this.button_savepdochanges); + this.Controls.Add(this.button_deletePDO); + this.Controls.Add(this.tableLayoutPanel1); + this.Margin = new System.Windows.Forms.Padding(2); + this.Name = "DevicePDOView2"; + this.Size = new System.Drawing.Size(1330, 741); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.contextMenuStrip_removeitem.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + } #endregion @@ -407,14 +453,11 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_cob; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label2; - private System.Windows.Forms.Label label_availableobjects; private System.Windows.Forms.ListView listView_TXPDO; private System.Windows.Forms.ColumnHeader columnHeader13; private System.Windows.Forms.ColumnHeader columnHeader15; private System.Windows.Forms.ColumnHeader columnHeader16; private System.Windows.Forms.ColumnHeader columnHeader17; - private SourceGrid.Grid grid1; - private System.Windows.Forms.Button button_down; private System.Windows.Forms.Button button_up; private System.Windows.Forms.ContextMenuStrip contextMenuStrip_removeitem; private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_removeitem; @@ -422,6 +465,11 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_mapping; private System.Windows.Forms.Label label1; private System.Windows.Forms.Button button_savepdochanges; - private System.Windows.Forms.ColumnHeader columnHeader1; + private System.Windows.Forms.ColumnHeader columnHeader1; + private SourceGrid.Grid grid1; + private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1; + private System.Windows.Forms.Button button_down; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.GroupBox groupBox3; } } diff --git a/EDSEditorGUI/DevicePDOView2.resx b/EDSEditorGUI/DevicePDOView2.resx index 00ddd377..b96e58f4 100644 --- a/EDSEditorGUI/DevicePDOView2.resx +++ b/EDSEditorGUI/DevicePDOView2.resx @@ -1,123 +1,123 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + \ No newline at end of file From 5f60e2ea853f9e6b8d7205872544c6fce5512525 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 19 Jan 2023 08:57:49 +0100 Subject: [PATCH 068/226] Trim defaultvalue before convert if $NODEID was removed ($NODEID could be at the beginning or end of the string) --- libEDSsharp/CanOpenNodeExporter.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 27a7e9bc..fa7a8528 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -1142,6 +1142,7 @@ string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring= { int nobase = 10; bool nodeidreplace = false; + if (defaultvalue == null || defaultvalue == "") { @@ -1166,6 +1167,7 @@ string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring= { defaultvalue = defaultvalue.Replace("$NODEID", ""); defaultvalue = defaultvalue.Replace("+", ""); + defaultvalue = defaultvalue.Trim(); nodeidreplace = true; } From d3e96315bb898a8895b81ccf406e5ba25c46dadc Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 30 Jan 2023 16:07:37 +0100 Subject: [PATCH 069/226] Add define for index in legacy header file CO_OD.h --- libEDSsharp/CanOpenNodeExporter.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index fa7a8528..55d29494 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -760,6 +760,7 @@ ALIASES FOR OBJECT DICTIONARY VARIABLES default: { file.WriteLine(string.Format("/*{0:X4}, Data Type: {1} */", od.Index, t.ToString())); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", make_cname(od.parameter_name,od)), loc, make_cname(od.parameter_name,od))); DataType dt = od.datatype; @@ -777,6 +778,7 @@ ALIASES FOR OBJECT DICTIONARY VARIABLES DataType dt = od.datatype; file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}, Array[{2}] */", od.Index, t.ToString(), od.Nosubindexes - 1)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); file.WriteLine(string.Format(" #define OD_{0,-48} {1}.{2}", make_cname(od.parameter_name,od), loc, make_cname(od.parameter_name,od))); file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_arrayLength", make_cname(od.parameter_name,od)), od.Nosubindexes - 1)); @@ -825,6 +827,7 @@ ALIASES FOR OBJECT DICTIONARY VARIABLES if (!constructed_rec_types.Contains(rectype)) { file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}_t */", od.Index, rectype)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", rectype), loc, rectype)); constructed_rec_types.Add(rectype); file.WriteLine(""); From 76baf61845d0dfeb26f36e7db8a07f2cc0f3d30b Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 20 Feb 2023 16:01:12 +0100 Subject: [PATCH 070/226] Update variable names and DCF output to DS306 conform capitalization NodeId => NodeID BaudRate => Baudrate --- EDSEditorGUI/DeviceInfoView.cs | 8 ++++---- EDSEditorGUI/DeviceView.resx | 2 +- libEDSsharp/Bridge.cs | 30 +++++++++++++++--------------- libEDSsharp/CanOpenNodeExporter.cs | 2 +- libEDSsharp/CanOpenXDD.cs | 10 +++++----- libEDSsharp/CanOpenXDD_1_1.cs | 10 +++++----- libEDSsharp/CanOpenXML.cs | 4 ++-- libEDSsharp/CanOpenXSD_1_1.cs | 2 +- libEDSsharp/NetworkPDOreport.cs | 6 +++--- libEDSsharp/eds.cs | 10 +++++----- 10 files changed, 42 insertions(+), 42 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index a1609ea2..31372a04 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -85,9 +85,9 @@ public void populatedeviceinfo() //DCF support if (eds.dc!=null) { - textBox_concretenodeid.Text = eds.dc.NodeId.ToString(); + textBox_concretenodeid.Text = eds.dc.NodeID.ToString(); textBox_nodename.Text = eds.dc.NodeName; - textBox_baudrate.Text = eds.dc.BaudRate.ToString(); + textBox_baudrate.Text = eds.dc.Baudrate.ToString(); textBox_netnum.Text = eds.dc.NetNumber.ToString(); checkBox_canopenmanager.Checked = eds.dc.CANopenManager; textBox_lssserial.Text = eds.dc.LSS_SerialNumber.ToString(); @@ -164,9 +164,9 @@ private void button_update_devfile_info_Click(object sender, EventArgs e) //textBox_txpdos.Text = eds.di.NrOfTXPDO.ToString(); //DCF support - eds.dc.NodeId = Convert.ToByte(textBox_concretenodeid.Text); + eds.dc.NodeID = Convert.ToByte(textBox_concretenodeid.Text); eds.dc.NodeName = textBox_nodename.Text; - eds.dc.BaudRate = Convert.ToUInt16(textBox_baudrate.Text); + eds.dc.Baudrate = Convert.ToUInt16(textBox_baudrate.Text); eds.dc.NetNumber = Convert.ToUInt32(textBox_netnum.Text); eds.dc.CANopenManager = checkBox_canopenmanager.Checked; eds.dc.LSS_SerialNumber = Convert.ToUInt32(textBox_lssserial.Text); diff --git a/EDSEditorGUI/DeviceView.resx b/EDSEditorGUI/DeviceView.resx index 12ab17e0..76c87766 100644 --- a/EDSEditorGUI/DeviceView.resx +++ b/EDSEditorGUI/DeviceView.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACk - CgAAAk1TRnQBSQFMAgEBBAEAAVABAAFQAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CgAAAk1TRnQBSQFMAgEBBAEAAVgBAAFYAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/libEDSsharp/Bridge.cs b/libEDSsharp/Bridge.cs index 56b52ed1..de0ad2b2 100644 --- a/libEDSsharp/Bridge.cs +++ b/libEDSsharp/Bridge.cs @@ -158,47 +158,47 @@ public Device convert(EDSsharp eds) Xml2CSharp.SupportedBaudRate baud = new Xml2CSharp.SupportedBaudRate(); - dev.Other.BaudRate = new Xml2CSharp.BaudRate(); - dev.Other.BaudRate.SupportedBaudRate = new List(); + dev.Other.Baudrate = new Xml2CSharp.Baudrate(); + dev.Other.Baudrate.SupportedBaudRate = new List(); baud.Value = "10 Kbps"; if (eds.di.BaudRate_10 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); baud = new Xml2CSharp.SupportedBaudRate(); baud.Value = "20 Kbps"; if (eds.di.BaudRate_20 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); baud = new Xml2CSharp.SupportedBaudRate(); baud.Value = "50 Kbps"; if (eds.di.BaudRate_50 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); baud = new Xml2CSharp.SupportedBaudRate(); baud.Value = "125 Kbps"; if (eds.di.BaudRate_125 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); baud = new Xml2CSharp.SupportedBaudRate(); baud.Value = "250 Kbps"; if (eds.di.BaudRate_250 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); baud = new Xml2CSharp.SupportedBaudRate(); baud.Value = "500 Kbps"; if (eds.di.BaudRate_500 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); baud = new Xml2CSharp.SupportedBaudRate(); baud.Value = "800 Kbps"; if (eds.di.BaudRate_800 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); baud = new Xml2CSharp.SupportedBaudRate(); baud.Value = "1000 Kbps"; if (eds.di.BaudRate_1000 == true) - dev.Other.BaudRate.SupportedBaudRate.Add(baud); + dev.Other.Baudrate.SupportedBaudRate.Add(baud); dev.Other.Capabilities = new Xml2CSharp.Capabilities(); @@ -224,8 +224,8 @@ public Device convert(EDSsharp eds) dev.Other.DeviceIdentity.ProductText.Description.Text = eds.fi.Description; - if (eds.dc.NodeId != 0) - dev.Other.DeviceIdentity.ConcreteNoideId = eds.dc.NodeId.ToString(); + if (eds.dc.NodeID != 0) + dev.Other.DeviceIdentity.ConcreteNoideId = eds.dc.NodeID.ToString(); dev.Other.DeviceIdentity.VendorName = eds.di.VendorName; dev.Other.DeviceIdentity.VendorNumber = eds.di.VendorNumber; @@ -431,7 +431,7 @@ public EDSsharp convert(Device dev) eds.du.Dummy0006 = dev.Other.DummyUsage.Dummy[5].Entry == "Dummy0006=1"; eds.du.Dummy0007 = dev.Other.DummyUsage.Dummy[6].Entry == "Dummy0007=1"; - foreach (Xml2CSharp.SupportedBaudRate baud in dev.Other.BaudRate.SupportedBaudRate) + foreach (Xml2CSharp.SupportedBaudRate baud in dev.Other.Baudrate.SupportedBaudRate) { if (baud.Value == "10 Kbps") eds.di.BaudRate_10 = true; @@ -506,11 +506,11 @@ public EDSsharp convert(Device dev) if (dev.Other.DeviceIdentity.ConcreteNoideId != null) { - eds.dc.NodeId = Convert.ToByte(dev.Other.DeviceIdentity.ConcreteNoideId); + eds.dc.NodeID = Convert.ToByte(dev.Other.DeviceIdentity.ConcreteNoideId); } else { - eds.dc.NodeId = 0; + eds.dc.NodeID = 0; } string dtcombined; diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 55d29494..350aad34 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -1195,7 +1195,7 @@ string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring= if (nodeidreplace) { UInt32 data = Convert.ToUInt32(defaultvalue.Trim(), nobase); - data += eds.NodeId; + data += eds.NodeID; defaultvalue = string.Format("0x{0:X}", data); nobase = 16; } diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index ad116a22..f35afc97 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -660,8 +660,8 @@ public ISO15745ProfileContainer convert(EDSsharp eds) NetworkManagement.deviceCommissioning = new ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning(); - NetworkManagement.deviceCommissioning.actualBaudRate = eds.dc.BaudRate.ToString(); - NetworkManagement.deviceCommissioning.nodeID = eds.dc.NodeId; + NetworkManagement.deviceCommissioning.actualBaudRate = eds.dc.Baudrate.ToString(); + NetworkManagement.deviceCommissioning.NodeID = eds.dc.NodeID; NetworkManagement.deviceCommissioning.networkName = eds.dc.NetworkName; NetworkManagement.deviceCommissioning.networkNumber = eds.dc.NetNumber; NetworkManagement.deviceCommissioning.CANopenManager = eds.dc.CANopenManager; @@ -923,8 +923,8 @@ public EDSsharp convert(ISO15745ProfileContainer container) if (NetworkManagment.deviceCommissioning != null) { - eds.dc.NodeId = NetworkManagment.deviceCommissioning.nodeID; - eds.dc.BaudRate = Convert.ToUInt16(NetworkManagment.deviceCommissioning.actualBaudRate); + eds.dc.NodeID = NetworkManagment.deviceCommissioning.NodeID; + eds.dc.Baudrate = Convert.ToUInt16(NetworkManagment.deviceCommissioning.actualBaudRate); eds.dc.CANopenManager = NetworkManagment.deviceCommissioning.CANopenManager; eds.dc.NetworkName = NetworkManagment.deviceCommissioning.networkName; eds.dc.NetNumber = Convert.ToUInt16(NetworkManagment.deviceCommissioning.networkNumber); @@ -4100,7 +4100,7 @@ public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementDe /// [System.Xml.Serialization.XmlAttributeAttribute()] - public byte nodeID + public byte NodeID { get { diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 1a6df8e9..4115e4db 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -788,9 +788,9 @@ private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool dev { NetworkManagement.deviceCommissioning = new ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning { - nodeID = eds.dc.NodeId, + NodeID = eds.dc.NodeID, nodeName = eds.dc.NodeName, - actualBaudRate = eds.dc.BaudRate.ToString(), + actualBaudRate = eds.dc.Baudrate.ToString(), networkNumber = eds.dc.NetNumber, networkName = eds.dc.NetworkName, CANopenManager = eds.dc.CANopenManager @@ -942,9 +942,9 @@ private EDSsharp Convert(ISO15745ProfileContainer container) if (NetworkManagement.deviceCommissioning != null) { - eds.dc.NodeId = NetworkManagement.deviceCommissioning.nodeID; - try { eds.dc.BaudRate = System.Convert.ToUInt16(NetworkManagement.deviceCommissioning.actualBaudRate); } - catch (Exception) { eds.dc.BaudRate = 0; } + eds.dc.NodeID = NetworkManagement.deviceCommissioning.NodeID; + try { eds.dc.Baudrate = System.Convert.ToUInt16(NetworkManagement.deviceCommissioning.actualBaudRate); } + catch (Exception) { eds.dc.Baudrate = 0; } eds.dc.CANopenManager = NetworkManagement.deviceCommissioning.CANopenManager; eds.dc.NetworkName = NetworkManagement.deviceCommissioning.networkName; try { eds.dc.NetNumber = System.Convert.ToUInt16(NetworkManagement.deviceCommissioning.networkNumber); } diff --git a/libEDSsharp/CanOpenXML.cs b/libEDSsharp/CanOpenXML.cs index f6e20afd..d80da611 100644 --- a/libEDSsharp/CanOpenXML.cs +++ b/libEDSsharp/CanOpenXML.cs @@ -281,7 +281,7 @@ public class SupportedBaudRate { } [XmlRoot(ElementName="baudRate")] - public class BaudRate { + public class Baudrate { [XmlElement(ElementName="supportedBaudRate")] public List SupportedBaudRate { get; set; } } @@ -307,7 +307,7 @@ public class Other { [XmlElement(ElementName="capabilities")] public Capabilities Capabilities { get; set; } [XmlElement(ElementName="baudRate")] - public BaudRate BaudRate { get; set; } + public Baudrate Baudrate { get; set; } [XmlElement(ElementName="dummyUsage")] public DummyUsage DummyUsage { get; set; } } diff --git a/libEDSsharp/CanOpenXSD_1_1.cs b/libEDSsharp/CanOpenXSD_1_1.cs index 639b88f4..8a91b4a3 100644 --- a/libEDSsharp/CanOpenXSD_1_1.cs +++ b/libEDSsharp/CanOpenXSD_1_1.cs @@ -2691,7 +2691,7 @@ public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementDe /// [System.Xml.Serialization.XmlAttributeAttribute()] - public byte nodeID { + public byte NodeID { get { return this.nodeIDField; } diff --git a/libEDSsharp/NetworkPDOreport.cs b/libEDSsharp/NetworkPDOreport.cs index be0883db..484f598a 100644 --- a/libEDSsharp/NetworkPDOreport.cs +++ b/libEDSsharp/NetworkPDOreport.cs @@ -44,7 +44,7 @@ public void gennetpdodoc(string filepath, List network) foreach (EDSsharp eds in network) { - write2linetablerow(eds.dc.NodeId.ToString(), eds.di.ProductName); + write2linetablerow(eds.dc.NodeID.ToString(), eds.di.ProductName); } file.Write(""); @@ -165,7 +165,7 @@ public void gennetpdodoc(string filepath, List network) } - file.Write(string.Format(" 0x{0:x2} {1} 0x{2:x4}/0x{3:x2}{4} {5}", eds.dc.NodeId, eds.di.ProductName, index, subindex, name, size)); + file.Write(string.Format(" 0x{0:x2} {1} 0x{2:x4}/0x{3:x2}{4} {5}", eds.dc.NodeID, eds.di.ProductName, index, subindex, name, size)); //find all receivers here @@ -279,7 +279,7 @@ public void gennetpdodoc(string filepath, List network) } - file.Write(string.Format(" 0x{0:x2} {1} 0x{2:x4}/0x{3:x2} {4}{5}{6}", eds2.dc.NodeId, eds2.di.ProductName, index2, subindex2, name2, size2, sizemsg)); + file.Write(string.Format(" 0x{0:x2} {1} 0x{2:x4}/0x{3:x2} {4}{5}{6}", eds2.dc.NodeID, eds2.di.ProductName, index2, subindex2, name2, size2, sizemsg)); } diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index d6dfa87f..3ab925b3 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -822,13 +822,13 @@ public DeviceCommissioning(Dictionary section) : this() } [DcfExport] - public byte NodeId = 0; + public byte NodeID = 0; [DcfExport(maxlength = 246)] public string NodeName = ""; //Max 246 characters [DcfExport] - public UInt16 BaudRate; + public UInt16 Baudrate; [DcfExport] public UInt32 NetNumber; @@ -1904,7 +1904,7 @@ public bool Dirty public Dictionary modules; - public UInt16 NodeId = 0; + public UInt16 NodeID = 0; public delegate void DataDirty(bool dirty, EDSsharp sender); public event DataDirty OnDataDirty; @@ -2930,7 +2930,7 @@ public UInt32 GetNodeID(string input, out bool nodeidpresent) try { - if (dc.NodeId == 0) + if (dc.NodeID == 0) { input = input.Replace("$NODEID", ""); input = input.Replace("+", ""); @@ -2938,7 +2938,7 @@ public UInt32 GetNodeID(string input, out bool nodeidpresent) return Convert.ToUInt32(input.Trim(), Getbase(input)); } - input = input.Replace("$NODEID", dc.NodeId.ToString()); // dc.NodeID is decimal + input = input.Replace("$NODEID", dc.NodeID.ToString()); // dc.NodeID is decimal string[] bits = Array.ConvertAll(input.Split('+'), p => p.Trim()); // Split and Trim the value if (bits.Length==1) { From 5b7f3f506c5344bf64c4d0fe60b0402620572da7 Mon Sep 17 00:00:00 2001 From: Janez Date: Thu, 16 Mar 2023 19:19:05 +0100 Subject: [PATCH 071/226] CANopenNode exporter V4: Fix mess with Count Labels. User has to provide correct Count Labels, as specified in https://github.com/CANopenNode/CANopenNode/blob/master/doc/objectDictionary.md Object Dictionary Requirements By CANopenNode V4. Otherwise warning is shown. Previously Count Labels were added automatically if missing. This was confusing and is now removed. --- libEDSsharp/CanOpenNodeExporter_V4.cs | 114 +++++++++----------------- libEDSsharp/docs/libEDSsharp.xml | 14 +++- 2 files changed, 50 insertions(+), 78 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 46d57a30..bd35830e 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -46,22 +46,6 @@ public class CanOpenNodeExporter_V4 : IExporter private Dictionary ODCnt; private Dictionary ODArrSize; - UInt16 CNT_NMT = 0; - UInt16 CNT_HB_CONS = 0; - UInt16 CNT_EM = 0; - UInt16 CNT_SDO_SRV = 0; - UInt16 CNT_SDO_CLI = 0; - UInt16 CNT_TIME = 0; - UInt16 CNT_SYNC = 0; - UInt16 CNT_RPDO = 0; - UInt16 CNT_TPDO = 0; - UInt16 CNT_GFC = 0; - UInt16 CNT_SRDO = 0; - UInt16 CNT_STORAGE = 0; - UInt16 CNT_EM_PROD = 0; - UInt16 CNT_SYNC_PROD = 0; - UInt16 CNT_HB_PROD = 0; - /// /// export the current data set in the CanOpen Node format V4 /// @@ -106,38 +90,7 @@ private void Prepare(EDSsharp eds) { if (od.prop.CO_disabled == true) continue; - // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. - // Count objects for initialization of CO_config_t object. - if (od.Index==0x1017) - CNT_NMT++; - if (od.Index==0x1016) - CNT_HB_CONS++; - if ((od.Index==0x1014 || od.Index==0x1015) && CNT_EM==0) - CNT_EM++; - if (od.Index>=0x1200 && od.Index<0x1280) - CNT_SDO_SRV++; - if (od.Index>=0x1280 && od.Index<0x1300) - CNT_SDO_CLI++; - if (od.Index==0x1012) - CNT_TIME++; - if (od.Index==0x1005) - CNT_SYNC++; - if (od.Index>=0x1400 && od.Index<0x1500) - CNT_RPDO++; - if (od.Index>=0x1800 && od.Index<0x1900) - CNT_TPDO++; - if (od.Index==0x1300) - CNT_GFC++; - if (od.Index>=0x1301 && od.Index<0x1380) - CNT_SRDO++; - if (od.Index==0x1010) - CNT_STORAGE++; - if (od.Index==0x1014) - CNT_EM_PROD++; - if (od.Index==0x1006) - CNT_SYNC_PROD++; - if (od.Index == 0x1006) - CNT_HB_PROD++; + string indexH = $"{od.Index:X4}"; string cName = Make_cname(od.parameter_name); string varName = $"{indexH}_{cName}"; @@ -157,17 +110,17 @@ private void Prepare(EDSsharp eds) switch (od.objecttype) { case ObjectType.VAR: - odObjectType = ObjectType.VAR.ToString(); + odObjectType = "VAR"; subEntriesCount = Prepare_var(od, indexH, varName, od.prop.CO_storageGroup); break; case ObjectType.ARRAY: - odObjectType = ObjectType.ARRAY.ToString(); + odObjectType = "ARR"; subEntriesCount = Prepare_arr(od, indexH, varName, od.prop.CO_storageGroup); break; case ObjectType.RECORD: - odObjectType = ObjectType.RECORD.ToString(); + odObjectType = "REC"; subEntriesCount = Prepare_rec(od, indexH, varName, od.prop.CO_storageGroup); break; } @@ -180,9 +133,6 @@ private void Prepare(EDSsharp eds) ODDefinesLong.Add($"#define {odname}_ENTRY_H{varName} &{odname}->list[{ODList.Count}]"); // object dictionary - if ((odObjectType == "ARRAY") || (odObjectType) == "RECORD") - odObjectType = odObjectType.Substring(0, 3); - ODList.Add($"{{0x{indexH}, 0x{subEntriesCount:X2}, ODT_{odObjectType}, &{odname}Objs.o_{varName}, NULL}}"); // count labels @@ -193,25 +143,40 @@ private void Prepare(EDSsharp eds) else ODCnt.Add(od.prop.CO_countLabel, 1); } + + // Verify objects, if they have set correct "CO_countLabel", according to Object Dictionary Requirements By CANopenNode V4. + // https://github.com/CANopenNode/CANopenNode/blob/master/doc/objectDictionary.md + VerifyCountLabel(od, 0x1000, 0x1000, "NMT"); + VerifyCountLabel(od, 0x1001, 0x1001, "EM"); + VerifyCountLabel(od, 0x1005, 0x1005, "SYNC"); + VerifyCountLabel(od, 0x1006, 0x1006, "SYNC_PROD"); + VerifyCountLabel(od, 0x1010, 0x1010, "STORAGE"); + VerifyCountLabel(od, 0x1012, 0x1012, "TIME"); + VerifyCountLabel(od, 0x1014, 0x1014, "EM_PROD"); + VerifyCountLabel(od, 0x1016, 0x1016, "HB_CONS"); + VerifyCountLabel(od, 0x1017, 0x1017, "HB_PROD"); + VerifyCountLabel(od, 0x1200, 0x127F, "SDO_SRV"); + VerifyCountLabel(od, 0x1280, 0x12FF, "SDO_CLI"); + VerifyCountLabel(od, 0x1300, 0x1300, "GFC"); + VerifyCountLabel(od, 0x1301, 0x1340, "SRDO"); + VerifyCountLabel(od, 0x1400, 0x15FF, "RPDO"); + VerifyCountLabel(od, 0x1800, 0x19FF, "TPDO"); } - CNT_SRDO=(UInt16)(CNT_SRDO/2); - // The code below is nessesary if you have old eds file, that do not have "CO_countLabel" set. - if (ODCnt.Count==0) { - ODCnt.Add("HB_CONS", CNT_HB_CONS); - ODCnt.Add("NMT", CNT_NMT); - ODCnt.Add("EM", CNT_EM); - ODCnt.Add("SDO_SRV", CNT_SDO_SRV); - ODCnt.Add("SDO_CLI", CNT_SDO_CLI); - ODCnt.Add("TIME", CNT_TIME); - ODCnt.Add("SYNC", CNT_SYNC); - ODCnt.Add("RPDO", CNT_RPDO); - ODCnt.Add("TPDO", CNT_TPDO); - ODCnt.Add("GFC", CNT_GFC); - ODCnt.Add("SRDO", CNT_SRDO); - ODCnt.Add("STORAGE", CNT_STORAGE); - ODCnt.Add("EM_PROD", CNT_EM_PROD); - ODCnt.Add("SYNC_PROD", CNT_SYNC_PROD); - ODCnt.Add("HB_PROD", CNT_HB_PROD); + } + + /// + /// Verify "Count Label" of the object and raise warning if uncorrect. + /// + /// + /// + /// + /// + /// + private void VerifyCountLabel(ODentry od, ushort indexL, ushort indexH, string countLabel) + { + if (od.Index >= indexL && od.Index <= indexH && od.prop.CO_countLabel != countLabel) + { + Warnings.AddWarning($"Error in 0x{od.Index:X4}: 'Count Label' must be '{countLabel}'", Warnings.warning_class.WARNING_BUILD); } } @@ -532,6 +497,7 @@ Object dictionary entries - shortcuts with names *******************************************************************************/ {0}", string.Join("\n", ODDefinesLong))); + // following code initializes CO_config_t structure as specified in file CANopenNode/CANopen.h file.WriteLine($@" /******************************************************************************* @@ -575,10 +541,6 @@ OD config structure (config).ENTRY_H1381 = {(eds.ods.ContainsKey(0x1381) ? odname + "_ENTRY_H1381" : "NULL")};\ (config).ENTRY_H13FE = {(eds.ods.ContainsKey(0x13FE) ? odname + "_ENTRY_H13FE" : "NULL")};\ (config).ENTRY_H13FF = {(eds.ods.ContainsKey(0x13FF) ? odname + "_ENTRY_H13FF" : "NULL")};\ - (config).CNT_GFC = {(ODCnt.ContainsKey("STORAGE") ? odname + "_CNT_STORAGE" : "0")};\ - (config).CNT_GFC = {(ODCnt.ContainsKey("EM_PROD") ? odname + "_EM_PROD" : "0")};\ - (config).CNT_GFC = {(ODCnt.ContainsKey("SYNC_PROD") ? odname + "_SYNC_PROD" : "0")};\ - (config).CNT_GFC = {(ODCnt.ContainsKey("HB_PROD") ? odname + "_HB_PROD" : "0")};\ (config).CNT_LSS_SLV = 0;\ (config).CNT_LSS_MST = 0;\ (config).CNT_GTWA = 0;\ diff --git a/libEDSsharp/docs/libEDSsharp.xml b/libEDSsharp/docs/libEDSsharp.xml index 4aaab1ea..564dab42 100644 --- a/libEDSsharp/docs/libEDSsharp.xml +++ b/libEDSsharp/docs/libEDSsharp.xml @@ -25,6 +25,16 @@ + + + Verify "Count Label" of the object and raise warning if uncorrect. + + + + + + + Generate ODStorage and ODObjs entries for VAR @@ -979,7 +989,7 @@ - + @@ -3394,7 +3404,7 @@ - + From a2f6414f793b334a745bcf4cf41bc7100838ac63 Mon Sep 17 00:00:00 2001 From: Janez Date: Thu, 16 Mar 2023 19:21:50 +0100 Subject: [PATCH 072/226] DS301_profile: Fixed Object dictionary mapping direction in 0x1001 --- EDSEditorGUI/Profiles/DS301_profile.xpd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 690bc4b2..913bd715 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -1,5 +1,5 @@ - + @@ -15,7 +15,7 @@ CANopen - + @@ -2277,11 +2277,11 @@ CANopen - + - + From 32ef9ebae8ecb54263f87409744a70c4d603a64c Mon Sep 17 00:00:00 2001 From: Janez Date: Thu, 16 Mar 2023 22:48:15 +0100 Subject: [PATCH 073/226] Issue #47 fixed: Saving after editing PDO Mappings is now correct. --- EDSEditorGUI/DevicePDOView2.Designer.cs | 53 +++++++------- EDSEditorGUI/DevicePDOView2.cs | 18 +++-- Tests/PDOHelperTests.cs | 4 +- libEDSsharp/PDOHelper.cs | 94 ++++++++++++++++--------- libEDSsharp/docs/libEDSsharp.xml | 2 +- 5 files changed, 100 insertions(+), 71 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.Designer.cs b/EDSEditorGUI/DevicePDOView2.Designer.cs index 7da61e86..6fe459f2 100644 --- a/EDSEditorGUI/DevicePDOView2.Designer.cs +++ b/EDSEditorGUI/DevicePDOView2.Designer.cs @@ -34,8 +34,6 @@ private void InitializeComponent() this.textBox_mapping = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.checkBox_invalidpdo = new System.Windows.Forms.CheckBox(); - this.button_savepdochanges = new System.Windows.Forms.Button(); - this.button_deletePDO = new System.Windows.Forms.Button(); this.textBox_slot = new System.Windows.Forms.TextBox(); this.textBox_syncstart = new System.Windows.Forms.TextBox(); this.textBox_eventtimer = new System.Windows.Forms.TextBox(); @@ -48,6 +46,8 @@ private void InitializeComponent() this.textBox_cob = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); + this.button_savepdochanges = new System.Windows.Forms.Button(); + this.button_deletePDO = new System.Windows.Forms.Button(); this.listView_TXPDO = new System.Windows.Forms.ListView(); this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); this.columnHeader15 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); @@ -134,30 +134,6 @@ private void InitializeComponent() this.checkBox_invalidpdo.UseVisualStyleBackColor = true; this.checkBox_invalidpdo.CheckedChanged += new System.EventHandler(this.checkBox_invalidpdo_CheckedChanged); // - // button_savepdochanges - // - this.button_savepdochanges.Image = global::ODEditor.Properties.Resources.Save_6530; - this.button_savepdochanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_savepdochanges.Location = new System.Drawing.Point(912, 177); - this.button_savepdochanges.Name = "button_savepdochanges"; - this.button_savepdochanges.Size = new System.Drawing.Size(101, 27); - this.button_savepdochanges.TabIndex = 8; - this.button_savepdochanges.Text = "Save "; - this.button_savepdochanges.UseVisualStyleBackColor = true; - this.button_savepdochanges.Click += new System.EventHandler(this.button_savepdochanges_Click_1); - // - // button_deletePDO - // - this.button_deletePDO.Image = global::ODEditor.Properties.Resources.Remove_16xLG; - this.button_deletePDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_deletePDO.Location = new System.Drawing.Point(912, 138); - this.button_deletePDO.Name = "button_deletePDO"; - this.button_deletePDO.Size = new System.Drawing.Size(101, 27); - this.button_deletePDO.TabIndex = 7; - this.button_deletePDO.Text = "Delete PDO"; - this.button_deletePDO.UseVisualStyleBackColor = true; - this.button_deletePDO.Click += new System.EventHandler(this.button_deletePDO_Click); - // // textBox_slot // this.textBox_slot.Location = new System.Drawing.Point(98, 20); @@ -254,6 +230,30 @@ private void InitializeComponent() this.label2.TabIndex = 0; this.label2.Text = "Communication"; // + // button_savepdochanges + // + this.button_savepdochanges.Image = global::ODEditor.Properties.Resources.Save_6530; + this.button_savepdochanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_savepdochanges.Location = new System.Drawing.Point(912, 177); + this.button_savepdochanges.Name = "button_savepdochanges"; + this.button_savepdochanges.Size = new System.Drawing.Size(101, 27); + this.button_savepdochanges.TabIndex = 8; + this.button_savepdochanges.Text = "Save "; + this.button_savepdochanges.UseVisualStyleBackColor = true; + this.button_savepdochanges.Click += new System.EventHandler(this.button_savepdochanges_Click_1); + // + // button_deletePDO + // + this.button_deletePDO.Image = global::ODEditor.Properties.Resources.Remove_16xLG; + this.button_deletePDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_deletePDO.Location = new System.Drawing.Point(912, 138); + this.button_deletePDO.Name = "button_deletePDO"; + this.button_deletePDO.Size = new System.Drawing.Size(101, 27); + this.button_deletePDO.TabIndex = 7; + this.button_deletePDO.Text = "Delete PDO"; + this.button_deletePDO.UseVisualStyleBackColor = true; + this.button_deletePDO.Click += new System.EventHandler(this.button_deletePDO_Click); + // // listView_TXPDO // this.listView_TXPDO.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { @@ -272,6 +272,7 @@ private void InitializeComponent() this.listView_TXPDO.UseCompatibleStateImageBehavior = false; this.listView_TXPDO.View = System.Windows.Forms.View.Details; this.listView_TXPDO.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.listView_TXPDO_ItemDrag); + this.listView_TXPDO.SelectedIndexChanged += new System.EventHandler(this.listView_TXPDO_SelectedIndexChanged); // // columnHeader13 // diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 5ca42faa..ba73ed6a 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -109,7 +109,7 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte } - helper.buildmappingsfromlists(); + helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); UpdatePDOinfo(); @@ -154,7 +154,7 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) slot.Mapping[location.ordinal] = newentry; } - helper.buildmappingsfromlists(); + helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); doUpdateOD(); UpdatePDOinfo(); @@ -688,7 +688,7 @@ private void grid1_DragDrop(object sender, DragEventArgs e) location.slot.insertMapping(location.ordinal, entry); } - helper.buildmappingsfromlists(); + helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); UpdatePDOinfo(false); //dont cause the list to refresh } @@ -723,7 +723,7 @@ private void button_deletePDO_Click(object sender, EventArgs e) helper.pdoslots.Remove(selectedslot); - helper.buildmappingsfromlists(); + helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); doUpdateOD(); UpdatePDOinfo(); @@ -744,7 +744,7 @@ private void addnewPDO() UInt16 slot = helper.findPDOslotgap(isTXPDO); helper.addPDOslot(slot); - helper.buildmappingsfromlists(); + helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); doUpdateOD(); UpdatePDOinfo(); } @@ -801,7 +801,7 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) try { - helper.buildmappingsfromlists(); + helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); } catch (Exception ex) { @@ -810,8 +810,12 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) doUpdateOD(); UpdatePDOinfo(); + } + + private void listView_TXPDO_SelectedIndexChanged(object sender, EventArgs e) + { + } - } } \ No newline at end of file diff --git a/Tests/PDOHelperTests.cs b/Tests/PDOHelperTests.cs index bcc59716..6db83077 100644 --- a/Tests/PDOHelperTests.cs +++ b/Tests/PDOHelperTests.cs @@ -36,7 +36,7 @@ public void Test_TPDO() tryGetODEntry(0x0004, out od); slot.Mapping.Add(od); - pdo.buildmappingsfromlists(); + pdo.buildmappingsfromlists(true); //check configuration object exists ODentry comparamOD; @@ -115,7 +115,7 @@ public void Test_RPDO() tryGetODEntry(0x0004, out od); slot.Mapping.Add(od); - pdo.buildmappingsfromlists(); + pdo.buildmappingsfromlists(true); //check configuration object exists ODentry comparamOD; diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 02569280..daa03ba3 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -82,7 +82,8 @@ public bool invalid public UInt16 eventtimer; public byte syncstart; public byte transmissiontype; - public string Description; + public string DescriptionComm; + public string DescriptionMap; public PDOSlot() { @@ -90,8 +91,9 @@ public PDOSlot() mappingloc = "PERSIST_COMM"; transmissiontype = 254; Mapping = new List(); - Description = ""; - } + DescriptionComm = ""; + DescriptionMap = ""; + } public string getTargetName(ODentry od) { @@ -206,7 +208,7 @@ public void build_PDOlist(UInt16 startcob, List slots) slot.configAccessType = od.accesstype; slot.configloc = od.prop.CO_storageGroup; - slot.Description = od.Description; + slot.DescriptionComm = od.Description; Console.WriteLine(String.Format("Found PDO Entry {0:x4} {1:x3}", idx, slot.COB)); @@ -214,6 +216,7 @@ public void build_PDOlist(UInt16 startcob, List slots) //Look at mappings ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); + slot.DescriptionMap = mapping.Description; if(mapping==null) { Console.WriteLine(string.Format("No mapping for index 0x{0:x4} should be at 0x{1:x4}", idx, idx + 0x200)); @@ -294,7 +297,7 @@ public void build_PDOlist(UInt16 startcob, List slots) /// Rebuild the communication and mapping paramaters from the /// lists the PDOhelper currently has. These live in the list pdoslots /// - public void buildmappingsfromlists() + public void buildmappingsfromlists(bool isCANopenNode_V4) { for(ushort x=0x1400;x<0x1c00;x++) { @@ -309,51 +312,53 @@ public void buildmappingsfromlists() config.Index = slot.ConfigurationIndex; config.datatype = DataType.PDO_COMMUNICATION_PARAMETER; config.objecttype = ObjectType.RECORD; - - ODentry sub = new ODentry("max sub-index", (ushort)slot.ConfigurationIndex, 0); - sub.defaultvalue = slot.isTXPDO()? "6" : "5";// max supported sub index TPDO=6, RPDO=5 according DS301 - sub.datatype = DataType.UNSIGNED8; - sub.accesstype = EDSsharp.AccessType.ro; - config.addsubobject(0x00,sub); - config.accesstype = slot.configAccessType; config.prop.CO_storageGroup = slot.configloc; - config.Description = slot.Description; + config.Description = slot.DescriptionComm; + ODentry sub; if (slot.isTXPDO()) { - config.parameter_name = "TPDO communication parameter"; - config.prop.CO_countLabel = "TPDO"; + config.prop.CO_countLabel = "TPDO"; + + sub = new ODentry("Highest sub-index supported", (ushort)slot.ConfigurationIndex, 0); + sub.defaultvalue = "0x06"; + sub.datatype = DataType.UNSIGNED8; + sub.accesstype = EDSsharp.AccessType.ro; + config.addsubobject(0x00, sub); sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; if (slot.nodeidpresent) - sub.defaultvalue = "$NODEID + "; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. + sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. sub.defaultvalue += slot.COB.ToHexString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); - sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); + sub = new ODentry("Transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); - sub = new ODentry("inhibit time", (ushort)slot.ConfigurationIndex, 3); + sub = new ODentry("Inhibit time", (ushort)slot.ConfigurationIndex, 3); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.inhibit.ToString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x03, sub); - sub = new ODentry("compatibility entry", (ushort)slot.ConfigurationIndex, 4); - sub.datatype = DataType.UNSIGNED8; - sub.defaultvalue = "0"; - sub.accesstype = EDSsharp.AccessType.rw; - config.addsubobject(0x04, sub); - - sub = new ODentry("event timer", (ushort)slot.ConfigurationIndex, 5); + if (!isCANopenNode_V4) + { + sub = new ODentry("compatibility entry", (ushort)slot.ConfigurationIndex, 4); + sub.datatype = DataType.UNSIGNED8; + sub.defaultvalue = "0"; + sub.accesstype = EDSsharp.AccessType.rw; + config.addsubobject(0x04, sub); + } + + sub = new ODentry("Event timer", (ushort)slot.ConfigurationIndex, 5); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.eventtimer.ToString(); sub.accesstype = EDSsharp.AccessType.rw; @@ -369,27 +374,36 @@ public void buildmappingsfromlists() else { config.parameter_name = "RPDO communication parameter"; - config.prop.CO_countLabel = "RPDO"; + config.prop.CO_countLabel = "RPDO"; + + sub = new ODentry("Highest sub-index supported", (ushort)slot.ConfigurationIndex, 0); + sub.defaultvalue = isCANopenNode_V4 ? "0x05" : "0x02"; + sub.datatype = DataType.UNSIGNED8; + sub.accesstype = EDSsharp.AccessType.ro; + config.addsubobject(0x00, sub); sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); sub.datatype = DataType.UNSIGNED32; if (slot.nodeidpresent) - sub.defaultvalue = "$NODEID + "; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. + sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. sub.defaultvalue += slot.COB.ToHexString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); - sub = new ODentry("transmission type", (ushort)slot.ConfigurationIndex, 2); + sub = new ODentry("Transmission type", (ushort)slot.ConfigurationIndex, 2); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x02, sub); - sub = new ODentry("event timer", (ushort)slot.ConfigurationIndex, 5); - sub.datatype = DataType.UNSIGNED16; - sub.defaultvalue = slot.eventtimer.ToString(); - sub.accesstype = EDSsharp.AccessType.rw; - config.addsubobject(0x05, sub); + if (isCANopenNode_V4) + { + sub = new ODentry("Event timer", (ushort)slot.ConfigurationIndex, 5); + sub.datatype = DataType.UNSIGNED16; + sub.defaultvalue = slot.eventtimer.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; + config.addsubobject(0x05, sub); + } } eds.ods.Add(slot.ConfigurationIndex,config); @@ -406,8 +420,9 @@ public void buildmappingsfromlists() mapping.prop.CO_storageGroup = slot.mappingloc; mapping.accesstype = slot.mappingAccessType; + mapping.Description = slot.DescriptionMap; - sub = new ODentry("Number of mapped objects", (ushort)slot.MappingIndex, 0); + sub = new ODentry("Number of mapped application objects in PDO", (ushort)slot.MappingIndex, 0); sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.Mapping.Count().ToString(); sub.accesstype = EDSsharp.AccessType.rw; @@ -416,7 +431,7 @@ public void buildmappingsfromlists() byte mappingcount = 1; foreach (ODentry mapslot in slot.Mapping) { - sub = new ODentry(String.Format("Mapped object {0:x}",mappingcount), (ushort)slot.MappingIndex, mappingcount); + sub = new ODentry(String.Format("Application object {0:x}", mappingcount), (ushort)slot.MappingIndex, mappingcount); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = string.Format("0x{0:x4}{1:x2}{2:x2}", mapslot.Index, mapslot.Subindex, mapslot.Sizeofdatatype()); sub.accesstype = EDSsharp.AccessType.rw; @@ -425,6 +440,15 @@ public void buildmappingsfromlists() mappingcount++; } + + for (; mappingcount <= 8; mappingcount++) + { + sub = new ODentry(String.Format("Application object {0:x}", mappingcount), (ushort)slot.MappingIndex, mappingcount); + sub.datatype = DataType.UNSIGNED32; + sub.defaultvalue = "0x00000000"; + sub.accesstype = EDSsharp.AccessType.rw; + mapping.addsubobject(mappingcount, sub); + } eds.ods.Add(slot.MappingIndex,mapping); } diff --git a/libEDSsharp/docs/libEDSsharp.xml b/libEDSsharp/docs/libEDSsharp.xml index 564dab42..6304a3c7 100644 --- a/libEDSsharp/docs/libEDSsharp.xml +++ b/libEDSsharp/docs/libEDSsharp.xml @@ -312,7 +312,7 @@ filled in with default values from the lowest possible index - + Rebuild the communication and mapping paramaters from the lists the PDOhelper currently has. These live in the list pdoslots From 2c8375fa7f3e1d1369b184daf880997f6e29dfac Mon Sep 17 00:00:00 2001 From: Janez Date: Fri, 17 Mar 2023 00:09:43 +0100 Subject: [PATCH 074/226] Issue #43 fixed: add/remove PDO works better, also in Linux. --- EDSEditorGUI/DevicePDOView2.cs | 2 +- libEDSsharp/PDOHelper.cs | 22 +++++++++++++++++++--- libEDSsharp/docs/libEDSsharp.xml | 6 ++++++ 3 files changed, 26 insertions(+), 4 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index ba73ed6a..3415fe7f 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -721,7 +721,7 @@ private void button_deletePDO_Click(object sender, EventArgs e) if (MessageBox.Show(string.Format("Are you sure you wish to delete the entire PDO 0x{0:x4}/0x{1:x4}", selectedslot.ConfigurationIndex, selectedslot.MappingIndex), "Are you sure", MessageBoxButtons.YesNo) == DialogResult.Yes) { - helper.pdoslots.Remove(selectedslot); + helper.removePDOslot(selectedslot.ConfigurationIndex); helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); doUpdateOD(); diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index daa03ba3..4c88e5db 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -477,9 +477,9 @@ public void addPDOslot(UInt16 configindex) PDOSlot newslot = new PDOSlot(); newslot.ConfigurationIndex = configindex; - newslot.COB = 0x180; // Fixme need better defaults??? - newslot.configloc = "RAM"; - newslot.mappingloc = "RAM"; + newslot.COB = 0xC0000000; + newslot.configloc = "PERSIST_COMM"; + newslot.mappingloc = "PERSIST_COMM"; pdoslots.Add(newslot); @@ -518,5 +518,21 @@ public UInt16 findPDOslotgap(bool isTXPDO) //no gaps return 0x0000; } + + /// + /// Remove existing PDO slot as set by index + /// + /// + public void removePDOslot(UInt16 configindex) + { + foreach (PDOSlot slot in pdoslots) + { + if (slot.ConfigurationIndex == configindex) + { + pdoslots.Remove(slot); + break; + } + } + } } } diff --git a/libEDSsharp/docs/libEDSsharp.xml b/libEDSsharp/docs/libEDSsharp.xml index 6304a3c7..eb2d6432 100644 --- a/libEDSsharp/docs/libEDSsharp.xml +++ b/libEDSsharp/docs/libEDSsharp.xml @@ -329,6 +329,12 @@ This finds a gap in the PDO slots + + + Remove existing PDO slot as set by index + + + From 43592ba22ea9438d3f9987d60a371aa47d56c1d8 Mon Sep 17 00:00:00 2001 From: Janez Date: Fri, 17 Mar 2023 00:21:05 +0100 Subject: [PATCH 075/226] Remove unimplemented "Modules" tab from the GUI. --- EDSEditorGUI/DeviceView.Designer.cs | 331 +++++++++++++--------------- EDSEditorGUI/DeviceView.cs | 4 +- EDSEditorGUI/DeviceView.resx | 2 +- 3 files changed, 157 insertions(+), 180 deletions(-) diff --git a/EDSEditorGUI/DeviceView.Designer.cs b/EDSEditorGUI/DeviceView.Designer.cs index f2559460..52b4b56a 100644 --- a/EDSEditorGUI/DeviceView.Designer.cs +++ b/EDSEditorGUI/DeviceView.Designer.cs @@ -28,185 +28,162 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeviceView)); - this.tabControl1 = new System.Windows.Forms.TabControl(); - this.tabPage1 = new System.Windows.Forms.TabPage(); - this.deviceInfoView = new ODEditor.DeviceInfoView(); - this.tabPage2 = new System.Windows.Forms.TabPage(); - this.deviceODView1 = new ODEditor.DeviceODView(); - this.tabPage3 = new System.Windows.Forms.TabPage(); - this.devicePDOView1 = new ODEditor.DevicePDOView2(); - this.tabPage4 = new System.Windows.Forms.TabPage(); - this.devicePDOView2 = new ODEditor.DevicePDOView2(); - this.tabPage5 = new System.Windows.Forms.TabPage(); - this.moduleInfo1 = new ODEditor.ModuleInfo(); - this.imageList1 = new System.Windows.Forms.ImageList(this.components); - this.tabControl1.SuspendLayout(); - this.tabPage1.SuspendLayout(); - this.tabPage2.SuspendLayout(); - this.tabPage3.SuspendLayout(); - this.tabPage4.SuspendLayout(); - this.tabPage5.SuspendLayout(); - this.SuspendLayout(); - // - // tabControl1 - // - this.tabControl1.Controls.Add(this.tabPage1); - this.tabControl1.Controls.Add(this.tabPage2); - this.tabControl1.Controls.Add(this.tabPage3); - this.tabControl1.Controls.Add(this.tabPage4); - this.tabControl1.Controls.Add(this.tabPage5); - this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabControl1.ImageList = this.imageList1; - this.tabControl1.Location = new System.Drawing.Point(0, 0); - this.tabControl1.Name = "tabControl1"; - this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(1122, 773); - this.tabControl1.TabIndex = 1; - // - // tabPage1 - // - this.tabPage1.Controls.Add(this.deviceInfoView); - this.tabPage1.ImageIndex = 1; - this.tabPage1.Location = new System.Drawing.Point(4, 23); - this.tabPage1.Name = "tabPage1"; - this.tabPage1.Padding = new System.Windows.Forms.Padding(3); - this.tabPage1.Size = new System.Drawing.Size(1114, 746); - this.tabPage1.TabIndex = 1; - this.tabPage1.Text = "Device Info"; - this.tabPage1.UseVisualStyleBackColor = true; - // - // deviceInfoView - // - this.deviceInfoView.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceInfoView.Location = new System.Drawing.Point(3, 3); - this.deviceInfoView.Margin = new System.Windows.Forms.Padding(4); - this.deviceInfoView.Name = "deviceInfoView"; - this.deviceInfoView.Size = new System.Drawing.Size(1108, 740); - this.deviceInfoView.TabIndex = 0; - // - // tabPage2 - // - this.tabPage2.Controls.Add(this.deviceODView1); - this.tabPage2.ImageIndex = 0; - this.tabPage2.Location = new System.Drawing.Point(4, 23); - this.tabPage2.Name = "tabPage2"; - this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(1114, 746); - this.tabPage2.TabIndex = 0; - this.tabPage2.Text = "Object Dictionary"; - this.tabPage2.UseVisualStyleBackColor = true; - // - // deviceODView1 - // - this.deviceODView1.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceODView1.Location = new System.Drawing.Point(3, 3); - this.deviceODView1.Margin = new System.Windows.Forms.Padding(4); - this.deviceODView1.Name = "deviceODView1"; - this.deviceODView1.Size = new System.Drawing.Size(1108, 740); - this.deviceODView1.TabIndex = 0; - // - // tabPage3 - // - this.tabPage3.Controls.Add(this.devicePDOView1); - this.tabPage3.ImageIndex = 2; - this.tabPage3.Location = new System.Drawing.Point(4, 23); - this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(1114, 746); - this.tabPage3.TabIndex = 2; - this.tabPage3.Text = "TX PDO Mapping"; - this.tabPage3.UseVisualStyleBackColor = true; - // - // devicePDOView1 - // - this.devicePDOView1.AutoScroll = true; - this.devicePDOView1.Dock = System.Windows.Forms.DockStyle.Fill; - this.devicePDOView1.Location = new System.Drawing.Point(0, 0); - this.devicePDOView1.Margin = new System.Windows.Forms.Padding(4); - this.devicePDOView1.Name = "devicePDOView1"; - this.devicePDOView1.Size = new System.Drawing.Size(1114, 746); - this.devicePDOView1.TabIndex = 0; - // - // tabPage4 - // - this.tabPage4.Controls.Add(this.devicePDOView2); - this.tabPage4.ImageIndex = 3; - this.tabPage4.Location = new System.Drawing.Point(4, 23); - this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(1114, 746); - this.tabPage4.TabIndex = 3; - this.tabPage4.Text = "RX PDO Mapping"; - this.tabPage4.UseVisualStyleBackColor = true; - // - // devicePDOView2 - // - this.devicePDOView2.AutoScroll = true; - this.devicePDOView2.Dock = System.Windows.Forms.DockStyle.Fill; - this.devicePDOView2.Location = new System.Drawing.Point(0, 0); - this.devicePDOView2.Margin = new System.Windows.Forms.Padding(4); - this.devicePDOView2.Name = "devicePDOView2"; - this.devicePDOView2.Size = new System.Drawing.Size(1114, 746); - this.devicePDOView2.TabIndex = 0; - // - // tabPage5 - // - this.tabPage5.Controls.Add(this.moduleInfo1); - this.tabPage5.Location = new System.Drawing.Point(4, 23); - this.tabPage5.Name = "tabPage5"; - this.tabPage5.Padding = new System.Windows.Forms.Padding(3); - this.tabPage5.Size = new System.Drawing.Size(1114, 746); - this.tabPage5.TabIndex = 4; - this.tabPage5.Text = "Modules"; - this.tabPage5.UseVisualStyleBackColor = true; - // - // moduleInfo1 - // - this.moduleInfo1.Dock = System.Windows.Forms.DockStyle.Fill; - this.moduleInfo1.Location = new System.Drawing.Point(3, 3); - this.moduleInfo1.Margin = new System.Windows.Forms.Padding(4); - this.moduleInfo1.Name = "moduleInfo1"; - this.moduleInfo1.Size = new System.Drawing.Size(1108, 740); - this.moduleInfo1.TabIndex = 0; - // - // imageList1 - // - this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream"))); - this.imageList1.TransparentColor = System.Drawing.Color.Transparent; - this.imageList1.Images.SetKeyName(0, "ListBox_686.png"); - this.imageList1.Images.SetKeyName(1, "notebook_16xLG.png"); - this.imageList1.Images.SetKeyName(2, "Output_16xLG.png"); - this.imageList1.Images.SetKeyName(3, "SingleInput_8170_16x.png"); - // - // DeviceView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.tabControl1); - this.Name = "DeviceView"; - this.Size = new System.Drawing.Size(1122, 773); - this.tabControl1.ResumeLayout(false); - this.tabPage1.ResumeLayout(false); - this.tabPage2.ResumeLayout(false); - this.tabPage3.ResumeLayout(false); - this.tabPage4.ResumeLayout(false); - this.tabPage5.ResumeLayout(false); - this.ResumeLayout(false); - + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeviceView)); + this.imageList1 = new System.Windows.Forms.ImageList(this.components); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.devicePDOView2 = new ODEditor.DevicePDOView2(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.devicePDOView1 = new ODEditor.DevicePDOView2(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.deviceODView1 = new ODEditor.DeviceODView(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.deviceInfoView = new ODEditor.DeviceInfoView(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage4.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.SuspendLayout(); + // + // imageList1 + // + this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream"))); + this.imageList1.TransparentColor = System.Drawing.Color.Transparent; + this.imageList1.Images.SetKeyName(0, "ListBox_686.png"); + this.imageList1.Images.SetKeyName(1, "notebook_16xLG.png"); + this.imageList1.Images.SetKeyName(2, "Output_16xLG.png"); + this.imageList1.Images.SetKeyName(3, "SingleInput_8170_16x.png"); + // + // tabPage4 + // + this.tabPage4.Controls.Add(this.devicePDOView2); + this.tabPage4.ImageIndex = 3; + this.tabPage4.Location = new System.Drawing.Point(4, 23); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Size = new System.Drawing.Size(1114, 746); + this.tabPage4.TabIndex = 3; + this.tabPage4.Text = "RX PDO Mapping"; + this.tabPage4.UseVisualStyleBackColor = true; + // + // devicePDOView2 + // + this.devicePDOView2.AutoScroll = true; + this.devicePDOView2.AutoSize = true; + this.devicePDOView2.Dock = System.Windows.Forms.DockStyle.Fill; + this.devicePDOView2.Location = new System.Drawing.Point(0, 0); + this.devicePDOView2.Margin = new System.Windows.Forms.Padding(4); + this.devicePDOView2.Name = "devicePDOView2"; + this.devicePDOView2.Size = new System.Drawing.Size(1114, 746); + this.devicePDOView2.TabIndex = 0; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.devicePDOView1); + this.tabPage3.ImageIndex = 2; + this.tabPage3.Location = new System.Drawing.Point(4, 23); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(1114, 746); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "TX PDO Mapping"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // devicePDOView1 + // + this.devicePDOView1.AutoScroll = true; + this.devicePDOView1.AutoSize = true; + this.devicePDOView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.devicePDOView1.Location = new System.Drawing.Point(0, 0); + this.devicePDOView1.Margin = new System.Windows.Forms.Padding(4); + this.devicePDOView1.Name = "devicePDOView1"; + this.devicePDOView1.Size = new System.Drawing.Size(1114, 746); + this.devicePDOView1.TabIndex = 0; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.deviceODView1); + this.tabPage2.ImageIndex = 0; + this.tabPage2.Location = new System.Drawing.Point(4, 23); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(1114, 746); + this.tabPage2.TabIndex = 0; + this.tabPage2.Text = "Object Dictionary"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // deviceODView1 + // + this.deviceODView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.deviceODView1.Location = new System.Drawing.Point(3, 3); + this.deviceODView1.Margin = new System.Windows.Forms.Padding(4); + this.deviceODView1.Name = "deviceODView1"; + this.deviceODView1.Size = new System.Drawing.Size(1108, 740); + this.deviceODView1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.deviceInfoView); + this.tabPage1.ImageIndex = 1; + this.tabPage1.Location = new System.Drawing.Point(4, 23); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(1114, 746); + this.tabPage1.TabIndex = 1; + this.tabPage1.Text = "Device Info"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // deviceInfoView + // + this.deviceInfoView.Dock = System.Windows.Forms.DockStyle.Fill; + this.deviceInfoView.Location = new System.Drawing.Point(3, 3); + this.deviceInfoView.Margin = new System.Windows.Forms.Padding(4); + this.deviceInfoView.Name = "deviceInfoView"; + this.deviceInfoView.Size = new System.Drawing.Size(1108, 740); + this.deviceInfoView.TabIndex = 0; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.ImageList = this.imageList1; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(1122, 773); + this.tabControl1.TabIndex = 1; + // + // DeviceView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tabControl1); + this.Name = "DeviceView"; + this.Size = new System.Drawing.Size(1122, 773); + this.tabPage4.ResumeLayout(false); + this.tabPage4.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.ResumeLayout(false); + } #endregion - private System.Windows.Forms.TabPage tabPage1; - private System.Windows.Forms.TabPage tabPage2; - private System.Windows.Forms.TabPage tabPage3; - private DeviceInfoView deviceInfoView; - private DevicePDOView2 devicePDOView1; - private DeviceODView deviceODView1; - private System.Windows.Forms.TabPage tabPage4; - private DevicePDOView2 devicePDOView2; - private System.Windows.Forms.ImageList imageList1; - private System.Windows.Forms.TabControl tabControl1; - private System.Windows.Forms.TabPage tabPage5; - private ModuleInfo moduleInfo1; + private System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.TabPage tabPage4; + private DevicePDOView2 devicePDOView2; + private System.Windows.Forms.TabPage tabPage3; + private DevicePDOView2 devicePDOView1; + private System.Windows.Forms.TabPage tabPage2; + private DeviceODView deviceODView1; + private System.Windows.Forms.TabPage tabPage1; + private DeviceInfoView deviceInfoView; + private System.Windows.Forms.TabControl tabControl1; } } diff --git a/EDSEditorGUI/DeviceView.cs b/EDSEditorGUI/DeviceView.cs index ed859d20..6963eda0 100644 --- a/EDSEditorGUI/DeviceView.cs +++ b/EDSEditorGUI/DeviceView.cs @@ -67,8 +67,8 @@ public void dispatch_updatedevice() deviceInfoView.populatedeviceinfo(); - moduleInfo1.eds = eds; - moduleInfo1.populatemoduleinfo(); + //moduleInfo1.eds = eds; + //moduleInfo1.populatemoduleinfo(); } public void dispatch_updatePDOinfo() diff --git a/EDSEditorGUI/DeviceView.resx b/EDSEditorGUI/DeviceView.resx index 76c87766..8cd3b4d7 100644 --- a/EDSEditorGUI/DeviceView.resx +++ b/EDSEditorGUI/DeviceView.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACk - CgAAAk1TRnQBSQFMAgEBBAEAAVgBAAFYAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CgAAAk1TRnQBSQFMAgEBBAEAAWABAAFgAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA From 511d1d93ec9a74034d37d9ed1bb9ca8e6cbb3ce7 Mon Sep 17 00:00:00 2001 From: Janez Date: Fri, 17 Mar 2023 00:43:48 +0100 Subject: [PATCH 076/226] PDO mapping tab: fixed toggle, uppercase hex numbers, Event Timer always Enabled --- EDSEditorGUI/DevicePDOView2.cs | 38 +++++++++++++++++----------------- libEDSsharp/PDOHelper.cs | 16 +++++++------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 3415fe7f..7f13067b 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -247,10 +247,10 @@ private void Grid1_Click(object sender, EventArgs e) if (isTXPDO) { - textBox_eventtimer.Enabled = true; textBox_inhibit.Enabled = true; textBox_syncstart.Enabled = true; - } + } + textBox_eventtimer.Enabled = true; textBox_type.Enabled = true; textBox_cob.Enabled = true; @@ -324,10 +324,10 @@ public void addPDOchoices() private void AddTXPDOoption(ODentry od) { - TXchoices.Add(String.Format("0x{0:x4}/{1:x2}/", od.Index, od.Subindex) + od.parameter_name); + TXchoices.Add(String.Format("0x{0:X4}/{1:X2}/", od.Index, od.Subindex) + od.parameter_name); - ListViewItem lvi = new ListViewItem(String.Format("0x{0:x4}", od.Index)); - lvi.SubItems.Add(String.Format("0x{0:x2}", od.Subindex)); + ListViewItem lvi = new ListViewItem(String.Format("0x{0:X4}", od.Index)); + lvi.SubItems.Add(String.Format("0x{0:X2}", od.Subindex)); lvi.SubItems.Add(od.parameter_name); DataType dt = od.datatype; @@ -348,13 +348,13 @@ public void updateslotdisplay() if (selectedslot == null) return; - textBox_slot.Text = string.Format("0x{0:x4}", selectedslot.ConfigurationIndex); - textBox_mapping.Text = string.Format("0x{0:x4}", selectedslot.MappingIndex); - textBox_cob.Text = string.Format("0x{0:x4}", selectedslot.COB); + textBox_slot.Text = string.Format("0x{0:X4}", selectedslot.ConfigurationIndex); + textBox_mapping.Text = string.Format("0x{0:X4}", selectedslot.MappingIndex); + textBox_cob.Text = string.Format("0x{0:X4}", selectedslot.COB); textBox_type.Text = string.Format("{0}", selectedslot.transmissiontype); textBox_inhibit.Text = string.Format("{0}", selectedslot.inhibit); - textBox_eventtimer.Text = string.Format("0x{0:x4}", selectedslot.eventtimer); - textBox_syncstart.Text = string.Format("0x{0:x4}", selectedslot.syncstart); + textBox_eventtimer.Text = string.Format("{0}", selectedslot.eventtimer); + textBox_syncstart.Text = string.Format("{0}", selectedslot.syncstart); } @@ -384,7 +384,7 @@ public void UpdatePDOinfo(bool updatechoices = true) foreach (ODentry od in eds.dummy_ods.Values) { - TXchoices.Add(String.Format("0x{0:x4}/{1:x2}/", od.Index, od.Subindex) + od.parameter_name); + TXchoices.Add(String.Format("0x{0:X4}/{1:X2}/", od.Index, od.Subindex) + od.parameter_name); } foreach (KeyValuePair kvp in eds.ods) @@ -397,7 +397,7 @@ public void UpdatePDOinfo(bool updatechoices = true) if (od.objecttype == ObjectType.VAR && (od.PDOtype == PDOMappingType.optional || (isTXPDO && (od.PDOtype == PDOMappingType.TPDO)) || (!isTXPDO && (od.PDOtype == PDOMappingType.RPDO)))) { - TXchoices.Add(String.Format("0x{0:x4}/{1:x2}/", od.Index, od.Subindex) + od.parameter_name); + TXchoices.Add(String.Format("0x{0:X4}/{1:X2}/", od.Index, od.Subindex) + od.parameter_name); } @@ -411,7 +411,7 @@ public void UpdatePDOinfo(bool updatechoices = true) if (odsub.PDOtype == PDOMappingType.optional || (isTXPDO && (odsub.PDOtype == PDOMappingType.TPDO)) || (!isTXPDO && (odsub.PDOtype == PDOMappingType.RPDO))) { - TXchoices.Add(String.Format("0x{0:x4}/{1:x2}/", odsub.Index, odsub.Subindex) + odsub.parameter_name); + TXchoices.Add(String.Format("0x{0:X4}/{1:X2}/", odsub.Index, odsub.Subindex) + odsub.parameter_name); } } @@ -446,8 +446,8 @@ public void UpdatePDOinfo(bool updatechoices = true) grid1.Rows[row + 2].Height = 30; grid1[row + 2, 0] = new SourceGrid.Cells.Cell(String.Format("{0}", row + 1), typeof(string)); - grid1[row + 2, 1] = new SourceGrid.Cells.Cell(String.Format("{0:x}", slot.COB), typeof(string)); - grid1[row + 2, 2] = new SourceGrid.Cells.Cell(String.Format("{0:x}", slot.ConfigurationIndex), typeof(string)); + grid1[row + 2, 1] = new SourceGrid.Cells.Cell(String.Format("{0:X}", slot.COB), typeof(string)); + grid1[row + 2, 2] = new SourceGrid.Cells.Cell(String.Format("{0:X}", slot.ConfigurationIndex), typeof(string)); grid1[grid1.RowsCount - 1, 0].View = viewCOB; grid1[grid1.RowsCount - 1, 1].View = viewCOB; @@ -718,7 +718,7 @@ private void button_deletePDO_Click(object sender, EventArgs e) if (selectedslot == null) return; - if (MessageBox.Show(string.Format("Are you sure you wish to delete the entire PDO 0x{0:x4}/0x{1:x4}", selectedslot.ConfigurationIndex, selectedslot.MappingIndex), "Are you sure", MessageBoxButtons.YesNo) == DialogResult.Yes) + if (MessageBox.Show(string.Format("Are you sure you wish to delete the entire PDO 0x{0:X4}/0x{1:X4}", selectedslot.ConfigurationIndex, selectedslot.MappingIndex), "Are you sure", MessageBoxButtons.YesNo) == DialogResult.Yes) { helper.removePDOslot(selectedslot.ConfigurationIndex); @@ -756,7 +756,7 @@ private void checkBox_invalidpdo_CheckedChanged(object sender, EventArgs e) selectedslot.invalid = checkBox_invalidpdo.Checked; - textBox_cob.Text = string.Format("0x{0:x4}", selectedslot.COB); + textBox_cob.Text = string.Format("0x{0:X4}", selectedslot.COB); } private void button_savepdochanges_Click(object sender, EventArgs e) @@ -773,7 +773,7 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) { if (config < 0x1400 | config >= 0x1600) { - MessageBox.Show(string.Format("Invalid TXPDO Communication parameters index 0x{0:x4}", config)); + MessageBox.Show(string.Format("Invalid TXPDO Communication parameters index 0x{0:X4}", config)); return; } } @@ -781,7 +781,7 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) { if (config < 0x1800 | config >= 0x1A00) { - MessageBox.Show(string.Format("Invalid RXPDO Communication parameters index 0x{0:x4}", config)); + MessageBox.Show(string.Format("Invalid RXPDO Communication parameters index 0x{0:X4}", config)); return; } } diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 4c88e5db..296f0373 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -72,7 +72,7 @@ public bool invalid if (value == true) COB = COB | 0x80000000; else - COB = COB & 0xEFFFFFFF; + COB = COB & 0x7FFFFFFF; } } @@ -127,7 +127,7 @@ public string getTargetName(ODentry od) } else { - target = String.Format("0x{0:x4}/{1:x2}/", od.Index, od.Subindex) + od.parameter_name; + target = String.Format("0x{0:X4}/{1:X2}/", od.Index, od.Subindex) + od.parameter_name; } return target; @@ -211,7 +211,7 @@ public void build_PDOlist(UInt16 startcob, List slots) slot.DescriptionComm = od.Description; - Console.WriteLine(String.Format("Found PDO Entry {0:x4} {1:x3}", idx, slot.COB)); + Console.WriteLine(String.Format("Found PDO Entry {0:X4} {1:X3}", idx, slot.COB)); //Look at mappings @@ -219,7 +219,7 @@ public void build_PDOlist(UInt16 startcob, List slots) slot.DescriptionMap = mapping.Description; if(mapping==null) { - Console.WriteLine(string.Format("No mapping for index 0x{0:x4} should be at 0x{1:x4}", idx, idx + 0x200)); + Console.WriteLine(string.Format("No mapping for index 0x{0:X4} should be at 0x{1:X4}", idx, idx + 0x200)); continue; } @@ -253,7 +253,7 @@ public void build_PDOlist(UInt16 startcob, List slots) totalsize += datasize; - Console.WriteLine(string.Format("Mapping 0x{0:x4}/{1:x2} size {2}", pdoindex, pdosub, datasize)); + Console.WriteLine(string.Format("Mapping 0x{0:X4}/{1:X2} size {2}", pdoindex, pdosub, datasize)); //validate this against what is in the actual object mapped try @@ -431,9 +431,9 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) byte mappingcount = 1; foreach (ODentry mapslot in slot.Mapping) { - sub = new ODentry(String.Format("Application object {0:x}", mappingcount), (ushort)slot.MappingIndex, mappingcount); + sub = new ODentry(String.Format("Application object {0:X}", mappingcount), (ushort)slot.MappingIndex, mappingcount); sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = string.Format("0x{0:x4}{1:x2}{2:x2}", mapslot.Index, mapslot.Subindex, mapslot.Sizeofdatatype()); + sub.defaultvalue = string.Format("0x{0:X4}{1:X2}{2:X2}", mapslot.Index, mapslot.Subindex, mapslot.Sizeofdatatype()); sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(mappingcount, sub); @@ -443,7 +443,7 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) for (; mappingcount <= 8; mappingcount++) { - sub = new ODentry(String.Format("Application object {0:x}", mappingcount), (ushort)slot.MappingIndex, mappingcount); + sub = new ODentry(String.Format("Application object {0:X}", mappingcount), (ushort)slot.MappingIndex, mappingcount); sub.datatype = DataType.UNSIGNED32; sub.defaultvalue = "0x00000000"; sub.accesstype = EDSsharp.AccessType.rw; From a49a51a313ce075fea47ed332ba08a9835867f30 Mon Sep 17 00:00:00 2001 From: Janez Date: Fri, 17 Mar 2023 02:11:59 +0100 Subject: [PATCH 077/226] DS301_profile.xpd: "$NODEID" now appears at the beginning of the expression. --- EDSEditorGUI/Profiles/DS301_profile.xpd | 28 ++++++++++++------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 913bd715..26f22454 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -1,5 +1,5 @@ - + @@ -15,7 +15,7 @@ CANopen - + @@ -856,7 +856,7 @@ * bit 11-30: set to 0 * bit 0-10: 11-bit CAN-ID - + @@ -1186,12 +1186,12 @@ - + - + * Sub-indexes 1 and 2: @@ -1279,7 +1279,7 @@ - + @@ -1314,7 +1314,7 @@ - + @@ -1349,7 +1349,7 @@ - + @@ -1384,7 +1384,7 @@ - + @@ -1747,7 +1747,7 @@ - + @@ -1798,7 +1798,7 @@ - + @@ -1849,7 +1849,7 @@ - + @@ -1900,7 +1900,7 @@ - + @@ -2277,7 +2277,7 @@ CANopen - + From ff637a74d607c92164203ad354f75b1da3ee5464 Mon Sep 17 00:00:00 2001 From: Janez Date: Sat, 18 Mar 2023 14:24:11 +0100 Subject: [PATCH 078/226] When adding new PDO, default value is according to standard: "$NODEID+0x180" or similar. --- libEDSsharp/PDOHelper.cs | 44 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 41 insertions(+), 3 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 296f0373..e6112dbc 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -333,7 +333,7 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) sub.datatype = DataType.UNSIGNED32; if (slot.nodeidpresent) sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. - sub.defaultvalue += slot.COB.ToHexString(); + sub.defaultvalue += String.Format("0x{0:X}", slot.COB); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -386,7 +386,7 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) sub.datatype = DataType.UNSIGNED32; if (slot.nodeidpresent) sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. - sub.defaultvalue += slot.COB.ToHexString(); + sub.defaultvalue += String.Format("0x{0:X}", slot.COB); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -477,7 +477,45 @@ public void addPDOslot(UInt16 configindex) PDOSlot newslot = new PDOSlot(); newslot.ConfigurationIndex = configindex; - newslot.COB = 0xC0000000; + switch (configindex) + { + case 0x1400: + newslot.COB = 0x80000200; + newslot.nodeidpresent = true; + break; + case 0x1401: + newslot.COB = 0x80000300; + newslot.nodeidpresent = true; + break; + case 0x1402: + newslot.COB = 0x80000400; + newslot.nodeidpresent = true; + break; + case 0x1403: + newslot.COB = 0x80000500; + newslot.nodeidpresent = true; + break; + case 0x1800: + newslot.COB = 0xC0000180; + newslot.nodeidpresent = true; + break; + case 0x1801: + newslot.COB = 0xC0000280; + newslot.nodeidpresent = true; + break; + case 0x1802: + newslot.COB = 0xC0000380; + newslot.nodeidpresent = true; + break; + case 0x1803: + newslot.COB = 0xC0000480; + newslot.nodeidpresent = true; + break; + default: + newslot.COB = 0xC0000000; + break; + } + newslot.configloc = "PERSIST_COMM"; newslot.mappingloc = "PERSIST_COMM"; From 93d61ccf2dd36146d190ef55339da57a1faad158 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Sun, 23 Apr 2023 12:34:41 +0200 Subject: [PATCH 079/226] Make message more explicit Add Autosave checkbox to save all changes when leaving the form When changes detected: Update the device info. Removed Update button on device Info --- EDSEditorGUI/DeviceInfoView.Designer.cs | 1684 ++++++++++++----------- EDSEditorGUI/DeviceInfoView.cs | 31 +- EDSEditorGUI/DeviceInfoView.resx | 238 ++-- EDSEditorGUI/DeviceODView.Designer.cs | 313 +++-- EDSEditorGUI/DeviceODView.cs | 1324 +++++++++--------- EDSEditorGUI/DeviceView.Designer.cs | 52 +- EDSEditorGUI/DeviceView.resx | 2 +- EDSEditorGUI/Form1.Designer.cs | 600 ++++---- EDSEditorGUI/Form1.cs | 4 +- EDSEditorGUI/Form1.resx | 653 ++++----- 10 files changed, 2548 insertions(+), 2353 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.Designer.cs b/EDSEditorGUI/DeviceInfoView.Designer.cs index fd64dba6..14e82f59 100644 --- a/EDSEditorGUI/DeviceInfoView.Designer.cs +++ b/EDSEditorGUI/DeviceInfoView.Designer.cs @@ -28,821 +28,887 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.panel1 = new System.Windows.Forms.Panel(); - this.groupBox5 = new System.Windows.Forms.GroupBox(); - this.label4 = new System.Windows.Forms.Label(); - this.textBox_mdFileName = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.textBox_xddfilenameStripped = new System.Windows.Forms.TextBox(); - this.textBox_canopennodeFileVersion = new System.Windows.Forms.TextBox(); - this.textBox_projectFileVersion = new System.Windows.Forms.TextBox(); - this.textBox_devicedcfname = new System.Windows.Forms.TextBox(); - this.label14 = new System.Windows.Forms.Label(); - this.label15 = new System.Windows.Forms.Label(); - this.textBox_canopennodeFileName = new System.Windows.Forms.TextBox(); - this.label16 = new System.Windows.Forms.Label(); - this.label31 = new System.Windows.Forms.Label(); - this.textBox_projectFileName = new System.Windows.Forms.TextBox(); - this.textBox_deviceedsname = new System.Windows.Forms.TextBox(); - this.groupBox6 = new System.Windows.Forms.GroupBox(); - this.label3 = new System.Windows.Forms.Label(); - this.textBox_lssserial = new System.Windows.Forms.TextBox(); - this.label9 = new System.Windows.Forms.Label(); - this.checkBox_canopenmanager = new System.Windows.Forms.CheckBox(); - this.label8 = new System.Windows.Forms.Label(); - this.textBox_netname = new System.Windows.Forms.TextBox(); - this.label7 = new System.Windows.Forms.Label(); - this.textBox_netnum = new System.Windows.Forms.TextBox(); - this.label6 = new System.Windows.Forms.Label(); - this.textBox_baudrate = new System.Windows.Forms.TextBox(); - this.label5 = new System.Windows.Forms.Label(); - this.textBox_nodename = new System.Windows.Forms.TextBox(); - this.label32 = new System.Windows.Forms.Label(); - this.textBox_concretenodeid = new System.Windows.Forms.TextBox(); - this.groupBox4 = new System.Windows.Forms.GroupBox(); - this.textBox_productnumber = new System.Windows.Forms.TextBox(); - this.textBox_productname = new System.Windows.Forms.TextBox(); - this.textBox_vendornumber = new System.Windows.Forms.TextBox(); - this.textBox_vendorname = new System.Windows.Forms.TextBox(); - this.label29 = new System.Windows.Forms.Label(); - this.label28 = new System.Windows.Forms.Label(); - this.label27 = new System.Windows.Forms.Label(); - this.label26 = new System.Windows.Forms.Label(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.checkBox_baud_auto = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_125 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_10 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_20 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_50 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_250 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_1000 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_500 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_800 = new System.Windows.Forms.CheckBox(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.textBox_granularity = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.textBox_txpdos = new System.Windows.Forms.TextBox(); - this.checkBox_lssMaster = new System.Windows.Forms.CheckBox(); - this.label30 = new System.Windows.Forms.Label(); - this.textBox_rxpdos = new System.Windows.Forms.TextBox(); - this.label17 = new System.Windows.Forms.Label(); - this.checkBox_lss = new System.Windows.Forms.CheckBox(); - this.groupBox3 = new System.Windows.Forms.GroupBox(); - this.textBox_modifiedby = new System.Windows.Forms.TextBox(); - this.textBox_modified_datetime = new System.Windows.Forms.TextBox(); - this.textBox_createdby = new System.Windows.Forms.TextBox(); - this.textBox_create_datetime = new System.Windows.Forms.TextBox(); - this.textBox_di_description = new System.Windows.Forms.TextBox(); - this.textBox_fileversion = new System.Windows.Forms.TextBox(); - this.label25 = new System.Windows.Forms.Label(); - this.label24 = new System.Windows.Forms.Label(); - this.label23 = new System.Windows.Forms.Label(); - this.label22 = new System.Windows.Forms.Label(); - this.label20 = new System.Windows.Forms.Label(); - this.label18 = new System.Windows.Forms.Label(); - this.button_update_devfile_info = new System.Windows.Forms.Button(); - this.panel1.SuspendLayout(); - this.groupBox5.SuspendLayout(); - this.groupBox6.SuspendLayout(); - this.groupBox4.SuspendLayout(); - this.groupBox1.SuspendLayout(); - this.groupBox2.SuspendLayout(); - this.groupBox3.SuspendLayout(); - this.SuspendLayout(); - // - // panel1 - // - this.panel1.Controls.Add(this.groupBox5); - this.panel1.Controls.Add(this.groupBox6); - this.panel1.Controls.Add(this.groupBox4); - this.panel1.Controls.Add(this.groupBox1); - this.panel1.Controls.Add(this.groupBox2); - this.panel1.Controls.Add(this.groupBox3); - this.panel1.Controls.Add(this.button_update_devfile_info); - this.panel1.Location = new System.Drawing.Point(0, 0); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(773, 537); - this.panel1.TabIndex = 60; - // - // groupBox5 - // - this.groupBox5.Controls.Add(this.label4); - this.groupBox5.Controls.Add(this.textBox_mdFileName); - this.groupBox5.Controls.Add(this.label2); - this.groupBox5.Controls.Add(this.textBox_xddfilenameStripped); - this.groupBox5.Controls.Add(this.textBox_canopennodeFileVersion); - this.groupBox5.Controls.Add(this.textBox_projectFileVersion); - this.groupBox5.Controls.Add(this.textBox_devicedcfname); - this.groupBox5.Controls.Add(this.label14); - this.groupBox5.Controls.Add(this.label15); - this.groupBox5.Controls.Add(this.textBox_canopennodeFileName); - this.groupBox5.Controls.Add(this.label16); - this.groupBox5.Controls.Add(this.label31); - this.groupBox5.Controls.Add(this.textBox_projectFileName); - this.groupBox5.Controls.Add(this.textBox_deviceedsname); - this.groupBox5.Location = new System.Drawing.Point(12, 332); - this.groupBox5.Name = "groupBox5"; - this.groupBox5.Size = new System.Drawing.Size(377, 182); - this.groupBox5.TabIndex = 63; - this.groupBox5.TabStop = false; - this.groupBox5.Text = "Project Info"; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(10, 153); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(95, 13); - this.label4.TabIndex = 70; - this.label4.Text = "Documentation file"; - // - // textBox_mdFileName - // - this.textBox_mdFileName.Location = new System.Drawing.Point(139, 150); - this.textBox_mdFileName.Name = "textBox_mdFileName"; - this.textBox_mdFileName.ReadOnly = true; - this.textBox_mdFileName.Size = new System.Drawing.Size(226, 20); - this.textBox_mdFileName.TabIndex = 69; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(10, 49); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(116, 13); - this.label2.TabIndex = 68; - this.label2.Text = "XDD v1.1 file - stripped"; - // - // textBox_xddfilenameStripped - // - this.textBox_xddfilenameStripped.Location = new System.Drawing.Point(139, 46); - this.textBox_xddfilenameStripped.Name = "textBox_xddfilenameStripped"; - this.textBox_xddfilenameStripped.ReadOnly = true; - this.textBox_xddfilenameStripped.Size = new System.Drawing.Size(226, 20); - this.textBox_xddfilenameStripped.TabIndex = 67; - // - // textBox_canopennodeFileVersion - // - this.textBox_canopennodeFileVersion.Location = new System.Drawing.Point(330, 124); - this.textBox_canopennodeFileVersion.Name = "textBox_canopennodeFileVersion"; - this.textBox_canopennodeFileVersion.ReadOnly = true; - this.textBox_canopennodeFileVersion.Size = new System.Drawing.Size(35, 20); - this.textBox_canopennodeFileVersion.TabIndex = 66; - // - // textBox_projectFileVersion - // - this.textBox_projectFileVersion.Location = new System.Drawing.Point(330, 20); - this.textBox_projectFileVersion.Name = "textBox_projectFileVersion"; - this.textBox_projectFileVersion.ReadOnly = true; - this.textBox_projectFileVersion.Size = new System.Drawing.Size(35, 20); - this.textBox_projectFileVersion.TabIndex = 65; - // - // textBox_devicedcfname - // - this.textBox_devicedcfname.Location = new System.Drawing.Point(139, 98); - this.textBox_devicedcfname.Name = "textBox_devicedcfname"; - this.textBox_devicedcfname.ReadOnly = true; - this.textBox_devicedcfname.Size = new System.Drawing.Size(226, 20); - this.textBox_devicedcfname.TabIndex = 8; - // - // label14 - // - this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(10, 127); - this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(119, 13); - this.label14.TabIndex = 21; - this.label14.Text = "CANopenNode file (ver)"; - // - // label15 - // - this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(10, 101); - this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(44, 13); - this.label15.TabIndex = 20; - this.label15.Text = "DCF file"; - // - // textBox_canopennodeFileName - // - this.textBox_canopennodeFileName.Location = new System.Drawing.Point(139, 124); - this.textBox_canopennodeFileName.Name = "textBox_canopennodeFileName"; - this.textBox_canopennodeFileName.ReadOnly = true; - this.textBox_canopennodeFileName.Size = new System.Drawing.Size(185, 20); - this.textBox_canopennodeFileName.TabIndex = 9; - // - // label16 - // - this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(10, 75); - this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(45, 13); - this.label16.TabIndex = 19; - this.label16.Text = "EDS file"; - // - // label31 - // - this.label31.AutoSize = true; - this.label31.Location = new System.Drawing.Point(10, 23); - this.label31.Name = "label31"; - this.label31.Size = new System.Drawing.Size(99, 13); - this.label31.TabIndex = 18; - this.label31.Text = "Project file (version)"; - // - // textBox_projectFileName - // - this.textBox_projectFileName.Location = new System.Drawing.Point(139, 20); - this.textBox_projectFileName.Name = "textBox_projectFileName"; - this.textBox_projectFileName.ReadOnly = true; - this.textBox_projectFileName.Size = new System.Drawing.Size(185, 20); - this.textBox_projectFileName.TabIndex = 6; - // - // textBox_deviceedsname - // - this.textBox_deviceedsname.Location = new System.Drawing.Point(139, 72); - this.textBox_deviceedsname.Name = "textBox_deviceedsname"; - this.textBox_deviceedsname.ReadOnly = true; - this.textBox_deviceedsname.Size = new System.Drawing.Size(226, 20); - this.textBox_deviceedsname.TabIndex = 7; - // - // groupBox6 - // - this.groupBox6.Controls.Add(this.label3); - this.groupBox6.Controls.Add(this.textBox_lssserial); - this.groupBox6.Controls.Add(this.label9); - this.groupBox6.Controls.Add(this.checkBox_canopenmanager); - this.groupBox6.Controls.Add(this.label8); - this.groupBox6.Controls.Add(this.textBox_netname); - this.groupBox6.Controls.Add(this.label7); - this.groupBox6.Controls.Add(this.textBox_netnum); - this.groupBox6.Controls.Add(this.label6); - this.groupBox6.Controls.Add(this.textBox_baudrate); - this.groupBox6.Controls.Add(this.label5); - this.groupBox6.Controls.Add(this.textBox_nodename); - this.groupBox6.Controls.Add(this.label32); - this.groupBox6.Controls.Add(this.textBox_concretenodeid); - this.groupBox6.Location = new System.Drawing.Point(395, 210); - this.groupBox6.Name = "groupBox6"; - this.groupBox6.Size = new System.Drawing.Size(339, 199); - this.groupBox6.TabIndex = 5; - this.groupBox6.TabStop = false; - this.groupBox6.Text = "Device commissioning"; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(7, 149); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(98, 13); - this.label3.TabIndex = 63; - this.label3.Text = "CANopen Manager"; - // - // textBox_lssserial - // - this.textBox_lssserial.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_lssserial.Location = new System.Drawing.Point(111, 171); - this.textBox_lssserial.Name = "textBox_lssserial"; - this.textBox_lssserial.Size = new System.Drawing.Size(218, 20); - this.textBox_lssserial.TabIndex = 7; - // - // label9 - // - this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(7, 174); - this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(71, 13); - this.label9.TabIndex = 6; - this.label9.Text = "LSS Serial no"; - // - // checkBox_canopenmanager - // - this.checkBox_canopenmanager.AutoSize = true; - this.checkBox_canopenmanager.BackColor = System.Drawing.Color.PeachPuff; - this.checkBox_canopenmanager.Location = new System.Drawing.Point(111, 148); - this.checkBox_canopenmanager.Name = "checkBox_canopenmanager"; - this.checkBox_canopenmanager.Padding = new System.Windows.Forms.Padding(0, 0, 202, 0); - this.checkBox_canopenmanager.Size = new System.Drawing.Size(217, 14); - this.checkBox_canopenmanager.TabIndex = 5; - this.checkBox_canopenmanager.UseVisualStyleBackColor = false; - // - // label8 - // - this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(7, 125); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(53, 13); - this.label8.TabIndex = 62; - this.label8.Text = "Net name"; - // - // textBox_netname - // - this.textBox_netname.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_netname.Location = new System.Drawing.Point(111, 122); - this.textBox_netname.Name = "textBox_netname"; - this.textBox_netname.Size = new System.Drawing.Size(218, 20); - this.textBox_netname.TabIndex = 4; - // - // label7 - // - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(7, 99); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(62, 13); - this.label7.TabIndex = 60; - this.label7.Text = "Net number"; - // - // textBox_netnum - // - this.textBox_netnum.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_netnum.Location = new System.Drawing.Point(111, 96); - this.textBox_netnum.Name = "textBox_netnum"; - this.textBox_netnum.Size = new System.Drawing.Size(218, 20); - this.textBox_netnum.TabIndex = 3; - // - // label6 - // - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(7, 74); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(50, 13); - this.label6.TabIndex = 58; - this.label6.Text = "Baudrate"; - // - // textBox_baudrate - // - this.textBox_baudrate.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_baudrate.Location = new System.Drawing.Point(111, 71); - this.textBox_baudrate.Name = "textBox_baudrate"; - this.textBox_baudrate.Size = new System.Drawing.Size(218, 20); - this.textBox_baudrate.TabIndex = 2; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(7, 48); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(62, 13); - this.label5.TabIndex = 56; - this.label5.Text = "Node name"; - // - // textBox_nodename - // - this.textBox_nodename.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_nodename.Location = new System.Drawing.Point(111, 45); - this.textBox_nodename.Name = "textBox_nodename"; - this.textBox_nodename.Size = new System.Drawing.Size(218, 20); - this.textBox_nodename.TabIndex = 1; - // - // label32 - // - this.label32.AutoSize = true; - this.label32.Location = new System.Drawing.Point(7, 22); - this.label32.Name = "label32"; - this.label32.Size = new System.Drawing.Size(91, 13); - this.label32.TabIndex = 53; - this.label32.Text = "Concrete node ID"; - // - // textBox_concretenodeid - // - this.textBox_concretenodeid.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_concretenodeid.Location = new System.Drawing.Point(111, 19); - this.textBox_concretenodeid.Name = "textBox_concretenodeid"; - this.textBox_concretenodeid.Size = new System.Drawing.Size(218, 20); - this.textBox_concretenodeid.TabIndex = 0; - // - // groupBox4 - // - this.groupBox4.Controls.Add(this.textBox_productnumber); - this.groupBox4.Controls.Add(this.textBox_productname); - this.groupBox4.Controls.Add(this.textBox_vendornumber); - this.groupBox4.Controls.Add(this.textBox_vendorname); - this.groupBox4.Controls.Add(this.label29); - this.groupBox4.Controls.Add(this.label28); - this.groupBox4.Controls.Add(this.label27); - this.groupBox4.Controls.Add(this.label26); - this.groupBox4.Location = new System.Drawing.Point(12, 14); - this.groupBox4.Name = "groupBox4"; - this.groupBox4.Size = new System.Drawing.Size(377, 126); - this.groupBox4.TabIndex = 0; - this.groupBox4.TabStop = false; - this.groupBox4.Text = "Device Info"; - // - // textBox_productnumber - // - this.textBox_productnumber.Location = new System.Drawing.Point(139, 46); - this.textBox_productnumber.Name = "textBox_productnumber"; - this.textBox_productnumber.Size = new System.Drawing.Size(226, 20); - this.textBox_productnumber.TabIndex = 1; - // - // textBox_productname - // - this.textBox_productname.Location = new System.Drawing.Point(139, 20); - this.textBox_productname.Name = "textBox_productname"; - this.textBox_productname.Size = new System.Drawing.Size(226, 20); - this.textBox_productname.TabIndex = 0; - // - // textBox_vendornumber - // - this.textBox_vendornumber.Location = new System.Drawing.Point(139, 98); - this.textBox_vendornumber.Name = "textBox_vendornumber"; - this.textBox_vendornumber.Size = new System.Drawing.Size(226, 20); - this.textBox_vendornumber.TabIndex = 3; - // - // textBox_vendorname - // - this.textBox_vendorname.Location = new System.Drawing.Point(139, 72); - this.textBox_vendorname.Name = "textBox_vendorname"; - this.textBox_vendorname.Size = new System.Drawing.Size(226, 20); - this.textBox_vendorname.TabIndex = 2; - // - // label29 - // - this.label29.AutoSize = true; - this.label29.Location = new System.Drawing.Point(10, 49); - this.label29.Name = "label29"; - this.label29.Size = new System.Drawing.Size(58, 13); - this.label29.TabIndex = 37; - this.label29.Text = "Product ID"; - // - // label28 - // - this.label28.AutoSize = true; - this.label28.Location = new System.Drawing.Point(10, 23); - this.label28.Name = "label28"; - this.label28.Size = new System.Drawing.Size(73, 13); - this.label28.TabIndex = 36; - this.label28.Text = "Product name"; - // - // label27 - // - this.label27.AutoSize = true; - this.label27.Location = new System.Drawing.Point(10, 101); - this.label27.Name = "label27"; - this.label27.Size = new System.Drawing.Size(55, 13); - this.label27.TabIndex = 35; - this.label27.Text = "Vendor ID"; - // - // label26 - // - this.label26.AutoSize = true; - this.label26.Location = new System.Drawing.Point(10, 75); - this.label26.Name = "label26"; - this.label26.Size = new System.Drawing.Size(70, 13); - this.label26.TabIndex = 34; - this.label26.Text = "Vendor name"; - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.checkBox_baud_auto); - this.groupBox1.Controls.Add(this.checkBox_baud_125); - this.groupBox1.Controls.Add(this.checkBox_baud_10); - this.groupBox1.Controls.Add(this.checkBox_baud_20); - this.groupBox1.Controls.Add(this.checkBox_baud_50); - this.groupBox1.Controls.Add(this.checkBox_baud_250); - this.groupBox1.Controls.Add(this.checkBox_baud_1000); - this.groupBox1.Controls.Add(this.checkBox_baud_500); - this.groupBox1.Controls.Add(this.checkBox_baud_800); - this.groupBox1.Location = new System.Drawing.Point(395, 14); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(120, 192); - this.groupBox1.TabIndex = 3; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Baudrates"; - // - // checkBox_baud_auto - // - this.checkBox_baud_auto.AutoSize = true; - this.checkBox_baud_auto.Location = new System.Drawing.Point(10, 163); - this.checkBox_baud_auto.Name = "checkBox_baud_auto"; - this.checkBox_baud_auto.Size = new System.Drawing.Size(47, 17); - this.checkBox_baud_auto.TabIndex = 8; - this.checkBox_baud_auto.Text = "auto"; - this.checkBox_baud_auto.UseVisualStyleBackColor = true; - // - // heckBox_baud_125 - // - this.checkBox_baud_125.AutoSize = true; - this.checkBox_baud_125.Location = new System.Drawing.Point(10, 72); - this.checkBox_baud_125.Name = "checkBox_baud_125"; - this.checkBox_baud_125.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_125.TabIndex = 3; - this.checkBox_baud_125.Text = "125 kbps"; - this.checkBox_baud_125.UseVisualStyleBackColor = true; - // - // checkBox_baud_10 - // - this.checkBox_baud_10.AutoSize = true; - this.checkBox_baud_10.Location = new System.Drawing.Point(10, 20); - this.checkBox_baud_10.Name = "checkBox_baud_10"; - this.checkBox_baud_10.Size = new System.Drawing.Size(64, 17); - this.checkBox_baud_10.TabIndex = 0; - this.checkBox_baud_10.Text = "10 kbps"; - this.checkBox_baud_10.UseVisualStyleBackColor = true; - // - // heckBox_baud_20 - // - this.checkBox_baud_20.AutoSize = true; - this.checkBox_baud_20.Location = new System.Drawing.Point(10, 37); - this.checkBox_baud_20.Name = "checkBox_baud_20"; - this.checkBox_baud_20.Size = new System.Drawing.Size(64, 17); - this.checkBox_baud_20.TabIndex = 1; - this.checkBox_baud_20.Text = "20 kbps"; - this.checkBox_baud_20.UseVisualStyleBackColor = true; - // - // checkBox_baud_50 - // - this.checkBox_baud_50.AutoSize = true; - this.checkBox_baud_50.Location = new System.Drawing.Point(10, 54); - this.checkBox_baud_50.Name = "checkBox_baud_50"; - this.checkBox_baud_50.Size = new System.Drawing.Size(64, 17); - this.checkBox_baud_50.TabIndex = 2; - this.checkBox_baud_50.Text = "50 kbps"; - this.checkBox_baud_50.UseVisualStyleBackColor = true; - // - // checkBox_baud_250 - // - this.checkBox_baud_250.AutoSize = true; - this.checkBox_baud_250.Location = new System.Drawing.Point(10, 90); - this.checkBox_baud_250.Name = "checkBox_baud_250"; - this.checkBox_baud_250.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_250.TabIndex = 4; - this.checkBox_baud_250.Text = "250 kbps"; - this.checkBox_baud_250.UseVisualStyleBackColor = true; - // - // checkBox_baud_1000 - // - this.checkBox_baud_1000.AutoSize = true; - this.checkBox_baud_1000.Location = new System.Drawing.Point(10, 145); - this.checkBox_baud_1000.Name = "checkBox_baud_1000"; - this.checkBox_baud_1000.Size = new System.Drawing.Size(76, 17); - this.checkBox_baud_1000.TabIndex = 7; - this.checkBox_baud_1000.Text = "1000 kbps"; - this.checkBox_baud_1000.UseVisualStyleBackColor = true; - // - // checkBox_baud_500 - // - this.checkBox_baud_500.AutoSize = true; - this.checkBox_baud_500.Location = new System.Drawing.Point(10, 109); - this.checkBox_baud_500.Name = "checkBox_baud_500"; - this.checkBox_baud_500.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_500.TabIndex = 5; - this.checkBox_baud_500.Text = "500 kbps"; - this.checkBox_baud_500.UseVisualStyleBackColor = true; - // - // checkBox_baud_800 - // - this.checkBox_baud_800.AutoSize = true; - this.checkBox_baud_800.Location = new System.Drawing.Point(10, 127); - this.checkBox_baud_800.Name = "checkBox_baud_800"; - this.checkBox_baud_800.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_800.TabIndex = 6; - this.checkBox_baud_800.Text = "800 kbps"; - this.checkBox_baud_800.UseVisualStyleBackColor = true; - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.textBox_granularity); - this.groupBox2.Controls.Add(this.label1); - this.groupBox2.Controls.Add(this.textBox_txpdos); - this.groupBox2.Controls.Add(this.checkBox_lssMaster); - this.groupBox2.Controls.Add(this.label30); - this.groupBox2.Controls.Add(this.textBox_rxpdos); - this.groupBox2.Controls.Add(this.label17); - this.groupBox2.Controls.Add(this.checkBox_lss); - this.groupBox2.Location = new System.Drawing.Point(521, 14); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(213, 192); - this.groupBox2.TabIndex = 4; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "General and Master Features"; - // - // textBox_granularity - // - this.textBox_granularity.Location = new System.Drawing.Point(102, 20); - this.textBox_granularity.Name = "textBox_granularity"; - this.textBox_granularity.Size = new System.Drawing.Size(101, 20); - this.textBox_granularity.TabIndex = 41; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(10, 23); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(57, 13); - this.label1.TabIndex = 40; - this.label1.Text = "Granularity"; - // - // textBox_txpdos - // - this.textBox_txpdos.Location = new System.Drawing.Point(102, 72); - this.textBox_txpdos.Name = "textBox_txpdos"; - this.textBox_txpdos.ReadOnly = true; - this.textBox_txpdos.Size = new System.Drawing.Size(101, 20); - this.textBox_txpdos.TabIndex = 1; - // - // checkBox_lssMaster - // - this.checkBox_lssMaster.AutoSize = true; - this.checkBox_lssMaster.Location = new System.Drawing.Point(10, 127); - this.checkBox_lssMaster.Name = "checkBox_lssMaster"; - this.checkBox_lssMaster.Size = new System.Drawing.Size(81, 17); - this.checkBox_lssMaster.TabIndex = 10; - this.checkBox_lssMaster.Text = "LSS Master"; - this.checkBox_lssMaster.UseVisualStyleBackColor = true; - // - // label30 - // - this.label30.AutoSize = true; - this.label30.Location = new System.Drawing.Point(10, 75); - this.label30.Name = "label30"; - this.label30.Size = new System.Drawing.Size(67, 13); - this.label30.TabIndex = 39; - this.label30.Text = "TPDO count"; - // - // textBox_rxpdos - // - this.textBox_rxpdos.Location = new System.Drawing.Point(102, 46); - this.textBox_rxpdos.Name = "textBox_rxpdos"; - this.textBox_rxpdos.ReadOnly = true; - this.textBox_rxpdos.Size = new System.Drawing.Size(101, 20); - this.textBox_rxpdos.TabIndex = 0; - // - // label17 - // - this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(10, 49); - this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(68, 13); - this.label17.TabIndex = 38; - this.label17.Text = "RPDO count"; - // - // checkBox_lss - // - this.checkBox_lss.AutoSize = true; - this.checkBox_lss.Location = new System.Drawing.Point(10, 109); - this.checkBox_lss.Name = "checkBox_lss"; - this.checkBox_lss.Size = new System.Drawing.Size(76, 17); - this.checkBox_lss.TabIndex = 6; - this.checkBox_lss.Text = "LSS Slave"; - this.checkBox_lss.UseVisualStyleBackColor = true; - // - // groupBox3 - // - this.groupBox3.Controls.Add(this.textBox_modifiedby); - this.groupBox3.Controls.Add(this.textBox_modified_datetime); - this.groupBox3.Controls.Add(this.textBox_createdby); - this.groupBox3.Controls.Add(this.textBox_create_datetime); - this.groupBox3.Controls.Add(this.textBox_di_description); - this.groupBox3.Controls.Add(this.textBox_fileversion); - this.groupBox3.Controls.Add(this.label25); - this.groupBox3.Controls.Add(this.label24); - this.groupBox3.Controls.Add(this.label23); - this.groupBox3.Controls.Add(this.label22); - this.groupBox3.Controls.Add(this.label20); - this.groupBox3.Controls.Add(this.label18); - this.groupBox3.Location = new System.Drawing.Point(12, 146); - this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(377, 180); - this.groupBox3.TabIndex = 1; - this.groupBox3.TabStop = false; - this.groupBox3.Text = "File Info"; - // - // textBox_modifiedby - // - this.textBox_modifiedby.Location = new System.Drawing.Point(139, 150); - this.textBox_modifiedby.Name = "textBox_modifiedby"; - this.textBox_modifiedby.Size = new System.Drawing.Size(226, 20); - this.textBox_modifiedby.TabIndex = 7; - // - // textBox_modified_datetime - // - this.textBox_modified_datetime.Location = new System.Drawing.Point(139, 124); - this.textBox_modified_datetime.Name = "textBox_modified_datetime"; - this.textBox_modified_datetime.ReadOnly = true; - this.textBox_modified_datetime.Size = new System.Drawing.Size(226, 20); - this.textBox_modified_datetime.TabIndex = 6; - // - // textBox_createdby - // - this.textBox_createdby.Location = new System.Drawing.Point(139, 98); - this.textBox_createdby.Name = "textBox_createdby"; - this.textBox_createdby.Size = new System.Drawing.Size(226, 20); - this.textBox_createdby.TabIndex = 5; - // - // textBox_create_datetime - // - this.textBox_create_datetime.Location = new System.Drawing.Point(139, 72); - this.textBox_create_datetime.Name = "textBox_create_datetime"; - this.textBox_create_datetime.Size = new System.Drawing.Size(226, 20); - this.textBox_create_datetime.TabIndex = 4; - // - // textBox_di_description - // - this.textBox_di_description.Location = new System.Drawing.Point(139, 46); - this.textBox_di_description.Name = "textBox_di_description"; - this.textBox_di_description.Size = new System.Drawing.Size(226, 20); - this.textBox_di_description.TabIndex = 3; - // - // textBox_fileversion - // - this.textBox_fileversion.Location = new System.Drawing.Point(139, 20); - this.textBox_fileversion.Name = "textBox_fileversion"; - this.textBox_fileversion.Size = new System.Drawing.Size(226, 20); - this.textBox_fileversion.TabIndex = 0; - // - // label25 - // - this.label25.AutoSize = true; - this.label25.Location = new System.Drawing.Point(10, 153); - this.label25.Name = "label25"; - this.label25.Size = new System.Drawing.Size(61, 13); - this.label25.TabIndex = 25; - this.label25.Text = "Modified by"; - // - // label24 - // - this.label24.AutoSize = true; - this.label24.Location = new System.Drawing.Point(10, 127); - this.label24.Name = "label24"; - this.label24.Size = new System.Drawing.Size(118, 13); - this.label24.TabIndex = 24; - this.label24.Text = "Modification Date/Time"; - // - // label23 - // - this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(10, 101); - this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(59, 13); - this.label23.TabIndex = 23; - this.label23.Text = "Created By"; - // - // label22 - // - this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(10, 75); - this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(100, 13); - this.label22.TabIndex = 22; - this.label22.Text = "Creation Date/Time"; - // - // label20 - // - this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(10, 49); - this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(60, 13); - this.label20.TabIndex = 20; - this.label20.Text = "Description"; - // - // label18 - // - this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(10, 23); - this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(60, 13); - this.label18.TabIndex = 18; - this.label18.Text = "File version"; - // - // button_update_devfile_info - // - this.button_update_devfile_info.Location = new System.Drawing.Point(405, 441); - this.button_update_devfile_info.Name = "button_update_devfile_info"; - this.button_update_devfile_info.Size = new System.Drawing.Size(318, 35); - this.button_update_devfile_info.TabIndex = 10; - this.button_update_devfile_info.Text = "Update"; - this.button_update_devfile_info.UseVisualStyleBackColor = true; - this.button_update_devfile_info.Click += new System.EventHandler(this.button_update_devfile_info_Click); - // - // DeviceInfoView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.panel1); - this.Name = "DeviceInfoView"; - this.Size = new System.Drawing.Size(773, 537); - this.panel1.ResumeLayout(false); - this.groupBox5.ResumeLayout(false); - this.groupBox5.PerformLayout(); - this.groupBox6.ResumeLayout(false); - this.groupBox6.PerformLayout(); - this.groupBox4.ResumeLayout(false); - this.groupBox4.PerformLayout(); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); - this.groupBox3.ResumeLayout(false); - this.groupBox3.PerformLayout(); - this.ResumeLayout(false); - + this.panel1 = new System.Windows.Forms.Panel(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox_mdFileName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox_xddfilenameStripped = new System.Windows.Forms.TextBox(); + this.textBox_canopennodeFileVersion = new System.Windows.Forms.TextBox(); + this.textBox_projectFileVersion = new System.Windows.Forms.TextBox(); + this.textBox_devicedcfname = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.textBox_canopennodeFileName = new System.Windows.Forms.TextBox(); + this.label16 = new System.Windows.Forms.Label(); + this.label31 = new System.Windows.Forms.Label(); + this.textBox_projectFileName = new System.Windows.Forms.TextBox(); + this.textBox_deviceedsname = new System.Windows.Forms.TextBox(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox_lssserial = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.checkBox_canopenmanager = new System.Windows.Forms.CheckBox(); + this.label8 = new System.Windows.Forms.Label(); + this.textBox_netname = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.textBox_netnum = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.textBox_baudrate = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.textBox_nodename = new System.Windows.Forms.TextBox(); + this.label32 = new System.Windows.Forms.Label(); + this.textBox_concretenodeid = new System.Windows.Forms.TextBox(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.textBox_productnumber = new System.Windows.Forms.TextBox(); + this.textBox_productname = new System.Windows.Forms.TextBox(); + this.textBox_vendornumber = new System.Windows.Forms.TextBox(); + this.textBox_vendorname = new System.Windows.Forms.TextBox(); + this.label29 = new System.Windows.Forms.Label(); + this.label28 = new System.Windows.Forms.Label(); + this.label27 = new System.Windows.Forms.Label(); + this.label26 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.checkBox_baud_auto = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_125 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_10 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_20 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_50 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_250 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_1000 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_500 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_800 = new System.Windows.Forms.CheckBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox_granularity = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox_txpdos = new System.Windows.Forms.TextBox(); + this.checkBox_lssMaster = new System.Windows.Forms.CheckBox(); + this.label30 = new System.Windows.Forms.Label(); + this.textBox_rxpdos = new System.Windows.Forms.TextBox(); + this.label17 = new System.Windows.Forms.Label(); + this.checkBox_lss = new System.Windows.Forms.CheckBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.textBox_modifiedby = new System.Windows.Forms.TextBox(); + this.textBox_modified_datetime = new System.Windows.Forms.TextBox(); + this.textBox_createdby = new System.Windows.Forms.TextBox(); + this.textBox_create_datetime = new System.Windows.Forms.TextBox(); + this.textBox_di_description = new System.Windows.Forms.TextBox(); + this.textBox_fileversion = new System.Windows.Forms.TextBox(); + this.label25 = new System.Windows.Forms.Label(); + this.label24 = new System.Windows.Forms.Label(); + this.label23 = new System.Windows.Forms.Label(); + this.label22 = new System.Windows.Forms.Label(); + this.label20 = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.panel1.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.groupBox6.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.groupBox5); + this.panel1.Controls.Add(this.groupBox6); + this.panel1.Controls.Add(this.groupBox4); + this.panel1.Controls.Add(this.groupBox1); + this.panel1.Controls.Add(this.groupBox2); + this.panel1.Controls.Add(this.groupBox3); + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Margin = new System.Windows.Forms.Padding(4); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(1031, 661); + this.panel1.TabIndex = 60; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.label4); + this.groupBox5.Controls.Add(this.textBox_mdFileName); + this.groupBox5.Controls.Add(this.label2); + this.groupBox5.Controls.Add(this.textBox_xddfilenameStripped); + this.groupBox5.Controls.Add(this.textBox_canopennodeFileVersion); + this.groupBox5.Controls.Add(this.textBox_projectFileVersion); + this.groupBox5.Controls.Add(this.textBox_devicedcfname); + this.groupBox5.Controls.Add(this.label14); + this.groupBox5.Controls.Add(this.label15); + this.groupBox5.Controls.Add(this.textBox_canopennodeFileName); + this.groupBox5.Controls.Add(this.label16); + this.groupBox5.Controls.Add(this.label31); + this.groupBox5.Controls.Add(this.textBox_projectFileName); + this.groupBox5.Controls.Add(this.textBox_deviceedsname); + this.groupBox5.Location = new System.Drawing.Point(16, 409); + this.groupBox5.Margin = new System.Windows.Forms.Padding(4); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Padding = new System.Windows.Forms.Padding(4); + this.groupBox5.Size = new System.Drawing.Size(503, 224); + this.groupBox5.TabIndex = 63; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Project Info"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(13, 188); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(117, 16); + this.label4.TabIndex = 70; + this.label4.Text = "Documentation file"; + // + // textBox_mdFileName + // + this.textBox_mdFileName.Location = new System.Drawing.Point(185, 185); + this.textBox_mdFileName.Margin = new System.Windows.Forms.Padding(4); + this.textBox_mdFileName.Name = "textBox_mdFileName"; + this.textBox_mdFileName.ReadOnly = true; + this.textBox_mdFileName.Size = new System.Drawing.Size(300, 22); + this.textBox_mdFileName.TabIndex = 69; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(13, 60); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(141, 16); + this.label2.TabIndex = 68; + this.label2.Text = "XDD v1.1 file - stripped"; + // + // textBox_xddfilenameStripped + // + this.textBox_xddfilenameStripped.Location = new System.Drawing.Point(185, 57); + this.textBox_xddfilenameStripped.Margin = new System.Windows.Forms.Padding(4); + this.textBox_xddfilenameStripped.Name = "textBox_xddfilenameStripped"; + this.textBox_xddfilenameStripped.ReadOnly = true; + this.textBox_xddfilenameStripped.Size = new System.Drawing.Size(300, 22); + this.textBox_xddfilenameStripped.TabIndex = 67; + // + // textBox_canopennodeFileVersion + // + this.textBox_canopennodeFileVersion.Location = new System.Drawing.Point(440, 153); + this.textBox_canopennodeFileVersion.Margin = new System.Windows.Forms.Padding(4); + this.textBox_canopennodeFileVersion.Name = "textBox_canopennodeFileVersion"; + this.textBox_canopennodeFileVersion.ReadOnly = true; + this.textBox_canopennodeFileVersion.Size = new System.Drawing.Size(45, 22); + this.textBox_canopennodeFileVersion.TabIndex = 66; + // + // textBox_projectFileVersion + // + this.textBox_projectFileVersion.Location = new System.Drawing.Point(440, 25); + this.textBox_projectFileVersion.Margin = new System.Windows.Forms.Padding(4); + this.textBox_projectFileVersion.Name = "textBox_projectFileVersion"; + this.textBox_projectFileVersion.ReadOnly = true; + this.textBox_projectFileVersion.Size = new System.Drawing.Size(45, 22); + this.textBox_projectFileVersion.TabIndex = 65; + // + // textBox_devicedcfname + // + this.textBox_devicedcfname.Location = new System.Drawing.Point(185, 121); + this.textBox_devicedcfname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_devicedcfname.Name = "textBox_devicedcfname"; + this.textBox_devicedcfname.ReadOnly = true; + this.textBox_devicedcfname.Size = new System.Drawing.Size(300, 22); + this.textBox_devicedcfname.TabIndex = 8; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(13, 156); + this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(150, 16); + this.label14.TabIndex = 21; + this.label14.Text = "CANopenNode file (ver)"; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(13, 124); + this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(54, 16); + this.label15.TabIndex = 20; + this.label15.Text = "DCF file"; + // + // textBox_canopennodeFileName + // + this.textBox_canopennodeFileName.Location = new System.Drawing.Point(185, 153); + this.textBox_canopennodeFileName.Margin = new System.Windows.Forms.Padding(4); + this.textBox_canopennodeFileName.Name = "textBox_canopennodeFileName"; + this.textBox_canopennodeFileName.ReadOnly = true; + this.textBox_canopennodeFileName.Size = new System.Drawing.Size(245, 22); + this.textBox_canopennodeFileName.TabIndex = 9; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(13, 92); + this.label16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(55, 16); + this.label16.TabIndex = 19; + this.label16.Text = "EDS file"; + // + // label31 + // + this.label31.AutoSize = true; + this.label31.Location = new System.Drawing.Point(13, 28); + this.label31.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(124, 16); + this.label31.TabIndex = 18; + this.label31.Text = "Project file (version)"; + // + // textBox_projectFileName + // + this.textBox_projectFileName.Location = new System.Drawing.Point(185, 25); + this.textBox_projectFileName.Margin = new System.Windows.Forms.Padding(4); + this.textBox_projectFileName.Name = "textBox_projectFileName"; + this.textBox_projectFileName.ReadOnly = true; + this.textBox_projectFileName.Size = new System.Drawing.Size(245, 22); + this.textBox_projectFileName.TabIndex = 6; + // + // textBox_deviceedsname + // + this.textBox_deviceedsname.Location = new System.Drawing.Point(185, 89); + this.textBox_deviceedsname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_deviceedsname.Name = "textBox_deviceedsname"; + this.textBox_deviceedsname.ReadOnly = true; + this.textBox_deviceedsname.Size = new System.Drawing.Size(300, 22); + this.textBox_deviceedsname.TabIndex = 7; + // + // groupBox6 + // + this.groupBox6.Controls.Add(this.label3); + this.groupBox6.Controls.Add(this.textBox_lssserial); + this.groupBox6.Controls.Add(this.label9); + this.groupBox6.Controls.Add(this.checkBox_canopenmanager); + this.groupBox6.Controls.Add(this.label8); + this.groupBox6.Controls.Add(this.textBox_netname); + this.groupBox6.Controls.Add(this.label7); + this.groupBox6.Controls.Add(this.textBox_netnum); + this.groupBox6.Controls.Add(this.label6); + this.groupBox6.Controls.Add(this.textBox_baudrate); + this.groupBox6.Controls.Add(this.label5); + this.groupBox6.Controls.Add(this.textBox_nodename); + this.groupBox6.Controls.Add(this.label32); + this.groupBox6.Controls.Add(this.textBox_concretenodeid); + this.groupBox6.Location = new System.Drawing.Point(527, 258); + this.groupBox6.Margin = new System.Windows.Forms.Padding(4); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Padding = new System.Windows.Forms.Padding(4); + this.groupBox6.Size = new System.Drawing.Size(452, 245); + this.groupBox6.TabIndex = 5; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Device commissioning"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(9, 183); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(123, 16); + this.label3.TabIndex = 63; + this.label3.Text = "CANopen Manager"; + // + // textBox_lssserial + // + this.textBox_lssserial.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_lssserial.Location = new System.Drawing.Point(148, 210); + this.textBox_lssserial.Margin = new System.Windows.Forms.Padding(4); + this.textBox_lssserial.Name = "textBox_lssserial"; + this.textBox_lssserial.Size = new System.Drawing.Size(289, 22); + this.textBox_lssserial.TabIndex = 7; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(9, 214); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(88, 16); + this.label9.TabIndex = 6; + this.label9.Text = "LSS Serial no"; + // + // checkBox_canopenmanager + // + this.checkBox_canopenmanager.AutoSize = true; + this.checkBox_canopenmanager.BackColor = System.Drawing.Color.PeachPuff; + this.checkBox_canopenmanager.Location = new System.Drawing.Point(148, 182); + this.checkBox_canopenmanager.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_canopenmanager.Name = "checkBox_canopenmanager"; + this.checkBox_canopenmanager.Padding = new System.Windows.Forms.Padding(0, 0, 269, 0); + this.checkBox_canopenmanager.Size = new System.Drawing.Size(287, 17); + this.checkBox_canopenmanager.TabIndex = 5; + this.checkBox_canopenmanager.UseVisualStyleBackColor = false; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(9, 154); + this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(65, 16); + this.label8.TabIndex = 62; + this.label8.Text = "Net name"; + // + // textBox_netname + // + this.textBox_netname.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_netname.Location = new System.Drawing.Point(148, 150); + this.textBox_netname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_netname.Name = "textBox_netname"; + this.textBox_netname.Size = new System.Drawing.Size(289, 22); + this.textBox_netname.TabIndex = 4; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(9, 122); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(76, 16); + this.label7.TabIndex = 60; + this.label7.Text = "Net number"; + // + // textBox_netnum + // + this.textBox_netnum.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_netnum.Location = new System.Drawing.Point(148, 118); + this.textBox_netnum.Margin = new System.Windows.Forms.Padding(4); + this.textBox_netnum.Name = "textBox_netnum"; + this.textBox_netnum.Size = new System.Drawing.Size(289, 22); + this.textBox_netnum.TabIndex = 3; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(9, 91); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(62, 16); + this.label6.TabIndex = 58; + this.label6.Text = "Baudrate"; + // + // textBox_baudrate + // + this.textBox_baudrate.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_baudrate.Location = new System.Drawing.Point(148, 87); + this.textBox_baudrate.Margin = new System.Windows.Forms.Padding(4); + this.textBox_baudrate.Name = "textBox_baudrate"; + this.textBox_baudrate.Size = new System.Drawing.Size(289, 22); + this.textBox_baudrate.TabIndex = 2; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(9, 59); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(78, 16); + this.label5.TabIndex = 56; + this.label5.Text = "Node name"; + // + // textBox_nodename + // + this.textBox_nodename.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_nodename.Location = new System.Drawing.Point(148, 55); + this.textBox_nodename.Margin = new System.Windows.Forms.Padding(4); + this.textBox_nodename.Name = "textBox_nodename"; + this.textBox_nodename.Size = new System.Drawing.Size(289, 22); + this.textBox_nodename.TabIndex = 1; + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(9, 27); + this.label32.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(111, 16); + this.label32.TabIndex = 53; + this.label32.Text = "Concrete node ID"; + // + // textBox_concretenodeid + // + this.textBox_concretenodeid.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_concretenodeid.Location = new System.Drawing.Point(148, 23); + this.textBox_concretenodeid.Margin = new System.Windows.Forms.Padding(4); + this.textBox_concretenodeid.Name = "textBox_concretenodeid"; + this.textBox_concretenodeid.Size = new System.Drawing.Size(289, 22); + this.textBox_concretenodeid.TabIndex = 0; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.textBox_productnumber); + this.groupBox4.Controls.Add(this.textBox_productname); + this.groupBox4.Controls.Add(this.textBox_vendornumber); + this.groupBox4.Controls.Add(this.textBox_vendorname); + this.groupBox4.Controls.Add(this.label29); + this.groupBox4.Controls.Add(this.label28); + this.groupBox4.Controls.Add(this.label27); + this.groupBox4.Controls.Add(this.label26); + this.groupBox4.Location = new System.Drawing.Point(16, 17); + this.groupBox4.Margin = new System.Windows.Forms.Padding(4); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Padding = new System.Windows.Forms.Padding(4); + this.groupBox4.Size = new System.Drawing.Size(503, 155); + this.groupBox4.TabIndex = 0; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Device Info"; + // + // textBox_productnumber + // + this.textBox_productnumber.Location = new System.Drawing.Point(185, 57); + this.textBox_productnumber.Margin = new System.Windows.Forms.Padding(4); + this.textBox_productnumber.Name = "textBox_productnumber"; + this.textBox_productnumber.Size = new System.Drawing.Size(300, 22); + this.textBox_productnumber.TabIndex = 1; + // + // textBox_productname + // + this.textBox_productname.Location = new System.Drawing.Point(185, 25); + this.textBox_productname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_productname.Name = "textBox_productname"; + this.textBox_productname.Size = new System.Drawing.Size(300, 22); + this.textBox_productname.TabIndex = 0; + // + // textBox_vendornumber + // + this.textBox_vendornumber.Location = new System.Drawing.Point(185, 121); + this.textBox_vendornumber.Margin = new System.Windows.Forms.Padding(4); + this.textBox_vendornumber.Name = "textBox_vendornumber"; + this.textBox_vendornumber.Size = new System.Drawing.Size(300, 22); + this.textBox_vendornumber.TabIndex = 3; + // + // textBox_vendorname + // + this.textBox_vendorname.Location = new System.Drawing.Point(185, 89); + this.textBox_vendorname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_vendorname.Name = "textBox_vendorname"; + this.textBox_vendorname.Size = new System.Drawing.Size(300, 22); + this.textBox_vendorname.TabIndex = 2; + // + // label29 + // + this.label29.AutoSize = true; + this.label29.Location = new System.Drawing.Point(13, 60); + this.label29.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(69, 16); + this.label29.TabIndex = 37; + this.label29.Text = "Product ID"; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(13, 28); + this.label28.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(90, 16); + this.label28.TabIndex = 36; + this.label28.Text = "Product name"; + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(13, 124); + this.label27.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(67, 16); + this.label27.TabIndex = 35; + this.label27.Text = "Vendor ID"; + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(13, 92); + this.label26.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(88, 16); + this.label26.TabIndex = 34; + this.label26.Text = "Vendor name"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.checkBox_baud_auto); + this.groupBox1.Controls.Add(this.checkBox_baud_125); + this.groupBox1.Controls.Add(this.checkBox_baud_10); + this.groupBox1.Controls.Add(this.checkBox_baud_20); + this.groupBox1.Controls.Add(this.checkBox_baud_50); + this.groupBox1.Controls.Add(this.checkBox_baud_250); + this.groupBox1.Controls.Add(this.checkBox_baud_1000); + this.groupBox1.Controls.Add(this.checkBox_baud_500); + this.groupBox1.Controls.Add(this.checkBox_baud_800); + this.groupBox1.Location = new System.Drawing.Point(527, 17); + this.groupBox1.Margin = new System.Windows.Forms.Padding(4); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(4); + this.groupBox1.Size = new System.Drawing.Size(160, 236); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Baudrates"; + // + // checkBox_baud_auto + // + this.checkBox_baud_auto.AutoSize = true; + this.checkBox_baud_auto.Location = new System.Drawing.Point(13, 201); + this.checkBox_baud_auto.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_auto.Name = "checkBox_baud_auto"; + this.checkBox_baud_auto.Size = new System.Drawing.Size(55, 20); + this.checkBox_baud_auto.TabIndex = 8; + this.checkBox_baud_auto.Text = "auto"; + this.checkBox_baud_auto.UseVisualStyleBackColor = true; + // + // checkBox_baud_125 + // + this.checkBox_baud_125.AutoSize = true; + this.checkBox_baud_125.Location = new System.Drawing.Point(13, 89); + this.checkBox_baud_125.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_125.Name = "checkBox_baud_125"; + this.checkBox_baud_125.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_125.TabIndex = 3; + this.checkBox_baud_125.Text = "125 kbps"; + this.checkBox_baud_125.UseVisualStyleBackColor = true; + // + // checkBox_baud_10 + // + this.checkBox_baud_10.AutoSize = true; + this.checkBox_baud_10.Location = new System.Drawing.Point(13, 25); + this.checkBox_baud_10.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_10.Name = "checkBox_baud_10"; + this.checkBox_baud_10.Size = new System.Drawing.Size(76, 20); + this.checkBox_baud_10.TabIndex = 0; + this.checkBox_baud_10.Text = "10 kbps"; + this.checkBox_baud_10.UseVisualStyleBackColor = true; + // + // checkBox_baud_20 + // + this.checkBox_baud_20.AutoSize = true; + this.checkBox_baud_20.Location = new System.Drawing.Point(13, 46); + this.checkBox_baud_20.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_20.Name = "checkBox_baud_20"; + this.checkBox_baud_20.Size = new System.Drawing.Size(76, 20); + this.checkBox_baud_20.TabIndex = 1; + this.checkBox_baud_20.Text = "20 kbps"; + this.checkBox_baud_20.UseVisualStyleBackColor = true; + // + // checkBox_baud_50 + // + this.checkBox_baud_50.AutoSize = true; + this.checkBox_baud_50.Location = new System.Drawing.Point(13, 66); + this.checkBox_baud_50.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_50.Name = "checkBox_baud_50"; + this.checkBox_baud_50.Size = new System.Drawing.Size(76, 20); + this.checkBox_baud_50.TabIndex = 2; + this.checkBox_baud_50.Text = "50 kbps"; + this.checkBox_baud_50.UseVisualStyleBackColor = true; + // + // checkBox_baud_250 + // + this.checkBox_baud_250.AutoSize = true; + this.checkBox_baud_250.Location = new System.Drawing.Point(13, 111); + this.checkBox_baud_250.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_250.Name = "checkBox_baud_250"; + this.checkBox_baud_250.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_250.TabIndex = 4; + this.checkBox_baud_250.Text = "250 kbps"; + this.checkBox_baud_250.UseVisualStyleBackColor = true; + // + // checkBox_baud_1000 + // + this.checkBox_baud_1000.AutoSize = true; + this.checkBox_baud_1000.Location = new System.Drawing.Point(13, 178); + this.checkBox_baud_1000.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_1000.Name = "checkBox_baud_1000"; + this.checkBox_baud_1000.Size = new System.Drawing.Size(90, 20); + this.checkBox_baud_1000.TabIndex = 7; + this.checkBox_baud_1000.Text = "1000 kbps"; + this.checkBox_baud_1000.UseVisualStyleBackColor = true; + // + // checkBox_baud_500 + // + this.checkBox_baud_500.AutoSize = true; + this.checkBox_baud_500.Location = new System.Drawing.Point(13, 134); + this.checkBox_baud_500.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_500.Name = "checkBox_baud_500"; + this.checkBox_baud_500.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_500.TabIndex = 5; + this.checkBox_baud_500.Text = "500 kbps"; + this.checkBox_baud_500.UseVisualStyleBackColor = true; + // + // checkBox_baud_800 + // + this.checkBox_baud_800.AutoSize = true; + this.checkBox_baud_800.Location = new System.Drawing.Point(13, 156); + this.checkBox_baud_800.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_800.Name = "checkBox_baud_800"; + this.checkBox_baud_800.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_800.TabIndex = 6; + this.checkBox_baud_800.Text = "800 kbps"; + this.checkBox_baud_800.UseVisualStyleBackColor = true; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.textBox_granularity); + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Controls.Add(this.textBox_txpdos); + this.groupBox2.Controls.Add(this.checkBox_lssMaster); + this.groupBox2.Controls.Add(this.label30); + this.groupBox2.Controls.Add(this.textBox_rxpdos); + this.groupBox2.Controls.Add(this.label17); + this.groupBox2.Controls.Add(this.checkBox_lss); + this.groupBox2.Location = new System.Drawing.Point(695, 17); + this.groupBox2.Margin = new System.Windows.Forms.Padding(4); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Padding = new System.Windows.Forms.Padding(4); + this.groupBox2.Size = new System.Drawing.Size(284, 236); + this.groupBox2.TabIndex = 4; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "General and Master Features"; + // + // textBox_granularity + // + this.textBox_granularity.Location = new System.Drawing.Point(136, 25); + this.textBox_granularity.Margin = new System.Windows.Forms.Padding(4); + this.textBox_granularity.Name = "textBox_granularity"; + this.textBox_granularity.Size = new System.Drawing.Size(133, 22); + this.textBox_granularity.TabIndex = 41; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(13, 28); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(71, 16); + this.label1.TabIndex = 40; + this.label1.Text = "Granularity"; + // + // textBox_txpdos + // + this.textBox_txpdos.Location = new System.Drawing.Point(136, 89); + this.textBox_txpdos.Margin = new System.Windows.Forms.Padding(4); + this.textBox_txpdos.Name = "textBox_txpdos"; + this.textBox_txpdos.ReadOnly = true; + this.textBox_txpdos.Size = new System.Drawing.Size(133, 22); + this.textBox_txpdos.TabIndex = 1; + // + // checkBox_lssMaster + // + this.checkBox_lssMaster.AutoSize = true; + this.checkBox_lssMaster.Location = new System.Drawing.Point(13, 156); + this.checkBox_lssMaster.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_lssMaster.Name = "checkBox_lssMaster"; + this.checkBox_lssMaster.Size = new System.Drawing.Size(98, 20); + this.checkBox_lssMaster.TabIndex = 10; + this.checkBox_lssMaster.Text = "LSS Master"; + this.checkBox_lssMaster.UseVisualStyleBackColor = true; + // + // label30 + // + this.label30.AutoSize = true; + this.label30.Location = new System.Drawing.Point(13, 92); + this.label30.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(80, 16); + this.label30.TabIndex = 39; + this.label30.Text = "TPDO count"; + // + // textBox_rxpdos + // + this.textBox_rxpdos.Location = new System.Drawing.Point(136, 57); + this.textBox_rxpdos.Margin = new System.Windows.Forms.Padding(4); + this.textBox_rxpdos.Name = "textBox_rxpdos"; + this.textBox_rxpdos.ReadOnly = true; + this.textBox_rxpdos.Size = new System.Drawing.Size(133, 22); + this.textBox_rxpdos.TabIndex = 0; + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(13, 60); + this.label17.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(81, 16); + this.label17.TabIndex = 38; + this.label17.Text = "RPDO count"; + // + // checkBox_lss + // + this.checkBox_lss.AutoSize = true; + this.checkBox_lss.Location = new System.Drawing.Point(13, 134); + this.checkBox_lss.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_lss.Name = "checkBox_lss"; + this.checkBox_lss.Size = new System.Drawing.Size(92, 20); + this.checkBox_lss.TabIndex = 6; + this.checkBox_lss.Text = "LSS Slave"; + this.checkBox_lss.UseVisualStyleBackColor = true; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.textBox_modifiedby); + this.groupBox3.Controls.Add(this.textBox_modified_datetime); + this.groupBox3.Controls.Add(this.textBox_createdby); + this.groupBox3.Controls.Add(this.textBox_create_datetime); + this.groupBox3.Controls.Add(this.textBox_di_description); + this.groupBox3.Controls.Add(this.textBox_fileversion); + this.groupBox3.Controls.Add(this.label25); + this.groupBox3.Controls.Add(this.label24); + this.groupBox3.Controls.Add(this.label23); + this.groupBox3.Controls.Add(this.label22); + this.groupBox3.Controls.Add(this.label20); + this.groupBox3.Controls.Add(this.label18); + this.groupBox3.Location = new System.Drawing.Point(16, 180); + this.groupBox3.Margin = new System.Windows.Forms.Padding(4); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Padding = new System.Windows.Forms.Padding(4); + this.groupBox3.Size = new System.Drawing.Size(503, 222); + this.groupBox3.TabIndex = 1; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "File Info"; + // + // textBox_modifiedby + // + this.textBox_modifiedby.Location = new System.Drawing.Point(185, 185); + this.textBox_modifiedby.Margin = new System.Windows.Forms.Padding(4); + this.textBox_modifiedby.Name = "textBox_modifiedby"; + this.textBox_modifiedby.Size = new System.Drawing.Size(300, 22); + this.textBox_modifiedby.TabIndex = 7; + // + // textBox_modified_datetime + // + this.textBox_modified_datetime.Location = new System.Drawing.Point(185, 153); + this.textBox_modified_datetime.Margin = new System.Windows.Forms.Padding(4); + this.textBox_modified_datetime.Name = "textBox_modified_datetime"; + this.textBox_modified_datetime.ReadOnly = true; + this.textBox_modified_datetime.Size = new System.Drawing.Size(300, 22); + this.textBox_modified_datetime.TabIndex = 6; + // + // textBox_createdby + // + this.textBox_createdby.Location = new System.Drawing.Point(185, 121); + this.textBox_createdby.Margin = new System.Windows.Forms.Padding(4); + this.textBox_createdby.Name = "textBox_createdby"; + this.textBox_createdby.Size = new System.Drawing.Size(300, 22); + this.textBox_createdby.TabIndex = 5; + // + // textBox_create_datetime + // + this.textBox_create_datetime.Location = new System.Drawing.Point(185, 89); + this.textBox_create_datetime.Margin = new System.Windows.Forms.Padding(4); + this.textBox_create_datetime.Name = "textBox_create_datetime"; + this.textBox_create_datetime.Size = new System.Drawing.Size(300, 22); + this.textBox_create_datetime.TabIndex = 4; + // + // textBox_di_description + // + this.textBox_di_description.Location = new System.Drawing.Point(185, 57); + this.textBox_di_description.Margin = new System.Windows.Forms.Padding(4); + this.textBox_di_description.Name = "textBox_di_description"; + this.textBox_di_description.Size = new System.Drawing.Size(300, 22); + this.textBox_di_description.TabIndex = 3; + // + // textBox_fileversion + // + this.textBox_fileversion.Location = new System.Drawing.Point(185, 25); + this.textBox_fileversion.Margin = new System.Windows.Forms.Padding(4); + this.textBox_fileversion.Name = "textBox_fileversion"; + this.textBox_fileversion.Size = new System.Drawing.Size(300, 22); + this.textBox_fileversion.TabIndex = 0; + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(13, 188); + this.label25.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(77, 16); + this.label25.TabIndex = 25; + this.label25.Text = "Modified by"; + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(13, 156); + this.label24.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(146, 16); + this.label24.TabIndex = 24; + this.label24.Text = "Modification Date/Time"; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(13, 124); + this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(74, 16); + this.label23.TabIndex = 23; + this.label23.Text = "Created By"; + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(13, 92); + this.label22.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(124, 16); + this.label22.TabIndex = 22; + this.label22.Text = "Creation Date/Time"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(13, 60); + this.label20.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(75, 16); + this.label20.TabIndex = 20; + this.label20.Text = "Description"; + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(13, 28); + this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(76, 16); + this.label18.TabIndex = 18; + this.label18.Text = "File version"; + // + // DeviceInfoView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.panel1); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "DeviceInfoView"; + this.Size = new System.Drawing.Size(1031, 661); + this.panel1.ResumeLayout(false); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); + this.groupBox6.ResumeLayout(false); + this.groupBox6.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + } #endregion private System.Windows.Forms.TextBox textBox_concretenodeid; private System.Windows.Forms.Label label32; - private System.Windows.Forms.Button button_update_devfile_info; private System.Windows.Forms.TextBox textBox_txpdos; private System.Windows.Forms.TextBox textBox_rxpdos; private System.Windows.Forms.Label label30; diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 31372a04..2c57c53a 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -97,21 +97,16 @@ public void populatedeviceinfo() } - - void InputControls_OnChange(object sender, EventArgs e) - { - // Do something to indicate the form is dirty like: - button_update_devfile_info.BackColor = System.Drawing.Color.Red; - } + void AddOnChangeHandlerToInputControls(ControlCollection ctrl) { foreach (Control subctrl in ctrl) { - //if (subctrl is TextBox) - // ((TextBox)subctrl).TextChanged += - // new EventHandler(InputControls_OnChange); - //else + if (subctrl is TextBox) + ((TextBox)subctrl).TextChanged += + new EventHandler(InputControls_OnChange); + else if (subctrl is CheckBox) ((CheckBox)subctrl).CheckedChanged += new EventHandler(InputControls_OnChange); @@ -121,11 +116,9 @@ void AddOnChangeHandlerToInputControls(ControlCollection ctrl) this.AddOnChangeHandlerToInputControls(subctrl.Controls); } } - } + } - - - private void button_update_devfile_info_Click(object sender, EventArgs e) + private void update_devfile_info() { if (eds == null) return; @@ -172,14 +165,18 @@ private void button_update_devfile_info_Click(object sender, EventArgs e) eds.dc.LSS_SerialNumber = Convert.ToUInt32(textBox_lssserial.Text); eds.Dirty = true; - button_update_devfile_info.BackColor = SystemColors.ButtonFace; - button_update_devfile_info.UseVisualStyleBackColor = true; } catch (Exception ex) { MessageBox.Show("Update failed, reason :-\n" + ex.ToString()); } - } + } + + void InputControls_OnChange(object sender, EventArgs e) + { + // Changes detected: Update the device info + update_devfile_info(); + } } } diff --git a/EDSEditorGUI/DeviceInfoView.resx b/EDSEditorGUI/DeviceInfoView.resx index 1af7de15..29dcb1b3 100644 --- a/EDSEditorGUI/DeviceInfoView.resx +++ b/EDSEditorGUI/DeviceInfoView.resx @@ -1,120 +1,120 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + \ No newline at end of file diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index 927dd188..7a1ae051 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -61,6 +61,7 @@ private void InitializeComponent() this.label23 = new System.Windows.Forms.Label(); this.textBox_index = new System.Windows.Forms.TextBox(); this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.checkBox_autosave = new System.Windows.Forms.CheckBox(); this.textBox_stringLengthMin = new System.Windows.Forms.TextBox(); this.label22 = new System.Windows.Forms.Label(); this.label20 = new System.Windows.Forms.Label(); @@ -134,6 +135,7 @@ private void InitializeComponent() // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 @@ -143,8 +145,9 @@ private void InitializeComponent() // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.splitContainer4); - this.splitContainer1.Size = new System.Drawing.Size(1138, 745); - this.splitContainer1.SplitterDistance = 281; + this.splitContainer1.Size = new System.Drawing.Size(1517, 917); + this.splitContainer1.SplitterDistance = 374; + this.splitContainer1.SplitterWidth = 5; this.splitContainer1.TabIndex = 2; this.splitContainer1.TabStop = false; // @@ -153,6 +156,7 @@ private void InitializeComponent() this.splitContainer2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer2.Location = new System.Drawing.Point(0, 0); + this.splitContainer2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer2.Name = "splitContainer2"; this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -163,8 +167,9 @@ private void InitializeComponent() // splitContainer2.Panel2 // this.splitContainer2.Panel2.Controls.Add(this.splitContainer3); - this.splitContainer2.Size = new System.Drawing.Size(281, 745); - this.splitContainer2.SplitterDistance = 246; + this.splitContainer2.Size = new System.Drawing.Size(374, 917); + this.splitContainer2.SplitterDistance = 302; + this.splitContainer2.SplitterWidth = 5; this.splitContainer2.TabIndex = 0; this.splitContainer2.TabStop = false; // @@ -176,11 +181,12 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 2; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(279, 244); + this.tableLayoutPanel1.Size = new System.Drawing.Size(372, 300); this.tableLayoutPanel1.TabIndex = 6; // // listView_communication_objects @@ -191,9 +197,10 @@ private void InitializeComponent() this.listView_communication_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_communication_objects.FullRowSelect = true; this.listView_communication_objects.HideSelection = false; - this.listView_communication_objects.Location = new System.Drawing.Point(3, 23); + this.listView_communication_objects.Location = new System.Drawing.Point(4, 29); + this.listView_communication_objects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.listView_communication_objects.Name = "listView_communication_objects"; - this.listView_communication_objects.Size = new System.Drawing.Size(273, 218); + this.listView_communication_objects.Size = new System.Drawing.Size(364, 267); this.listView_communication_objects.TabIndex = 0; this.listView_communication_objects.UseCompatibleStateImageBehavior = false; this.listView_communication_objects.View = System.Windows.Forms.View.Details; @@ -213,9 +220,10 @@ private void InitializeComponent() // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(3, 0); + this.label1.Location = new System.Drawing.Point(4, 0); + this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(176, 13); + this.label1.Size = new System.Drawing.Size(223, 16); this.label1.TabIndex = 3; this.label1.Text = "Communication Specific Parameters"; // @@ -224,6 +232,7 @@ private void InitializeComponent() this.splitContainer3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer3.Location = new System.Drawing.Point(0, 0); + this.splitContainer3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer3.Name = "splitContainer3"; this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -234,8 +243,9 @@ private void InitializeComponent() // splitContainer3.Panel2 // this.splitContainer3.Panel2.Controls.Add(this.tableLayoutPanel3); - this.splitContainer3.Size = new System.Drawing.Size(281, 495); - this.splitContainer3.SplitterDistance = 245; + this.splitContainer3.Size = new System.Drawing.Size(374, 610); + this.splitContainer3.SplitterDistance = 301; + this.splitContainer3.SplitterWidth = 5; this.splitContainer3.TabIndex = 0; this.splitContainer3.TabStop = false; // @@ -247,19 +257,21 @@ private void InitializeComponent() this.tableLayoutPanel2.Controls.Add(this.listView_manufacturer_objects, 0, 1); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 2; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(279, 243); + this.tableLayoutPanel2.Size = new System.Drawing.Size(372, 299); this.tableLayoutPanel2.TabIndex = 7; // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(3, 0); + this.label2.Location = new System.Drawing.Point(4, 0); + this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(167, 13); + this.label2.Size = new System.Drawing.Size(208, 16); this.label2.TabIndex = 4; this.label2.Text = "Manufacturer Specific Parameters"; // @@ -271,9 +283,10 @@ private void InitializeComponent() this.listView_manufacturer_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_manufacturer_objects.FullRowSelect = true; this.listView_manufacturer_objects.HideSelection = false; - this.listView_manufacturer_objects.Location = new System.Drawing.Point(3, 23); + this.listView_manufacturer_objects.Location = new System.Drawing.Point(4, 29); + this.listView_manufacturer_objects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.listView_manufacturer_objects.Name = "listView_manufacturer_objects"; - this.listView_manufacturer_objects.Size = new System.Drawing.Size(273, 217); + this.listView_manufacturer_objects.Size = new System.Drawing.Size(364, 266); this.listView_manufacturer_objects.TabIndex = 0; this.listView_manufacturer_objects.UseCompatibleStateImageBehavior = false; this.listView_manufacturer_objects.View = System.Windows.Forms.View.Details; @@ -298,19 +311,21 @@ private void InitializeComponent() this.tableLayoutPanel3.Controls.Add(this.listView_deviceProfile_objects, 0, 1); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 2; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(279, 244); + this.tableLayoutPanel3.Size = new System.Drawing.Size(372, 302); this.tableLayoutPanel3.TabIndex = 8; // // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(3, 0); + this.label3.Location = new System.Drawing.Point(4, 0); + this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(170, 13); + this.label3.Size = new System.Drawing.Size(215, 16); this.label3.TabIndex = 5; this.label3.Text = "Device Profile Specific Parameters"; // @@ -322,9 +337,10 @@ private void InitializeComponent() this.listView_deviceProfile_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_deviceProfile_objects.FullRowSelect = true; this.listView_deviceProfile_objects.HideSelection = false; - this.listView_deviceProfile_objects.Location = new System.Drawing.Point(3, 23); + this.listView_deviceProfile_objects.Location = new System.Drawing.Point(4, 29); + this.listView_deviceProfile_objects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.listView_deviceProfile_objects.Name = "listView_deviceProfile_objects"; - this.listView_deviceProfile_objects.Size = new System.Drawing.Size(273, 218); + this.listView_deviceProfile_objects.Size = new System.Drawing.Size(364, 269); this.listView_deviceProfile_objects.TabIndex = 0; this.listView_deviceProfile_objects.UseCompatibleStateImageBehavior = false; this.listView_deviceProfile_objects.View = System.Windows.Forms.View.Details; @@ -345,6 +361,7 @@ private void InitializeComponent() // this.splitContainer4.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer4.Location = new System.Drawing.Point(0, 0); + this.splitContainer4.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer4.Name = "splitContainer4"; this.splitContainer4.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -365,8 +382,9 @@ private void InitializeComponent() this.splitContainer4.Panel2.Controls.Add(this.label6); this.splitContainer4.Panel2.Controls.Add(this.textBox_name); this.splitContainer4.Panel2.Controls.Add(this.textBox_description); - this.splitContainer4.Size = new System.Drawing.Size(853, 745); - this.splitContainer4.SplitterDistance = 225; + this.splitContainer4.Size = new System.Drawing.Size(1138, 917); + this.splitContainer4.SplitterDistance = 276; + this.splitContainer4.SplitterWidth = 5; this.splitContainer4.TabIndex = 28; this.splitContainer4.TabStop = false; // @@ -387,8 +405,9 @@ private void InitializeComponent() this.listView_subObjects.FullRowSelect = true; this.listView_subObjects.HideSelection = false; this.listView_subObjects.Location = new System.Drawing.Point(0, 0); + this.listView_subObjects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.listView_subObjects.Name = "listView_subObjects"; - this.listView_subObjects.Size = new System.Drawing.Size(850, 223); + this.listView_subObjects.Size = new System.Drawing.Size(1133, 273); this.listView_subObjects.TabIndex = 0; this.listView_subObjects.UseCompatibleStateImageBehavior = false; this.listView_subObjects.View = System.Windows.Forms.View.Details; @@ -437,33 +456,37 @@ private void InitializeComponent() // // textBox_subIndex // - this.textBox_subIndex.Location = new System.Drawing.Point(260, 8); + this.textBox_subIndex.Location = new System.Drawing.Point(347, 10); + this.textBox_subIndex.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_subIndex.Name = "textBox_subIndex"; this.textBox_subIndex.ReadOnly = true; - this.textBox_subIndex.Size = new System.Drawing.Size(100, 20); + this.textBox_subIndex.Size = new System.Drawing.Size(132, 22); this.textBox_subIndex.TabIndex = 0; this.textBox_subIndex.TabStop = false; // // label23 // this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(199, 11); + this.label23.Location = new System.Drawing.Point(265, 14); + this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(55, 13); + this.label23.Size = new System.Drawing.Size(66, 16); this.label23.TabIndex = 34; this.label23.Text = "Sub Index"; // // textBox_index // - this.textBox_index.Location = new System.Drawing.Point(90, 8); + this.textBox_index.Location = new System.Drawing.Point(120, 10); + this.textBox_index.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_index.Name = "textBox_index"; this.textBox_index.ReadOnly = true; - this.textBox_index.Size = new System.Drawing.Size(100, 20); + this.textBox_index.Size = new System.Drawing.Size(132, 22); this.textBox_index.TabIndex = 0; this.textBox_index.TabStop = false; // // groupBox1 // + this.groupBox1.Controls.Add(this.checkBox_autosave); this.groupBox1.Controls.Add(this.textBox_stringLengthMin); this.groupBox1.Controls.Add(this.label22); this.groupBox1.Controls.Add(this.label20); @@ -494,38 +517,51 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.label11); this.groupBox1.Controls.Add(this.comboBox_accessPDO); this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; - this.groupBox1.Location = new System.Drawing.Point(0, 328); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Location = new System.Drawing.Point(0, 405); + this.groupBox1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.groupBox1.Size = new System.Drawing.Size(853, 188); + this.groupBox1.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.groupBox1.Size = new System.Drawing.Size(1138, 231); this.groupBox1.TabIndex = 33; this.groupBox1.TabStop = false; this.groupBox1.Text = "Object settings"; // + // checkBox_autosave + // + this.checkBox_autosave.Location = new System.Drawing.Point(936, 182); + this.checkBox_autosave.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.checkBox_autosave.Name = "checkBox_autosave"; + this.checkBox_autosave.Size = new System.Drawing.Size(185, 21); + this.checkBox_autosave.TabIndex = 35; + this.checkBox_autosave.Text = "Autosave changes"; + this.checkBox_autosave.UseVisualStyleBackColor = true; + // // textBox_stringLengthMin // - this.textBox_stringLengthMin.Location = new System.Drawing.Point(340, 99); + this.textBox_stringLengthMin.Location = new System.Drawing.Point(453, 122); + this.textBox_stringLengthMin.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_stringLengthMin.Name = "textBox_stringLengthMin"; - this.textBox_stringLengthMin.Size = new System.Drawing.Size(122, 20); + this.textBox_stringLengthMin.Size = new System.Drawing.Size(161, 22); this.textBox_stringLengthMin.TabIndex = 24; this.textBox_stringLengthMin.TextChanged += new System.EventHandler(this.DataDirty); // // label22 // this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(248, 102); + this.label22.Location = new System.Drawing.Point(331, 126); + this.label22.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(75, 13); + this.label22.Size = new System.Drawing.Size(90, 16); this.label22.TabIndex = 39; this.label22.Text = "String Len Min"; // // label20 // this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(482, 21); + this.label20.Location = new System.Drawing.Point(643, 26); + this.label20.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(64, 13); + this.label20.Size = new System.Drawing.Size(78, 16); this.label20.TabIndex = 36; this.label20.Text = "Count Label"; // @@ -533,18 +569,20 @@ private void InitializeComponent() // this.comboBox_countLabel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_countLabel.FormattingEnabled = true; - this.comboBox_countLabel.Location = new System.Drawing.Point(574, 18); + this.comboBox_countLabel.Location = new System.Drawing.Point(765, 22); + this.comboBox_countLabel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.comboBox_countLabel.Name = "comboBox_countLabel"; - this.comboBox_countLabel.Size = new System.Drawing.Size(122, 21); + this.comboBox_countLabel.Size = new System.Drawing.Size(161, 24); this.comboBox_countLabel.TabIndex = 30; this.comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label19 // this.label19.AutoSize = true; - this.label19.Location = new System.Drawing.Point(13, 129); + this.label19.Location = new System.Drawing.Point(17, 159); + this.label19.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label19.Name = "label19"; - this.label19.Size = new System.Drawing.Size(76, 13); + this.label19.Size = new System.Drawing.Size(94, 16); this.label19.TabIndex = 34; this.label19.Text = "Access SRDO"; // @@ -552,61 +590,68 @@ private void InitializeComponent() // this.comboBox_accessSRDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSRDO.FormattingEnabled = true; - this.comboBox_accessSRDO.Location = new System.Drawing.Point(108, 126); + this.comboBox_accessSRDO.Location = new System.Drawing.Point(144, 155); + this.comboBox_accessSRDO.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.comboBox_accessSRDO.Name = "comboBox_accessSRDO"; - this.comboBox_accessSRDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessSRDO.Size = new System.Drawing.Size(161, 24); this.comboBox_accessSRDO.TabIndex = 14; this.comboBox_accessSRDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_actualValue // this.textBox_actualValue.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_actualValue.Location = new System.Drawing.Point(340, 72); + this.textBox_actualValue.Location = new System.Drawing.Point(453, 89); + this.textBox_actualValue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_actualValue.Name = "textBox_actualValue"; - this.textBox_actualValue.Size = new System.Drawing.Size(122, 20); + this.textBox_actualValue.Size = new System.Drawing.Size(161, 22); this.textBox_actualValue.TabIndex = 23; this.textBox_actualValue.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_lowLimit // - this.textBox_lowLimit.Location = new System.Drawing.Point(340, 45); + this.textBox_lowLimit.Location = new System.Drawing.Point(453, 55); + this.textBox_lowLimit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_lowLimit.Name = "textBox_lowLimit"; - this.textBox_lowLimit.Size = new System.Drawing.Size(122, 20); + this.textBox_lowLimit.Size = new System.Drawing.Size(161, 22); this.textBox_lowLimit.TabIndex = 22; this.textBox_lowLimit.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_highLimit // - this.textBox_highLimit.Location = new System.Drawing.Point(340, 18); + this.textBox_highLimit.Location = new System.Drawing.Point(453, 22); + this.textBox_highLimit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_highLimit.Name = "textBox_highLimit"; - this.textBox_highLimit.Size = new System.Drawing.Size(122, 20); + this.textBox_highLimit.Size = new System.Drawing.Size(161, 22); this.textBox_highLimit.TabIndex = 21; this.textBox_highLimit.TextChanged += new System.EventHandler(this.DataDirty); // // label18 // this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(248, 75); + this.label18.Location = new System.Drawing.Point(331, 92); + this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(67, 13); + this.label18.Size = new System.Drawing.Size(82, 16); this.label18.TabIndex = 32; this.label18.Text = "Actual Value"; // // label17 // this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(248, 48); + this.label17.Location = new System.Drawing.Point(331, 59); + this.label17.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(48, 13); + this.label17.Size = new System.Drawing.Size(58, 16); this.label17.TabIndex = 31; this.label17.Text = "LowLimit"; // // label14 // this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(248, 21); + this.label14.Location = new System.Drawing.Point(331, 26); + this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(50, 13); + this.label14.Size = new System.Drawing.Size(62, 16); this.label14.TabIndex = 30; this.label14.Text = "HighLimit"; // @@ -614,9 +659,10 @@ private void InitializeComponent() // this.button_saveChanges.Image = global::ODEditor.Properties.Resources.Save_6530; this.button_saveChanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_saveChanges.Location = new System.Drawing.Point(485, 138); + this.button_saveChanges.Location = new System.Drawing.Point(647, 170); + this.button_saveChanges.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.button_saveChanges.Name = "button_saveChanges"; - this.button_saveChanges.Size = new System.Drawing.Size(211, 35); + this.button_saveChanges.Size = new System.Drawing.Size(281, 43); this.button_saveChanges.TabIndex = 50; this.button_saveChanges.Text = "Save Changes"; this.button_saveChanges.UseVisualStyleBackColor = true; @@ -625,9 +671,10 @@ private void InitializeComponent() // label16 // this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(482, 48); + this.label16.Location = new System.Drawing.Point(643, 59); + this.label16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(76, 13); + this.label16.Size = new System.Drawing.Size(95, 16); this.label16.TabIndex = 26; this.label16.Text = "Storage Group"; // @@ -635,27 +682,30 @@ private void InitializeComponent() // this.comboBox_storageGroup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_storageGroup.FormattingEnabled = true; - this.comboBox_storageGroup.Location = new System.Drawing.Point(574, 45); + this.comboBox_storageGroup.Location = new System.Drawing.Point(765, 55); + this.comboBox_storageGroup.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.comboBox_storageGroup.Name = "comboBox_storageGroup"; - this.comboBox_storageGroup.Size = new System.Drawing.Size(122, 21); + this.comboBox_storageGroup.Size = new System.Drawing.Size(161, 24); this.comboBox_storageGroup.TabIndex = 31; this.comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label15 // this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(482, 72); + this.label15.Location = new System.Drawing.Point(643, 89); + this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(46, 13); + this.label15.Size = new System.Drawing.Size(58, 16); this.label15.TabIndex = 24; this.label15.Text = "Enabled"; // // checkBox_enabled // this.checkBox_enabled.AutoSize = true; - this.checkBox_enabled.Location = new System.Drawing.Point(574, 72); + this.checkBox_enabled.Location = new System.Drawing.Point(765, 89); + this.checkBox_enabled.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.checkBox_enabled.Name = "checkBox_enabled"; - this.checkBox_enabled.Size = new System.Drawing.Size(15, 14); + this.checkBox_enabled.Size = new System.Drawing.Size(18, 17); this.checkBox_enabled.TabIndex = 32; this.checkBox_enabled.UseVisualStyleBackColor = true; this.checkBox_enabled.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -663,9 +713,10 @@ private void InitializeComponent() // label7 // this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(13, 21); + this.label7.Location = new System.Drawing.Point(17, 26); + this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(65, 13); + this.label7.Size = new System.Drawing.Size(81, 16); this.label7.TabIndex = 7; this.label7.Text = "Object Type"; // @@ -673,18 +724,20 @@ private void InitializeComponent() // this.comboBox_objectType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_objectType.FormattingEnabled = true; - this.comboBox_objectType.Location = new System.Drawing.Point(108, 18); + this.comboBox_objectType.Location = new System.Drawing.Point(144, 22); + this.comboBox_objectType.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.comboBox_objectType.Name = "comboBox_objectType"; - this.comboBox_objectType.Size = new System.Drawing.Size(122, 21); + this.comboBox_objectType.Size = new System.Drawing.Size(161, 24); this.comboBox_objectType.TabIndex = 10; this.comboBox_objectType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label8 // this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(13, 48); + this.label8.Location = new System.Drawing.Point(17, 59); + this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(57, 13); + this.label8.Size = new System.Drawing.Size(71, 16); this.label8.TabIndex = 9; this.label8.Text = "Data Type"; // @@ -692,36 +745,40 @@ private void InitializeComponent() // this.comboBox_dataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_dataType.FormattingEnabled = true; - this.comboBox_dataType.Location = new System.Drawing.Point(108, 45); + this.comboBox_dataType.Location = new System.Drawing.Point(144, 55); + this.comboBox_dataType.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.comboBox_dataType.Name = "comboBox_dataType"; - this.comboBox_dataType.Size = new System.Drawing.Size(122, 21); + this.comboBox_dataType.Size = new System.Drawing.Size(161, 24); this.comboBox_dataType.TabIndex = 11; this.comboBox_dataType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label_pdoFlags // this.label_pdoFlags.AutoSize = true; - this.label_pdoFlags.Location = new System.Drawing.Point(482, 92); + this.label_pdoFlags.Location = new System.Drawing.Point(643, 113); + this.label_pdoFlags.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label_pdoFlags.Name = "label_pdoFlags"; - this.label_pdoFlags.Size = new System.Drawing.Size(62, 13); + this.label_pdoFlags.Size = new System.Drawing.Size(76, 16); this.label_pdoFlags.TabIndex = 18; this.label_pdoFlags.Text = "TPDO COS"; // // label9 // this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(13, 75); + this.label9.Location = new System.Drawing.Point(17, 92); + this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(68, 13); + this.label9.Size = new System.Drawing.Size(84, 16); this.label9.TabIndex = 11; this.label9.Text = "Access SDO"; // // checkBox_pdoFlags // this.checkBox_pdoFlags.AutoSize = true; - this.checkBox_pdoFlags.Location = new System.Drawing.Point(574, 92); + this.checkBox_pdoFlags.Location = new System.Drawing.Point(765, 113); + this.checkBox_pdoFlags.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.checkBox_pdoFlags.Name = "checkBox_pdoFlags"; - this.checkBox_pdoFlags.Size = new System.Drawing.Size(15, 14); + this.checkBox_pdoFlags.Size = new System.Drawing.Size(18, 17); this.checkBox_pdoFlags.TabIndex = 34; this.checkBox_pdoFlags.UseVisualStyleBackColor = true; this.checkBox_pdoFlags.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -730,35 +787,39 @@ private void InitializeComponent() // this.comboBox_accessSDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSDO.FormattingEnabled = true; - this.comboBox_accessSDO.Location = new System.Drawing.Point(108, 72); + this.comboBox_accessSDO.Location = new System.Drawing.Point(144, 89); + this.comboBox_accessSDO.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.comboBox_accessSDO.Name = "comboBox_accessSDO"; - this.comboBox_accessSDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessSDO.Size = new System.Drawing.Size(161, 24); this.comboBox_accessSDO.TabIndex = 12; this.comboBox_accessSDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_defaultValue // - this.textBox_defaultValue.Location = new System.Drawing.Point(108, 153); + this.textBox_defaultValue.Location = new System.Drawing.Point(144, 188); + this.textBox_defaultValue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_defaultValue.Name = "textBox_defaultValue"; - this.textBox_defaultValue.Size = new System.Drawing.Size(354, 20); + this.textBox_defaultValue.Size = new System.Drawing.Size(471, 22); this.textBox_defaultValue.TabIndex = 20; this.textBox_defaultValue.TextChanged += new System.EventHandler(this.DataDirty); // // label10 // this.label10.AutoSize = true; - this.label10.Location = new System.Drawing.Point(13, 102); + this.label10.Location = new System.Drawing.Point(17, 126); + this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(68, 13); + this.label10.Size = new System.Drawing.Size(84, 16); this.label10.TabIndex = 13; this.label10.Text = "Access PDO"; // // label11 // this.label11.AutoSize = true; - this.label11.Location = new System.Drawing.Point(13, 156); + this.label11.Location = new System.Drawing.Point(17, 192); + this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(70, 13); + this.label11.Size = new System.Drawing.Size(85, 16); this.label11.TabIndex = 15; this.label11.Text = "Default value"; // @@ -766,9 +827,10 @@ private void InitializeComponent() // this.comboBox_accessPDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessPDO.FormattingEnabled = true; - this.comboBox_accessPDO.Location = new System.Drawing.Point(108, 99); + this.comboBox_accessPDO.Location = new System.Drawing.Point(144, 122); + this.comboBox_accessPDO.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.comboBox_accessPDO.Name = "comboBox_accessPDO"; - this.comboBox_accessPDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessPDO.Size = new System.Drawing.Size(161, 24); this.comboBox_accessPDO.TabIndex = 13; this.comboBox_accessPDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // @@ -777,45 +839,50 @@ private void InitializeComponent() this.textBox_denotation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_denotation.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_denotation.Location = new System.Drawing.Point(90, 60); + this.textBox_denotation.Location = new System.Drawing.Point(120, 74); + this.textBox_denotation.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_denotation.Name = "textBox_denotation"; - this.textBox_denotation.Size = new System.Drawing.Size(760, 20); + this.textBox_denotation.Size = new System.Drawing.Size(1013, 22); this.textBox_denotation.TabIndex = 3; this.textBox_denotation.TextChanged += new System.EventHandler(this.DataDirty); // // label13 // this.label13.AutoSize = true; - this.label13.Location = new System.Drawing.Point(13, 63); + this.label13.Location = new System.Drawing.Point(17, 78); + this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(59, 13); + this.label13.Size = new System.Drawing.Size(72, 16); this.label13.TabIndex = 28; this.label13.Text = "Denotation"; // // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(13, 11); + this.label4.Location = new System.Drawing.Point(17, 14); + this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(33, 13); + this.label4.Size = new System.Drawing.Size(39, 16); this.label4.TabIndex = 1; this.label4.Text = "Index"; // // label5 // this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(13, 37); + this.label5.Location = new System.Drawing.Point(17, 46); + this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(35, 13); + this.label5.Size = new System.Drawing.Size(44, 16); this.label5.TabIndex = 2; this.label5.Text = "Name"; // // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(13, 89); + this.label6.Location = new System.Drawing.Point(17, 110); + this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(60, 13); + this.label6.Size = new System.Drawing.Size(75, 16); this.label6.TabIndex = 3; this.label6.Text = "Description"; // @@ -823,9 +890,10 @@ private void InitializeComponent() // this.textBox_name.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_name.Location = new System.Drawing.Point(90, 34); + this.textBox_name.Location = new System.Drawing.Point(120, 42); + this.textBox_name.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_name.Name = "textBox_name"; - this.textBox_name.Size = new System.Drawing.Size(760, 20); + this.textBox_name.Size = new System.Drawing.Size(1013, 22); this.textBox_name.TabIndex = 2; this.textBox_name.TextChanged += new System.EventHandler(this.DataDirty); // @@ -837,11 +905,12 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_description.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBox_description.Location = new System.Drawing.Point(90, 86); + this.textBox_description.Location = new System.Drawing.Point(120, 106); + this.textBox_description.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.textBox_description.Multiline = true; this.textBox_description.Name = "textBox_description"; this.textBox_description.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBox_description.Size = new System.Drawing.Size(760, 227); + this.textBox_description.Size = new System.Drawing.Size(1013, 279); this.textBox_description.TabIndex = 4; this.textBox_description.TextChanged += new System.EventHandler(this.DataDirty); // @@ -854,12 +923,12 @@ private void InitializeComponent() this.contextMenu_object_deleteObjectToolStripMenuItem, this.contextMenu_object_toggleObjectToolStripMenuItem}); this.contextMenu_object.Name = "contextMenuStrip1"; - this.contextMenu_object.Size = new System.Drawing.Size(121, 108); + this.contextMenu_object.Size = new System.Drawing.Size(136, 108); // // contextMenu_object_addNewObjectToolStripMenuItem // this.contextMenu_object_addNewObjectToolStripMenuItem.Name = "contextMenu_object_addNewObjectToolStripMenuItem"; - this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.contextMenu_object_addNewObjectToolStripMenuItem.Text = "&Clone..."; this.contextMenu_object_addNewObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_clone_ToolStripMenuItem_Click); // @@ -867,7 +936,7 @@ private void InitializeComponent() // this.addToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.addToolStripMenuItem.Name = "addToolStripMenuItem"; - this.addToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.addToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.addToolStripMenuItem.Text = "Add..."; this.addToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_add_ToolStripMenuItem_Click); // @@ -875,14 +944,14 @@ private void InitializeComponent() // this.contextMenu_object_deleteObjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_object_deleteObjectToolStripMenuItem.Name = "contextMenu_object_deleteObjectToolStripMenuItem"; - this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.contextMenu_object_deleteObjectToolStripMenuItem.Text = "&Delete..."; this.contextMenu_object_deleteObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_delete_ToolStripMenuItem_Click); // // contextMenu_object_toggleObjectToolStripMenuItem // this.contextMenu_object_toggleObjectToolStripMenuItem.Name = "contextMenu_object_toggleObjectToolStripMenuItem"; - this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); this.contextMenu_object_toggleObjectToolStripMenuItem.Text = "&Toggle"; this.contextMenu_object_toggleObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_toggle_ToolStripMenuItem_Click); // @@ -894,13 +963,13 @@ private void InitializeComponent() this.contextMenu_subObject_removeSubItemToolStripMenuItem, this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem}); this.contextMenu_subObject.Name = "contextMenu_array"; - this.contextMenu_subObject.Size = new System.Drawing.Size(183, 82); + this.contextMenu_subObject.Size = new System.Drawing.Size(216, 82); // // contextMenu_subObject_addSubItemToolStripMenuItem // this.contextMenu_subObject_addSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.contextMenu_subObject_addSubItemToolStripMenuItem.Name = "contextMenu_subObject_addSubItemToolStripMenuItem"; - this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); this.contextMenu_subObject_addSubItemToolStripMenuItem.Text = "Add"; this.contextMenu_subObject_addSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_add_ToolStripMenuItem_Click); // @@ -908,7 +977,7 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); this.contextMenu_subObject_removeSubItemToolStripMenuItem.Text = "Remove (shift up)"; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // @@ -916,17 +985,18 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(215, 26); this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Text = "Remove (leave gap)"; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // // DeviceODView // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.splitContainer1); + this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "DeviceODView"; - this.Size = new System.Drawing.Size(1138, 745); + this.Size = new System.Drawing.Size(1517, 917); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); @@ -1036,6 +1106,7 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_stringLengthMin; private System.Windows.Forms.TextBox textBox_subIndex; private System.Windows.Forms.Label label23; - private System.Windows.Forms.ToolStripMenuItem addToolStripMenuItem; + private System.Windows.Forms.ToolStripMenuItem addToolStripMenuItem; + private System.Windows.Forms.CheckBox checkBox_autosave; } } diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index dc0453a5..318b8aa7 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -1,47 +1,48 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius - Copyright(c) 2020 Janez Paternoster -*/ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; -using System.Reflection; -using System.Text.RegularExpressions; +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius + Copyright(c) 2020 Janez Paternoster +*/ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.Text.RegularExpressions; using libEDSsharp; -namespace ODEditor -{ - - public partial class DeviceODView : MyTabUserControl - { - EDSsharp eds = null; - - ODentry selectedObject; - ODentry lastSelectedObject; - ListView selectedList; + +namespace ODEditor +{ + + public partial class DeviceODView : MyTabUserControl + { + EDSsharp eds = null; + + ODentry selectedObject; + ODentry lastSelectedObject; + ListView selectedList; bool justUpdating = false; bool ExporterOld = false; bool ExporterV4 = false; - public DeviceODView() - { - + public DeviceODView() + { + InitializeComponent(); RebuildControls(); @@ -126,322 +127,350 @@ private bool ExporterTypeV4() { return (type == ExporterFactory.Exporter.CANOPENNODE_V4); } - private bool Checkdirty() - { - if (button_saveChanges.BackColor == Color.Red) - { - if (lastSelectedObject != null && MessageBox.Show(String.Format("Unsaved changes on Index 0x{0:X4}/{1:X2}.\nDo you wish to switch object and loose your changes?", lastSelectedObject.Index, lastSelectedObject.Subindex), "Unsaved changes", MessageBoxButtons.YesNo) == DialogResult.No) - { - return true; - } - button_saveChanges.BackColor = default; - } - - return false; - } - - private void ComboBoxSet(ComboBox comboBox, string item) - { - if (item == null) - item = ""; - - if (!comboBox.Items.Contains(item)) - comboBox.Items.Add(item); - - comboBox.SelectedItem = item; - } - - public void PopulateObjectLists(EDSsharp eds_target) - { - if (eds_target == null) - return; - - eds = eds_target; - eds.UpdatePDOcount(); - doUpdateDeviceInfo(); - doUpdatePDOs(); - - /* save scroll positions */ - int listview_communication_position = 0; - int listview_manufacturer_position = 0; - int listview_deviceProfile_position = 0; - - if (listView_communication_objects.TopItem != null) - listview_communication_position = listView_communication_objects.TopItem.Index; - if (listView_manufacturer_objects.TopItem != null) - listview_manufacturer_position = listView_manufacturer_objects.TopItem.Index; - if (listView_deviceProfile_objects.TopItem != null) - listview_deviceProfile_position = listView_deviceProfile_objects.TopItem.Index; - - /* prevent flickering */ - listView_communication_objects.BeginUpdate(); - listView_manufacturer_objects.BeginUpdate(); - listView_deviceProfile_objects.BeginUpdate(); - - listView_communication_objects.Items.Clear(); - listView_manufacturer_objects.Items.Clear(); - listView_deviceProfile_objects.Items.Clear(); - - foreach (ODentry od in eds.ods.Values) - { - UInt16 index = od.Index; - ListViewItem lvi = new ListViewItem(new string[] { - string.Format("0x{0:X4}", index), - od.parameter_name - }); - - lvi.Tag = od; - if (selectedObject != null && index == selectedObject.Index) - lvi.Selected = true; - if (od.prop.CO_disabled == true) - lvi.ForeColor = Color.LightGray; - - if (index <= 0x1000 || index < 0x2000) - listView_communication_objects.Items.Add(lvi); - else if (index >= 0x2000 && index < 0x6000) - listView_manufacturer_objects.Items.Add(lvi); - else - listView_deviceProfile_objects.Items.Add(lvi); - - string countLabel = od.prop.CO_countLabel; - if (!comboBox_countLabel.Items.Contains(countLabel)) - comboBox_countLabel.Items.Insert(comboBox_countLabel.Items.Count - 1, countLabel); - - string storageGroup = od.prop.CO_storageGroup; - if (!comboBox_storageGroup.Items.Contains(storageGroup)) - comboBox_storageGroup.Items.Insert(comboBox_storageGroup.Items.Count - 1, storageGroup); - } - - listView_communication_objects.EndUpdate(); - listView_manufacturer_objects.EndUpdate(); - listView_deviceProfile_objects.EndUpdate(); - - /* reset scroll position and selection */ - if (listview_communication_position != 0 && listView_communication_objects.Items.Count > 0) - listView_communication_objects.TopItem = listView_communication_objects.Items[listview_communication_position]; - if (listview_manufacturer_position != 0 && listView_manufacturer_objects.Items.Count > 0) - listView_manufacturer_objects.TopItem = listView_manufacturer_objects.Items[listview_manufacturer_position]; - if (listview_deviceProfile_position != 0 && listView_deviceProfile_objects.Items.Count > 0) - listView_deviceProfile_objects.TopItem = listView_deviceProfile_objects.Items[listview_deviceProfile_position]; - } - - public void PopulateSubList() - { - listView_subObjects.Items.Clear(); - - if (selectedObject == null) + private bool Checkdirty() + { + var result = false; + + if (button_saveChanges.BackColor == Color.Red) + { + + var answer = checkBox_autosave.Checked + ? DialogResult.No + : MessageBox.Show(String.Format("Unsaved changes on Index 0x{0:X4}/{1:X2}.\nDo you wish to switch object and loose your changes?\n\nYes = Lose changes\nNo = Save\nCancel = Go back and stay on the object", lastSelectedObject.Index, lastSelectedObject.Subindex), "Unsaved changes", MessageBoxButtons.YesNoCancel); ; + + + switch (answer) + { + case DialogResult.Cancel: + default: + result = lastSelectedObject != null; + break; + + case DialogResult.Yes: + result = false; + break; + + case DialogResult.No: + if (lastSelectedObject != null) + { + ObjectSave(); + result = false; + } + break; + } + + button_saveChanges.BackColor = default; + } + + return result; + } + + private void ComboBoxSet(ComboBox comboBox, string item) + { + if (item == null) + item = ""; + + if (!comboBox.Items.Contains(item)) + comboBox.Items.Add(item); + + comboBox.SelectedItem = item; + } + + public void PopulateObjectLists(EDSsharp eds_target) + { + if (eds_target == null) return; - ODentry od = selectedObject.parent ?? selectedObject; - - if (od.objecttype == ObjectType.VAR) - { - ListViewItem lvi = new ListViewItem(new string[] { - " ", // subindex - od.parameter_name, - od.ObjectTypeString(), - od.datatype.ToString(), - od.AccessSDO().ToString(), - od.AccessPDO().ToString(), - od.prop.CO_accessSRDO.ToString(), - od.defaultvalue - }); - lvi.Tag = od; - listView_subObjects.Items.Add(lvi); - } - else if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) - { - ListViewItem lvi = new ListViewItem(new string[]{ - " ", - od.parameter_name, - od.ObjectTypeString() - }); - lvi.Tag = od; - listView_subObjects.Items.Add(lvi); - - foreach (KeyValuePair kvp in od.subobjects) - { - ODentry subod = kvp.Value; - int subindex = kvp.Key; - - ListViewItem lvi2 = new ListViewItem(new string[] { - string.Format("0x{0:X2}", subindex), - subod.parameter_name, - subod.ObjectTypeString(), - (subod.datatype != DataType.UNKNOWN) ? subod.datatype.ToString() : od.datatype.ToString(), - subod.AccessSDO().ToString(), - subod.AccessPDO().ToString(), - subod.prop.CO_accessSRDO.ToString(), - subod.defaultvalue - }); - lvi2.Tag = subod; - listView_subObjects.Items.Add(lvi2); - } - } - } - - public void PopulateObject() - { - - ExporterV4 = ExporterTypeV4(); + + eds = eds_target; + eds.UpdatePDOcount(); + doUpdateDeviceInfo(); + doUpdatePDOs(); + + /* save scroll positions */ + int listview_communication_position = 0; + int listview_manufacturer_position = 0; + int listview_deviceProfile_position = 0; + + if (listView_communication_objects.TopItem != null) + listview_communication_position = listView_communication_objects.TopItem.Index; + if (listView_manufacturer_objects.TopItem != null) + listview_manufacturer_position = listView_manufacturer_objects.TopItem.Index; + if (listView_deviceProfile_objects.TopItem != null) + listview_deviceProfile_position = listView_deviceProfile_objects.TopItem.Index; + + /* prevent flickering */ + listView_communication_objects.BeginUpdate(); + listView_manufacturer_objects.BeginUpdate(); + listView_deviceProfile_objects.BeginUpdate(); + + listView_communication_objects.Items.Clear(); + listView_manufacturer_objects.Items.Clear(); + listView_deviceProfile_objects.Items.Clear(); + + foreach (ODentry od in eds.ods.Values) + { + UInt16 index = od.Index; + ListViewItem lvi = new ListViewItem(new string[] { + string.Format("0x{0:X4}", index), + od.parameter_name + }); + + lvi.Tag = od; + if (selectedObject != null && index == selectedObject.Index) + lvi.Selected = true; + if (od.prop.CO_disabled == true) + lvi.ForeColor = Color.LightGray; + + if (index <= 0x1000 || index < 0x2000) + listView_communication_objects.Items.Add(lvi); + else if (index >= 0x2000 && index < 0x6000) + listView_manufacturer_objects.Items.Add(lvi); + else + listView_deviceProfile_objects.Items.Add(lvi); + + string countLabel = od.prop.CO_countLabel; + if (!comboBox_countLabel.Items.Contains(countLabel)) + comboBox_countLabel.Items.Insert(comboBox_countLabel.Items.Count - 1, countLabel); + + string storageGroup = od.prop.CO_storageGroup; + if (!comboBox_storageGroup.Items.Contains(storageGroup)) + comboBox_storageGroup.Items.Insert(comboBox_storageGroup.Items.Count - 1, storageGroup); + } + + listView_communication_objects.EndUpdate(); + listView_manufacturer_objects.EndUpdate(); + listView_deviceProfile_objects.EndUpdate(); + + /* reset scroll position and selection */ + if (listview_communication_position != 0 && listView_communication_objects.Items.Count > 0) + listView_communication_objects.TopItem = listView_communication_objects.Items[listview_communication_position]; + if (listview_manufacturer_position != 0 && listView_manufacturer_objects.Items.Count > 0) + listView_manufacturer_objects.TopItem = listView_manufacturer_objects.Items[listview_manufacturer_position]; + if (listview_deviceProfile_position != 0 && listView_deviceProfile_objects.Items.Count > 0) + listView_deviceProfile_objects.TopItem = listView_deviceProfile_objects.Items[listview_deviceProfile_position]; + } + + public void PopulateSubList() + { + listView_subObjects.Items.Clear(); + + if (selectedObject == null) + return; + ODentry od = selectedObject.parent ?? selectedObject; + + if (od.objecttype == ObjectType.VAR) + { + ListViewItem lvi = new ListViewItem(new string[] { + " ", // subindex + od.parameter_name, + od.ObjectTypeString(), + od.datatype.ToString(), + od.AccessSDO().ToString(), + od.AccessPDO().ToString(), + od.prop.CO_accessSRDO.ToString(), + od.defaultvalue + }); + lvi.Tag = od; + listView_subObjects.Items.Add(lvi); + } + else if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) + { + ListViewItem lvi = new ListViewItem(new string[]{ + " ", + od.parameter_name, + od.ObjectTypeString() + }); + lvi.Tag = od; + listView_subObjects.Items.Add(lvi); + + foreach (KeyValuePair kvp in od.subobjects) + { + ODentry subod = kvp.Value; + int subindex = kvp.Key; + + ListViewItem lvi2 = new ListViewItem(new string[] { + string.Format("0x{0:X2}", subindex), + subod.parameter_name, + subod.ObjectTypeString(), + (subod.datatype != DataType.UNKNOWN) ? subod.datatype.ToString() : od.datatype.ToString(), + subod.AccessSDO().ToString(), + subod.AccessPDO().ToString(), + subod.prop.CO_accessSRDO.ToString(), + subod.defaultvalue + }); + lvi2.Tag = subod; + listView_subObjects.Items.Add(lvi2); + } + } + } + + public void PopulateObject() + { + + ExporterV4 = ExporterTypeV4(); if (ExporterOld != ExporterV4) - { - RebuildControls(); + { + RebuildControls(); ExporterOld = ExporterV4; - } - - justUpdating = true; - lastSelectedObject = selectedObject; - - - if (selectedObject == null) - { - textBox_index.Text = ""; - textBox_subIndex.Text = ""; - textBox_name.Text = ""; - textBox_denotation.Text = ""; - textBox_description.Text = ""; - justUpdating = false; - return; - } - - ODentry od = selectedObject; - - textBox_index.Text = string.Format("0x{0:X4}", od.Index); - textBox_name.Text = od.parameter_name; - textBox_denotation.Text = od.denotation; - textBox_description.Text = (od.Description == null) ? "" : Regex.Replace(od.Description, "(? 0) - { - foreach (ODentry subod in od.parent.subobjects.Values) - { - if (subod.Subindex > 0) - { - subod.datatype = od.datatype; - subod.accesstype = od.accesstype; - subod.PDOtype = od.PDOtype; - subod.prop.CO_accessSRDO = od.prop.CO_accessSRDO; - } - } - od.parent.datatype = od.datatype; - od.parent.accesstype = od.accesstype; - od.parent.PDOtype = od.PDOtype; - od.parent.prop.CO_accessSRDO = od.prop.CO_accessSRDO; - } - } - - if (od.parent == null) - { - od.prop.CO_countLabel = comboBox_countLabel.SelectedItem.ToString(); - od.prop.CO_storageGroup = comboBox_storageGroup.SelectedItem.ToString(); - od.prop.CO_disabled = !checkBox_enabled.Checked; - od.prop.CO_flagsPDO = checkBox_pdoFlags.Checked; - } - - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - - private void ListView_objects_MouseClick(object sender, MouseEventArgs e) - { - ListView listview = (ListView)sender; - ODentry od = listview.SelectedItems.Count > 0 ? (ODentry)listview.SelectedItems[0].Tag : null; - - if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) - { - selectedList = listview; - selectedObject = od; - - if (e.Button == MouseButtons.Right) - { - contextMenu_object.Show(Cursor.Position); - } - - PopulateObject(); - PopulateSubList(); - } - listView_communication_objects.HideSelection = true; - listView_deviceProfile_objects.HideSelection = true; - listView_manufacturer_objects.HideSelection = true; - } - - private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) - { - ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); - } - - private void ListView_objects_ColumnClick(object sender, ColumnClickEventArgs e) - { - ((ListView)sender).SelectedItems.Clear(); - ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0)); - } - - private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) - { - if (listView_subObjects.SelectedItems.Count == 0) - return; - - ODentry od = (ODentry)listView_subObjects.SelectedItems[0].Tag; - - if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) - { - if (e.Button == MouseButtons.Right) - { - ODentry parent = od.parent ?? od; - - if (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.RECORD) - { - contextMenu_subObject_removeSubItemToolStripMenuItem.Enabled = od.Subindex > 0 && od.parent != null; - contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Enabled = parent.objecttype == ObjectType.RECORD && od.Subindex > 0 && od.parent != null; - - if (listView_subObjects.FocusedItem.Bounds.Contains(e.Location) == true) - { - contextMenu_subObject.Show(Cursor.Position); - } - } - } - selectedObject = od; - PopulateObject(); - } - } - - private void ListView_subObjects_SelectedIndexChanged(object sender, EventArgs e) - { - ListView_subObjects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); - } - - private void ComboBox_countLabel_Add(object sender, EventArgs e) - { - ComboBox comboBox = (ComboBox)sender; - - if (comboBox.SelectedItem != null && comboBox.SelectedItem.ToString() == "Add...") - { - NewItem dialog = new NewItem("Add Count Label"); - if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) - { - comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); - comboBox.SelectedItem = dialog.name; - } - } - } - - private void ComboBox_storageGroup_Add(object sender, EventArgs e) - { - ComboBox comboBox = (ComboBox)sender; - - if (comboBox.SelectedItem!=null && comboBox.SelectedItem.ToString() == "Add...") - { - NewItem dialog = new NewItem("Add Storage Group"); - if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) - { - comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); - comboBox.SelectedItem = dialog.name; - /* add new dialog location to eds back end */ - eds.CO_storageGroups.Add(dialog.name); - } - } - } - - private void ContextMenu_object_clone_ToolStripMenuItem_Click(object sender, EventArgs e) - { - var srcObjects = new SortedDictionary(); - foreach (ListViewItem item in selectedList.SelectedItems) - { - ODentry od = (ODentry)item.Tag; - srcObjects.Add(od.Index, od); - } - - if (srcObjects.Count > 0) - { - InsertObjects insObjForm = new InsertObjects(eds, srcObjects, "1"); - - if (insObjForm.ShowDialog() == DialogResult.OK) - { - selectedObject = null; - eds.Dirty = true; - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - } - } - - private void ContextMenu_object_add_ToolStripMenuItem_Click(object sender, EventArgs e) - { - NewIndex ni = new NewIndex(eds, (UInt16)(selectedObject == null ? 0x2000 : selectedObject.Index + 1)); - - if (ni.ShowDialog() == DialogResult.OK) - { - selectedObject = ni.od; - eds.Dirty = true; - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - } - - private void ContextMenu_object_delete_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; - if (selectedItems.Count > 0) - { - DialogResult confirmDelete = MessageBox.Show(string.Format("Do you really want to delete the selected {0} items?", selectedItems.Count), "Are you sure?", MessageBoxButtons.YesNo); - - if (confirmDelete == DialogResult.Yes) - { - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - eds.ods.Remove(od.Index); - } - - eds.Dirty = true; - selectedObject = null; - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - } - } - - private void ContextMenu_object_toggle_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; - - justUpdating = true; - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - - od.prop.CO_disabled = !od.prop.CO_disabled; - } - justUpdating = false; - eds.Dirty = true; - PopulateObjectLists(eds); - PopulateObject(); - } - - private void ContextMenu_subObject_add_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; - - ODentry newOd = null; - - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - newOd = od.AddSubEntry(); - } - - eds.Dirty = true; - selectedObject = newOd; - PopulateSubList(); - PopulateObject(); - } - - private void ContextMenu_subObject_remove_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; - bool renumber = sender == contextMenu_subObject_removeSubItemToolStripMenuItem; - bool update = false; - - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - od.RemoveSubEntry(renumber); - update = true; - } - - if (update) - { - eds.Dirty = true; - selectedObject = selectedObject.parent; - PopulateSubList(); - PopulateObject(); - } - } - } - - public static class ControlExtensions - { - public static void DoubleBuffering(this Control control, bool enable) - { - var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic); - method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable }); - } - } -} + od.prop.CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), comboBox_accessSRDO.SelectedItem.ToString()); + } + catch (Exception) + { + od.prop.CO_accessSRDO = AccessSRDO.no; + } + + od.defaultvalue = textBox_defaultValue.Text; + od.actualvalue = textBox_actualValue.Text; + od.HighLimit = textBox_highLimit.Text; + od.LowLimit = textBox_lowLimit.Text; + + // CO_stringLengthMin + if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.UNICODE_STRING || od.datatype == DataType.OCTET_STRING) + { + try + { + od.prop.CO_stringLengthMin = (uint)new System.ComponentModel.UInt32Converter().ConvertFromString(textBox_stringLengthMin.Text); + } + catch (Exception) + { + od.prop.CO_stringLengthMin = 0; + } + } + else + { + od.prop.CO_stringLengthMin = 0; + } + + // some propeties in all array sub elements (and base element) must be equal + if (od.parent != null && od.parent.objecttype == ObjectType.ARRAY && od.Subindex > 0) + { + foreach (ODentry subod in od.parent.subobjects.Values) + { + if (subod.Subindex > 0) + { + subod.datatype = od.datatype; + subod.accesstype = od.accesstype; + subod.PDOtype = od.PDOtype; + subod.prop.CO_accessSRDO = od.prop.CO_accessSRDO; + } + } + od.parent.datatype = od.datatype; + od.parent.accesstype = od.accesstype; + od.parent.PDOtype = od.PDOtype; + od.parent.prop.CO_accessSRDO = od.prop.CO_accessSRDO; + } + } + + if (od.parent == null) + { + od.prop.CO_countLabel = comboBox_countLabel.SelectedItem.ToString(); + od.prop.CO_storageGroup = comboBox_storageGroup.SelectedItem.ToString(); + od.prop.CO_disabled = !checkBox_enabled.Checked; + od.prop.CO_flagsPDO = checkBox_pdoFlags.Checked; + } + + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + + private void ListView_objects_MouseClick(object sender, MouseEventArgs e) + { + ListView listview = (ListView)sender; + ODentry od = listview.SelectedItems.Count > 0 ? (ODentry)listview.SelectedItems[0].Tag : null; + + if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) + { + selectedList = listview; + selectedObject = od; + + if (e.Button == MouseButtons.Right) + { + contextMenu_object.Show(Cursor.Position); + } + + PopulateObject(); + PopulateSubList(); + } + listView_communication_objects.HideSelection = true; + listView_deviceProfile_objects.HideSelection = true; + listView_manufacturer_objects.HideSelection = true; + } + + private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) + { + ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); + } + + private void ListView_objects_ColumnClick(object sender, ColumnClickEventArgs e) + { + ((ListView)sender).SelectedItems.Clear(); + ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0)); + } + + private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) + { + if (listView_subObjects.SelectedItems.Count == 0) + return; + + ODentry od = (ODentry)listView_subObjects.SelectedItems[0].Tag; + + if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) + { + if (e.Button == MouseButtons.Right) + { + ODentry parent = od.parent ?? od; + + if (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.RECORD) + { + contextMenu_subObject_removeSubItemToolStripMenuItem.Enabled = od.Subindex > 0 && od.parent != null; + contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Enabled = parent.objecttype == ObjectType.RECORD && od.Subindex > 0 && od.parent != null; + + + if (isClickOnItem(e.Location)) + { + contextMenu_subObject.Show(Cursor.Position); + } + } + } + selectedObject = od; + PopulateObject(); + } + } + + private bool isClickOnItem(Point location) + { + if (listView_subObjects.FocusedItem != null) + { + return listView_subObjects.FocusedItem.Bounds.Contains(location); + } + + foreach (ListViewItem item in listView_subObjects.Items) + { + if (item.Bounds.Contains(location)) + { + return true; + } + } + + return false; + } + + private void ListView_subObjects_SelectedIndexChanged(object sender, EventArgs e) + { + ListView_subObjects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); + } + + private void ComboBox_countLabel_Add(object sender, EventArgs e) + { + ComboBox comboBox = (ComboBox)sender; + + if (comboBox.SelectedItem != null && comboBox.SelectedItem.ToString() == "Add...") + { + NewItem dialog = new NewItem("Add Count Label"); + if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) + { + comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); + comboBox.SelectedItem = dialog.name; + } + } + } + + private void ComboBox_storageGroup_Add(object sender, EventArgs e) + { + ComboBox comboBox = (ComboBox)sender; + + if (comboBox.SelectedItem!=null && comboBox.SelectedItem.ToString() == "Add...") + { + NewItem dialog = new NewItem("Add Storage Group"); + if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) + { + comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); + comboBox.SelectedItem = dialog.name; + /* add new dialog location to eds back end */ + eds.CO_storageGroups.Add(dialog.name); + } + } + } + + private void ContextMenu_object_clone_ToolStripMenuItem_Click(object sender, EventArgs e) + { + var srcObjects = new SortedDictionary(); + foreach (ListViewItem item in selectedList.SelectedItems) + { + ODentry od = (ODentry)item.Tag; + srcObjects.Add(od.Index, od); + } + + if (srcObjects.Count > 0) + { + InsertObjects insObjForm = new InsertObjects(eds, srcObjects, "1"); + + if (insObjForm.ShowDialog() == DialogResult.OK) + { + selectedObject = null; + eds.Dirty = true; + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + } + } + + private void ContextMenu_object_add_ToolStripMenuItem_Click(object sender, EventArgs e) + { + NewIndex ni = new NewIndex(eds, (UInt16)(selectedObject == null ? 0x2000 : selectedObject.Index + 1)); + + if (ni.ShowDialog() == DialogResult.OK) + { + selectedObject = ni.od; + eds.Dirty = true; + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + } + + private void ContextMenu_object_delete_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; + if (selectedItems.Count > 0) + { + DialogResult confirmDelete = MessageBox.Show(string.Format("Do you really want to delete the selected {0} items?", selectedItems.Count), "Are you sure?", MessageBoxButtons.YesNo); + + if (confirmDelete == DialogResult.Yes) + { + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + eds.ods.Remove(od.Index); + } + + eds.Dirty = true; + selectedObject = null; + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + } + } + + private void ContextMenu_object_toggle_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; + + justUpdating = true; + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + + od.prop.CO_disabled = !od.prop.CO_disabled; + } + justUpdating = false; + eds.Dirty = true; + PopulateObjectLists(eds); + PopulateObject(); + } + + private void ContextMenu_subObject_add_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; + + ODentry newOd = null; + + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + newOd = od.AddSubEntry(); + } + + eds.Dirty = true; + selectedObject = newOd; + PopulateSubList(); + PopulateObject(); + } + + private void ContextMenu_subObject_remove_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; + bool renumber = sender == contextMenu_subObject_removeSubItemToolStripMenuItem; + bool update = false; + + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + od.RemoveSubEntry(renumber); + update = true; + } + + if (update) + { + eds.Dirty = true; + selectedObject = selectedObject.parent; + PopulateSubList(); + PopulateObject(); + } + } + } + + public static class ControlExtensions + { + public static void DoubleBuffering(this Control control, bool enable) + { + var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic); + method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable }); + } + } +} diff --git a/EDSEditorGUI/DeviceView.Designer.cs b/EDSEditorGUI/DeviceView.Designer.cs index 52b4b56a..27657fd5 100644 --- a/EDSEditorGUI/DeviceView.Designer.cs +++ b/EDSEditorGUI/DeviceView.Designer.cs @@ -60,9 +60,10 @@ private void InitializeComponent() // this.tabPage4.Controls.Add(this.devicePDOView2); this.tabPage4.ImageIndex = 3; - this.tabPage4.Location = new System.Drawing.Point(4, 23); + this.tabPage4.Location = new System.Drawing.Point(4, 25); + this.tabPage4.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(1114, 746); + this.tabPage4.Size = new System.Drawing.Size(1488, 922); this.tabPage4.TabIndex = 3; this.tabPage4.Text = "RX PDO Mapping"; this.tabPage4.UseVisualStyleBackColor = true; @@ -73,18 +74,19 @@ private void InitializeComponent() this.devicePDOView2.AutoSize = true; this.devicePDOView2.Dock = System.Windows.Forms.DockStyle.Fill; this.devicePDOView2.Location = new System.Drawing.Point(0, 0); - this.devicePDOView2.Margin = new System.Windows.Forms.Padding(4); + this.devicePDOView2.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); this.devicePDOView2.Name = "devicePDOView2"; - this.devicePDOView2.Size = new System.Drawing.Size(1114, 746); + this.devicePDOView2.Size = new System.Drawing.Size(1488, 922); this.devicePDOView2.TabIndex = 0; // // tabPage3 // this.tabPage3.Controls.Add(this.devicePDOView1); this.tabPage3.ImageIndex = 2; - this.tabPage3.Location = new System.Drawing.Point(4, 23); + this.tabPage3.Location = new System.Drawing.Point(4, 25); + this.tabPage3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(1114, 746); + this.tabPage3.Size = new System.Drawing.Size(1488, 922); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "TX PDO Mapping"; this.tabPage3.UseVisualStyleBackColor = true; @@ -95,19 +97,20 @@ private void InitializeComponent() this.devicePDOView1.AutoSize = true; this.devicePDOView1.Dock = System.Windows.Forms.DockStyle.Fill; this.devicePDOView1.Location = new System.Drawing.Point(0, 0); - this.devicePDOView1.Margin = new System.Windows.Forms.Padding(4); + this.devicePDOView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); this.devicePDOView1.Name = "devicePDOView1"; - this.devicePDOView1.Size = new System.Drawing.Size(1114, 746); + this.devicePDOView1.Size = new System.Drawing.Size(1488, 922); this.devicePDOView1.TabIndex = 0; // // tabPage2 // this.tabPage2.Controls.Add(this.deviceODView1); this.tabPage2.ImageIndex = 0; - this.tabPage2.Location = new System.Drawing.Point(4, 23); + this.tabPage2.Location = new System.Drawing.Point(4, 25); + this.tabPage2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tabPage2.Name = "tabPage2"; - this.tabPage2.Padding = new System.Windows.Forms.Padding(3); - this.tabPage2.Size = new System.Drawing.Size(1114, 746); + this.tabPage2.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage2.Size = new System.Drawing.Size(1488, 922); this.tabPage2.TabIndex = 0; this.tabPage2.Text = "Object Dictionary"; this.tabPage2.UseVisualStyleBackColor = true; @@ -115,20 +118,21 @@ private void InitializeComponent() // deviceODView1 // this.deviceODView1.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceODView1.Location = new System.Drawing.Point(3, 3); - this.deviceODView1.Margin = new System.Windows.Forms.Padding(4); + this.deviceODView1.Location = new System.Drawing.Point(4, 4); + this.deviceODView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); this.deviceODView1.Name = "deviceODView1"; - this.deviceODView1.Size = new System.Drawing.Size(1108, 740); + this.deviceODView1.Size = new System.Drawing.Size(1480, 914); this.deviceODView1.TabIndex = 0; // // tabPage1 // this.tabPage1.Controls.Add(this.deviceInfoView); this.tabPage1.ImageIndex = 1; - this.tabPage1.Location = new System.Drawing.Point(4, 23); + this.tabPage1.Location = new System.Drawing.Point(4, 25); + this.tabPage1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tabPage1.Name = "tabPage1"; - this.tabPage1.Padding = new System.Windows.Forms.Padding(3); - this.tabPage1.Size = new System.Drawing.Size(1114, 746); + this.tabPage1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage1.Size = new System.Drawing.Size(1488, 922); this.tabPage1.TabIndex = 1; this.tabPage1.Text = "Device Info"; this.tabPage1.UseVisualStyleBackColor = true; @@ -136,10 +140,10 @@ private void InitializeComponent() // deviceInfoView // this.deviceInfoView.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceInfoView.Location = new System.Drawing.Point(3, 3); - this.deviceInfoView.Margin = new System.Windows.Forms.Padding(4); + this.deviceInfoView.Location = new System.Drawing.Point(4, 4); + this.deviceInfoView.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); this.deviceInfoView.Name = "deviceInfoView"; - this.deviceInfoView.Size = new System.Drawing.Size(1108, 740); + this.deviceInfoView.Size = new System.Drawing.Size(1480, 914); this.deviceInfoView.TabIndex = 0; // // tabControl1 @@ -151,18 +155,20 @@ private void InitializeComponent() this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl1.ImageList = this.imageList1; this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(1122, 773); + this.tabControl1.Size = new System.Drawing.Size(1496, 951); this.tabControl1.TabIndex = 1; // // DeviceView // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.tabControl1); + this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "DeviceView"; - this.Size = new System.Drawing.Size(1122, 773); + this.Size = new System.Drawing.Size(1496, 951); this.tabPage4.ResumeLayout(false); this.tabPage4.PerformLayout(); this.tabPage3.ResumeLayout(false); diff --git a/EDSEditorGUI/DeviceView.resx b/EDSEditorGUI/DeviceView.resx index 8cd3b4d7..8e4e9474 100644 --- a/EDSEditorGUI/DeviceView.resx +++ b/EDSEditorGUI/DeviceView.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACk - CgAAAk1TRnQBSQFMAgEBBAEAAWABAAFgAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CgAAAk1TRnQBSQFMAgEBBAEAAWgBAAFoAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/EDSEditorGUI/Form1.Designer.cs b/EDSEditorGUI/Form1.Designer.cs index 6baecbbd..8851ddfc 100644 --- a/EDSEditorGUI/Form1.Designer.cs +++ b/EDSEditorGUI/Form1.Designer.cs @@ -28,305 +28,307 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ODEditor_MainForm)); - this.menuStrip1 = new System.Windows.Forms.MenuStrip(); - this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.openCanOpenNodeXMLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveProjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.loadNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); - this.mnuRecentlyUsed = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.exportDeviceFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.exportCanOpenNodeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveExportAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.closeFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); - this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.insertToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.reportsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.documentationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.networkPDOToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.tabControl1 = new System.Windows.Forms.TabControl(); - this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); - this.menuStrip1.SuspendLayout(); - this.SuspendLayout(); - // - // menuStrip1 - // - this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); - this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.fileToolStripMenuItem, - this.insertToolStripMenuItem, - this.reportsToolStripMenuItem, - this.toolsToolStripMenuItem}); - this.menuStrip1.Location = new System.Drawing.Point(0, 0); - this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Size = new System.Drawing.Size(1199, 24); - this.menuStrip1.TabIndex = 1; - this.menuStrip1.Text = "menuStrip1"; - // - // fileToolStripMenuItem - // - this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.newToolStripMenuItem, - this.openCanOpenNodeXMLToolStripMenuItem, - this.saveProjectToolStripMenuItem, - this.saveAsToolStripMenuItem, - this.toolStripSeparator3, - this.loadNetworkXmlToolStripMenuItem, - this.saveNetworkXmlToolStripMenuItem, - this.toolStripSeparator6, - this.mnuRecentlyUsed, - this.toolStripSeparator1, - this.exportDeviceFileToolStripMenuItem, - this.exportCanOpenNodeToolStripMenuItem, - this.saveExportAllToolStripMenuItem, - this.toolStripSeparator2, - this.closeFileToolStripMenuItem, - this.toolStripSeparator4, - this.quitToolStripMenuItem}); - this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; - this.fileToolStripMenuItem.Size = new System.Drawing.Size(37, 20); - this.fileToolStripMenuItem.Text = "&File"; - // - // newToolStripMenuItem - // - this.newToolStripMenuItem.Image = global::ODEditor.Properties.Resources.NewFile_6276; - this.newToolStripMenuItem.Name = "newToolStripMenuItem"; - this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); - this.newToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.newToolStripMenuItem.Text = "&New"; - this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click); - // - // openCanOpenNodeXMLToolStripMenuItem - // - this.openCanOpenNodeXMLToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; - this.openCanOpenNodeXMLToolStripMenuItem.Name = "openCanOpenNodeXMLToolStripMenuItem"; - this.openCanOpenNodeXMLToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); - this.openCanOpenNodeXMLToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.openCanOpenNodeXMLToolStripMenuItem.Text = "&Open"; - this.openCanOpenNodeXMLToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); - // - // saveProjectToolStripMenuItem - // - this.saveProjectToolStripMenuItem.Enabled = false; - this.saveProjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; - this.saveProjectToolStripMenuItem.Name = "saveProjectToolStripMenuItem"; - this.saveProjectToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); - this.saveProjectToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.saveProjectToolStripMenuItem.Text = "&Save Project"; - this.saveProjectToolStripMenuItem.Click += new System.EventHandler(this.saveProjectToolStripMenuItem_Click); - // - // saveAsToolStripMenuItem - // - this.saveAsToolStripMenuItem.Enabled = false; - this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem"; - this.saveAsToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) - | System.Windows.Forms.Keys.S))); - this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.saveAsToolStripMenuItem.Text = "Save &Project As..."; - this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click); - // - // toolStripSeparator3 - // - this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(236, 6); - // - // loadNetworkXmlToolStripMenuItem - // - this.loadNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; - this.loadNetworkXmlToolStripMenuItem.Name = "loadNetworkXmlToolStripMenuItem"; - this.loadNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.loadNetworkXmlToolStripMenuItem.Text = "Open &Network XML"; - this.loadNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.loadNetworkXmlToolStripMenuItem_Click); - // - // saveNetworkXmlToolStripMenuItem - // - this.saveNetworkXmlToolStripMenuItem.Enabled = false; - this.saveNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; - this.saveNetworkXmlToolStripMenuItem.Name = "saveNetworkXmlToolStripMenuItem"; - this.saveNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.saveNetworkXmlToolStripMenuItem.Text = "Save Networ&k XML"; - this.saveNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.saveNetworkXmlToolStripMenuItem_Click); - // - // toolStripSeparator6 - // - this.toolStripSeparator6.Name = "toolStripSeparator6"; - this.toolStripSeparator6.Size = new System.Drawing.Size(236, 6); - // - // mnuRecentlyUsed - // - this.mnuRecentlyUsed.Name = "mnuRecentlyUsed"; - this.mnuRecentlyUsed.Size = new System.Drawing.Size(239, 26); - this.mnuRecentlyUsed.Text = "&Recent Files"; - // - // toolStripSeparator1 - // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(236, 6); - // - // exportDeviceFileToolStripMenuItem - // - this.exportDeviceFileToolStripMenuItem.Enabled = false; - this.exportDeviceFileToolStripMenuItem.Name = "exportDeviceFileToolStripMenuItem"; - this.exportDeviceFileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); - this.exportDeviceFileToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.exportDeviceFileToolStripMenuItem.Text = "&Export..."; - this.exportDeviceFileToolStripMenuItem.Click += new System.EventHandler(this.exportDeviceFileToolStripMenuItem_Click); - // - // exportCanOpenNodeToolStripMenuItem - // - this.exportCanOpenNodeToolStripMenuItem.Enabled = false; - this.exportCanOpenNodeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("exportCanOpenNodeToolStripMenuItem.Image"))); - this.exportCanOpenNodeToolStripMenuItem.Name = "exportCanOpenNodeToolStripMenuItem"; - this.exportCanOpenNodeToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.exportCanOpenNodeToolStripMenuItem.Text = "E&xport CanOpenNode..."; - this.exportCanOpenNodeToolStripMenuItem.Click += new System.EventHandler(this.exportCanOpenNodeToolStripMenuItem_Click); - // - // saveExportAllToolStripMenuItem - // - this.saveExportAllToolStripMenuItem.Enabled = false; - this.saveExportAllToolStripMenuItem.Name = "saveExportAllToolStripMenuItem"; - this.saveExportAllToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.saveExportAllToolStripMenuItem.Text = "Save &All"; - this.saveExportAllToolStripMenuItem.Click += new System.EventHandler(this.saveExportAllToolStripMenuItem_Click); - // - // toolStripSeparator2 - // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(236, 6); - // - // closeFileToolStripMenuItem - // - this.closeFileToolStripMenuItem.Enabled = false; - this.closeFileToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Close_6519; - this.closeFileToolStripMenuItem.Name = "closeFileToolStripMenuItem"; - this.closeFileToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.closeFileToolStripMenuItem.Text = "&Close file"; - this.closeFileToolStripMenuItem.Click += new System.EventHandler(this.closeFileToolStripMenuItem_Click); - // - // toolStripSeparator4 - // - this.toolStripSeparator4.Name = "toolStripSeparator4"; - this.toolStripSeparator4.Size = new System.Drawing.Size(236, 6); - // - // quitToolStripMenuItem - // - this.quitToolStripMenuItem.Image = global::ODEditor.Properties.Resources._305_Close_16x16_72; - this.quitToolStripMenuItem.Name = "quitToolStripMenuItem"; - this.quitToolStripMenuItem.Size = new System.Drawing.Size(239, 26); - this.quitToolStripMenuItem.Text = "&Quit"; - this.quitToolStripMenuItem.Click += new System.EventHandler(this.quitToolStripMenuItem_Click); - // - // insertToolStripMenuItem - // - this.insertToolStripMenuItem.Name = "insertToolStripMenuItem"; - this.insertToolStripMenuItem.Size = new System.Drawing.Size(85, 20); - this.insertToolStripMenuItem.Text = "&Insert Profile"; - // - // reportsToolStripMenuItem - // - this.reportsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.documentationToolStripMenuItem, - this.networkPDOToolStripMenuItem}); - this.reportsToolStripMenuItem.Name = "reportsToolStripMenuItem"; - this.reportsToolStripMenuItem.Size = new System.Drawing.Size(59, 20); - this.reportsToolStripMenuItem.Text = "&Reports"; - // - // documentationToolStripMenuItem - // - this.documentationToolStripMenuItem.Enabled = false; - this.documentationToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; - this.documentationToolStripMenuItem.Name = "documentationToolStripMenuItem"; - this.documentationToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); - this.documentationToolStripMenuItem.Size = new System.Drawing.Size(219, 22); - this.documentationToolStripMenuItem.Text = "&Documentation"; - this.documentationToolStripMenuItem.Click += new System.EventHandler(this.documentationToolStripMenuItem_Click); - // - // networkPDOToolStripMenuItem - // - this.networkPDOToolStripMenuItem.Enabled = false; - this.networkPDOToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; - this.networkPDOToolStripMenuItem.Name = "networkPDOToolStripMenuItem"; - this.networkPDOToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) - | System.Windows.Forms.Keys.P))); - this.networkPDOToolStripMenuItem.Size = new System.Drawing.Size(219, 22); - this.networkPDOToolStripMenuItem.Text = "&Network PDO"; - this.networkPDOToolStripMenuItem.Click += new System.EventHandler(this.networkPDOToolStripMenuItem_Click); - // - // toolsToolStripMenuItem - // - this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem}); - this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; - this.toolsToolStripMenuItem.Size = new System.Drawing.Size(46, 20); - this.toolsToolStripMenuItem.Text = "Tools"; - // - // preferencesToolStripMenuItem - // - this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; - this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(135, 22); - this.preferencesToolStripMenuItem.Text = "Preferences"; - this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); - // - // tabControl1 - // - this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Left; - this.tabControl1.AllowDrop = true; - this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabControl1.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed; - this.tabControl1.ItemSize = new System.Drawing.Size(24, 120); - this.tabControl1.Location = new System.Drawing.Point(0, 24); - this.tabControl1.Multiline = true; - this.tabControl1.Name = "tabControl1"; - this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(1199, 737); - this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; - this.tabControl1.TabIndex = 2; - this.tabControl1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabControl1_DrawItem); - this.tabControl1.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.tabControl1_ControlsChanged); - this.tabControl1.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.tabControl1_Controlsremoved); - this.tabControl1.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); - this.tabControl1.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); - this.tabControl1.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); - this.tabControl1.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); - this.tabControl1.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); - // - // ODEditor_MainForm - // - this.AllowDrop = true; - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1199, 761); - this.Controls.Add(this.tabControl1); - this.Controls.Add(this.menuStrip1); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Name = "ODEditor_MainForm"; - this.Text = "Object Dictionary Editor "; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ODEditor_MainForm_FormClosing); - this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ODEditor_MainForm_FormClosed); - this.Load += new System.EventHandler(this.ODEditor_MainForm_Load); - this.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); - this.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); - this.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); - this.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); - this.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); - this.MouseCaptureChanged += new System.EventHandler(this.ODEditor_MainForm_Leave); - this.MouseLeave += new System.EventHandler(this.ODEditor_MainForm_Leave); - this.menuStrip1.ResumeLayout(false); - this.menuStrip1.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ODEditor_MainForm)); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openCanOpenNodeXMLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveProjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.loadNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuRecentlyUsed = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.exportDeviceFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exportCanOpenNodeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveExportAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.closeFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.insertToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.reportsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.documentationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.networkPDOToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.menuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.insertToolStripMenuItem, + this.reportsToolStripMenuItem, + this.toolsToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(1599, 28); + this.menuStrip1.TabIndex = 1; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.newToolStripMenuItem, + this.openCanOpenNodeXMLToolStripMenuItem, + this.saveProjectToolStripMenuItem, + this.saveAsToolStripMenuItem, + this.toolStripSeparator3, + this.loadNetworkXmlToolStripMenuItem, + this.saveNetworkXmlToolStripMenuItem, + this.toolStripSeparator6, + this.mnuRecentlyUsed, + this.toolStripSeparator1, + this.exportDeviceFileToolStripMenuItem, + this.exportCanOpenNodeToolStripMenuItem, + this.saveExportAllToolStripMenuItem, + this.toolStripSeparator2, + this.closeFileToolStripMenuItem, + this.toolStripSeparator4, + this.quitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(46, 24); + this.fileToolStripMenuItem.Text = "&File"; + // + // newToolStripMenuItem + // + this.newToolStripMenuItem.Image = global::ODEditor.Properties.Resources.NewFile_6276; + this.newToolStripMenuItem.Name = "newToolStripMenuItem"; + this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); + this.newToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.newToolStripMenuItem.Text = "&New"; + this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click); + // + // openCanOpenNodeXMLToolStripMenuItem + // + this.openCanOpenNodeXMLToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; + this.openCanOpenNodeXMLToolStripMenuItem.Name = "openCanOpenNodeXMLToolStripMenuItem"; + this.openCanOpenNodeXMLToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.openCanOpenNodeXMLToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.openCanOpenNodeXMLToolStripMenuItem.Text = "&Open"; + this.openCanOpenNodeXMLToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); + // + // saveProjectToolStripMenuItem + // + this.saveProjectToolStripMenuItem.Enabled = false; + this.saveProjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; + this.saveProjectToolStripMenuItem.Name = "saveProjectToolStripMenuItem"; + this.saveProjectToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.saveProjectToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveProjectToolStripMenuItem.Text = "&Save Project"; + this.saveProjectToolStripMenuItem.Click += new System.EventHandler(this.saveProjectToolStripMenuItem_Click); + // + // saveAsToolStripMenuItem + // + this.saveAsToolStripMenuItem.Enabled = false; + this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem"; + this.saveAsToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.S))); + this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveAsToolStripMenuItem.Text = "Save &Project As..."; + this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(356, 6); + // + // loadNetworkXmlToolStripMenuItem + // + this.loadNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; + this.loadNetworkXmlToolStripMenuItem.Name = "loadNetworkXmlToolStripMenuItem"; + this.loadNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.loadNetworkXmlToolStripMenuItem.Text = "Open &Network XML"; + this.loadNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.loadNetworkXmlToolStripMenuItem_Click); + // + // saveNetworkXmlToolStripMenuItem + // + this.saveNetworkXmlToolStripMenuItem.Enabled = false; + this.saveNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; + this.saveNetworkXmlToolStripMenuItem.Name = "saveNetworkXmlToolStripMenuItem"; + this.saveNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveNetworkXmlToolStripMenuItem.Text = "Save Networ&k XML"; + this.saveNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.saveNetworkXmlToolStripMenuItem_Click); + // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(356, 6); + // + // mnuRecentlyUsed + // + this.mnuRecentlyUsed.Name = "mnuRecentlyUsed"; + this.mnuRecentlyUsed.Size = new System.Drawing.Size(359, 26); + this.mnuRecentlyUsed.Text = "&Recent Files"; + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(356, 6); + // + // exportDeviceFileToolStripMenuItem + // + this.exportDeviceFileToolStripMenuItem.Enabled = false; + this.exportDeviceFileToolStripMenuItem.Name = "exportDeviceFileToolStripMenuItem"; + this.exportDeviceFileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); + this.exportDeviceFileToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.exportDeviceFileToolStripMenuItem.Text = "&Export..."; + this.exportDeviceFileToolStripMenuItem.Click += new System.EventHandler(this.exportDeviceFileToolStripMenuItem_Click); + // + // exportCanOpenNodeToolStripMenuItem + // + this.exportCanOpenNodeToolStripMenuItem.Enabled = false; + this.exportCanOpenNodeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("exportCanOpenNodeToolStripMenuItem.Image"))); + this.exportCanOpenNodeToolStripMenuItem.Name = "exportCanOpenNodeToolStripMenuItem"; + this.exportCanOpenNodeToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.exportCanOpenNodeToolStripMenuItem.Text = "E&xport CanOpenNode..."; + this.exportCanOpenNodeToolStripMenuItem.Click += new System.EventHandler(this.exportCanOpenNodeToolStripMenuItem_Click); + // + // saveExportAllToolStripMenuItem + // + this.saveExportAllToolStripMenuItem.Enabled = false; + this.saveExportAllToolStripMenuItem.Name = "saveExportAllToolStripMenuItem"; + this.saveExportAllToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveExportAllToolStripMenuItem.Text = "Save &All"; + this.saveExportAllToolStripMenuItem.Click += new System.EventHandler(this.saveExportAllToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(356, 6); + // + // closeFileToolStripMenuItem + // + this.closeFileToolStripMenuItem.Enabled = false; + this.closeFileToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Close_6519; + this.closeFileToolStripMenuItem.Name = "closeFileToolStripMenuItem"; + this.closeFileToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.closeFileToolStripMenuItem.Text = "&Close file"; + this.closeFileToolStripMenuItem.Click += new System.EventHandler(this.closeFileToolStripMenuItem_Click); + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(356, 6); + // + // quitToolStripMenuItem + // + this.quitToolStripMenuItem.Image = global::ODEditor.Properties.Resources._305_Close_16x16_72; + this.quitToolStripMenuItem.Name = "quitToolStripMenuItem"; + this.quitToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.quitToolStripMenuItem.Text = "&Quit"; + this.quitToolStripMenuItem.Click += new System.EventHandler(this.quitToolStripMenuItem_Click); + // + // insertToolStripMenuItem + // + this.insertToolStripMenuItem.Name = "insertToolStripMenuItem"; + this.insertToolStripMenuItem.Size = new System.Drawing.Size(106, 24); + this.insertToolStripMenuItem.Text = "&Insert Profile"; + // + // reportsToolStripMenuItem + // + this.reportsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.documentationToolStripMenuItem, + this.networkPDOToolStripMenuItem}); + this.reportsToolStripMenuItem.Name = "reportsToolStripMenuItem"; + this.reportsToolStripMenuItem.Size = new System.Drawing.Size(74, 24); + this.reportsToolStripMenuItem.Text = "&Reports"; + // + // documentationToolStripMenuItem + // + this.documentationToolStripMenuItem.Enabled = false; + this.documentationToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; + this.documentationToolStripMenuItem.Name = "documentationToolStripMenuItem"; + this.documentationToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); + this.documentationToolStripMenuItem.Size = new System.Drawing.Size(339, 26); + this.documentationToolStripMenuItem.Text = "&Documentation"; + this.documentationToolStripMenuItem.Click += new System.EventHandler(this.documentationToolStripMenuItem_Click); + // + // networkPDOToolStripMenuItem + // + this.networkPDOToolStripMenuItem.Enabled = false; + this.networkPDOToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; + this.networkPDOToolStripMenuItem.Name = "networkPDOToolStripMenuItem"; + this.networkPDOToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.P))); + this.networkPDOToolStripMenuItem.Size = new System.Drawing.Size(339, 26); + this.networkPDOToolStripMenuItem.Text = "&Network PDO"; + this.networkPDOToolStripMenuItem.Click += new System.EventHandler(this.networkPDOToolStripMenuItem_Click); + // + // toolsToolStripMenuItem + // + this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.preferencesToolStripMenuItem}); + this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; + this.toolsToolStripMenuItem.Size = new System.Drawing.Size(58, 24); + this.toolsToolStripMenuItem.Text = "Tools"; + // + // preferencesToolStripMenuItem + // + this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; + this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(168, 26); + this.preferencesToolStripMenuItem.Text = "Preferences"; + this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); + // + // tabControl1 + // + this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Left; + this.tabControl1.AllowDrop = true; + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed; + this.tabControl1.ItemSize = new System.Drawing.Size(24, 120); + this.tabControl1.Location = new System.Drawing.Point(0, 28); + this.tabControl1.Margin = new System.Windows.Forms.Padding(4); + this.tabControl1.Multiline = true; + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(1599, 909); + this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.tabControl1.TabIndex = 2; + this.tabControl1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabControl1_DrawItem); + this.tabControl1.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.tabControl1_ControlsChanged); + this.tabControl1.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.tabControl1_Controlsremoved); + this.tabControl1.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); + this.tabControl1.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); + this.tabControl1.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); + this.tabControl1.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); + this.tabControl1.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); + // + // ODEditor_MainForm + // + this.AllowDrop = true; + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1599, 937); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.menuStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4); + this.Name = "ODEditor_MainForm"; + this.Text = "Object Dictionary Editor "; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ODEditor_MainForm_FormClosing); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ODEditor_MainForm_FormClosed); + this.Load += new System.EventHandler(this.ODEditor_MainForm_Load); + this.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); + this.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); + this.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); + this.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); + this.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); + this.MouseCaptureChanged += new System.EventHandler(this.ODEditor_MainForm_Leave); + this.MouseLeave += new System.EventHandler(this.ODEditor_MainForm_Leave); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + } #endregion diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 405c71b6..cd787376 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -532,7 +532,9 @@ private void saveProjectToolStripMenuItem_Click(object sender, EventArgs e) { saveAsToolStripMenuItem_Click(sender, e); } + dv.eds.Dirty = false; } + } private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) @@ -632,7 +634,7 @@ void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripp } break; } - + dv.dispatch_updateOD(); } diff --git a/EDSEditorGUI/Form1.resx b/EDSEditorGUI/Form1.resx index bce4e822..c579fe98 100644 --- a/EDSEditorGUI/Form1.resx +++ b/EDSEditorGUI/Form1.resx @@ -1,326 +1,329 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - 17, 17 - - - - - iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABhWlDQ1BJQ0MgcHJvZmlsZQAAKM+VkT1I - w1AUhU9TpaIVBwuKOESoThZERRw1CkWoEGqFVh1MXvojNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ - 0UVKvC8ptAgVfHB5H+e9c7jvPkCoFplut40BuuFYybgkpjMrYugVXRCohtCnMNucleUEWq6vewT4fhfj - Wfjf6tayNgMCIvEMMy2HeJ14atMxOe8TR1hB0YjPiUctapD4keuqz2+c8x4LPDNipZJzxBFiMd/EahOz - gqUTTxJHNd2gfCHts8Z5i7NeLLN6n/yF4ayxvMR1qkHEsYBFyBChoowNFOEgRrtBio0knUst/AOeXyaX - Sq4NMHLMowQdiucH/4Pfs7VzE+N+UlgC2l9c92MYCO0CtYrrfh+7bu0ECD4DV0bDX6oC05+kVxpa9Ajo - 2QYurhuaugdc7gD9T6ZiKZ4UpBJyOeD9jL4pA/TeAp2r/tzq5zh9AFI0q8QNcHAIjOQpe63Fuzua5/bn - HW9+kH4AMgFyjcd8GS4AAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF - WHRDb21tZW50AENBTm9wZW7cllV1AAAC8UlEQVRYR9WWz2sTQRTHkx6SQy5RxFv1JDGHogiVIkqFEqLE - QigetKY3iSUpPYh/gD8uoQiJIEKJ0UNNRZKjTaQiHozePAk21eagCC20NdW1plTa8X3f7mw3cZNuzSr6 - hQ+8zn6/M29nZts6/hWdIu4T4xZJE2cJ23QvGAyKRCJhCXgp80CN2qNxTAyVP5QZZVXhn6H5mRlGCl5k - 1Kg94gZmP86K/lQ/M/l8khd7Mjoq3haLokyghv5YA8p3hRcGaGahXObFoVdjY+L1xASPtWhgHzFCRC1w - hNClH8ECbTUWWVMUvQHU3xYXud6mgRF/5x4RCx9rSajnIPIFNaKKG8Dk+d5eBm8LySMAFo4gigU2X6SE - KN1qSvHmJeSn1YgqbgBvioXlVkuhNv68XQNmixoxayD9G5/hQzVapyi2Fwu04sbF0780gF8q+K7xVsz+ - A4cehYcu1wBq4zMCi8eIRuFi4Wynd+/tfHkieG4doMZYA7iszXX38Xt/pjBXBai1YctqN+/IPJ3ryrx5 - V2Oo1oYtq93832sgM1Xxm3CYGMgUKl+ZqcoZHsekoN4HjFlJyJAfIMx8PjSwTFQbWCVqxKYGJqrqb4R6 - yweMWQkWlnnMZeZbMmvAGPxBrBMrJg0YfaiNc4AVYo1AvpmPG2jclhDxhYB5iDhOqM/qj0D6AGrjHJIe - 4jyBucx8Pu0mbEl7IDts+vnY7dNlNbAjH45MPTaLDVgIsM9KAzgyeXeo1oaby2rg/2kAvh0egY/MS4zZ - LdXEPvqMNNr2SXUcPRkeHBy++vlC7PpyV3ffFRrzqI/qZLeP1UFcIzZcLpfwer34mw1KxC5Cym6frj5i - IxAIiHQ6LbLZrIjH48LpdCJ0hx2q7PbpSrndbjbn83kml8vJ/34+EU522e/TdRvbhE5lAEQiEQTmCRmw - 26drmOBtQqcwJ5NJ4fF4EHjGDlV2+3ThdpZwRtgmdKqZq0Q3DJrs9tUJtxMXBGeEbUKnZmabfA7HT/fX - L2pBY683AAAAAElFTkSuQmCC - - - - 132, 17 - - - - AAABAAYAEBAQAAEABAAoAQAAZgAAABAQAAABAAgAaAUAAI4BAAAQEAAAAQAgAGgEAAD2BgAAICAQAAEA - BADoAgAAXgsAACAgAAABAAgAqAgAAEYOAAAgIAAAAQAgAKgQAADuFgAAKAAAABAAAAAgAAAAAQAEAAAA - AACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA - /wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAA//////////D3d/93f/d38Pf3/39/9/fw93 - f/d3/3d/D/f//3//9/8A9///f//38AD3d3d3d3fwAP///3////AAAAAPfwAAAAAAD/9//wAAAAAPd3d/ - AAAAAA9//38AAAAAD3//fwAAAAAPd3d/AAAAAA////8AAP//AACAAAAAgAAAAIAAAACAAAAAgAAAAMAB - AADAAQAAwAEAAP4/AAD4DwAA+A8AAPgPAAD4DwAA+A8AAPgPAAAoAAAAEAAAACAAAAABAAgAAAAAAAAB - AAAAAAAAAAAAAAABAAAAAQAAAAAAAEJCQgDx7/AA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAAMBAQED - AwEBAQMDAQEBAwADAQIBAwMBAgEDAwECAQMAAwEBAQMDAQEBAwMBAQEDAAMDAQMDAwMBAwMDAwEDAwAA - AwEDAwMDAQMDAwMBAwAAAAMBAQEBAQEBAQEBAQMAAAADAwMDAwMBAwMDAwMDAAAAAAAAAAADAQMAAAAA - AAAAAAAAAAMDAwEDAwMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwECAgIBAwAAAAAAAAAAAAMBAgIC - AQMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwMDAwMDAwAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAA - AADAAQAAwAEAAMABAAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAABAAAAAgAAAAAQAgAAAA - AABABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAPb29v9CQkL/QkJC/0JCQv/29vb/9vb2/0JC - Qv9CQkL/QkJC//b29v/29vb/QkJC/0JCQv9CQkL/9vb2/wAAAAD29vb/QkJC//Hv8P9CQkL/9vb2//b2 - 9v9CQkL/8e/w/0JCQv/29vb/9vb2/0JCQv/x7/D/QkJC//b29v8AAAAA9vb2/0JCQv9CQkL/QkJC//b2 - 9v/29vb/QkJC/0JCQv9CQkL/9vb2//b29v9CQkL/QkJC/0JCQv/29vb/AAAAAPb29v/29vb/QkJC//b2 - 9v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2/0JC - Qv/29vb/9vb2//b29v/29vb/QkJC//b29v/29vb/9vb2//b29v9CQkL/9vb2/wAAAAAAAAAAAAAAAPb2 - 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v8AAAAAAAAAAAAA - AAD29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2/0JCQv/29vb/9vb2//b29v8AAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2/0JCQv/x7/D/8e/w//Hv8P9CQkL/9vb2/wAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v9CQkL/8e/w//Hv8P/x7/D/QkJC//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JC - Qv/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAAAADAAQAAwAEAAMAB - AAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAACAAAABAAAAAAQAEAAAAAAAAAgAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8A - AAD/AP8A//8AAP///wAAAAAAAAAAAAAAAAAAAAAAD///////////////////8A////////////////// - //AP93d3f//3d3d///d3d3/wD/d3d3//93d3f//3d3d/8A/3f/d///d/93//93/3f/AP93/3f//3f/d/ - //d/93/wD/d3d3//93d3f//3d3d/8A/3d3d///d3d3//93d3f/AP//d/////93/////3f//wD//3f/// - //d/////93//8AAP93/////3f/////d/8AAAD/d/////93/////3f/AAAA/3d3d3d3d3d3d3d3/wAAAP - 93d3d3d3d3d3d3d/8AAAD///////93////////AAAA////////d////////wAAAAAAAAAA/3f/AAAAAA - AAAAAAAAAAAP93/wAAAAAAAAAAAAAA////d////wAAAAAAAAAAAP///3f///8AAAAAAAAAAAD/d3d3d3 - f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d////3f/AAAAAAAAAAAA/3 - f///93/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d3d3d3f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAA - AAAP////////8AAAAAAAAAAAD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA - AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 - H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//////KAAAACAA - AABAAAAAAQAIAAAAAAAABAAAAAAAAAAAAAAAAQAAAAEAAAAAAABCQkIA8e/wAPb29gAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAMDAwMDAwMDAwMDAwMDAwMD - AwMDAwMDAwMDAwMDAwAAAwMBAQEBAQEDAwMDAQEBAQEBAwMDAwEBAQEBAQMDAAADAwEBAQEBAQMDAwMB - AQEBAQEDAwMDAQEBAQEBAwMAAAMDAQECAgEBAwMDAwEBAgIBAQMDAwMBAQICAQEDAwAAAwMBAQICAQED - AwMDAQECAgEBAwMDAwEBAgIBAQMDAAADAwEBAQEBAQMDAwMBAQEBAQEDAwMDAQEBAQEBAwMAAAMDAQEB - AQEBAwMDAwEBAQEBAQMDAwMBAQEBAQEDAwAAAwMDAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwMDAAAD - AwMDAQEDAwMDAwMDAwEBAwMDAwMDAwMBAQMDAwMAAAAAAwMBAQMDAwMDAwMDAQEDAwMDAwMDAwEBAwMA - AAAAAAADAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwAAAAAAAAMDAQEBAQEBAQEBAQEBAQEBAQEBAQEB - AQMDAAAAAAAAAwMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAwMAAAAAAAADAwMDAwMDAwMDAwMBAQMDAwMD - AwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwEBAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAMDAQED - AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMD - AwEBAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAQEDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAD - AwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAAAAAAAAAAAAAAAAAA - AAAAAwMBAQICAgICAgEBAwMAAAAAAAAAAAAAAAAAAAAAAAADAwEBAgICAgICAQEDAwAAAAAAAAAAAAAA - AAAAAAAAAAMDAQECAgICAgIBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQICAgICAgEBAwMAAAAAAAAA - AAAAAAAAAAAAAAADAwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAA - AAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMD - AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4AAAAGAAAABgAAAAYAA - AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAHgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAf/+B////gf//+A - Af//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//////8oAAAAIAAAAEAA - AAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAD29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAPb2 - 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA - AAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b2 - 9v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b2 - 9v9CQkL/QkJC//Hv8P/x7/D/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JC - Qv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JCQv9CQkL/9vb2//b2 - 9v/29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC//Hv - 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv/29vb/9vb2//b29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b2 - 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/9vb2//b2 - 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/wAAAAAAAAAA9vb2//b2 - 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JC - Qv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC - Qv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/9vb2//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JC - Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b29v/29vb/9vb2//b2 - 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2//b2 - 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b2 - 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b2 - 9v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//Hv8P/x7/D/8e/w//Hv8P/x7/D/8e/w/0JC - Qv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P/x7/D/8e/w//Hv - 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv - 8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JC - Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 - 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 - 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA - AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 - H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf////// - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 17, 17 + + + + + iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAABhWlDQ1BJQ0MgcHJvZmlsZQAAKM+VkT1I + w1AUhU9TpaIVBwuKOESoThZERRw1CkWoEGqFVh1MXvojNGlIUlwcBdeCgz+LVQcXZ10dXAVB8AfEydFJ + 0UVKvC8ptAgVfHB5H+e9c7jvPkCoFplut40BuuFYybgkpjMrYugVXRCohtCnMNucleUEWq6vewT4fhfj + Wfjf6tayNgMCIvEMMy2HeJ14atMxOe8TR1hB0YjPiUctapD4keuqz2+c8x4LPDNipZJzxBFiMd/EahOz + gqUTTxJHNd2gfCHts8Z5i7NeLLN6n/yF4ayxvMR1qkHEsYBFyBChoowNFOEgRrtBio0knUst/AOeXyaX + Sq4NMHLMowQdiucH/4Pfs7VzE+N+UlgC2l9c92MYCO0CtYrrfh+7bu0ECD4DV0bDX6oC05+kVxpa9Ajo + 2QYurhuaugdc7gD9T6ZiKZ4UpBJyOeD9jL4pA/TeAp2r/tzq5zh9AFI0q8QNcHAIjOQpe63Fuzua5/bn + HW9+kH4AMgFyjcd8GS4AAAAJcEhZcwAACxAAAAsQAa0jvXUAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF + WHRDb21tZW50AENBTm9wZW7cllV1AAAC8UlEQVRYR9WWz2sTQRTHkx6SQy5RxFv1JDGHogiVIkqFEqLE + QigetKY3iSUpPYh/gD8uoQiJIEKJ0UNNRZKjTaQiHozePAk21eagCC20NdW1plTa8X3f7mw3cZNuzSr6 + hQ+8zn6/M29nZts6/hWdIu4T4xZJE2cJ23QvGAyKRCJhCXgp80CN2qNxTAyVP5QZZVXhn6H5mRlGCl5k + 1Kg94gZmP86K/lQ/M/l8khd7Mjoq3haLokyghv5YA8p3hRcGaGahXObFoVdjY+L1xASPtWhgHzFCRC1w + hNClH8ECbTUWWVMUvQHU3xYXud6mgRF/5x4RCx9rSajnIPIFNaKKG8Dk+d5eBm8LySMAFo4gigU2X6SE + KN1qSvHmJeSn1YgqbgBvioXlVkuhNv68XQNmixoxayD9G5/hQzVapyi2Fwu04sbF0780gF8q+K7xVsz+ + A4cehYcu1wBq4zMCi8eIRuFi4Wynd+/tfHkieG4doMZYA7iszXX38Xt/pjBXBai1YctqN+/IPJ3ryrx5 + V2Oo1oYtq93832sgM1Xxm3CYGMgUKl+ZqcoZHsekoN4HjFlJyJAfIMx8PjSwTFQbWCVqxKYGJqrqb4R6 + yweMWQkWlnnMZeZbMmvAGPxBrBMrJg0YfaiNc4AVYo1AvpmPG2jclhDxhYB5iDhOqM/qj0D6AGrjHJIe + 4jyBucx8Pu0mbEl7IDts+vnY7dNlNbAjH45MPTaLDVgIsM9KAzgyeXeo1oaby2rg/2kAvh0egY/MS4zZ + LdXEPvqMNNr2SXUcPRkeHBy++vlC7PpyV3ffFRrzqI/qZLeP1UFcIzZcLpfwer34mw1KxC5Cym6frj5i + IxAIiHQ6LbLZrIjH48LpdCJ0hx2q7PbpSrndbjbn83kml8vJ/34+EU522e/TdRvbhE5lAEQiEQTmCRmw + 26drmOBtQqcwJ5NJ4fF4EHjGDlV2+3ThdpZwRtgmdKqZq0Q3DJrs9tUJtxMXBGeEbUKnZmabfA7HT/fX + L2pBY683AAAAAElFTkSuQmCC + + + + 132, 17 + + + 164 + + + + AAABAAYAEBAQAAEABAAoAQAAZgAAABAQAAABAAgAaAUAAI4BAAAQEAAAAQAgAGgEAAD2BgAAICAQAAEA + BADoAgAAXgsAACAgAAABAAgAqAgAAEYOAAAgIAAAAQAgAKgQAADuFgAAKAAAABAAAAAgAAAAAQAEAAAA + AACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA + /wAA/wAAAP//AP8AAAD/AP8A//8AAP///wAAAAAAAAAAAA//////////D3d/93f/d38Pf3/39/9/fw93 + f/d3/3d/D/f//3//9/8A9///f//38AD3d3d3d3fwAP///3////AAAAAPfwAAAAAAD/9//wAAAAAPd3d/ + AAAAAA9//38AAAAAD3//fwAAAAAPd3d/AAAAAA////8AAP//AACAAAAAgAAAAIAAAACAAAAAgAAAAMAB + AADAAQAAwAEAAP4/AAD4DwAA+A8AAPgPAAD4DwAA+A8AAPgPAAAoAAAAEAAAACAAAAABAAgAAAAAAAAB + AAAAAAAAAAAAAAABAAAAAQAAAAAAAEJCQgDx7/AA9vb2AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA////AAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMDAAMBAQED + AwEBAQMDAQEBAwADAQIBAwMBAgEDAwECAQMAAwEBAQMDAQEBAwMBAQEDAAMDAQMDAwMBAwMDAwEDAwAA + AwEDAwMDAQMDAwMBAwAAAAMBAQEBAQEBAQEBAQMAAAADAwMDAwMBAwMDAwMDAAAAAAAAAAADAQMAAAAA + AAAAAAAAAAMDAwEDAwMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwECAgIBAwAAAAAAAAAAAAMBAgIC + AQMAAAAAAAAAAAADAQEBAQEDAAAAAAAAAAAAAwMDAwMDAwAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAA + AADAAQAAwAEAAMABAAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAABAAAAAgAAAAAQAgAAAA + AABABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAPb29v9CQkL/QkJC/0JCQv/29vb/9vb2/0JC + Qv9CQkL/QkJC//b29v/29vb/QkJC/0JCQv9CQkL/9vb2/wAAAAD29vb/QkJC//Hv8P9CQkL/9vb2//b2 + 9v9CQkL/8e/w/0JCQv/29vb/9vb2/0JCQv/x7/D/QkJC//b29v8AAAAA9vb2/0JCQv9CQkL/QkJC//b2 + 9v/29vb/QkJC/0JCQv9CQkL/9vb2//b29v9CQkL/QkJC/0JCQv/29vb/AAAAAPb29v/29vb/QkJC//b2 + 9v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2/0JC + Qv/29vb/9vb2//b29v/29vb/QkJC//b29v/29vb/9vb2//b29v9CQkL/9vb2/wAAAAAAAAAAAAAAAPb2 + 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v8AAAAAAAAAAAAA + AAD29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2/0JCQv/29vb/9vb2//b29v8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2/0JCQv/x7/D/8e/w//Hv8P9CQkL/9vb2/wAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v9CQkL/8e/w//Hv8P/x7/D/QkJC//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/QkJC/0JCQv9CQkL/QkJC/0JC + Qv/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAD//wAAgAAAAIAAAACAAAAAgAAAAIAAAADAAQAAwAEAAMAB + AAD+PwAA+A8AAPgPAAD4DwAA+A8AAPgPAAD4DwAAKAAAACAAAABAAAAAAQAEAAAAAAAAAgAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8A + AAD/AP8A//8AAP///wAAAAAAAAAAAAAAAAAAAAAAD///////////////////8A////////////////// + //AP93d3f//3d3d///d3d3/wD/d3d3//93d3f//3d3d/8A/3f/d///d/93//93/3f/AP93/3f//3f/d/ + //d/93/wD/d3d3//93d3f//3d3d/8A/3d3d///d3d3//93d3f/AP//d/////93/////3f//wD//3f/// + //d/////93//8AAP93/////3f/////d/8AAAD/d/////93/////3f/AAAA/3d3d3d3d3d3d3d3/wAAAP + 93d3d3d3d3d3d3d/8AAAD///////93////////AAAA////////d////////wAAAAAAAAAA/3f/AAAAAA + AAAAAAAAAAAP93/wAAAAAAAAAAAAAA////d////wAAAAAAAAAAAP///3f///8AAAAAAAAAAAD/d3d3d3 + f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d////3f/AAAAAAAAAAAA/3 + f///93/wAAAAAAAAAAAP93////d/8AAAAAAAAAAAD/d3d3d3f/AAAAAAAAAAAA/3d3d3d3/wAAAAAAAA + AAAP////////8AAAAAAAAAAAD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 + H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//////KAAAACAA + AABAAAAAAQAIAAAAAAAABAAAAAAAAAAAAAAAAQAAAAEAAAAAAABCQkIA8e/wAPb29gAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAADAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMDAwMAAAMDAwMDAwMDAwMDAwMDAwMD + AwMDAwMDAwMDAwMDAwAAAwMBAQEBAQEDAwMDAQEBAQEBAwMDAwEBAQEBAQMDAAADAwEBAQEBAQMDAwMB + AQEBAQEDAwMDAQEBAQEBAwMAAAMDAQECAgEBAwMDAwEBAgIBAQMDAwMBAQICAQEDAwAAAwMBAQICAQED + AwMDAQECAgEBAwMDAwEBAgIBAQMDAAADAwEBAQEBAQMDAwMBAQEBAQEDAwMDAQEBAQEBAwMAAAMDAQEB + AQEBAwMDAwEBAQEBAQMDAwMBAQEBAQEDAwAAAwMDAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwMDAAAD + AwMDAQEDAwMDAwMDAwEBAwMDAwMDAwMBAQMDAwMAAAAAAwMBAQMDAwMDAwMDAQEDAwMDAwMDAwEBAwMA + AAAAAAADAwEBAwMDAwMDAwMBAQMDAwMDAwMDAQEDAwAAAAAAAAMDAQEBAQEBAQEBAQEBAQEBAQEBAQEB + AQMDAAAAAAAAAwMBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAwMAAAAAAAADAwMDAwMDAwMDAwMBAQMDAwMD + AwMDAwMDAwAAAAAAAAMDAwMDAwMDAwMDAwEBAwMDAwMDAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAMDAQED + AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMDAwMD + AwEBAwMDAwMDAAAAAAAAAAAAAAAAAAAAAAAAAwMDAwMDAQEDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAAD + AwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAAAAAAAAAAAAAAAAAA + AAAAAwMBAQICAgICAgEBAwMAAAAAAAAAAAAAAAAAAAAAAAADAwEBAgICAgICAQEDAwAAAAAAAAAAAAAA + AAAAAAAAAAMDAQECAgICAgIBAQMDAAAAAAAAAAAAAAAAAAAAAAAAAwMBAQICAgICAgEBAwMAAAAAAAAA + AAAAAAAAAAAAAAADAwEBAQEBAQEBAQEDAwAAAAAAAAAAAAAAAAAAAAAAAAMDAQEBAQEBAQEBAQMDAAAA + AAAAAAAAAAAAAAAAAAAAAwMDAwMDAwMDAwMDAwMAAAAAAAAAAAAAAAAAAAAAAAADAwMDAwMDAwMDAwMD + AwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////4AAAAGAAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAHgAAAH4AAAB+AAAAfgAAAH4AAAB+AAAAf/+B////gf//+A + Af//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//////8oAAAAIAAAAEAA + AAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAD29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAPb2 + 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA + AAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC//b2 + 9v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b2 + 9v9CQkL/QkJC//Hv8P/x7/D/QkJC/0JCQv/29vb/9vb2//b29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JC + Qv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w/0JCQv9CQkL/9vb2//b2 + 9v/29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC//Hv + 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv/29vb/9vb2//b29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC//b29v/29vb/9vb2//b29v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2//b2 + 9v/29vb/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAPb29v/29vb/9vb2//b2 + 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2/wAAAAAAAAAA9vb2//b2 + 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JC + Qv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/0JCQv9CQkL/9vb2//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/QkJC/0JCQv/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v9CQkL/QkJC//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/9vb2//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JC + Qv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2//b29v/29vb/9vb2//b2 + 9v9CQkL/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/9vb2//b2 + 9v/29vb/9vb2/0JCQv9CQkL/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b2 + 9v9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAD29vb/9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b2 + 9v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC//Hv8P/x7/D/8e/w//Hv8P/x7/D/8e/w/0JC + Qv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JCQv9CQkL/8e/w//Hv8P/x7/D/8e/w//Hv + 8P/x7/D/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb29v/29vb/QkJC/0JCQv/x7/D/8e/w//Hv + 8P/x7/D/8e/w//Hv8P9CQkL/QkJC//b29v/29vb/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA9vb2//b29v9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2//b29v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD29vb/9vb2/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/9vb2/wAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPb2 + 9v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/AAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAA9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA + AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////+AAAABgAAAAYAA + AAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAAB4AAAB+AAAAfgAAAH4AAAB+AAAAfgAAAH//gf///4 + H///gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf//gAH//4AB//+AAf////// + + \ No newline at end of file From 7dae47c638372c3331da4516a492c13ed20bc7dd Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 27 Apr 2023 12:25:05 +0200 Subject: [PATCH 080/226] Disable comboBox_objectType listbox, because there is no code in the DataDirty event handler that handles the change of the object type. Irritating, because the value is not taken over after saving Bug fix for issue #53: Subobjects without default value won't appear in OD.h/.c --- EDSEditorGUI/DeviceODView.Designer.cs | 5 +++-- libEDSsharp/CanOpenNodeExporter_V4.cs | 18 +++++++++--------- 2 files changed, 12 insertions(+), 11 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index 927dd188..83570eb7 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -495,9 +495,9 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.comboBox_accessPDO); this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; this.groupBox1.Location = new System.Drawing.Point(0, 328); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Padding = new System.Windows.Forms.Padding(2); this.groupBox1.Size = new System.Drawing.Size(853, 188); this.groupBox1.TabIndex = 33; this.groupBox1.TabStop = false; @@ -672,6 +672,7 @@ private void InitializeComponent() // comboBox_objectType // this.comboBox_objectType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_objectType.Enabled = false; this.comboBox_objectType.FormattingEnabled = true; this.comboBox_objectType.Location = new System.Drawing.Point(108, 18); this.comboBox_objectType.Name = "comboBox_objectType"; diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 1bd46108..1eacad4a 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -194,14 +194,14 @@ private int Prepare_var(ODentry od, string indexH, string varName, string group) string attr = Get_attributes(od, data.cTypeMultibyte, data.cTypeString); // data storage - string dataPtr = "NULL"; + string dataPtr = "NULL"; + ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); if (data.cValue != null) { - ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); ODStorage[group].Add($".x{varName} = {data.cValue}"); - dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; - } - + } + + dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; // objects ODObjs_t.Add($"OD_obj_var_t o_{varName};"); ODObjs.Add($" .o_{varName} = {{"); @@ -345,13 +345,13 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) Warnings.AddWarning($"Error in 0x{indexH}: Data type in RECORD, subIndex 0 must be UNSIGNED8, not {sub.datatype}!", Warnings.warning_class.WARNING_BUILD); string subcName = Make_cname(sub.parameter_name); - string dataPtr = "NULL"; + string dataPtr = "NULL"; + subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); if (data.cValue != null) { - subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); subODStorage.Add($".{subcName} = {data.cValue}"); - dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; - } + } + dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; ODObjs.Add($" {{"); ODObjs.Add($" .dataOrig = {dataPtr},"); ODObjs.Add($" .subIndex = {sub.Subindex},"); From c1212916eedb4d906589f499a5de5a03cf865561 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Thu, 27 Apr 2023 12:40:29 +0200 Subject: [PATCH 081/226] Disable comboBox_objectType listbox, because there is no code in the DataDirty event handler that handles the change of the object type. Irritating, because the value is not taken over after saving --- EDSEditorGUI/DeviceODView.Designer.cs | 304 +++++++++++--------------- 1 file changed, 123 insertions(+), 181 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index e7979dcd..d2fcea02 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -135,7 +135,6 @@ private void InitializeComponent() // this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer1.Location = new System.Drawing.Point(0, 0); - this.splitContainer1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer1.Name = "splitContainer1"; // // splitContainer1.Panel1 @@ -145,9 +144,8 @@ private void InitializeComponent() // splitContainer1.Panel2 // this.splitContainer1.Panel2.Controls.Add(this.splitContainer4); - this.splitContainer1.Size = new System.Drawing.Size(1517, 917); - this.splitContainer1.SplitterDistance = 374; - this.splitContainer1.SplitterWidth = 5; + this.splitContainer1.Size = new System.Drawing.Size(1138, 745); + this.splitContainer1.SplitterDistance = 280; this.splitContainer1.TabIndex = 2; this.splitContainer1.TabStop = false; // @@ -156,7 +154,6 @@ private void InitializeComponent() this.splitContainer2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer2.Location = new System.Drawing.Point(0, 0); - this.splitContainer2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer2.Name = "splitContainer2"; this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -167,9 +164,8 @@ private void InitializeComponent() // splitContainer2.Panel2 // this.splitContainer2.Panel2.Controls.Add(this.splitContainer3); - this.splitContainer2.Size = new System.Drawing.Size(374, 917); - this.splitContainer2.SplitterDistance = 302; - this.splitContainer2.SplitterWidth = 5; + this.splitContainer2.Size = new System.Drawing.Size(280, 745); + this.splitContainer2.SplitterDistance = 245; this.splitContainer2.TabIndex = 0; this.splitContainer2.TabStop = false; // @@ -181,12 +177,11 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; this.tableLayoutPanel1.RowCount = 2; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(372, 300); + this.tableLayoutPanel1.Size = new System.Drawing.Size(278, 243); this.tableLayoutPanel1.TabIndex = 6; // // listView_communication_objects @@ -197,10 +192,9 @@ private void InitializeComponent() this.listView_communication_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_communication_objects.FullRowSelect = true; this.listView_communication_objects.HideSelection = false; - this.listView_communication_objects.Location = new System.Drawing.Point(4, 29); - this.listView_communication_objects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.listView_communication_objects.Location = new System.Drawing.Point(3, 23); this.listView_communication_objects.Name = "listView_communication_objects"; - this.listView_communication_objects.Size = new System.Drawing.Size(364, 267); + this.listView_communication_objects.Size = new System.Drawing.Size(272, 217); this.listView_communication_objects.TabIndex = 0; this.listView_communication_objects.UseCompatibleStateImageBehavior = false; this.listView_communication_objects.View = System.Windows.Forms.View.Details; @@ -220,10 +214,9 @@ private void InitializeComponent() // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(4, 0); - this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Location = new System.Drawing.Point(3, 0); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(223, 16); + this.label1.Size = new System.Drawing.Size(176, 13); this.label1.TabIndex = 3; this.label1.Text = "Communication Specific Parameters"; // @@ -232,7 +225,6 @@ private void InitializeComponent() this.splitContainer3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer3.Location = new System.Drawing.Point(0, 0); - this.splitContainer3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer3.Name = "splitContainer3"; this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -243,9 +235,8 @@ private void InitializeComponent() // splitContainer3.Panel2 // this.splitContainer3.Panel2.Controls.Add(this.tableLayoutPanel3); - this.splitContainer3.Size = new System.Drawing.Size(374, 610); - this.splitContainer3.SplitterDistance = 301; - this.splitContainer3.SplitterWidth = 5; + this.splitContainer3.Size = new System.Drawing.Size(280, 496); + this.splitContainer3.SplitterDistance = 244; this.splitContainer3.TabIndex = 0; this.splitContainer3.TabStop = false; // @@ -257,21 +248,19 @@ private void InitializeComponent() this.tableLayoutPanel2.Controls.Add(this.listView_manufacturer_objects, 0, 1); this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tableLayoutPanel2.Name = "tableLayoutPanel2"; this.tableLayoutPanel2.RowCount = 2; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(372, 299); + this.tableLayoutPanel2.Size = new System.Drawing.Size(278, 242); this.tableLayoutPanel2.TabIndex = 7; // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(4, 0); - this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Location = new System.Drawing.Point(3, 0); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(208, 16); + this.label2.Size = new System.Drawing.Size(167, 13); this.label2.TabIndex = 4; this.label2.Text = "Manufacturer Specific Parameters"; // @@ -283,10 +272,9 @@ private void InitializeComponent() this.listView_manufacturer_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_manufacturer_objects.FullRowSelect = true; this.listView_manufacturer_objects.HideSelection = false; - this.listView_manufacturer_objects.Location = new System.Drawing.Point(4, 29); - this.listView_manufacturer_objects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.listView_manufacturer_objects.Location = new System.Drawing.Point(3, 23); this.listView_manufacturer_objects.Name = "listView_manufacturer_objects"; - this.listView_manufacturer_objects.Size = new System.Drawing.Size(364, 266); + this.listView_manufacturer_objects.Size = new System.Drawing.Size(272, 216); this.listView_manufacturer_objects.TabIndex = 0; this.listView_manufacturer_objects.UseCompatibleStateImageBehavior = false; this.listView_manufacturer_objects.View = System.Windows.Forms.View.Details; @@ -311,21 +299,19 @@ private void InitializeComponent() this.tableLayoutPanel3.Controls.Add(this.listView_deviceProfile_objects, 0, 1); this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tableLayoutPanel3.Name = "tableLayoutPanel3"; this.tableLayoutPanel3.RowCount = 2; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 25F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(372, 302); + this.tableLayoutPanel3.Size = new System.Drawing.Size(278, 246); this.tableLayoutPanel3.TabIndex = 8; // // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(4, 0); - this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Location = new System.Drawing.Point(3, 0); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(215, 16); + this.label3.Size = new System.Drawing.Size(170, 13); this.label3.TabIndex = 5; this.label3.Text = "Device Profile Specific Parameters"; // @@ -337,10 +323,9 @@ private void InitializeComponent() this.listView_deviceProfile_objects.Dock = System.Windows.Forms.DockStyle.Fill; this.listView_deviceProfile_objects.FullRowSelect = true; this.listView_deviceProfile_objects.HideSelection = false; - this.listView_deviceProfile_objects.Location = new System.Drawing.Point(4, 29); - this.listView_deviceProfile_objects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.listView_deviceProfile_objects.Location = new System.Drawing.Point(3, 23); this.listView_deviceProfile_objects.Name = "listView_deviceProfile_objects"; - this.listView_deviceProfile_objects.Size = new System.Drawing.Size(364, 269); + this.listView_deviceProfile_objects.Size = new System.Drawing.Size(272, 220); this.listView_deviceProfile_objects.TabIndex = 0; this.listView_deviceProfile_objects.UseCompatibleStateImageBehavior = false; this.listView_deviceProfile_objects.View = System.Windows.Forms.View.Details; @@ -361,7 +346,6 @@ private void InitializeComponent() // this.splitContainer4.Dock = System.Windows.Forms.DockStyle.Fill; this.splitContainer4.Location = new System.Drawing.Point(0, 0); - this.splitContainer4.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.splitContainer4.Name = "splitContainer4"; this.splitContainer4.Orientation = System.Windows.Forms.Orientation.Horizontal; // @@ -382,9 +366,8 @@ private void InitializeComponent() this.splitContainer4.Panel2.Controls.Add(this.label6); this.splitContainer4.Panel2.Controls.Add(this.textBox_name); this.splitContainer4.Panel2.Controls.Add(this.textBox_description); - this.splitContainer4.Size = new System.Drawing.Size(1138, 917); - this.splitContainer4.SplitterDistance = 276; - this.splitContainer4.SplitterWidth = 5; + this.splitContainer4.Size = new System.Drawing.Size(854, 745); + this.splitContainer4.SplitterDistance = 224; this.splitContainer4.TabIndex = 28; this.splitContainer4.TabStop = false; // @@ -405,9 +388,8 @@ private void InitializeComponent() this.listView_subObjects.FullRowSelect = true; this.listView_subObjects.HideSelection = false; this.listView_subObjects.Location = new System.Drawing.Point(0, 0); - this.listView_subObjects.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.listView_subObjects.Name = "listView_subObjects"; - this.listView_subObjects.Size = new System.Drawing.Size(1133, 273); + this.listView_subObjects.Size = new System.Drawing.Size(851, 223); this.listView_subObjects.TabIndex = 0; this.listView_subObjects.UseCompatibleStateImageBehavior = false; this.listView_subObjects.View = System.Windows.Forms.View.Details; @@ -456,31 +438,28 @@ private void InitializeComponent() // // textBox_subIndex // - this.textBox_subIndex.Location = new System.Drawing.Point(347, 10); - this.textBox_subIndex.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_subIndex.Location = new System.Drawing.Point(260, 8); this.textBox_subIndex.Name = "textBox_subIndex"; this.textBox_subIndex.ReadOnly = true; - this.textBox_subIndex.Size = new System.Drawing.Size(132, 22); + this.textBox_subIndex.Size = new System.Drawing.Size(100, 20); this.textBox_subIndex.TabIndex = 0; this.textBox_subIndex.TabStop = false; // // label23 // this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(265, 14); - this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label23.Location = new System.Drawing.Point(199, 11); this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(66, 16); + this.label23.Size = new System.Drawing.Size(55, 13); this.label23.TabIndex = 34; this.label23.Text = "Sub Index"; // // textBox_index // - this.textBox_index.Location = new System.Drawing.Point(120, 10); - this.textBox_index.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_index.Location = new System.Drawing.Point(90, 8); this.textBox_index.Name = "textBox_index"; this.textBox_index.ReadOnly = true; - this.textBox_index.Size = new System.Drawing.Size(132, 22); + this.textBox_index.Size = new System.Drawing.Size(100, 20); this.textBox_index.TabIndex = 0; this.textBox_index.TabStop = false; // @@ -517,51 +496,47 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.label11); this.groupBox1.Controls.Add(this.comboBox_accessPDO); this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; - this.groupBox1.Location = new System.Drawing.Point(0, 405); - this.groupBox1.Margin = new System.Windows.Forms.Padding(3, 2, 3, 2); + this.groupBox1.Location = new System.Drawing.Point(0, 329); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(3, 2, 3, 2); - this.groupBox1.Size = new System.Drawing.Size(1138, 231); + this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Size = new System.Drawing.Size(854, 188); this.groupBox1.TabIndex = 33; this.groupBox1.TabStop = false; this.groupBox1.Text = "Object settings"; // // checkBox_autosave // - this.checkBox_autosave.Location = new System.Drawing.Point(936, 182); - this.checkBox_autosave.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.checkBox_autosave.Location = new System.Drawing.Point(702, 148); this.checkBox_autosave.Name = "checkBox_autosave"; - this.checkBox_autosave.Size = new System.Drawing.Size(185, 21); + this.checkBox_autosave.Size = new System.Drawing.Size(139, 17); this.checkBox_autosave.TabIndex = 35; this.checkBox_autosave.Text = "Autosave changes"; this.checkBox_autosave.UseVisualStyleBackColor = true; // // textBox_stringLengthMin // - this.textBox_stringLengthMin.Location = new System.Drawing.Point(453, 122); - this.textBox_stringLengthMin.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_stringLengthMin.Location = new System.Drawing.Point(340, 99); this.textBox_stringLengthMin.Name = "textBox_stringLengthMin"; - this.textBox_stringLengthMin.Size = new System.Drawing.Size(161, 22); + this.textBox_stringLengthMin.Size = new System.Drawing.Size(122, 20); this.textBox_stringLengthMin.TabIndex = 24; this.textBox_stringLengthMin.TextChanged += new System.EventHandler(this.DataDirty); // // label22 // this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(331, 126); - this.label22.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label22.Location = new System.Drawing.Point(248, 102); this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(90, 16); + this.label22.Size = new System.Drawing.Size(75, 13); this.label22.TabIndex = 39; this.label22.Text = "String Len Min"; // // label20 // this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(643, 26); - this.label20.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label20.Location = new System.Drawing.Point(482, 21); this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(78, 16); + this.label20.Size = new System.Drawing.Size(64, 13); this.label20.TabIndex = 36; this.label20.Text = "Count Label"; // @@ -569,20 +544,18 @@ private void InitializeComponent() // this.comboBox_countLabel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_countLabel.FormattingEnabled = true; - this.comboBox_countLabel.Location = new System.Drawing.Point(765, 22); - this.comboBox_countLabel.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.comboBox_countLabel.Location = new System.Drawing.Point(574, 18); this.comboBox_countLabel.Name = "comboBox_countLabel"; - this.comboBox_countLabel.Size = new System.Drawing.Size(161, 24); + this.comboBox_countLabel.Size = new System.Drawing.Size(122, 21); this.comboBox_countLabel.TabIndex = 30; this.comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label19 // this.label19.AutoSize = true; - this.label19.Location = new System.Drawing.Point(17, 159); - this.label19.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label19.Location = new System.Drawing.Point(13, 129); this.label19.Name = "label19"; - this.label19.Size = new System.Drawing.Size(94, 16); + this.label19.Size = new System.Drawing.Size(76, 13); this.label19.TabIndex = 34; this.label19.Text = "Access SRDO"; // @@ -590,68 +563,61 @@ private void InitializeComponent() // this.comboBox_accessSRDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSRDO.FormattingEnabled = true; - this.comboBox_accessSRDO.Location = new System.Drawing.Point(144, 155); - this.comboBox_accessSRDO.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.comboBox_accessSRDO.Location = new System.Drawing.Point(108, 126); this.comboBox_accessSRDO.Name = "comboBox_accessSRDO"; - this.comboBox_accessSRDO.Size = new System.Drawing.Size(161, 24); + this.comboBox_accessSRDO.Size = new System.Drawing.Size(122, 21); this.comboBox_accessSRDO.TabIndex = 14; this.comboBox_accessSRDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_actualValue // this.textBox_actualValue.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_actualValue.Location = new System.Drawing.Point(453, 89); - this.textBox_actualValue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_actualValue.Location = new System.Drawing.Point(340, 72); this.textBox_actualValue.Name = "textBox_actualValue"; - this.textBox_actualValue.Size = new System.Drawing.Size(161, 22); + this.textBox_actualValue.Size = new System.Drawing.Size(122, 20); this.textBox_actualValue.TabIndex = 23; this.textBox_actualValue.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_lowLimit // - this.textBox_lowLimit.Location = new System.Drawing.Point(453, 55); - this.textBox_lowLimit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_lowLimit.Location = new System.Drawing.Point(340, 45); this.textBox_lowLimit.Name = "textBox_lowLimit"; - this.textBox_lowLimit.Size = new System.Drawing.Size(161, 22); + this.textBox_lowLimit.Size = new System.Drawing.Size(122, 20); this.textBox_lowLimit.TabIndex = 22; this.textBox_lowLimit.TextChanged += new System.EventHandler(this.DataDirty); // // textBox_highLimit // - this.textBox_highLimit.Location = new System.Drawing.Point(453, 22); - this.textBox_highLimit.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_highLimit.Location = new System.Drawing.Point(340, 18); this.textBox_highLimit.Name = "textBox_highLimit"; - this.textBox_highLimit.Size = new System.Drawing.Size(161, 22); + this.textBox_highLimit.Size = new System.Drawing.Size(122, 20); this.textBox_highLimit.TabIndex = 21; this.textBox_highLimit.TextChanged += new System.EventHandler(this.DataDirty); // // label18 // this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(331, 92); - this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label18.Location = new System.Drawing.Point(248, 75); this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(82, 16); + this.label18.Size = new System.Drawing.Size(67, 13); this.label18.TabIndex = 32; this.label18.Text = "Actual Value"; // // label17 // this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(331, 59); - this.label17.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label17.Location = new System.Drawing.Point(248, 48); this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(58, 16); + this.label17.Size = new System.Drawing.Size(48, 13); this.label17.TabIndex = 31; this.label17.Text = "LowLimit"; // // label14 // this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(331, 26); - this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label14.Location = new System.Drawing.Point(248, 21); this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(62, 16); + this.label14.Size = new System.Drawing.Size(50, 13); this.label14.TabIndex = 30; this.label14.Text = "HighLimit"; // @@ -659,10 +625,9 @@ private void InitializeComponent() // this.button_saveChanges.Image = global::ODEditor.Properties.Resources.Save_6530; this.button_saveChanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_saveChanges.Location = new System.Drawing.Point(647, 170); - this.button_saveChanges.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.button_saveChanges.Location = new System.Drawing.Point(485, 138); this.button_saveChanges.Name = "button_saveChanges"; - this.button_saveChanges.Size = new System.Drawing.Size(281, 43); + this.button_saveChanges.Size = new System.Drawing.Size(211, 35); this.button_saveChanges.TabIndex = 50; this.button_saveChanges.Text = "Save Changes"; this.button_saveChanges.UseVisualStyleBackColor = true; @@ -671,10 +636,9 @@ private void InitializeComponent() // label16 // this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(643, 59); - this.label16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label16.Location = new System.Drawing.Point(482, 48); this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(95, 16); + this.label16.Size = new System.Drawing.Size(76, 13); this.label16.TabIndex = 26; this.label16.Text = "Storage Group"; // @@ -682,30 +646,27 @@ private void InitializeComponent() // this.comboBox_storageGroup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_storageGroup.FormattingEnabled = true; - this.comboBox_storageGroup.Location = new System.Drawing.Point(765, 55); - this.comboBox_storageGroup.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.comboBox_storageGroup.Location = new System.Drawing.Point(574, 45); this.comboBox_storageGroup.Name = "comboBox_storageGroup"; - this.comboBox_storageGroup.Size = new System.Drawing.Size(161, 24); + this.comboBox_storageGroup.Size = new System.Drawing.Size(122, 21); this.comboBox_storageGroup.TabIndex = 31; this.comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label15 // this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(643, 89); - this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label15.Location = new System.Drawing.Point(482, 72); this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(58, 16); + this.label15.Size = new System.Drawing.Size(46, 13); this.label15.TabIndex = 24; this.label15.Text = "Enabled"; // // checkBox_enabled // this.checkBox_enabled.AutoSize = true; - this.checkBox_enabled.Location = new System.Drawing.Point(765, 89); - this.checkBox_enabled.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.checkBox_enabled.Location = new System.Drawing.Point(574, 72); this.checkBox_enabled.Name = "checkBox_enabled"; - this.checkBox_enabled.Size = new System.Drawing.Size(18, 17); + this.checkBox_enabled.Size = new System.Drawing.Size(15, 14); this.checkBox_enabled.TabIndex = 32; this.checkBox_enabled.UseVisualStyleBackColor = true; this.checkBox_enabled.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -713,31 +674,29 @@ private void InitializeComponent() // label7 // this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(17, 26); - this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Location = new System.Drawing.Point(13, 21); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(81, 16); + this.label7.Size = new System.Drawing.Size(65, 13); this.label7.TabIndex = 7; this.label7.Text = "Object Type"; // // comboBox_objectType // this.comboBox_objectType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_objectType.Enabled = false; this.comboBox_objectType.FormattingEnabled = true; - this.comboBox_objectType.Location = new System.Drawing.Point(144, 22); - this.comboBox_objectType.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.comboBox_objectType.Location = new System.Drawing.Point(108, 18); this.comboBox_objectType.Name = "comboBox_objectType"; - this.comboBox_objectType.Size = new System.Drawing.Size(161, 24); + this.comboBox_objectType.Size = new System.Drawing.Size(122, 21); this.comboBox_objectType.TabIndex = 10; this.comboBox_objectType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label8 // this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(17, 59); - this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Location = new System.Drawing.Point(13, 48); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(71, 16); + this.label8.Size = new System.Drawing.Size(57, 13); this.label8.TabIndex = 9; this.label8.Text = "Data Type"; // @@ -745,40 +704,36 @@ private void InitializeComponent() // this.comboBox_dataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_dataType.FormattingEnabled = true; - this.comboBox_dataType.Location = new System.Drawing.Point(144, 55); - this.comboBox_dataType.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.comboBox_dataType.Location = new System.Drawing.Point(108, 45); this.comboBox_dataType.Name = "comboBox_dataType"; - this.comboBox_dataType.Size = new System.Drawing.Size(161, 24); + this.comboBox_dataType.Size = new System.Drawing.Size(122, 21); this.comboBox_dataType.TabIndex = 11; this.comboBox_dataType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // label_pdoFlags // this.label_pdoFlags.AutoSize = true; - this.label_pdoFlags.Location = new System.Drawing.Point(643, 113); - this.label_pdoFlags.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label_pdoFlags.Location = new System.Drawing.Point(482, 92); this.label_pdoFlags.Name = "label_pdoFlags"; - this.label_pdoFlags.Size = new System.Drawing.Size(76, 16); + this.label_pdoFlags.Size = new System.Drawing.Size(62, 13); this.label_pdoFlags.TabIndex = 18; this.label_pdoFlags.Text = "TPDO COS"; // // label9 // this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(17, 92); - this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Location = new System.Drawing.Point(13, 75); this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(84, 16); + this.label9.Size = new System.Drawing.Size(68, 13); this.label9.TabIndex = 11; this.label9.Text = "Access SDO"; // // checkBox_pdoFlags // this.checkBox_pdoFlags.AutoSize = true; - this.checkBox_pdoFlags.Location = new System.Drawing.Point(765, 113); - this.checkBox_pdoFlags.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.checkBox_pdoFlags.Location = new System.Drawing.Point(574, 92); this.checkBox_pdoFlags.Name = "checkBox_pdoFlags"; - this.checkBox_pdoFlags.Size = new System.Drawing.Size(18, 17); + this.checkBox_pdoFlags.Size = new System.Drawing.Size(15, 14); this.checkBox_pdoFlags.TabIndex = 34; this.checkBox_pdoFlags.UseVisualStyleBackColor = true; this.checkBox_pdoFlags.CheckedChanged += new System.EventHandler(this.DataDirty); @@ -787,39 +742,35 @@ private void InitializeComponent() // this.comboBox_accessSDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessSDO.FormattingEnabled = true; - this.comboBox_accessSDO.Location = new System.Drawing.Point(144, 89); - this.comboBox_accessSDO.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.comboBox_accessSDO.Location = new System.Drawing.Point(108, 72); this.comboBox_accessSDO.Name = "comboBox_accessSDO"; - this.comboBox_accessSDO.Size = new System.Drawing.Size(161, 24); + this.comboBox_accessSDO.Size = new System.Drawing.Size(122, 21); this.comboBox_accessSDO.TabIndex = 12; this.comboBox_accessSDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // // textBox_defaultValue // - this.textBox_defaultValue.Location = new System.Drawing.Point(144, 188); - this.textBox_defaultValue.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_defaultValue.Location = new System.Drawing.Point(108, 153); this.textBox_defaultValue.Name = "textBox_defaultValue"; - this.textBox_defaultValue.Size = new System.Drawing.Size(471, 22); + this.textBox_defaultValue.Size = new System.Drawing.Size(354, 20); this.textBox_defaultValue.TabIndex = 20; this.textBox_defaultValue.TextChanged += new System.EventHandler(this.DataDirty); // // label10 // this.label10.AutoSize = true; - this.label10.Location = new System.Drawing.Point(17, 126); - this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label10.Location = new System.Drawing.Point(13, 102); this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(84, 16); + this.label10.Size = new System.Drawing.Size(68, 13); this.label10.TabIndex = 13; this.label10.Text = "Access PDO"; // // label11 // this.label11.AutoSize = true; - this.label11.Location = new System.Drawing.Point(17, 192); - this.label11.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label11.Location = new System.Drawing.Point(13, 156); this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(85, 16); + this.label11.Size = new System.Drawing.Size(70, 13); this.label11.TabIndex = 15; this.label11.Text = "Default value"; // @@ -827,10 +778,9 @@ private void InitializeComponent() // this.comboBox_accessPDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; this.comboBox_accessPDO.FormattingEnabled = true; - this.comboBox_accessPDO.Location = new System.Drawing.Point(144, 122); - this.comboBox_accessPDO.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.comboBox_accessPDO.Location = new System.Drawing.Point(108, 99); this.comboBox_accessPDO.Name = "comboBox_accessPDO"; - this.comboBox_accessPDO.Size = new System.Drawing.Size(161, 24); + this.comboBox_accessPDO.Size = new System.Drawing.Size(122, 21); this.comboBox_accessPDO.TabIndex = 13; this.comboBox_accessPDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); // @@ -839,50 +789,45 @@ private void InitializeComponent() this.textBox_denotation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_denotation.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_denotation.Location = new System.Drawing.Point(120, 74); - this.textBox_denotation.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_denotation.Location = new System.Drawing.Point(90, 60); this.textBox_denotation.Name = "textBox_denotation"; - this.textBox_denotation.Size = new System.Drawing.Size(1013, 22); + this.textBox_denotation.Size = new System.Drawing.Size(761, 20); this.textBox_denotation.TabIndex = 3; this.textBox_denotation.TextChanged += new System.EventHandler(this.DataDirty); // // label13 // this.label13.AutoSize = true; - this.label13.Location = new System.Drawing.Point(17, 78); - this.label13.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label13.Location = new System.Drawing.Point(13, 63); this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(72, 16); + this.label13.Size = new System.Drawing.Size(59, 13); this.label13.TabIndex = 28; this.label13.Text = "Denotation"; // // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(17, 14); - this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Location = new System.Drawing.Point(13, 11); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(39, 16); + this.label4.Size = new System.Drawing.Size(33, 13); this.label4.TabIndex = 1; this.label4.Text = "Index"; // // label5 // this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(17, 46); - this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Location = new System.Drawing.Point(13, 37); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(44, 16); + this.label5.Size = new System.Drawing.Size(35, 13); this.label5.TabIndex = 2; this.label5.Text = "Name"; // // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(17, 110); - this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Location = new System.Drawing.Point(13, 89); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(75, 16); + this.label6.Size = new System.Drawing.Size(60, 13); this.label6.TabIndex = 3; this.label6.Text = "Description"; // @@ -890,10 +835,9 @@ private void InitializeComponent() // this.textBox_name.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_name.Location = new System.Drawing.Point(120, 42); - this.textBox_name.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_name.Location = new System.Drawing.Point(90, 34); this.textBox_name.Name = "textBox_name"; - this.textBox_name.Size = new System.Drawing.Size(1013, 22); + this.textBox_name.Size = new System.Drawing.Size(761, 20); this.textBox_name.TabIndex = 2; this.textBox_name.TextChanged += new System.EventHandler(this.DataDirty); // @@ -905,12 +849,11 @@ private void InitializeComponent() | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); this.textBox_description.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBox_description.Location = new System.Drawing.Point(120, 106); - this.textBox_description.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.textBox_description.Location = new System.Drawing.Point(90, 86); this.textBox_description.Multiline = true; this.textBox_description.Name = "textBox_description"; this.textBox_description.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBox_description.Size = new System.Drawing.Size(1013, 279); + this.textBox_description.Size = new System.Drawing.Size(761, 227); this.textBox_description.TabIndex = 4; this.textBox_description.TextChanged += new System.EventHandler(this.DataDirty); // @@ -923,12 +866,12 @@ private void InitializeComponent() this.contextMenu_object_deleteObjectToolStripMenuItem, this.contextMenu_object_toggleObjectToolStripMenuItem}); this.contextMenu_object.Name = "contextMenuStrip1"; - this.contextMenu_object.Size = new System.Drawing.Size(136, 108); + this.contextMenu_object.Size = new System.Drawing.Size(121, 108); // // contextMenu_object_addNewObjectToolStripMenuItem // this.contextMenu_object_addNewObjectToolStripMenuItem.Name = "contextMenu_object_addNewObjectToolStripMenuItem"; - this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.contextMenu_object_addNewObjectToolStripMenuItem.Text = "&Clone..."; this.contextMenu_object_addNewObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_clone_ToolStripMenuItem_Click); // @@ -936,7 +879,7 @@ private void InitializeComponent() // this.addToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.addToolStripMenuItem.Name = "addToolStripMenuItem"; - this.addToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.addToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.addToolStripMenuItem.Text = "Add..."; this.addToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_add_ToolStripMenuItem_Click); // @@ -944,14 +887,14 @@ private void InitializeComponent() // this.contextMenu_object_deleteObjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_object_deleteObjectToolStripMenuItem.Name = "contextMenu_object_deleteObjectToolStripMenuItem"; - this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.contextMenu_object_deleteObjectToolStripMenuItem.Text = "&Delete..."; this.contextMenu_object_deleteObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_delete_ToolStripMenuItem_Click); // // contextMenu_object_toggleObjectToolStripMenuItem // this.contextMenu_object_toggleObjectToolStripMenuItem.Name = "contextMenu_object_toggleObjectToolStripMenuItem"; - this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(135, 26); + this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); this.contextMenu_object_toggleObjectToolStripMenuItem.Text = "&Toggle"; this.contextMenu_object_toggleObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_toggle_ToolStripMenuItem_Click); // @@ -963,13 +906,13 @@ private void InitializeComponent() this.contextMenu_subObject_removeSubItemToolStripMenuItem, this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem}); this.contextMenu_subObject.Name = "contextMenu_array"; - this.contextMenu_subObject.Size = new System.Drawing.Size(216, 82); + this.contextMenu_subObject.Size = new System.Drawing.Size(183, 82); // // contextMenu_subObject_addSubItemToolStripMenuItem // this.contextMenu_subObject_addSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; this.contextMenu_subObject_addSubItemToolStripMenuItem.Name = "contextMenu_subObject_addSubItemToolStripMenuItem"; - this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); + this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); this.contextMenu_subObject_addSubItemToolStripMenuItem.Text = "Add"; this.contextMenu_subObject_addSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_add_ToolStripMenuItem_Click); // @@ -977,7 +920,7 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(215, 26); + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); this.contextMenu_subObject_removeSubItemToolStripMenuItem.Text = "Remove (shift up)"; this.contextMenu_subObject_removeSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // @@ -985,18 +928,17 @@ private void InitializeComponent() // this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(215, 26); + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(182, 26); this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Text = "Remove (leave gap)"; this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); // // DeviceODView // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.splitContainer1); - this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "DeviceODView"; - this.Size = new System.Drawing.Size(1517, 917); + this.Size = new System.Drawing.Size(1138, 745); this.splitContainer1.Panel1.ResumeLayout(false); this.splitContainer1.Panel2.ResumeLayout(false); ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); From 0522d6af087cf7e89be4f920ef113d6f8eacbb40 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Fri, 12 May 2023 16:29:56 +0200 Subject: [PATCH 082/226] Update CanOpenNodeExporter.cs --- libEDSsharp/CanOpenNodeExporter.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 350aad34..a4a4a2c8 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -394,7 +394,7 @@ protected string print_h_entry(ODentry od) specialarraylength = string.Format("[{0}]", maxlength); } - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}{specialarraylength}[{od.Nosubindexes - 1}];"); + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{od.Nosubindexes - 1}]{specialarraylength};"); } } } From 643471c9a03340ae50ea0425dac87d5b3c21bf63 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 15 May 2023 12:24:46 +0200 Subject: [PATCH 083/226] bugfix for #57 TOUPPER to fetch different case of "NODeID" (allowed acording DS301) --- libEDSsharp/CanOpenNodeExporter_V4.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 1eacad4a..3d82e577 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -735,7 +735,7 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue valueDefined = false; else if (dataType != DataType.VISIBLE_STRING && dataType != DataType.UNICODE_STRING && dataType != DataType.OCTET_STRING) { - defaultvalue = defaultvalue.Trim(); + defaultvalue = defaultvalue.Trim().ToUpper(); // TOUPPER to fetch different case of "NODeID" (allowed acording DS301) if (defaultvalue.Contains("$NODEID")) { From e956b1709424f51c44d284a97420b56999c21d82 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 15 May 2023 14:21:36 +0200 Subject: [PATCH 084/226] bugfix #57 --- libEDSsharp/CanOpenNodeExporter.cs | 4 ++-- libEDSsharp/CanOpenNodeExporter_V4.cs | 6 +++--- libEDSsharp/extensions.cs | 16 ++++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 350aad34..259f419a 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -1166,9 +1166,9 @@ string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring= defaultvalue = "0"; } - if (defaultvalue.Contains("$NODEID")) + if (defaultvalue.Contains("$NODEID", StringComparison.OrdinalIgnoreCase)) // fetch different case of "NODeID" (allowed according DS301) { - defaultvalue = defaultvalue.Replace("$NODEID", ""); + defaultvalue = defaultvalue.ToUpper().Replace("$NODEID", ""); defaultvalue = defaultvalue.Replace("+", ""); defaultvalue = defaultvalue.Trim(); nodeidreplace = true; diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 3d82e577..366b8a1d 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -735,11 +735,11 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue valueDefined = false; else if (dataType != DataType.VISIBLE_STRING && dataType != DataType.UNICODE_STRING && dataType != DataType.OCTET_STRING) { - defaultvalue = defaultvalue.Trim().ToUpper(); // TOUPPER to fetch different case of "NODeID" (allowed acording DS301) + defaultvalue = defaultvalue.Trim(); - if (defaultvalue.Contains("$NODEID")) + if (defaultvalue.Contains("$NODEID",StringComparison.OrdinalIgnoreCase)) // fetch different case of "NODeID" (allowed according DS301) { - defaultvalue = defaultvalue.Replace("$NODEID", ""); + defaultvalue = defaultvalue.ToUpper().Replace("$NODEID", ""); defaultvalue = defaultvalue.Replace("+", ""); defaultvalue = defaultvalue.Trim(); if (defaultvalue == "") diff --git a/libEDSsharp/extensions.cs b/libEDSsharp/extensions.cs index 0dd1c46c..6619e303 100644 --- a/libEDSsharp/extensions.cs +++ b/libEDSsharp/extensions.cs @@ -24,4 +24,20 @@ public static string ToHexString(this UInt32 val) } } + + public static class StringExtensions + { + public static bool Contains(this String str, String substring, + StringComparison comp) + { + if (substring == null) + throw new ArgumentNullException("substring", + "substring cannot be null."); + else if (!Enum.IsDefined(typeof(StringComparison), comp)) + throw new ArgumentException("comp is not a member of StringComparison", + "comp"); + + return str.IndexOf(substring, comp) >= 0; + } + } } From eb1a6f16b90ea3cf4bb7da7f8b0c934764338aa9 Mon Sep 17 00:00:00 2001 From: Michael Menzi Date: Tue, 23 May 2023 09:53:22 +0200 Subject: [PATCH 085/226] Inserting into chosen target works. DeviceODView has to be notified to update its view. --- EDSEditorGUI/DeviceODView.cs | 1281 ++++++------ EDSEditorGUI/DeviceView.Designer.cs | 70 +- EDSEditorGUI/DeviceView.cs | 7 +- EDSEditorGUI/Form1.cs | 2604 ++++++++++++------------ EDSEditorGUI/InsertObjects.Designer.cs | 116 +- EDSEditorGUI/InsertObjects.cs | 484 +++-- 6 files changed, 2314 insertions(+), 2248 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index dc0453a5..8c8f94b4 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -1,47 +1,48 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius - Copyright(c) 2020 Janez Paternoster -*/ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; -using System.Reflection; -using System.Text.RegularExpressions; +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius + Copyright(c) 2020 Janez Paternoster +*/ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using System.Reflection; +using System.Text.RegularExpressions; using libEDSsharp; -namespace ODEditor -{ - - public partial class DeviceODView : MyTabUserControl - { - EDSsharp eds = null; - - ODentry selectedObject; - ODentry lastSelectedObject; - ListView selectedList; +namespace ODEditor +{ + + public partial class DeviceODView : MyTabUserControl + { + EDSsharp eds = null; + public List network; + + ODentry selectedObject; + ODentry lastSelectedObject; + ListView selectedList; bool justUpdating = false; bool ExporterOld = false; bool ExporterV4 = false; - public DeviceODView() - { - + public DeviceODView() + { + InitializeComponent(); RebuildControls(); @@ -126,322 +127,322 @@ private bool ExporterTypeV4() { return (type == ExporterFactory.Exporter.CANOPENNODE_V4); } - private bool Checkdirty() - { - if (button_saveChanges.BackColor == Color.Red) - { - if (lastSelectedObject != null && MessageBox.Show(String.Format("Unsaved changes on Index 0x{0:X4}/{1:X2}.\nDo you wish to switch object and loose your changes?", lastSelectedObject.Index, lastSelectedObject.Subindex), "Unsaved changes", MessageBoxButtons.YesNo) == DialogResult.No) - { - return true; - } - button_saveChanges.BackColor = default; - } - - return false; - } - - private void ComboBoxSet(ComboBox comboBox, string item) - { - if (item == null) - item = ""; - - if (!comboBox.Items.Contains(item)) - comboBox.Items.Add(item); - - comboBox.SelectedItem = item; - } - - public void PopulateObjectLists(EDSsharp eds_target) - { - if (eds_target == null) - return; - - eds = eds_target; - eds.UpdatePDOcount(); - doUpdateDeviceInfo(); - doUpdatePDOs(); - - /* save scroll positions */ - int listview_communication_position = 0; - int listview_manufacturer_position = 0; - int listview_deviceProfile_position = 0; - - if (listView_communication_objects.TopItem != null) - listview_communication_position = listView_communication_objects.TopItem.Index; - if (listView_manufacturer_objects.TopItem != null) - listview_manufacturer_position = listView_manufacturer_objects.TopItem.Index; - if (listView_deviceProfile_objects.TopItem != null) - listview_deviceProfile_position = listView_deviceProfile_objects.TopItem.Index; - - /* prevent flickering */ - listView_communication_objects.BeginUpdate(); - listView_manufacturer_objects.BeginUpdate(); - listView_deviceProfile_objects.BeginUpdate(); - - listView_communication_objects.Items.Clear(); - listView_manufacturer_objects.Items.Clear(); - listView_deviceProfile_objects.Items.Clear(); - - foreach (ODentry od in eds.ods.Values) - { - UInt16 index = od.Index; - ListViewItem lvi = new ListViewItem(new string[] { - string.Format("0x{0:X4}", index), - od.parameter_name - }); - - lvi.Tag = od; - if (selectedObject != null && index == selectedObject.Index) - lvi.Selected = true; - if (od.prop.CO_disabled == true) - lvi.ForeColor = Color.LightGray; - - if (index <= 0x1000 || index < 0x2000) - listView_communication_objects.Items.Add(lvi); - else if (index >= 0x2000 && index < 0x6000) - listView_manufacturer_objects.Items.Add(lvi); - else - listView_deviceProfile_objects.Items.Add(lvi); - - string countLabel = od.prop.CO_countLabel; - if (!comboBox_countLabel.Items.Contains(countLabel)) - comboBox_countLabel.Items.Insert(comboBox_countLabel.Items.Count - 1, countLabel); - - string storageGroup = od.prop.CO_storageGroup; - if (!comboBox_storageGroup.Items.Contains(storageGroup)) - comboBox_storageGroup.Items.Insert(comboBox_storageGroup.Items.Count - 1, storageGroup); - } - - listView_communication_objects.EndUpdate(); - listView_manufacturer_objects.EndUpdate(); - listView_deviceProfile_objects.EndUpdate(); - - /* reset scroll position and selection */ - if (listview_communication_position != 0 && listView_communication_objects.Items.Count > 0) - listView_communication_objects.TopItem = listView_communication_objects.Items[listview_communication_position]; - if (listview_manufacturer_position != 0 && listView_manufacturer_objects.Items.Count > 0) - listView_manufacturer_objects.TopItem = listView_manufacturer_objects.Items[listview_manufacturer_position]; - if (listview_deviceProfile_position != 0 && listView_deviceProfile_objects.Items.Count > 0) - listView_deviceProfile_objects.TopItem = listView_deviceProfile_objects.Items[listview_deviceProfile_position]; - } - - public void PopulateSubList() - { - listView_subObjects.Items.Clear(); - - if (selectedObject == null) + private bool Checkdirty() + { + if (button_saveChanges.BackColor == Color.Red) + { + if (lastSelectedObject != null && MessageBox.Show(String.Format("Unsaved changes on Index 0x{0:X4}/{1:X2}.\nDo you wish to switch object and loose your changes?", lastSelectedObject.Index, lastSelectedObject.Subindex), "Unsaved changes", MessageBoxButtons.YesNo) == DialogResult.No) + { + return true; + } + button_saveChanges.BackColor = default; + } + + return false; + } + + private void ComboBoxSet(ComboBox comboBox, string item) + { + if (item == null) + item = ""; + + if (!comboBox.Items.Contains(item)) + comboBox.Items.Add(item); + + comboBox.SelectedItem = item; + } + + public void PopulateObjectLists(EDSsharp eds_target) + { + if (eds_target == null) return; - ODentry od = selectedObject.parent ?? selectedObject; - - if (od.objecttype == ObjectType.VAR) - { - ListViewItem lvi = new ListViewItem(new string[] { - " ", // subindex - od.parameter_name, - od.ObjectTypeString(), - od.datatype.ToString(), - od.AccessSDO().ToString(), - od.AccessPDO().ToString(), - od.prop.CO_accessSRDO.ToString(), - od.defaultvalue - }); - lvi.Tag = od; - listView_subObjects.Items.Add(lvi); - } - else if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) - { - ListViewItem lvi = new ListViewItem(new string[]{ - " ", - od.parameter_name, - od.ObjectTypeString() - }); - lvi.Tag = od; - listView_subObjects.Items.Add(lvi); - - foreach (KeyValuePair kvp in od.subobjects) - { - ODentry subod = kvp.Value; - int subindex = kvp.Key; - - ListViewItem lvi2 = new ListViewItem(new string[] { - string.Format("0x{0:X2}", subindex), - subod.parameter_name, - subod.ObjectTypeString(), - (subod.datatype != DataType.UNKNOWN) ? subod.datatype.ToString() : od.datatype.ToString(), - subod.AccessSDO().ToString(), - subod.AccessPDO().ToString(), - subod.prop.CO_accessSRDO.ToString(), - subod.defaultvalue - }); - lvi2.Tag = subod; - listView_subObjects.Items.Add(lvi2); - } - } - } - - public void PopulateObject() - { - - ExporterV4 = ExporterTypeV4(); + + eds = eds_target; + eds.UpdatePDOcount(); + doUpdateDeviceInfo(); + doUpdatePDOs(); + + /* save scroll positions */ + int listview_communication_position = 0; + int listview_manufacturer_position = 0; + int listview_deviceProfile_position = 0; + + if (listView_communication_objects.TopItem != null) + listview_communication_position = listView_communication_objects.TopItem.Index; + if (listView_manufacturer_objects.TopItem != null) + listview_manufacturer_position = listView_manufacturer_objects.TopItem.Index; + if (listView_deviceProfile_objects.TopItem != null) + listview_deviceProfile_position = listView_deviceProfile_objects.TopItem.Index; + + /* prevent flickering */ + listView_communication_objects.BeginUpdate(); + listView_manufacturer_objects.BeginUpdate(); + listView_deviceProfile_objects.BeginUpdate(); + + listView_communication_objects.Items.Clear(); + listView_manufacturer_objects.Items.Clear(); + listView_deviceProfile_objects.Items.Clear(); + + foreach (ODentry od in eds.ods.Values) + { + UInt16 index = od.Index; + ListViewItem lvi = new ListViewItem(new string[] { + string.Format("0x{0:X4}", index), + od.parameter_name + }); + + lvi.Tag = od; + if (selectedObject != null && index == selectedObject.Index) + lvi.Selected = true; + if (od.prop.CO_disabled == true) + lvi.ForeColor = Color.LightGray; + + if (index <= 0x1000 || index < 0x2000) + listView_communication_objects.Items.Add(lvi); + else if (index >= 0x2000 && index < 0x6000) + listView_manufacturer_objects.Items.Add(lvi); + else + listView_deviceProfile_objects.Items.Add(lvi); + + string countLabel = od.prop.CO_countLabel; + if (!comboBox_countLabel.Items.Contains(countLabel)) + comboBox_countLabel.Items.Insert(comboBox_countLabel.Items.Count - 1, countLabel); + + string storageGroup = od.prop.CO_storageGroup; + if (!comboBox_storageGroup.Items.Contains(storageGroup)) + comboBox_storageGroup.Items.Insert(comboBox_storageGroup.Items.Count - 1, storageGroup); + } + + listView_communication_objects.EndUpdate(); + listView_manufacturer_objects.EndUpdate(); + listView_deviceProfile_objects.EndUpdate(); + + /* reset scroll position and selection */ + if (listview_communication_position != 0 && listView_communication_objects.Items.Count > 0) + listView_communication_objects.TopItem = listView_communication_objects.Items[listview_communication_position]; + if (listview_manufacturer_position != 0 && listView_manufacturer_objects.Items.Count > 0) + listView_manufacturer_objects.TopItem = listView_manufacturer_objects.Items[listview_manufacturer_position]; + if (listview_deviceProfile_position != 0 && listView_deviceProfile_objects.Items.Count > 0) + listView_deviceProfile_objects.TopItem = listView_deviceProfile_objects.Items[listview_deviceProfile_position]; + } + + public void PopulateSubList() + { + listView_subObjects.Items.Clear(); + + if (selectedObject == null) + return; + ODentry od = selectedObject.parent ?? selectedObject; + + if (od.objecttype == ObjectType.VAR) + { + ListViewItem lvi = new ListViewItem(new string[] { + " ", // subindex + od.parameter_name, + od.ObjectTypeString(), + od.datatype.ToString(), + od.AccessSDO().ToString(), + od.AccessPDO().ToString(), + od.prop.CO_accessSRDO.ToString(), + od.defaultvalue + }); + lvi.Tag = od; + listView_subObjects.Items.Add(lvi); + } + else if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) + { + ListViewItem lvi = new ListViewItem(new string[]{ + " ", + od.parameter_name, + od.ObjectTypeString() + }); + lvi.Tag = od; + listView_subObjects.Items.Add(lvi); + + foreach (KeyValuePair kvp in od.subobjects) + { + ODentry subod = kvp.Value; + int subindex = kvp.Key; + + ListViewItem lvi2 = new ListViewItem(new string[] { + string.Format("0x{0:X2}", subindex), + subod.parameter_name, + subod.ObjectTypeString(), + (subod.datatype != DataType.UNKNOWN) ? subod.datatype.ToString() : od.datatype.ToString(), + subod.AccessSDO().ToString(), + subod.AccessPDO().ToString(), + subod.prop.CO_accessSRDO.ToString(), + subod.defaultvalue + }); + lvi2.Tag = subod; + listView_subObjects.Items.Add(lvi2); + } + } + } + + public void PopulateObject() + { + + ExporterV4 = ExporterTypeV4(); if (ExporterOld != ExporterV4) - { - RebuildControls(); + { + RebuildControls(); ExporterOld = ExporterV4; - } - - justUpdating = true; - lastSelectedObject = selectedObject; - - - if (selectedObject == null) - { - textBox_index.Text = ""; - textBox_subIndex.Text = ""; - textBox_name.Text = ""; - textBox_denotation.Text = ""; - textBox_description.Text = ""; - justUpdating = false; - return; - } - - ODentry od = selectedObject; - - textBox_index.Text = string.Format("0x{0:X4}", od.Index); - textBox_name.Text = od.parameter_name; - textBox_denotation.Text = od.denotation; - textBox_description.Text = (od.Description == null) ? "" : Regex.Replace(od.Description, "(? 0) - { - foreach (ODentry subod in od.parent.subobjects.Values) - { - if (subod.Subindex > 0) - { - subod.datatype = od.datatype; - subod.accesstype = od.accesstype; - subod.PDOtype = od.PDOtype; - subod.prop.CO_accessSRDO = od.prop.CO_accessSRDO; - } - } - od.parent.datatype = od.datatype; - od.parent.accesstype = od.accesstype; - od.parent.PDOtype = od.PDOtype; - od.parent.prop.CO_accessSRDO = od.prop.CO_accessSRDO; - } - } - - if (od.parent == null) - { - od.prop.CO_countLabel = comboBox_countLabel.SelectedItem.ToString(); - od.prop.CO_storageGroup = comboBox_storageGroup.SelectedItem.ToString(); - od.prop.CO_disabled = !checkBox_enabled.Checked; - od.prop.CO_flagsPDO = checkBox_pdoFlags.Checked; - } - - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - - private void ListView_objects_MouseClick(object sender, MouseEventArgs e) - { - ListView listview = (ListView)sender; - ODentry od = listview.SelectedItems.Count > 0 ? (ODentry)listview.SelectedItems[0].Tag : null; - - if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) - { - selectedList = listview; - selectedObject = od; - - if (e.Button == MouseButtons.Right) - { - contextMenu_object.Show(Cursor.Position); - } - - PopulateObject(); - PopulateSubList(); - } - listView_communication_objects.HideSelection = true; - listView_deviceProfile_objects.HideSelection = true; - listView_manufacturer_objects.HideSelection = true; - } - - private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) - { - ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); - } - - private void ListView_objects_ColumnClick(object sender, ColumnClickEventArgs e) - { - ((ListView)sender).SelectedItems.Clear(); - ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0)); - } - - private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) - { - if (listView_subObjects.SelectedItems.Count == 0) - return; - - ODentry od = (ODentry)listView_subObjects.SelectedItems[0].Tag; - - if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) - { - if (e.Button == MouseButtons.Right) - { - ODentry parent = od.parent ?? od; - - if (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.RECORD) - { - contextMenu_subObject_removeSubItemToolStripMenuItem.Enabled = od.Subindex > 0 && od.parent != null; - contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Enabled = parent.objecttype == ObjectType.RECORD && od.Subindex > 0 && od.parent != null; - - if (listView_subObjects.FocusedItem.Bounds.Contains(e.Location) == true) - { - contextMenu_subObject.Show(Cursor.Position); - } - } - } - selectedObject = od; - PopulateObject(); - } - } - - private void ListView_subObjects_SelectedIndexChanged(object sender, EventArgs e) - { - ListView_subObjects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); - } - - private void ComboBox_countLabel_Add(object sender, EventArgs e) - { - ComboBox comboBox = (ComboBox)sender; - - if (comboBox.SelectedItem != null && comboBox.SelectedItem.ToString() == "Add...") - { - NewItem dialog = new NewItem("Add Count Label"); - if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) - { - comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); - comboBox.SelectedItem = dialog.name; - } - } - } - - private void ComboBox_storageGroup_Add(object sender, EventArgs e) - { - ComboBox comboBox = (ComboBox)sender; - - if (comboBox.SelectedItem!=null && comboBox.SelectedItem.ToString() == "Add...") - { - NewItem dialog = new NewItem("Add Storage Group"); - if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) - { - comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); - comboBox.SelectedItem = dialog.name; - /* add new dialog location to eds back end */ - eds.CO_storageGroups.Add(dialog.name); - } - } - } - - private void ContextMenu_object_clone_ToolStripMenuItem_Click(object sender, EventArgs e) - { - var srcObjects = new SortedDictionary(); - foreach (ListViewItem item in selectedList.SelectedItems) - { - ODentry od = (ODentry)item.Tag; - srcObjects.Add(od.Index, od); - } - - if (srcObjects.Count > 0) - { - InsertObjects insObjForm = new InsertObjects(eds, srcObjects, "1"); - - if (insObjForm.ShowDialog() == DialogResult.OK) - { - selectedObject = null; - eds.Dirty = true; - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - } - } - - private void ContextMenu_object_add_ToolStripMenuItem_Click(object sender, EventArgs e) - { - NewIndex ni = new NewIndex(eds, (UInt16)(selectedObject == null ? 0x2000 : selectedObject.Index + 1)); - - if (ni.ShowDialog() == DialogResult.OK) - { - selectedObject = ni.od; - eds.Dirty = true; - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - } - - private void ContextMenu_object_delete_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; - if (selectedItems.Count > 0) - { - DialogResult confirmDelete = MessageBox.Show(string.Format("Do you really want to delete the selected {0} items?", selectedItems.Count), "Are you sure?", MessageBoxButtons.YesNo); - - if (confirmDelete == DialogResult.Yes) - { - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - eds.ods.Remove(od.Index); - } - - eds.Dirty = true; - selectedObject = null; - PopulateObjectLists(eds); - PopulateSubList(); - PopulateObject(); - } - } - } - - private void ContextMenu_object_toggle_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; - - justUpdating = true; - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - - od.prop.CO_disabled = !od.prop.CO_disabled; - } - justUpdating = false; - eds.Dirty = true; - PopulateObjectLists(eds); - PopulateObject(); - } - - private void ContextMenu_subObject_add_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; - - ODentry newOd = null; - - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - newOd = od.AddSubEntry(); - } - - eds.Dirty = true; - selectedObject = newOd; - PopulateSubList(); - PopulateObject(); - } - - private void ContextMenu_subObject_remove_ToolStripMenuItem_Click(object sender, EventArgs e) - { - ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; - bool renumber = sender == contextMenu_subObject_removeSubItemToolStripMenuItem; - bool update = false; - - foreach (ListViewItem item in selectedItems) - { - ODentry od = (ODentry)item.Tag; - od.RemoveSubEntry(renumber); - update = true; - } - - if (update) - { - eds.Dirty = true; - selectedObject = selectedObject.parent; - PopulateSubList(); - PopulateObject(); - } - } - } - - public static class ControlExtensions - { - public static void DoubleBuffering(this Control control, bool enable) - { - var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic); - method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable }); - } - } -} + od.prop.CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), comboBox_accessSRDO.SelectedItem.ToString()); + } + catch (Exception) + { + od.prop.CO_accessSRDO = AccessSRDO.no; + } + + od.defaultvalue = textBox_defaultValue.Text; + od.actualvalue = textBox_actualValue.Text; + od.HighLimit = textBox_highLimit.Text; + od.LowLimit = textBox_lowLimit.Text; + + // CO_stringLengthMin + if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.UNICODE_STRING || od.datatype == DataType.OCTET_STRING) + { + try + { + od.prop.CO_stringLengthMin = (uint)new System.ComponentModel.UInt32Converter().ConvertFromString(textBox_stringLengthMin.Text); + } + catch (Exception) + { + od.prop.CO_stringLengthMin = 0; + } + } + else + { + od.prop.CO_stringLengthMin = 0; + } + + // some propeties in all array sub elements (and base element) must be equal + if (od.parent != null && od.parent.objecttype == ObjectType.ARRAY && od.Subindex > 0) + { + foreach (ODentry subod in od.parent.subobjects.Values) + { + if (subod.Subindex > 0) + { + subod.datatype = od.datatype; + subod.accesstype = od.accesstype; + subod.PDOtype = od.PDOtype; + subod.prop.CO_accessSRDO = od.prop.CO_accessSRDO; + } + } + od.parent.datatype = od.datatype; + od.parent.accesstype = od.accesstype; + od.parent.PDOtype = od.PDOtype; + od.parent.prop.CO_accessSRDO = od.prop.CO_accessSRDO; + } + } + + if (od.parent == null) + { + od.prop.CO_countLabel = comboBox_countLabel.SelectedItem.ToString(); + od.prop.CO_storageGroup = comboBox_storageGroup.SelectedItem.ToString(); + od.prop.CO_disabled = !checkBox_enabled.Checked; + od.prop.CO_flagsPDO = checkBox_pdoFlags.Checked; + } + + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + + private void ListView_objects_MouseClick(object sender, MouseEventArgs e) + { + ListView listview = (ListView)sender; + ODentry od = listview.SelectedItems.Count > 0 ? (ODentry)listview.SelectedItems[0].Tag : null; + + if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) + { + selectedList = listview; + selectedObject = od; + + if (e.Button == MouseButtons.Right) + { + contextMenu_object.Show(Cursor.Position); + } + + PopulateObject(); + PopulateSubList(); + } + listView_communication_objects.HideSelection = true; + listView_deviceProfile_objects.HideSelection = true; + listView_manufacturer_objects.HideSelection = true; + } + + private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) + { + ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); + } + + private void ListView_objects_ColumnClick(object sender, ColumnClickEventArgs e) + { + ((ListView)sender).SelectedItems.Clear(); + ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0)); + } + + private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) + { + if (listView_subObjects.SelectedItems.Count == 0) + return; + + ODentry od = (ODentry)listView_subObjects.SelectedItems[0].Tag; + + if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) + { + if (e.Button == MouseButtons.Right) + { + ODentry parent = od.parent ?? od; + + if (parent.objecttype == ObjectType.ARRAY || parent.objecttype == ObjectType.RECORD) + { + contextMenu_subObject_removeSubItemToolStripMenuItem.Enabled = od.Subindex > 0 && od.parent != null; + contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Enabled = parent.objecttype == ObjectType.RECORD && od.Subindex > 0 && od.parent != null; + + if (listView_subObjects.FocusedItem.Bounds.Contains(e.Location) == true) + { + contextMenu_subObject.Show(Cursor.Position); + } + } + } + selectedObject = od; + PopulateObject(); + } + } + + private void ListView_subObjects_SelectedIndexChanged(object sender, EventArgs e) + { + ListView_subObjects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); + } + + private void ComboBox_countLabel_Add(object sender, EventArgs e) + { + ComboBox comboBox = (ComboBox)sender; + + if (comboBox.SelectedItem != null && comboBox.SelectedItem.ToString() == "Add...") + { + NewItem dialog = new NewItem("Add Count Label"); + if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) + { + comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); + comboBox.SelectedItem = dialog.name; + } + } + } + + private void ComboBox_storageGroup_Add(object sender, EventArgs e) + { + ComboBox comboBox = (ComboBox)sender; + + if (comboBox.SelectedItem!=null && comboBox.SelectedItem.ToString() == "Add...") + { + NewItem dialog = new NewItem("Add Storage Group"); + if (dialog.ShowDialog() == DialogResult.OK && comboBox.FindStringExact(dialog.name) == -1) + { + comboBox.Items.Insert(comboBox.Items.Count - 1, dialog.name); + comboBox.SelectedItem = dialog.name; + /* add new dialog location to eds back end */ + eds.CO_storageGroups.Add(dialog.name); + } + } + } + + private void ContextMenu_object_clone_ToolStripMenuItem_Click(object sender, EventArgs e) + { + var srcObjects = new SortedDictionary(); + foreach (ListViewItem item in selectedList.SelectedItems) + { + ODentry od = (ODentry)item.Tag; + srcObjects.Add(od.Index, od); + } + + if (srcObjects.Count > 0) + { + InsertObjects insObjForm = new InsertObjects(eds, network, srcObjects, "1"); + + if (insObjForm.ShowDialog() == DialogResult.OK) + { + selectedObject = null; + EDSsharp modifiedEds = insObjForm.GetModifiedEDS(); + modifiedEds.Dirty = true; + if(modifiedEds == this.eds) + { + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + } + } + } + + private void ContextMenu_object_add_ToolStripMenuItem_Click(object sender, EventArgs e) + { + NewIndex ni = new NewIndex(eds, (UInt16)(selectedObject == null ? 0x2000 : selectedObject.Index + 1)); + + if (ni.ShowDialog() == DialogResult.OK) + { + selectedObject = ni.od; + eds.Dirty = true; + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + } + + private void ContextMenu_object_delete_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; + if (selectedItems.Count > 0) + { + DialogResult confirmDelete = MessageBox.Show(string.Format("Do you really want to delete the selected {0} items?", selectedItems.Count), "Are you sure?", MessageBoxButtons.YesNo); + + if (confirmDelete == DialogResult.Yes) + { + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + eds.ods.Remove(od.Index); + } + + eds.Dirty = true; + selectedObject = null; + PopulateObjectLists(eds); + PopulateSubList(); + PopulateObject(); + } + } + } + + private void ContextMenu_object_toggle_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = selectedList.SelectedItems; + + justUpdating = true; + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + + od.prop.CO_disabled = !od.prop.CO_disabled; + } + justUpdating = false; + eds.Dirty = true; + PopulateObjectLists(eds); + PopulateObject(); + } + + private void ContextMenu_subObject_add_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; + + ODentry newOd = null; + + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + newOd = od.AddSubEntry(); + } + + eds.Dirty = true; + selectedObject = newOd; + PopulateSubList(); + PopulateObject(); + } + + private void ContextMenu_subObject_remove_ToolStripMenuItem_Click(object sender, EventArgs e) + { + ListView.SelectedListViewItemCollection selectedItems = listView_subObjects.SelectedItems; + bool renumber = sender == contextMenu_subObject_removeSubItemToolStripMenuItem; + bool update = false; + + foreach (ListViewItem item in selectedItems) + { + ODentry od = (ODentry)item.Tag; + od.RemoveSubEntry(renumber); + update = true; + } + + if (update) + { + eds.Dirty = true; + selectedObject = selectedObject.parent; + PopulateSubList(); + PopulateObject(); + } + } + } + + public static class ControlExtensions + { + public static void DoubleBuffering(this Control control, bool enable) + { + var method = typeof(Control).GetMethod("SetStyle", BindingFlags.Instance | BindingFlags.NonPublic); + method.Invoke(control, new object[] { ControlStyles.OptimizedDoubleBuffer, enable }); + } + } +} diff --git a/EDSEditorGUI/DeviceView.Designer.cs b/EDSEditorGUI/DeviceView.Designer.cs index 52b4b56a..16c3efe1 100644 --- a/EDSEditorGUI/DeviceView.Designer.cs +++ b/EDSEditorGUI/DeviceView.Designer.cs @@ -1,33 +1,33 @@ -namespace ODEditor -{ - partial class DeviceView - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace ODEditor +{ + partial class DeviceView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { this.components = new System.ComponentModel.Container(); System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeviceView)); this.imageList1 = new System.Windows.Forms.ImageList(this.components); @@ -172,9 +172,9 @@ private void InitializeComponent() this.tabControl1.ResumeLayout(false); this.ResumeLayout(false); - } - - #endregion + } + + #endregion private System.Windows.Forms.ImageList imageList1; private System.Windows.Forms.TabPage tabPage4; private DevicePDOView2 devicePDOView2; @@ -185,5 +185,5 @@ private void InitializeComponent() private System.Windows.Forms.TabPage tabPage1; private DeviceInfoView deviceInfoView; private System.Windows.Forms.TabControl tabControl1; - } -} + } +} diff --git a/EDSEditorGUI/DeviceView.cs b/EDSEditorGUI/DeviceView.cs index 6963eda0..375329eb 100644 --- a/EDSEditorGUI/DeviceView.cs +++ b/EDSEditorGUI/DeviceView.cs @@ -18,6 +18,7 @@ You should have received a copy of the GNU General Public License */ using System; +using System.Collections.Generic; using System.Windows.Forms; using libEDSsharp; @@ -27,13 +28,17 @@ public partial class DeviceView : MyTabUserControl { readonly public EDSsharp eds; + readonly private List network; - public DeviceView(EDSsharp eds_target) + public DeviceView(EDSsharp eds_target, List network) { eds = eds_target; + this.network = network; InitializeComponent(); + this.deviceODView1.network = network; + foreach (TabPage tp in tabControl1.TabPages) { foreach(Object o in tp.Controls) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 405c71b6..316416ec 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -1,663 +1,663 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - - Copyright(c) 2016 - 2019 Robin Cornelius -*/ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq; -using System.Windows.Forms; -using System.IO; -using libEDSsharp; -using Xml2CSharp; - -namespace ODEditor -{ - public partial class ODEditor_MainForm : Form - { - - private List _mru = new List(); - private string appdatafolder; - - private string networkfilename; - - private string gitVersion; - - private string toolTipsString; //used for holding the tooltip message for file drag and drop events - - public static Dictionary TXCobMap = new Dictionary(); - List network = new List(); - - public ODEditor_MainForm() - { - InitializeComponent(); - loadprofiles(); - insertToolStripMenuItem.Enabled = false; - Warnings.warning_mask = Properties.Settings.Default.WarningMask; - } - - private void loadprofiles() - { - - // load default profiles from the install directory - // load user profiles from the My Documents\.edseditor\profiles\ folder - // Personal is my documents in windows and ~ in mono - - try - { - - List profilelist = Directory.GetFiles(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "Profiles").ToList(); - string homepath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".edseditor"); - homepath = Path.Combine(homepath, "profiles"); - - if (Directory.Exists(homepath)) - { - profilelist.AddRange(Directory.GetFiles(homepath).ToList()); - } - - var items = new List(); - - ToolStripMenuItem item = new ToolStripMenuItem(); - item.Name = "///openFile"; - item.Text = "Open Profile File..."; - item.Click += ProfileAddClick; - item.Image = Properties.Resources.InsertColumn_5626; - items.Add(item); - - foreach (string file in profilelist) - { - string ext = Path.GetExtension(file).ToLower(); - if (ext == ".xml" || ext == ".xpd" || ext == ".xdd") - { - item = new ToolStripMenuItem(); - item.Name = Path.GetFileName(file); - item.Text = Path.GetFileName(file); - item.Click += ProfileAddClick; - item.Image = Properties.Resources.InsertColumn_5626; - items.Add(item); - } - } - - insertToolStripMenuItem.DropDownItems.AddRange(items.ToArray()); - } - catch (Exception e) - { - MessageBox.Show("Loading profiles has failed for the following reason :\n" + e.ToString()); - } - - } - - void ProfileAddClick(object sender, EventArgs e) - { - if (tabControl1.SelectedTab != null) - { - ToolStripMenuItem item = (ToolStripMenuItem)sender; - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - string filename; - EDSsharp eds = null; - - if (item.Name == "///openFile") - { - OpenFileDialog odf = new OpenFileDialog(); - odf.Filter = "All supported files (*.xpd;*.xdd;*.xdc;*.xml)|*.xpd;*.xdd;*.xdc;*.xml|" - + "CANopen XPD 1.1 (*.xpd)|*.xpd|" - + "CANopen XDD 1.1 (*.xdd)|*.xdd|" - + "CANopen XDC 1.1 (*.xdc)|*.xdc|" - + "CANopenNode XML, old (*.xml)|*.xml"; - - if (odf.ShowDialog() != DialogResult.OK) - return; - - filename = odf.FileName; - } - else - { - filename = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "Profiles" + Path.DirectorySeparatorChar + item.Name; - } - - switch (Path.GetExtension(filename).ToLower()) - { - case ".xdd": - case ".xdc": - case ".xpd": - CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); - eds = coxml_1_1.ReadXML(filename); - break; - - case ".xml": - CanOpenXML coxml = new CanOpenXML(); - coxml.readXML(filename); - Bridge b = new Bridge(); - eds = b.convert(coxml.dev); - break; - } - - if (eds == null) - { - MessageBox.Show("Problem with loading the file."); - return; - } - - InsertObjects insObjForm = new InsertObjects(dv.eds, eds.ods, "0"); - - if (insObjForm.ShowDialog() == DialogResult.OK) - { - dv.eds.Dirty = true; - dv.dispatch_updateOD(); - dv.dispatch_updatePDOinfo(); - - dv.eds.UpdatePDOcount(); - dv.dispatch_updatedevice(); - } - } - } - - private void openEDSfile(string path,InfoSection.Filetype ft) - { - Warnings.warning_list.Clear(); - - try - { - EDSsharp eds = new EDSsharp(); - Device dev; - - eds.Loadfile(path); - Bridge bridge = new Bridge(); //tell me again why bridge is not static? - dev = bridge.convert(eds); - - DeviceView device = new DeviceView(eds); - - eds.OnDataDirty += Eds_onDataDirty; - - tabControl1.TabPages.Add(eds.di.ProductName); - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - - device.Dock = DockStyle.Fill; - device.dispatch_updateOD(); - - network.Add(eds); - } - catch (Exception ex) - { - Warnings.warning_list.Add(ex.ToString()); - } - - if (Warnings.warning_list.Count != 0) - { - WarningsFrm frm = new WarningsFrm(); - frm.Show(); - } - } - - private void exportCanOpenNode(DeviceView dv, string FileName, ExporterFactory.Exporter exporterType) - { - Warnings.warning_list.Clear(); - - IExporter exporter = ExporterFactory.getExporter(exporterType); - - try - { - string savePath = Path.GetDirectoryName(FileName); - string baseFileName = Path.GetFileNameWithoutExtension(FileName); - exporter.export(savePath, baseFileName, this.gitVersion, dv.eds, baseFileName); - } - catch (Exception ex) - { - MessageBox.Show("Export failed see detailed reason below :-\n" + ex.ToString()); - } - - if (Warnings.warning_list.Count != 0) - { - WarningsFrm frm = new WarningsFrm(); - frm.Show(); - } - - dv.dispatch_updateOD(); - } - - private void exportCanOpenNodeToolStripMenuItem_Click(object sender, EventArgs e) - { - if (tabControl1.SelectedTab != null) - { - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; - - SaveFileDialog sfd = new SaveFileDialog(); - sfd.CheckFileExists = false; - - sfd.InitialDirectory = (dv.eds.ODfilename != null && dv.eds.ODfilename != "") - ? Path.GetDirectoryName(dv.eds.ODfilename) - : Path.GetDirectoryName(dv.eds.projectFilename); - sfd.RestoreDirectory = true; - sfd.FileName = (type == ExporterFactory.Exporter.CANOPENNODE_V4) ? "OD.h" : "CO_OD.c"; - sfd.Filter = "CANopenNode (*.h, *.c)|*.h"; - - DialogResult result = sfd.ShowDialog(); - - if (result == DialogResult.OK) - { - dv.eds.ODfilename = sfd.FileName; - dv.eds.ODfileVersion = (type == ExporterFactory.Exporter.CANOPENNODE_V4) ? "V4" : "V1"; - - exportCanOpenNode(dv, sfd.FileName, type); - } - } - } - - private void openToolStripMenuItem_Click(object sender, EventArgs e) - { - - Warnings.warning_list.Clear(); - - OpenFileDialog odf = new OpenFileDialog(); - odf.Filter = "All supported files (*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.xml)|*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.xml|" - + "CANopen XDD (*.xdd)|*.xdd|" - + "CANopen XDC (*.xdc)|*.xdc|" - + "CANopen XPD (*.xpd)|*.xpd|" - + "Electronic Data Sheet (*.eds)|*.eds|" - + "Device Configuration File (*.dcf)|*.dcf|" - + "CANopenNode XML, old (*.xml)|*.xml"; - - if (odf.ShowDialog() == DialogResult.OK) - { - - switch(Path.GetExtension(odf.FileName).ToLower()) - { - case ".xdd": - case ".xdc": - case ".xpd": - openXDDfile(odf.FileName); - break; - - case ".xml": - openXMLfile(odf.FileName); - break; - - case ".eds": - openEDSfile(odf.FileName, InfoSection.Filetype.File_EDS); - break; - - case ".dcf": - openEDSfile(odf.FileName, InfoSection.Filetype.File_DCF); - break; - - default: - return; - - } - - addtoMRU(odf.FileName); - } - - } - - private void openXDDfile(string path) - { - try - { - EDSsharp eds; - - string xddfileVersion = "1.1"; - CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); - eds = coxml_1_1.ReadXML(path); - - if (eds == null) - { - xddfileVersion = "1.0"; - CanOpenXDD coxml = new CanOpenXDD(); - eds = coxml.readXML(path); - - if (eds == null) - return; - } - - eds.projectFilename = path; - if (xddfileVersion == "1.0") - eds.xddfilename_1_0 = path; - else - eds.xddfilename_1_1 = path; - - tabControl1.TabPages.Add(eds.di.ProductName); - - DeviceView device = new DeviceView(eds); - - eds.OnDataDirty += Eds_onDataDirty; - - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - - device.Dock = DockStyle.Fill; - device.dispatch_updateOD(); - - network.Add(eds); - } - catch (Exception ex) - { - Warnings.warning_list.Add(ex.ToString()); - } - - if (Warnings.warning_list.Count != 0) - { - WarningsFrm frm = new WarningsFrm(); - frm.Show(); - } - - - - } - - private void openXMLfile(string path) - { - - try - { - EDSsharp eds; - Device dev; //one day this will be multiple devices - - CanOpenXML coxml = new CanOpenXML(); - coxml.readXML(path); - - Bridge b = new Bridge(); - - eds = b.convert(coxml.dev); - eds.projectFilename = path; - - dev = coxml.dev; - - tabControl1.TabPages.Add(eds.di.ProductName); - - DeviceView device = new DeviceView(eds); - - eds.OnDataDirty += Eds_onDataDirty; - - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - - device.Dock = DockStyle.Fill; - device.dispatch_updateOD(); - - network.Add(eds); - } - catch (Exception ex) - { - Warnings.warning_list.Add(ex.ToString()); - } - - if (Warnings.warning_list.Count != 0) - { - WarningsFrm frm = new WarningsFrm(); - frm.Show(); - } - - } - - private void Eds_onDataDirty(bool dirty, EDSsharp sender) - { - foreach(TabPage page in tabControl1.TabPages) - { - foreach(Control c in page.Controls) - { - if(c.GetType() == typeof(DeviceView)) - { - DeviceView d = (DeviceView)c; - if (d.eds.Dirty == true) - { - page.BackColor = Color.Red; - } - else - { - page.BackColor = default(Color); - } - } - - } - - } - - } - - private void tabControl1_DrawItem(Object sender, System.Windows.Forms.DrawItemEventArgs e) - { - Graphics g = e.Graphics; - Brush _textBrush; - - // Get the item from the collection. - TabPage _tabPage = tabControl1.TabPages[e.Index]; - - // Get the real bounds for the tab rectangle. - Rectangle _tabBounds = tabControl1.GetTabRect(e.Index); - - if (e.State == DrawItemState.Selected) - { - - // Draw a different background color, and don't paint a focus rectangle. - _textBrush = new SolidBrush(Color.GhostWhite); - g.FillRectangle(Brushes.Gray, e.Bounds); - } - else - { - _textBrush = new System.Drawing.SolidBrush(e.ForeColor); - e.DrawBackground(); - } - - // Use our own font. - Font _tabFont = new Font("Arial", (float)10.0, FontStyle.Bold, GraphicsUnit.Pixel); - - // Draw string. Center the text. - StringFormat _stringFlags = new StringFormat(); - _stringFlags.Alignment = StringAlignment.Center; - _stringFlags.LineAlignment = StringAlignment.Center; - g.DrawString(_tabPage.Text, _tabFont, _textBrush, _tabBounds, new StringFormat(_stringFlags)); - } - - private void closeFileToolStripMenuItem_Click(object sender, EventArgs e) - { - if (tabControl1.SelectedTab != null) - { - // tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - - DeviceView device = (DeviceView)tabControl1.SelectedTab.Controls[0]; - - if(device.eds.Dirty==true) - { - if (MessageBox.Show( "All unsaved changes will be lost\n continue?", "Unsaved changes", MessageBoxButtons.YesNo) == DialogResult.No) - return; - } - - network.Remove(device.eds); - - tabControl1.TabPages.Remove(tabControl1.SelectedTab); - } - - } - - private void quitToolStripMenuItem_Click(object sender, EventArgs e) - { - Close(); - } - - private void exportDeviceFileToolStripMenuItem_Click(object sender, EventArgs e) - { - if (tabControl1.SelectedTab != null) - { - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - SaveFileDialog sfd = new SaveFileDialog(); - - sfd.Filter = "CANopen XDD v1.1 stripped (*.xdd)|*.xdd|" //must be first or change condition below - + "Electronic Data Sheet (*.eds)|*.eds|" - + "Device Configuration File (*.dcf)|*.dcf|" - + "Documentation (*.md)|*.md|" - + "CANopen XDD v1.0, old (*.xdd)|*.xdd|" - + "CANopenNode XML, old (*.xml)|*.xml"; - - sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); - sfd.RestoreDirectory = true; - sfd.FileName = Path.GetFileNameWithoutExtension(dv.eds.projectFilename); - - if (sfd.ShowDialog() == DialogResult.OK) - { - if (sfd.FilterIndex == 1) - dosave(dv, sfd.FileName, true, true); - else - dosave(dv, sfd.FileName, false); - } - } - } - - private void saveProjectToolStripMenuItem_Click(object sender, EventArgs e) - { - if (tabControl1.SelectedTab != null) - { - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - - if (dv.eds.xddfilename_1_1 != "") - { - dosave(dv, dv.eds.xddfilename_1_1, true); - } - else - { - saveAsToolStripMenuItem_Click(sender, e); - } - } - } - - private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) - { - if (tabControl1.SelectedTab != null) - { - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - SaveFileDialog sfd = new SaveFileDialog(); - - sfd.Filter = "CANopen XDD v1.1 (*.xdd)|*.xdd|" - + "CANopen XDC v1.1 (*.xdc)|*.xdc|" +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + + Copyright(c) 2016 - 2019 Robin Cornelius +*/ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq; +using System.Windows.Forms; +using System.IO; +using libEDSsharp; +using Xml2CSharp; + +namespace ODEditor +{ + public partial class ODEditor_MainForm : Form + { + + private List _mru = new List(); + private string appdatafolder; + + private string networkfilename; + + private string gitVersion; + + private string toolTipsString; //used for holding the tooltip message for file drag and drop events + + public static Dictionary TXCobMap = new Dictionary(); + List network = new List(); + + public ODEditor_MainForm() + { + InitializeComponent(); + loadprofiles(); + insertToolStripMenuItem.Enabled = false; + Warnings.warning_mask = Properties.Settings.Default.WarningMask; + } + + private void loadprofiles() + { + + // load default profiles from the install directory + // load user profiles from the My Documents\.edseditor\profiles\ folder + // Personal is my documents in windows and ~ in mono + + try + { + + List profilelist = Directory.GetFiles(System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "Profiles").ToList(); + string homepath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".edseditor"); + homepath = Path.Combine(homepath, "profiles"); + + if (Directory.Exists(homepath)) + { + profilelist.AddRange(Directory.GetFiles(homepath).ToList()); + } + + var items = new List(); + + ToolStripMenuItem item = new ToolStripMenuItem(); + item.Name = "///openFile"; + item.Text = "Open Profile File..."; + item.Click += ProfileAddClick; + item.Image = Properties.Resources.InsertColumn_5626; + items.Add(item); + + foreach (string file in profilelist) + { + string ext = Path.GetExtension(file).ToLower(); + if (ext == ".xml" || ext == ".xpd" || ext == ".xdd") + { + item = new ToolStripMenuItem(); + item.Name = Path.GetFileName(file); + item.Text = Path.GetFileName(file); + item.Click += ProfileAddClick; + item.Image = Properties.Resources.InsertColumn_5626; + items.Add(item); + } + } + + insertToolStripMenuItem.DropDownItems.AddRange(items.ToArray()); + } + catch (Exception e) + { + MessageBox.Show("Loading profiles has failed for the following reason :\n" + e.ToString()); + } + + } + + void ProfileAddClick(object sender, EventArgs e) + { + if (tabControl1.SelectedTab != null) + { + ToolStripMenuItem item = (ToolStripMenuItem)sender; + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + string filename; + EDSsharp eds = null; + + if (item.Name == "///openFile") + { + OpenFileDialog odf = new OpenFileDialog(); + odf.Filter = "All supported files (*.xpd;*.xdd;*.xdc;*.xml)|*.xpd;*.xdd;*.xdc;*.xml|" + + "CANopen XPD 1.1 (*.xpd)|*.xpd|" + + "CANopen XDD 1.1 (*.xdd)|*.xdd|" + + "CANopen XDC 1.1 (*.xdc)|*.xdc|" + + "CANopenNode XML, old (*.xml)|*.xml"; + + if (odf.ShowDialog() != DialogResult.OK) + return; + + filename = odf.FileName; + } + else + { + filename = System.IO.Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().Location) + Path.DirectorySeparatorChar + "Profiles" + Path.DirectorySeparatorChar + item.Name; + } + + switch (Path.GetExtension(filename).ToLower()) + { + case ".xdd": + case ".xdc": + case ".xpd": + CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); + eds = coxml_1_1.ReadXML(filename); + break; + + case ".xml": + CanOpenXML coxml = new CanOpenXML(); + coxml.readXML(filename); + Bridge b = new Bridge(); + eds = b.convert(coxml.dev); + break; + } + + if (eds == null) + { + MessageBox.Show("Problem with loading the file."); + return; + } + + InsertObjects insObjForm = new InsertObjects(dv.eds, network, eds.ods, "0"); + + if (insObjForm.ShowDialog() == DialogResult.OK) + { + dv.eds.Dirty = true; + dv.dispatch_updateOD(); + dv.dispatch_updatePDOinfo(); + + dv.eds.UpdatePDOcount(); + dv.dispatch_updatedevice(); + } + } + } + + private void openEDSfile(string path,InfoSection.Filetype ft) + { + Warnings.warning_list.Clear(); + + try + { + EDSsharp eds = new EDSsharp(); + Device dev; + + eds.Loadfile(path); + Bridge bridge = new Bridge(); //tell me again why bridge is not static? + dev = bridge.convert(eds); + + DeviceView device = new DeviceView(eds, network); + + eds.OnDataDirty += Eds_onDataDirty; + + tabControl1.TabPages.Add(eds.di.ProductName); + tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + + device.Dock = DockStyle.Fill; + device.dispatch_updateOD(); + + network.Add(eds); + } + catch (Exception ex) + { + Warnings.warning_list.Add(ex.ToString()); + } + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + } + + private void exportCanOpenNode(DeviceView dv, string FileName, ExporterFactory.Exporter exporterType) + { + Warnings.warning_list.Clear(); + + IExporter exporter = ExporterFactory.getExporter(exporterType); + + try + { + string savePath = Path.GetDirectoryName(FileName); + string baseFileName = Path.GetFileNameWithoutExtension(FileName); + exporter.export(savePath, baseFileName, this.gitVersion, dv.eds, baseFileName); + } + catch (Exception ex) + { + MessageBox.Show("Export failed see detailed reason below :-\n" + ex.ToString()); + } + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + + dv.dispatch_updateOD(); + } + + private void exportCanOpenNodeToolStripMenuItem_Click(object sender, EventArgs e) + { + if (tabControl1.SelectedTab != null) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; + + SaveFileDialog sfd = new SaveFileDialog(); + sfd.CheckFileExists = false; + + sfd.InitialDirectory = (dv.eds.ODfilename != null && dv.eds.ODfilename != "") + ? Path.GetDirectoryName(dv.eds.ODfilename) + : Path.GetDirectoryName(dv.eds.projectFilename); + sfd.RestoreDirectory = true; + sfd.FileName = (type == ExporterFactory.Exporter.CANOPENNODE_V4) ? "OD.h" : "CO_OD.c"; + sfd.Filter = "CANopenNode (*.h, *.c)|*.h"; + + DialogResult result = sfd.ShowDialog(); + + if (result == DialogResult.OK) + { + dv.eds.ODfilename = sfd.FileName; + dv.eds.ODfileVersion = (type == ExporterFactory.Exporter.CANOPENNODE_V4) ? "V4" : "V1"; + + exportCanOpenNode(dv, sfd.FileName, type); + } + } + } + + private void openToolStripMenuItem_Click(object sender, EventArgs e) + { + + Warnings.warning_list.Clear(); + + OpenFileDialog odf = new OpenFileDialog(); + odf.Filter = "All supported files (*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.xml)|*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.xml|" + + "CANopen XDD (*.xdd)|*.xdd|" + + "CANopen XDC (*.xdc)|*.xdc|" + + "CANopen XPD (*.xpd)|*.xpd|" + + "Electronic Data Sheet (*.eds)|*.eds|" + + "Device Configuration File (*.dcf)|*.dcf|" + + "CANopenNode XML, old (*.xml)|*.xml"; + + if (odf.ShowDialog() == DialogResult.OK) + { + + switch(Path.GetExtension(odf.FileName).ToLower()) + { + case ".xdd": + case ".xdc": + case ".xpd": + openXDDfile(odf.FileName); + break; + + case ".xml": + openXMLfile(odf.FileName); + break; + + case ".eds": + openEDSfile(odf.FileName, InfoSection.Filetype.File_EDS); + break; + + case ".dcf": + openEDSfile(odf.FileName, InfoSection.Filetype.File_DCF); + break; + + default: + return; + + } + + addtoMRU(odf.FileName); + } + + } + + private void openXDDfile(string path) + { + try + { + EDSsharp eds; + + string xddfileVersion = "1.1"; + CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); + eds = coxml_1_1.ReadXML(path); + + if (eds == null) + { + xddfileVersion = "1.0"; + CanOpenXDD coxml = new CanOpenXDD(); + eds = coxml.readXML(path); + + if (eds == null) + return; + } + + eds.projectFilename = path; + if (xddfileVersion == "1.0") + eds.xddfilename_1_0 = path; + else + eds.xddfilename_1_1 = path; + + tabControl1.TabPages.Add(eds.di.ProductName); + + DeviceView device = new DeviceView(eds, network); + + eds.OnDataDirty += Eds_onDataDirty; + + tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + + device.Dock = DockStyle.Fill; + device.dispatch_updateOD(); + + network.Add(eds); + } + catch (Exception ex) + { + Warnings.warning_list.Add(ex.ToString()); + } + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + + + + } + + private void openXMLfile(string path) + { + + try + { + EDSsharp eds; + Device dev; //one day this will be multiple devices + + CanOpenXML coxml = new CanOpenXML(); + coxml.readXML(path); + + Bridge b = new Bridge(); + + eds = b.convert(coxml.dev); + eds.projectFilename = path; + + dev = coxml.dev; + + tabControl1.TabPages.Add(eds.di.ProductName); + + DeviceView device = new DeviceView(eds, network); + + eds.OnDataDirty += Eds_onDataDirty; + + tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + + device.Dock = DockStyle.Fill; + device.dispatch_updateOD(); + + network.Add(eds); + } + catch (Exception ex) + { + Warnings.warning_list.Add(ex.ToString()); + } + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + + } + + private void Eds_onDataDirty(bool dirty, EDSsharp sender) + { + foreach(TabPage page in tabControl1.TabPages) + { + foreach(Control c in page.Controls) + { + if(c.GetType() == typeof(DeviceView)) + { + DeviceView d = (DeviceView)c; + if (d.eds.Dirty == true) + { + page.BackColor = Color.Red; + } + else + { + page.BackColor = default(Color); + } + } + + } + + } + + } + + private void tabControl1_DrawItem(Object sender, System.Windows.Forms.DrawItemEventArgs e) + { + Graphics g = e.Graphics; + Brush _textBrush; + + // Get the item from the collection. + TabPage _tabPage = tabControl1.TabPages[e.Index]; + + // Get the real bounds for the tab rectangle. + Rectangle _tabBounds = tabControl1.GetTabRect(e.Index); + + if (e.State == DrawItemState.Selected) + { + + // Draw a different background color, and don't paint a focus rectangle. + _textBrush = new SolidBrush(Color.GhostWhite); + g.FillRectangle(Brushes.Gray, e.Bounds); + } + else + { + _textBrush = new System.Drawing.SolidBrush(e.ForeColor); + e.DrawBackground(); + } + + // Use our own font. + Font _tabFont = new Font("Arial", (float)10.0, FontStyle.Bold, GraphicsUnit.Pixel); + + // Draw string. Center the text. + StringFormat _stringFlags = new StringFormat(); + _stringFlags.Alignment = StringAlignment.Center; + _stringFlags.LineAlignment = StringAlignment.Center; + g.DrawString(_tabPage.Text, _tabFont, _textBrush, _tabBounds, new StringFormat(_stringFlags)); + } + + private void closeFileToolStripMenuItem_Click(object sender, EventArgs e) + { + if (tabControl1.SelectedTab != null) + { + // tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + + DeviceView device = (DeviceView)tabControl1.SelectedTab.Controls[0]; + + if(device.eds.Dirty==true) + { + if (MessageBox.Show( "All unsaved changes will be lost\n continue?", "Unsaved changes", MessageBoxButtons.YesNo) == DialogResult.No) + return; + } + + network.Remove(device.eds); + + tabControl1.TabPages.Remove(tabControl1.SelectedTab); + } + + } + + private void quitToolStripMenuItem_Click(object sender, EventArgs e) + { + Close(); + } + + private void exportDeviceFileToolStripMenuItem_Click(object sender, EventArgs e) + { + if (tabControl1.SelectedTab != null) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + SaveFileDialog sfd = new SaveFileDialog(); + + sfd.Filter = "CANopen XDD v1.1 stripped (*.xdd)|*.xdd|" //must be first or change condition below + + "Electronic Data Sheet (*.eds)|*.eds|" + + "Device Configuration File (*.dcf)|*.dcf|" + + "Documentation (*.md)|*.md|" + + "CANopen XDD v1.0, old (*.xdd)|*.xdd|" + + "CANopenNode XML, old (*.xml)|*.xml"; + + sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); + sfd.RestoreDirectory = true; + sfd.FileName = Path.GetFileNameWithoutExtension(dv.eds.projectFilename); + + if (sfd.ShowDialog() == DialogResult.OK) + { + if (sfd.FilterIndex == 1) + dosave(dv, sfd.FileName, true, true); + else + dosave(dv, sfd.FileName, false); + } + } + } + + private void saveProjectToolStripMenuItem_Click(object sender, EventArgs e) + { + if (tabControl1.SelectedTab != null) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + + if (dv.eds.xddfilename_1_1 != "") + { + dosave(dv, dv.eds.xddfilename_1_1, true); + } + else + { + saveAsToolStripMenuItem_Click(sender, e); + } + } + } + + private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) + { + if (tabControl1.SelectedTab != null) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + SaveFileDialog sfd = new SaveFileDialog(); + + sfd.Filter = "CANopen XDD v1.1 (*.xdd)|*.xdd|" + + "CANopen XDC v1.1 (*.xdc)|*.xdc|" + "CANopen XPD v1.1 (*.xpd)|*.xpd"; - if (dv.eds.projectFilename == "") - { - sfd.FileName = Path.GetFileNameWithoutExtension(networkfilename); - } - else + if (dv.eds.projectFilename == "") + { + sfd.FileName = Path.GetFileNameWithoutExtension(networkfilename); + } + else { sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); sfd.RestoreDirectory = true; - sfd.FileName = Path.GetFileNameWithoutExtension(dv.eds.projectFilename); - } - - - if (sfd.ShowDialog() == DialogResult.OK) - { - dosave(dv, sfd.FileName, true); - } - } - - } - - - void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripped = false) - { - - switch (Path.GetExtension(FileName)) - { - case ".eds": - dv.eds.Savefile(FileName, InfoSection.Filetype.File_EDS); - dv.eds.edsfilename = FileName; - break; - - case ".dcf": - dv.eds.Savefile(FileName, InfoSection.Filetype.File_DCF); - dv.eds.dcffilename = FileName; - break; - - case ".md": - DocumentationGen docgen = new DocumentationGen(); - docgen.genmddoc(FileName, dv.eds, this.gitVersion); - dv.eds.mdfilename = FileName; - break; - - case ".xml": - Bridge b = new Bridge(); - Device d = b.convert(dv.eds); - - CanOpenXML coxml = new CanOpenXML(); - coxml.dev = d; - coxml.writeXML(FileName); - dv.eds.xmlfilename = FileName; - break; - - case ".xdd": - case ".xdc": - case ".xpd": - if (xddfileVersion_1_1) - { - if (stripped) - { - dv.eds.xddfilenameStripped = FileName; - } - else - { - dv.eds.projectFilename = FileName; - dv.eds.xddfilename_1_1 = FileName; - } - Warnings.warning_list.Clear(); - - CanOpenXDD_1_1 coxdd = new CanOpenXDD_1_1(); - coxdd.WriteXML(FileName, dv.eds, this.gitVersion, Path.GetExtension(FileName) == ".xdc", stripped); - dv.eds.Dirty = false; - - if (Warnings.warning_list.Count != 0) - { - WarningsFrm frm = new WarningsFrm(); - frm.Show(); - } - } - else - { - CanOpenXDD coxdd = new CanOpenXDD(); - coxdd.writeXML(FileName, dv.eds); - dv.eds.xddfilename_1_0 = FileName; - } - break; - } - - dv.dispatch_updateOD(); - - } - - private void newToolStripMenuItem_Click(object sender, EventArgs e) - { - EDSsharp eds = new EDSsharp(); - eds.di.ProductName = "New Product"; - - string dir = Environment.OSVersion.Platform == PlatformID.Win32NT ? "\\" : "/"; - eds.projectFilename = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir + "project"; - - tabControl1.TabPages.Add(eds.di.ProductName); - - DeviceView device = new DeviceView(eds); - - eds.OnDataDirty += Eds_onDataDirty; - - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - - device.Dock = DockStyle.Fill; - device.dispatch_updateOD(); - - network.Add(eds); - } + sfd.FileName = Path.GetFileNameWithoutExtension(dv.eds.projectFilename); + } + + + if (sfd.ShowDialog() == DialogResult.OK) + { + dosave(dv, sfd.FileName, true); + } + } + + } + + + void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripped = false) + { + + switch (Path.GetExtension(FileName)) + { + case ".eds": + dv.eds.Savefile(FileName, InfoSection.Filetype.File_EDS); + dv.eds.edsfilename = FileName; + break; + + case ".dcf": + dv.eds.Savefile(FileName, InfoSection.Filetype.File_DCF); + dv.eds.dcffilename = FileName; + break; + + case ".md": + DocumentationGen docgen = new DocumentationGen(); + docgen.genmddoc(FileName, dv.eds, this.gitVersion); + dv.eds.mdfilename = FileName; + break; + + case ".xml": + Bridge b = new Bridge(); + Device d = b.convert(dv.eds); + + CanOpenXML coxml = new CanOpenXML(); + coxml.dev = d; + coxml.writeXML(FileName); + dv.eds.xmlfilename = FileName; + break; + + case ".xdd": + case ".xdc": + case ".xpd": + if (xddfileVersion_1_1) + { + if (stripped) + { + dv.eds.xddfilenameStripped = FileName; + } + else + { + dv.eds.projectFilename = FileName; + dv.eds.xddfilename_1_1 = FileName; + } + Warnings.warning_list.Clear(); + + CanOpenXDD_1_1 coxdd = new CanOpenXDD_1_1(); + coxdd.WriteXML(FileName, dv.eds, this.gitVersion, Path.GetExtension(FileName) == ".xdc", stripped); + dv.eds.Dirty = false; + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + } + else + { + CanOpenXDD coxdd = new CanOpenXDD(); + coxdd.writeXML(FileName, dv.eds); + dv.eds.xddfilename_1_0 = FileName; + } + break; + } + + dv.dispatch_updateOD(); + + } + + private void newToolStripMenuItem_Click(object sender, EventArgs e) + { + EDSsharp eds = new EDSsharp(); + eds.di.ProductName = "New Product"; + + string dir = Environment.OSVersion.Platform == PlatformID.Win32NT ? "\\" : "/"; + eds.projectFilename = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir + "project"; + + tabControl1.TabPages.Add(eds.di.ProductName); + + DeviceView device = new DeviceView(eds, network); + + eds.OnDataDirty += Eds_onDataDirty; + + tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + + device.Dock = DockStyle.Fill; + device.dispatch_updateOD(); + + network.Add(eds); + } private void TabControl1_Selected(Object sender, TabControlEventArgs e) { if(tabControl1.SelectedIndex == 0) @@ -668,650 +668,650 @@ private void TabControl1_Selected(Object sender, TabControlEventArgs e) dv.eds.UpdatePDOcount(); dv.dispatch_updatedevice(); } - } - private void tabControl1_ControlsChanged(object sender, ControlEventArgs e) - { - enablesavemenus(tabControl1.TabCount > 0); - } - - private void tabControl1_Controlsremoved(object sender, ControlEventArgs e) - { - //Because - enablesavemenus(tabControl1.TabCount > 1); - } - - private void enablesavemenus(bool enable) - { - insertToolStripMenuItem.Enabled = enable; - saveProjectToolStripMenuItem.Enabled = enable; - exportCanOpenNodeToolStripMenuItem.Enabled = enable; - closeFileToolStripMenuItem.Enabled = enable; - saveNetworkXmlToolStripMenuItem.Enabled = enable; - documentationToolStripMenuItem.Enabled = enable; - networkPDOToolStripMenuItem.Enabled = enable; - saveExportAllToolStripMenuItem.Enabled = enable; - exportDeviceFileToolStripMenuItem.Enabled = enable; - saveAsToolStripMenuItem.Enabled = true; - - } - - void OpenRecentFile(object sender, EventArgs e) - { - var menuItem = (ToolStripMenuItem)sender; - var filepath = (string)menuItem.Tag; - - string ext = Path.GetExtension(filepath); - - if (ext != null) - ext = ext.ToLower(); - - if ( ext == ".xml" ) - openXMLfile(filepath); - if (ext == ".xdd" || ext == ".xdc" || ext == ".xpd") - openXDDfile(filepath); - if ( ext == ".eds" ) - openEDSfile(filepath, InfoSection.Filetype.File_EDS); - if (ext == ".dcf") - openEDSfile(filepath, InfoSection.Filetype.File_DCF); - if (ext == ".nxml") - openNetworkfile(filepath); - - } - - private void ODEditor_MainForm_FormClosed(object sender, FormClosedEventArgs e) - { - var mruFilePath = Path.Combine(appdatafolder, "MRU.txt"); - System.IO.File.WriteAllLines(mruFilePath, _mru); - } - - private void ODEditor_MainForm_Load(object sender, EventArgs e) - { - //read git version string, show in title bar - //(https://stackoverflow.com/a/15145121) - string gitVersion = String.Empty; - using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly() - .GetManifestResourceStream("ODEditor." + "version.txt")) - using (StreamReader reader = new StreamReader(stream)) - { - gitVersion = reader.ReadToEnd().TrimEnd('\n'); - } - if (gitVersion == "") - { - gitVersion = "Unknown"; - } - this.Text += gitVersion; - this.gitVersion = gitVersion; - - //First lets create an appdata folder - - // The folder for the roaming current user - string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); - - // Combine the base folder with your specific folder.... - appdatafolder = Path.Combine(folder, "EDSEditor"); - - // Check if folder exists and if not, create it - if (!Directory.Exists(appdatafolder)) - Directory.CreateDirectory(appdatafolder); - - var mruFilePath = Path.Combine(appdatafolder, "MRU.txt"); - if (System.IO.File.Exists(mruFilePath)) - _mru.AddRange(System.IO.File.ReadAllLines(mruFilePath)); - - populateMRU(); - } - - private void addtoMRU(string path) - { - // if it already exists remove it then let it re-add itself - // so it will be promoted to the top of the list - if (_mru.Contains(path)) - _mru.Remove(path); - - _mru.Insert(0, path); - - if (_mru.Count > 10) - _mru.RemoveAt(10); - - populateMRU(); - - } - - private void populateMRU() - { - - mnuRecentlyUsed.DropDownItems.Clear(); - - foreach (var path in _mru) - { - var item = new ToolStripMenuItem(path); - item.Tag = path; - item.Click += OpenRecentFile; - switch(Path.GetExtension(path)) - { - case ".xml": - item.Image = Properties.Resources.GenericVSEditor_9905; - break; - case ".eds": - item.Image = Properties.Resources.EventLog_5735; - break; - case ".nxml": - item.Image = Properties.Resources.Index_8287_16x; - break; - } - - mnuRecentlyUsed.DropDownItems.Add(item); - } - } - - private void saveNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) - { - SaveFileDialog sfd = new SaveFileDialog(); - - sfd.Filter = "CANopen Network XDD v1.1 (*.nxdd)|*.nxdd|" - + "CANopen Network XDC v1.1 (*.nxdc)|*.nxdc|" - + "CANopen Network XDD v1.0, old (*.nxdd)|*.nxdd|" - + "CANopenNode network XML, old (*.nxml)|*.nxml"; - - sfd.InitialDirectory = Path.GetDirectoryName(networkfilename); - sfd.RestoreDirectory = true; - sfd.FileName = Path.GetFileNameWithoutExtension(networkfilename); - - if (sfd.ShowDialog() == DialogResult.OK) - { - switch (sfd.FilterIndex) - { - case 4: // .nxml - NetworkXML net = new NetworkXML(); - net.writeXML(sfd.FileName, network); - addtoMRU(sfd.FileName); - break; - - case 3: // .nxdd V1.0 - CanOpenXDD xdd = new CanOpenXDD(); - xdd.writeMultiXML(sfd.FileName, network); - break; - - case 2: // .nxdc V1.1 with actual value, denotation and deviceCommissioning info - CanOpenXDD_1_1 xdc_1_1 = new CanOpenXDD_1_1(); - xdc_1_1.WriteMultiXML(sfd.FileName, network, this.gitVersion, true); - break; - - case 1: // .nxdd V1.1 - CanOpenXDD_1_1 xdd_1_1 = new CanOpenXDD_1_1(); - xdd_1_1.WriteMultiXML(sfd.FileName, network, this.gitVersion, false); - break; - } - } - } - - private void loadNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) - { - - OpenFileDialog odf = new OpenFileDialog(); - odf.Filter = "All supported files (*.nxdd;*.nxdc;*.nxml)|*.nxdd;*.nxdc;*.nxml|" - + "CANopen Network XDD (*.nxdd)|*.nxdd|" - + "CANopen Network XDC (*.nxdc)|*.nxdc|" - + "CANopenNode network XML, old (*.nxml)|*.nxml"; - - if (odf.ShowDialog() == DialogResult.OK) - { - switch (Path.GetExtension(odf.FileName).ToLower()) - { - case ".nxml": - openNetworkfile(odf.FileName); - break; - - case ".nxdd": - case ".nxdc": - openXDDNetworkfile(odf.FileName); - - break; - } - } - } - - private void openXDDNetworkfile(string file) - { - CanOpenXDD_1_1 xdd_1_1 = new CanOpenXDD_1_1(); - List edss = xdd_1_1.ReadMultiXML(file); - - if (edss == null) - { - CanOpenXDD xdd = new CanOpenXDD(); - edss = xdd.readMultiXML(file); - - if (edss == null) - return; - } - - foreach (EDSsharp eds in edss) - { - - tabControl1.TabPages.Add(eds.di.ProductName); - - DeviceView device = new DeviceView(eds); - - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - device.Dock = DockStyle.Fill; - - network.Add(eds); - eds.OnDataDirty += Eds_onDataDirty; - - device.dispatch_updateOD(); - } - - addtoMRU(file); - networkfilename = file; - - } - - private void openNetworkfile(string file) - { - NetworkXML net = new NetworkXML(); - List devs = net.readXML(file); - - foreach (Device d in devs) - { - Bridge b = new Bridge(); - - EDSsharp eds = b.convert(d); - //eds.filename = path; //fixme: We need to save the projectfilename or SaveAs will throw an exception - - tabControl1.TabPages.Add(eds.di.ProductName); - - - DeviceView device = new DeviceView(eds); - - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - device.Dock = DockStyle.Fill; - - network.Add(eds); - eds.OnDataDirty += Eds_onDataDirty; - - device.dispatch_updateOD(); - - addtoMRU(file); - } - - networkfilename = file; - } - - private void networkPDOToolStripMenuItem_Click(object sender, EventArgs e) - { - - - string dir = GetTemporaryDirectory(); - - string csspath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".edseditor"); - csspath = Path.Combine(csspath, "style.css"); - - if (!System.IO.File.Exists(csspath)) - { - csspath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "style.css"); - } - - if (System.IO.File.Exists(csspath)) - { - System.IO.File.Copy(csspath, dir + Path.DirectorySeparatorChar + "style.css"); - } - - string temp = dir + Path.DirectorySeparatorChar + "network.html"; - - NetworkPDOreport npr = new NetworkPDOreport(); - npr.gennetpdodoc(temp, network); - - if (IsRunningOnMono()) - { - System.Diagnostics.Process.Start("file://"+temp); - } - else - { - ReportView rv = new ReportView(temp); - rv.Show(); - } - } - - public string GetTemporaryDirectory() - { - string tempDirectory; - - do - { - tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); - - } while (Directory.Exists(tempDirectory)); - - Directory.CreateDirectory(tempDirectory); - return tempDirectory; - } - - public static bool IsRunningOnMono() - { - return Type.GetType("Mono.Runtime") != null; - } - - private void documentationToolStripMenuItem_Click(object sender, EventArgs e) - { - try - { - - Warnings.warning_list.Clear(); - - if (tabControl1.SelectedTab != null) - { - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - SaveFileDialog sfd = new SaveFileDialog(); - - string dir = GetTemporaryDirectory(); - - - string csspath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".edseditor"); - csspath = Path.Combine(csspath, "style.css"); - - if (!System.IO.File.Exists(csspath)) - { - csspath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "style.css"); - } - - if (System.IO.File.Exists(csspath)) - { - System.IO.File.Copy(csspath, dir + Path.DirectorySeparatorChar + "style.css"); - } - - string temp = dir + Path.DirectorySeparatorChar + "documentation.html"; - string temp2 = dir + Path.DirectorySeparatorChar + "documentation.md"; - - this.UseWaitCursor = true; - - DocumentationGen docgen = new DocumentationGen(); - docgen.genhtmldoc(temp, dv.eds); - docgen.genmddoc(temp2, dv.eds, this.gitVersion); - System.Diagnostics.Process.Start("file://" + temp2); - if (IsRunningOnMono()) - { - System.Diagnostics.Process.Start("file://" + temp); - } - else - { - ReportView rv = new ReportView(temp); - rv.Show(); - } - - this.UseWaitCursor = false; - - } - } - catch (Exception ex) - { - Warnings.warning_list.Add(ex.ToString()); - } - - if (Warnings.warning_list.Count != 0) - { - WarningsFrm frm = new WarningsFrm(); - frm.Show(); - } - } - - private void saveExportAllToolStripMenuItem_Click(object sender, EventArgs e) - { - if (tabControl1.SelectedTab != null) - { - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - int cnt = 0; - - if (dv.eds.xddfilename_1_1 != "" && dv.eds.xddfilename_1_1 == dv.eds.projectFilename) - { - dosave(dv, dv.eds.xddfilename_1_1, true); - } - else - { - MessageBox.Show("Please save project file at least once!"); - return; - } - - if (dv.eds.edsfilename != null && dv.eds.edsfilename != "") - { - dv.eds.Savefile(dv.eds.edsfilename, InfoSection.Filetype.File_EDS); - cnt++; - } - - if (dv.eds.dcffilename != null && dv.eds.dcffilename != "") - { - dv.eds.Savefile(dv.eds.dcffilename, InfoSection.Filetype.File_DCF); - cnt++; - } - - if (dv.eds.mdfilename != null && dv.eds.mdfilename != "") - { - DocumentationGen docgen = new DocumentationGen(); - docgen.genmddoc(dv.eds.mdfilename, dv.eds, this.gitVersion); - cnt++; - } - - if (dv.eds.ODfilename != null && dv.eds.ODfilename != "") - { - ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; - string version = (type == ExporterFactory.Exporter.CANOPENNODE_V4) ? "V4" : "V1"; - - if (dv.eds.ODfileVersion == version) - { - exportCanOpenNode(dv, dv.eds.ODfilename, type); - } - else - { - // exporter type changed in preferences - dv.eds.ODfilename = ""; - dv.eds.ODfileVersion = ""; - dv.dispatch_updatedevice(); - MessageBox.Show("CANopenNode exporter changed. Please export manually at least once!"); - } - cnt++; - } - - if (cnt == 0) - { - MessageBox.Show("Nothing exported. Please use 'Export...' at least once!"); - } - - dv.eds.Dirty = false; - } - } - - private void ODEditor_MainForm_FormClosing(object sender, FormClosingEventArgs e) - { - - foreach (TabPage page in tabControl1.TabPages) - { - foreach (Control c in page.Controls) - { - if (c.GetType() == typeof(DeviceView)) - { - DeviceView d = (DeviceView)c; - if (d.eds.Dirty == true) - { - if(MessageBox.Show("Warning you have unsaved changes\n Do you wish to continue","Unsaved changes",MessageBoxButtons.YesNo)==DialogResult.No) - { - e.Cancel = true; - return; - } - } - - } - - } - - } - } - - private bool fileTypeSupported(string fileName) - { - bool typeSupported = false; - if (Path.HasExtension(fileName)) - { - switch (Path.GetExtension(fileName).ToLower()) - { - case ".xdd": - case ".xdc": - case ".xpd": - case ".xml": - case ".eds": - case ".dcf": - case ".nxdd": - case ".nxdc": - case ".nxml": - typeSupported = true; - break; - } - } - - return typeSupported; - - } - - private void ODEditor_MainForm_DragEnter(object sender, DragEventArgs e) - { - this.Activate(); - bool unsupportedFile = false; - var data = e.Data.GetData(DataFormats.FileDrop); - if (data != null && data.GetType()==typeof(String)) - { - var rawFileNames = data as string[]; - if (rawFileNames.Length > 0) - { - var fileNames = rawFileNames.Distinct(); - foreach (string fileName in fileNames) - { - if(fileTypeSupported(fileName) == false) - { - unsupportedFile = true; - break; - } - } - - } - - toolTipsString = (unsupportedFile ? "1 or more files not supported" : "Drop files here to open"); - - if (unsupportedFile) - { - e.Effect = DragDropEffects.None; - } - else - { - e.Effect = DragDropEffects.All; - } - - enableDragDropTooltip(); - - } - - else - { - e.Effect = DragDropEffects.None; - //disableDragDropTooltip(); - enableDragDropTooltip(); - } - - } - - private void enableDragDropTooltip() - { - toolTip1.Active = true; - toolTip1.ReshowDelay = 0; - toolTip1.InitialDelay = 0; - toolTip1.UseAnimation = false; - toolTip1.UseFading = false; - toolTip1.Show(toolTipsString, this, this.PointToClient(Cursor.Position).X, this.PointToClient(Cursor.Position).Y); - } - - private void disableDragDropTooltip() - { - toolTip1.Active = false; - } - - private void ODEditor_MainForm_DragLeave(object sender, EventArgs e) - { - disableDragDropTooltip(); - } - - private void ODEditor_MainForm_DragDrop(object sender, DragEventArgs e) - { - var data = e.Data.GetData(DataFormats.FileDrop); - if (data != null) - { - var rawFileNames = data as string[]; - - if (rawFileNames.Length > 0) - { - var fileNames = rawFileNames.Distinct(); - foreach (string fileName in fileNames) - { - switch (Path.GetExtension(fileName).ToLower()) - { - case ".xpd": - case ".xdc": - case ".xdd": - openXDDfile(fileName); - break; - - case ".xml": - openXMLfile(fileName); - break; - - case ".eds": - openEDSfile(fileName, InfoSection.Filetype.File_EDS); - break; - - case ".dcf": - openEDSfile(fileName, InfoSection.Filetype.File_DCF); - break; - - case ".nxml": - openNetworkfile(fileName); - break; - - case ".nxdc": - case ".nxdd": - openXDDNetworkfile(fileName); - break; - - default: - break; - - } - - addtoMRU(fileName); - } - } - } - disableDragDropTooltip(); - } - - private void ODEditor_MainForm_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) - { - if(e.EscapePressed) - { - e.Action = DragAction.Cancel; - disableDragDropTooltip(); - } - } - - private void ODEditor_MainForm_Leave(object sender, EventArgs e) - { - disableDragDropTooltip(); - } - - private void ODEditor_MainForm_DragOver(object sender, DragEventArgs e) - { - enableDragDropTooltip(); - } - - private void preferencesToolStripMenuItem_Click(object sender, EventArgs e) - { - Preferences p = new Preferences(); - p.ShowDialog(); - } - } -} + } + private void tabControl1_ControlsChanged(object sender, ControlEventArgs e) + { + enablesavemenus(tabControl1.TabCount > 0); + } + + private void tabControl1_Controlsremoved(object sender, ControlEventArgs e) + { + //Because + enablesavemenus(tabControl1.TabCount > 1); + } + + private void enablesavemenus(bool enable) + { + insertToolStripMenuItem.Enabled = enable; + saveProjectToolStripMenuItem.Enabled = enable; + exportCanOpenNodeToolStripMenuItem.Enabled = enable; + closeFileToolStripMenuItem.Enabled = enable; + saveNetworkXmlToolStripMenuItem.Enabled = enable; + documentationToolStripMenuItem.Enabled = enable; + networkPDOToolStripMenuItem.Enabled = enable; + saveExportAllToolStripMenuItem.Enabled = enable; + exportDeviceFileToolStripMenuItem.Enabled = enable; + saveAsToolStripMenuItem.Enabled = true; + + } + + void OpenRecentFile(object sender, EventArgs e) + { + var menuItem = (ToolStripMenuItem)sender; + var filepath = (string)menuItem.Tag; + + string ext = Path.GetExtension(filepath); + + if (ext != null) + ext = ext.ToLower(); + + if ( ext == ".xml" ) + openXMLfile(filepath); + if (ext == ".xdd" || ext == ".xdc" || ext == ".xpd") + openXDDfile(filepath); + if ( ext == ".eds" ) + openEDSfile(filepath, InfoSection.Filetype.File_EDS); + if (ext == ".dcf") + openEDSfile(filepath, InfoSection.Filetype.File_DCF); + if (ext == ".nxml") + openNetworkfile(filepath); + + } + + private void ODEditor_MainForm_FormClosed(object sender, FormClosedEventArgs e) + { + var mruFilePath = Path.Combine(appdatafolder, "MRU.txt"); + System.IO.File.WriteAllLines(mruFilePath, _mru); + } + + private void ODEditor_MainForm_Load(object sender, EventArgs e) + { + //read git version string, show in title bar + //(https://stackoverflow.com/a/15145121) + string gitVersion = String.Empty; + using (Stream stream = System.Reflection.Assembly.GetExecutingAssembly() + .GetManifestResourceStream("ODEditor." + "version.txt")) + using (StreamReader reader = new StreamReader(stream)) + { + gitVersion = reader.ReadToEnd().TrimEnd('\n'); + } + if (gitVersion == "") + { + gitVersion = "Unknown"; + } + this.Text += gitVersion; + this.gitVersion = gitVersion; + + //First lets create an appdata folder + + // The folder for the roaming current user + string folder = Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData); + + // Combine the base folder with your specific folder.... + appdatafolder = Path.Combine(folder, "EDSEditor"); + + // Check if folder exists and if not, create it + if (!Directory.Exists(appdatafolder)) + Directory.CreateDirectory(appdatafolder); + + var mruFilePath = Path.Combine(appdatafolder, "MRU.txt"); + if (System.IO.File.Exists(mruFilePath)) + _mru.AddRange(System.IO.File.ReadAllLines(mruFilePath)); + + populateMRU(); + } + + private void addtoMRU(string path) + { + // if it already exists remove it then let it re-add itself + // so it will be promoted to the top of the list + if (_mru.Contains(path)) + _mru.Remove(path); + + _mru.Insert(0, path); + + if (_mru.Count > 10) + _mru.RemoveAt(10); + + populateMRU(); + + } + + private void populateMRU() + { + + mnuRecentlyUsed.DropDownItems.Clear(); + + foreach (var path in _mru) + { + var item = new ToolStripMenuItem(path); + item.Tag = path; + item.Click += OpenRecentFile; + switch(Path.GetExtension(path)) + { + case ".xml": + item.Image = Properties.Resources.GenericVSEditor_9905; + break; + case ".eds": + item.Image = Properties.Resources.EventLog_5735; + break; + case ".nxml": + item.Image = Properties.Resources.Index_8287_16x; + break; + } + + mnuRecentlyUsed.DropDownItems.Add(item); + } + } + + private void saveNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) + { + SaveFileDialog sfd = new SaveFileDialog(); + + sfd.Filter = "CANopen Network XDD v1.1 (*.nxdd)|*.nxdd|" + + "CANopen Network XDC v1.1 (*.nxdc)|*.nxdc|" + + "CANopen Network XDD v1.0, old (*.nxdd)|*.nxdd|" + + "CANopenNode network XML, old (*.nxml)|*.nxml"; + + sfd.InitialDirectory = Path.GetDirectoryName(networkfilename); + sfd.RestoreDirectory = true; + sfd.FileName = Path.GetFileNameWithoutExtension(networkfilename); + + if (sfd.ShowDialog() == DialogResult.OK) + { + switch (sfd.FilterIndex) + { + case 4: // .nxml + NetworkXML net = new NetworkXML(); + net.writeXML(sfd.FileName, network); + addtoMRU(sfd.FileName); + break; + + case 3: // .nxdd V1.0 + CanOpenXDD xdd = new CanOpenXDD(); + xdd.writeMultiXML(sfd.FileName, network); + break; + + case 2: // .nxdc V1.1 with actual value, denotation and deviceCommissioning info + CanOpenXDD_1_1 xdc_1_1 = new CanOpenXDD_1_1(); + xdc_1_1.WriteMultiXML(sfd.FileName, network, this.gitVersion, true); + break; + + case 1: // .nxdd V1.1 + CanOpenXDD_1_1 xdd_1_1 = new CanOpenXDD_1_1(); + xdd_1_1.WriteMultiXML(sfd.FileName, network, this.gitVersion, false); + break; + } + } + } + + private void loadNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) + { + + OpenFileDialog odf = new OpenFileDialog(); + odf.Filter = "All supported files (*.nxdd;*.nxdc;*.nxml)|*.nxdd;*.nxdc;*.nxml|" + + "CANopen Network XDD (*.nxdd)|*.nxdd|" + + "CANopen Network XDC (*.nxdc)|*.nxdc|" + + "CANopenNode network XML, old (*.nxml)|*.nxml"; + + if (odf.ShowDialog() == DialogResult.OK) + { + switch (Path.GetExtension(odf.FileName).ToLower()) + { + case ".nxml": + openNetworkfile(odf.FileName); + break; + + case ".nxdd": + case ".nxdc": + openXDDNetworkfile(odf.FileName); + + break; + } + } + } + + private void openXDDNetworkfile(string file) + { + CanOpenXDD_1_1 xdd_1_1 = new CanOpenXDD_1_1(); + List edss = xdd_1_1.ReadMultiXML(file); + + if (edss == null) + { + CanOpenXDD xdd = new CanOpenXDD(); + edss = xdd.readMultiXML(file); + + if (edss == null) + return; + } + + foreach (EDSsharp eds in edss) + { + + tabControl1.TabPages.Add(eds.di.ProductName); + + DeviceView device = new DeviceView(eds, network); + + tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + device.Dock = DockStyle.Fill; + + network.Add(eds); + eds.OnDataDirty += Eds_onDataDirty; + + device.dispatch_updateOD(); + } + + addtoMRU(file); + networkfilename = file; + + } + + private void openNetworkfile(string file) + { + NetworkXML net = new NetworkXML(); + List devs = net.readXML(file); + + foreach (Device d in devs) + { + Bridge b = new Bridge(); + + EDSsharp eds = b.convert(d); + //eds.filename = path; //fixme: We need to save the projectfilename or SaveAs will throw an exception + + tabControl1.TabPages.Add(eds.di.ProductName); + + + DeviceView device = new DeviceView(eds, network); + + tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + device.Dock = DockStyle.Fill; + + network.Add(eds); + eds.OnDataDirty += Eds_onDataDirty; + + device.dispatch_updateOD(); + + addtoMRU(file); + } + + networkfilename = file; + } + + private void networkPDOToolStripMenuItem_Click(object sender, EventArgs e) + { + + + string dir = GetTemporaryDirectory(); + + string csspath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".edseditor"); + csspath = Path.Combine(csspath, "style.css"); + + if (!System.IO.File.Exists(csspath)) + { + csspath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "style.css"); + } + + if (System.IO.File.Exists(csspath)) + { + System.IO.File.Copy(csspath, dir + Path.DirectorySeparatorChar + "style.css"); + } + + string temp = dir + Path.DirectorySeparatorChar + "network.html"; + + NetworkPDOreport npr = new NetworkPDOreport(); + npr.gennetpdodoc(temp, network); + + if (IsRunningOnMono()) + { + System.Diagnostics.Process.Start("file://"+temp); + } + else + { + ReportView rv = new ReportView(temp); + rv.Show(); + } + } + + public string GetTemporaryDirectory() + { + string tempDirectory; + + do + { + tempDirectory = Path.Combine(Path.GetTempPath(), Path.GetRandomFileName()); + + } while (Directory.Exists(tempDirectory)); + + Directory.CreateDirectory(tempDirectory); + return tempDirectory; + } + + public static bool IsRunningOnMono() + { + return Type.GetType("Mono.Runtime") != null; + } + + private void documentationToolStripMenuItem_Click(object sender, EventArgs e) + { + try + { + + Warnings.warning_list.Clear(); + + if (tabControl1.SelectedTab != null) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + SaveFileDialog sfd = new SaveFileDialog(); + + string dir = GetTemporaryDirectory(); + + + string csspath = Path.Combine(System.Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".edseditor"); + csspath = Path.Combine(csspath, "style.css"); + + if (!System.IO.File.Exists(csspath)) + { + csspath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "style.css"); + } + + if (System.IO.File.Exists(csspath)) + { + System.IO.File.Copy(csspath, dir + Path.DirectorySeparatorChar + "style.css"); + } + + string temp = dir + Path.DirectorySeparatorChar + "documentation.html"; + string temp2 = dir + Path.DirectorySeparatorChar + "documentation.md"; + + this.UseWaitCursor = true; + + DocumentationGen docgen = new DocumentationGen(); + docgen.genhtmldoc(temp, dv.eds); + docgen.genmddoc(temp2, dv.eds, this.gitVersion); + System.Diagnostics.Process.Start("file://" + temp2); + if (IsRunningOnMono()) + { + System.Diagnostics.Process.Start("file://" + temp); + } + else + { + ReportView rv = new ReportView(temp); + rv.Show(); + } + + this.UseWaitCursor = false; + + } + } + catch (Exception ex) + { + Warnings.warning_list.Add(ex.ToString()); + } + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + } + + private void saveExportAllToolStripMenuItem_Click(object sender, EventArgs e) + { + if (tabControl1.SelectedTab != null) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + int cnt = 0; + + if (dv.eds.xddfilename_1_1 != "" && dv.eds.xddfilename_1_1 == dv.eds.projectFilename) + { + dosave(dv, dv.eds.xddfilename_1_1, true); + } + else + { + MessageBox.Show("Please save project file at least once!"); + return; + } + + if (dv.eds.edsfilename != null && dv.eds.edsfilename != "") + { + dv.eds.Savefile(dv.eds.edsfilename, InfoSection.Filetype.File_EDS); + cnt++; + } + + if (dv.eds.dcffilename != null && dv.eds.dcffilename != "") + { + dv.eds.Savefile(dv.eds.dcffilename, InfoSection.Filetype.File_DCF); + cnt++; + } + + if (dv.eds.mdfilename != null && dv.eds.mdfilename != "") + { + DocumentationGen docgen = new DocumentationGen(); + docgen.genmddoc(dv.eds.mdfilename, dv.eds, this.gitVersion); + cnt++; + } + + if (dv.eds.ODfilename != null && dv.eds.ODfilename != "") + { + ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; + string version = (type == ExporterFactory.Exporter.CANOPENNODE_V4) ? "V4" : "V1"; + + if (dv.eds.ODfileVersion == version) + { + exportCanOpenNode(dv, dv.eds.ODfilename, type); + } + else + { + // exporter type changed in preferences + dv.eds.ODfilename = ""; + dv.eds.ODfileVersion = ""; + dv.dispatch_updatedevice(); + MessageBox.Show("CANopenNode exporter changed. Please export manually at least once!"); + } + cnt++; + } + + if (cnt == 0) + { + MessageBox.Show("Nothing exported. Please use 'Export...' at least once!"); + } + + dv.eds.Dirty = false; + } + } + + private void ODEditor_MainForm_FormClosing(object sender, FormClosingEventArgs e) + { + + foreach (TabPage page in tabControl1.TabPages) + { + foreach (Control c in page.Controls) + { + if (c.GetType() == typeof(DeviceView)) + { + DeviceView d = (DeviceView)c; + if (d.eds.Dirty == true) + { + if(MessageBox.Show("Warning you have unsaved changes\n Do you wish to continue","Unsaved changes",MessageBoxButtons.YesNo)==DialogResult.No) + { + e.Cancel = true; + return; + } + } + + } + + } + + } + } + + private bool fileTypeSupported(string fileName) + { + bool typeSupported = false; + if (Path.HasExtension(fileName)) + { + switch (Path.GetExtension(fileName).ToLower()) + { + case ".xdd": + case ".xdc": + case ".xpd": + case ".xml": + case ".eds": + case ".dcf": + case ".nxdd": + case ".nxdc": + case ".nxml": + typeSupported = true; + break; + } + } + + return typeSupported; + + } + + private void ODEditor_MainForm_DragEnter(object sender, DragEventArgs e) + { + this.Activate(); + bool unsupportedFile = false; + var data = e.Data.GetData(DataFormats.FileDrop); + if (data != null && data.GetType()==typeof(String)) + { + var rawFileNames = data as string[]; + if (rawFileNames.Length > 0) + { + var fileNames = rawFileNames.Distinct(); + foreach (string fileName in fileNames) + { + if(fileTypeSupported(fileName) == false) + { + unsupportedFile = true; + break; + } + } + + } + + toolTipsString = (unsupportedFile ? "1 or more files not supported" : "Drop files here to open"); + + if (unsupportedFile) + { + e.Effect = DragDropEffects.None; + } + else + { + e.Effect = DragDropEffects.All; + } + + enableDragDropTooltip(); + + } + + else + { + e.Effect = DragDropEffects.None; + //disableDragDropTooltip(); + enableDragDropTooltip(); + } + + } + + private void enableDragDropTooltip() + { + toolTip1.Active = true; + toolTip1.ReshowDelay = 0; + toolTip1.InitialDelay = 0; + toolTip1.UseAnimation = false; + toolTip1.UseFading = false; + toolTip1.Show(toolTipsString, this, this.PointToClient(Cursor.Position).X, this.PointToClient(Cursor.Position).Y); + } + + private void disableDragDropTooltip() + { + toolTip1.Active = false; + } + + private void ODEditor_MainForm_DragLeave(object sender, EventArgs e) + { + disableDragDropTooltip(); + } + + private void ODEditor_MainForm_DragDrop(object sender, DragEventArgs e) + { + var data = e.Data.GetData(DataFormats.FileDrop); + if (data != null) + { + var rawFileNames = data as string[]; + + if (rawFileNames.Length > 0) + { + var fileNames = rawFileNames.Distinct(); + foreach (string fileName in fileNames) + { + switch (Path.GetExtension(fileName).ToLower()) + { + case ".xpd": + case ".xdc": + case ".xdd": + openXDDfile(fileName); + break; + + case ".xml": + openXMLfile(fileName); + break; + + case ".eds": + openEDSfile(fileName, InfoSection.Filetype.File_EDS); + break; + + case ".dcf": + openEDSfile(fileName, InfoSection.Filetype.File_DCF); + break; + + case ".nxml": + openNetworkfile(fileName); + break; + + case ".nxdc": + case ".nxdd": + openXDDNetworkfile(fileName); + break; + + default: + break; + + } + + addtoMRU(fileName); + } + } + } + disableDragDropTooltip(); + } + + private void ODEditor_MainForm_QueryContinueDrag(object sender, QueryContinueDragEventArgs e) + { + if(e.EscapePressed) + { + e.Action = DragAction.Cancel; + disableDragDropTooltip(); + } + } + + private void ODEditor_MainForm_Leave(object sender, EventArgs e) + { + disableDragDropTooltip(); + } + + private void ODEditor_MainForm_DragOver(object sender, DragEventArgs e) + { + enableDragDropTooltip(); + } + + private void preferencesToolStripMenuItem_Click(object sender, EventArgs e) + { + Preferences p = new Preferences(); + p.ShowDialog(); + } + } +} diff --git a/EDSEditorGUI/InsertObjects.Designer.cs b/EDSEditorGUI/InsertObjects.Designer.cs index 82a1a0fa..10194b99 100644 --- a/EDSEditorGUI/InsertObjects.Designer.cs +++ b/EDSEditorGUI/InsertObjects.Designer.cs @@ -1,33 +1,33 @@ -namespace ODEditor -{ - partial class InsertObjects - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { +namespace ODEditor +{ + partial class InsertObjects + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InsertObjects)); this.label2 = new System.Windows.Forms.Label(); this.textBox_offsets = new System.Windows.Forms.TextBox(); @@ -35,13 +35,15 @@ private void InitializeComponent() this.button_cancel = new System.Windows.Forms.Button(); this.dataGridView = new System.Windows.Forms.DataGridView(); this.button_uncheck = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.cbox_Target = new System.Windows.Forms.ComboBox(); ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit(); this.SuspendLayout(); // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(12, 9); + this.label2.Location = new System.Drawing.Point(12, 54); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(290, 13); this.label2.TabIndex = 4; @@ -51,7 +53,7 @@ private void InitializeComponent() // this.textBox_offsets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_offsets.Location = new System.Drawing.Point(12, 25); + this.textBox_offsets.Location = new System.Drawing.Point(12, 70); this.textBox_offsets.Name = "textBox_offsets"; this.textBox_offsets.Size = new System.Drawing.Size(432, 20); this.textBox_offsets.TabIndex = 2; @@ -62,7 +64,7 @@ private void InitializeComponent() // button_insert // this.button_insert.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.button_insert.Location = new System.Drawing.Point(154, 345); + this.button_insert.Location = new System.Drawing.Point(154, 401); this.button_insert.Name = "button_insert"; this.button_insert.Size = new System.Drawing.Size(130, 37); this.button_insert.TabIndex = 6; @@ -73,7 +75,7 @@ private void InitializeComponent() // button_cancel // this.button_cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.button_cancel.Location = new System.Drawing.Point(314, 345); + this.button_cancel.Location = new System.Drawing.Point(314, 401); this.button_cancel.Name = "button_cancel"; this.button_cancel.Size = new System.Drawing.Size(130, 37); this.button_cancel.TabIndex = 7; @@ -92,9 +94,9 @@ private void InitializeComponent() this.dataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells; this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; this.dataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.dataGridView.Location = new System.Drawing.Point(12, 51); + this.dataGridView.Location = new System.Drawing.Point(12, 96); this.dataGridView.Name = "dataGridView"; - this.dataGridView.Size = new System.Drawing.Size(432, 283); + this.dataGridView.Size = new System.Drawing.Size(432, 294); this.dataGridView.TabIndex = 10; this.dataGridView.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.DataGridView_ColumnHeaderMouseClick); this.dataGridView.Leave += new System.EventHandler(this.DataGridView_Leave); @@ -102,7 +104,7 @@ private void InitializeComponent() // button_uncheck // this.button_uncheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.button_uncheck.Location = new System.Drawing.Point(12, 345); + this.button_uncheck.Location = new System.Drawing.Point(12, 401); this.button_uncheck.Name = "button_uncheck"; this.button_uncheck.Size = new System.Drawing.Size(130, 37); this.button_uncheck.TabIndex = 11; @@ -110,11 +112,31 @@ private void InitializeComponent() this.button_uncheck.UseVisualStyleBackColor = true; this.button_uncheck.Click += new System.EventHandler(this.button_uncheck_Click); // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 13); + this.label1.TabIndex = 12; + this.label1.Text = "Target"; + // + // cbox_Target + // + this.cbox_Target.FormattingEnabled = true; + this.cbox_Target.Location = new System.Drawing.Point(12, 25); + this.cbox_Target.Name = "cbox_Target"; + this.cbox_Target.Size = new System.Drawing.Size(432, 21); + this.cbox_Target.TabIndex = 13; + this.cbox_Target.SelectedIndexChanged += new System.EventHandler(this.cbox_Target_SelectedIndexChanged); + // // InsertObjects // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(456, 394); + this.ClientSize = new System.Drawing.Size(456, 450); + this.Controls.Add(this.cbox_Target); + this.Controls.Add(this.label1); this.Controls.Add(this.button_uncheck); this.Controls.Add(this.dataGridView); this.Controls.Add(this.button_cancel); @@ -128,14 +150,16 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - private System.Windows.Forms.Label label2; - private System.Windows.Forms.TextBox textBox_offsets; - private System.Windows.Forms.Button button_insert; - private System.Windows.Forms.Button button_cancel; + } + + #endregion + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox_offsets; + private System.Windows.Forms.Button button_insert; + private System.Windows.Forms.Button button_cancel; private System.Windows.Forms.DataGridView dataGridView; private System.Windows.Forms.Button button_uncheck; - } + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox cbox_Target; + } } \ No newline at end of file diff --git a/EDSEditorGUI/InsertObjects.cs b/EDSEditorGUI/InsertObjects.cs index 8e48b05e..2abff3a5 100644 --- a/EDSEditorGUI/InsertObjects.cs +++ b/EDSEditorGUI/InsertObjects.cs @@ -1,231 +1,241 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius - Copyright(c) 2020 Janez Paternoster -*/ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Windows.Forms; -using libEDSsharp; - -namespace ODEditor -{ - public partial class InsertObjects : Form - { - readonly EDSsharp eds; - readonly SortedDictionary srcObjects; - readonly bool[] enabled; - readonly int dataGridView_InitialColumnCount; - List offsets; - - /// - /// Display form to: specify offset(s), insert clone of selected srcObjects into existing eds - /// - /// - /// - public InsertObjects(EDSsharp eds, SortedDictionary srcObjects, string initialOffset) - { - this.eds = eds; - this.srcObjects = srcObjects; - - InitializeComponent(); - textBox_offsets.Text = initialOffset; - - dataGridView.Columns.Add(new DataGridViewCheckBoxColumn() - { - Name = "Insert", - FalseValue = false, - TrueValue = true, - Visible = true - }); - int idx = dataGridView.Columns.Add("Original Object", "Original Object"); - dataGridView.Columns[idx].ReadOnly = true; - dataGridView_InitialColumnCount = dataGridView.ColumnCount; - - enabled = new bool[srcObjects.Count]; - for(int i = 0; i < enabled.Length; i++) - enabled[i] = true; - - Verify(initialOffset == "0"); - - DialogResult = DialogResult.Cancel; - } - - private void Button_cancel_Click(object sender, EventArgs e) - { - Close(); - } - - private bool Verify(bool InitiallyDisableIfError = false) - { - /* get offests */ - offsets = new List(); - string[] str = textBox_offsets.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string s in str) - { - try - { - int value = (int)new System.ComponentModel.Int32Converter().ConvertFromString(s); - offsets.Add(value); - } - catch (Exception) - { - MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers."); - return false; - } - } - - // write column headers - int colIdx = dataGridView_InitialColumnCount; - dataGridView.ColumnCount = colIdx + offsets.Count; - foreach (int o in offsets) - { - dataGridView.Columns[colIdx].Name = $"Offset {o}"; - dataGridView.Columns[colIdx++].ReadOnly = true; - } - - // write rows and verify errors - bool newIndexesValid = true; - var newIndexes = new List(); - DataGridViewCellStyle styleErr = new DataGridViewCellStyle - { - Font = new Font(dataGridView.Font, FontStyle.Bold), - ForeColor = Color.Red - }; - - dataGridView.Rows.Clear(); - - int odIdx = 0; - foreach (ODentry od in srcObjects.Values) - { - int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {od.parameter_name}"); - int cellIdx = dataGridView_InitialColumnCount; - - foreach (int o in offsets) - { - int newIndex = (int)od.Index + o; - bool err = newIndex <= 0 || newIndex > 0xFFFF; - - dataGridView.Rows[rowIdx].Cells[cellIdx].Value = err ? $"{newIndex}" : $"0x{newIndex:X4}"; - - if (!err) - err = newIndexes.Contains(newIndex); - - if (!err) - { - newIndexes.Add(newIndex); - err = eds.ods.ContainsKey((UInt16)newIndex); - } - - if (err) - { - if (enabled[odIdx] && InitiallyDisableIfError) - { - dataGridView.Rows[rowIdx].Cells[0].Value = false; - enabled[odIdx] = false; - } - else if (enabled[odIdx]) - { - newIndexesValid = false; - } - dataGridView.Rows[rowIdx].Cells[cellIdx].Style = styleErr; - } - cellIdx++; - } - odIdx++; - } - - dataGridView.ClearSelection(); - - return newIndexesValid; - } - - private void Button_create_Click(object sender, EventArgs e) - { - if (Verify()) - { - // clone OD objects - int odIdx = 0; - foreach (ODentry od in srcObjects.Values) - { - if (enabled[odIdx]) - { - foreach (int o in offsets) - { - UInt16 newIndex = (UInt16)(od.Index + o); - ODentry newObject = od.Clone(); - newObject.Index = newIndex; - - eds.ods.Add(newIndex, newObject); - } - } - odIdx++; - } - - DialogResult = DialogResult.OK; - Close(); - } - } - - private void TextBox_offsets_KeyPress(object sender, KeyPressEventArgs e) - { - if (e.KeyChar == ' ' || e.KeyChar == '\r') - { - Verify(); - } - } - - private void TextBox_offsets_Leave(object sender, EventArgs e) - { - Verify(); - } - - private void DataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) - { - // toggle selection on click on first column - if (e.ColumnIndex == 0) - { - dataGridView.ClearSelection(); - dataGridView.CurrentCell = null; - foreach (DataGridViewRow row in dataGridView.Rows) - { - row.Cells[0].Value = !((bool)row.Cells[0].Value); - } - } - } - - private void DataGridView_Leave(object sender, EventArgs e) - { - // recalculate enabled[] - dataGridView.ClearSelection(); - dataGridView.CurrentCell = null; - int odIdx = 0; - foreach (DataGridViewRow row in dataGridView.Rows) - { - enabled[odIdx++] = (bool)row.Cells[0].Value; - } +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius + Copyright(c) 2020 Janez Paternoster +*/ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Windows.Forms; +using libEDSsharp; + +namespace ODEditor +{ + public partial class InsertObjects : Form + { + private EDSsharp eds; + readonly SortedDictionary srcObjects; + readonly bool[] enabled; + readonly int dataGridView_InitialColumnCount; + List network; + List offsets; + + /// + /// Display form to: specify offset(s), insert clone of selected srcObjects into existing eds + /// + /// + /// + public InsertObjects(EDSsharp eds, List network, SortedDictionary srcObjects, string initialOffset) + { + this.eds = eds; + this.srcObjects = srcObjects; + this.network = network; + + InitializeComponent(); + + cbox_Target.Items.Clear(); + foreach(var item in network) + { + cbox_Target.Items.Add(item.di.ProductName); + } + cbox_Target.SelectedItem = eds.di.ProductName; + + textBox_offsets.Text = initialOffset; + + dataGridView.Columns.Add(new DataGridViewCheckBoxColumn() + { + Name = "Insert", + FalseValue = false, + TrueValue = true, + Visible = true + }); + int idx = dataGridView.Columns.Add("Original Object", "Original Object"); + dataGridView.Columns[idx].ReadOnly = true; + dataGridView_InitialColumnCount = dataGridView.ColumnCount; + + enabled = new bool[srcObjects.Count]; + for(int i = 0; i < enabled.Length; i++) + enabled[i] = true; + + Verify(initialOffset == "0"); + + DialogResult = DialogResult.Cancel; + } + + private void Button_cancel_Click(object sender, EventArgs e) + { + Close(); + } + + private bool Verify(bool InitiallyDisableIfError = false) + { + /* get offests */ + offsets = new List(); + string[] str = textBox_offsets.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string s in str) + { + try + { + int value = (int)new System.ComponentModel.Int32Converter().ConvertFromString(s); + offsets.Add(value); + } + catch (Exception) + { + MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers."); + return false; + } + } + + // write column headers + int colIdx = dataGridView_InitialColumnCount; + dataGridView.ColumnCount = colIdx + offsets.Count; + foreach (int o in offsets) + { + dataGridView.Columns[colIdx].Name = $"Offset {o}"; + dataGridView.Columns[colIdx++].ReadOnly = true; + } + + // write rows and verify errors + bool newIndexesValid = true; + var newIndexes = new List(); + DataGridViewCellStyle styleErr = new DataGridViewCellStyle + { + Font = new Font(dataGridView.Font, FontStyle.Bold), + ForeColor = Color.Red + }; + + dataGridView.Rows.Clear(); + + int odIdx = 0; + foreach (ODentry od in srcObjects.Values) + { + int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {od.parameter_name}"); + int cellIdx = dataGridView_InitialColumnCount; + + foreach (int o in offsets) + { + int newIndex = (int)od.Index + o; + bool err = newIndex <= 0 || newIndex > 0xFFFF; + + dataGridView.Rows[rowIdx].Cells[cellIdx].Value = err ? $"{newIndex}" : $"0x{newIndex:X4}"; + + if (!err) + err = newIndexes.Contains(newIndex); + + if (!err) + { + newIndexes.Add(newIndex); + err = eds.ods.ContainsKey((UInt16)newIndex); + } + + if (err) + { + if (enabled[odIdx] && InitiallyDisableIfError) + { + dataGridView.Rows[rowIdx].Cells[0].Value = false; + enabled[odIdx] = false; + } + else if (enabled[odIdx]) + { + newIndexesValid = false; + } + dataGridView.Rows[rowIdx].Cells[cellIdx].Style = styleErr; + } + cellIdx++; + } + odIdx++; + } + + dataGridView.ClearSelection(); + + return newIndexesValid; + } + + private void Button_create_Click(object sender, EventArgs e) + { + if (Verify()) + { + // clone OD objects + int odIdx = 0; + foreach (ODentry od in srcObjects.Values) + { + if (enabled[odIdx]) + { + foreach (int o in offsets) + { + UInt16 newIndex = (UInt16)(od.Index + o); + ODentry newObject = od.Clone(); + newObject.Index = newIndex; + + eds.ods.Add(newIndex, newObject); + } + } + odIdx++; + } + + DialogResult = DialogResult.OK; + Close(); + } + } + + private void TextBox_offsets_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == ' ' || e.KeyChar == '\r') + { + Verify(); + } + } + + private void TextBox_offsets_Leave(object sender, EventArgs e) + { + Verify(); + } + + private void DataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) + { + // toggle selection on click on first column + if (e.ColumnIndex == 0) + { + dataGridView.ClearSelection(); + dataGridView.CurrentCell = null; + foreach (DataGridViewRow row in dataGridView.Rows) + { + row.Cells[0].Value = !((bool)row.Cells[0].Value); + } + } + } + + private void DataGridView_Leave(object sender, EventArgs e) + { + // recalculate enabled[] + dataGridView.ClearSelection(); + dataGridView.CurrentCell = null; + int odIdx = 0; + foreach (DataGridViewRow row in dataGridView.Rows) + { + enabled[odIdx++] = (bool)row.Cells[0].Value; + } } private void button_uncheck_Click(object sender, EventArgs e) { - int odIdx = 0; - foreach (DataGridViewRow item in dataGridView.Rows) + int odIdx = 0; + foreach (DataGridViewRow item in dataGridView.Rows) { DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)item.Cells[0]; @@ -233,5 +243,27 @@ private void button_uncheck_Click(object sender, EventArgs e) enabled[odIdx++] = false; } } - } -} + + private void cbox_Target_SelectedIndexChanged(object sender, EventArgs e) + { + EDSsharp edsBefore = eds; + foreach (var item in network) + { + if((string)cbox_Target.SelectedItem == item.di.ProductName) + { + this.eds = item; + break; + } + } + if(this.eds != null && this.eds != edsBefore) + { + Verify(false); + } + } + + public EDSsharp GetModifiedEDS() + { + return this.eds; + } + } +} From 292d620a5c9f022f44fa9b125ca05c4ce4708ecd Mon Sep 17 00:00:00 2001 From: Michael Menzi Date: Tue, 23 May 2023 10:30:08 +0200 Subject: [PATCH 086/226] MainForm gets notified about changes in the OD of an EDS and dispatches the updateOD in the corresponding deviceView. --- EDSEditorGUI/DeviceODView.cs | 6 ++++++ EDSEditorGUI/DeviceView.cs | 12 ++++++++++++ EDSEditorGUI/EDSEditorGUI.csproj | 1 + EDSEditorGUI/Form1.cs | 28 ++++++++++++++++++++++++++- EDSEditorGUI/UpdateODViewEventArgs.cs | 19 ++++++++++++++++++ 5 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 EDSEditorGUI/UpdateODViewEventArgs.cs diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index 8c8f94b4..d5436863 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -39,6 +39,8 @@ public partial class DeviceODView : MyTabUserControl bool justUpdating = false; bool ExporterOld = false; bool ExporterV4 = false; + + public event EventHandler UpdateODViewForEDS; public DeviceODView() { @@ -679,6 +681,10 @@ private void ContextMenu_object_clone_ToolStripMenuItem_Click(object sender, Eve PopulateSubList(); PopulateObject(); } + else + { + UpdateODViewForEDS?.Invoke(this, new UpdateODViewEventArgs(modifiedEds)); + } } } } diff --git a/EDSEditorGUI/DeviceView.cs b/EDSEditorGUI/DeviceView.cs index 375329eb..51f001db 100644 --- a/EDSEditorGUI/DeviceView.cs +++ b/EDSEditorGUI/DeviceView.cs @@ -30,6 +30,8 @@ public partial class DeviceView : MyTabUserControl readonly public EDSsharp eds; readonly private List network; + public event EventHandler UpdateODViewForEDS; + public DeviceView(EDSsharp eds_target, List network) { eds = eds_target; @@ -38,6 +40,7 @@ public DeviceView(EDSsharp eds_target, List network) InitializeComponent(); this.deviceODView1.network = network; + this.deviceODView1.UpdateODViewForEDS += DeviceODView1_UpdateODView; foreach (TabPage tp in tabControl1.TabPages) { @@ -59,6 +62,15 @@ public DeviceView(EDSsharp eds_target, List network) } + private void DeviceODView1_UpdateODView(object sender, UpdateODViewEventArgs e) + { + EventHandler handler = UpdateODViewForEDS; + if(handler != null) + { + handler(this, e); + } + } + #region UpdateDispatchEvents // This region handles update requests that are dispatched to the various user controls on the tabs diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index d7dff2c9..a5de6e21 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -152,6 +152,7 @@ Component + Form diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 316416ec..5e36270b 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -26,6 +26,7 @@ You should have received a copy of the GNU General Public License using System.IO; using libEDSsharp; using Xml2CSharp; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace ODEditor { @@ -183,6 +184,7 @@ private void openEDSfile(string path,InfoSection.Filetype ft) DeviceView device = new DeviceView(eds, network); + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; tabControl1.TabPages.Add(eds.di.ProductName); @@ -337,6 +339,7 @@ private void openXDDfile(string path) DeviceView device = new DeviceView(eds, network); + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); @@ -382,7 +385,7 @@ private void openXMLfile(string path) tabControl1.TabPages.Add(eds.di.ProductName); DeviceView device = new DeviceView(eds, network); - + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); @@ -405,6 +408,26 @@ private void openXMLfile(string path) } + private void Device_UpdateODViewForEDS(object sender, UpdateODViewEventArgs e) + { + foreach (TabPage page in tabControl1.TabPages) + { + foreach (Control c in page.Controls) + { + if (c.GetType() == typeof(DeviceView)) + { + DeviceView d = (DeviceView)c; + if (d.eds == e.EDS) + { + d.dispatch_updateOD(); + } + } + + } + } + } + + private void Eds_onDataDirty(bool dirty, EDSsharp sender) { foreach(TabPage page in tabControl1.TabPages) @@ -648,6 +671,7 @@ private void newToolStripMenuItem_Click(object sender, EventArgs e) tabControl1.TabPages.Add(eds.di.ProductName); DeviceView device = new DeviceView(eds, network); + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; @@ -896,6 +920,7 @@ private void openXDDNetworkfile(string file) device.Dock = DockStyle.Fill; network.Add(eds); + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; device.dispatch_updateOD(); @@ -927,6 +952,7 @@ private void openNetworkfile(string file) device.Dock = DockStyle.Fill; network.Add(eds); + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; device.dispatch_updateOD(); diff --git a/EDSEditorGUI/UpdateODViewEventArgs.cs b/EDSEditorGUI/UpdateODViewEventArgs.cs new file mode 100644 index 00000000..e71a3ff8 --- /dev/null +++ b/EDSEditorGUI/UpdateODViewEventArgs.cs @@ -0,0 +1,19 @@ +using libEDSsharp; +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +namespace ODEditor +{ + public class UpdateODViewEventArgs : EventArgs + { + public EDSsharp EDS { get; set; } + + public UpdateODViewEventArgs(EDSsharp eds) + { + EDS = eds; + } + } +} From 45e1d410c983860e844bcc6c4e3220a4634ca6fd Mon Sep 17 00:00:00 2001 From: Michael Menzi Date: Tue, 23 May 2023 10:37:42 +0200 Subject: [PATCH 087/226] Handling EDS target when inserting a profile from the main menu bar. --- EDSEditorGUI/Form1.cs | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 5e36270b..958679f9 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -159,12 +159,32 @@ void ProfileAddClick(object sender, EventArgs e) if (insObjForm.ShowDialog() == DialogResult.OK) { - dv.eds.Dirty = true; - dv.dispatch_updateOD(); - dv.dispatch_updatePDOinfo(); + EDSsharp modifiedEds = insObjForm.GetModifiedEDS(); + modifiedEds.Dirty = true; - dv.eds.UpdatePDOcount(); - dv.dispatch_updatedevice(); + if(modifiedEds == dv.eds) + { + dv.dispatch_updateOD(); + dv.dispatch_updatePDOinfo(); + + dv.eds.UpdatePDOcount(); + dv.dispatch_updatedevice(); + } + else + { + foreach(TabPage page in tabControl1.TabPages) + { + DeviceView devView = (DeviceView)page.Controls[0]; + if(devView.eds == modifiedEds) + { + devView.dispatch_updateOD(); + devView.dispatch_updatePDOinfo(); + + devView.eds.UpdatePDOcount(); + devView.dispatch_updatedevice(); + } + } + } } } } From 3e780c0fd05296f2fbae8bd7d22854ae50cad891 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 23 May 2023 15:05:18 +0200 Subject: [PATCH 088/226] Merge artifact deleted --- EDSEditorGUI/DeviceODView.cs | 1 - 1 file changed, 1 deletion(-) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index a36f84bd..c3a94824 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -165,7 +165,6 @@ private bool Checkdirty() } return result; - } return false; } private void ComboBoxSet(ComboBox comboBox, string item) From c74067bf2d73f8aa6af237a47a270a39d8a99b09 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Fri, 26 May 2023 19:12:00 +0200 Subject: [PATCH 089/226] changed bootstrap from dotnet 4.5 -> 4.8 --- EDSEditorGUI/EDSEditorGUI.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index a5de6e21..0c34e458 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -234,9 +234,9 @@ - + False - Microsoft .NET Framework 4.5 %28x86 and x64%29 + Microsoft .NET Framework 4.8 %28x86 and x64%29 true From c6033b6d5945813215f77090a119356f4078202d Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Fri, 26 May 2023 19:12:37 +0200 Subject: [PATCH 090/226] maybe windows-latest will work now --- .github/workflows/dotnet.yml | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index a72ac2e3..5e96e36f 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -9,8 +9,7 @@ on: jobs: build: - runs-on: windows-2019 -# runs-on: windows-latest # error MSB3644: The reference assemblies for .NETFramework,Version=v4.5 were not found. + runs-on: windows-latest # runs-on: ubuntu-latest # Error: setup-msbuild can only be run on Windows runners steps: - name: Checkout From 7bee03997ae3b125fa685dc447411c490710059a Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 12 Jun 2023 15:22:29 +0200 Subject: [PATCH 091/226] Framework to 4.8 --- EDSEditorGUI/EDSEditorGUI.csproj | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 0c34e458..43bbd99a 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -12,6 +12,7 @@ v4.8 512 false + publish\ true Disk @@ -26,7 +27,6 @@ 1.0.0.%2a false true - AnyCPU @@ -47,6 +47,8 @@ TRACE prompt 4 + false + false Index_8287_16x.ico @@ -236,7 +238,7 @@ False - Microsoft .NET Framework 4.8 %28x86 and x64%29 + Microsoft .NET Framework 4.8 %28x86 und x64%29 true From 14e838fd4b4add0ecb8d495c79c98a34ab0939eb Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Wed, 5 Jul 2023 16:11:10 +0100 Subject: [PATCH 092/226] Some small fixes with the legacy exporter --- libEDSsharp/CanOpenNodeExporter.cs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index a4a4a2c8..24daa18f 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -580,6 +580,9 @@ TYPE DEFINITIONS FOR RECORDS od = maxTXmappingsOD; } + if (od == null) + continue; + List structmemberlist = new List(); file.WriteLine(string.Format("/*{0:X4} */ typedef struct {{", kvp.Key)); @@ -1119,6 +1122,14 @@ public byte getflags(ODentry od) flags |=0x40; } + if(od.parent!=null && od.parent.prop.CO_flagsPDO) + { + //parent types are storing the prop in the ODeditor in the parent object but the child object is tested to set the flag + //this is breaking legacy export + flags |= 0x40; + } + + int datasize = (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); if (datasize > 1) From afa8991831289a9587b5a42e224fa513d2bf415f Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Wed, 5 Jul 2023 16:12:05 +0100 Subject: [PATCH 093/226] If loading in legacy XML, convert object type REC to RECORD and try the enum parse incase it fails. --- libEDSsharp/Bridge.cs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/libEDSsharp/Bridge.cs b/libEDSsharp/Bridge.cs index de0ad2b2..f320313a 100644 --- a/libEDSsharp/Bridge.cs +++ b/libEDSsharp/Bridge.cs @@ -323,8 +323,18 @@ public EDSsharp convert(Device dev) } + //Fix for old CanOpen XML; + if (coo.ObjectType == "REC") + { + coo.ObjectType = "RECORD"; + } - entry.objecttype = (ObjectType)Enum.Parse(typeof(ObjectType), coo.ObjectType); + ObjectType oType; + if(Enum.TryParse(coo.ObjectType, out oType)) + { + //TDO Parsing failed, we should alert the user + } + entry.objecttype = oType; entry.defaultvalue = coo.DefaultValue; entry.HighLimit = coo.HighValue; From a5b012783aed1bb80c80e63de7c16e4520e93a45 Mon Sep 17 00:00:00 2001 From: Robin Cornelius Date: Wed, 5 Jul 2023 16:12:40 +0100 Subject: [PATCH 094/226] Include all dlls from the build folder in the setup --- setup.nsi | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup.nsi b/setup.nsi index 046fa29b..b40f83d5 100644 --- a/setup.nsi +++ b/setup.nsi @@ -59,7 +59,7 @@ Section "OpenEdsEditor" Secopeneds ;No components page, name is not important ; Put file there File EDSEditorGUI\bin\Release\EDSEditor.exe File EDSEditorGUI\bin\Release\EDSEditor.exe.config - File EDSEditorGUI\bin\Release\libEDSsharp.dll + File EDSEditorGUI\bin\Release\*.dll File EDSEditorGUI\bin\Release\style.css File Index_8287_16x.ico File License-GPLv3.txt From 6cee7706ef8c02c4f45e7eb68d2626692d175554 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 5 Jul 2023 17:32:00 +0200 Subject: [PATCH 095/226] Limiting the length of the objects to be mapped in a PDO to the maximum length of a CAN message (8 bytes) --- EDSEditorGUI/DevicePDOView2.cs | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 7f13067b..ac63dee7 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -440,7 +440,8 @@ public void UpdatePDOinfo(bool updatechoices = true) { if (isTXPDO != slot.isTXPDO()) continue; - + if (grid1.ColumnsCount > 64+3) + grid1.ColumnsCount = 64+3; grid1.Redim(grid1.RowsCount + 1, grid1.ColumnsCount); grid1.Rows[grid1.RowsCount - 1].Tag = slot; grid1.Rows[row + 2].Height = 30; @@ -477,9 +478,15 @@ public void UpdatePDOinfo(bool updatechoices = true) grid1[row + 2, bitoff + 3].AddController(vcc); bitoff += entry.Sizeofdatatype(); + } + + ordinal++; + + if (bitoff >= 64) { + MessageBox.Show(string.Format("Invalid TXPDO mapping parameters in 0x{0:X}. Trying to map more than 64 bit (8 Bytes). CAN message maximum lenght is 8 Byte", slot.ConfigurationIndex)); + break; } - ordinal++; } //Pad out with an empty combo From 30720994fdc3d675637f2a3d8321e5a168d02869 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 10 Jul 2023 12:21:53 +0200 Subject: [PATCH 096/226] Allow 64 Bit CAN message len --- EDSEditorGUI/DevicePDOView2.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index ac63dee7..ed6b2842 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -482,7 +482,7 @@ public void UpdatePDOinfo(bool updatechoices = true) ordinal++; - if (bitoff >= 64) { + if (bitoff > 64) { MessageBox.Show(string.Format("Invalid TXPDO mapping parameters in 0x{0:X}. Trying to map more than 64 bit (8 Bytes). CAN message maximum lenght is 8 Byte", slot.ConfigurationIndex)); break; } From 169e5790bea80e07171033dbf830cb81f9f3f347 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 15 Aug 2023 14:00:10 +0200 Subject: [PATCH 097/226] Bugfix drag&drop files Allow range "x-y" when cloning object. If an object name of an object to clone ends with a number, increase number with every added object --- EDSEditorGUI/Form1.cs | 8 ++-- EDSEditorGUI/Form1.resx | 2 +- EDSEditorGUI/InsertObjects.cs | 83 ++++++++++++++++++++++++++++++----- 3 files changed, 78 insertions(+), 15 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 0d55595c..a7804933 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -725,6 +725,7 @@ private void tabControl1_Controlsremoved(object sender, ControlEventArgs e) enablesavemenus(tabControl1.TabCount > 1); } + private void enablesavemenus(bool enable) { insertToolStripMenuItem.Enabled = enable; @@ -1215,14 +1216,14 @@ private bool fileTypeSupported(string fileName) return typeSupported; - } + } private void ODEditor_MainForm_DragEnter(object sender, DragEventArgs e) { this.Activate(); bool unsupportedFile = false; - var data = e.Data.GetData(DataFormats.FileDrop); - if (data != null && data.GetType()==typeof(String)) + string[] data = (string[]) e.Data.GetData(DataFormats.FileDrop); + if (data != null) { var rawFileNames = data as string[]; if (rawFileNames.Length > 0) @@ -1283,6 +1284,7 @@ private void ODEditor_MainForm_DragLeave(object sender, EventArgs e) disableDragDropTooltip(); } + private void ODEditor_MainForm_DragDrop(object sender, DragEventArgs e) { var data = e.Data.GetData(DataFormats.FileDrop); diff --git a/EDSEditorGUI/Form1.resx b/EDSEditorGUI/Form1.resx index c579fe98..29de9ad8 100644 --- a/EDSEditorGUI/Form1.resx +++ b/EDSEditorGUI/Form1.resx @@ -130,7 +130,7 @@ gqUTTxJHNd2gfCHts8Z5i7NeLLN6n/yF4ayxvMR1qkHEsYBFyBChoowNFOEgRrtBio0knUst/AOeXyaX Sq4NMHLMowQdiucH/4Pfs7VzE+N+UlgC2l9c92MYCO0CtYrrfh+7bu0ECD4DV0bDX6oC05+kVxpa9Ajo 2QYurhuaugdc7gD9T6ZiKZ4UpBJyOeD9jL4pA/TeAp2r/tzq5zh9AFI0q8QNcHAIjOQpe63Fuzua5/bn - HW9+kH4AMgFyjcd8GS4AAAAJcEhZcwAACxAAAAsQAa0jvXUAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF + HW9+kH4AMgFyjcd8GS4AAAAJcEhZcwAACw4AAAsOAUC+4UEAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF WHRDb21tZW50AENBTm9wZW7cllV1AAAC8UlEQVRYR9WWz2sTQRTHkx6SQy5RxFv1JDGHogiVIkqFEqLE QigetKY3iSUpPYh/gD8uoQiJIEKJ0UNNRZKjTaQiHozePAk21eagCC20NdW1plTa8X3f7mw3cZNuzSr6 hQ+8zn6/M29nZts6/hWdIu4T4xZJE2cJ23QvGAyKRCJhCXgp80CN2qNxTAyVP5QZZVXhn6H5mRlGCl5k diff --git a/EDSEditorGUI/InsertObjects.cs b/EDSEditorGUI/InsertObjects.cs index 2abff3a5..2b8b376c 100644 --- a/EDSEditorGUI/InsertObjects.cs +++ b/EDSEditorGUI/InsertObjects.cs @@ -21,6 +21,8 @@ You should have received a copy of the GNU General Public License using System; using System.Collections.Generic; using System.Drawing; +using System.Linq.Expressions; +using System.Text.RegularExpressions; using System.Windows.Forms; using libEDSsharp; @@ -84,23 +86,50 @@ private void Button_cancel_Click(object sender, EventArgs e) private bool Verify(bool InitiallyDisableIfError = false) { + String pattern = @"(\d+)\s*?([-])\s*?(\d+)"; /* get offests */ offsets = new List(); - string[] str = textBox_offsets.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string s in str) - { - try + + MatchCollection matches = System.Text.RegularExpressions.Regex.Matches(textBox_offsets.Text, pattern); + if (matches.Count != 0) { + foreach (System.Text.RegularExpressions.Match m in matches) { - int value = (int)new System.ComponentModel.Int32Converter().ConvertFromString(s); - offsets.Add(value); + int value1 = Int32.Parse(m.Groups[1].Value); + int value2 = Int32.Parse(m.Groups[3].Value); + + if ((value2 > value1) && (m.Groups[2].Value == "-")) + { + for (int i = value1; i <= value2; i++) + { + try + { + offsets.Add(i); + } + catch (Exception) + { + MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); + return false; + } + } + } } - catch (Exception) + } + else { + string[] str = textBox_offsets.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string s in str) { - MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers."); - return false; + try + { + int value = (int)new System.ComponentModel.Int32Converter().ConvertFromString(s); + offsets.Add(value); + } + catch (Exception) + { + MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); + return false; + } } } - // write column headers int colIdx = dataGridView_InitialColumnCount; dataGridView.ColumnCount = colIdx + offsets.Count; @@ -122,9 +151,27 @@ private bool Verify(bool InitiallyDisableIfError = false) dataGridView.Rows.Clear(); int odIdx = 0; + int j = 1; foreach (ODentry od in srcObjects.Values) { - int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {od.parameter_name}"); + String numpattern = @"(\w*\d+\Z)"; + string newname; + + string[] words = Regex.Split(od.parameter_name, numpattern); + // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); + if (words.Length > 1) + { + + // value1 = Int32.Parse(m.Groups[1].Value); + int nameidx = Int32.Parse(words[1]) + j++; + + newname = words[0] + nameidx;// nameidx.ToString ; + + } + else { + newname = od.parameter_name; + } + int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {newname}"); int cellIdx = dataGridView_InitialColumnCount; foreach (int o in offsets) @@ -139,6 +186,7 @@ private bool Verify(bool InitiallyDisableIfError = false) if (!err) { + newIndexes.Add(newIndex); err = eds.ods.ContainsKey((UInt16)newIndex); } @@ -172,6 +220,7 @@ private void Button_create_Click(object sender, EventArgs e) { // clone OD objects int odIdx = 0; + int i = 1; foreach (ODentry od in srcObjects.Values) { if (enabled[odIdx]) @@ -180,6 +229,18 @@ private void Button_create_Click(object sender, EventArgs e) { UInt16 newIndex = (UInt16)(od.Index + o); ODentry newObject = od.Clone(); + + String pattern = @"(\w*\d+\Z)"; + + string[] words = Regex.Split(od.parameter_name, pattern); + // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); + if (words.Length > 1) + { + int nameidx = Int32.Parse(words[1]) + i++; + newObject.parameter_name = words[0] + nameidx;// nameidx.ToString ; + + } + newObject.Index = newIndex; eds.ods.Add(newIndex, newObject); From ed03227a06278b4b4272e3ecff695060a5ccada6 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 16 Aug 2023 09:14:36 +0200 Subject: [PATCH 098/226] Bugfix clonig objects: Range operator evaluated too early --- EDSEditorGUI/InsertObjects.cs | 39 ++++++++++++++++++++--------------- 1 file changed, 22 insertions(+), 17 deletions(-) diff --git a/EDSEditorGUI/InsertObjects.cs b/EDSEditorGUI/InsertObjects.cs index 2b8b376c..cb03e41a 100644 --- a/EDSEditorGUI/InsertObjects.cs +++ b/EDSEditorGUI/InsertObjects.cs @@ -86,35 +86,40 @@ private void Button_cancel_Click(object sender, EventArgs e) private bool Verify(bool InitiallyDisableIfError = false) { - String pattern = @"(\d+)\s*?([-])\s*?(\d+)"; + String pattern = @"(\d+)\s*([-])\s*(\d+)"; /* get offests */ offsets = new List(); - MatchCollection matches = System.Text.RegularExpressions.Regex.Matches(textBox_offsets.Text, pattern); - if (matches.Count != 0) { - foreach (System.Text.RegularExpressions.Match m in matches) + if (textBox_offsets.Text.Contains("-")) + { + MatchCollection matches = System.Text.RegularExpressions.Regex.Matches(textBox_offsets.Text, pattern); + if (matches.Count != 0) { - int value1 = Int32.Parse(m.Groups[1].Value); - int value2 = Int32.Parse(m.Groups[3].Value); - - if ((value2 > value1) && (m.Groups[2].Value == "-")) + foreach (System.Text.RegularExpressions.Match m in matches) { - for (int i = value1; i <= value2; i++) + int value1 = Int32.Parse(m.Groups[1].Value); + int value2 = Int32.Parse(m.Groups[3].Value); + + if ((value2 > value1) && (m.Groups[2].Value == "-")) { - try + for (int i = value1; i <= value2; i++) { - offsets.Add(i); - } - catch (Exception) - { - MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); - return false; + try + { + offsets.Add(i); + } + catch (Exception) + { + MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); + return false; + } } } } } } - else { + else + { string[] str = textBox_offsets.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); foreach (string s in str) { From c9419d124634e3353a5d6c73d03498093f0a1e97 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Tue, 12 Sep 2023 10:37:11 +0200 Subject: [PATCH 099/226] Update GUI for Nodeguarding Objects --- EDSEditorGUI/DeviceInfoView.Designer.cs | 72 +++++++++++++++++++++---- libEDSsharp/CanOpenNodeExporter_V4.cs | 2 +- 2 files changed, 64 insertions(+), 10 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.Designer.cs b/EDSEditorGUI/DeviceInfoView.Designer.cs index 14e82f59..7264736a 100644 --- a/EDSEditorGUI/DeviceInfoView.Designer.cs +++ b/EDSEditorGUI/DeviceInfoView.Designer.cs @@ -100,6 +100,10 @@ private void InitializeComponent() this.label22 = new System.Windows.Forms.Label(); this.label20 = new System.Windows.Forms.Label(); this.label18 = new System.Windows.Forms.Label(); + this.checkBox_NG_Master = new System.Windows.Forms.CheckBox(); + this.checkBox_NG_Slave = new System.Windows.Forms.CheckBox(); + this.textBox_NG_NumOfNodes = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); this.panel1.SuspendLayout(); this.groupBox5.SuspendLayout(); this.groupBox6.SuspendLayout(); @@ -279,7 +283,7 @@ private void InitializeComponent() this.textBox_deviceedsname.ReadOnly = true; this.textBox_deviceedsname.Size = new System.Drawing.Size(300, 22); this.textBox_deviceedsname.TabIndex = 7; - // + // // groupBox6 // this.groupBox6.Controls.Add(this.label3); @@ -296,11 +300,11 @@ private void InitializeComponent() this.groupBox6.Controls.Add(this.textBox_nodename); this.groupBox6.Controls.Add(this.label32); this.groupBox6.Controls.Add(this.textBox_concretenodeid); - this.groupBox6.Location = new System.Drawing.Point(527, 258); + this.groupBox6.Location = new System.Drawing.Point(527, 385); this.groupBox6.Margin = new System.Windows.Forms.Padding(4); this.groupBox6.Name = "groupBox6"; this.groupBox6.Padding = new System.Windows.Forms.Padding(4); - this.groupBox6.Size = new System.Drawing.Size(452, 245); + this.groupBox6.Size = new System.Drawing.Size(452, 248); this.groupBox6.TabIndex = 5; this.groupBox6.TabStop = false; this.groupBox6.Text = "Device commissioning"; @@ -547,7 +551,7 @@ private void InitializeComponent() this.groupBox1.Margin = new System.Windows.Forms.Padding(4); this.groupBox1.Name = "groupBox1"; this.groupBox1.Padding = new System.Windows.Forms.Padding(4); - this.groupBox1.Size = new System.Drawing.Size(160, 236); + this.groupBox1.Size = new System.Drawing.Size(160, 271); this.groupBox1.TabIndex = 3; this.groupBox1.TabStop = false; this.groupBox1.Text = "Baudrates"; @@ -653,6 +657,10 @@ private void InitializeComponent() // // groupBox2 // + this.groupBox2.Controls.Add(this.textBox_NG_NumOfNodes); + this.groupBox2.Controls.Add(this.label10); + this.groupBox2.Controls.Add(this.checkBox_NG_Master); + this.groupBox2.Controls.Add(this.checkBox_NG_Slave); this.groupBox2.Controls.Add(this.textBox_granularity); this.groupBox2.Controls.Add(this.label1); this.groupBox2.Controls.Add(this.textBox_txpdos); @@ -665,7 +673,7 @@ private void InitializeComponent() this.groupBox2.Margin = new System.Windows.Forms.Padding(4); this.groupBox2.Name = "groupBox2"; this.groupBox2.Padding = new System.Windows.Forms.Padding(4); - this.groupBox2.Size = new System.Drawing.Size(284, 236); + this.groupBox2.Size = new System.Drawing.Size(284, 271); this.groupBox2.TabIndex = 4; this.groupBox2.TabStop = false; this.groupBox2.Text = "General and Master Features"; @@ -700,7 +708,7 @@ private void InitializeComponent() // checkBox_lssMaster // this.checkBox_lssMaster.AutoSize = true; - this.checkBox_lssMaster.Location = new System.Drawing.Point(13, 156); + this.checkBox_lssMaster.Location = new System.Drawing.Point(13, 158); this.checkBox_lssMaster.Margin = new System.Windows.Forms.Padding(4); this.checkBox_lssMaster.Name = "checkBox_lssMaster"; this.checkBox_lssMaster.Size = new System.Drawing.Size(98, 20); @@ -740,7 +748,7 @@ private void InitializeComponent() // checkBox_lss // this.checkBox_lss.AutoSize = true; - this.checkBox_lss.Location = new System.Drawing.Point(13, 134); + this.checkBox_lss.Location = new System.Drawing.Point(13, 136); this.checkBox_lss.Margin = new System.Windows.Forms.Padding(4); this.checkBox_lss.Name = "checkBox_lss"; this.checkBox_lss.Size = new System.Drawing.Size(92, 20); @@ -803,7 +811,7 @@ private void InitializeComponent() this.textBox_create_datetime.Name = "textBox_create_datetime"; this.textBox_create_datetime.Size = new System.Drawing.Size(300, 22); this.textBox_create_datetime.TabIndex = 4; - // + // // textBox_di_description // this.textBox_di_description.Location = new System.Drawing.Point(185, 57); @@ -880,6 +888,48 @@ private void InitializeComponent() this.label18.TabIndex = 18; this.label18.Text = "File version"; // + // checkBox_NG_Master + // + this.checkBox_NG_Master.AutoSize = true; + this.checkBox_NG_Master.Location = new System.Drawing.Point(13, 216); + this.checkBox_NG_Master.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_NG_Master.Name = "checkBox_NG_Master"; + this.checkBox_NG_Master.Size = new System.Drawing.Size(163, 20); + this.checkBox_NG_Master.TabIndex = 43; + this.checkBox_NG_Master.Text = "Node guarding Master"; + this.checkBox_NG_Master.UseVisualStyleBackColor = true; + // + // checkBox_NG_Slave + // + this.checkBox_NG_Slave.AutoSize = true; + this.checkBox_NG_Slave.Location = new System.Drawing.Point(13, 195); + this.checkBox_NG_Slave.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_NG_Slave.Name = "checkBox_NG_Slave"; + this.checkBox_NG_Slave.Size = new System.Drawing.Size(157, 20); + this.checkBox_NG_Slave.TabIndex = 42; + this.checkBox_NG_Slave.Text = "Node guarding Slave"; + this.checkBox_NG_Slave.UseVisualStyleBackColor = true; + // + // textBox_NG_NumOfNodes + // + this.textBox_NG_NumOfNodes.BackColor = System.Drawing.SystemColors.Window; + this.textBox_NG_NumOfNodes.Location = new System.Drawing.Point(165, 238); + this.textBox_NG_NumOfNodes.Margin = new System.Windows.Forms.Padding(4); + this.textBox_NG_NumOfNodes.Name = "textBox_NG_NumOfNodes"; + this.textBox_NG_NumOfNodes.ReadOnly = true; + this.textBox_NG_NumOfNodes.Size = new System.Drawing.Size(105, 22); + this.textBox_NG_NumOfNodes.TabIndex = 44; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(14, 241); + this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(143, 16); + this.label10.TabIndex = 45; + this.label10.Text = "No of monitored nodes"; + // // DeviceInfoView // this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); @@ -978,6 +1028,10 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_xddfilenameStripped; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; - private System.Windows.Forms.TextBox textBox_mdFileName; + private System.Windows.Forms.TextBox textBox_mdFileName; + private System.Windows.Forms.TextBox textBox_NG_NumOfNodes; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.CheckBox checkBox_NG_Master; + private System.Windows.Forms.CheckBox checkBox_NG_Slave; } } diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 366b8a1d..57962c66 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -268,7 +268,7 @@ private int Prepare_arr(ODentry od, string indexH, string varName, string group) attrElem = attr; } else - { + {// FixIt: There is nothing in the CiA 306 definition for EDS files that justifies these warnings! The EDSchecker from Vector would also check this object as error-free! if (data.cType != dataElem.cType || data.length != dataElem.length) Warnings.AddWarning($"Error in 0x{indexH}: Data type of elements in ARRAY must be equal!", Warnings.warning_class.WARNING_BUILD); if ((data.cValue == null && dataElem.cValue != null) || (data.cValue != null && dataElem.cValue == null)) From ad5da4c43001ff84901e9dbcc622350e34fef04d Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 15 Sep 2023 11:15:47 +0200 Subject: [PATCH 100/226] Add support for Node Guarding (not finished jet) Bugfix for #69 (Modules are parsed correct now, but the module view tab is not implemented, need fix) --- EDSEditorGUI/App.config | 4 +- EDSEditorGUI/DeviceInfoView.Designer.cs | 466 ++++++++----------- EDSEditorGUI/DeviceInfoView.cs | 32 +- EDSEditorGUI/DeviceODView.cs | 21 +- EDSEditorGUI/DeviceView.Designer.cs | 52 +-- EDSEditorGUI/DeviceView.cs | 4 +- EDSEditorGUI/DeviceView.resx | 2 +- EDSEditorGUI/EDSEditorGUI.csproj | 2 +- EDSEditorGUI/Properties/Settings.Designer.cs | 2 +- EDSSharp/App.config | 2 +- EDSSharp/EDSSharp.csproj | 2 +- libEDSsharp/CanOpenNodeExporter.cs | 9 + libEDSsharp/CanOpenXDD.cs | 1 + libEDSsharp/DocumentationGen.cs | 4 +- libEDSsharp/Properties/Resources.Designer.cs | 63 +++ libEDSsharp/Properties/Resources.resx | 101 ++++ libEDSsharp/docs/libEDSsharp.xml | 16 + libEDSsharp/eds.cs | 101 +++- libEDSsharp/libEDSsharp.csproj | 13 +- 19 files changed, 552 insertions(+), 345 deletions(-) create mode 100644 libEDSsharp/Properties/Resources.Designer.cs create mode 100644 libEDSsharp/Properties/Resources.resx diff --git a/EDSEditorGUI/App.config b/EDSEditorGUI/App.config index f0b21cff..66a11baa 100644 --- a/EDSEditorGUI/App.config +++ b/EDSEditorGUI/App.config @@ -6,8 +6,8 @@ - - + + diff --git a/EDSEditorGUI/DeviceInfoView.Designer.cs b/EDSEditorGUI/DeviceInfoView.Designer.cs index 7264736a..e88a0725 100644 --- a/EDSEditorGUI/DeviceInfoView.Designer.cs +++ b/EDSEditorGUI/DeviceInfoView.Designer.cs @@ -79,6 +79,10 @@ private void InitializeComponent() this.checkBox_baud_500 = new System.Windows.Forms.CheckBox(); this.checkBox_baud_800 = new System.Windows.Forms.CheckBox(); this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox_NG_NumOfNodes = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.checkBox_ngMaster = new System.Windows.Forms.CheckBox(); + this.checkBox_ngSlave = new System.Windows.Forms.CheckBox(); this.textBox_granularity = new System.Windows.Forms.TextBox(); this.label1 = new System.Windows.Forms.Label(); this.textBox_txpdos = new System.Windows.Forms.TextBox(); @@ -100,10 +104,6 @@ private void InitializeComponent() this.label22 = new System.Windows.Forms.Label(); this.label20 = new System.Windows.Forms.Label(); this.label18 = new System.Windows.Forms.Label(); - this.checkBox_NG_Master = new System.Windows.Forms.CheckBox(); - this.checkBox_NG_Slave = new System.Windows.Forms.CheckBox(); - this.textBox_NG_NumOfNodes = new System.Windows.Forms.TextBox(); - this.label10 = new System.Windows.Forms.Label(); this.panel1.SuspendLayout(); this.groupBox5.SuspendLayout(); this.groupBox6.SuspendLayout(); @@ -122,9 +122,8 @@ private void InitializeComponent() this.panel1.Controls.Add(this.groupBox2); this.panel1.Controls.Add(this.groupBox3); this.panel1.Location = new System.Drawing.Point(0, 0); - this.panel1.Margin = new System.Windows.Forms.Padding(4); this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(1031, 661); + this.panel1.Size = new System.Drawing.Size(773, 537); this.panel1.TabIndex = 60; // // groupBox5 @@ -143,11 +142,9 @@ private void InitializeComponent() this.groupBox5.Controls.Add(this.label31); this.groupBox5.Controls.Add(this.textBox_projectFileName); this.groupBox5.Controls.Add(this.textBox_deviceedsname); - this.groupBox5.Location = new System.Drawing.Point(16, 409); - this.groupBox5.Margin = new System.Windows.Forms.Padding(4); + this.groupBox5.Location = new System.Drawing.Point(12, 332); this.groupBox5.Name = "groupBox5"; - this.groupBox5.Padding = new System.Windows.Forms.Padding(4); - this.groupBox5.Size = new System.Drawing.Size(503, 224); + this.groupBox5.Size = new System.Drawing.Size(377, 182); this.groupBox5.TabIndex = 63; this.groupBox5.TabStop = false; this.groupBox5.Text = "Project Info"; @@ -155,133 +152,119 @@ private void InitializeComponent() // label4 // this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(13, 188); - this.label4.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label4.Location = new System.Drawing.Point(10, 153); this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(117, 16); + this.label4.Size = new System.Drawing.Size(95, 13); this.label4.TabIndex = 70; this.label4.Text = "Documentation file"; // // textBox_mdFileName // - this.textBox_mdFileName.Location = new System.Drawing.Point(185, 185); - this.textBox_mdFileName.Margin = new System.Windows.Forms.Padding(4); + this.textBox_mdFileName.Location = new System.Drawing.Point(139, 150); this.textBox_mdFileName.Name = "textBox_mdFileName"; this.textBox_mdFileName.ReadOnly = true; - this.textBox_mdFileName.Size = new System.Drawing.Size(300, 22); + this.textBox_mdFileName.Size = new System.Drawing.Size(226, 20); this.textBox_mdFileName.TabIndex = 69; // // label2 // this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(13, 60); - this.label2.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label2.Location = new System.Drawing.Point(10, 49); this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(141, 16); + this.label2.Size = new System.Drawing.Size(116, 13); this.label2.TabIndex = 68; this.label2.Text = "XDD v1.1 file - stripped"; // // textBox_xddfilenameStripped // - this.textBox_xddfilenameStripped.Location = new System.Drawing.Point(185, 57); - this.textBox_xddfilenameStripped.Margin = new System.Windows.Forms.Padding(4); + this.textBox_xddfilenameStripped.Location = new System.Drawing.Point(139, 46); this.textBox_xddfilenameStripped.Name = "textBox_xddfilenameStripped"; this.textBox_xddfilenameStripped.ReadOnly = true; - this.textBox_xddfilenameStripped.Size = new System.Drawing.Size(300, 22); + this.textBox_xddfilenameStripped.Size = new System.Drawing.Size(226, 20); this.textBox_xddfilenameStripped.TabIndex = 67; // // textBox_canopennodeFileVersion // - this.textBox_canopennodeFileVersion.Location = new System.Drawing.Point(440, 153); - this.textBox_canopennodeFileVersion.Margin = new System.Windows.Forms.Padding(4); + this.textBox_canopennodeFileVersion.Location = new System.Drawing.Point(330, 124); this.textBox_canopennodeFileVersion.Name = "textBox_canopennodeFileVersion"; this.textBox_canopennodeFileVersion.ReadOnly = true; - this.textBox_canopennodeFileVersion.Size = new System.Drawing.Size(45, 22); + this.textBox_canopennodeFileVersion.Size = new System.Drawing.Size(35, 20); this.textBox_canopennodeFileVersion.TabIndex = 66; // // textBox_projectFileVersion // - this.textBox_projectFileVersion.Location = new System.Drawing.Point(440, 25); - this.textBox_projectFileVersion.Margin = new System.Windows.Forms.Padding(4); + this.textBox_projectFileVersion.Location = new System.Drawing.Point(330, 20); this.textBox_projectFileVersion.Name = "textBox_projectFileVersion"; this.textBox_projectFileVersion.ReadOnly = true; - this.textBox_projectFileVersion.Size = new System.Drawing.Size(45, 22); + this.textBox_projectFileVersion.Size = new System.Drawing.Size(35, 20); this.textBox_projectFileVersion.TabIndex = 65; // // textBox_devicedcfname // - this.textBox_devicedcfname.Location = new System.Drawing.Point(185, 121); - this.textBox_devicedcfname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_devicedcfname.Location = new System.Drawing.Point(139, 98); this.textBox_devicedcfname.Name = "textBox_devicedcfname"; this.textBox_devicedcfname.ReadOnly = true; - this.textBox_devicedcfname.Size = new System.Drawing.Size(300, 22); + this.textBox_devicedcfname.Size = new System.Drawing.Size(226, 20); this.textBox_devicedcfname.TabIndex = 8; // // label14 // this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(13, 156); - this.label14.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label14.Location = new System.Drawing.Point(10, 127); this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(150, 16); + this.label14.Size = new System.Drawing.Size(119, 13); this.label14.TabIndex = 21; this.label14.Text = "CANopenNode file (ver)"; // // label15 // this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(13, 124); - this.label15.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label15.Location = new System.Drawing.Point(10, 101); this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(54, 16); + this.label15.Size = new System.Drawing.Size(44, 13); this.label15.TabIndex = 20; this.label15.Text = "DCF file"; // // textBox_canopennodeFileName // - this.textBox_canopennodeFileName.Location = new System.Drawing.Point(185, 153); - this.textBox_canopennodeFileName.Margin = new System.Windows.Forms.Padding(4); + this.textBox_canopennodeFileName.Location = new System.Drawing.Point(139, 124); this.textBox_canopennodeFileName.Name = "textBox_canopennodeFileName"; this.textBox_canopennodeFileName.ReadOnly = true; - this.textBox_canopennodeFileName.Size = new System.Drawing.Size(245, 22); + this.textBox_canopennodeFileName.Size = new System.Drawing.Size(185, 20); this.textBox_canopennodeFileName.TabIndex = 9; // // label16 // this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(13, 92); - this.label16.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label16.Location = new System.Drawing.Point(10, 75); this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(55, 16); + this.label16.Size = new System.Drawing.Size(45, 13); this.label16.TabIndex = 19; this.label16.Text = "EDS file"; // // label31 // this.label31.AutoSize = true; - this.label31.Location = new System.Drawing.Point(13, 28); - this.label31.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label31.Location = new System.Drawing.Point(10, 23); this.label31.Name = "label31"; - this.label31.Size = new System.Drawing.Size(124, 16); + this.label31.Size = new System.Drawing.Size(99, 13); this.label31.TabIndex = 18; this.label31.Text = "Project file (version)"; // // textBox_projectFileName // - this.textBox_projectFileName.Location = new System.Drawing.Point(185, 25); - this.textBox_projectFileName.Margin = new System.Windows.Forms.Padding(4); + this.textBox_projectFileName.Location = new System.Drawing.Point(139, 20); this.textBox_projectFileName.Name = "textBox_projectFileName"; this.textBox_projectFileName.ReadOnly = true; - this.textBox_projectFileName.Size = new System.Drawing.Size(245, 22); + this.textBox_projectFileName.Size = new System.Drawing.Size(185, 20); this.textBox_projectFileName.TabIndex = 6; // // textBox_deviceedsname // - this.textBox_deviceedsname.Location = new System.Drawing.Point(185, 89); - this.textBox_deviceedsname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_deviceedsname.Location = new System.Drawing.Point(139, 72); this.textBox_deviceedsname.Name = "textBox_deviceedsname"; this.textBox_deviceedsname.ReadOnly = true; - this.textBox_deviceedsname.Size = new System.Drawing.Size(300, 22); + this.textBox_deviceedsname.Size = new System.Drawing.Size(226, 20); this.textBox_deviceedsname.TabIndex = 7; // // groupBox6 @@ -300,11 +283,9 @@ private void InitializeComponent() this.groupBox6.Controls.Add(this.textBox_nodename); this.groupBox6.Controls.Add(this.label32); this.groupBox6.Controls.Add(this.textBox_concretenodeid); - this.groupBox6.Location = new System.Drawing.Point(527, 385); - this.groupBox6.Margin = new System.Windows.Forms.Padding(4); + this.groupBox6.Location = new System.Drawing.Point(395, 313); this.groupBox6.Name = "groupBox6"; - this.groupBox6.Padding = new System.Windows.Forms.Padding(4); - this.groupBox6.Size = new System.Drawing.Size(452, 248); + this.groupBox6.Size = new System.Drawing.Size(339, 202); this.groupBox6.TabIndex = 5; this.groupBox6.TabStop = false; this.groupBox6.Text = "Device commissioning"; @@ -312,29 +293,26 @@ private void InitializeComponent() // label3 // this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(9, 183); - this.label3.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label3.Location = new System.Drawing.Point(7, 149); this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(123, 16); + this.label3.Size = new System.Drawing.Size(98, 13); this.label3.TabIndex = 63; this.label3.Text = "CANopen Manager"; // // textBox_lssserial // this.textBox_lssserial.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_lssserial.Location = new System.Drawing.Point(148, 210); - this.textBox_lssserial.Margin = new System.Windows.Forms.Padding(4); + this.textBox_lssserial.Location = new System.Drawing.Point(111, 171); this.textBox_lssserial.Name = "textBox_lssserial"; - this.textBox_lssserial.Size = new System.Drawing.Size(289, 22); + this.textBox_lssserial.Size = new System.Drawing.Size(218, 20); this.textBox_lssserial.TabIndex = 7; // // label9 // this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(9, 214); - this.label9.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label9.Location = new System.Drawing.Point(7, 174); this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(88, 16); + this.label9.Size = new System.Drawing.Size(71, 13); this.label9.TabIndex = 6; this.label9.Text = "LSS Serial no"; // @@ -342,107 +320,96 @@ private void InitializeComponent() // this.checkBox_canopenmanager.AutoSize = true; this.checkBox_canopenmanager.BackColor = System.Drawing.Color.PeachPuff; - this.checkBox_canopenmanager.Location = new System.Drawing.Point(148, 182); - this.checkBox_canopenmanager.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_canopenmanager.Location = new System.Drawing.Point(111, 148); this.checkBox_canopenmanager.Name = "checkBox_canopenmanager"; - this.checkBox_canopenmanager.Padding = new System.Windows.Forms.Padding(0, 0, 269, 0); - this.checkBox_canopenmanager.Size = new System.Drawing.Size(287, 17); + this.checkBox_canopenmanager.Padding = new System.Windows.Forms.Padding(0, 0, 202, 0); + this.checkBox_canopenmanager.Size = new System.Drawing.Size(217, 14); this.checkBox_canopenmanager.TabIndex = 5; this.checkBox_canopenmanager.UseVisualStyleBackColor = false; // // label8 // this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(9, 154); - this.label8.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label8.Location = new System.Drawing.Point(7, 125); this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(65, 16); + this.label8.Size = new System.Drawing.Size(53, 13); this.label8.TabIndex = 62; this.label8.Text = "Net name"; // // textBox_netname // this.textBox_netname.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_netname.Location = new System.Drawing.Point(148, 150); - this.textBox_netname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_netname.Location = new System.Drawing.Point(111, 122); this.textBox_netname.Name = "textBox_netname"; - this.textBox_netname.Size = new System.Drawing.Size(289, 22); + this.textBox_netname.Size = new System.Drawing.Size(218, 20); this.textBox_netname.TabIndex = 4; // // label7 // this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(9, 122); - this.label7.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label7.Location = new System.Drawing.Point(7, 99); this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(76, 16); + this.label7.Size = new System.Drawing.Size(62, 13); this.label7.TabIndex = 60; this.label7.Text = "Net number"; // // textBox_netnum // this.textBox_netnum.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_netnum.Location = new System.Drawing.Point(148, 118); - this.textBox_netnum.Margin = new System.Windows.Forms.Padding(4); + this.textBox_netnum.Location = new System.Drawing.Point(111, 96); this.textBox_netnum.Name = "textBox_netnum"; - this.textBox_netnum.Size = new System.Drawing.Size(289, 22); + this.textBox_netnum.Size = new System.Drawing.Size(218, 20); this.textBox_netnum.TabIndex = 3; // // label6 // this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(9, 91); - this.label6.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label6.Location = new System.Drawing.Point(7, 74); this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(62, 16); + this.label6.Size = new System.Drawing.Size(50, 13); this.label6.TabIndex = 58; this.label6.Text = "Baudrate"; // // textBox_baudrate // this.textBox_baudrate.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_baudrate.Location = new System.Drawing.Point(148, 87); - this.textBox_baudrate.Margin = new System.Windows.Forms.Padding(4); + this.textBox_baudrate.Location = new System.Drawing.Point(111, 71); this.textBox_baudrate.Name = "textBox_baudrate"; - this.textBox_baudrate.Size = new System.Drawing.Size(289, 22); + this.textBox_baudrate.Size = new System.Drawing.Size(218, 20); this.textBox_baudrate.TabIndex = 2; // // label5 // this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(9, 59); - this.label5.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label5.Location = new System.Drawing.Point(7, 48); this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(78, 16); + this.label5.Size = new System.Drawing.Size(62, 13); this.label5.TabIndex = 56; this.label5.Text = "Node name"; // // textBox_nodename // this.textBox_nodename.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_nodename.Location = new System.Drawing.Point(148, 55); - this.textBox_nodename.Margin = new System.Windows.Forms.Padding(4); + this.textBox_nodename.Location = new System.Drawing.Point(111, 45); this.textBox_nodename.Name = "textBox_nodename"; - this.textBox_nodename.Size = new System.Drawing.Size(289, 22); + this.textBox_nodename.Size = new System.Drawing.Size(218, 20); this.textBox_nodename.TabIndex = 1; // // label32 // this.label32.AutoSize = true; - this.label32.Location = new System.Drawing.Point(9, 27); - this.label32.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label32.Location = new System.Drawing.Point(7, 22); this.label32.Name = "label32"; - this.label32.Size = new System.Drawing.Size(111, 16); + this.label32.Size = new System.Drawing.Size(91, 13); this.label32.TabIndex = 53; this.label32.Text = "Concrete node ID"; // // textBox_concretenodeid // this.textBox_concretenodeid.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_concretenodeid.Location = new System.Drawing.Point(148, 23); - this.textBox_concretenodeid.Margin = new System.Windows.Forms.Padding(4); + this.textBox_concretenodeid.Location = new System.Drawing.Point(111, 19); this.textBox_concretenodeid.Name = "textBox_concretenodeid"; - this.textBox_concretenodeid.Size = new System.Drawing.Size(289, 22); + this.textBox_concretenodeid.Size = new System.Drawing.Size(218, 20); this.textBox_concretenodeid.TabIndex = 0; // // groupBox4 @@ -455,84 +422,74 @@ private void InitializeComponent() this.groupBox4.Controls.Add(this.label28); this.groupBox4.Controls.Add(this.label27); this.groupBox4.Controls.Add(this.label26); - this.groupBox4.Location = new System.Drawing.Point(16, 17); - this.groupBox4.Margin = new System.Windows.Forms.Padding(4); + this.groupBox4.Location = new System.Drawing.Point(12, 14); this.groupBox4.Name = "groupBox4"; - this.groupBox4.Padding = new System.Windows.Forms.Padding(4); - this.groupBox4.Size = new System.Drawing.Size(503, 155); + this.groupBox4.Size = new System.Drawing.Size(377, 126); this.groupBox4.TabIndex = 0; this.groupBox4.TabStop = false; this.groupBox4.Text = "Device Info"; // // textBox_productnumber // - this.textBox_productnumber.Location = new System.Drawing.Point(185, 57); - this.textBox_productnumber.Margin = new System.Windows.Forms.Padding(4); + this.textBox_productnumber.Location = new System.Drawing.Point(139, 46); this.textBox_productnumber.Name = "textBox_productnumber"; - this.textBox_productnumber.Size = new System.Drawing.Size(300, 22); + this.textBox_productnumber.Size = new System.Drawing.Size(226, 20); this.textBox_productnumber.TabIndex = 1; // // textBox_productname // - this.textBox_productname.Location = new System.Drawing.Point(185, 25); - this.textBox_productname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_productname.Location = new System.Drawing.Point(139, 20); this.textBox_productname.Name = "textBox_productname"; - this.textBox_productname.Size = new System.Drawing.Size(300, 22); + this.textBox_productname.Size = new System.Drawing.Size(226, 20); this.textBox_productname.TabIndex = 0; // // textBox_vendornumber // - this.textBox_vendornumber.Location = new System.Drawing.Point(185, 121); - this.textBox_vendornumber.Margin = new System.Windows.Forms.Padding(4); + this.textBox_vendornumber.Location = new System.Drawing.Point(139, 98); this.textBox_vendornumber.Name = "textBox_vendornumber"; - this.textBox_vendornumber.Size = new System.Drawing.Size(300, 22); + this.textBox_vendornumber.Size = new System.Drawing.Size(226, 20); this.textBox_vendornumber.TabIndex = 3; // // textBox_vendorname // - this.textBox_vendorname.Location = new System.Drawing.Point(185, 89); - this.textBox_vendorname.Margin = new System.Windows.Forms.Padding(4); + this.textBox_vendorname.Location = new System.Drawing.Point(139, 72); this.textBox_vendorname.Name = "textBox_vendorname"; - this.textBox_vendorname.Size = new System.Drawing.Size(300, 22); + this.textBox_vendorname.Size = new System.Drawing.Size(226, 20); this.textBox_vendorname.TabIndex = 2; // // label29 // this.label29.AutoSize = true; - this.label29.Location = new System.Drawing.Point(13, 60); - this.label29.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label29.Location = new System.Drawing.Point(10, 49); this.label29.Name = "label29"; - this.label29.Size = new System.Drawing.Size(69, 16); + this.label29.Size = new System.Drawing.Size(58, 13); this.label29.TabIndex = 37; this.label29.Text = "Product ID"; // // label28 // this.label28.AutoSize = true; - this.label28.Location = new System.Drawing.Point(13, 28); - this.label28.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label28.Location = new System.Drawing.Point(10, 23); this.label28.Name = "label28"; - this.label28.Size = new System.Drawing.Size(90, 16); + this.label28.Size = new System.Drawing.Size(73, 13); this.label28.TabIndex = 36; this.label28.Text = "Product name"; // // label27 // this.label27.AutoSize = true; - this.label27.Location = new System.Drawing.Point(13, 124); - this.label27.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label27.Location = new System.Drawing.Point(10, 101); this.label27.Name = "label27"; - this.label27.Size = new System.Drawing.Size(67, 16); + this.label27.Size = new System.Drawing.Size(55, 13); this.label27.TabIndex = 35; this.label27.Text = "Vendor ID"; // // label26 // this.label26.AutoSize = true; - this.label26.Location = new System.Drawing.Point(13, 92); - this.label26.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label26.Location = new System.Drawing.Point(10, 75); this.label26.Name = "label26"; - this.label26.Size = new System.Drawing.Size(88, 16); + this.label26.Size = new System.Drawing.Size(70, 13); this.label26.TabIndex = 34; this.label26.Text = "Vendor name"; // @@ -547,11 +504,9 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.checkBox_baud_1000); this.groupBox1.Controls.Add(this.checkBox_baud_500); this.groupBox1.Controls.Add(this.checkBox_baud_800); - this.groupBox1.Location = new System.Drawing.Point(527, 17); - this.groupBox1.Margin = new System.Windows.Forms.Padding(4); + this.groupBox1.Location = new System.Drawing.Point(395, 14); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(4); - this.groupBox1.Size = new System.Drawing.Size(160, 271); + this.groupBox1.Size = new System.Drawing.Size(120, 220); this.groupBox1.TabIndex = 3; this.groupBox1.TabStop = false; this.groupBox1.Text = "Baudrates"; @@ -559,10 +514,9 @@ private void InitializeComponent() // checkBox_baud_auto // this.checkBox_baud_auto.AutoSize = true; - this.checkBox_baud_auto.Location = new System.Drawing.Point(13, 201); - this.checkBox_baud_auto.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_auto.Location = new System.Drawing.Point(10, 163); this.checkBox_baud_auto.Name = "checkBox_baud_auto"; - this.checkBox_baud_auto.Size = new System.Drawing.Size(55, 20); + this.checkBox_baud_auto.Size = new System.Drawing.Size(47, 17); this.checkBox_baud_auto.TabIndex = 8; this.checkBox_baud_auto.Text = "auto"; this.checkBox_baud_auto.UseVisualStyleBackColor = true; @@ -570,10 +524,9 @@ private void InitializeComponent() // checkBox_baud_125 // this.checkBox_baud_125.AutoSize = true; - this.checkBox_baud_125.Location = new System.Drawing.Point(13, 89); - this.checkBox_baud_125.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_125.Location = new System.Drawing.Point(10, 72); this.checkBox_baud_125.Name = "checkBox_baud_125"; - this.checkBox_baud_125.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_125.Size = new System.Drawing.Size(70, 17); this.checkBox_baud_125.TabIndex = 3; this.checkBox_baud_125.Text = "125 kbps"; this.checkBox_baud_125.UseVisualStyleBackColor = true; @@ -581,10 +534,9 @@ private void InitializeComponent() // checkBox_baud_10 // this.checkBox_baud_10.AutoSize = true; - this.checkBox_baud_10.Location = new System.Drawing.Point(13, 25); - this.checkBox_baud_10.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_10.Location = new System.Drawing.Point(10, 20); this.checkBox_baud_10.Name = "checkBox_baud_10"; - this.checkBox_baud_10.Size = new System.Drawing.Size(76, 20); + this.checkBox_baud_10.Size = new System.Drawing.Size(64, 17); this.checkBox_baud_10.TabIndex = 0; this.checkBox_baud_10.Text = "10 kbps"; this.checkBox_baud_10.UseVisualStyleBackColor = true; @@ -592,10 +544,9 @@ private void InitializeComponent() // checkBox_baud_20 // this.checkBox_baud_20.AutoSize = true; - this.checkBox_baud_20.Location = new System.Drawing.Point(13, 46); - this.checkBox_baud_20.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_20.Location = new System.Drawing.Point(10, 37); this.checkBox_baud_20.Name = "checkBox_baud_20"; - this.checkBox_baud_20.Size = new System.Drawing.Size(76, 20); + this.checkBox_baud_20.Size = new System.Drawing.Size(64, 17); this.checkBox_baud_20.TabIndex = 1; this.checkBox_baud_20.Text = "20 kbps"; this.checkBox_baud_20.UseVisualStyleBackColor = true; @@ -603,10 +554,9 @@ private void InitializeComponent() // checkBox_baud_50 // this.checkBox_baud_50.AutoSize = true; - this.checkBox_baud_50.Location = new System.Drawing.Point(13, 66); - this.checkBox_baud_50.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_50.Location = new System.Drawing.Point(10, 54); this.checkBox_baud_50.Name = "checkBox_baud_50"; - this.checkBox_baud_50.Size = new System.Drawing.Size(76, 20); + this.checkBox_baud_50.Size = new System.Drawing.Size(64, 17); this.checkBox_baud_50.TabIndex = 2; this.checkBox_baud_50.Text = "50 kbps"; this.checkBox_baud_50.UseVisualStyleBackColor = true; @@ -614,10 +564,9 @@ private void InitializeComponent() // checkBox_baud_250 // this.checkBox_baud_250.AutoSize = true; - this.checkBox_baud_250.Location = new System.Drawing.Point(13, 111); - this.checkBox_baud_250.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_250.Location = new System.Drawing.Point(10, 90); this.checkBox_baud_250.Name = "checkBox_baud_250"; - this.checkBox_baud_250.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_250.Size = new System.Drawing.Size(70, 17); this.checkBox_baud_250.TabIndex = 4; this.checkBox_baud_250.Text = "250 kbps"; this.checkBox_baud_250.UseVisualStyleBackColor = true; @@ -625,10 +574,9 @@ private void InitializeComponent() // checkBox_baud_1000 // this.checkBox_baud_1000.AutoSize = true; - this.checkBox_baud_1000.Location = new System.Drawing.Point(13, 178); - this.checkBox_baud_1000.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_1000.Location = new System.Drawing.Point(10, 145); this.checkBox_baud_1000.Name = "checkBox_baud_1000"; - this.checkBox_baud_1000.Size = new System.Drawing.Size(90, 20); + this.checkBox_baud_1000.Size = new System.Drawing.Size(76, 17); this.checkBox_baud_1000.TabIndex = 7; this.checkBox_baud_1000.Text = "1000 kbps"; this.checkBox_baud_1000.UseVisualStyleBackColor = true; @@ -636,10 +584,9 @@ private void InitializeComponent() // checkBox_baud_500 // this.checkBox_baud_500.AutoSize = true; - this.checkBox_baud_500.Location = new System.Drawing.Point(13, 134); - this.checkBox_baud_500.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_500.Location = new System.Drawing.Point(10, 109); this.checkBox_baud_500.Name = "checkBox_baud_500"; - this.checkBox_baud_500.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_500.Size = new System.Drawing.Size(70, 17); this.checkBox_baud_500.TabIndex = 5; this.checkBox_baud_500.Text = "500 kbps"; this.checkBox_baud_500.UseVisualStyleBackColor = true; @@ -647,10 +594,9 @@ private void InitializeComponent() // checkBox_baud_800 // this.checkBox_baud_800.AutoSize = true; - this.checkBox_baud_800.Location = new System.Drawing.Point(13, 156); - this.checkBox_baud_800.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_baud_800.Location = new System.Drawing.Point(10, 127); this.checkBox_baud_800.Name = "checkBox_baud_800"; - this.checkBox_baud_800.Size = new System.Drawing.Size(83, 20); + this.checkBox_baud_800.Size = new System.Drawing.Size(70, 17); this.checkBox_baud_800.TabIndex = 6; this.checkBox_baud_800.Text = "800 kbps"; this.checkBox_baud_800.UseVisualStyleBackColor = true; @@ -659,8 +605,8 @@ private void InitializeComponent() // this.groupBox2.Controls.Add(this.textBox_NG_NumOfNodes); this.groupBox2.Controls.Add(this.label10); - this.groupBox2.Controls.Add(this.checkBox_NG_Master); - this.groupBox2.Controls.Add(this.checkBox_NG_Slave); + this.groupBox2.Controls.Add(this.checkBox_ngMaster); + this.groupBox2.Controls.Add(this.checkBox_ngSlave); this.groupBox2.Controls.Add(this.textBox_granularity); this.groupBox2.Controls.Add(this.label1); this.groupBox2.Controls.Add(this.textBox_txpdos); @@ -669,49 +615,80 @@ private void InitializeComponent() this.groupBox2.Controls.Add(this.textBox_rxpdos); this.groupBox2.Controls.Add(this.label17); this.groupBox2.Controls.Add(this.checkBox_lss); - this.groupBox2.Location = new System.Drawing.Point(695, 17); - this.groupBox2.Margin = new System.Windows.Forms.Padding(4); + this.groupBox2.Location = new System.Drawing.Point(521, 14); this.groupBox2.Name = "groupBox2"; - this.groupBox2.Padding = new System.Windows.Forms.Padding(4); - this.groupBox2.Size = new System.Drawing.Size(284, 271); + this.groupBox2.Size = new System.Drawing.Size(213, 220); this.groupBox2.TabIndex = 4; this.groupBox2.TabStop = false; this.groupBox2.Text = "General and Master Features"; // + // textBox_NG_NumOfNodes + // + this.textBox_NG_NumOfNodes.BackColor = System.Drawing.SystemColors.Window; + this.textBox_NG_NumOfNodes.Location = new System.Drawing.Point(124, 193); + this.textBox_NG_NumOfNodes.Name = "textBox_NG_NumOfNodes"; + this.textBox_NG_NumOfNodes.Size = new System.Drawing.Size(80, 20); + this.textBox_NG_NumOfNodes.TabIndex = 44; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(10, 196); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(114, 13); + this.label10.TabIndex = 45; + this.label10.Text = "No of monitored nodes"; + // + // checkBox_ngMaster + // + this.checkBox_ngMaster.AutoSize = true; + this.checkBox_ngMaster.Location = new System.Drawing.Point(10, 176); + this.checkBox_ngMaster.Name = "checkBox_ngMaster"; + this.checkBox_ngMaster.Size = new System.Drawing.Size(131, 17); + this.checkBox_ngMaster.TabIndex = 43; + this.checkBox_ngMaster.Text = "Node guarding Master"; + this.checkBox_ngMaster.UseVisualStyleBackColor = true; + // + // checkBox_ngSlave + // + this.checkBox_ngSlave.AutoSize = true; + this.checkBox_ngSlave.Location = new System.Drawing.Point(10, 158); + this.checkBox_ngSlave.Name = "checkBox_ngSlave"; + this.checkBox_ngSlave.Size = new System.Drawing.Size(126, 17); + this.checkBox_ngSlave.TabIndex = 42; + this.checkBox_ngSlave.Text = "Node guarding Slave"; + this.checkBox_ngSlave.UseVisualStyleBackColor = true; + // // textBox_granularity // - this.textBox_granularity.Location = new System.Drawing.Point(136, 25); - this.textBox_granularity.Margin = new System.Windows.Forms.Padding(4); + this.textBox_granularity.Location = new System.Drawing.Point(102, 20); this.textBox_granularity.Name = "textBox_granularity"; - this.textBox_granularity.Size = new System.Drawing.Size(133, 22); + this.textBox_granularity.Size = new System.Drawing.Size(101, 20); this.textBox_granularity.TabIndex = 41; // // label1 // this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(13, 28); - this.label1.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label1.Location = new System.Drawing.Point(10, 23); this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(71, 16); + this.label1.Size = new System.Drawing.Size(57, 13); this.label1.TabIndex = 40; this.label1.Text = "Granularity"; // // textBox_txpdos // - this.textBox_txpdos.Location = new System.Drawing.Point(136, 89); - this.textBox_txpdos.Margin = new System.Windows.Forms.Padding(4); + this.textBox_txpdos.Location = new System.Drawing.Point(102, 72); this.textBox_txpdos.Name = "textBox_txpdos"; this.textBox_txpdos.ReadOnly = true; - this.textBox_txpdos.Size = new System.Drawing.Size(133, 22); + this.textBox_txpdos.Size = new System.Drawing.Size(101, 20); this.textBox_txpdos.TabIndex = 1; // // checkBox_lssMaster // this.checkBox_lssMaster.AutoSize = true; - this.checkBox_lssMaster.Location = new System.Drawing.Point(13, 158); - this.checkBox_lssMaster.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_lssMaster.Location = new System.Drawing.Point(10, 128); this.checkBox_lssMaster.Name = "checkBox_lssMaster"; - this.checkBox_lssMaster.Size = new System.Drawing.Size(98, 20); + this.checkBox_lssMaster.Size = new System.Drawing.Size(81, 17); this.checkBox_lssMaster.TabIndex = 10; this.checkBox_lssMaster.Text = "LSS Master"; this.checkBox_lssMaster.UseVisualStyleBackColor = true; @@ -719,39 +696,35 @@ private void InitializeComponent() // label30 // this.label30.AutoSize = true; - this.label30.Location = new System.Drawing.Point(13, 92); - this.label30.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label30.Location = new System.Drawing.Point(10, 75); this.label30.Name = "label30"; - this.label30.Size = new System.Drawing.Size(80, 16); + this.label30.Size = new System.Drawing.Size(67, 13); this.label30.TabIndex = 39; this.label30.Text = "TPDO count"; // // textBox_rxpdos // - this.textBox_rxpdos.Location = new System.Drawing.Point(136, 57); - this.textBox_rxpdos.Margin = new System.Windows.Forms.Padding(4); + this.textBox_rxpdos.Location = new System.Drawing.Point(102, 46); this.textBox_rxpdos.Name = "textBox_rxpdos"; this.textBox_rxpdos.ReadOnly = true; - this.textBox_rxpdos.Size = new System.Drawing.Size(133, 22); + this.textBox_rxpdos.Size = new System.Drawing.Size(101, 20); this.textBox_rxpdos.TabIndex = 0; // // label17 // this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(13, 60); - this.label17.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label17.Location = new System.Drawing.Point(10, 49); this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(81, 16); + this.label17.Size = new System.Drawing.Size(68, 13); this.label17.TabIndex = 38; this.label17.Text = "RPDO count"; // // checkBox_lss // this.checkBox_lss.AutoSize = true; - this.checkBox_lss.Location = new System.Drawing.Point(13, 136); - this.checkBox_lss.Margin = new System.Windows.Forms.Padding(4); + this.checkBox_lss.Location = new System.Drawing.Point(10, 110); this.checkBox_lss.Name = "checkBox_lss"; - this.checkBox_lss.Size = new System.Drawing.Size(92, 20); + this.checkBox_lss.Size = new System.Drawing.Size(76, 17); this.checkBox_lss.TabIndex = 6; this.checkBox_lss.Text = "LSS Slave"; this.checkBox_lss.UseVisualStyleBackColor = true; @@ -770,174 +743,117 @@ private void InitializeComponent() this.groupBox3.Controls.Add(this.label22); this.groupBox3.Controls.Add(this.label20); this.groupBox3.Controls.Add(this.label18); - this.groupBox3.Location = new System.Drawing.Point(16, 180); - this.groupBox3.Margin = new System.Windows.Forms.Padding(4); + this.groupBox3.Location = new System.Drawing.Point(12, 146); this.groupBox3.Name = "groupBox3"; - this.groupBox3.Padding = new System.Windows.Forms.Padding(4); - this.groupBox3.Size = new System.Drawing.Size(503, 222); + this.groupBox3.Size = new System.Drawing.Size(377, 180); this.groupBox3.TabIndex = 1; this.groupBox3.TabStop = false; this.groupBox3.Text = "File Info"; // // textBox_modifiedby // - this.textBox_modifiedby.Location = new System.Drawing.Point(185, 185); - this.textBox_modifiedby.Margin = new System.Windows.Forms.Padding(4); + this.textBox_modifiedby.Location = new System.Drawing.Point(139, 150); this.textBox_modifiedby.Name = "textBox_modifiedby"; - this.textBox_modifiedby.Size = new System.Drawing.Size(300, 22); + this.textBox_modifiedby.Size = new System.Drawing.Size(226, 20); this.textBox_modifiedby.TabIndex = 7; // // textBox_modified_datetime // - this.textBox_modified_datetime.Location = new System.Drawing.Point(185, 153); - this.textBox_modified_datetime.Margin = new System.Windows.Forms.Padding(4); + this.textBox_modified_datetime.Location = new System.Drawing.Point(139, 124); this.textBox_modified_datetime.Name = "textBox_modified_datetime"; this.textBox_modified_datetime.ReadOnly = true; - this.textBox_modified_datetime.Size = new System.Drawing.Size(300, 22); + this.textBox_modified_datetime.Size = new System.Drawing.Size(226, 20); this.textBox_modified_datetime.TabIndex = 6; // // textBox_createdby // - this.textBox_createdby.Location = new System.Drawing.Point(185, 121); - this.textBox_createdby.Margin = new System.Windows.Forms.Padding(4); + this.textBox_createdby.Location = new System.Drawing.Point(139, 98); this.textBox_createdby.Name = "textBox_createdby"; - this.textBox_createdby.Size = new System.Drawing.Size(300, 22); + this.textBox_createdby.Size = new System.Drawing.Size(226, 20); this.textBox_createdby.TabIndex = 5; // // textBox_create_datetime // - this.textBox_create_datetime.Location = new System.Drawing.Point(185, 89); - this.textBox_create_datetime.Margin = new System.Windows.Forms.Padding(4); + this.textBox_create_datetime.Location = new System.Drawing.Point(139, 72); this.textBox_create_datetime.Name = "textBox_create_datetime"; - this.textBox_create_datetime.Size = new System.Drawing.Size(300, 22); + this.textBox_create_datetime.Size = new System.Drawing.Size(226, 20); this.textBox_create_datetime.TabIndex = 4; // // textBox_di_description // - this.textBox_di_description.Location = new System.Drawing.Point(185, 57); - this.textBox_di_description.Margin = new System.Windows.Forms.Padding(4); + this.textBox_di_description.Location = new System.Drawing.Point(139, 46); this.textBox_di_description.Name = "textBox_di_description"; - this.textBox_di_description.Size = new System.Drawing.Size(300, 22); + this.textBox_di_description.Size = new System.Drawing.Size(226, 20); this.textBox_di_description.TabIndex = 3; // // textBox_fileversion // - this.textBox_fileversion.Location = new System.Drawing.Point(185, 25); - this.textBox_fileversion.Margin = new System.Windows.Forms.Padding(4); + this.textBox_fileversion.Location = new System.Drawing.Point(139, 20); this.textBox_fileversion.Name = "textBox_fileversion"; - this.textBox_fileversion.Size = new System.Drawing.Size(300, 22); + this.textBox_fileversion.Size = new System.Drawing.Size(226, 20); this.textBox_fileversion.TabIndex = 0; // // label25 // this.label25.AutoSize = true; - this.label25.Location = new System.Drawing.Point(13, 188); - this.label25.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label25.Location = new System.Drawing.Point(10, 153); this.label25.Name = "label25"; - this.label25.Size = new System.Drawing.Size(77, 16); + this.label25.Size = new System.Drawing.Size(61, 13); this.label25.TabIndex = 25; this.label25.Text = "Modified by"; // // label24 // this.label24.AutoSize = true; - this.label24.Location = new System.Drawing.Point(13, 156); - this.label24.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label24.Location = new System.Drawing.Point(10, 127); this.label24.Name = "label24"; - this.label24.Size = new System.Drawing.Size(146, 16); + this.label24.Size = new System.Drawing.Size(118, 13); this.label24.TabIndex = 24; this.label24.Text = "Modification Date/Time"; // // label23 // this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(13, 124); - this.label23.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label23.Location = new System.Drawing.Point(10, 101); this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(74, 16); + this.label23.Size = new System.Drawing.Size(59, 13); this.label23.TabIndex = 23; this.label23.Text = "Created By"; // // label22 // this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(13, 92); - this.label22.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label22.Location = new System.Drawing.Point(10, 75); this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(124, 16); + this.label22.Size = new System.Drawing.Size(100, 13); this.label22.TabIndex = 22; this.label22.Text = "Creation Date/Time"; // // label20 // this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(13, 60); - this.label20.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label20.Location = new System.Drawing.Point(10, 49); this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(75, 16); + this.label20.Size = new System.Drawing.Size(60, 13); this.label20.TabIndex = 20; this.label20.Text = "Description"; // // label18 // this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(13, 28); - this.label18.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); + this.label18.Location = new System.Drawing.Point(10, 23); this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(76, 16); + this.label18.Size = new System.Drawing.Size(60, 13); this.label18.TabIndex = 18; this.label18.Text = "File version"; // - // checkBox_NG_Master - // - this.checkBox_NG_Master.AutoSize = true; - this.checkBox_NG_Master.Location = new System.Drawing.Point(13, 216); - this.checkBox_NG_Master.Margin = new System.Windows.Forms.Padding(4); - this.checkBox_NG_Master.Name = "checkBox_NG_Master"; - this.checkBox_NG_Master.Size = new System.Drawing.Size(163, 20); - this.checkBox_NG_Master.TabIndex = 43; - this.checkBox_NG_Master.Text = "Node guarding Master"; - this.checkBox_NG_Master.UseVisualStyleBackColor = true; - // - // checkBox_NG_Slave - // - this.checkBox_NG_Slave.AutoSize = true; - this.checkBox_NG_Slave.Location = new System.Drawing.Point(13, 195); - this.checkBox_NG_Slave.Margin = new System.Windows.Forms.Padding(4); - this.checkBox_NG_Slave.Name = "checkBox_NG_Slave"; - this.checkBox_NG_Slave.Size = new System.Drawing.Size(157, 20); - this.checkBox_NG_Slave.TabIndex = 42; - this.checkBox_NG_Slave.Text = "Node guarding Slave"; - this.checkBox_NG_Slave.UseVisualStyleBackColor = true; - // - // textBox_NG_NumOfNodes - // - this.textBox_NG_NumOfNodes.BackColor = System.Drawing.SystemColors.Window; - this.textBox_NG_NumOfNodes.Location = new System.Drawing.Point(165, 238); - this.textBox_NG_NumOfNodes.Margin = new System.Windows.Forms.Padding(4); - this.textBox_NG_NumOfNodes.Name = "textBox_NG_NumOfNodes"; - this.textBox_NG_NumOfNodes.ReadOnly = true; - this.textBox_NG_NumOfNodes.Size = new System.Drawing.Size(105, 22); - this.textBox_NG_NumOfNodes.TabIndex = 44; - // - // label10 - // - this.label10.AutoSize = true; - this.label10.Location = new System.Drawing.Point(14, 241); - this.label10.Margin = new System.Windows.Forms.Padding(4, 0, 4, 0); - this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(143, 16); - this.label10.TabIndex = 45; - this.label10.Text = "No of monitored nodes"; - // // DeviceInfoView // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.panel1); - this.Margin = new System.Windows.Forms.Padding(4); this.Name = "DeviceInfoView"; - this.Size = new System.Drawing.Size(1031, 661); + this.Size = new System.Drawing.Size(773, 537); this.panel1.ResumeLayout(false); this.groupBox5.ResumeLayout(false); this.groupBox5.PerformLayout(); @@ -1031,7 +947,7 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_mdFileName; private System.Windows.Forms.TextBox textBox_NG_NumOfNodes; private System.Windows.Forms.Label label10; - private System.Windows.Forms.CheckBox checkBox_NG_Master; - private System.Windows.Forms.CheckBox checkBox_NG_Slave; + private System.Windows.Forms.CheckBox checkBox_ngMaster; + private System.Windows.Forms.CheckBox checkBox_ngSlave; } } diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 2c57c53a..1f8f96de 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -66,8 +66,19 @@ public void populatedeviceinfo() textBox_rxpdos.Text = eds.di.NrOfRXPDO.ToString(); textBox_txpdos.Text = eds.di.NrOfTXPDO.ToString(); checkBox_lss.Checked = eds.di.LSS_Supported; - checkBox_lssMaster.Checked = eds.di.LSS_Master; - + checkBox_lssMaster.Checked = eds.di.LSS_Master; + + checkBox_ngSlave.Checked = eds.di.NG_Slave; + checkBox_ngMaster.Checked = eds.di.NG_Master; + + if (textBox_NG_NumOfNodes.Enabled) + textBox_NG_NumOfNodes.Text = eds.di.NrOfNG_MonitoredNodes.ToString(); + else + { + textBox_NG_NumOfNodes.Text = ""; + eds.di.NrOfNG_MonitoredNodes = 0; + } + textBox_projectFileName.Text = Path.GetFileName(eds.projectFilename); if (eds.xddfilename_1_1 != "") textBox_projectFileVersion.Text = "v1.1"; @@ -148,8 +159,21 @@ private void update_devfile_info() eds.di.Granularity = Convert.ToByte(textBox_granularity.Text); eds.di.LSS_Supported = checkBox_lss.Checked; - eds.di.LSS_Master = checkBox_lssMaster.Checked; - + eds.di.LSS_Master = checkBox_lssMaster.Checked; + + // ToDO: Node guarding ist confiured manually, but should reflect the OD settings + // NG_Slave active if heartbeat producer time (0x1017) == 0 and Guardtime (0x100C) != 0 + // NG_Master active (according DSP302) if consumer time (0x1016) == 0 and NodeID is in network list (0x1F81) and Guardtime (0x100C) != 0 + // NrOfNG_MonitoredNodes should be the sum of all NodeIDs that are in network list (0x1F81) if heartbeat consumer time (0x1016) == 0 and Guardtime (0x100C) != 0 + textBox_NG_NumOfNodes.Enabled = checkBox_ngMaster.Checked; + eds.di.NG_Slave = checkBox_ngSlave.Checked; + eds.di.NG_Master = checkBox_ngMaster.Checked; + System.UInt16.TryParse(textBox_NG_NumOfNodes.Text,out eds.di.NrOfNG_MonitoredNodes); + if (eds.di.NrOfNG_MonitoredNodes > 127) + { + MessageBox.Show("Number of monitored nodes must be between 0 and 127"); + } + doUpdatePDOs(); //These are read only and auto calculated diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index c3a94824..b7ded4ce 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -25,6 +25,8 @@ You should have received a copy of the GNU General Public License using System.Reflection; using System.Text.RegularExpressions; using libEDSsharp; + + namespace ODEditor { @@ -588,7 +590,11 @@ private void ObjectSave() private void ListView_objects_MouseClick(object sender, MouseEventArgs e) { ListView listview = (ListView)sender; - ODentry od = listview.SelectedItems.Count > 0 ? (ODentry)listview.SelectedItems[0].Tag : null; + + if (listview.SelectedItems.Count <= 0) + return; + + ODentry od = (ODentry)listview.SelectedItems[0].Tag; if ((od != selectedObject || e.Button == MouseButtons.Right) && !Checkdirty()) { @@ -602,6 +608,16 @@ private void ListView_objects_MouseClick(object sender, MouseEventArgs e) PopulateObject(); PopulateSubList(); + } + else { + //selectedObject = lastSelectedObject; + //od = selectedObject; + //selectedList.Select(); + //string indesnew = "0x" + Convert.ToString(selectedObject.Index, 16); + //ListViewItem itemnew = selectedList.FindItemWithText(indesnew); + //listview.FocusedItem = itemnew; + //listView_subObjects.Focus(); + } listView_communication_objects.HideSelection = true; listView_deviceProfile_objects.HideSelection = true; @@ -609,7 +625,8 @@ private void ListView_objects_MouseClick(object sender, MouseEventArgs e) } private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) - { + { + ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); } diff --git a/EDSEditorGUI/DeviceView.Designer.cs b/EDSEditorGUI/DeviceView.Designer.cs index 51039581..16c3efe1 100644 --- a/EDSEditorGUI/DeviceView.Designer.cs +++ b/EDSEditorGUI/DeviceView.Designer.cs @@ -60,10 +60,9 @@ private void InitializeComponent() // this.tabPage4.Controls.Add(this.devicePDOView2); this.tabPage4.ImageIndex = 3; - this.tabPage4.Location = new System.Drawing.Point(4, 25); - this.tabPage4.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage4.Location = new System.Drawing.Point(4, 23); this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(1488, 922); + this.tabPage4.Size = new System.Drawing.Size(1114, 746); this.tabPage4.TabIndex = 3; this.tabPage4.Text = "RX PDO Mapping"; this.tabPage4.UseVisualStyleBackColor = true; @@ -74,19 +73,18 @@ private void InitializeComponent() this.devicePDOView2.AutoSize = true; this.devicePDOView2.Dock = System.Windows.Forms.DockStyle.Fill; this.devicePDOView2.Location = new System.Drawing.Point(0, 0); - this.devicePDOView2.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.devicePDOView2.Margin = new System.Windows.Forms.Padding(4); this.devicePDOView2.Name = "devicePDOView2"; - this.devicePDOView2.Size = new System.Drawing.Size(1488, 922); + this.devicePDOView2.Size = new System.Drawing.Size(1114, 746); this.devicePDOView2.TabIndex = 0; // // tabPage3 // this.tabPage3.Controls.Add(this.devicePDOView1); this.tabPage3.ImageIndex = 2; - this.tabPage3.Location = new System.Drawing.Point(4, 25); - this.tabPage3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage3.Location = new System.Drawing.Point(4, 23); this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(1488, 922); + this.tabPage3.Size = new System.Drawing.Size(1114, 746); this.tabPage3.TabIndex = 2; this.tabPage3.Text = "TX PDO Mapping"; this.tabPage3.UseVisualStyleBackColor = true; @@ -97,20 +95,19 @@ private void InitializeComponent() this.devicePDOView1.AutoSize = true; this.devicePDOView1.Dock = System.Windows.Forms.DockStyle.Fill; this.devicePDOView1.Location = new System.Drawing.Point(0, 0); - this.devicePDOView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.devicePDOView1.Margin = new System.Windows.Forms.Padding(4); this.devicePDOView1.Name = "devicePDOView1"; - this.devicePDOView1.Size = new System.Drawing.Size(1488, 922); + this.devicePDOView1.Size = new System.Drawing.Size(1114, 746); this.devicePDOView1.TabIndex = 0; // // tabPage2 // this.tabPage2.Controls.Add(this.deviceODView1); this.tabPage2.ImageIndex = 0; - this.tabPage2.Location = new System.Drawing.Point(4, 25); - this.tabPage2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage2.Location = new System.Drawing.Point(4, 23); this.tabPage2.Name = "tabPage2"; - this.tabPage2.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage2.Size = new System.Drawing.Size(1488, 922); + this.tabPage2.Padding = new System.Windows.Forms.Padding(3); + this.tabPage2.Size = new System.Drawing.Size(1114, 746); this.tabPage2.TabIndex = 0; this.tabPage2.Text = "Object Dictionary"; this.tabPage2.UseVisualStyleBackColor = true; @@ -118,21 +115,20 @@ private void InitializeComponent() // deviceODView1 // this.deviceODView1.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceODView1.Location = new System.Drawing.Point(4, 4); - this.deviceODView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.deviceODView1.Location = new System.Drawing.Point(3, 3); + this.deviceODView1.Margin = new System.Windows.Forms.Padding(4); this.deviceODView1.Name = "deviceODView1"; - this.deviceODView1.Size = new System.Drawing.Size(1480, 914); + this.deviceODView1.Size = new System.Drawing.Size(1108, 740); this.deviceODView1.TabIndex = 0; // // tabPage1 // this.tabPage1.Controls.Add(this.deviceInfoView); this.tabPage1.ImageIndex = 1; - this.tabPage1.Location = new System.Drawing.Point(4, 25); - this.tabPage1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage1.Location = new System.Drawing.Point(4, 23); this.tabPage1.Name = "tabPage1"; - this.tabPage1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage1.Size = new System.Drawing.Size(1488, 922); + this.tabPage1.Padding = new System.Windows.Forms.Padding(3); + this.tabPage1.Size = new System.Drawing.Size(1114, 746); this.tabPage1.TabIndex = 1; this.tabPage1.Text = "Device Info"; this.tabPage1.UseVisualStyleBackColor = true; @@ -140,10 +136,10 @@ private void InitializeComponent() // deviceInfoView // this.deviceInfoView.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceInfoView.Location = new System.Drawing.Point(4, 4); - this.deviceInfoView.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.deviceInfoView.Location = new System.Drawing.Point(3, 3); + this.deviceInfoView.Margin = new System.Windows.Forms.Padding(4); this.deviceInfoView.Name = "deviceInfoView"; - this.deviceInfoView.Size = new System.Drawing.Size(1480, 914); + this.deviceInfoView.Size = new System.Drawing.Size(1108, 740); this.deviceInfoView.TabIndex = 0; // // tabControl1 @@ -155,20 +151,18 @@ private void InitializeComponent() this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl1.ImageList = this.imageList1; this.tabControl1.Location = new System.Drawing.Point(0, 0); - this.tabControl1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(1496, 951); + this.tabControl1.Size = new System.Drawing.Size(1122, 773); this.tabControl1.TabIndex = 1; // // DeviceView // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.Controls.Add(this.tabControl1); - this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); this.Name = "DeviceView"; - this.Size = new System.Drawing.Size(1496, 951); + this.Size = new System.Drawing.Size(1122, 773); this.tabPage4.ResumeLayout(false); this.tabPage4.PerformLayout(); this.tabPage3.ResumeLayout(false); diff --git a/EDSEditorGUI/DeviceView.cs b/EDSEditorGUI/DeviceView.cs index 51f001db..536af994 100644 --- a/EDSEditorGUI/DeviceView.cs +++ b/EDSEditorGUI/DeviceView.cs @@ -84,8 +84,8 @@ public void dispatch_updatedevice() deviceInfoView.populatedeviceinfo(); - //moduleInfo1.eds = eds; - //moduleInfo1.populatemoduleinfo(); + //moduleInfo.eds = eds; + //moduleInfo.populatemoduleinfo(); } public void dispatch_updatePDOinfo() diff --git a/EDSEditorGUI/DeviceView.resx b/EDSEditorGUI/DeviceView.resx index 8e4e9474..4b423794 100644 --- a/EDSEditorGUI/DeviceView.resx +++ b/EDSEditorGUI/DeviceView.resx @@ -125,7 +125,7 @@ AAEAAAD/////AQAAAAAAAAAMAgAAAFdTeXN0ZW0uV2luZG93cy5Gb3JtcywgVmVyc2lvbj00LjAuMC4w LCBDdWx0dXJlPW5ldXRyYWwsIFB1YmxpY0tleVRva2VuPWI3N2E1YzU2MTkzNGUwODkFAQAAACZTeXN0 ZW0uV2luZG93cy5Gb3Jtcy5JbWFnZUxpc3RTdHJlYW1lcgEAAAAERGF0YQcCAgAAAAkDAAAADwMAAACk - CgAAAk1TRnQBSQFMAgEBBAEAAWgBAAFoAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo + CgAAAk1TRnQBSQFMAgEBBAEAAaABAAGgAQABEAEAARABAAT/AQkBAAj/AUIBTQE2AQQGAAE2AQQCAAEo AwABQAMAASADAAEBAQABCAYAAQgYAAGAAgABgAMAAoABAAGAAwABgAEAAYABAAKAAgADwAEAAcAB3AHA AQAB8AHKAaYBAAEzBQABMwEAATMBAAEzAQACMwIAAxYBAAMcAQADIgEAAykBAANVAQADTQEAA0IBAAM5 AQABgAF8Af8BAAJQAf8BAAGTAQAB1gEAAf8B7AHMAQABxgHWAe8BAAHWAucBAAGQAakBrQIAAf8BMwMA diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 43bbd99a..bd713c33 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -9,7 +9,7 @@ Properties ODEditor EDSEditor - v4.8 + v4.8.1 512 false diff --git a/EDSEditorGUI/Properties/Settings.Designer.cs b/EDSEditorGUI/Properties/Settings.Designer.cs index 828c6e10..04412fe2 100644 --- a/EDSEditorGUI/Properties/Settings.Designer.cs +++ b/EDSEditorGUI/Properties/Settings.Designer.cs @@ -12,7 +12,7 @@ namespace ODEditor.Properties { [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.1.0.0")] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); diff --git a/EDSSharp/App.config b/EDSSharp/App.config index 8a99d30d..2423eab0 100644 --- a/EDSSharp/App.config +++ b/EDSSharp/App.config @@ -1,6 +1,6 @@ - + diff --git a/EDSSharp/EDSSharp.csproj b/EDSSharp/EDSSharp.csproj index e0b139bb..6e4cebd6 100644 --- a/EDSSharp/EDSSharp.csproj +++ b/EDSSharp/EDSSharp.csproj @@ -8,7 +8,7 @@ Exe EDSSharp EDSSharp - v4.8 + v4.8.1 512 true diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index c7fe31fa..f779d4e8 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -506,6 +506,15 @@ CANopen DATA TYPES } file.WriteLine(string.Format(" #define CO_NO_LSS_CLIENT {0} //LSS Master", lssClient)); + int ngSlave = 0; + if (eds.di.NG_Slave == true) + { + ngSlave = 1; + } + file.WriteLine(string.Format(" #define CO_NODE_GUARDING_SLAVE {0} //NG Slave", ngSlave)); + + file.WriteLine(string.Format(" #define CO_NODE_GUARDING_MASTER {0} //NG Master", eds.di.NrOfNG_MonitoredNodes)); + file.WriteLine(string.Format(" #define CO_NO_RPDO {0} //Associated objects: 14xx, 16xx", noRXpdos)); file.WriteLine(string.Format(" #define CO_NO_TPDO {0} //Associated objects: 18xx, 1Axx", noTXpdos)); diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index f35afc97..439bb626 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -645,6 +645,7 @@ public ISO15745ProfileContainer convert(EDSsharp eds) NetworkManagement.CANopenGeneralFeatures.nrOfRxPDO = eds.di.NrOfRXPDO; NetworkManagement.CANopenGeneralFeatures.nrOfTxPDO = eds.di.NrOfTXPDO; //extra items + //NetworkManagment.CANopenGeneralFeatures.SDORequestingDevice; //NetworkManagment.CANopenGeneralFeatures.selfStartingDevice; diff --git a/libEDSsharp/DocumentationGen.cs b/libEDSsharp/DocumentationGen.cs index 606cea0d..9b18e144 100644 --- a/libEDSsharp/DocumentationGen.cs +++ b/libEDSsharp/DocumentationGen.cs @@ -199,9 +199,11 @@ Device Information | TPDO count | {6,-30} | | LSS Slave | {7,-30} | | LSS Master | {8,-30} | +| NG Slave | {9,-30} | +| NG Master | {10,-30} | ", eds.di.VendorName, eds.di.VendorNumber, eds.di.ProductName, eds.di.ProductNumber, eds.di.Granularity, eds.di.NrOfRXPDO.ToString(), eds.di.NrOfTXPDO.ToString(), - eds.di.LSS_Supported, eds.di.LSS_Master)); + eds.di.LSS_Supported, eds.di.LSS_Master, eds.di.NG_Slave, eds.di.NG_Master)); file.WriteLine($"#### Supported Baud rates"); file.WriteLine($"* [{(eds.di.BaudRate_10 ? "x" : " ")}] 10 kBit/s"); diff --git a/libEDSsharp/Properties/Resources.Designer.cs b/libEDSsharp/Properties/Resources.Designer.cs new file mode 100644 index 00000000..a5a81006 --- /dev/null +++ b/libEDSsharp/Properties/Resources.Designer.cs @@ -0,0 +1,63 @@ +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace libEDSsharp.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("libEDSsharp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/libEDSsharp/Properties/Resources.resx b/libEDSsharp/Properties/Resources.resx new file mode 100644 index 00000000..85c90909 --- /dev/null +++ b/libEDSsharp/Properties/Resources.resx @@ -0,0 +1,101 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.3500.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/libEDSsharp/docs/libEDSsharp.xml b/libEDSsharp/docs/libEDSsharp.xml index eb2d6432..b31722ad 100644 --- a/libEDSsharp/docs/libEDSsharp.xml +++ b/libEDSsharp/docs/libEDSsharp.xml @@ -335,6 +335,22 @@ + + + Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + + + + + Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + + + + + Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + + diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 3ab925b3..c16f1581 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -27,6 +27,8 @@ You should have received a copy of the GNU General Public License using CanOpenXSD_1_1; using System.Runtime.Remoting.Messaging; using System.Net.NetworkInformation; +using System.Security.Cryptography; +using Xml2CSharp; namespace libEDSsharp { @@ -792,7 +794,15 @@ public class DeviceInfo : InfoSection [EdsExport] public bool LSS_Supported; - public bool LSS_Master; + public bool LSS_Master; + + [EdsExport] + public bool NG_Slave; + + public bool NG_Master; + + [EdsExport] + public UInt16 NrOfNG_MonitoredNodes=0; public DeviceInfo() { @@ -2137,10 +2147,15 @@ public void ParseEDSentry(KeyValuePair> kvp) Match m2 = r2.Match(m.Groups[0].ToString()); if (m2.Success) - { + { + UInt16 modindex=0, odindex=0; + + try { modindex = Convert.ToUInt16(m2.Groups[1].Value); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + m2.Groups[1].Value); } + //Indexes in the EDS are always in hex format without the pre 0x + try { odindex = Convert.ToUInt16(m2.Groups[3].Value, 16); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + m2.Groups[3].Value); } - UInt16 modindex = Convert.ToUInt16(m2.Groups[1].Value); - UInt16 odindex = Convert.ToUInt16(m2.Groups[3].Value); if (!modules.ContainsKey(modindex)) modules.Add(modindex, new Module(modindex)); @@ -2211,13 +2226,41 @@ public void ParseEDSentry(KeyValuePair> kvp) } if (kvp.Value.ContainsKey("Count")) - { - od.count = Convert.ToByte(kvp.Value["Count"]); + { + /* FIXME: The format of "Count" is Unsigned8[; Unsigned8] according DS306 + * Count: + Number of extended Sub-Indexes with this description that are created per module. The format is Unsigned8 [; Unsigned8]. + If one or more Sub - Indexes are created per attached module to build a new sub- index, then Count is that Number. In example 32 bit module creates 4 Sub - Indexes each having 8 Bit: Count = 4 + If several modules are gathered to form a new Sub- Index, then the number is 0, followed by semicolon and the number of bits that are created per module to build a new Sub-Index.In example 2 bit modules with 8 bit objects: The first Sub - Index is built upon modules 1 - 4, the next upon modules 5 - 8 etc.: Count = 0; 2.The objects are created, when a new byte begins: Module 1 creates the Sub - Index 1; modules 2 - 4 fill it up; module 5 creates Sub-Index 2 and so forth. + */ + pat2 = @"\s*([0-9a-fA-F]+)\s*;\s*([0-9a-fA-F]+)"; + r2 = new Regex(pat2, RegexOptions.IgnoreCase); + m2 = r2.Match(kvp.Value["Count"]); + + + + if (m2.Success) + { + Console.WriteLine("** FIXME Count format not supported ** Count: " + kvp.Value["Count"]); + int found = kvp.Value["Count"].IndexOf(";"); + string s = kvp.Value["Count"].Substring(found + 1); + try { od.count = Convert.ToByte(s, Getbase(s)); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } + } + else + { + + try { od.count = Convert.ToByte(kvp.Value["Count"], Getbase(kvp.Value["Count"])); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } + } + } if (kvp.Value.ContainsKey("ObjExtend")) { - od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); + try { od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** ObjExtend:" + kvp.Value["ObjExtend"]); } + } @@ -2228,23 +2271,30 @@ public void ParseEDSentry(KeyValuePair> kvp) throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); if (kvp.Value.ContainsKey("ParameterValue")) - { - od.actualvalue = kvp.Value["ParameterValue"]; + { + + try { od.actualvalue = kvp.Value["ParameterValue"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** ParameterValue:" + kvp.Value["ParameterValue"]); } } if (kvp.Value.ContainsKey("HighLimit")) - { - od.HighLimit = kvp.Value["HighLimit"]; + { + try { od.HighLimit = kvp.Value["HighLimit"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** HighLimit:" + kvp.Value["HighLimit"]); } } if (kvp.Value.ContainsKey("LowLimit")) - { - od.LowLimit = kvp.Value["LowLimit"]; + { + try { od.LowLimit = kvp.Value["LowLimit"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** LowLimit:" + kvp.Value["LowLimit"]); } } if (kvp.Value.ContainsKey("Denotation")) - { - od.denotation = kvp.Value["Denotation"]; + { + try { od.denotation = kvp.Value["Denotation"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Denotation:" + kvp.Value["Denotation"]); } + + } if (m.Groups[5].Length != 0) @@ -2381,7 +2431,7 @@ public void Loadfile(string filename) //try { int lineno = 1; - foreach (string linex in File.ReadLines(filename)) + foreach (string linex in System.IO.File.ReadLines(filename)) { Parseline(linex,lineno); lineno++; @@ -2390,8 +2440,11 @@ public void Loadfile(string filename) di = new DeviceInfo(eds["DeviceInfo"]); foreach (KeyValuePair> kvp in eds) - { - ParseEDSentry(kvp); + { + + try { ParseEDSentry(kvp); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + kvp); } + } fi = new FileInfo(eds["FileInfo"]); @@ -2440,7 +2493,7 @@ public void Loadfile(string filename) foreach (string s in eds.Keys) { - String pat = @"^M([0-9]+)ModuleInfo"; + String pat = @"M([0-9]+)ModuleInfo"; Regex r = new Regex(pat, RegexOptions.IgnoreCase); Match m = r.Match(s); @@ -2457,7 +2510,7 @@ public void Loadfile(string filename) } - pat = @"^M([0-9]+)Comments"; + pat = @"M([0-9]+)Comments"; r = new Regex(pat, RegexOptions.IgnoreCase); m = r.Match(s); @@ -2472,8 +2525,7 @@ public void Loadfile(string filename) modules[modindex].mc = mc; } - - pat = @"^M([0-9]+)SubExtends"; + pat = @"M([0-9]+)SubExtends"; r = new Regex(pat, RegexOptions.IgnoreCase); m = r.Match(s); @@ -2490,7 +2542,8 @@ public void Loadfile(string filename) //DCF only - pat = @"^M([0-9]+)FixedObjects"; + + pat = @"M([0-9]+)FixedObjects"; r = new Regex(pat, RegexOptions.IgnoreCase); m = r.Match(s); @@ -2658,7 +2711,7 @@ public void Savefile(string filename, InfoSection.Filetype ft) fi.EDSVersionMajor = 4; fi.EDSVersionMinor = 0; - StreamWriter writer = File.CreateText(filename); + StreamWriter writer = System.IO.File.CreateText(filename); writer.NewLine = "\n"; fi.Write(writer,ft); di.Write(writer,ft); diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 8962b7de..5b6c3000 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -9,7 +9,7 @@ Properties libEDSsharp libEDSsharp - v4.8 + v4.8.1 512 @@ -57,10 +57,21 @@ + + True + True + Resources.resx + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + @@ -15,7 +15,7 @@ CANopen - + @@ -769,6 +769,22 @@ + + The objects at index 100Ch and 100Dh include the guard time in milliseconds and the life time factor. + +The life time factor multiplied with the guard time gives the life time for the Life Guarding Protocol. It is + +0 if not used. + + + + + The life time factor multiplied with the guard time gives the life time for the node guarding protocol. It is + +0 if not used. + + + Sub-indexes 1 and above: * Reading provides information about its storage functionality: @@ -2277,7 +2293,7 @@ CANopen - + @@ -2308,6 +2324,8 @@ + + From ea727a681792a19543d75f653791a0de03c55702 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 31 Oct 2023 12:50:16 +0100 Subject: [PATCH 104/226] - Bugfix NodeGuarding index in profile file --- EDSEditorGUI/Profiles/DS301_profile.xpd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 117b4b93..a553570f 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -769,7 +769,7 @@ - + The objects at index 100Ch and 100Dh include the guard time in milliseconds and the life time factor. The life time factor multiplied with the guard time gives the life time for the Life Guarding Protocol. It is @@ -778,7 +778,7 @@ The life time factor multiplied with the guard time gives the life time for the - + The life time factor multiplied with the guard time gives the life time for the node guarding protocol. It is 0 if not used. @@ -2324,8 +2324,8 @@ The life time factor multiplied with the guard time gives the life time for the - - + + From bfad860e0e20cb4edab92f7a29610e8b6be384af Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 10 Nov 2023 14:18:07 +0100 Subject: [PATCH 105/226] show context menu on ColumnClick if list is empty V4 exporter: Create empty (NULL) string objects if no default value and throw warning --- EDSEditorGUI/DeviceODView.Designer.cs | 4 +- EDSEditorGUI/DeviceODView.cs | 11 ++- EDSEditorGUI/Profiles/DS301_profile.xpd | 4 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 96 +++++++++++++++---------- 4 files changed, 70 insertions(+), 45 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index 75f379cb..aea57c48 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -497,9 +497,9 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.comboBox_accessPDO); this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; this.groupBox1.Location = new System.Drawing.Point(0, 329); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Padding = new System.Windows.Forms.Padding(2); this.groupBox1.Size = new System.Drawing.Size(854, 188); this.groupBox1.TabIndex = 33; this.groupBox1.TabStop = false; diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index b7ded4ce..ff4c0577 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -589,9 +589,9 @@ private void ObjectSave() private void ListView_objects_MouseClick(object sender, MouseEventArgs e) { - ListView listview = (ListView)sender; + ListView listview = (ListView)sender; - if (listview.SelectedItems.Count <= 0) + if (listview.SelectedItems.Count <= 0 ) return; ODentry od = (ODentry)listview.SelectedItems[0].Tag; @@ -632,7 +632,12 @@ private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) private void ListView_objects_ColumnClick(object sender, ColumnClickEventArgs e) { - ((ListView)sender).SelectedItems.Clear(); + ((ListView)sender).SelectedItems.Clear(); + + contextMenu_object.Show(Cursor.Position); + PopulateObject(); + PopulateSubList(); + ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0)); } diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 117b4b93..ad6ba063 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -15,7 +15,7 @@ CANopen - + @@ -2293,7 +2293,7 @@ The life time factor multiplied with the guard time gives the life time for the CANopen - + diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 57962c66..8466e11d 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -190,7 +190,11 @@ private void VerifyCountLabel(ODentry od, ushort indexL, ushort indexH, string c /// private int Prepare_var(ODentry od, string indexH, string varName, string group) { - DataProperties data = Get_dataProperties(od.datatype, od.defaultvalue, od.prop.CO_stringLengthMin, indexH); + DataProperties data = Get_dataProperties(od.datatype, od.defaultvalue, od.prop.CO_stringLengthMin, indexH); + + if ((data.length == 0) && (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.UNICODE_STRING)) + Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex), Warnings.warning_class.WARNING_STRING); + string attr = Get_attributes(od, data.cTypeMultibyte, data.cTypeString); // data storage @@ -246,6 +250,11 @@ private int Prepare_arr(ODentry od, string indexH, string varName, string group) DataType dataType = (sub.datatype != DataType.UNKNOWN) ? sub.datatype : od.datatype; DataProperties data = Get_dataProperties(dataType, sub.defaultvalue, sub.prop.CO_stringLengthMin, indexH); + + if ((data.length == 0) && (dataType == DataType.VISIBLE_STRING || dataType == DataType.UNICODE_STRING)) + Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex), Warnings.warning_class.WARNING_STRING); + + string attr = Get_attributes(sub, data.cTypeMultibyte, data.cTypeString); if (sub.Subindex != i) @@ -338,7 +347,11 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) foreach (ODentry sub in od.subobjects.Values) { - DataProperties data = Get_dataProperties(sub.datatype, sub.defaultvalue, sub.prop.CO_stringLengthMin, indexH); + DataProperties data = Get_dataProperties(sub.datatype, sub.defaultvalue, sub.prop.CO_stringLengthMin, indexH); + + if ((data.length == 0) && (sub.datatype == DataType.VISIBLE_STRING || sub.datatype == DataType.UNICODE_STRING )) + Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex), Warnings.warning_class.WARNING_STRING); + string attr = Get_attributes(sub, data.cTypeMultibyte, data.cTypeString); if (sub.Subindex == 0 && (data.cType != "uint8_t" || data.length != 1)) @@ -605,8 +618,11 @@ OD data initialization of all groups } // remove ',' from the last element - string s = ODObjs[ODObjs.Count - 1]; - ODObjs[ODObjs.Count - 1] = s.Remove(s.Length - 1); + if (ODObjs.Count > 0) + { + string s = ODObjs[ODObjs.Count - 1]; + ODObjs[ODObjs.Count - 1] = s.Remove(s.Length - 1); + } file.WriteLine(string.Format(@" @@ -768,7 +784,8 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue try { bool signedNumber = false; - bool unsignedNumber = false; + bool unsignedNumber = false; + UInt32 len = 0; switch (dataType) { @@ -871,17 +888,16 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue } break; - case DataType.DOMAIN: - // keep default values (0 and null) + case DataType.DOMAIN: + // keep default values (0 and null) + data.cType = "uint8_t"; break; case DataType.VISIBLE_STRING: - data.cTypeString = true; + data.cTypeString = true; + List chars = new List(); if (valueDefined || stringLength > 0) { - List chars = new List(); - UInt32 len = 0; - if (valueDefined) { UTF8Encoding utf8 = new UTF8Encoding(); @@ -905,25 +921,26 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue chars.Add("0"); } - // extra string terminator - chars.Add("0"); - - data.length = len; - data.cType = "char"; - data.cTypeArray = $"[{len + 1}]"; - data.cTypeArray0 = "[0]"; - data.cValue = $"{{{string.Join(", ", chars)}}}"; - } + } + // extra string terminator + chars.Add("0"); + data.length = len; + + data.cType = "char"; + data.cTypeArray = $"[{len + 1}]"; + data.cTypeArray0 = "[0]"; + + data.cValue = $"{{{string.Join(", ", chars)}}}"; break; case DataType.OCTET_STRING: - defaultvalue = defaultvalue.Trim(); + defaultvalue = defaultvalue.Trim(); + List bytes = new List(); if (defaultvalue == "") valueDefined = false; if (valueDefined || stringLength > 0) { - List bytes = new List(); - UInt32 len = 0; + if (valueDefined) { @@ -939,19 +956,20 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue bytes.Add("0x00"); } - data.length = len; - data.cType = "uint8_t"; - data.cTypeArray = $"[{len}]"; - data.cTypeArray0 = "[0]"; + data.cValue = $"{{{string.Join(", ", bytes)}}}"; - } + } + data.length = len; + data.cType = "uint8_t"; + data.cTypeArray = $"[{len}]"; + data.cTypeArray0 = "[0]"; break; case DataType.UNICODE_STRING: - data.cTypeString = true; + data.cTypeString = true; + List words = new List(); if (valueDefined || stringLength > 0) { - List words = new List(); - UInt32 len = 0; + if (valueDefined) { @@ -969,15 +987,17 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue words.Add("0x0000"); } - // extra string terminator - words.Add("0x0000"); - data.length = len * 2; - data.cType = "uint16_t"; - data.cTypeArray = $"[{len + 1}]"; - data.cTypeArray0 = "[0]"; + + data.cValue = $"{{{string.Join(", ", words)}}}"; - } + } + // extra string terminator + words.Add("0x0000"); + data.length = len * 2; + data.cType = "uint16_t"; + data.cTypeArray = $"[{len + 1}]"; + data.cTypeArray0 = "[0]"; break; case DataType.INTEGER24: From ea3c0e5bd5522b8d90c8ee1b4d472ca70befb4a5 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Fri, 10 Nov 2023 14:28:32 +0100 Subject: [PATCH 106/226] Revert "Merge branch 'bugfix' of https://github.com/CANopenNode/CANopenEditor into bugfix" This reverts commit b7283a1a1909cf961a6a0bee7573fafb8d1ecb67, reversing changes made to bfad860e0e20cb4edab92f7a29610e8b6be384af. Revert "show context menu on ColumnClick if list is empty" This reverts commit bfad860e0e20cb4edab92f7a29610e8b6be384af. --- EDSEditorGUI/DeviceODView.Designer.cs | 4 +- EDSEditorGUI/DeviceODView.cs | 11 +-- EDSEditorGUI/Profiles/DS301_profile.xpd | 12 ++-- libEDSsharp/CanOpenNodeExporter_V4.cs | 96 ++++++++++--------------- 4 files changed, 49 insertions(+), 74 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index aea57c48..75f379cb 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -497,9 +497,9 @@ private void InitializeComponent() this.groupBox1.Controls.Add(this.comboBox_accessPDO); this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; this.groupBox1.Location = new System.Drawing.Point(0, 329); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2); + this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); this.groupBox1.Size = new System.Drawing.Size(854, 188); this.groupBox1.TabIndex = 33; this.groupBox1.TabStop = false; diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index ff4c0577..b7ded4ce 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -589,9 +589,9 @@ private void ObjectSave() private void ListView_objects_MouseClick(object sender, MouseEventArgs e) { - ListView listview = (ListView)sender; + ListView listview = (ListView)sender; - if (listview.SelectedItems.Count <= 0 ) + if (listview.SelectedItems.Count <= 0) return; ODentry od = (ODentry)listview.SelectedItems[0].Tag; @@ -632,12 +632,7 @@ private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) private void ListView_objects_ColumnClick(object sender, ColumnClickEventArgs e) { - ((ListView)sender).SelectedItems.Clear(); - - contextMenu_object.Show(Cursor.Position); - PopulateObject(); - PopulateSubList(); - + ((ListView)sender).SelectedItems.Clear(); ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0)); } diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 8a5f5f47..117b4b93 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -15,7 +15,7 @@ CANopen - + @@ -769,7 +769,7 @@ - + The objects at index 100Ch and 100Dh include the guard time in milliseconds and the life time factor. The life time factor multiplied with the guard time gives the life time for the Life Guarding Protocol. It is @@ -778,7 +778,7 @@ The life time factor multiplied with the guard time gives the life time for the - + The life time factor multiplied with the guard time gives the life time for the node guarding protocol. It is 0 if not used. @@ -2293,7 +2293,7 @@ The life time factor multiplied with the guard time gives the life time for the CANopen - + @@ -2324,8 +2324,8 @@ The life time factor multiplied with the guard time gives the life time for the - - + + diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 8466e11d..57962c66 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -190,11 +190,7 @@ private void VerifyCountLabel(ODentry od, ushort indexL, ushort indexH, string c /// private int Prepare_var(ODentry od, string indexH, string varName, string group) { - DataProperties data = Get_dataProperties(od.datatype, od.defaultvalue, od.prop.CO_stringLengthMin, indexH); - - if ((data.length == 0) && (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.UNICODE_STRING)) - Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex), Warnings.warning_class.WARNING_STRING); - + DataProperties data = Get_dataProperties(od.datatype, od.defaultvalue, od.prop.CO_stringLengthMin, indexH); string attr = Get_attributes(od, data.cTypeMultibyte, data.cTypeString); // data storage @@ -250,11 +246,6 @@ private int Prepare_arr(ODentry od, string indexH, string varName, string group) DataType dataType = (sub.datatype != DataType.UNKNOWN) ? sub.datatype : od.datatype; DataProperties data = Get_dataProperties(dataType, sub.defaultvalue, sub.prop.CO_stringLengthMin, indexH); - - if ((data.length == 0) && (dataType == DataType.VISIBLE_STRING || dataType == DataType.UNICODE_STRING)) - Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex), Warnings.warning_class.WARNING_STRING); - - string attr = Get_attributes(sub, data.cTypeMultibyte, data.cTypeString); if (sub.Subindex != i) @@ -347,11 +338,7 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) foreach (ODentry sub in od.subobjects.Values) { - DataProperties data = Get_dataProperties(sub.datatype, sub.defaultvalue, sub.prop.CO_stringLengthMin, indexH); - - if ((data.length == 0) && (sub.datatype == DataType.VISIBLE_STRING || sub.datatype == DataType.UNICODE_STRING )) - Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex), Warnings.warning_class.WARNING_STRING); - + DataProperties data = Get_dataProperties(sub.datatype, sub.defaultvalue, sub.prop.CO_stringLengthMin, indexH); string attr = Get_attributes(sub, data.cTypeMultibyte, data.cTypeString); if (sub.Subindex == 0 && (data.cType != "uint8_t" || data.length != 1)) @@ -618,11 +605,8 @@ OD data initialization of all groups } // remove ',' from the last element - if (ODObjs.Count > 0) - { - string s = ODObjs[ODObjs.Count - 1]; - ODObjs[ODObjs.Count - 1] = s.Remove(s.Length - 1); - } + string s = ODObjs[ODObjs.Count - 1]; + ODObjs[ODObjs.Count - 1] = s.Remove(s.Length - 1); file.WriteLine(string.Format(@" @@ -784,8 +768,7 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue try { bool signedNumber = false; - bool unsignedNumber = false; - UInt32 len = 0; + bool unsignedNumber = false; switch (dataType) { @@ -888,16 +871,17 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue } break; - case DataType.DOMAIN: - // keep default values (0 and null) - data.cType = "uint8_t"; + case DataType.DOMAIN: + // keep default values (0 and null) break; case DataType.VISIBLE_STRING: - data.cTypeString = true; - List chars = new List(); + data.cTypeString = true; if (valueDefined || stringLength > 0) { + List chars = new List(); + UInt32 len = 0; + if (valueDefined) { UTF8Encoding utf8 = new UTF8Encoding(); @@ -921,26 +905,25 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue chars.Add("0"); } - } - // extra string terminator - chars.Add("0"); - data.length = len; - - data.cType = "char"; - data.cTypeArray = $"[{len + 1}]"; - data.cTypeArray0 = "[0]"; - - data.cValue = $"{{{string.Join(", ", chars)}}}"; + // extra string terminator + chars.Add("0"); + + data.length = len; + data.cType = "char"; + data.cTypeArray = $"[{len + 1}]"; + data.cTypeArray0 = "[0]"; + data.cValue = $"{{{string.Join(", ", chars)}}}"; + } break; case DataType.OCTET_STRING: - defaultvalue = defaultvalue.Trim(); - List bytes = new List(); + defaultvalue = defaultvalue.Trim(); if (defaultvalue == "") valueDefined = false; if (valueDefined || stringLength > 0) { - + List bytes = new List(); + UInt32 len = 0; if (valueDefined) { @@ -956,20 +939,19 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue bytes.Add("0x00"); } - + data.length = len; + data.cType = "uint8_t"; + data.cTypeArray = $"[{len}]"; + data.cTypeArray0 = "[0]"; data.cValue = $"{{{string.Join(", ", bytes)}}}"; - } - data.length = len; - data.cType = "uint8_t"; - data.cTypeArray = $"[{len}]"; - data.cTypeArray0 = "[0]"; + } break; case DataType.UNICODE_STRING: - data.cTypeString = true; - List words = new List(); + data.cTypeString = true; if (valueDefined || stringLength > 0) { - + List words = new List(); + UInt32 len = 0; if (valueDefined) { @@ -987,17 +969,15 @@ private DataProperties Get_dataProperties(DataType dataType, string defaultvalue words.Add("0x0000"); } + // extra string terminator + words.Add("0x0000"); - - + data.length = len * 2; + data.cType = "uint16_t"; + data.cTypeArray = $"[{len + 1}]"; + data.cTypeArray0 = "[0]"; data.cValue = $"{{{string.Join(", ", words)}}}"; - } - // extra string terminator - words.Add("0x0000"); - data.length = len * 2; - data.cType = "uint16_t"; - data.cTypeArray = $"[{len + 1}]"; - data.cTypeArray0 = "[0]"; + } break; case DataType.INTEGER24: From 7895516ad470b7fd83dd69f6465415c8e401e298 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Sun, 12 Nov 2023 16:34:41 +0100 Subject: [PATCH 107/226] revert 7dae47c638372c3331da4516a492c13ed20bc7dd Details in #73 --- libEDSsharp/CanOpenNodeExporter_V4.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 57962c66..2f142611 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -195,13 +195,13 @@ private int Prepare_var(ODentry od, string indexH, string varName, string group) // data storage string dataPtr = "NULL"; - ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); if (data.cValue != null) { + ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); ODStorage[group].Add($".x{varName} = {data.cValue}"); + dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; } - dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; // objects ODObjs_t.Add($"OD_obj_var_t o_{varName};"); ODObjs.Add($" .o_{varName} = {{"); @@ -346,12 +346,12 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) string subcName = Make_cname(sub.parameter_name); string dataPtr = "NULL"; - subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); if (data.cValue != null) { + subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); subODStorage.Add($".{subcName} = {data.cValue}"); + dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; } - dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; ODObjs.Add($" {{"); ODObjs.Add($" .dataOrig = {dataPtr},"); ODObjs.Add($" .subIndex = {sub.Subindex},"); From 88b9e52f8e8826e0fe4a385121e01b07c7e4b8fa Mon Sep 17 00:00:00 2001 From: Janez Date: Sat, 18 Nov 2023 12:14:53 +0100 Subject: [PATCH 108/226] DS301_profile.xpd updated for Node guarding. --- EDSEditorGUI/Profiles/DS301_profile.xpd | 18 +++++++++++------- libEDSsharp/CanOpenNodeExporter_V4.cs | 12 ++++++------ 2 files changed, 17 insertions(+), 13 deletions(-) diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 117b4b93..224c5da5 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -1,5 +1,5 @@ - + @@ -15,7 +15,7 @@ CANopen - + @@ -769,7 +769,7 @@ - + The objects at index 100Ch and 100Dh include the guard time in milliseconds and the life time factor. The life time factor multiplied with the guard time gives the life time for the Life Guarding Protocol. It is @@ -777,13 +777,17 @@ The life time factor multiplied with the guard time gives the life time for the 0 if not used. + + - + The life time factor multiplied with the guard time gives the life time for the node guarding protocol. It is 0 if not used. + + Sub-indexes 1 and above: @@ -2293,7 +2297,7 @@ The life time factor multiplied with the guard time gives the life time for the CANopen - + @@ -2324,8 +2328,8 @@ The life time factor multiplied with the guard time gives the life time for the - - + + diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 2f142611..455ffd08 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -194,14 +194,14 @@ private int Prepare_var(ODentry od, string indexH, string varName, string group) string attr = Get_attributes(od, data.cTypeMultibyte, data.cTypeString); // data storage - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); ODStorage[group].Add($".x{varName} = {data.cValue}"); dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; - } - + } + // objects ODObjs_t.Add($"OD_obj_var_t o_{varName};"); ODObjs.Add($" .o_{varName} = {{"); @@ -268,7 +268,7 @@ private int Prepare_arr(ODentry od, string indexH, string varName, string group) attrElem = attr; } else - {// FixIt: There is nothing in the CiA 306 definition for EDS files that justifies these warnings! The EDSchecker from Vector would also check this object as error-free! + {// Following checks are requirement of CANopenNode. Arrays must be C arrays. if (data.cType != dataElem.cType || data.length != dataElem.length) Warnings.AddWarning($"Error in 0x{indexH}: Data type of elements in ARRAY must be equal!", Warnings.warning_class.WARNING_BUILD); if ((data.cValue == null && dataElem.cValue != null) || (data.cValue != null && dataElem.cValue == null)) @@ -345,13 +345,13 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) Warnings.AddWarning($"Error in 0x{indexH}: Data type in RECORD, subIndex 0 must be UNSIGNED8, not {sub.datatype}!", Warnings.warning_class.WARNING_BUILD); string subcName = Make_cname(sub.parameter_name); - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); subODStorage.Add($".{subcName} = {data.cValue}"); dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; - } + } ODObjs.Add($" {{"); ODObjs.Add($" .dataOrig = {dataPtr},"); ODObjs.Add($" .subIndex = {sub.Subindex},"); From cb8cfea3f24b1ebb7d337ced934df8ea83475a64 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 13 Feb 2024 08:53:25 +0100 Subject: [PATCH 109/226] correct NodeGuarding index in profile file --- EDSEditorGUI/Profiles/DS301_profile.xpd | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/EDSEditorGUI/Profiles/DS301_profile.xpd b/EDSEditorGUI/Profiles/DS301_profile.xpd index 117b4b93..a553570f 100644 --- a/EDSEditorGUI/Profiles/DS301_profile.xpd +++ b/EDSEditorGUI/Profiles/DS301_profile.xpd @@ -769,7 +769,7 @@ - + The objects at index 100Ch and 100Dh include the guard time in milliseconds and the life time factor. The life time factor multiplied with the guard time gives the life time for the Life Guarding Protocol. It is @@ -778,7 +778,7 @@ The life time factor multiplied with the guard time gives the life time for the - + The life time factor multiplied with the guard time gives the life time for the node guarding protocol. It is 0 if not used. @@ -2324,8 +2324,8 @@ The life time factor multiplied with the guard time gives the life time for the - - + + From eaa8513083939e31be9327dd7bc8a6fad3f5bf1d Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 19 Feb 2024 12:22:03 +0100 Subject: [PATCH 110/226] Buxfix extensions --- EDSEditorGUI/Form1.cs | 2 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 10 +++++----- libEDSsharp/PDOHelper.cs | 8 +++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index a7804933..c54cf88f 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -1222,7 +1222,7 @@ private void ODEditor_MainForm_DragEnter(object sender, DragEventArgs e) { this.Activate(); bool unsupportedFile = false; - string[] data = (string[]) e.Data.GetData(DataFormats.FileDrop); + string[] data = e.Data.GetData(DataFormats.FileDrop) as string[]; if (data != null) { var rawFileNames = data as string[]; diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 455ffd08..a10f41e9 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -194,14 +194,14 @@ private int Prepare_var(ODentry od, string indexH, string varName, string group) string attr = Get_attributes(od, data.cTypeMultibyte, data.cTypeString); // data storage - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); ODStorage[group].Add($".x{varName} = {data.cValue}"); dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; - } - + } + // objects ODObjs_t.Add($"OD_obj_var_t o_{varName};"); ODObjs.Add($" .o_{varName} = {{"); @@ -345,12 +345,12 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) Warnings.AddWarning($"Error in 0x{indexH}: Data type in RECORD, subIndex 0 must be UNSIGNED8, not {sub.datatype}!", Warnings.warning_class.WARNING_BUILD); string subcName = Make_cname(sub.parameter_name); - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); subODStorage.Add($".{subcName} = {data.cValue}"); - dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; + dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; } ODObjs.Add($" {{"); ODObjs.Add($" .dataOrig = {dataPtr},"); diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index e6112dbc..f8fbba08 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -215,9 +215,11 @@ public void build_PDOlist(UInt16 startcob, List slots) //Look at mappings - ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); - slot.DescriptionMap = mapping.Description; - if(mapping==null) + ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); + + if (mapping != null) { + slot.DescriptionMap = mapping.Description; + }else { Console.WriteLine(string.Format("No mapping for index 0x{0:X4} should be at 0x{1:X4}", idx, idx + 0x200)); continue; From 99619b6701309cae6c4816c48f63fd471ace9129 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 19 Feb 2024 12:22:03 +0100 Subject: [PATCH 111/226] Buxfix extensions --- EDSEditorGUI/Form1.cs | 2 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 10 +++++----- libEDSsharp/PDOHelper.cs | 8 +++++--- 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index a7804933..c54cf88f 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -1222,7 +1222,7 @@ private void ODEditor_MainForm_DragEnter(object sender, DragEventArgs e) { this.Activate(); bool unsupportedFile = false; - string[] data = (string[]) e.Data.GetData(DataFormats.FileDrop); + string[] data = e.Data.GetData(DataFormats.FileDrop) as string[]; if (data != null) { var rawFileNames = data as string[]; diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 455ffd08..a10f41e9 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -194,14 +194,14 @@ private int Prepare_var(ODentry od, string indexH, string varName, string group) string attr = Get_attributes(od, data.cTypeMultibyte, data.cTypeString); // data storage - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); ODStorage[group].Add($".x{varName} = {data.cValue}"); dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; - } - + } + // objects ODObjs_t.Add($"OD_obj_var_t o_{varName};"); ODObjs.Add($" .o_{varName} = {{"); @@ -345,12 +345,12 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) Warnings.AddWarning($"Error in 0x{indexH}: Data type in RECORD, subIndex 0 must be UNSIGNED8, not {sub.datatype}!", Warnings.warning_class.WARNING_BUILD); string subcName = Make_cname(sub.parameter_name); - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); subODStorage.Add($".{subcName} = {data.cValue}"); - dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; + dataPtr = $"&{odname}_{group}.x{varName}.{subcName}{data.cTypeArray0}"; } ODObjs.Add($" {{"); ODObjs.Add($" .dataOrig = {dataPtr},"); diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index e6112dbc..f8fbba08 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -215,9 +215,11 @@ public void build_PDOlist(UInt16 startcob, List slots) //Look at mappings - ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); - slot.DescriptionMap = mapping.Description; - if(mapping==null) + ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); + + if (mapping != null) { + slot.DescriptionMap = mapping.Description; + }else { Console.WriteLine(string.Format("No mapping for index 0x{0:X4} should be at 0x{1:X4}", idx, idx + 0x200)); continue; From 6336108d916fe2fe8167255257c71adf2cac062f Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Tue, 12 Mar 2024 19:24:43 +0100 Subject: [PATCH 112/226] Normalize all the line endings --- .gitattributes | 6 + EDSEditorGUI/DeviceInfoView.Designer.cs | 1692 ++++---- EDSEditorGUI/DeviceInfoView.cs | 132 +- EDSEditorGUI/DeviceODView.Designer.cs | 1882 ++++----- EDSEditorGUI/DeviceODView.cs | 456 +-- EDSEditorGUI/DevicePDOView2.Designer.cs | 780 ++-- EDSEditorGUI/DevicePDOView2.cs | 152 +- EDSEditorGUI/DeviceView.Designer.cs | 390 +- EDSEditorGUI/Form1.Designer.cs | 604 +-- EDSEditorGUI/Form1.cs | 142 +- EDSEditorGUI/InsertObjects.Designer.cs | 328 +- EDSEditorGUI/InsertObjects.cs | 670 ++-- EDSEditorGUI/NewIndex.Designer.cs | 4 +- EDSEditorGUI/Properties/Resources.Designer.cs | 506 +-- EDSEditorGUI/Properties/Settings.Designer.cs | 100 +- libEDSsharp/CanOpenNodeExporter.cs | 3440 ++++++++--------- libEDSsharp/CanOpenNodeExporter_V4.cs | 8 +- libEDSsharp/CanOpenXDD.cs | 24 +- libEDSsharp/CanOpenXSD_1_1.cs | 8 +- libEDSsharp/NetworkPDOreport.cs | 2 +- libEDSsharp/PDOHelper.cs | 178 +- libEDSsharp/Properties/Resources.Designer.cs | 126 +- libEDSsharp/eds.cs | 146 +- libEDSsharp/extensions.cs | 28 +- 24 files changed, 5905 insertions(+), 5899 deletions(-) create mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..0d03288a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,6 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto + +# Explicitly declare text files you want to always be normalized and converted +# to native line endings on checkout. +*.cs text \ No newline at end of file diff --git a/EDSEditorGUI/DeviceInfoView.Designer.cs b/EDSEditorGUI/DeviceInfoView.Designer.cs index e88a0725..ce68a85c 100644 --- a/EDSEditorGUI/DeviceInfoView.Designer.cs +++ b/EDSEditorGUI/DeviceInfoView.Designer.cs @@ -28,847 +28,847 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.panel1 = new System.Windows.Forms.Panel(); - this.groupBox5 = new System.Windows.Forms.GroupBox(); - this.label4 = new System.Windows.Forms.Label(); - this.textBox_mdFileName = new System.Windows.Forms.TextBox(); - this.label2 = new System.Windows.Forms.Label(); - this.textBox_xddfilenameStripped = new System.Windows.Forms.TextBox(); - this.textBox_canopennodeFileVersion = new System.Windows.Forms.TextBox(); - this.textBox_projectFileVersion = new System.Windows.Forms.TextBox(); - this.textBox_devicedcfname = new System.Windows.Forms.TextBox(); - this.label14 = new System.Windows.Forms.Label(); - this.label15 = new System.Windows.Forms.Label(); - this.textBox_canopennodeFileName = new System.Windows.Forms.TextBox(); - this.label16 = new System.Windows.Forms.Label(); - this.label31 = new System.Windows.Forms.Label(); - this.textBox_projectFileName = new System.Windows.Forms.TextBox(); - this.textBox_deviceedsname = new System.Windows.Forms.TextBox(); - this.groupBox6 = new System.Windows.Forms.GroupBox(); - this.label3 = new System.Windows.Forms.Label(); - this.textBox_lssserial = new System.Windows.Forms.TextBox(); - this.label9 = new System.Windows.Forms.Label(); - this.checkBox_canopenmanager = new System.Windows.Forms.CheckBox(); - this.label8 = new System.Windows.Forms.Label(); - this.textBox_netname = new System.Windows.Forms.TextBox(); - this.label7 = new System.Windows.Forms.Label(); - this.textBox_netnum = new System.Windows.Forms.TextBox(); - this.label6 = new System.Windows.Forms.Label(); - this.textBox_baudrate = new System.Windows.Forms.TextBox(); - this.label5 = new System.Windows.Forms.Label(); - this.textBox_nodename = new System.Windows.Forms.TextBox(); - this.label32 = new System.Windows.Forms.Label(); - this.textBox_concretenodeid = new System.Windows.Forms.TextBox(); - this.groupBox4 = new System.Windows.Forms.GroupBox(); - this.textBox_productnumber = new System.Windows.Forms.TextBox(); - this.textBox_productname = new System.Windows.Forms.TextBox(); - this.textBox_vendornumber = new System.Windows.Forms.TextBox(); - this.textBox_vendorname = new System.Windows.Forms.TextBox(); - this.label29 = new System.Windows.Forms.Label(); - this.label28 = new System.Windows.Forms.Label(); - this.label27 = new System.Windows.Forms.Label(); - this.label26 = new System.Windows.Forms.Label(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.checkBox_baud_auto = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_125 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_10 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_20 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_50 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_250 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_1000 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_500 = new System.Windows.Forms.CheckBox(); - this.checkBox_baud_800 = new System.Windows.Forms.CheckBox(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.textBox_NG_NumOfNodes = new System.Windows.Forms.TextBox(); - this.label10 = new System.Windows.Forms.Label(); - this.checkBox_ngMaster = new System.Windows.Forms.CheckBox(); - this.checkBox_ngSlave = new System.Windows.Forms.CheckBox(); - this.textBox_granularity = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.textBox_txpdos = new System.Windows.Forms.TextBox(); - this.checkBox_lssMaster = new System.Windows.Forms.CheckBox(); - this.label30 = new System.Windows.Forms.Label(); - this.textBox_rxpdos = new System.Windows.Forms.TextBox(); - this.label17 = new System.Windows.Forms.Label(); - this.checkBox_lss = new System.Windows.Forms.CheckBox(); - this.groupBox3 = new System.Windows.Forms.GroupBox(); - this.textBox_modifiedby = new System.Windows.Forms.TextBox(); - this.textBox_modified_datetime = new System.Windows.Forms.TextBox(); - this.textBox_createdby = new System.Windows.Forms.TextBox(); - this.textBox_create_datetime = new System.Windows.Forms.TextBox(); - this.textBox_di_description = new System.Windows.Forms.TextBox(); - this.textBox_fileversion = new System.Windows.Forms.TextBox(); - this.label25 = new System.Windows.Forms.Label(); - this.label24 = new System.Windows.Forms.Label(); - this.label23 = new System.Windows.Forms.Label(); - this.label22 = new System.Windows.Forms.Label(); - this.label20 = new System.Windows.Forms.Label(); - this.label18 = new System.Windows.Forms.Label(); - this.panel1.SuspendLayout(); - this.groupBox5.SuspendLayout(); - this.groupBox6.SuspendLayout(); - this.groupBox4.SuspendLayout(); - this.groupBox1.SuspendLayout(); - this.groupBox2.SuspendLayout(); - this.groupBox3.SuspendLayout(); - this.SuspendLayout(); - // - // panel1 - // - this.panel1.Controls.Add(this.groupBox5); - this.panel1.Controls.Add(this.groupBox6); - this.panel1.Controls.Add(this.groupBox4); - this.panel1.Controls.Add(this.groupBox1); - this.panel1.Controls.Add(this.groupBox2); - this.panel1.Controls.Add(this.groupBox3); - this.panel1.Location = new System.Drawing.Point(0, 0); - this.panel1.Name = "panel1"; - this.panel1.Size = new System.Drawing.Size(773, 537); - this.panel1.TabIndex = 60; - // - // groupBox5 - // - this.groupBox5.Controls.Add(this.label4); - this.groupBox5.Controls.Add(this.textBox_mdFileName); - this.groupBox5.Controls.Add(this.label2); - this.groupBox5.Controls.Add(this.textBox_xddfilenameStripped); - this.groupBox5.Controls.Add(this.textBox_canopennodeFileVersion); - this.groupBox5.Controls.Add(this.textBox_projectFileVersion); - this.groupBox5.Controls.Add(this.textBox_devicedcfname); - this.groupBox5.Controls.Add(this.label14); - this.groupBox5.Controls.Add(this.label15); - this.groupBox5.Controls.Add(this.textBox_canopennodeFileName); - this.groupBox5.Controls.Add(this.label16); - this.groupBox5.Controls.Add(this.label31); - this.groupBox5.Controls.Add(this.textBox_projectFileName); - this.groupBox5.Controls.Add(this.textBox_deviceedsname); - this.groupBox5.Location = new System.Drawing.Point(12, 332); - this.groupBox5.Name = "groupBox5"; - this.groupBox5.Size = new System.Drawing.Size(377, 182); - this.groupBox5.TabIndex = 63; - this.groupBox5.TabStop = false; - this.groupBox5.Text = "Project Info"; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(10, 153); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(95, 13); - this.label4.TabIndex = 70; - this.label4.Text = "Documentation file"; - // - // textBox_mdFileName - // - this.textBox_mdFileName.Location = new System.Drawing.Point(139, 150); - this.textBox_mdFileName.Name = "textBox_mdFileName"; - this.textBox_mdFileName.ReadOnly = true; - this.textBox_mdFileName.Size = new System.Drawing.Size(226, 20); - this.textBox_mdFileName.TabIndex = 69; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(10, 49); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(116, 13); - this.label2.TabIndex = 68; - this.label2.Text = "XDD v1.1 file - stripped"; - // - // textBox_xddfilenameStripped - // - this.textBox_xddfilenameStripped.Location = new System.Drawing.Point(139, 46); - this.textBox_xddfilenameStripped.Name = "textBox_xddfilenameStripped"; - this.textBox_xddfilenameStripped.ReadOnly = true; - this.textBox_xddfilenameStripped.Size = new System.Drawing.Size(226, 20); - this.textBox_xddfilenameStripped.TabIndex = 67; - // - // textBox_canopennodeFileVersion - // - this.textBox_canopennodeFileVersion.Location = new System.Drawing.Point(330, 124); - this.textBox_canopennodeFileVersion.Name = "textBox_canopennodeFileVersion"; - this.textBox_canopennodeFileVersion.ReadOnly = true; - this.textBox_canopennodeFileVersion.Size = new System.Drawing.Size(35, 20); - this.textBox_canopennodeFileVersion.TabIndex = 66; - // - // textBox_projectFileVersion - // - this.textBox_projectFileVersion.Location = new System.Drawing.Point(330, 20); - this.textBox_projectFileVersion.Name = "textBox_projectFileVersion"; - this.textBox_projectFileVersion.ReadOnly = true; - this.textBox_projectFileVersion.Size = new System.Drawing.Size(35, 20); - this.textBox_projectFileVersion.TabIndex = 65; - // - // textBox_devicedcfname - // - this.textBox_devicedcfname.Location = new System.Drawing.Point(139, 98); - this.textBox_devicedcfname.Name = "textBox_devicedcfname"; - this.textBox_devicedcfname.ReadOnly = true; - this.textBox_devicedcfname.Size = new System.Drawing.Size(226, 20); - this.textBox_devicedcfname.TabIndex = 8; - // - // label14 - // - this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(10, 127); - this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(119, 13); - this.label14.TabIndex = 21; - this.label14.Text = "CANopenNode file (ver)"; - // - // label15 - // - this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(10, 101); - this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(44, 13); - this.label15.TabIndex = 20; - this.label15.Text = "DCF file"; - // - // textBox_canopennodeFileName - // - this.textBox_canopennodeFileName.Location = new System.Drawing.Point(139, 124); - this.textBox_canopennodeFileName.Name = "textBox_canopennodeFileName"; - this.textBox_canopennodeFileName.ReadOnly = true; - this.textBox_canopennodeFileName.Size = new System.Drawing.Size(185, 20); - this.textBox_canopennodeFileName.TabIndex = 9; - // - // label16 - // - this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(10, 75); - this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(45, 13); - this.label16.TabIndex = 19; - this.label16.Text = "EDS file"; - // - // label31 - // - this.label31.AutoSize = true; - this.label31.Location = new System.Drawing.Point(10, 23); - this.label31.Name = "label31"; - this.label31.Size = new System.Drawing.Size(99, 13); - this.label31.TabIndex = 18; - this.label31.Text = "Project file (version)"; - // - // textBox_projectFileName - // - this.textBox_projectFileName.Location = new System.Drawing.Point(139, 20); - this.textBox_projectFileName.Name = "textBox_projectFileName"; - this.textBox_projectFileName.ReadOnly = true; - this.textBox_projectFileName.Size = new System.Drawing.Size(185, 20); - this.textBox_projectFileName.TabIndex = 6; - // - // textBox_deviceedsname - // - this.textBox_deviceedsname.Location = new System.Drawing.Point(139, 72); - this.textBox_deviceedsname.Name = "textBox_deviceedsname"; - this.textBox_deviceedsname.ReadOnly = true; - this.textBox_deviceedsname.Size = new System.Drawing.Size(226, 20); - this.textBox_deviceedsname.TabIndex = 7; - // - // groupBox6 - // - this.groupBox6.Controls.Add(this.label3); - this.groupBox6.Controls.Add(this.textBox_lssserial); - this.groupBox6.Controls.Add(this.label9); - this.groupBox6.Controls.Add(this.checkBox_canopenmanager); - this.groupBox6.Controls.Add(this.label8); - this.groupBox6.Controls.Add(this.textBox_netname); - this.groupBox6.Controls.Add(this.label7); - this.groupBox6.Controls.Add(this.textBox_netnum); - this.groupBox6.Controls.Add(this.label6); - this.groupBox6.Controls.Add(this.textBox_baudrate); - this.groupBox6.Controls.Add(this.label5); - this.groupBox6.Controls.Add(this.textBox_nodename); - this.groupBox6.Controls.Add(this.label32); - this.groupBox6.Controls.Add(this.textBox_concretenodeid); - this.groupBox6.Location = new System.Drawing.Point(395, 313); - this.groupBox6.Name = "groupBox6"; - this.groupBox6.Size = new System.Drawing.Size(339, 202); - this.groupBox6.TabIndex = 5; - this.groupBox6.TabStop = false; - this.groupBox6.Text = "Device commissioning"; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(7, 149); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(98, 13); - this.label3.TabIndex = 63; - this.label3.Text = "CANopen Manager"; - // - // textBox_lssserial - // - this.textBox_lssserial.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_lssserial.Location = new System.Drawing.Point(111, 171); - this.textBox_lssserial.Name = "textBox_lssserial"; - this.textBox_lssserial.Size = new System.Drawing.Size(218, 20); - this.textBox_lssserial.TabIndex = 7; - // - // label9 - // - this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(7, 174); - this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(71, 13); - this.label9.TabIndex = 6; - this.label9.Text = "LSS Serial no"; - // - // checkBox_canopenmanager - // - this.checkBox_canopenmanager.AutoSize = true; - this.checkBox_canopenmanager.BackColor = System.Drawing.Color.PeachPuff; - this.checkBox_canopenmanager.Location = new System.Drawing.Point(111, 148); - this.checkBox_canopenmanager.Name = "checkBox_canopenmanager"; - this.checkBox_canopenmanager.Padding = new System.Windows.Forms.Padding(0, 0, 202, 0); - this.checkBox_canopenmanager.Size = new System.Drawing.Size(217, 14); - this.checkBox_canopenmanager.TabIndex = 5; - this.checkBox_canopenmanager.UseVisualStyleBackColor = false; - // - // label8 - // - this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(7, 125); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(53, 13); - this.label8.TabIndex = 62; - this.label8.Text = "Net name"; - // - // textBox_netname - // - this.textBox_netname.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_netname.Location = new System.Drawing.Point(111, 122); - this.textBox_netname.Name = "textBox_netname"; - this.textBox_netname.Size = new System.Drawing.Size(218, 20); - this.textBox_netname.TabIndex = 4; - // - // label7 - // - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(7, 99); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(62, 13); - this.label7.TabIndex = 60; - this.label7.Text = "Net number"; - // - // textBox_netnum - // - this.textBox_netnum.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_netnum.Location = new System.Drawing.Point(111, 96); - this.textBox_netnum.Name = "textBox_netnum"; - this.textBox_netnum.Size = new System.Drawing.Size(218, 20); - this.textBox_netnum.TabIndex = 3; - // - // label6 - // - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(7, 74); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(50, 13); - this.label6.TabIndex = 58; - this.label6.Text = "Baudrate"; - // - // textBox_baudrate - // - this.textBox_baudrate.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_baudrate.Location = new System.Drawing.Point(111, 71); - this.textBox_baudrate.Name = "textBox_baudrate"; - this.textBox_baudrate.Size = new System.Drawing.Size(218, 20); - this.textBox_baudrate.TabIndex = 2; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(7, 48); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(62, 13); - this.label5.TabIndex = 56; - this.label5.Text = "Node name"; - // - // textBox_nodename - // - this.textBox_nodename.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_nodename.Location = new System.Drawing.Point(111, 45); - this.textBox_nodename.Name = "textBox_nodename"; - this.textBox_nodename.Size = new System.Drawing.Size(218, 20); - this.textBox_nodename.TabIndex = 1; - // - // label32 - // - this.label32.AutoSize = true; - this.label32.Location = new System.Drawing.Point(7, 22); - this.label32.Name = "label32"; - this.label32.Size = new System.Drawing.Size(91, 13); - this.label32.TabIndex = 53; - this.label32.Text = "Concrete node ID"; - // - // textBox_concretenodeid - // - this.textBox_concretenodeid.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_concretenodeid.Location = new System.Drawing.Point(111, 19); - this.textBox_concretenodeid.Name = "textBox_concretenodeid"; - this.textBox_concretenodeid.Size = new System.Drawing.Size(218, 20); - this.textBox_concretenodeid.TabIndex = 0; - // - // groupBox4 - // - this.groupBox4.Controls.Add(this.textBox_productnumber); - this.groupBox4.Controls.Add(this.textBox_productname); - this.groupBox4.Controls.Add(this.textBox_vendornumber); - this.groupBox4.Controls.Add(this.textBox_vendorname); - this.groupBox4.Controls.Add(this.label29); - this.groupBox4.Controls.Add(this.label28); - this.groupBox4.Controls.Add(this.label27); - this.groupBox4.Controls.Add(this.label26); - this.groupBox4.Location = new System.Drawing.Point(12, 14); - this.groupBox4.Name = "groupBox4"; - this.groupBox4.Size = new System.Drawing.Size(377, 126); - this.groupBox4.TabIndex = 0; - this.groupBox4.TabStop = false; - this.groupBox4.Text = "Device Info"; - // - // textBox_productnumber - // - this.textBox_productnumber.Location = new System.Drawing.Point(139, 46); - this.textBox_productnumber.Name = "textBox_productnumber"; - this.textBox_productnumber.Size = new System.Drawing.Size(226, 20); - this.textBox_productnumber.TabIndex = 1; - // - // textBox_productname - // - this.textBox_productname.Location = new System.Drawing.Point(139, 20); - this.textBox_productname.Name = "textBox_productname"; - this.textBox_productname.Size = new System.Drawing.Size(226, 20); - this.textBox_productname.TabIndex = 0; - // - // textBox_vendornumber - // - this.textBox_vendornumber.Location = new System.Drawing.Point(139, 98); - this.textBox_vendornumber.Name = "textBox_vendornumber"; - this.textBox_vendornumber.Size = new System.Drawing.Size(226, 20); - this.textBox_vendornumber.TabIndex = 3; - // - // textBox_vendorname - // - this.textBox_vendorname.Location = new System.Drawing.Point(139, 72); - this.textBox_vendorname.Name = "textBox_vendorname"; - this.textBox_vendorname.Size = new System.Drawing.Size(226, 20); - this.textBox_vendorname.TabIndex = 2; - // - // label29 - // - this.label29.AutoSize = true; - this.label29.Location = new System.Drawing.Point(10, 49); - this.label29.Name = "label29"; - this.label29.Size = new System.Drawing.Size(58, 13); - this.label29.TabIndex = 37; - this.label29.Text = "Product ID"; - // - // label28 - // - this.label28.AutoSize = true; - this.label28.Location = new System.Drawing.Point(10, 23); - this.label28.Name = "label28"; - this.label28.Size = new System.Drawing.Size(73, 13); - this.label28.TabIndex = 36; - this.label28.Text = "Product name"; - // - // label27 - // - this.label27.AutoSize = true; - this.label27.Location = new System.Drawing.Point(10, 101); - this.label27.Name = "label27"; - this.label27.Size = new System.Drawing.Size(55, 13); - this.label27.TabIndex = 35; - this.label27.Text = "Vendor ID"; - // - // label26 - // - this.label26.AutoSize = true; - this.label26.Location = new System.Drawing.Point(10, 75); - this.label26.Name = "label26"; - this.label26.Size = new System.Drawing.Size(70, 13); - this.label26.TabIndex = 34; - this.label26.Text = "Vendor name"; - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.checkBox_baud_auto); - this.groupBox1.Controls.Add(this.checkBox_baud_125); - this.groupBox1.Controls.Add(this.checkBox_baud_10); - this.groupBox1.Controls.Add(this.checkBox_baud_20); - this.groupBox1.Controls.Add(this.checkBox_baud_50); - this.groupBox1.Controls.Add(this.checkBox_baud_250); - this.groupBox1.Controls.Add(this.checkBox_baud_1000); - this.groupBox1.Controls.Add(this.checkBox_baud_500); - this.groupBox1.Controls.Add(this.checkBox_baud_800); - this.groupBox1.Location = new System.Drawing.Point(395, 14); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(120, 220); - this.groupBox1.TabIndex = 3; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Baudrates"; - // - // checkBox_baud_auto - // - this.checkBox_baud_auto.AutoSize = true; - this.checkBox_baud_auto.Location = new System.Drawing.Point(10, 163); - this.checkBox_baud_auto.Name = "checkBox_baud_auto"; - this.checkBox_baud_auto.Size = new System.Drawing.Size(47, 17); - this.checkBox_baud_auto.TabIndex = 8; - this.checkBox_baud_auto.Text = "auto"; - this.checkBox_baud_auto.UseVisualStyleBackColor = true; - // - // checkBox_baud_125 - // - this.checkBox_baud_125.AutoSize = true; - this.checkBox_baud_125.Location = new System.Drawing.Point(10, 72); - this.checkBox_baud_125.Name = "checkBox_baud_125"; - this.checkBox_baud_125.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_125.TabIndex = 3; - this.checkBox_baud_125.Text = "125 kbps"; - this.checkBox_baud_125.UseVisualStyleBackColor = true; - // - // checkBox_baud_10 - // - this.checkBox_baud_10.AutoSize = true; - this.checkBox_baud_10.Location = new System.Drawing.Point(10, 20); - this.checkBox_baud_10.Name = "checkBox_baud_10"; - this.checkBox_baud_10.Size = new System.Drawing.Size(64, 17); - this.checkBox_baud_10.TabIndex = 0; - this.checkBox_baud_10.Text = "10 kbps"; - this.checkBox_baud_10.UseVisualStyleBackColor = true; - // - // checkBox_baud_20 - // - this.checkBox_baud_20.AutoSize = true; - this.checkBox_baud_20.Location = new System.Drawing.Point(10, 37); - this.checkBox_baud_20.Name = "checkBox_baud_20"; - this.checkBox_baud_20.Size = new System.Drawing.Size(64, 17); - this.checkBox_baud_20.TabIndex = 1; - this.checkBox_baud_20.Text = "20 kbps"; - this.checkBox_baud_20.UseVisualStyleBackColor = true; - // - // checkBox_baud_50 - // - this.checkBox_baud_50.AutoSize = true; - this.checkBox_baud_50.Location = new System.Drawing.Point(10, 54); - this.checkBox_baud_50.Name = "checkBox_baud_50"; - this.checkBox_baud_50.Size = new System.Drawing.Size(64, 17); - this.checkBox_baud_50.TabIndex = 2; - this.checkBox_baud_50.Text = "50 kbps"; - this.checkBox_baud_50.UseVisualStyleBackColor = true; - // - // checkBox_baud_250 - // - this.checkBox_baud_250.AutoSize = true; - this.checkBox_baud_250.Location = new System.Drawing.Point(10, 90); - this.checkBox_baud_250.Name = "checkBox_baud_250"; - this.checkBox_baud_250.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_250.TabIndex = 4; - this.checkBox_baud_250.Text = "250 kbps"; - this.checkBox_baud_250.UseVisualStyleBackColor = true; - // - // checkBox_baud_1000 - // - this.checkBox_baud_1000.AutoSize = true; - this.checkBox_baud_1000.Location = new System.Drawing.Point(10, 145); - this.checkBox_baud_1000.Name = "checkBox_baud_1000"; - this.checkBox_baud_1000.Size = new System.Drawing.Size(76, 17); - this.checkBox_baud_1000.TabIndex = 7; - this.checkBox_baud_1000.Text = "1000 kbps"; - this.checkBox_baud_1000.UseVisualStyleBackColor = true; - // - // checkBox_baud_500 - // - this.checkBox_baud_500.AutoSize = true; - this.checkBox_baud_500.Location = new System.Drawing.Point(10, 109); - this.checkBox_baud_500.Name = "checkBox_baud_500"; - this.checkBox_baud_500.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_500.TabIndex = 5; - this.checkBox_baud_500.Text = "500 kbps"; - this.checkBox_baud_500.UseVisualStyleBackColor = true; - // - // checkBox_baud_800 - // - this.checkBox_baud_800.AutoSize = true; - this.checkBox_baud_800.Location = new System.Drawing.Point(10, 127); - this.checkBox_baud_800.Name = "checkBox_baud_800"; - this.checkBox_baud_800.Size = new System.Drawing.Size(70, 17); - this.checkBox_baud_800.TabIndex = 6; - this.checkBox_baud_800.Text = "800 kbps"; - this.checkBox_baud_800.UseVisualStyleBackColor = true; - // - // groupBox2 - // - this.groupBox2.Controls.Add(this.textBox_NG_NumOfNodes); - this.groupBox2.Controls.Add(this.label10); - this.groupBox2.Controls.Add(this.checkBox_ngMaster); - this.groupBox2.Controls.Add(this.checkBox_ngSlave); - this.groupBox2.Controls.Add(this.textBox_granularity); - this.groupBox2.Controls.Add(this.label1); - this.groupBox2.Controls.Add(this.textBox_txpdos); - this.groupBox2.Controls.Add(this.checkBox_lssMaster); - this.groupBox2.Controls.Add(this.label30); - this.groupBox2.Controls.Add(this.textBox_rxpdos); - this.groupBox2.Controls.Add(this.label17); - this.groupBox2.Controls.Add(this.checkBox_lss); - this.groupBox2.Location = new System.Drawing.Point(521, 14); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(213, 220); - this.groupBox2.TabIndex = 4; - this.groupBox2.TabStop = false; - this.groupBox2.Text = "General and Master Features"; - // - // textBox_NG_NumOfNodes - // - this.textBox_NG_NumOfNodes.BackColor = System.Drawing.SystemColors.Window; - this.textBox_NG_NumOfNodes.Location = new System.Drawing.Point(124, 193); - this.textBox_NG_NumOfNodes.Name = "textBox_NG_NumOfNodes"; - this.textBox_NG_NumOfNodes.Size = new System.Drawing.Size(80, 20); - this.textBox_NG_NumOfNodes.TabIndex = 44; - // - // label10 - // - this.label10.AutoSize = true; - this.label10.Location = new System.Drawing.Point(10, 196); - this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(114, 13); - this.label10.TabIndex = 45; - this.label10.Text = "No of monitored nodes"; - // - // checkBox_ngMaster - // - this.checkBox_ngMaster.AutoSize = true; - this.checkBox_ngMaster.Location = new System.Drawing.Point(10, 176); - this.checkBox_ngMaster.Name = "checkBox_ngMaster"; - this.checkBox_ngMaster.Size = new System.Drawing.Size(131, 17); - this.checkBox_ngMaster.TabIndex = 43; - this.checkBox_ngMaster.Text = "Node guarding Master"; - this.checkBox_ngMaster.UseVisualStyleBackColor = true; - // - // checkBox_ngSlave - // - this.checkBox_ngSlave.AutoSize = true; - this.checkBox_ngSlave.Location = new System.Drawing.Point(10, 158); - this.checkBox_ngSlave.Name = "checkBox_ngSlave"; - this.checkBox_ngSlave.Size = new System.Drawing.Size(126, 17); - this.checkBox_ngSlave.TabIndex = 42; - this.checkBox_ngSlave.Text = "Node guarding Slave"; - this.checkBox_ngSlave.UseVisualStyleBackColor = true; - // - // textBox_granularity - // - this.textBox_granularity.Location = new System.Drawing.Point(102, 20); - this.textBox_granularity.Name = "textBox_granularity"; - this.textBox_granularity.Size = new System.Drawing.Size(101, 20); - this.textBox_granularity.TabIndex = 41; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(10, 23); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(57, 13); - this.label1.TabIndex = 40; - this.label1.Text = "Granularity"; - // - // textBox_txpdos - // - this.textBox_txpdos.Location = new System.Drawing.Point(102, 72); - this.textBox_txpdos.Name = "textBox_txpdos"; - this.textBox_txpdos.ReadOnly = true; - this.textBox_txpdos.Size = new System.Drawing.Size(101, 20); - this.textBox_txpdos.TabIndex = 1; - // - // checkBox_lssMaster - // - this.checkBox_lssMaster.AutoSize = true; - this.checkBox_lssMaster.Location = new System.Drawing.Point(10, 128); - this.checkBox_lssMaster.Name = "checkBox_lssMaster"; - this.checkBox_lssMaster.Size = new System.Drawing.Size(81, 17); - this.checkBox_lssMaster.TabIndex = 10; - this.checkBox_lssMaster.Text = "LSS Master"; - this.checkBox_lssMaster.UseVisualStyleBackColor = true; - // - // label30 - // - this.label30.AutoSize = true; - this.label30.Location = new System.Drawing.Point(10, 75); - this.label30.Name = "label30"; - this.label30.Size = new System.Drawing.Size(67, 13); - this.label30.TabIndex = 39; - this.label30.Text = "TPDO count"; - // - // textBox_rxpdos - // - this.textBox_rxpdos.Location = new System.Drawing.Point(102, 46); - this.textBox_rxpdos.Name = "textBox_rxpdos"; - this.textBox_rxpdos.ReadOnly = true; - this.textBox_rxpdos.Size = new System.Drawing.Size(101, 20); - this.textBox_rxpdos.TabIndex = 0; - // - // label17 - // - this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(10, 49); - this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(68, 13); - this.label17.TabIndex = 38; - this.label17.Text = "RPDO count"; - // - // checkBox_lss - // - this.checkBox_lss.AutoSize = true; - this.checkBox_lss.Location = new System.Drawing.Point(10, 110); - this.checkBox_lss.Name = "checkBox_lss"; - this.checkBox_lss.Size = new System.Drawing.Size(76, 17); - this.checkBox_lss.TabIndex = 6; - this.checkBox_lss.Text = "LSS Slave"; - this.checkBox_lss.UseVisualStyleBackColor = true; - // - // groupBox3 - // - this.groupBox3.Controls.Add(this.textBox_modifiedby); - this.groupBox3.Controls.Add(this.textBox_modified_datetime); - this.groupBox3.Controls.Add(this.textBox_createdby); - this.groupBox3.Controls.Add(this.textBox_create_datetime); - this.groupBox3.Controls.Add(this.textBox_di_description); - this.groupBox3.Controls.Add(this.textBox_fileversion); - this.groupBox3.Controls.Add(this.label25); - this.groupBox3.Controls.Add(this.label24); - this.groupBox3.Controls.Add(this.label23); - this.groupBox3.Controls.Add(this.label22); - this.groupBox3.Controls.Add(this.label20); - this.groupBox3.Controls.Add(this.label18); - this.groupBox3.Location = new System.Drawing.Point(12, 146); - this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(377, 180); - this.groupBox3.TabIndex = 1; - this.groupBox3.TabStop = false; - this.groupBox3.Text = "File Info"; - // - // textBox_modifiedby - // - this.textBox_modifiedby.Location = new System.Drawing.Point(139, 150); - this.textBox_modifiedby.Name = "textBox_modifiedby"; - this.textBox_modifiedby.Size = new System.Drawing.Size(226, 20); - this.textBox_modifiedby.TabIndex = 7; - // - // textBox_modified_datetime - // - this.textBox_modified_datetime.Location = new System.Drawing.Point(139, 124); - this.textBox_modified_datetime.Name = "textBox_modified_datetime"; - this.textBox_modified_datetime.ReadOnly = true; - this.textBox_modified_datetime.Size = new System.Drawing.Size(226, 20); - this.textBox_modified_datetime.TabIndex = 6; - // - // textBox_createdby - // - this.textBox_createdby.Location = new System.Drawing.Point(139, 98); - this.textBox_createdby.Name = "textBox_createdby"; - this.textBox_createdby.Size = new System.Drawing.Size(226, 20); - this.textBox_createdby.TabIndex = 5; - // - // textBox_create_datetime - // - this.textBox_create_datetime.Location = new System.Drawing.Point(139, 72); - this.textBox_create_datetime.Name = "textBox_create_datetime"; - this.textBox_create_datetime.Size = new System.Drawing.Size(226, 20); - this.textBox_create_datetime.TabIndex = 4; - // - // textBox_di_description - // - this.textBox_di_description.Location = new System.Drawing.Point(139, 46); - this.textBox_di_description.Name = "textBox_di_description"; - this.textBox_di_description.Size = new System.Drawing.Size(226, 20); - this.textBox_di_description.TabIndex = 3; - // - // textBox_fileversion - // - this.textBox_fileversion.Location = new System.Drawing.Point(139, 20); - this.textBox_fileversion.Name = "textBox_fileversion"; - this.textBox_fileversion.Size = new System.Drawing.Size(226, 20); - this.textBox_fileversion.TabIndex = 0; - // - // label25 - // - this.label25.AutoSize = true; - this.label25.Location = new System.Drawing.Point(10, 153); - this.label25.Name = "label25"; - this.label25.Size = new System.Drawing.Size(61, 13); - this.label25.TabIndex = 25; - this.label25.Text = "Modified by"; - // - // label24 - // - this.label24.AutoSize = true; - this.label24.Location = new System.Drawing.Point(10, 127); - this.label24.Name = "label24"; - this.label24.Size = new System.Drawing.Size(118, 13); - this.label24.TabIndex = 24; - this.label24.Text = "Modification Date/Time"; - // - // label23 - // - this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(10, 101); - this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(59, 13); - this.label23.TabIndex = 23; - this.label23.Text = "Created By"; - // - // label22 - // - this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(10, 75); - this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(100, 13); - this.label22.TabIndex = 22; - this.label22.Text = "Creation Date/Time"; - // - // label20 - // - this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(10, 49); - this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(60, 13); - this.label20.TabIndex = 20; - this.label20.Text = "Description"; - // - // label18 - // - this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(10, 23); - this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(60, 13); - this.label18.TabIndex = 18; - this.label18.Text = "File version"; - // - // DeviceInfoView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.panel1); - this.Name = "DeviceInfoView"; - this.Size = new System.Drawing.Size(773, 537); - this.panel1.ResumeLayout(false); - this.groupBox5.ResumeLayout(false); - this.groupBox5.PerformLayout(); - this.groupBox6.ResumeLayout(false); - this.groupBox6.PerformLayout(); - this.groupBox4.ResumeLayout(false); - this.groupBox4.PerformLayout(); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); - this.groupBox3.ResumeLayout(false); - this.groupBox3.PerformLayout(); - this.ResumeLayout(false); - + this.panel1 = new System.Windows.Forms.Panel(); + this.groupBox5 = new System.Windows.Forms.GroupBox(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox_mdFileName = new System.Windows.Forms.TextBox(); + this.label2 = new System.Windows.Forms.Label(); + this.textBox_xddfilenameStripped = new System.Windows.Forms.TextBox(); + this.textBox_canopennodeFileVersion = new System.Windows.Forms.TextBox(); + this.textBox_projectFileVersion = new System.Windows.Forms.TextBox(); + this.textBox_devicedcfname = new System.Windows.Forms.TextBox(); + this.label14 = new System.Windows.Forms.Label(); + this.label15 = new System.Windows.Forms.Label(); + this.textBox_canopennodeFileName = new System.Windows.Forms.TextBox(); + this.label16 = new System.Windows.Forms.Label(); + this.label31 = new System.Windows.Forms.Label(); + this.textBox_projectFileName = new System.Windows.Forms.TextBox(); + this.textBox_deviceedsname = new System.Windows.Forms.TextBox(); + this.groupBox6 = new System.Windows.Forms.GroupBox(); + this.label3 = new System.Windows.Forms.Label(); + this.textBox_lssserial = new System.Windows.Forms.TextBox(); + this.label9 = new System.Windows.Forms.Label(); + this.checkBox_canopenmanager = new System.Windows.Forms.CheckBox(); + this.label8 = new System.Windows.Forms.Label(); + this.textBox_netname = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.textBox_netnum = new System.Windows.Forms.TextBox(); + this.label6 = new System.Windows.Forms.Label(); + this.textBox_baudrate = new System.Windows.Forms.TextBox(); + this.label5 = new System.Windows.Forms.Label(); + this.textBox_nodename = new System.Windows.Forms.TextBox(); + this.label32 = new System.Windows.Forms.Label(); + this.textBox_concretenodeid = new System.Windows.Forms.TextBox(); + this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.textBox_productnumber = new System.Windows.Forms.TextBox(); + this.textBox_productname = new System.Windows.Forms.TextBox(); + this.textBox_vendornumber = new System.Windows.Forms.TextBox(); + this.textBox_vendorname = new System.Windows.Forms.TextBox(); + this.label29 = new System.Windows.Forms.Label(); + this.label28 = new System.Windows.Forms.Label(); + this.label27 = new System.Windows.Forms.Label(); + this.label26 = new System.Windows.Forms.Label(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.checkBox_baud_auto = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_125 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_10 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_20 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_50 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_250 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_1000 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_500 = new System.Windows.Forms.CheckBox(); + this.checkBox_baud_800 = new System.Windows.Forms.CheckBox(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.textBox_NG_NumOfNodes = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.checkBox_ngMaster = new System.Windows.Forms.CheckBox(); + this.checkBox_ngSlave = new System.Windows.Forms.CheckBox(); + this.textBox_granularity = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.textBox_txpdos = new System.Windows.Forms.TextBox(); + this.checkBox_lssMaster = new System.Windows.Forms.CheckBox(); + this.label30 = new System.Windows.Forms.Label(); + this.textBox_rxpdos = new System.Windows.Forms.TextBox(); + this.label17 = new System.Windows.Forms.Label(); + this.checkBox_lss = new System.Windows.Forms.CheckBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.textBox_modifiedby = new System.Windows.Forms.TextBox(); + this.textBox_modified_datetime = new System.Windows.Forms.TextBox(); + this.textBox_createdby = new System.Windows.Forms.TextBox(); + this.textBox_create_datetime = new System.Windows.Forms.TextBox(); + this.textBox_di_description = new System.Windows.Forms.TextBox(); + this.textBox_fileversion = new System.Windows.Forms.TextBox(); + this.label25 = new System.Windows.Forms.Label(); + this.label24 = new System.Windows.Forms.Label(); + this.label23 = new System.Windows.Forms.Label(); + this.label22 = new System.Windows.Forms.Label(); + this.label20 = new System.Windows.Forms.Label(); + this.label18 = new System.Windows.Forms.Label(); + this.panel1.SuspendLayout(); + this.groupBox5.SuspendLayout(); + this.groupBox6.SuspendLayout(); + this.groupBox4.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // panel1 + // + this.panel1.Controls.Add(this.groupBox5); + this.panel1.Controls.Add(this.groupBox6); + this.panel1.Controls.Add(this.groupBox4); + this.panel1.Controls.Add(this.groupBox1); + this.panel1.Controls.Add(this.groupBox2); + this.panel1.Controls.Add(this.groupBox3); + this.panel1.Location = new System.Drawing.Point(0, 0); + this.panel1.Name = "panel1"; + this.panel1.Size = new System.Drawing.Size(773, 537); + this.panel1.TabIndex = 60; + // + // groupBox5 + // + this.groupBox5.Controls.Add(this.label4); + this.groupBox5.Controls.Add(this.textBox_mdFileName); + this.groupBox5.Controls.Add(this.label2); + this.groupBox5.Controls.Add(this.textBox_xddfilenameStripped); + this.groupBox5.Controls.Add(this.textBox_canopennodeFileVersion); + this.groupBox5.Controls.Add(this.textBox_projectFileVersion); + this.groupBox5.Controls.Add(this.textBox_devicedcfname); + this.groupBox5.Controls.Add(this.label14); + this.groupBox5.Controls.Add(this.label15); + this.groupBox5.Controls.Add(this.textBox_canopennodeFileName); + this.groupBox5.Controls.Add(this.label16); + this.groupBox5.Controls.Add(this.label31); + this.groupBox5.Controls.Add(this.textBox_projectFileName); + this.groupBox5.Controls.Add(this.textBox_deviceedsname); + this.groupBox5.Location = new System.Drawing.Point(12, 332); + this.groupBox5.Name = "groupBox5"; + this.groupBox5.Size = new System.Drawing.Size(377, 182); + this.groupBox5.TabIndex = 63; + this.groupBox5.TabStop = false; + this.groupBox5.Text = "Project Info"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(10, 153); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(95, 13); + this.label4.TabIndex = 70; + this.label4.Text = "Documentation file"; + // + // textBox_mdFileName + // + this.textBox_mdFileName.Location = new System.Drawing.Point(139, 150); + this.textBox_mdFileName.Name = "textBox_mdFileName"; + this.textBox_mdFileName.ReadOnly = true; + this.textBox_mdFileName.Size = new System.Drawing.Size(226, 20); + this.textBox_mdFileName.TabIndex = 69; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(10, 49); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(116, 13); + this.label2.TabIndex = 68; + this.label2.Text = "XDD v1.1 file - stripped"; + // + // textBox_xddfilenameStripped + // + this.textBox_xddfilenameStripped.Location = new System.Drawing.Point(139, 46); + this.textBox_xddfilenameStripped.Name = "textBox_xddfilenameStripped"; + this.textBox_xddfilenameStripped.ReadOnly = true; + this.textBox_xddfilenameStripped.Size = new System.Drawing.Size(226, 20); + this.textBox_xddfilenameStripped.TabIndex = 67; + // + // textBox_canopennodeFileVersion + // + this.textBox_canopennodeFileVersion.Location = new System.Drawing.Point(330, 124); + this.textBox_canopennodeFileVersion.Name = "textBox_canopennodeFileVersion"; + this.textBox_canopennodeFileVersion.ReadOnly = true; + this.textBox_canopennodeFileVersion.Size = new System.Drawing.Size(35, 20); + this.textBox_canopennodeFileVersion.TabIndex = 66; + // + // textBox_projectFileVersion + // + this.textBox_projectFileVersion.Location = new System.Drawing.Point(330, 20); + this.textBox_projectFileVersion.Name = "textBox_projectFileVersion"; + this.textBox_projectFileVersion.ReadOnly = true; + this.textBox_projectFileVersion.Size = new System.Drawing.Size(35, 20); + this.textBox_projectFileVersion.TabIndex = 65; + // + // textBox_devicedcfname + // + this.textBox_devicedcfname.Location = new System.Drawing.Point(139, 98); + this.textBox_devicedcfname.Name = "textBox_devicedcfname"; + this.textBox_devicedcfname.ReadOnly = true; + this.textBox_devicedcfname.Size = new System.Drawing.Size(226, 20); + this.textBox_devicedcfname.TabIndex = 8; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(10, 127); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(119, 13); + this.label14.TabIndex = 21; + this.label14.Text = "CANopenNode file (ver)"; + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(10, 101); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(44, 13); + this.label15.TabIndex = 20; + this.label15.Text = "DCF file"; + // + // textBox_canopennodeFileName + // + this.textBox_canopennodeFileName.Location = new System.Drawing.Point(139, 124); + this.textBox_canopennodeFileName.Name = "textBox_canopennodeFileName"; + this.textBox_canopennodeFileName.ReadOnly = true; + this.textBox_canopennodeFileName.Size = new System.Drawing.Size(185, 20); + this.textBox_canopennodeFileName.TabIndex = 9; + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(10, 75); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(45, 13); + this.label16.TabIndex = 19; + this.label16.Text = "EDS file"; + // + // label31 + // + this.label31.AutoSize = true; + this.label31.Location = new System.Drawing.Point(10, 23); + this.label31.Name = "label31"; + this.label31.Size = new System.Drawing.Size(99, 13); + this.label31.TabIndex = 18; + this.label31.Text = "Project file (version)"; + // + // textBox_projectFileName + // + this.textBox_projectFileName.Location = new System.Drawing.Point(139, 20); + this.textBox_projectFileName.Name = "textBox_projectFileName"; + this.textBox_projectFileName.ReadOnly = true; + this.textBox_projectFileName.Size = new System.Drawing.Size(185, 20); + this.textBox_projectFileName.TabIndex = 6; + // + // textBox_deviceedsname + // + this.textBox_deviceedsname.Location = new System.Drawing.Point(139, 72); + this.textBox_deviceedsname.Name = "textBox_deviceedsname"; + this.textBox_deviceedsname.ReadOnly = true; + this.textBox_deviceedsname.Size = new System.Drawing.Size(226, 20); + this.textBox_deviceedsname.TabIndex = 7; + // + // groupBox6 + // + this.groupBox6.Controls.Add(this.label3); + this.groupBox6.Controls.Add(this.textBox_lssserial); + this.groupBox6.Controls.Add(this.label9); + this.groupBox6.Controls.Add(this.checkBox_canopenmanager); + this.groupBox6.Controls.Add(this.label8); + this.groupBox6.Controls.Add(this.textBox_netname); + this.groupBox6.Controls.Add(this.label7); + this.groupBox6.Controls.Add(this.textBox_netnum); + this.groupBox6.Controls.Add(this.label6); + this.groupBox6.Controls.Add(this.textBox_baudrate); + this.groupBox6.Controls.Add(this.label5); + this.groupBox6.Controls.Add(this.textBox_nodename); + this.groupBox6.Controls.Add(this.label32); + this.groupBox6.Controls.Add(this.textBox_concretenodeid); + this.groupBox6.Location = new System.Drawing.Point(395, 313); + this.groupBox6.Name = "groupBox6"; + this.groupBox6.Size = new System.Drawing.Size(339, 202); + this.groupBox6.TabIndex = 5; + this.groupBox6.TabStop = false; + this.groupBox6.Text = "Device commissioning"; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(7, 149); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(98, 13); + this.label3.TabIndex = 63; + this.label3.Text = "CANopen Manager"; + // + // textBox_lssserial + // + this.textBox_lssserial.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_lssserial.Location = new System.Drawing.Point(111, 171); + this.textBox_lssserial.Name = "textBox_lssserial"; + this.textBox_lssserial.Size = new System.Drawing.Size(218, 20); + this.textBox_lssserial.TabIndex = 7; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(7, 174); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(71, 13); + this.label9.TabIndex = 6; + this.label9.Text = "LSS Serial no"; + // + // checkBox_canopenmanager + // + this.checkBox_canopenmanager.AutoSize = true; + this.checkBox_canopenmanager.BackColor = System.Drawing.Color.PeachPuff; + this.checkBox_canopenmanager.Location = new System.Drawing.Point(111, 148); + this.checkBox_canopenmanager.Name = "checkBox_canopenmanager"; + this.checkBox_canopenmanager.Padding = new System.Windows.Forms.Padding(0, 0, 202, 0); + this.checkBox_canopenmanager.Size = new System.Drawing.Size(217, 14); + this.checkBox_canopenmanager.TabIndex = 5; + this.checkBox_canopenmanager.UseVisualStyleBackColor = false; + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(7, 125); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(53, 13); + this.label8.TabIndex = 62; + this.label8.Text = "Net name"; + // + // textBox_netname + // + this.textBox_netname.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_netname.Location = new System.Drawing.Point(111, 122); + this.textBox_netname.Name = "textBox_netname"; + this.textBox_netname.Size = new System.Drawing.Size(218, 20); + this.textBox_netname.TabIndex = 4; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(7, 99); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(62, 13); + this.label7.TabIndex = 60; + this.label7.Text = "Net number"; + // + // textBox_netnum + // + this.textBox_netnum.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_netnum.Location = new System.Drawing.Point(111, 96); + this.textBox_netnum.Name = "textBox_netnum"; + this.textBox_netnum.Size = new System.Drawing.Size(218, 20); + this.textBox_netnum.TabIndex = 3; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(7, 74); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(50, 13); + this.label6.TabIndex = 58; + this.label6.Text = "Baudrate"; + // + // textBox_baudrate + // + this.textBox_baudrate.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_baudrate.Location = new System.Drawing.Point(111, 71); + this.textBox_baudrate.Name = "textBox_baudrate"; + this.textBox_baudrate.Size = new System.Drawing.Size(218, 20); + this.textBox_baudrate.TabIndex = 2; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(7, 48); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(62, 13); + this.label5.TabIndex = 56; + this.label5.Text = "Node name"; + // + // textBox_nodename + // + this.textBox_nodename.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_nodename.Location = new System.Drawing.Point(111, 45); + this.textBox_nodename.Name = "textBox_nodename"; + this.textBox_nodename.Size = new System.Drawing.Size(218, 20); + this.textBox_nodename.TabIndex = 1; + // + // label32 + // + this.label32.AutoSize = true; + this.label32.Location = new System.Drawing.Point(7, 22); + this.label32.Name = "label32"; + this.label32.Size = new System.Drawing.Size(91, 13); + this.label32.TabIndex = 53; + this.label32.Text = "Concrete node ID"; + // + // textBox_concretenodeid + // + this.textBox_concretenodeid.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_concretenodeid.Location = new System.Drawing.Point(111, 19); + this.textBox_concretenodeid.Name = "textBox_concretenodeid"; + this.textBox_concretenodeid.Size = new System.Drawing.Size(218, 20); + this.textBox_concretenodeid.TabIndex = 0; + // + // groupBox4 + // + this.groupBox4.Controls.Add(this.textBox_productnumber); + this.groupBox4.Controls.Add(this.textBox_productname); + this.groupBox4.Controls.Add(this.textBox_vendornumber); + this.groupBox4.Controls.Add(this.textBox_vendorname); + this.groupBox4.Controls.Add(this.label29); + this.groupBox4.Controls.Add(this.label28); + this.groupBox4.Controls.Add(this.label27); + this.groupBox4.Controls.Add(this.label26); + this.groupBox4.Location = new System.Drawing.Point(12, 14); + this.groupBox4.Name = "groupBox4"; + this.groupBox4.Size = new System.Drawing.Size(377, 126); + this.groupBox4.TabIndex = 0; + this.groupBox4.TabStop = false; + this.groupBox4.Text = "Device Info"; + // + // textBox_productnumber + // + this.textBox_productnumber.Location = new System.Drawing.Point(139, 46); + this.textBox_productnumber.Name = "textBox_productnumber"; + this.textBox_productnumber.Size = new System.Drawing.Size(226, 20); + this.textBox_productnumber.TabIndex = 1; + // + // textBox_productname + // + this.textBox_productname.Location = new System.Drawing.Point(139, 20); + this.textBox_productname.Name = "textBox_productname"; + this.textBox_productname.Size = new System.Drawing.Size(226, 20); + this.textBox_productname.TabIndex = 0; + // + // textBox_vendornumber + // + this.textBox_vendornumber.Location = new System.Drawing.Point(139, 98); + this.textBox_vendornumber.Name = "textBox_vendornumber"; + this.textBox_vendornumber.Size = new System.Drawing.Size(226, 20); + this.textBox_vendornumber.TabIndex = 3; + // + // textBox_vendorname + // + this.textBox_vendorname.Location = new System.Drawing.Point(139, 72); + this.textBox_vendorname.Name = "textBox_vendorname"; + this.textBox_vendorname.Size = new System.Drawing.Size(226, 20); + this.textBox_vendorname.TabIndex = 2; + // + // label29 + // + this.label29.AutoSize = true; + this.label29.Location = new System.Drawing.Point(10, 49); + this.label29.Name = "label29"; + this.label29.Size = new System.Drawing.Size(58, 13); + this.label29.TabIndex = 37; + this.label29.Text = "Product ID"; + // + // label28 + // + this.label28.AutoSize = true; + this.label28.Location = new System.Drawing.Point(10, 23); + this.label28.Name = "label28"; + this.label28.Size = new System.Drawing.Size(73, 13); + this.label28.TabIndex = 36; + this.label28.Text = "Product name"; + // + // label27 + // + this.label27.AutoSize = true; + this.label27.Location = new System.Drawing.Point(10, 101); + this.label27.Name = "label27"; + this.label27.Size = new System.Drawing.Size(55, 13); + this.label27.TabIndex = 35; + this.label27.Text = "Vendor ID"; + // + // label26 + // + this.label26.AutoSize = true; + this.label26.Location = new System.Drawing.Point(10, 75); + this.label26.Name = "label26"; + this.label26.Size = new System.Drawing.Size(70, 13); + this.label26.TabIndex = 34; + this.label26.Text = "Vendor name"; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.checkBox_baud_auto); + this.groupBox1.Controls.Add(this.checkBox_baud_125); + this.groupBox1.Controls.Add(this.checkBox_baud_10); + this.groupBox1.Controls.Add(this.checkBox_baud_20); + this.groupBox1.Controls.Add(this.checkBox_baud_50); + this.groupBox1.Controls.Add(this.checkBox_baud_250); + this.groupBox1.Controls.Add(this.checkBox_baud_1000); + this.groupBox1.Controls.Add(this.checkBox_baud_500); + this.groupBox1.Controls.Add(this.checkBox_baud_800); + this.groupBox1.Location = new System.Drawing.Point(395, 14); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(120, 220); + this.groupBox1.TabIndex = 3; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Baudrates"; + // + // checkBox_baud_auto + // + this.checkBox_baud_auto.AutoSize = true; + this.checkBox_baud_auto.Location = new System.Drawing.Point(10, 163); + this.checkBox_baud_auto.Name = "checkBox_baud_auto"; + this.checkBox_baud_auto.Size = new System.Drawing.Size(47, 17); + this.checkBox_baud_auto.TabIndex = 8; + this.checkBox_baud_auto.Text = "auto"; + this.checkBox_baud_auto.UseVisualStyleBackColor = true; + // + // checkBox_baud_125 + // + this.checkBox_baud_125.AutoSize = true; + this.checkBox_baud_125.Location = new System.Drawing.Point(10, 72); + this.checkBox_baud_125.Name = "checkBox_baud_125"; + this.checkBox_baud_125.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_125.TabIndex = 3; + this.checkBox_baud_125.Text = "125 kbps"; + this.checkBox_baud_125.UseVisualStyleBackColor = true; + // + // checkBox_baud_10 + // + this.checkBox_baud_10.AutoSize = true; + this.checkBox_baud_10.Location = new System.Drawing.Point(10, 20); + this.checkBox_baud_10.Name = "checkBox_baud_10"; + this.checkBox_baud_10.Size = new System.Drawing.Size(64, 17); + this.checkBox_baud_10.TabIndex = 0; + this.checkBox_baud_10.Text = "10 kbps"; + this.checkBox_baud_10.UseVisualStyleBackColor = true; + // + // checkBox_baud_20 + // + this.checkBox_baud_20.AutoSize = true; + this.checkBox_baud_20.Location = new System.Drawing.Point(10, 37); + this.checkBox_baud_20.Name = "checkBox_baud_20"; + this.checkBox_baud_20.Size = new System.Drawing.Size(64, 17); + this.checkBox_baud_20.TabIndex = 1; + this.checkBox_baud_20.Text = "20 kbps"; + this.checkBox_baud_20.UseVisualStyleBackColor = true; + // + // checkBox_baud_50 + // + this.checkBox_baud_50.AutoSize = true; + this.checkBox_baud_50.Location = new System.Drawing.Point(10, 54); + this.checkBox_baud_50.Name = "checkBox_baud_50"; + this.checkBox_baud_50.Size = new System.Drawing.Size(64, 17); + this.checkBox_baud_50.TabIndex = 2; + this.checkBox_baud_50.Text = "50 kbps"; + this.checkBox_baud_50.UseVisualStyleBackColor = true; + // + // checkBox_baud_250 + // + this.checkBox_baud_250.AutoSize = true; + this.checkBox_baud_250.Location = new System.Drawing.Point(10, 90); + this.checkBox_baud_250.Name = "checkBox_baud_250"; + this.checkBox_baud_250.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_250.TabIndex = 4; + this.checkBox_baud_250.Text = "250 kbps"; + this.checkBox_baud_250.UseVisualStyleBackColor = true; + // + // checkBox_baud_1000 + // + this.checkBox_baud_1000.AutoSize = true; + this.checkBox_baud_1000.Location = new System.Drawing.Point(10, 145); + this.checkBox_baud_1000.Name = "checkBox_baud_1000"; + this.checkBox_baud_1000.Size = new System.Drawing.Size(76, 17); + this.checkBox_baud_1000.TabIndex = 7; + this.checkBox_baud_1000.Text = "1000 kbps"; + this.checkBox_baud_1000.UseVisualStyleBackColor = true; + // + // checkBox_baud_500 + // + this.checkBox_baud_500.AutoSize = true; + this.checkBox_baud_500.Location = new System.Drawing.Point(10, 109); + this.checkBox_baud_500.Name = "checkBox_baud_500"; + this.checkBox_baud_500.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_500.TabIndex = 5; + this.checkBox_baud_500.Text = "500 kbps"; + this.checkBox_baud_500.UseVisualStyleBackColor = true; + // + // checkBox_baud_800 + // + this.checkBox_baud_800.AutoSize = true; + this.checkBox_baud_800.Location = new System.Drawing.Point(10, 127); + this.checkBox_baud_800.Name = "checkBox_baud_800"; + this.checkBox_baud_800.Size = new System.Drawing.Size(70, 17); + this.checkBox_baud_800.TabIndex = 6; + this.checkBox_baud_800.Text = "800 kbps"; + this.checkBox_baud_800.UseVisualStyleBackColor = true; + // + // groupBox2 + // + this.groupBox2.Controls.Add(this.textBox_NG_NumOfNodes); + this.groupBox2.Controls.Add(this.label10); + this.groupBox2.Controls.Add(this.checkBox_ngMaster); + this.groupBox2.Controls.Add(this.checkBox_ngSlave); + this.groupBox2.Controls.Add(this.textBox_granularity); + this.groupBox2.Controls.Add(this.label1); + this.groupBox2.Controls.Add(this.textBox_txpdos); + this.groupBox2.Controls.Add(this.checkBox_lssMaster); + this.groupBox2.Controls.Add(this.label30); + this.groupBox2.Controls.Add(this.textBox_rxpdos); + this.groupBox2.Controls.Add(this.label17); + this.groupBox2.Controls.Add(this.checkBox_lss); + this.groupBox2.Location = new System.Drawing.Point(521, 14); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(213, 220); + this.groupBox2.TabIndex = 4; + this.groupBox2.TabStop = false; + this.groupBox2.Text = "General and Master Features"; + // + // textBox_NG_NumOfNodes + // + this.textBox_NG_NumOfNodes.BackColor = System.Drawing.SystemColors.Window; + this.textBox_NG_NumOfNodes.Location = new System.Drawing.Point(124, 193); + this.textBox_NG_NumOfNodes.Name = "textBox_NG_NumOfNodes"; + this.textBox_NG_NumOfNodes.Size = new System.Drawing.Size(80, 20); + this.textBox_NG_NumOfNodes.TabIndex = 44; + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(10, 196); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(114, 13); + this.label10.TabIndex = 45; + this.label10.Text = "No of monitored nodes"; + // + // checkBox_ngMaster + // + this.checkBox_ngMaster.AutoSize = true; + this.checkBox_ngMaster.Location = new System.Drawing.Point(10, 176); + this.checkBox_ngMaster.Name = "checkBox_ngMaster"; + this.checkBox_ngMaster.Size = new System.Drawing.Size(131, 17); + this.checkBox_ngMaster.TabIndex = 43; + this.checkBox_ngMaster.Text = "Node guarding Master"; + this.checkBox_ngMaster.UseVisualStyleBackColor = true; + // + // checkBox_ngSlave + // + this.checkBox_ngSlave.AutoSize = true; + this.checkBox_ngSlave.Location = new System.Drawing.Point(10, 158); + this.checkBox_ngSlave.Name = "checkBox_ngSlave"; + this.checkBox_ngSlave.Size = new System.Drawing.Size(126, 17); + this.checkBox_ngSlave.TabIndex = 42; + this.checkBox_ngSlave.Text = "Node guarding Slave"; + this.checkBox_ngSlave.UseVisualStyleBackColor = true; + // + // textBox_granularity + // + this.textBox_granularity.Location = new System.Drawing.Point(102, 20); + this.textBox_granularity.Name = "textBox_granularity"; + this.textBox_granularity.Size = new System.Drawing.Size(101, 20); + this.textBox_granularity.TabIndex = 41; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(10, 23); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(57, 13); + this.label1.TabIndex = 40; + this.label1.Text = "Granularity"; + // + // textBox_txpdos + // + this.textBox_txpdos.Location = new System.Drawing.Point(102, 72); + this.textBox_txpdos.Name = "textBox_txpdos"; + this.textBox_txpdos.ReadOnly = true; + this.textBox_txpdos.Size = new System.Drawing.Size(101, 20); + this.textBox_txpdos.TabIndex = 1; + // + // checkBox_lssMaster + // + this.checkBox_lssMaster.AutoSize = true; + this.checkBox_lssMaster.Location = new System.Drawing.Point(10, 128); + this.checkBox_lssMaster.Name = "checkBox_lssMaster"; + this.checkBox_lssMaster.Size = new System.Drawing.Size(81, 17); + this.checkBox_lssMaster.TabIndex = 10; + this.checkBox_lssMaster.Text = "LSS Master"; + this.checkBox_lssMaster.UseVisualStyleBackColor = true; + // + // label30 + // + this.label30.AutoSize = true; + this.label30.Location = new System.Drawing.Point(10, 75); + this.label30.Name = "label30"; + this.label30.Size = new System.Drawing.Size(67, 13); + this.label30.TabIndex = 39; + this.label30.Text = "TPDO count"; + // + // textBox_rxpdos + // + this.textBox_rxpdos.Location = new System.Drawing.Point(102, 46); + this.textBox_rxpdos.Name = "textBox_rxpdos"; + this.textBox_rxpdos.ReadOnly = true; + this.textBox_rxpdos.Size = new System.Drawing.Size(101, 20); + this.textBox_rxpdos.TabIndex = 0; + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(10, 49); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(68, 13); + this.label17.TabIndex = 38; + this.label17.Text = "RPDO count"; + // + // checkBox_lss + // + this.checkBox_lss.AutoSize = true; + this.checkBox_lss.Location = new System.Drawing.Point(10, 110); + this.checkBox_lss.Name = "checkBox_lss"; + this.checkBox_lss.Size = new System.Drawing.Size(76, 17); + this.checkBox_lss.TabIndex = 6; + this.checkBox_lss.Text = "LSS Slave"; + this.checkBox_lss.UseVisualStyleBackColor = true; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.textBox_modifiedby); + this.groupBox3.Controls.Add(this.textBox_modified_datetime); + this.groupBox3.Controls.Add(this.textBox_createdby); + this.groupBox3.Controls.Add(this.textBox_create_datetime); + this.groupBox3.Controls.Add(this.textBox_di_description); + this.groupBox3.Controls.Add(this.textBox_fileversion); + this.groupBox3.Controls.Add(this.label25); + this.groupBox3.Controls.Add(this.label24); + this.groupBox3.Controls.Add(this.label23); + this.groupBox3.Controls.Add(this.label22); + this.groupBox3.Controls.Add(this.label20); + this.groupBox3.Controls.Add(this.label18); + this.groupBox3.Location = new System.Drawing.Point(12, 146); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(377, 180); + this.groupBox3.TabIndex = 1; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "File Info"; + // + // textBox_modifiedby + // + this.textBox_modifiedby.Location = new System.Drawing.Point(139, 150); + this.textBox_modifiedby.Name = "textBox_modifiedby"; + this.textBox_modifiedby.Size = new System.Drawing.Size(226, 20); + this.textBox_modifiedby.TabIndex = 7; + // + // textBox_modified_datetime + // + this.textBox_modified_datetime.Location = new System.Drawing.Point(139, 124); + this.textBox_modified_datetime.Name = "textBox_modified_datetime"; + this.textBox_modified_datetime.ReadOnly = true; + this.textBox_modified_datetime.Size = new System.Drawing.Size(226, 20); + this.textBox_modified_datetime.TabIndex = 6; + // + // textBox_createdby + // + this.textBox_createdby.Location = new System.Drawing.Point(139, 98); + this.textBox_createdby.Name = "textBox_createdby"; + this.textBox_createdby.Size = new System.Drawing.Size(226, 20); + this.textBox_createdby.TabIndex = 5; + // + // textBox_create_datetime + // + this.textBox_create_datetime.Location = new System.Drawing.Point(139, 72); + this.textBox_create_datetime.Name = "textBox_create_datetime"; + this.textBox_create_datetime.Size = new System.Drawing.Size(226, 20); + this.textBox_create_datetime.TabIndex = 4; + // + // textBox_di_description + // + this.textBox_di_description.Location = new System.Drawing.Point(139, 46); + this.textBox_di_description.Name = "textBox_di_description"; + this.textBox_di_description.Size = new System.Drawing.Size(226, 20); + this.textBox_di_description.TabIndex = 3; + // + // textBox_fileversion + // + this.textBox_fileversion.Location = new System.Drawing.Point(139, 20); + this.textBox_fileversion.Name = "textBox_fileversion"; + this.textBox_fileversion.Size = new System.Drawing.Size(226, 20); + this.textBox_fileversion.TabIndex = 0; + // + // label25 + // + this.label25.AutoSize = true; + this.label25.Location = new System.Drawing.Point(10, 153); + this.label25.Name = "label25"; + this.label25.Size = new System.Drawing.Size(61, 13); + this.label25.TabIndex = 25; + this.label25.Text = "Modified by"; + // + // label24 + // + this.label24.AutoSize = true; + this.label24.Location = new System.Drawing.Point(10, 127); + this.label24.Name = "label24"; + this.label24.Size = new System.Drawing.Size(118, 13); + this.label24.TabIndex = 24; + this.label24.Text = "Modification Date/Time"; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(10, 101); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(59, 13); + this.label23.TabIndex = 23; + this.label23.Text = "Created By"; + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(10, 75); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(100, 13); + this.label22.TabIndex = 22; + this.label22.Text = "Creation Date/Time"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(10, 49); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(60, 13); + this.label20.TabIndex = 20; + this.label20.Text = "Description"; + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(10, 23); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(60, 13); + this.label18.TabIndex = 18; + this.label18.Text = "File version"; + // + // DeviceInfoView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.panel1); + this.Name = "DeviceInfoView"; + this.Size = new System.Drawing.Size(773, 537); + this.panel1.ResumeLayout(false); + this.groupBox5.ResumeLayout(false); + this.groupBox5.PerformLayout(); + this.groupBox6.ResumeLayout(false); + this.groupBox6.PerformLayout(); + this.groupBox4.ResumeLayout(false); + this.groupBox4.PerformLayout(); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.groupBox3.PerformLayout(); + this.ResumeLayout(false); + } #endregion @@ -944,10 +944,10 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_xddfilenameStripped; private System.Windows.Forms.Label label3; private System.Windows.Forms.Label label4; - private System.Windows.Forms.TextBox textBox_mdFileName; - private System.Windows.Forms.TextBox textBox_NG_NumOfNodes; - private System.Windows.Forms.Label label10; - private System.Windows.Forms.CheckBox checkBox_ngMaster; - private System.Windows.Forms.CheckBox checkBox_ngSlave; + private System.Windows.Forms.TextBox textBox_mdFileName; + private System.Windows.Forms.TextBox textBox_NG_NumOfNodes; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.CheckBox checkBox_ngMaster; + private System.Windows.Forms.CheckBox checkBox_ngSlave; } } diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 1f8f96de..20ef719d 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -21,9 +21,9 @@ You should have received a copy of the GNU General Public License using System.Windows.Forms; using libEDSsharp; using System.IO; -using System.Runtime.CompilerServices; -using System.Drawing; - +using System.Runtime.CompilerServices; +using System.Drawing; + namespace ODEditor { public partial class DeviceInfoView : MyTabUserControl @@ -66,19 +66,19 @@ public void populatedeviceinfo() textBox_rxpdos.Text = eds.di.NrOfRXPDO.ToString(); textBox_txpdos.Text = eds.di.NrOfTXPDO.ToString(); checkBox_lss.Checked = eds.di.LSS_Supported; - checkBox_lssMaster.Checked = eds.di.LSS_Master; - - checkBox_ngSlave.Checked = eds.di.NG_Slave; - checkBox_ngMaster.Checked = eds.di.NG_Master; - - if (textBox_NG_NumOfNodes.Enabled) + checkBox_lssMaster.Checked = eds.di.LSS_Master; + + checkBox_ngSlave.Checked = eds.di.NG_Slave; + checkBox_ngMaster.Checked = eds.di.NG_Master; + + if (textBox_NG_NumOfNodes.Enabled) textBox_NG_NumOfNodes.Text = eds.di.NrOfNG_MonitoredNodes.ToString(); - else - { - textBox_NG_NumOfNodes.Text = ""; - eds.di.NrOfNG_MonitoredNodes = 0; - } - + else + { + textBox_NG_NumOfNodes.Text = ""; + eds.di.NrOfNG_MonitoredNodes = 0; + } + textBox_projectFileName.Text = Path.GetFileName(eds.projectFilename); if (eds.xddfilename_1_1 != "") textBox_projectFileVersion.Text = "v1.1"; @@ -102,33 +102,33 @@ public void populatedeviceinfo() textBox_netnum.Text = eds.dc.NetNumber.ToString(); checkBox_canopenmanager.Checked = eds.dc.CANopenManager; textBox_lssserial.Text = eds.dc.LSS_SerialNumber.ToString(); - } - - AddOnChangeHandlerToInputControls(this.Controls); - - } - - - - void AddOnChangeHandlerToInputControls(ControlCollection ctrl) - { - foreach (Control subctrl in ctrl) - { - if (subctrl is TextBox) - ((TextBox)subctrl).TextChanged += - new EventHandler(InputControls_OnChange); - else - if (subctrl is CheckBox) - ((CheckBox)subctrl).CheckedChanged += - new EventHandler(InputControls_OnChange); - else - { - if (subctrl.Controls.Count > 0) - this.AddOnChangeHandlerToInputControls(subctrl.Controls); - } - } - } - + } + + AddOnChangeHandlerToInputControls(this.Controls); + + } + + + + void AddOnChangeHandlerToInputControls(ControlCollection ctrl) + { + foreach (Control subctrl in ctrl) + { + if (subctrl is TextBox) + ((TextBox)subctrl).TextChanged += + new EventHandler(InputControls_OnChange); + else + if (subctrl is CheckBox) + ((CheckBox)subctrl).CheckedChanged += + new EventHandler(InputControls_OnChange); + else + { + if (subctrl.Controls.Count > 0) + this.AddOnChangeHandlerToInputControls(subctrl.Controls); + } + } + } + private void update_devfile_info() { if (eds == null) @@ -159,23 +159,23 @@ private void update_devfile_info() eds.di.Granularity = Convert.ToByte(textBox_granularity.Text); eds.di.LSS_Supported = checkBox_lss.Checked; - eds.di.LSS_Master = checkBox_lssMaster.Checked; - - // ToDO: Node guarding ist confiured manually, but should reflect the OD settings - // NG_Slave active if heartbeat producer time (0x1017) == 0 and Guardtime (0x100C) != 0 - // NG_Master active (according DSP302) if consumer time (0x1016) == 0 and NodeID is in network list (0x1F81) and Guardtime (0x100C) != 0 - // NrOfNG_MonitoredNodes should be the sum of all NodeIDs that are in network list (0x1F81) if heartbeat consumer time (0x1016) == 0 and Guardtime (0x100C) != 0 - textBox_NG_NumOfNodes.Enabled = checkBox_ngMaster.Checked; - eds.di.NG_Slave = checkBox_ngSlave.Checked; - eds.di.NG_Master = checkBox_ngMaster.Checked; - System.UInt16.TryParse(textBox_NG_NumOfNodes.Text,out eds.di.NrOfNG_MonitoredNodes); - if (eds.di.NrOfNG_MonitoredNodes > 127) - { - MessageBox.Show("Number of monitored nodes must be between 0 and 127"); - } - - doUpdatePDOs(); - + eds.di.LSS_Master = checkBox_lssMaster.Checked; + + // ToDO: Node guarding ist confiured manually, but should reflect the OD settings + // NG_Slave active if heartbeat producer time (0x1017) == 0 and Guardtime (0x100C) != 0 + // NG_Master active (according DSP302) if consumer time (0x1016) == 0 and NodeID is in network list (0x1F81) and Guardtime (0x100C) != 0 + // NrOfNG_MonitoredNodes should be the sum of all NodeIDs that are in network list (0x1F81) if heartbeat consumer time (0x1016) == 0 and Guardtime (0x100C) != 0 + textBox_NG_NumOfNodes.Enabled = checkBox_ngMaster.Checked; + eds.di.NG_Slave = checkBox_ngSlave.Checked; + eds.di.NG_Master = checkBox_ngMaster.Checked; + System.UInt16.TryParse(textBox_NG_NumOfNodes.Text,out eds.di.NrOfNG_MonitoredNodes); + if (eds.di.NrOfNG_MonitoredNodes > 127) + { + MessageBox.Show("Number of monitored nodes must be between 0 and 127"); + } + + doUpdatePDOs(); + //These are read only and auto calculated //textBox_rxpdos.Text = eds.di.NrOfRXPDO.ToString(); //textBox_txpdos.Text = eds.di.NrOfTXPDO.ToString(); @@ -195,12 +195,12 @@ private void update_devfile_info() { MessageBox.Show("Update failed, reason :-\n" + ex.ToString()); } - } - - void InputControls_OnChange(object sender, EventArgs e) - { - // Changes detected: Update the device info - update_devfile_info(); - } + } + + void InputControls_OnChange(object sender, EventArgs e) + { + // Changes detected: Update the device info + update_devfile_info(); + } } } diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index 75f379cb..11eb304d 100644 --- a/EDSEditorGUI/DeviceODView.Designer.cs +++ b/EDSEditorGUI/DeviceODView.Designer.cs @@ -28,946 +28,946 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.splitContainer1 = new System.Windows.Forms.SplitContainer(); - this.splitContainer2 = new System.Windows.Forms.SplitContainer(); - this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); - this.listView_communication_objects = new System.Windows.Forms.ListView(); - this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.label1 = new System.Windows.Forms.Label(); - this.splitContainer3 = new System.Windows.Forms.SplitContainer(); - this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); - this.label2 = new System.Windows.Forms.Label(); - this.listView_manufacturer_objects = new System.Windows.Forms.ListView(); - this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); - this.label3 = new System.Windows.Forms.Label(); - this.listView_deviceProfile_objects = new System.Windows.Forms.ListView(); - this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.splitContainer4 = new System.Windows.Forms.SplitContainer(); - this.listView_subObjects = new System.Windows.Forms.ListView(); - this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader10 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader11 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader12 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader14 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.textBox_subIndex = new System.Windows.Forms.TextBox(); - this.label23 = new System.Windows.Forms.Label(); - this.textBox_index = new System.Windows.Forms.TextBox(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.checkBox_autosave = new System.Windows.Forms.CheckBox(); - this.textBox_stringLengthMin = new System.Windows.Forms.TextBox(); - this.label22 = new System.Windows.Forms.Label(); - this.label20 = new System.Windows.Forms.Label(); - this.comboBox_countLabel = new System.Windows.Forms.ComboBox(); - this.label19 = new System.Windows.Forms.Label(); - this.comboBox_accessSRDO = new System.Windows.Forms.ComboBox(); - this.textBox_actualValue = new System.Windows.Forms.TextBox(); - this.textBox_lowLimit = new System.Windows.Forms.TextBox(); - this.textBox_highLimit = new System.Windows.Forms.TextBox(); - this.label18 = new System.Windows.Forms.Label(); - this.label17 = new System.Windows.Forms.Label(); - this.label14 = new System.Windows.Forms.Label(); - this.button_saveChanges = new System.Windows.Forms.Button(); - this.label16 = new System.Windows.Forms.Label(); - this.comboBox_storageGroup = new System.Windows.Forms.ComboBox(); - this.label15 = new System.Windows.Forms.Label(); - this.checkBox_enabled = new System.Windows.Forms.CheckBox(); - this.label7 = new System.Windows.Forms.Label(); - this.comboBox_objectType = new System.Windows.Forms.ComboBox(); - this.label8 = new System.Windows.Forms.Label(); - this.comboBox_dataType = new System.Windows.Forms.ComboBox(); - this.label_pdoFlags = new System.Windows.Forms.Label(); - this.label9 = new System.Windows.Forms.Label(); - this.checkBox_pdoFlags = new System.Windows.Forms.CheckBox(); - this.comboBox_accessSDO = new System.Windows.Forms.ComboBox(); - this.textBox_defaultValue = new System.Windows.Forms.TextBox(); - this.label10 = new System.Windows.Forms.Label(); - this.label11 = new System.Windows.Forms.Label(); - this.comboBox_accessPDO = new System.Windows.Forms.ComboBox(); - this.textBox_denotation = new System.Windows.Forms.TextBox(); - this.label13 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.label5 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.textBox_name = new System.Windows.Forms.TextBox(); - this.textBox_description = new System.Windows.Forms.TextBox(); - this.contextMenu_object = new System.Windows.Forms.ContextMenuStrip(this.components); - this.contextMenu_object_addNewObjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.addToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.contextMenu_object_deleteObjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.contextMenu_object_toggleObjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.contextMenu_subObject = new System.Windows.Forms.ContextMenuStrip(this.components); - this.contextMenu_subObject_addSubItemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.contextMenu_subObject_removeSubItemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); - this.splitContainer1.Panel1.SuspendLayout(); - this.splitContainer1.Panel2.SuspendLayout(); - this.splitContainer1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); - this.splitContainer2.Panel1.SuspendLayout(); - this.splitContainer2.Panel2.SuspendLayout(); - this.splitContainer2.SuspendLayout(); - this.tableLayoutPanel1.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); - this.splitContainer3.Panel1.SuspendLayout(); - this.splitContainer3.Panel2.SuspendLayout(); - this.splitContainer3.SuspendLayout(); - this.tableLayoutPanel2.SuspendLayout(); - this.tableLayoutPanel3.SuspendLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer4)).BeginInit(); - this.splitContainer4.Panel1.SuspendLayout(); - this.splitContainer4.Panel2.SuspendLayout(); - this.splitContainer4.SuspendLayout(); - this.groupBox1.SuspendLayout(); - this.contextMenu_object.SuspendLayout(); - this.contextMenu_subObject.SuspendLayout(); - this.SuspendLayout(); - // - // splitContainer1 - // - this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer1.Location = new System.Drawing.Point(0, 0); - this.splitContainer1.Name = "splitContainer1"; - // - // splitContainer1.Panel1 - // - this.splitContainer1.Panel1.Controls.Add(this.splitContainer2); - // - // splitContainer1.Panel2 - // - this.splitContainer1.Panel2.Controls.Add(this.splitContainer4); - this.splitContainer1.Size = new System.Drawing.Size(1138, 745); - this.splitContainer1.SplitterDistance = 280; - this.splitContainer1.TabIndex = 2; - this.splitContainer1.TabStop = false; - // - // splitContainer2 - // - this.splitContainer2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer2.Location = new System.Drawing.Point(0, 0); - this.splitContainer2.Name = "splitContainer2"; - this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer2.Panel1 - // - this.splitContainer2.Panel1.Controls.Add(this.tableLayoutPanel1); - // - // splitContainer2.Panel2 - // - this.splitContainer2.Panel2.Controls.Add(this.splitContainer3); - this.splitContainer2.Size = new System.Drawing.Size(280, 745); - this.splitContainer2.SplitterDistance = 245; - this.splitContainer2.TabIndex = 0; - this.splitContainer2.TabStop = false; - // - // tableLayoutPanel1 - // - this.tableLayoutPanel1.ColumnCount = 1; - this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Controls.Add(this.listView_communication_objects, 0, 1); - this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); - this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel1.Name = "tableLayoutPanel1"; - this.tableLayoutPanel1.RowCount = 2; - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel1.Size = new System.Drawing.Size(278, 243); - this.tableLayoutPanel1.TabIndex = 6; - // - // listView_communication_objects - // - this.listView_communication_objects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader1, - this.columnHeader2}); - this.listView_communication_objects.Dock = System.Windows.Forms.DockStyle.Fill; - this.listView_communication_objects.FullRowSelect = true; - this.listView_communication_objects.HideSelection = false; - this.listView_communication_objects.Location = new System.Drawing.Point(3, 23); - this.listView_communication_objects.Name = "listView_communication_objects"; - this.listView_communication_objects.Size = new System.Drawing.Size(272, 217); - this.listView_communication_objects.TabIndex = 0; - this.listView_communication_objects.UseCompatibleStateImageBehavior = false; - this.listView_communication_objects.View = System.Windows.Forms.View.Details; - this.listView_communication_objects.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.ListView_objects_ColumnClick); - this.listView_communication_objects.SelectedIndexChanged += new System.EventHandler(this.ListView_objects_SelectedIndexChanged); - this.listView_communication_objects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_objects_MouseClick); - // - // columnHeader1 - // - this.columnHeader1.Text = "Index"; - // - // columnHeader2 - // - this.columnHeader2.Text = "Name"; - this.columnHeader2.Width = 185; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(3, 0); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(176, 13); - this.label1.TabIndex = 3; - this.label1.Text = "Communication Specific Parameters"; - // - // splitContainer3 - // - this.splitContainer3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; - this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer3.Location = new System.Drawing.Point(0, 0); - this.splitContainer3.Name = "splitContainer3"; - this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer3.Panel1 - // - this.splitContainer3.Panel1.Controls.Add(this.tableLayoutPanel2); - // - // splitContainer3.Panel2 - // - this.splitContainer3.Panel2.Controls.Add(this.tableLayoutPanel3); - this.splitContainer3.Size = new System.Drawing.Size(280, 496); - this.splitContainer3.SplitterDistance = 244; - this.splitContainer3.TabIndex = 0; - this.splitContainer3.TabStop = false; - // - // tableLayoutPanel2 - // - this.tableLayoutPanel2.ColumnCount = 1; - this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Controls.Add(this.label2, 0, 0); - this.tableLayoutPanel2.Controls.Add(this.listView_manufacturer_objects, 0, 1); - this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel2.Name = "tableLayoutPanel2"; - this.tableLayoutPanel2.RowCount = 2; - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel2.Size = new System.Drawing.Size(278, 242); - this.tableLayoutPanel2.TabIndex = 7; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(3, 0); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(167, 13); - this.label2.TabIndex = 4; - this.label2.Text = "Manufacturer Specific Parameters"; - // - // listView_manufacturer_objects - // - this.listView_manufacturer_objects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader3, - this.columnHeader4}); - this.listView_manufacturer_objects.Dock = System.Windows.Forms.DockStyle.Fill; - this.listView_manufacturer_objects.FullRowSelect = true; - this.listView_manufacturer_objects.HideSelection = false; - this.listView_manufacturer_objects.Location = new System.Drawing.Point(3, 23); - this.listView_manufacturer_objects.Name = "listView_manufacturer_objects"; - this.listView_manufacturer_objects.Size = new System.Drawing.Size(272, 216); - this.listView_manufacturer_objects.TabIndex = 0; - this.listView_manufacturer_objects.UseCompatibleStateImageBehavior = false; - this.listView_manufacturer_objects.View = System.Windows.Forms.View.Details; - this.listView_manufacturer_objects.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.ListView_objects_ColumnClick); - this.listView_manufacturer_objects.SelectedIndexChanged += new System.EventHandler(this.ListView_objects_SelectedIndexChanged); - this.listView_manufacturer_objects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_objects_MouseClick); - // - // columnHeader3 - // - this.columnHeader3.Text = "Index"; - // - // columnHeader4 - // - this.columnHeader4.Text = "Name"; - this.columnHeader4.Width = 200; - // - // tableLayoutPanel3 - // - this.tableLayoutPanel3.ColumnCount = 1; - this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Controls.Add(this.label3, 0, 0); - this.tableLayoutPanel3.Controls.Add(this.listView_deviceProfile_objects, 0, 1); - this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; - this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); - this.tableLayoutPanel3.Name = "tableLayoutPanel3"; - this.tableLayoutPanel3.RowCount = 2; - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); - this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); - this.tableLayoutPanel3.Size = new System.Drawing.Size(278, 246); - this.tableLayoutPanel3.TabIndex = 8; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(3, 0); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(170, 13); - this.label3.TabIndex = 5; - this.label3.Text = "Device Profile Specific Parameters"; - // - // listView_deviceProfile_objects - // - this.listView_deviceProfile_objects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader5, - this.columnHeader6}); - this.listView_deviceProfile_objects.Dock = System.Windows.Forms.DockStyle.Fill; - this.listView_deviceProfile_objects.FullRowSelect = true; - this.listView_deviceProfile_objects.HideSelection = false; - this.listView_deviceProfile_objects.Location = new System.Drawing.Point(3, 23); - this.listView_deviceProfile_objects.Name = "listView_deviceProfile_objects"; - this.listView_deviceProfile_objects.Size = new System.Drawing.Size(272, 220); - this.listView_deviceProfile_objects.TabIndex = 0; - this.listView_deviceProfile_objects.UseCompatibleStateImageBehavior = false; - this.listView_deviceProfile_objects.View = System.Windows.Forms.View.Details; - this.listView_deviceProfile_objects.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.ListView_objects_ColumnClick); - this.listView_deviceProfile_objects.SelectedIndexChanged += new System.EventHandler(this.ListView_objects_SelectedIndexChanged); - this.listView_deviceProfile_objects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_objects_MouseClick); - // - // columnHeader5 - // - this.columnHeader5.Text = "Index"; - // - // columnHeader6 - // - this.columnHeader6.Text = "Name"; - this.columnHeader6.Width = 200; - // - // splitContainer4 - // - this.splitContainer4.Dock = System.Windows.Forms.DockStyle.Fill; - this.splitContainer4.Location = new System.Drawing.Point(0, 0); - this.splitContainer4.Name = "splitContainer4"; - this.splitContainer4.Orientation = System.Windows.Forms.Orientation.Horizontal; - // - // splitContainer4.Panel1 - // - this.splitContainer4.Panel1.Controls.Add(this.listView_subObjects); - // - // splitContainer4.Panel2 - // - this.splitContainer4.Panel2.Controls.Add(this.textBox_subIndex); - this.splitContainer4.Panel2.Controls.Add(this.label23); - this.splitContainer4.Panel2.Controls.Add(this.textBox_index); - this.splitContainer4.Panel2.Controls.Add(this.groupBox1); - this.splitContainer4.Panel2.Controls.Add(this.textBox_denotation); - this.splitContainer4.Panel2.Controls.Add(this.label13); - this.splitContainer4.Panel2.Controls.Add(this.label4); - this.splitContainer4.Panel2.Controls.Add(this.label5); - this.splitContainer4.Panel2.Controls.Add(this.label6); - this.splitContainer4.Panel2.Controls.Add(this.textBox_name); - this.splitContainer4.Panel2.Controls.Add(this.textBox_description); - this.splitContainer4.Size = new System.Drawing.Size(854, 745); - this.splitContainer4.SplitterDistance = 224; - this.splitContainer4.TabIndex = 28; - this.splitContainer4.TabStop = false; - // - // listView_subObjects - // - this.listView_subObjects.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.listView_subObjects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader7, - this.columnHeader8, - this.columnHeader9, - this.columnHeader10, - this.columnHeader11, - this.columnHeader12, - this.columnHeader13, - this.columnHeader14}); - this.listView_subObjects.FullRowSelect = true; - this.listView_subObjects.HideSelection = false; - this.listView_subObjects.Location = new System.Drawing.Point(0, 0); - this.listView_subObjects.Name = "listView_subObjects"; - this.listView_subObjects.Size = new System.Drawing.Size(851, 223); - this.listView_subObjects.TabIndex = 0; - this.listView_subObjects.UseCompatibleStateImageBehavior = false; - this.listView_subObjects.View = System.Windows.Forms.View.Details; - this.listView_subObjects.SelectedIndexChanged += new System.EventHandler(this.ListView_subObjects_SelectedIndexChanged); - this.listView_subObjects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_subObjects_MouseClick); - // - // columnHeader7 - // - this.columnHeader7.Text = "Sub"; - this.columnHeader7.Width = 40; - // - // columnHeader8 - // - this.columnHeader8.Text = "Name"; - this.columnHeader8.Width = 200; - // - // columnHeader9 - // - this.columnHeader9.Text = "Obj Type"; - this.columnHeader9.Width = 65; - // - // columnHeader10 - // - this.columnHeader10.Text = "Data Type"; - this.columnHeader10.Width = 120; - // - // columnHeader11 - // - this.columnHeader11.Text = "SDO"; - this.columnHeader11.Width = 50; - // - // columnHeader12 - // - this.columnHeader12.Text = "PDO"; - this.columnHeader12.Width = 50; - // - // columnHeader13 - // - this.columnHeader13.Text = "SRDO"; - this.columnHeader13.Width = 50; - // - // columnHeader14 - // - this.columnHeader14.Text = "Default Value"; - this.columnHeader14.Width = 190; - // - // textBox_subIndex - // - this.textBox_subIndex.Location = new System.Drawing.Point(260, 8); - this.textBox_subIndex.Name = "textBox_subIndex"; - this.textBox_subIndex.ReadOnly = true; - this.textBox_subIndex.Size = new System.Drawing.Size(100, 20); - this.textBox_subIndex.TabIndex = 0; - this.textBox_subIndex.TabStop = false; - // - // label23 - // - this.label23.AutoSize = true; - this.label23.Location = new System.Drawing.Point(199, 11); - this.label23.Name = "label23"; - this.label23.Size = new System.Drawing.Size(55, 13); - this.label23.TabIndex = 34; - this.label23.Text = "Sub Index"; - // - // textBox_index - // - this.textBox_index.Location = new System.Drawing.Point(90, 8); - this.textBox_index.Name = "textBox_index"; - this.textBox_index.ReadOnly = true; - this.textBox_index.Size = new System.Drawing.Size(100, 20); - this.textBox_index.TabIndex = 0; - this.textBox_index.TabStop = false; - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.checkBox_autosave); - this.groupBox1.Controls.Add(this.textBox_stringLengthMin); - this.groupBox1.Controls.Add(this.label22); - this.groupBox1.Controls.Add(this.label20); - this.groupBox1.Controls.Add(this.comboBox_countLabel); - this.groupBox1.Controls.Add(this.label19); - this.groupBox1.Controls.Add(this.comboBox_accessSRDO); - this.groupBox1.Controls.Add(this.textBox_actualValue); - this.groupBox1.Controls.Add(this.textBox_lowLimit); - this.groupBox1.Controls.Add(this.textBox_highLimit); - this.groupBox1.Controls.Add(this.label18); - this.groupBox1.Controls.Add(this.label17); - this.groupBox1.Controls.Add(this.label14); - this.groupBox1.Controls.Add(this.button_saveChanges); - this.groupBox1.Controls.Add(this.label16); - this.groupBox1.Controls.Add(this.comboBox_storageGroup); - this.groupBox1.Controls.Add(this.label15); - this.groupBox1.Controls.Add(this.checkBox_enabled); - this.groupBox1.Controls.Add(this.label7); - this.groupBox1.Controls.Add(this.comboBox_objectType); - this.groupBox1.Controls.Add(this.label8); - this.groupBox1.Controls.Add(this.comboBox_dataType); - this.groupBox1.Controls.Add(this.label_pdoFlags); - this.groupBox1.Controls.Add(this.label9); - this.groupBox1.Controls.Add(this.checkBox_pdoFlags); - this.groupBox1.Controls.Add(this.comboBox_accessSDO); - this.groupBox1.Controls.Add(this.textBox_defaultValue); - this.groupBox1.Controls.Add(this.label10); - this.groupBox1.Controls.Add(this.label11); - this.groupBox1.Controls.Add(this.comboBox_accessPDO); - this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; - this.groupBox1.Location = new System.Drawing.Point(0, 329); - this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); - this.groupBox1.Size = new System.Drawing.Size(854, 188); - this.groupBox1.TabIndex = 33; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Object settings"; - // - // checkBox_autosave - // - this.checkBox_autosave.Location = new System.Drawing.Point(634, 146); - this.checkBox_autosave.Name = "checkBox_autosave"; - this.checkBox_autosave.Size = new System.Drawing.Size(116, 21); - this.checkBox_autosave.TabIndex = 35; - this.checkBox_autosave.Text = "Autosave changes"; - this.checkBox_autosave.UseVisualStyleBackColor = true; - // - // textBox_stringLengthMin - // - this.textBox_stringLengthMin.Location = new System.Drawing.Point(340, 99); - this.textBox_stringLengthMin.Name = "textBox_stringLengthMin"; - this.textBox_stringLengthMin.Size = new System.Drawing.Size(122, 20); - this.textBox_stringLengthMin.TabIndex = 24; - this.textBox_stringLengthMin.TextChanged += new System.EventHandler(this.DataDirty); - // - // label22 - // - this.label22.AutoSize = true; - this.label22.Location = new System.Drawing.Point(248, 102); - this.label22.Name = "label22"; - this.label22.Size = new System.Drawing.Size(75, 13); - this.label22.TabIndex = 39; - this.label22.Text = "String Len Min"; - // - // label20 - // - this.label20.AutoSize = true; - this.label20.Location = new System.Drawing.Point(482, 21); - this.label20.Name = "label20"; - this.label20.Size = new System.Drawing.Size(64, 13); - this.label20.TabIndex = 36; - this.label20.Text = "Count Label"; - // - // comboBox_countLabel - // - this.comboBox_countLabel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboBox_countLabel.FormattingEnabled = true; - this.comboBox_countLabel.Location = new System.Drawing.Point(574, 18); - this.comboBox_countLabel.Name = "comboBox_countLabel"; - this.comboBox_countLabel.Size = new System.Drawing.Size(122, 21); - this.comboBox_countLabel.TabIndex = 30; - this.comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.DataDirty); - // - // label19 - // - this.label19.AutoSize = true; - this.label19.Location = new System.Drawing.Point(13, 129); - this.label19.Name = "label19"; - this.label19.Size = new System.Drawing.Size(76, 13); - this.label19.TabIndex = 34; - this.label19.Text = "Access SRDO"; - // - // comboBox_accessSRDO - // - this.comboBox_accessSRDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboBox_accessSRDO.FormattingEnabled = true; - this.comboBox_accessSRDO.Location = new System.Drawing.Point(108, 126); - this.comboBox_accessSRDO.Name = "comboBox_accessSRDO"; - this.comboBox_accessSRDO.Size = new System.Drawing.Size(122, 21); - this.comboBox_accessSRDO.TabIndex = 14; - this.comboBox_accessSRDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); - // - // textBox_actualValue - // - this.textBox_actualValue.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_actualValue.Location = new System.Drawing.Point(340, 72); - this.textBox_actualValue.Name = "textBox_actualValue"; - this.textBox_actualValue.Size = new System.Drawing.Size(122, 20); - this.textBox_actualValue.TabIndex = 23; - this.textBox_actualValue.TextChanged += new System.EventHandler(this.DataDirty); - // - // textBox_lowLimit - // - this.textBox_lowLimit.Location = new System.Drawing.Point(340, 45); - this.textBox_lowLimit.Name = "textBox_lowLimit"; - this.textBox_lowLimit.Size = new System.Drawing.Size(122, 20); - this.textBox_lowLimit.TabIndex = 22; - this.textBox_lowLimit.TextChanged += new System.EventHandler(this.DataDirty); - // - // textBox_highLimit - // - this.textBox_highLimit.Location = new System.Drawing.Point(340, 18); - this.textBox_highLimit.Name = "textBox_highLimit"; - this.textBox_highLimit.Size = new System.Drawing.Size(122, 20); - this.textBox_highLimit.TabIndex = 21; - this.textBox_highLimit.TextChanged += new System.EventHandler(this.DataDirty); - // - // label18 - // - this.label18.AutoSize = true; - this.label18.Location = new System.Drawing.Point(248, 75); - this.label18.Name = "label18"; - this.label18.Size = new System.Drawing.Size(67, 13); - this.label18.TabIndex = 32; - this.label18.Text = "Actual Value"; - // - // label17 - // - this.label17.AutoSize = true; - this.label17.Location = new System.Drawing.Point(248, 48); - this.label17.Name = "label17"; - this.label17.Size = new System.Drawing.Size(48, 13); - this.label17.TabIndex = 31; - this.label17.Text = "LowLimit"; - // - // label14 - // - this.label14.AutoSize = true; - this.label14.Location = new System.Drawing.Point(248, 21); - this.label14.Name = "label14"; - this.label14.Size = new System.Drawing.Size(50, 13); - this.label14.TabIndex = 30; - this.label14.Text = "HighLimit"; - // - // button_saveChanges - // - this.button_saveChanges.Image = global::ODEditor.Properties.Resources.Save_6530; - this.button_saveChanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_saveChanges.Location = new System.Drawing.Point(485, 138); - this.button_saveChanges.Name = "button_saveChanges"; - this.button_saveChanges.Size = new System.Drawing.Size(143, 35); - this.button_saveChanges.TabIndex = 50; - this.button_saveChanges.Text = "Save Changes"; - this.button_saveChanges.UseVisualStyleBackColor = true; - this.button_saveChanges.Click += new System.EventHandler(this.Button_saveChanges_Click); - // - // label16 - // - this.label16.AutoSize = true; - this.label16.Location = new System.Drawing.Point(482, 48); - this.label16.Name = "label16"; - this.label16.Size = new System.Drawing.Size(76, 13); - this.label16.TabIndex = 26; - this.label16.Text = "Storage Group"; - // - // comboBox_storageGroup - // - this.comboBox_storageGroup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboBox_storageGroup.FormattingEnabled = true; - this.comboBox_storageGroup.Location = new System.Drawing.Point(574, 45); - this.comboBox_storageGroup.Name = "comboBox_storageGroup"; - this.comboBox_storageGroup.Size = new System.Drawing.Size(122, 21); - this.comboBox_storageGroup.TabIndex = 31; - this.comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.DataDirty); - // - // label15 - // - this.label15.AutoSize = true; - this.label15.Location = new System.Drawing.Point(482, 72); - this.label15.Name = "label15"; - this.label15.Size = new System.Drawing.Size(46, 13); - this.label15.TabIndex = 24; - this.label15.Text = "Enabled"; - // - // checkBox_enabled - // - this.checkBox_enabled.AutoSize = true; - this.checkBox_enabled.Location = new System.Drawing.Point(574, 72); - this.checkBox_enabled.Name = "checkBox_enabled"; - this.checkBox_enabled.Size = new System.Drawing.Size(15, 14); - this.checkBox_enabled.TabIndex = 32; - this.checkBox_enabled.UseVisualStyleBackColor = true; - this.checkBox_enabled.CheckedChanged += new System.EventHandler(this.DataDirty); - // - // label7 - // - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(13, 21); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(65, 13); - this.label7.TabIndex = 7; - this.label7.Text = "Object Type"; - // - // comboBox_objectType - // - this.comboBox_objectType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboBox_objectType.Enabled = false; - this.comboBox_objectType.FormattingEnabled = true; - this.comboBox_objectType.Location = new System.Drawing.Point(108, 18); - this.comboBox_objectType.Name = "comboBox_objectType"; - this.comboBox_objectType.Size = new System.Drawing.Size(122, 21); - this.comboBox_objectType.TabIndex = 10; - this.comboBox_objectType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); - // - // label8 - // - this.label8.AutoSize = true; - this.label8.Location = new System.Drawing.Point(13, 48); - this.label8.Name = "label8"; - this.label8.Size = new System.Drawing.Size(57, 13); - this.label8.TabIndex = 9; - this.label8.Text = "Data Type"; - // - // comboBox_dataType - // - this.comboBox_dataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboBox_dataType.FormattingEnabled = true; - this.comboBox_dataType.Location = new System.Drawing.Point(108, 45); - this.comboBox_dataType.Name = "comboBox_dataType"; - this.comboBox_dataType.Size = new System.Drawing.Size(122, 21); - this.comboBox_dataType.TabIndex = 11; - this.comboBox_dataType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); - // - // label_pdoFlags - // - this.label_pdoFlags.AutoSize = true; - this.label_pdoFlags.Location = new System.Drawing.Point(482, 92); - this.label_pdoFlags.Name = "label_pdoFlags"; - this.label_pdoFlags.Size = new System.Drawing.Size(62, 13); - this.label_pdoFlags.TabIndex = 18; - this.label_pdoFlags.Text = "TPDO COS"; - // - // label9 - // - this.label9.AutoSize = true; - this.label9.Location = new System.Drawing.Point(13, 75); - this.label9.Name = "label9"; - this.label9.Size = new System.Drawing.Size(68, 13); - this.label9.TabIndex = 11; - this.label9.Text = "Access SDO"; - // - // checkBox_pdoFlags - // - this.checkBox_pdoFlags.AutoSize = true; - this.checkBox_pdoFlags.Location = new System.Drawing.Point(574, 92); - this.checkBox_pdoFlags.Name = "checkBox_pdoFlags"; - this.checkBox_pdoFlags.Size = new System.Drawing.Size(15, 14); - this.checkBox_pdoFlags.TabIndex = 34; - this.checkBox_pdoFlags.UseVisualStyleBackColor = true; - this.checkBox_pdoFlags.CheckedChanged += new System.EventHandler(this.DataDirty); - // - // comboBox_accessSDO - // - this.comboBox_accessSDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboBox_accessSDO.FormattingEnabled = true; - this.comboBox_accessSDO.Location = new System.Drawing.Point(108, 72); - this.comboBox_accessSDO.Name = "comboBox_accessSDO"; - this.comboBox_accessSDO.Size = new System.Drawing.Size(122, 21); - this.comboBox_accessSDO.TabIndex = 12; - this.comboBox_accessSDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); - // - // textBox_defaultValue - // - this.textBox_defaultValue.Location = new System.Drawing.Point(108, 153); - this.textBox_defaultValue.Name = "textBox_defaultValue"; - this.textBox_defaultValue.Size = new System.Drawing.Size(354, 20); - this.textBox_defaultValue.TabIndex = 20; - this.textBox_defaultValue.TextChanged += new System.EventHandler(this.DataDirty); - // - // label10 - // - this.label10.AutoSize = true; - this.label10.Location = new System.Drawing.Point(13, 102); - this.label10.Name = "label10"; - this.label10.Size = new System.Drawing.Size(68, 13); - this.label10.TabIndex = 13; - this.label10.Text = "Access PDO"; - // - // label11 - // - this.label11.AutoSize = true; - this.label11.Location = new System.Drawing.Point(13, 156); - this.label11.Name = "label11"; - this.label11.Size = new System.Drawing.Size(70, 13); - this.label11.TabIndex = 15; - this.label11.Text = "Default value"; - // - // comboBox_accessPDO - // - this.comboBox_accessPDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.comboBox_accessPDO.FormattingEnabled = true; - this.comboBox_accessPDO.Location = new System.Drawing.Point(108, 99); - this.comboBox_accessPDO.Name = "comboBox_accessPDO"; - this.comboBox_accessPDO.Size = new System.Drawing.Size(122, 21); - this.comboBox_accessPDO.TabIndex = 13; - this.comboBox_accessPDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); - // - // textBox_denotation - // - this.textBox_denotation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_denotation.BackColor = System.Drawing.Color.PeachPuff; - this.textBox_denotation.Location = new System.Drawing.Point(90, 60); - this.textBox_denotation.Name = "textBox_denotation"; - this.textBox_denotation.Size = new System.Drawing.Size(761, 20); - this.textBox_denotation.TabIndex = 3; - this.textBox_denotation.TextChanged += new System.EventHandler(this.DataDirty); - // - // label13 - // - this.label13.AutoSize = true; - this.label13.Location = new System.Drawing.Point(13, 63); - this.label13.Name = "label13"; - this.label13.Size = new System.Drawing.Size(59, 13); - this.label13.TabIndex = 28; - this.label13.Text = "Denotation"; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(13, 11); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(33, 13); - this.label4.TabIndex = 1; - this.label4.Text = "Index"; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(13, 37); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(35, 13); - this.label5.TabIndex = 2; - this.label5.Text = "Name"; - // - // label6 - // - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(13, 89); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(60, 13); - this.label6.TabIndex = 3; - this.label6.Text = "Description"; - // - // textBox_name - // - this.textBox_name.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_name.Location = new System.Drawing.Point(90, 34); - this.textBox_name.Name = "textBox_name"; - this.textBox_name.Size = new System.Drawing.Size(761, 20); - this.textBox_name.TabIndex = 2; - this.textBox_name.TextChanged += new System.EventHandler(this.DataDirty); - // - // textBox_description - // - this.textBox_description.AcceptsReturn = true; - this.textBox_description.AcceptsTab = true; - this.textBox_description.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_description.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); - this.textBox_description.Location = new System.Drawing.Point(90, 86); - this.textBox_description.Multiline = true; - this.textBox_description.Name = "textBox_description"; - this.textBox_description.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; - this.textBox_description.Size = new System.Drawing.Size(761, 227); - this.textBox_description.TabIndex = 4; - this.textBox_description.TextChanged += new System.EventHandler(this.DataDirty); - // - // contextMenu_object - // - this.contextMenu_object.ImageScalingSize = new System.Drawing.Size(20, 20); - this.contextMenu_object.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.contextMenu_object_addNewObjectToolStripMenuItem, - this.addToolStripMenuItem, - this.contextMenu_object_deleteObjectToolStripMenuItem, - this.contextMenu_object_toggleObjectToolStripMenuItem}); - this.contextMenu_object.Name = "contextMenuStrip1"; - this.contextMenu_object.Size = new System.Drawing.Size(121, 108); - // - // contextMenu_object_addNewObjectToolStripMenuItem - // - this.contextMenu_object_addNewObjectToolStripMenuItem.Name = "contextMenu_object_addNewObjectToolStripMenuItem"; - this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); - this.contextMenu_object_addNewObjectToolStripMenuItem.Text = "&Clone..."; - this.contextMenu_object_addNewObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_clone_ToolStripMenuItem_Click); - // - // addToolStripMenuItem - // - this.addToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; - this.addToolStripMenuItem.Name = "addToolStripMenuItem"; - this.addToolStripMenuItem.Size = new System.Drawing.Size(120, 26); - this.addToolStripMenuItem.Text = "Add..."; - this.addToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_add_ToolStripMenuItem_Click); - // - // contextMenu_object_deleteObjectToolStripMenuItem - // - this.contextMenu_object_deleteObjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; - this.contextMenu_object_deleteObjectToolStripMenuItem.Name = "contextMenu_object_deleteObjectToolStripMenuItem"; - this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); - this.contextMenu_object_deleteObjectToolStripMenuItem.Text = "&Delete..."; - this.contextMenu_object_deleteObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_delete_ToolStripMenuItem_Click); - // - // contextMenu_object_toggleObjectToolStripMenuItem - // - this.contextMenu_object_toggleObjectToolStripMenuItem.Name = "contextMenu_object_toggleObjectToolStripMenuItem"; - this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); - this.contextMenu_object_toggleObjectToolStripMenuItem.Text = "&Toggle"; - this.contextMenu_object_toggleObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_toggle_ToolStripMenuItem_Click); - // - // contextMenu_subObject - // - this.contextMenu_subObject.ImageScalingSize = new System.Drawing.Size(20, 20); - this.contextMenu_subObject.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.contextMenu_subObject_addSubItemToolStripMenuItem, - this.contextMenu_subObject_removeSubItemToolStripMenuItem, - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem}); - this.contextMenu_subObject.Name = "contextMenu_array"; - this.contextMenu_subObject.Size = new System.Drawing.Size(183, 82); - // - // contextMenu_subObject_addSubItemToolStripMenuItem - // - this.contextMenu_subObject_addSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; - this.contextMenu_subObject_addSubItemToolStripMenuItem.Name = "contextMenu_subObject_addSubItemToolStripMenuItem"; - this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); - this.contextMenu_subObject_addSubItemToolStripMenuItem.Text = "Add"; - this.contextMenu_subObject_addSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_add_ToolStripMenuItem_Click); - // - // contextMenu_subObject_removeSubItemToolStripMenuItem - // - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Text = "Remove (shift up)"; - this.contextMenu_subObject_removeSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); - // - // contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem - // - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem"; - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(182, 26); - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Text = "Remove (leave gap)"; - this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); - // - // DeviceODView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.splitContainer1); - this.Name = "DeviceODView"; - this.Size = new System.Drawing.Size(1138, 745); - this.splitContainer1.Panel1.ResumeLayout(false); - this.splitContainer1.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); - this.splitContainer1.ResumeLayout(false); - this.splitContainer2.Panel1.ResumeLayout(false); - this.splitContainer2.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); - this.splitContainer2.ResumeLayout(false); - this.tableLayoutPanel1.ResumeLayout(false); - this.tableLayoutPanel1.PerformLayout(); - this.splitContainer3.Panel1.ResumeLayout(false); - this.splitContainer3.Panel2.ResumeLayout(false); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); - this.splitContainer3.ResumeLayout(false); - this.tableLayoutPanel2.ResumeLayout(false); - this.tableLayoutPanel2.PerformLayout(); - this.tableLayoutPanel3.ResumeLayout(false); - this.tableLayoutPanel3.PerformLayout(); - this.splitContainer4.Panel1.ResumeLayout(false); - this.splitContainer4.Panel2.ResumeLayout(false); - this.splitContainer4.Panel2.PerformLayout(); - ((System.ComponentModel.ISupportInitialize)(this.splitContainer4)).EndInit(); - this.splitContainer4.ResumeLayout(false); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.contextMenu_object.ResumeLayout(false); - this.contextMenu_subObject.ResumeLayout(false); - this.ResumeLayout(false); - + this.components = new System.ComponentModel.Container(); + this.splitContainer1 = new System.Windows.Forms.SplitContainer(); + this.splitContainer2 = new System.Windows.Forms.SplitContainer(); + this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.listView_communication_objects = new System.Windows.Forms.ListView(); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader2 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.label1 = new System.Windows.Forms.Label(); + this.splitContainer3 = new System.Windows.Forms.SplitContainer(); + this.tableLayoutPanel2 = new System.Windows.Forms.TableLayoutPanel(); + this.label2 = new System.Windows.Forms.Label(); + this.listView_manufacturer_objects = new System.Windows.Forms.ListView(); + this.columnHeader3 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader4 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.tableLayoutPanel3 = new System.Windows.Forms.TableLayoutPanel(); + this.label3 = new System.Windows.Forms.Label(); + this.listView_deviceProfile_objects = new System.Windows.Forms.ListView(); + this.columnHeader5 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader6 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.splitContainer4 = new System.Windows.Forms.SplitContainer(); + this.listView_subObjects = new System.Windows.Forms.ListView(); + this.columnHeader7 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader8 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader9 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader10 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader11 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader12 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader14 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.textBox_subIndex = new System.Windows.Forms.TextBox(); + this.label23 = new System.Windows.Forms.Label(); + this.textBox_index = new System.Windows.Forms.TextBox(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.checkBox_autosave = new System.Windows.Forms.CheckBox(); + this.textBox_stringLengthMin = new System.Windows.Forms.TextBox(); + this.label22 = new System.Windows.Forms.Label(); + this.label20 = new System.Windows.Forms.Label(); + this.comboBox_countLabel = new System.Windows.Forms.ComboBox(); + this.label19 = new System.Windows.Forms.Label(); + this.comboBox_accessSRDO = new System.Windows.Forms.ComboBox(); + this.textBox_actualValue = new System.Windows.Forms.TextBox(); + this.textBox_lowLimit = new System.Windows.Forms.TextBox(); + this.textBox_highLimit = new System.Windows.Forms.TextBox(); + this.label18 = new System.Windows.Forms.Label(); + this.label17 = new System.Windows.Forms.Label(); + this.label14 = new System.Windows.Forms.Label(); + this.button_saveChanges = new System.Windows.Forms.Button(); + this.label16 = new System.Windows.Forms.Label(); + this.comboBox_storageGroup = new System.Windows.Forms.ComboBox(); + this.label15 = new System.Windows.Forms.Label(); + this.checkBox_enabled = new System.Windows.Forms.CheckBox(); + this.label7 = new System.Windows.Forms.Label(); + this.comboBox_objectType = new System.Windows.Forms.ComboBox(); + this.label8 = new System.Windows.Forms.Label(); + this.comboBox_dataType = new System.Windows.Forms.ComboBox(); + this.label_pdoFlags = new System.Windows.Forms.Label(); + this.label9 = new System.Windows.Forms.Label(); + this.checkBox_pdoFlags = new System.Windows.Forms.CheckBox(); + this.comboBox_accessSDO = new System.Windows.Forms.ComboBox(); + this.textBox_defaultValue = new System.Windows.Forms.TextBox(); + this.label10 = new System.Windows.Forms.Label(); + this.label11 = new System.Windows.Forms.Label(); + this.comboBox_accessPDO = new System.Windows.Forms.ComboBox(); + this.textBox_denotation = new System.Windows.Forms.TextBox(); + this.label13 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.textBox_name = new System.Windows.Forms.TextBox(); + this.textBox_description = new System.Windows.Forms.TextBox(); + this.contextMenu_object = new System.Windows.Forms.ContextMenuStrip(this.components); + this.contextMenu_object_addNewObjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.addToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenu_object_deleteObjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenu_object_toggleObjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenu_subObject = new System.Windows.Forms.ContextMenuStrip(this.components); + this.contextMenu_subObject_addSubItemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenu_subObject_removeSubItemToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).BeginInit(); + this.splitContainer1.Panel1.SuspendLayout(); + this.splitContainer1.Panel2.SuspendLayout(); + this.splitContainer1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).BeginInit(); + this.splitContainer2.Panel1.SuspendLayout(); + this.splitContainer2.Panel2.SuspendLayout(); + this.splitContainer2.SuspendLayout(); + this.tableLayoutPanel1.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).BeginInit(); + this.splitContainer3.Panel1.SuspendLayout(); + this.splitContainer3.Panel2.SuspendLayout(); + this.splitContainer3.SuspendLayout(); + this.tableLayoutPanel2.SuspendLayout(); + this.tableLayoutPanel3.SuspendLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer4)).BeginInit(); + this.splitContainer4.Panel1.SuspendLayout(); + this.splitContainer4.Panel2.SuspendLayout(); + this.splitContainer4.SuspendLayout(); + this.groupBox1.SuspendLayout(); + this.contextMenu_object.SuspendLayout(); + this.contextMenu_subObject.SuspendLayout(); + this.SuspendLayout(); + // + // splitContainer1 + // + this.splitContainer1.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer1.Location = new System.Drawing.Point(0, 0); + this.splitContainer1.Name = "splitContainer1"; + // + // splitContainer1.Panel1 + // + this.splitContainer1.Panel1.Controls.Add(this.splitContainer2); + // + // splitContainer1.Panel2 + // + this.splitContainer1.Panel2.Controls.Add(this.splitContainer4); + this.splitContainer1.Size = new System.Drawing.Size(1138, 745); + this.splitContainer1.SplitterDistance = 280; + this.splitContainer1.TabIndex = 2; + this.splitContainer1.TabStop = false; + // + // splitContainer2 + // + this.splitContainer2.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.splitContainer2.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer2.Location = new System.Drawing.Point(0, 0); + this.splitContainer2.Name = "splitContainer2"; + this.splitContainer2.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer2.Panel1 + // + this.splitContainer2.Panel1.Controls.Add(this.tableLayoutPanel1); + // + // splitContainer2.Panel2 + // + this.splitContainer2.Panel2.Controls.Add(this.splitContainer3); + this.splitContainer2.Size = new System.Drawing.Size(280, 745); + this.splitContainer2.SplitterDistance = 245; + this.splitContainer2.TabIndex = 0; + this.splitContainer2.TabStop = false; + // + // tableLayoutPanel1 + // + this.tableLayoutPanel1.ColumnCount = 1; + this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Controls.Add(this.listView_communication_objects, 0, 1); + this.tableLayoutPanel1.Controls.Add(this.label1, 0, 0); + this.tableLayoutPanel1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel1.Name = "tableLayoutPanel1"; + this.tableLayoutPanel1.RowCount = 2; + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel1.Size = new System.Drawing.Size(278, 243); + this.tableLayoutPanel1.TabIndex = 6; + // + // listView_communication_objects + // + this.listView_communication_objects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader1, + this.columnHeader2}); + this.listView_communication_objects.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView_communication_objects.FullRowSelect = true; + this.listView_communication_objects.HideSelection = false; + this.listView_communication_objects.Location = new System.Drawing.Point(3, 23); + this.listView_communication_objects.Name = "listView_communication_objects"; + this.listView_communication_objects.Size = new System.Drawing.Size(272, 217); + this.listView_communication_objects.TabIndex = 0; + this.listView_communication_objects.UseCompatibleStateImageBehavior = false; + this.listView_communication_objects.View = System.Windows.Forms.View.Details; + this.listView_communication_objects.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.ListView_objects_ColumnClick); + this.listView_communication_objects.SelectedIndexChanged += new System.EventHandler(this.ListView_objects_SelectedIndexChanged); + this.listView_communication_objects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_objects_MouseClick); + // + // columnHeader1 + // + this.columnHeader1.Text = "Index"; + // + // columnHeader2 + // + this.columnHeader2.Text = "Name"; + this.columnHeader2.Width = 185; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(3, 0); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(176, 13); + this.label1.TabIndex = 3; + this.label1.Text = "Communication Specific Parameters"; + // + // splitContainer3 + // + this.splitContainer3.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle; + this.splitContainer3.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer3.Location = new System.Drawing.Point(0, 0); + this.splitContainer3.Name = "splitContainer3"; + this.splitContainer3.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer3.Panel1 + // + this.splitContainer3.Panel1.Controls.Add(this.tableLayoutPanel2); + // + // splitContainer3.Panel2 + // + this.splitContainer3.Panel2.Controls.Add(this.tableLayoutPanel3); + this.splitContainer3.Size = new System.Drawing.Size(280, 496); + this.splitContainer3.SplitterDistance = 244; + this.splitContainer3.TabIndex = 0; + this.splitContainer3.TabStop = false; + // + // tableLayoutPanel2 + // + this.tableLayoutPanel2.ColumnCount = 1; + this.tableLayoutPanel2.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Controls.Add(this.label2, 0, 0); + this.tableLayoutPanel2.Controls.Add(this.listView_manufacturer_objects, 0, 1); + this.tableLayoutPanel2.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel2.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel2.Name = "tableLayoutPanel2"; + this.tableLayoutPanel2.RowCount = 2; + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel2.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel2.Size = new System.Drawing.Size(278, 242); + this.tableLayoutPanel2.TabIndex = 7; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(3, 0); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(167, 13); + this.label2.TabIndex = 4; + this.label2.Text = "Manufacturer Specific Parameters"; + // + // listView_manufacturer_objects + // + this.listView_manufacturer_objects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader3, + this.columnHeader4}); + this.listView_manufacturer_objects.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView_manufacturer_objects.FullRowSelect = true; + this.listView_manufacturer_objects.HideSelection = false; + this.listView_manufacturer_objects.Location = new System.Drawing.Point(3, 23); + this.listView_manufacturer_objects.Name = "listView_manufacturer_objects"; + this.listView_manufacturer_objects.Size = new System.Drawing.Size(272, 216); + this.listView_manufacturer_objects.TabIndex = 0; + this.listView_manufacturer_objects.UseCompatibleStateImageBehavior = false; + this.listView_manufacturer_objects.View = System.Windows.Forms.View.Details; + this.listView_manufacturer_objects.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.ListView_objects_ColumnClick); + this.listView_manufacturer_objects.SelectedIndexChanged += new System.EventHandler(this.ListView_objects_SelectedIndexChanged); + this.listView_manufacturer_objects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_objects_MouseClick); + // + // columnHeader3 + // + this.columnHeader3.Text = "Index"; + // + // columnHeader4 + // + this.columnHeader4.Text = "Name"; + this.columnHeader4.Width = 200; + // + // tableLayoutPanel3 + // + this.tableLayoutPanel3.ColumnCount = 1; + this.tableLayoutPanel3.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.Controls.Add(this.label3, 0, 0); + this.tableLayoutPanel3.Controls.Add(this.listView_deviceProfile_objects, 0, 1); + this.tableLayoutPanel3.Dock = System.Windows.Forms.DockStyle.Fill; + this.tableLayoutPanel3.Location = new System.Drawing.Point(0, 0); + this.tableLayoutPanel3.Name = "tableLayoutPanel3"; + this.tableLayoutPanel3.RowCount = 2; + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Absolute, 20F)); + this.tableLayoutPanel3.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 100F)); + this.tableLayoutPanel3.Size = new System.Drawing.Size(278, 246); + this.tableLayoutPanel3.TabIndex = 8; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(3, 0); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(170, 13); + this.label3.TabIndex = 5; + this.label3.Text = "Device Profile Specific Parameters"; + // + // listView_deviceProfile_objects + // + this.listView_deviceProfile_objects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader5, + this.columnHeader6}); + this.listView_deviceProfile_objects.Dock = System.Windows.Forms.DockStyle.Fill; + this.listView_deviceProfile_objects.FullRowSelect = true; + this.listView_deviceProfile_objects.HideSelection = false; + this.listView_deviceProfile_objects.Location = new System.Drawing.Point(3, 23); + this.listView_deviceProfile_objects.Name = "listView_deviceProfile_objects"; + this.listView_deviceProfile_objects.Size = new System.Drawing.Size(272, 220); + this.listView_deviceProfile_objects.TabIndex = 0; + this.listView_deviceProfile_objects.UseCompatibleStateImageBehavior = false; + this.listView_deviceProfile_objects.View = System.Windows.Forms.View.Details; + this.listView_deviceProfile_objects.ColumnClick += new System.Windows.Forms.ColumnClickEventHandler(this.ListView_objects_ColumnClick); + this.listView_deviceProfile_objects.SelectedIndexChanged += new System.EventHandler(this.ListView_objects_SelectedIndexChanged); + this.listView_deviceProfile_objects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_objects_MouseClick); + // + // columnHeader5 + // + this.columnHeader5.Text = "Index"; + // + // columnHeader6 + // + this.columnHeader6.Text = "Name"; + this.columnHeader6.Width = 200; + // + // splitContainer4 + // + this.splitContainer4.Dock = System.Windows.Forms.DockStyle.Fill; + this.splitContainer4.Location = new System.Drawing.Point(0, 0); + this.splitContainer4.Name = "splitContainer4"; + this.splitContainer4.Orientation = System.Windows.Forms.Orientation.Horizontal; + // + // splitContainer4.Panel1 + // + this.splitContainer4.Panel1.Controls.Add(this.listView_subObjects); + // + // splitContainer4.Panel2 + // + this.splitContainer4.Panel2.Controls.Add(this.textBox_subIndex); + this.splitContainer4.Panel2.Controls.Add(this.label23); + this.splitContainer4.Panel2.Controls.Add(this.textBox_index); + this.splitContainer4.Panel2.Controls.Add(this.groupBox1); + this.splitContainer4.Panel2.Controls.Add(this.textBox_denotation); + this.splitContainer4.Panel2.Controls.Add(this.label13); + this.splitContainer4.Panel2.Controls.Add(this.label4); + this.splitContainer4.Panel2.Controls.Add(this.label5); + this.splitContainer4.Panel2.Controls.Add(this.label6); + this.splitContainer4.Panel2.Controls.Add(this.textBox_name); + this.splitContainer4.Panel2.Controls.Add(this.textBox_description); + this.splitContainer4.Size = new System.Drawing.Size(854, 745); + this.splitContainer4.SplitterDistance = 224; + this.splitContainer4.TabIndex = 28; + this.splitContainer4.TabStop = false; + // + // listView_subObjects + // + this.listView_subObjects.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.listView_subObjects.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader7, + this.columnHeader8, + this.columnHeader9, + this.columnHeader10, + this.columnHeader11, + this.columnHeader12, + this.columnHeader13, + this.columnHeader14}); + this.listView_subObjects.FullRowSelect = true; + this.listView_subObjects.HideSelection = false; + this.listView_subObjects.Location = new System.Drawing.Point(0, 0); + this.listView_subObjects.Name = "listView_subObjects"; + this.listView_subObjects.Size = new System.Drawing.Size(851, 223); + this.listView_subObjects.TabIndex = 0; + this.listView_subObjects.UseCompatibleStateImageBehavior = false; + this.listView_subObjects.View = System.Windows.Forms.View.Details; + this.listView_subObjects.SelectedIndexChanged += new System.EventHandler(this.ListView_subObjects_SelectedIndexChanged); + this.listView_subObjects.MouseClick += new System.Windows.Forms.MouseEventHandler(this.ListView_subObjects_MouseClick); + // + // columnHeader7 + // + this.columnHeader7.Text = "Sub"; + this.columnHeader7.Width = 40; + // + // columnHeader8 + // + this.columnHeader8.Text = "Name"; + this.columnHeader8.Width = 200; + // + // columnHeader9 + // + this.columnHeader9.Text = "Obj Type"; + this.columnHeader9.Width = 65; + // + // columnHeader10 + // + this.columnHeader10.Text = "Data Type"; + this.columnHeader10.Width = 120; + // + // columnHeader11 + // + this.columnHeader11.Text = "SDO"; + this.columnHeader11.Width = 50; + // + // columnHeader12 + // + this.columnHeader12.Text = "PDO"; + this.columnHeader12.Width = 50; + // + // columnHeader13 + // + this.columnHeader13.Text = "SRDO"; + this.columnHeader13.Width = 50; + // + // columnHeader14 + // + this.columnHeader14.Text = "Default Value"; + this.columnHeader14.Width = 190; + // + // textBox_subIndex + // + this.textBox_subIndex.Location = new System.Drawing.Point(260, 8); + this.textBox_subIndex.Name = "textBox_subIndex"; + this.textBox_subIndex.ReadOnly = true; + this.textBox_subIndex.Size = new System.Drawing.Size(100, 20); + this.textBox_subIndex.TabIndex = 0; + this.textBox_subIndex.TabStop = false; + // + // label23 + // + this.label23.AutoSize = true; + this.label23.Location = new System.Drawing.Point(199, 11); + this.label23.Name = "label23"; + this.label23.Size = new System.Drawing.Size(55, 13); + this.label23.TabIndex = 34; + this.label23.Text = "Sub Index"; + // + // textBox_index + // + this.textBox_index.Location = new System.Drawing.Point(90, 8); + this.textBox_index.Name = "textBox_index"; + this.textBox_index.ReadOnly = true; + this.textBox_index.Size = new System.Drawing.Size(100, 20); + this.textBox_index.TabIndex = 0; + this.textBox_index.TabStop = false; + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.checkBox_autosave); + this.groupBox1.Controls.Add(this.textBox_stringLengthMin); + this.groupBox1.Controls.Add(this.label22); + this.groupBox1.Controls.Add(this.label20); + this.groupBox1.Controls.Add(this.comboBox_countLabel); + this.groupBox1.Controls.Add(this.label19); + this.groupBox1.Controls.Add(this.comboBox_accessSRDO); + this.groupBox1.Controls.Add(this.textBox_actualValue); + this.groupBox1.Controls.Add(this.textBox_lowLimit); + this.groupBox1.Controls.Add(this.textBox_highLimit); + this.groupBox1.Controls.Add(this.label18); + this.groupBox1.Controls.Add(this.label17); + this.groupBox1.Controls.Add(this.label14); + this.groupBox1.Controls.Add(this.button_saveChanges); + this.groupBox1.Controls.Add(this.label16); + this.groupBox1.Controls.Add(this.comboBox_storageGroup); + this.groupBox1.Controls.Add(this.label15); + this.groupBox1.Controls.Add(this.checkBox_enabled); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.comboBox_objectType); + this.groupBox1.Controls.Add(this.label8); + this.groupBox1.Controls.Add(this.comboBox_dataType); + this.groupBox1.Controls.Add(this.label_pdoFlags); + this.groupBox1.Controls.Add(this.label9); + this.groupBox1.Controls.Add(this.checkBox_pdoFlags); + this.groupBox1.Controls.Add(this.comboBox_accessSDO); + this.groupBox1.Controls.Add(this.textBox_defaultValue); + this.groupBox1.Controls.Add(this.label10); + this.groupBox1.Controls.Add(this.label11); + this.groupBox1.Controls.Add(this.comboBox_accessPDO); + this.groupBox1.Dock = System.Windows.Forms.DockStyle.Bottom; + this.groupBox1.Location = new System.Drawing.Point(0, 329); + this.groupBox1.Margin = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Padding = new System.Windows.Forms.Padding(2, 2, 2, 2); + this.groupBox1.Size = new System.Drawing.Size(854, 188); + this.groupBox1.TabIndex = 33; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Object settings"; + // + // checkBox_autosave + // + this.checkBox_autosave.Location = new System.Drawing.Point(634, 146); + this.checkBox_autosave.Name = "checkBox_autosave"; + this.checkBox_autosave.Size = new System.Drawing.Size(116, 21); + this.checkBox_autosave.TabIndex = 35; + this.checkBox_autosave.Text = "Autosave changes"; + this.checkBox_autosave.UseVisualStyleBackColor = true; + // + // textBox_stringLengthMin + // + this.textBox_stringLengthMin.Location = new System.Drawing.Point(340, 99); + this.textBox_stringLengthMin.Name = "textBox_stringLengthMin"; + this.textBox_stringLengthMin.Size = new System.Drawing.Size(122, 20); + this.textBox_stringLengthMin.TabIndex = 24; + this.textBox_stringLengthMin.TextChanged += new System.EventHandler(this.DataDirty); + // + // label22 + // + this.label22.AutoSize = true; + this.label22.Location = new System.Drawing.Point(248, 102); + this.label22.Name = "label22"; + this.label22.Size = new System.Drawing.Size(75, 13); + this.label22.TabIndex = 39; + this.label22.Text = "String Len Min"; + // + // label20 + // + this.label20.AutoSize = true; + this.label20.Location = new System.Drawing.Point(482, 21); + this.label20.Name = "label20"; + this.label20.Size = new System.Drawing.Size(64, 13); + this.label20.TabIndex = 36; + this.label20.Text = "Count Label"; + // + // comboBox_countLabel + // + this.comboBox_countLabel.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_countLabel.FormattingEnabled = true; + this.comboBox_countLabel.Location = new System.Drawing.Point(574, 18); + this.comboBox_countLabel.Name = "comboBox_countLabel"; + this.comboBox_countLabel.Size = new System.Drawing.Size(122, 21); + this.comboBox_countLabel.TabIndex = 30; + this.comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.DataDirty); + // + // label19 + // + this.label19.AutoSize = true; + this.label19.Location = new System.Drawing.Point(13, 129); + this.label19.Name = "label19"; + this.label19.Size = new System.Drawing.Size(76, 13); + this.label19.TabIndex = 34; + this.label19.Text = "Access SRDO"; + // + // comboBox_accessSRDO + // + this.comboBox_accessSRDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_accessSRDO.FormattingEnabled = true; + this.comboBox_accessSRDO.Location = new System.Drawing.Point(108, 126); + this.comboBox_accessSRDO.Name = "comboBox_accessSRDO"; + this.comboBox_accessSRDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessSRDO.TabIndex = 14; + this.comboBox_accessSRDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); + // + // textBox_actualValue + // + this.textBox_actualValue.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_actualValue.Location = new System.Drawing.Point(340, 72); + this.textBox_actualValue.Name = "textBox_actualValue"; + this.textBox_actualValue.Size = new System.Drawing.Size(122, 20); + this.textBox_actualValue.TabIndex = 23; + this.textBox_actualValue.TextChanged += new System.EventHandler(this.DataDirty); + // + // textBox_lowLimit + // + this.textBox_lowLimit.Location = new System.Drawing.Point(340, 45); + this.textBox_lowLimit.Name = "textBox_lowLimit"; + this.textBox_lowLimit.Size = new System.Drawing.Size(122, 20); + this.textBox_lowLimit.TabIndex = 22; + this.textBox_lowLimit.TextChanged += new System.EventHandler(this.DataDirty); + // + // textBox_highLimit + // + this.textBox_highLimit.Location = new System.Drawing.Point(340, 18); + this.textBox_highLimit.Name = "textBox_highLimit"; + this.textBox_highLimit.Size = new System.Drawing.Size(122, 20); + this.textBox_highLimit.TabIndex = 21; + this.textBox_highLimit.TextChanged += new System.EventHandler(this.DataDirty); + // + // label18 + // + this.label18.AutoSize = true; + this.label18.Location = new System.Drawing.Point(248, 75); + this.label18.Name = "label18"; + this.label18.Size = new System.Drawing.Size(67, 13); + this.label18.TabIndex = 32; + this.label18.Text = "Actual Value"; + // + // label17 + // + this.label17.AutoSize = true; + this.label17.Location = new System.Drawing.Point(248, 48); + this.label17.Name = "label17"; + this.label17.Size = new System.Drawing.Size(48, 13); + this.label17.TabIndex = 31; + this.label17.Text = "LowLimit"; + // + // label14 + // + this.label14.AutoSize = true; + this.label14.Location = new System.Drawing.Point(248, 21); + this.label14.Name = "label14"; + this.label14.Size = new System.Drawing.Size(50, 13); + this.label14.TabIndex = 30; + this.label14.Text = "HighLimit"; + // + // button_saveChanges + // + this.button_saveChanges.Image = global::ODEditor.Properties.Resources.Save_6530; + this.button_saveChanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_saveChanges.Location = new System.Drawing.Point(485, 138); + this.button_saveChanges.Name = "button_saveChanges"; + this.button_saveChanges.Size = new System.Drawing.Size(143, 35); + this.button_saveChanges.TabIndex = 50; + this.button_saveChanges.Text = "Save Changes"; + this.button_saveChanges.UseVisualStyleBackColor = true; + this.button_saveChanges.Click += new System.EventHandler(this.Button_saveChanges_Click); + // + // label16 + // + this.label16.AutoSize = true; + this.label16.Location = new System.Drawing.Point(482, 48); + this.label16.Name = "label16"; + this.label16.Size = new System.Drawing.Size(76, 13); + this.label16.TabIndex = 26; + this.label16.Text = "Storage Group"; + // + // comboBox_storageGroup + // + this.comboBox_storageGroup.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_storageGroup.FormattingEnabled = true; + this.comboBox_storageGroup.Location = new System.Drawing.Point(574, 45); + this.comboBox_storageGroup.Name = "comboBox_storageGroup"; + this.comboBox_storageGroup.Size = new System.Drawing.Size(122, 21); + this.comboBox_storageGroup.TabIndex = 31; + this.comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.DataDirty); + // + // label15 + // + this.label15.AutoSize = true; + this.label15.Location = new System.Drawing.Point(482, 72); + this.label15.Name = "label15"; + this.label15.Size = new System.Drawing.Size(46, 13); + this.label15.TabIndex = 24; + this.label15.Text = "Enabled"; + // + // checkBox_enabled + // + this.checkBox_enabled.AutoSize = true; + this.checkBox_enabled.Location = new System.Drawing.Point(574, 72); + this.checkBox_enabled.Name = "checkBox_enabled"; + this.checkBox_enabled.Size = new System.Drawing.Size(15, 14); + this.checkBox_enabled.TabIndex = 32; + this.checkBox_enabled.UseVisualStyleBackColor = true; + this.checkBox_enabled.CheckedChanged += new System.EventHandler(this.DataDirty); + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(13, 21); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(65, 13); + this.label7.TabIndex = 7; + this.label7.Text = "Object Type"; + // + // comboBox_objectType + // + this.comboBox_objectType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_objectType.Enabled = false; + this.comboBox_objectType.FormattingEnabled = true; + this.comboBox_objectType.Location = new System.Drawing.Point(108, 18); + this.comboBox_objectType.Name = "comboBox_objectType"; + this.comboBox_objectType.Size = new System.Drawing.Size(122, 21); + this.comboBox_objectType.TabIndex = 10; + this.comboBox_objectType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); + // + // label8 + // + this.label8.AutoSize = true; + this.label8.Location = new System.Drawing.Point(13, 48); + this.label8.Name = "label8"; + this.label8.Size = new System.Drawing.Size(57, 13); + this.label8.TabIndex = 9; + this.label8.Text = "Data Type"; + // + // comboBox_dataType + // + this.comboBox_dataType.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_dataType.FormattingEnabled = true; + this.comboBox_dataType.Location = new System.Drawing.Point(108, 45); + this.comboBox_dataType.Name = "comboBox_dataType"; + this.comboBox_dataType.Size = new System.Drawing.Size(122, 21); + this.comboBox_dataType.TabIndex = 11; + this.comboBox_dataType.SelectedIndexChanged += new System.EventHandler(this.DataDirty); + // + // label_pdoFlags + // + this.label_pdoFlags.AutoSize = true; + this.label_pdoFlags.Location = new System.Drawing.Point(482, 92); + this.label_pdoFlags.Name = "label_pdoFlags"; + this.label_pdoFlags.Size = new System.Drawing.Size(62, 13); + this.label_pdoFlags.TabIndex = 18; + this.label_pdoFlags.Text = "TPDO COS"; + // + // label9 + // + this.label9.AutoSize = true; + this.label9.Location = new System.Drawing.Point(13, 75); + this.label9.Name = "label9"; + this.label9.Size = new System.Drawing.Size(68, 13); + this.label9.TabIndex = 11; + this.label9.Text = "Access SDO"; + // + // checkBox_pdoFlags + // + this.checkBox_pdoFlags.AutoSize = true; + this.checkBox_pdoFlags.Location = new System.Drawing.Point(574, 92); + this.checkBox_pdoFlags.Name = "checkBox_pdoFlags"; + this.checkBox_pdoFlags.Size = new System.Drawing.Size(15, 14); + this.checkBox_pdoFlags.TabIndex = 34; + this.checkBox_pdoFlags.UseVisualStyleBackColor = true; + this.checkBox_pdoFlags.CheckedChanged += new System.EventHandler(this.DataDirty); + // + // comboBox_accessSDO + // + this.comboBox_accessSDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_accessSDO.FormattingEnabled = true; + this.comboBox_accessSDO.Location = new System.Drawing.Point(108, 72); + this.comboBox_accessSDO.Name = "comboBox_accessSDO"; + this.comboBox_accessSDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessSDO.TabIndex = 12; + this.comboBox_accessSDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); + // + // textBox_defaultValue + // + this.textBox_defaultValue.Location = new System.Drawing.Point(108, 153); + this.textBox_defaultValue.Name = "textBox_defaultValue"; + this.textBox_defaultValue.Size = new System.Drawing.Size(354, 20); + this.textBox_defaultValue.TabIndex = 20; + this.textBox_defaultValue.TextChanged += new System.EventHandler(this.DataDirty); + // + // label10 + // + this.label10.AutoSize = true; + this.label10.Location = new System.Drawing.Point(13, 102); + this.label10.Name = "label10"; + this.label10.Size = new System.Drawing.Size(68, 13); + this.label10.TabIndex = 13; + this.label10.Text = "Access PDO"; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(13, 156); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(70, 13); + this.label11.TabIndex = 15; + this.label11.Text = "Default value"; + // + // comboBox_accessPDO + // + this.comboBox_accessPDO.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + this.comboBox_accessPDO.FormattingEnabled = true; + this.comboBox_accessPDO.Location = new System.Drawing.Point(108, 99); + this.comboBox_accessPDO.Name = "comboBox_accessPDO"; + this.comboBox_accessPDO.Size = new System.Drawing.Size(122, 21); + this.comboBox_accessPDO.TabIndex = 13; + this.comboBox_accessPDO.SelectedIndexChanged += new System.EventHandler(this.DataDirty); + // + // textBox_denotation + // + this.textBox_denotation.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox_denotation.BackColor = System.Drawing.Color.PeachPuff; + this.textBox_denotation.Location = new System.Drawing.Point(90, 60); + this.textBox_denotation.Name = "textBox_denotation"; + this.textBox_denotation.Size = new System.Drawing.Size(761, 20); + this.textBox_denotation.TabIndex = 3; + this.textBox_denotation.TextChanged += new System.EventHandler(this.DataDirty); + // + // label13 + // + this.label13.AutoSize = true; + this.label13.Location = new System.Drawing.Point(13, 63); + this.label13.Name = "label13"; + this.label13.Size = new System.Drawing.Size(59, 13); + this.label13.TabIndex = 28; + this.label13.Text = "Denotation"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(13, 11); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(33, 13); + this.label4.TabIndex = 1; + this.label4.Text = "Index"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(13, 37); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(35, 13); + this.label5.TabIndex = 2; + this.label5.Text = "Name"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(13, 89); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(60, 13); + this.label6.TabIndex = 3; + this.label6.Text = "Description"; + // + // textBox_name + // + this.textBox_name.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox_name.Location = new System.Drawing.Point(90, 34); + this.textBox_name.Name = "textBox_name"; + this.textBox_name.Size = new System.Drawing.Size(761, 20); + this.textBox_name.TabIndex = 2; + this.textBox_name.TextChanged += new System.EventHandler(this.DataDirty); + // + // textBox_description + // + this.textBox_description.AcceptsReturn = true; + this.textBox_description.AcceptsTab = true; + this.textBox_description.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox_description.Font = new System.Drawing.Font("Courier New", 8.25F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0))); + this.textBox_description.Location = new System.Drawing.Point(90, 86); + this.textBox_description.Multiline = true; + this.textBox_description.Name = "textBox_description"; + this.textBox_description.ScrollBars = System.Windows.Forms.ScrollBars.Vertical; + this.textBox_description.Size = new System.Drawing.Size(761, 227); + this.textBox_description.TabIndex = 4; + this.textBox_description.TextChanged += new System.EventHandler(this.DataDirty); + // + // contextMenu_object + // + this.contextMenu_object.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenu_object.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.contextMenu_object_addNewObjectToolStripMenuItem, + this.addToolStripMenuItem, + this.contextMenu_object_deleteObjectToolStripMenuItem, + this.contextMenu_object_toggleObjectToolStripMenuItem}); + this.contextMenu_object.Name = "contextMenuStrip1"; + this.contextMenu_object.Size = new System.Drawing.Size(121, 108); + // + // contextMenu_object_addNewObjectToolStripMenuItem + // + this.contextMenu_object_addNewObjectToolStripMenuItem.Name = "contextMenu_object_addNewObjectToolStripMenuItem"; + this.contextMenu_object_addNewObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_addNewObjectToolStripMenuItem.Text = "&Clone..."; + this.contextMenu_object_addNewObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_clone_ToolStripMenuItem_Click); + // + // addToolStripMenuItem + // + this.addToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; + this.addToolStripMenuItem.Name = "addToolStripMenuItem"; + this.addToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.addToolStripMenuItem.Text = "Add..."; + this.addToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_add_ToolStripMenuItem_Click); + // + // contextMenu_object_deleteObjectToolStripMenuItem + // + this.contextMenu_object_deleteObjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; + this.contextMenu_object_deleteObjectToolStripMenuItem.Name = "contextMenu_object_deleteObjectToolStripMenuItem"; + this.contextMenu_object_deleteObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_deleteObjectToolStripMenuItem.Text = "&Delete..."; + this.contextMenu_object_deleteObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_delete_ToolStripMenuItem_Click); + // + // contextMenu_object_toggleObjectToolStripMenuItem + // + this.contextMenu_object_toggleObjectToolStripMenuItem.Name = "contextMenu_object_toggleObjectToolStripMenuItem"; + this.contextMenu_object_toggleObjectToolStripMenuItem.Size = new System.Drawing.Size(120, 26); + this.contextMenu_object_toggleObjectToolStripMenuItem.Text = "&Toggle"; + this.contextMenu_object_toggleObjectToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_object_toggle_ToolStripMenuItem_Click); + // + // contextMenu_subObject + // + this.contextMenu_subObject.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenu_subObject.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.contextMenu_subObject_addSubItemToolStripMenuItem, + this.contextMenu_subObject_removeSubItemToolStripMenuItem, + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem}); + this.contextMenu_subObject.Name = "contextMenu_array"; + this.contextMenu_subObject.Size = new System.Drawing.Size(183, 82); + // + // contextMenu_subObject_addSubItemToolStripMenuItem + // + this.contextMenu_subObject_addSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.action_add_16xLG; + this.contextMenu_subObject_addSubItemToolStripMenuItem.Name = "contextMenu_subObject_addSubItemToolStripMenuItem"; + this.contextMenu_subObject_addSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_addSubItemToolStripMenuItem.Text = "Add"; + this.contextMenu_subObject_addSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_add_ToolStripMenuItem_Click); + // + // contextMenu_subObject_removeSubItemToolStripMenuItem + // + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemToolStripMenuItem"; + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Text = "Remove (shift up)"; + this.contextMenu_subObject_removeSubItemToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); + // + // contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem + // + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Remove_16xLG; + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Name = "contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem"; + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Size = new System.Drawing.Size(182, 26); + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Text = "Remove (leave gap)"; + this.contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Click += new System.EventHandler(this.ContextMenu_subObject_remove_ToolStripMenuItem_Click); + // + // DeviceODView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.splitContainer1); + this.Name = "DeviceODView"; + this.Size = new System.Drawing.Size(1138, 745); + this.splitContainer1.Panel1.ResumeLayout(false); + this.splitContainer1.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer1)).EndInit(); + this.splitContainer1.ResumeLayout(false); + this.splitContainer2.Panel1.ResumeLayout(false); + this.splitContainer2.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer2)).EndInit(); + this.splitContainer2.ResumeLayout(false); + this.tableLayoutPanel1.ResumeLayout(false); + this.tableLayoutPanel1.PerformLayout(); + this.splitContainer3.Panel1.ResumeLayout(false); + this.splitContainer3.Panel2.ResumeLayout(false); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer3)).EndInit(); + this.splitContainer3.ResumeLayout(false); + this.tableLayoutPanel2.ResumeLayout(false); + this.tableLayoutPanel2.PerformLayout(); + this.tableLayoutPanel3.ResumeLayout(false); + this.tableLayoutPanel3.PerformLayout(); + this.splitContainer4.Panel1.ResumeLayout(false); + this.splitContainer4.Panel2.ResumeLayout(false); + this.splitContainer4.Panel2.PerformLayout(); + ((System.ComponentModel.ISupportInitialize)(this.splitContainer4)).EndInit(); + this.splitContainer4.ResumeLayout(false); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.contextMenu_object.ResumeLayout(false); + this.contextMenu_subObject.ResumeLayout(false); + this.ResumeLayout(false); + } #endregion @@ -1049,6 +1049,6 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_subIndex; private System.Windows.Forms.Label label23; private System.Windows.Forms.ToolStripMenuItem addToolStripMenuItem; - private System.Windows.Forms.CheckBox checkBox_autosave; + private System.Windows.Forms.CheckBox checkBox_autosave; } } diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index b7ded4ce..fcc18215 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -24,149 +24,149 @@ You should have received a copy of the GNU General Public License using System.Windows.Forms; using System.Reflection; using System.Text.RegularExpressions; -using libEDSsharp; - - +using libEDSsharp; + + namespace ODEditor { public partial class DeviceODView : MyTabUserControl { EDSsharp eds = null; - public List network; + public List network; ODentry selectedObject; ODentry lastSelectedObject; ListView selectedList; - bool justUpdating = false; - bool ExporterOld = false; - bool ExporterV4 = false; - - public event EventHandler UpdateODViewForEDS; - + bool justUpdating = false; + bool ExporterOld = false; + bool ExporterV4 = false; + + public event EventHandler UpdateODViewForEDS; + public DeviceODView() { - InitializeComponent(); - RebuildControls(); - - // other elements may be added in PopulateObjectLists() - comboBox_countLabel.Items.Add(""); - comboBox_countLabel.Items.Add("Add..."); - comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.ComboBox_countLabel_Add); - comboBox_storageGroup.Items.Add("Add..."); - comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.ComboBox_storageGroup_Add); - - listView_communication_objects.DoubleBuffering(true); - listView_deviceProfile_objects.DoubleBuffering(true); - listView_manufacturer_objects.DoubleBuffering(true); - listView_subObjects.DoubleBuffering(true); - } - - - public void RebuildControls() - { - if (ExporterTypeV4()) - { - comboBox_dataType.Items.Clear(); - comboBox_dataType.Items.Add(DataType.BOOLEAN.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER8.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER16.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER32.ToString()); - comboBox_dataType.Items.Add(DataType.INTEGER64.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED8.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED16.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED32.ToString()); - comboBox_dataType.Items.Add(DataType.UNSIGNED64.ToString()); - comboBox_dataType.Items.Add(DataType.REAL32.ToString()); - comboBox_dataType.Items.Add(DataType.REAL64.ToString()); - comboBox_dataType.Items.Add(DataType.VISIBLE_STRING.ToString()); - comboBox_dataType.Items.Add(DataType.OCTET_STRING.ToString()); - comboBox_dataType.Items.Add(DataType.UNICODE_STRING.ToString()); - comboBox_dataType.Items.Add(DataType.DOMAIN.ToString()); - - comboBox_objectType.Items.Clear(); - comboBox_objectType.Items.Add(ObjectType.VAR.ToString()); - comboBox_objectType.Items.Add(ObjectType.ARRAY.ToString()); - comboBox_objectType.Items.Add(ObjectType.RECORD.ToString()); - - comboBox_accessSDO.Items.Clear(); - foreach (AccessSDO foo in Enum.GetValues(typeof(AccessSDO))) - comboBox_accessSDO.Items.Add(foo.ToString()); - - comboBox_accessPDO.Items.Clear(); - foreach (AccessPDO foo in Enum.GetValues(typeof(AccessPDO))) - comboBox_accessPDO.Items.Add(foo.ToString()); - - label_pdoFlags.Visible = false; - checkBox_pdoFlags.Visible = false; - } - else - { - comboBox_dataType.Items.Clear(); - foreach (DataType foo in Enum.GetValues(typeof(DataType))) - comboBox_dataType.Items.Add(foo.ToString()); - comboBox_objectType.Items.Clear(); - foreach (ObjectType foo in Enum.GetValues(typeof(ObjectType))) - comboBox_objectType.Items.Add(foo.ToString()); - comboBox_accessSDO.Items.Clear(); - foreach (EDSsharp.AccessType foo in Enum.GetValues(typeof(EDSsharp.AccessType))) - comboBox_accessSDO.Items.Add(foo.ToString()); - comboBox_accessPDO.Items.Clear(); - foreach (PDOMappingType foo in Enum.GetValues(typeof(PDOMappingType))) - comboBox_accessPDO.Items.Add(foo.ToString()); - - label_pdoFlags.Visible = true; - checkBox_pdoFlags.Visible = true; - } - - comboBox_accessSRDO.Items.Clear(); - foreach (AccessSRDO foo in Enum.GetValues(typeof(AccessSRDO))) - comboBox_accessSRDO.Items.Add(foo.ToString()); - - - } - private bool ExporterTypeV4() { - ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; - return (type == ExporterFactory.Exporter.CANOPENNODE_V4); - } - - private bool Checkdirty() - { - var result = false; - - if (button_saveChanges.BackColor == Color.Red) - { - - var answer = checkBox_autosave.Checked - ? DialogResult.No - : MessageBox.Show(String.Format("Unsaved changes on Index 0x{0:X4}/{1:X2}.\nDo you wish to switch object and loose your changes?\n\nYes = Lose changes\nNo = Save\nCancel = Go back and stay on the object", lastSelectedObject.Index, lastSelectedObject.Subindex), "Unsaved changes", MessageBoxButtons.YesNoCancel); ; - - - switch (answer) - { - case DialogResult.Cancel: - default: - result = lastSelectedObject != null; - break; - - case DialogResult.Yes: - result = false; - break; - - case DialogResult.No: - if (lastSelectedObject != null) - { - ObjectSave(); - result = false; - } - break; - } - - button_saveChanges.BackColor = default; - } - - return result; + InitializeComponent(); + RebuildControls(); + + // other elements may be added in PopulateObjectLists() + comboBox_countLabel.Items.Add(""); + comboBox_countLabel.Items.Add("Add..."); + comboBox_countLabel.SelectedIndexChanged += new System.EventHandler(this.ComboBox_countLabel_Add); + comboBox_storageGroup.Items.Add("Add..."); + comboBox_storageGroup.SelectedIndexChanged += new System.EventHandler(this.ComboBox_storageGroup_Add); + + listView_communication_objects.DoubleBuffering(true); + listView_deviceProfile_objects.DoubleBuffering(true); + listView_manufacturer_objects.DoubleBuffering(true); + listView_subObjects.DoubleBuffering(true); + } + + + public void RebuildControls() + { + if (ExporterTypeV4()) + { + comboBox_dataType.Items.Clear(); + comboBox_dataType.Items.Add(DataType.BOOLEAN.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER8.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER16.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER32.ToString()); + comboBox_dataType.Items.Add(DataType.INTEGER64.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED8.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED16.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED32.ToString()); + comboBox_dataType.Items.Add(DataType.UNSIGNED64.ToString()); + comboBox_dataType.Items.Add(DataType.REAL32.ToString()); + comboBox_dataType.Items.Add(DataType.REAL64.ToString()); + comboBox_dataType.Items.Add(DataType.VISIBLE_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.OCTET_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.UNICODE_STRING.ToString()); + comboBox_dataType.Items.Add(DataType.DOMAIN.ToString()); + + comboBox_objectType.Items.Clear(); + comboBox_objectType.Items.Add(ObjectType.VAR.ToString()); + comboBox_objectType.Items.Add(ObjectType.ARRAY.ToString()); + comboBox_objectType.Items.Add(ObjectType.RECORD.ToString()); + + comboBox_accessSDO.Items.Clear(); + foreach (AccessSDO foo in Enum.GetValues(typeof(AccessSDO))) + comboBox_accessSDO.Items.Add(foo.ToString()); + + comboBox_accessPDO.Items.Clear(); + foreach (AccessPDO foo in Enum.GetValues(typeof(AccessPDO))) + comboBox_accessPDO.Items.Add(foo.ToString()); + + label_pdoFlags.Visible = false; + checkBox_pdoFlags.Visible = false; + } + else + { + comboBox_dataType.Items.Clear(); + foreach (DataType foo in Enum.GetValues(typeof(DataType))) + comboBox_dataType.Items.Add(foo.ToString()); + comboBox_objectType.Items.Clear(); + foreach (ObjectType foo in Enum.GetValues(typeof(ObjectType))) + comboBox_objectType.Items.Add(foo.ToString()); + comboBox_accessSDO.Items.Clear(); + foreach (EDSsharp.AccessType foo in Enum.GetValues(typeof(EDSsharp.AccessType))) + comboBox_accessSDO.Items.Add(foo.ToString()); + comboBox_accessPDO.Items.Clear(); + foreach (PDOMappingType foo in Enum.GetValues(typeof(PDOMappingType))) + comboBox_accessPDO.Items.Add(foo.ToString()); + + label_pdoFlags.Visible = true; + checkBox_pdoFlags.Visible = true; + } + + comboBox_accessSRDO.Items.Clear(); + foreach (AccessSRDO foo in Enum.GetValues(typeof(AccessSRDO))) + comboBox_accessSRDO.Items.Add(foo.ToString()); + + + } + private bool ExporterTypeV4() { + ExporterFactory.Exporter type = (ExporterFactory.Exporter)Properties.Settings.Default.ExporterType; + return (type == ExporterFactory.Exporter.CANOPENNODE_V4); + } + + private bool Checkdirty() + { + var result = false; + + if (button_saveChanges.BackColor == Color.Red) + { + + var answer = checkBox_autosave.Checked + ? DialogResult.No + : MessageBox.Show(String.Format("Unsaved changes on Index 0x{0:X4}/{1:X2}.\nDo you wish to switch object and loose your changes?\n\nYes = Lose changes\nNo = Save\nCancel = Go back and stay on the object", lastSelectedObject.Index, lastSelectedObject.Subindex), "Unsaved changes", MessageBoxButtons.YesNoCancel); ; + + + switch (answer) + { + case DialogResult.Cancel: + default: + result = lastSelectedObject != null; + break; + + case DialogResult.Yes: + result = false; + break; + + case DialogResult.No: + if (lastSelectedObject != null) + { + ObjectSave(); + result = false; + } + break; + } + + button_saveChanges.BackColor = default; + } + + return result; } private void ComboBoxSet(ComboBox comboBox, string item) @@ -259,7 +259,7 @@ public void PopulateSubList() listView_subObjects.Items.Clear(); if (selectedObject == null) - return; + return; ODentry od = selectedObject.parent ?? selectedObject; if (od.objecttype == ObjectType.VAR) @@ -312,10 +312,10 @@ public void PopulateObject() { ExporterV4 = ExporterTypeV4(); - if (ExporterOld != ExporterV4) + if (ExporterOld != ExporterV4) { RebuildControls(); - ExporterOld = ExporterV4; + ExporterOld = ExporterV4; } justUpdating = true; @@ -360,15 +360,15 @@ public void PopulateObject() : od.datatype.ToString(); ComboBoxSet(comboBox_dataType, dataType); - if (ExporterV4) - { - comboBox_accessSDO.SelectedItem = od.AccessSDO().ToString(); - comboBox_accessPDO.SelectedItem = od.AccessPDO().ToString(); + if (ExporterV4) + { + comboBox_accessSDO.SelectedItem = od.AccessSDO().ToString(); + comboBox_accessPDO.SelectedItem = od.AccessPDO().ToString(); } - else - { - comboBox_accessSDO.SelectedItem = od.accesstype.ToString(); - comboBox_accessPDO.SelectedItem = od.PDOtype.ToString(); + else + { + comboBox_accessSDO.SelectedItem = od.accesstype.ToString(); + comboBox_accessPDO.SelectedItem = od.PDOtype.ToString(); } comboBox_accessSRDO.SelectedItem = od.prop.CO_accessSRDO.ToString(); @@ -439,17 +439,17 @@ private void DataDirty(object sender, EventArgs e) } private void Button_saveChanges_Click(object sender, EventArgs e) - { - ObjectSave(); - } + { + ObjectSave(); + } - private void ObjectSave() - { + private void ObjectSave() + { ExporterV4 = ExporterTypeV4(); - if (ExporterOld != ExporterV4) + if (ExporterOld != ExporterV4) { RebuildControls(); - ExporterOld = ExporterV4; + ExporterOld = ExporterV4; } if (selectedObject == null) @@ -475,56 +475,56 @@ private void ObjectSave() od.datatype = DataType.UNKNOWN; } - if (ExporterV4) - { - AccessSDO accessSDO; - try - { - accessSDO = (AccessSDO)Enum.Parse(typeof(AccessSDO), comboBox_accessSDO.SelectedItem.ToString()); - } - catch (Exception) - { - accessSDO = AccessSDO.ro; - } - - AccessPDO accessPDO; - try - { - accessPDO = (AccessPDO)Enum.Parse(typeof(AccessPDO), comboBox_accessPDO.SelectedItem.ToString()); - } - catch (Exception) - { - accessPDO = AccessPDO.no; - } - - od.AccessSDO(accessSDO, accessPDO); - od.AccessPDO(accessPDO); + if (ExporterV4) + { + AccessSDO accessSDO; + try + { + accessSDO = (AccessSDO)Enum.Parse(typeof(AccessSDO), comboBox_accessSDO.SelectedItem.ToString()); + } + catch (Exception) + { + accessSDO = AccessSDO.ro; + } + + AccessPDO accessPDO; + try + { + accessPDO = (AccessPDO)Enum.Parse(typeof(AccessPDO), comboBox_accessPDO.SelectedItem.ToString()); + } + catch (Exception) + { + accessPDO = AccessPDO.no; + } + + od.AccessSDO(accessSDO, accessPDO); + od.AccessPDO(accessPDO); } - else - { - try - { - od.accesstype = (EDSsharp.AccessType)Enum.Parse(typeof(EDSsharp.AccessType), comboBox_accessSDO.SelectedItem.ToString()); - } - catch (Exception) - { - od.accesstype = EDSsharp.AccessType.ro; - } - - try - { - od.PDOtype = (PDOMappingType)Enum.Parse(typeof(PDOMappingType), comboBox_accessPDO.SelectedItem.ToString()); - } - catch (Exception) - { - od.PDOtype = PDOMappingType.no; - } + else + { + try + { + od.accesstype = (EDSsharp.AccessType)Enum.Parse(typeof(EDSsharp.AccessType), comboBox_accessSDO.SelectedItem.ToString()); + } + catch (Exception) + { + od.accesstype = EDSsharp.AccessType.ro; + } + + try + { + od.PDOtype = (PDOMappingType)Enum.Parse(typeof(PDOMappingType), comboBox_accessPDO.SelectedItem.ToString()); + } + catch (Exception) + { + od.PDOtype = PDOMappingType.no; + } } // CO_accessSRDO try { - if(comboBox_accessSRDO.SelectedItem != null) + if(comboBox_accessSRDO.SelectedItem != null) od.prop.CO_accessSRDO = (AccessSRDO)Enum.Parse(typeof(AccessSRDO), comboBox_accessSRDO.SelectedItem.ToString()); } catch (Exception) @@ -590,9 +590,9 @@ private void ObjectSave() private void ListView_objects_MouseClick(object sender, MouseEventArgs e) { ListView listview = (ListView)sender; - - if (listview.SelectedItems.Count <= 0) - return; + + if (listview.SelectedItems.Count <= 0) + return; ODentry od = (ODentry)listview.SelectedItems[0].Tag; @@ -608,10 +608,10 @@ private void ListView_objects_MouseClick(object sender, MouseEventArgs e) PopulateObject(); PopulateSubList(); - } - else { + } + else { //selectedObject = lastSelectedObject; - //od = selectedObject; + //od = selectedObject; //selectedList.Select(); //string indesnew = "0x" + Convert.ToString(selectedObject.Index, 16); //ListViewItem itemnew = selectedList.FindItemWithText(indesnew); @@ -625,7 +625,7 @@ private void ListView_objects_MouseClick(object sender, MouseEventArgs e) } private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) - { + { ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.None, 0, 0, 0, 0)); } @@ -654,7 +654,7 @@ private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) contextMenu_subObject_removeSubItemToolStripMenuItem.Enabled = od.Subindex > 0 && od.parent != null; contextMenu_subObject_removeSubItemLeaveGapToolStripMenuItem.Enabled = parent.objecttype == ObjectType.RECORD && od.Subindex > 0 && od.parent != null; - if (isClickOnItem(e.Location)) + if (isClickOnItem(e.Location)) { contextMenu_subObject.Show(Cursor.Position); } @@ -663,24 +663,24 @@ private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) selectedObject = od; PopulateObject(); } - } - - private bool isClickOnItem(Point location) - { - if (listView_subObjects.FocusedItem != null) - { - return listView_subObjects.FocusedItem.Bounds.Contains(location); - } - - foreach (ListViewItem item in listView_subObjects.Items) - { - if (item.Bounds.Contains(location)) - { - return true; - } - } - - return false; + } + + private bool isClickOnItem(Point location) + { + if (listView_subObjects.FocusedItem != null) + { + return listView_subObjects.FocusedItem.Bounds.Contains(location); + } + + foreach (ListViewItem item in listView_subObjects.Items) + { + if (item.Bounds.Contains(location)) + { + return true; + } + } + + return false; } private void ListView_subObjects_SelectedIndexChanged(object sender, EventArgs e) @@ -731,23 +731,23 @@ private void ContextMenu_object_clone_ToolStripMenuItem_Click(object sender, Eve if (srcObjects.Count > 0) { - InsertObjects insObjForm = new InsertObjects(eds, network, srcObjects, "1"); + InsertObjects insObjForm = new InsertObjects(eds, network, srcObjects, "1"); if (insObjForm.ShowDialog() == DialogResult.OK) { selectedObject = null; - EDSsharp modifiedEds = insObjForm.GetModifiedEDS(); - modifiedEds.Dirty = true; - if(modifiedEds == this.eds) - { + EDSsharp modifiedEds = insObjForm.GetModifiedEDS(); + modifiedEds.Dirty = true; + if(modifiedEds == this.eds) + { PopulateObjectLists(eds); PopulateSubList(); PopulateObject(); - } - else - { - UpdateODViewForEDS?.Invoke(this, new UpdateODViewEventArgs(modifiedEds)); - } + } + else + { + UpdateODViewForEDS?.Invoke(this, new UpdateODViewEventArgs(modifiedEds)); + } } } } diff --git a/EDSEditorGUI/DevicePDOView2.Designer.cs b/EDSEditorGUI/DevicePDOView2.Designer.cs index ba03f81e..b94639a0 100644 --- a/EDSEditorGUI/DevicePDOView2.Designer.cs +++ b/EDSEditorGUI/DevicePDOView2.Designer.cs @@ -28,391 +28,391 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - this.button_addPDO = new System.Windows.Forms.Button(); - this.groupBox1 = new System.Windows.Forms.GroupBox(); - this.textBox_mapping = new System.Windows.Forms.TextBox(); - this.label1 = new System.Windows.Forms.Label(); - this.checkBox_invalidpdo = new System.Windows.Forms.CheckBox(); - this.textBox_slot = new System.Windows.Forms.TextBox(); - this.textBox_syncstart = new System.Windows.Forms.TextBox(); - this.textBox_eventtimer = new System.Windows.Forms.TextBox(); - this.textBox_inhibit = new System.Windows.Forms.TextBox(); - this.textBox_type = new System.Windows.Forms.TextBox(); - this.label7 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.label5 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.textBox_cob = new System.Windows.Forms.TextBox(); - this.label3 = new System.Windows.Forms.Label(); - this.label2 = new System.Windows.Forms.Label(); - this.button_savepdochanges = new System.Windows.Forms.Button(); - this.button_deletePDO = new System.Windows.Forms.Button(); - this.listView_TXPDO = new System.Windows.Forms.ListView(); - this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader15 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader16 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader17 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); - this.button_up = new System.Windows.Forms.Button(); - this.contextMenuStrip_removeitem = new System.Windows.Forms.ContextMenuStrip(this.components); - this.toolStripMenuItem_removeitem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripMenuItem_insert = new System.Windows.Forms.ToolStripMenuItem(); - this.grid1 = new SourceGrid.Grid(); - this.button_down = new System.Windows.Forms.Button(); - this.groupBox2 = new System.Windows.Forms.GroupBox(); - this.groupBox3 = new System.Windows.Forms.GroupBox(); - this.groupBox1.SuspendLayout(); - this.contextMenuStrip_removeitem.SuspendLayout(); - this.groupBox2.SuspendLayout(); - this.groupBox3.SuspendLayout(); - this.SuspendLayout(); - // - // button_addPDO - // - this.button_addPDO.Image = global::ODEditor.Properties.Resources.action_add_16xLG; - this.button_addPDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_addPDO.Location = new System.Drawing.Point(912, 101); - this.button_addPDO.Name = "button_addPDO"; - this.button_addPDO.Size = new System.Drawing.Size(101, 27); - this.button_addPDO.TabIndex = 9; - this.button_addPDO.Text = "Add new PDO"; - this.button_addPDO.UseVisualStyleBackColor = true; - this.button_addPDO.Click += new System.EventHandler(this.button_addPDO_Click); - // - // groupBox1 - // - this.groupBox1.Controls.Add(this.textBox_mapping); - this.groupBox1.Controls.Add(this.label1); - this.groupBox1.Controls.Add(this.checkBox_invalidpdo); - this.groupBox1.Controls.Add(this.textBox_slot); - this.groupBox1.Controls.Add(this.textBox_syncstart); - this.groupBox1.Controls.Add(this.textBox_eventtimer); - this.groupBox1.Controls.Add(this.textBox_inhibit); - this.groupBox1.Controls.Add(this.textBox_type); - this.groupBox1.Controls.Add(this.label7); - this.groupBox1.Controls.Add(this.label6); - this.groupBox1.Controls.Add(this.label5); - this.groupBox1.Controls.Add(this.label4); - this.groupBox1.Controls.Add(this.textBox_cob); - this.groupBox1.Controls.Add(this.label3); - this.groupBox1.Controls.Add(this.label2); - this.groupBox1.Location = new System.Drawing.Point(612, 7); - this.groupBox1.Name = "groupBox1"; - this.groupBox1.Size = new System.Drawing.Size(283, 206); - this.groupBox1.TabIndex = 16; - this.groupBox1.TabStop = false; - this.groupBox1.Text = "Communication parameters"; - // - // textBox_mapping - // - this.textBox_mapping.Location = new System.Drawing.Point(98, 47); - this.textBox_mapping.Name = "textBox_mapping"; - this.textBox_mapping.ReadOnly = true; - this.textBox_mapping.Size = new System.Drawing.Size(96, 20); - this.textBox_mapping.TabIndex = 2; - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(8, 50); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(48, 13); - this.label1.TabIndex = 10; - this.label1.Text = "Mapping"; - // - // checkBox_invalidpdo - // - this.checkBox_invalidpdo.AutoSize = true; - this.checkBox_invalidpdo.Location = new System.Drawing.Point(214, 183); - this.checkBox_invalidpdo.Name = "checkBox_invalidpdo"; - this.checkBox_invalidpdo.Size = new System.Drawing.Size(57, 17); - this.checkBox_invalidpdo.TabIndex = 8; - this.checkBox_invalidpdo.Text = "Invalid"; - this.checkBox_invalidpdo.UseVisualStyleBackColor = true; - this.checkBox_invalidpdo.CheckedChanged += new System.EventHandler(this.checkBox_invalidpdo_CheckedChanged); - // - // textBox_slot - // - this.textBox_slot.Location = new System.Drawing.Point(98, 20); - this.textBox_slot.Name = "textBox_slot"; - this.textBox_slot.Size = new System.Drawing.Size(96, 20); - this.textBox_slot.TabIndex = 1; - // - // textBox_syncstart - // - this.textBox_syncstart.Location = new System.Drawing.Point(98, 181); - this.textBox_syncstart.Name = "textBox_syncstart"; - this.textBox_syncstart.Size = new System.Drawing.Size(96, 20); - this.textBox_syncstart.TabIndex = 7; - // - // textBox_eventtimer - // - this.textBox_eventtimer.Location = new System.Drawing.Point(98, 154); - this.textBox_eventtimer.Name = "textBox_eventtimer"; - this.textBox_eventtimer.Size = new System.Drawing.Size(96, 20); - this.textBox_eventtimer.TabIndex = 6; - // - // textBox_inhibit - // - this.textBox_inhibit.Location = new System.Drawing.Point(98, 128); - this.textBox_inhibit.Name = "textBox_inhibit"; - this.textBox_inhibit.Size = new System.Drawing.Size(96, 20); - this.textBox_inhibit.TabIndex = 5; - // - // textBox_type - // - this.textBox_type.Location = new System.Drawing.Point(98, 101); - this.textBox_type.Name = "textBox_type"; - this.textBox_type.Size = new System.Drawing.Size(96, 20); - this.textBox_type.TabIndex = 4; - // - // label7 - // - this.label7.AutoSize = true; - this.label7.Location = new System.Drawing.Point(10, 184); - this.label7.Name = "label7"; - this.label7.Size = new System.Drawing.Size(54, 13); - this.label7.TabIndex = 6; - this.label7.Text = "Sync start"; - // - // label6 - // - this.label6.AutoSize = true; - this.label6.Location = new System.Drawing.Point(10, 131); - this.label6.Name = "label6"; - this.label6.Size = new System.Drawing.Size(35, 13); - this.label6.TabIndex = 5; - this.label6.Text = "Inhibit"; - // - // label5 - // - this.label5.AutoSize = true; - this.label5.Location = new System.Drawing.Point(10, 158); - this.label5.Name = "label5"; - this.label5.Size = new System.Drawing.Size(64, 13); - this.label5.TabIndex = 4; - this.label5.Text = "Event Timer"; - // - // label4 - // - this.label4.AutoSize = true; - this.label4.Location = new System.Drawing.Point(10, 104); - this.label4.Name = "label4"; - this.label4.Size = new System.Drawing.Size(31, 13); - this.label4.TabIndex = 3; - this.label4.Text = "Type"; - // - // textBox_cob - // - this.textBox_cob.Location = new System.Drawing.Point(98, 74); - this.textBox_cob.Name = "textBox_cob"; - this.textBox_cob.Size = new System.Drawing.Size(96, 20); - this.textBox_cob.TabIndex = 3; - // - // label3 - // - this.label3.AutoSize = true; - this.label3.Location = new System.Drawing.Point(10, 77); - this.label3.Name = "label3"; - this.label3.Size = new System.Drawing.Size(29, 13); - this.label3.TabIndex = 1; - this.label3.Text = "COB"; - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(8, 24); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(79, 13); - this.label2.TabIndex = 0; - this.label2.Text = "Communication"; - // - // button_savepdochanges - // - this.button_savepdochanges.Image = global::ODEditor.Properties.Resources.Save_6530; - this.button_savepdochanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_savepdochanges.Location = new System.Drawing.Point(912, 177); - this.button_savepdochanges.Name = "button_savepdochanges"; - this.button_savepdochanges.Size = new System.Drawing.Size(101, 27); - this.button_savepdochanges.TabIndex = 11; - this.button_savepdochanges.Text = "Save "; - this.button_savepdochanges.UseVisualStyleBackColor = true; - this.button_savepdochanges.Click += new System.EventHandler(this.button_savepdochanges_Click_1); - // - // button_deletePDO - // - this.button_deletePDO.Image = global::ODEditor.Properties.Resources.Remove_16xLG; - this.button_deletePDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; - this.button_deletePDO.Location = new System.Drawing.Point(912, 138); - this.button_deletePDO.Name = "button_deletePDO"; - this.button_deletePDO.Size = new System.Drawing.Size(101, 27); - this.button_deletePDO.TabIndex = 10; - this.button_deletePDO.Text = "Delete PDO"; - this.button_deletePDO.UseVisualStyleBackColor = true; - this.button_deletePDO.Click += new System.EventHandler(this.button_deletePDO_Click); - // - // listView_TXPDO - // - this.listView_TXPDO.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { - this.columnHeader13, - this.columnHeader15, - this.columnHeader16, - this.columnHeader17, - this.columnHeader1}); - this.listView_TXPDO.FullRowSelect = true; - this.listView_TXPDO.HideSelection = false; - this.listView_TXPDO.Location = new System.Drawing.Point(6, 19); - this.listView_TXPDO.MultiSelect = false; - this.listView_TXPDO.Name = "listView_TXPDO"; - this.listView_TXPDO.Size = new System.Drawing.Size(587, 182); - this.listView_TXPDO.TabIndex = 0; - this.listView_TXPDO.UseCompatibleStateImageBehavior = false; - this.listView_TXPDO.View = System.Windows.Forms.View.Details; - this.listView_TXPDO.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.listView_TXPDO_ItemDrag); - this.listView_TXPDO.SelectedIndexChanged += new System.EventHandler(this.listView_TXPDO_SelectedIndexChanged); - // - // columnHeader13 - // - this.columnHeader13.Text = "Index"; - this.columnHeader13.Width = 55; - // - // columnHeader15 - // - this.columnHeader15.Text = "Sub"; - this.columnHeader15.Width = 40; - // - // columnHeader16 - // - this.columnHeader16.Text = "Name"; - this.columnHeader16.Width = 206; - // - // columnHeader17 - // - this.columnHeader17.Text = "Datatype"; - this.columnHeader17.Width = 183; - // - // columnHeader1 - // - this.columnHeader1.Text = "Bits"; - // - // button_up - // - this.button_up.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.button_up.Location = new System.Drawing.Point(2, 409); - this.button_up.Margin = new System.Windows.Forms.Padding(2); - this.button_up.Name = "button_up"; - this.button_up.Size = new System.Drawing.Size(85, 30); - this.button_up.TabIndex = 13; - this.button_up.Text = "Zoom In"; - this.button_up.UseVisualStyleBackColor = true; - this.button_up.Click += new System.EventHandler(this.button_up_Click); - // - // contextMenuStrip_removeitem - // - this.contextMenuStrip_removeitem.ImageScalingSize = new System.Drawing.Size(20, 20); - this.contextMenuStrip_removeitem.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.toolStripMenuItem_removeitem, - this.toolStripMenuItem_insert}); - this.contextMenuStrip_removeitem.Name = "contextMenuStrip_removeitem"; - this.contextMenuStrip_removeitem.Size = new System.Drawing.Size(145, 48); - this.contextMenuStrip_removeitem.Text = "Remove Item"; - // - // toolStripMenuItem_removeitem - // - this.toolStripMenuItem_removeitem.Name = "toolStripMenuItem_removeitem"; - this.toolStripMenuItem_removeitem.Size = new System.Drawing.Size(144, 22); - this.toolStripMenuItem_removeitem.Tag = "remove"; - this.toolStripMenuItem_removeitem.Text = "Remove Item"; - // - // toolStripMenuItem_insert - // - this.toolStripMenuItem_insert.Name = "toolStripMenuItem_insert"; - this.toolStripMenuItem_insert.Size = new System.Drawing.Size(144, 22); - this.toolStripMenuItem_insert.Tag = "insert"; - this.toolStripMenuItem_insert.Text = "Insert Item"; - // - // grid1 - // - this.grid1.AllowDrop = true; - this.grid1.AutoSize = true; - this.grid1.DefaultWidth = 18; - this.grid1.Dock = System.Windows.Forms.DockStyle.Fill; - this.grid1.EnableSort = false; - this.grid1.Location = new System.Drawing.Point(3, 16); - this.grid1.Margin = new System.Windows.Forms.Padding(2); - this.grid1.Name = "grid1"; - this.grid1.OptimizeMode = SourceGrid.CellOptimizeMode.ForRows; - this.grid1.SelectionMode = SourceGrid.GridSelectionMode.Cell; - this.grid1.Size = new System.Drawing.Size(1004, 166); - this.grid1.TabIndex = 12; - this.grid1.TabStop = true; - this.grid1.ToolTipText = ""; - this.grid1.DragDrop += new System.Windows.Forms.DragEventHandler(this.grid1_DragDrop); - this.grid1.DragEnter += new System.Windows.Forms.DragEventHandler(this.grid1_DragEnter); - this.grid1.DragOver += new System.Windows.Forms.DragEventHandler(this.grid1_DragOver); - // - // button_down - // - this.button_down.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.button_down.Location = new System.Drawing.Point(91, 409); - this.button_down.Margin = new System.Windows.Forms.Padding(2); - this.button_down.Name = "button_down"; - this.button_down.Size = new System.Drawing.Size(102, 31); - this.button_down.TabIndex = 14; - this.button_down.Text = "Zoom Out"; - this.button_down.UseVisualStyleBackColor = true; - this.button_down.Click += new System.EventHandler(this.button_down_Click); - // - // groupBox2 - // - this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.groupBox2.AutoSize = true; - this.groupBox2.Controls.Add(this.grid1); - this.groupBox2.Location = new System.Drawing.Point(5, 219); - this.groupBox2.Name = "groupBox2"; - this.groupBox2.Size = new System.Drawing.Size(1010, 185); - this.groupBox2.TabIndex = 17; - this.groupBox2.TabStop = false; - // - // groupBox3 - // - this.groupBox3.Controls.Add(this.listView_TXPDO); - this.groupBox3.Location = new System.Drawing.Point(5, 7); - this.groupBox3.Name = "groupBox3"; - this.groupBox3.Size = new System.Drawing.Size(593, 205); - this.groupBox3.TabIndex = 15; - this.groupBox3.TabStop = false; - this.groupBox3.Text = "Available Objects for PDO"; - // - // DevicePDOView2 - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.AutoScroll = true; - this.AutoSize = true; - this.Controls.Add(this.groupBox3); - this.Controls.Add(this.groupBox1); - this.Controls.Add(this.button_addPDO); - this.Controls.Add(this.button_savepdochanges); - this.Controls.Add(this.button_deletePDO); - this.Controls.Add(this.groupBox2); - this.Controls.Add(this.button_up); - this.Controls.Add(this.button_down); - this.Margin = new System.Windows.Forms.Padding(2); - this.Name = "DevicePDOView2"; - this.Size = new System.Drawing.Size(1021, 441); - this.groupBox1.ResumeLayout(false); - this.groupBox1.PerformLayout(); - this.contextMenuStrip_removeitem.ResumeLayout(false); - this.groupBox2.ResumeLayout(false); - this.groupBox2.PerformLayout(); - this.groupBox3.ResumeLayout(false); - this.ResumeLayout(false); - this.PerformLayout(); - + this.components = new System.ComponentModel.Container(); + this.button_addPDO = new System.Windows.Forms.Button(); + this.groupBox1 = new System.Windows.Forms.GroupBox(); + this.textBox_mapping = new System.Windows.Forms.TextBox(); + this.label1 = new System.Windows.Forms.Label(); + this.checkBox_invalidpdo = new System.Windows.Forms.CheckBox(); + this.textBox_slot = new System.Windows.Forms.TextBox(); + this.textBox_syncstart = new System.Windows.Forms.TextBox(); + this.textBox_eventtimer = new System.Windows.Forms.TextBox(); + this.textBox_inhibit = new System.Windows.Forms.TextBox(); + this.textBox_type = new System.Windows.Forms.TextBox(); + this.label7 = new System.Windows.Forms.Label(); + this.label6 = new System.Windows.Forms.Label(); + this.label5 = new System.Windows.Forms.Label(); + this.label4 = new System.Windows.Forms.Label(); + this.textBox_cob = new System.Windows.Forms.TextBox(); + this.label3 = new System.Windows.Forms.Label(); + this.label2 = new System.Windows.Forms.Label(); + this.button_savepdochanges = new System.Windows.Forms.Button(); + this.button_deletePDO = new System.Windows.Forms.Button(); + this.listView_TXPDO = new System.Windows.Forms.ListView(); + this.columnHeader13 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader15 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader16 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader17 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.columnHeader1 = ((System.Windows.Forms.ColumnHeader)(new System.Windows.Forms.ColumnHeader())); + this.button_up = new System.Windows.Forms.Button(); + this.contextMenuStrip_removeitem = new System.Windows.Forms.ContextMenuStrip(this.components); + this.toolStripMenuItem_removeitem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem_insert = new System.Windows.Forms.ToolStripMenuItem(); + this.grid1 = new SourceGrid.Grid(); + this.button_down = new System.Windows.Forms.Button(); + this.groupBox2 = new System.Windows.Forms.GroupBox(); + this.groupBox3 = new System.Windows.Forms.GroupBox(); + this.groupBox1.SuspendLayout(); + this.contextMenuStrip_removeitem.SuspendLayout(); + this.groupBox2.SuspendLayout(); + this.groupBox3.SuspendLayout(); + this.SuspendLayout(); + // + // button_addPDO + // + this.button_addPDO.Image = global::ODEditor.Properties.Resources.action_add_16xLG; + this.button_addPDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_addPDO.Location = new System.Drawing.Point(912, 101); + this.button_addPDO.Name = "button_addPDO"; + this.button_addPDO.Size = new System.Drawing.Size(101, 27); + this.button_addPDO.TabIndex = 9; + this.button_addPDO.Text = "Add new PDO"; + this.button_addPDO.UseVisualStyleBackColor = true; + this.button_addPDO.Click += new System.EventHandler(this.button_addPDO_Click); + // + // groupBox1 + // + this.groupBox1.Controls.Add(this.textBox_mapping); + this.groupBox1.Controls.Add(this.label1); + this.groupBox1.Controls.Add(this.checkBox_invalidpdo); + this.groupBox1.Controls.Add(this.textBox_slot); + this.groupBox1.Controls.Add(this.textBox_syncstart); + this.groupBox1.Controls.Add(this.textBox_eventtimer); + this.groupBox1.Controls.Add(this.textBox_inhibit); + this.groupBox1.Controls.Add(this.textBox_type); + this.groupBox1.Controls.Add(this.label7); + this.groupBox1.Controls.Add(this.label6); + this.groupBox1.Controls.Add(this.label5); + this.groupBox1.Controls.Add(this.label4); + this.groupBox1.Controls.Add(this.textBox_cob); + this.groupBox1.Controls.Add(this.label3); + this.groupBox1.Controls.Add(this.label2); + this.groupBox1.Location = new System.Drawing.Point(612, 7); + this.groupBox1.Name = "groupBox1"; + this.groupBox1.Size = new System.Drawing.Size(283, 206); + this.groupBox1.TabIndex = 16; + this.groupBox1.TabStop = false; + this.groupBox1.Text = "Communication parameters"; + // + // textBox_mapping + // + this.textBox_mapping.Location = new System.Drawing.Point(98, 47); + this.textBox_mapping.Name = "textBox_mapping"; + this.textBox_mapping.ReadOnly = true; + this.textBox_mapping.Size = new System.Drawing.Size(96, 20); + this.textBox_mapping.TabIndex = 2; + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(8, 50); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(48, 13); + this.label1.TabIndex = 10; + this.label1.Text = "Mapping"; + // + // checkBox_invalidpdo + // + this.checkBox_invalidpdo.AutoSize = true; + this.checkBox_invalidpdo.Location = new System.Drawing.Point(214, 183); + this.checkBox_invalidpdo.Name = "checkBox_invalidpdo"; + this.checkBox_invalidpdo.Size = new System.Drawing.Size(57, 17); + this.checkBox_invalidpdo.TabIndex = 8; + this.checkBox_invalidpdo.Text = "Invalid"; + this.checkBox_invalidpdo.UseVisualStyleBackColor = true; + this.checkBox_invalidpdo.CheckedChanged += new System.EventHandler(this.checkBox_invalidpdo_CheckedChanged); + // + // textBox_slot + // + this.textBox_slot.Location = new System.Drawing.Point(98, 20); + this.textBox_slot.Name = "textBox_slot"; + this.textBox_slot.Size = new System.Drawing.Size(96, 20); + this.textBox_slot.TabIndex = 1; + // + // textBox_syncstart + // + this.textBox_syncstart.Location = new System.Drawing.Point(98, 181); + this.textBox_syncstart.Name = "textBox_syncstart"; + this.textBox_syncstart.Size = new System.Drawing.Size(96, 20); + this.textBox_syncstart.TabIndex = 7; + // + // textBox_eventtimer + // + this.textBox_eventtimer.Location = new System.Drawing.Point(98, 154); + this.textBox_eventtimer.Name = "textBox_eventtimer"; + this.textBox_eventtimer.Size = new System.Drawing.Size(96, 20); + this.textBox_eventtimer.TabIndex = 6; + // + // textBox_inhibit + // + this.textBox_inhibit.Location = new System.Drawing.Point(98, 128); + this.textBox_inhibit.Name = "textBox_inhibit"; + this.textBox_inhibit.Size = new System.Drawing.Size(96, 20); + this.textBox_inhibit.TabIndex = 5; + // + // textBox_type + // + this.textBox_type.Location = new System.Drawing.Point(98, 101); + this.textBox_type.Name = "textBox_type"; + this.textBox_type.Size = new System.Drawing.Size(96, 20); + this.textBox_type.TabIndex = 4; + // + // label7 + // + this.label7.AutoSize = true; + this.label7.Location = new System.Drawing.Point(10, 184); + this.label7.Name = "label7"; + this.label7.Size = new System.Drawing.Size(54, 13); + this.label7.TabIndex = 6; + this.label7.Text = "Sync start"; + // + // label6 + // + this.label6.AutoSize = true; + this.label6.Location = new System.Drawing.Point(10, 131); + this.label6.Name = "label6"; + this.label6.Size = new System.Drawing.Size(35, 13); + this.label6.TabIndex = 5; + this.label6.Text = "Inhibit"; + // + // label5 + // + this.label5.AutoSize = true; + this.label5.Location = new System.Drawing.Point(10, 158); + this.label5.Name = "label5"; + this.label5.Size = new System.Drawing.Size(64, 13); + this.label5.TabIndex = 4; + this.label5.Text = "Event Timer"; + // + // label4 + // + this.label4.AutoSize = true; + this.label4.Location = new System.Drawing.Point(10, 104); + this.label4.Name = "label4"; + this.label4.Size = new System.Drawing.Size(31, 13); + this.label4.TabIndex = 3; + this.label4.Text = "Type"; + // + // textBox_cob + // + this.textBox_cob.Location = new System.Drawing.Point(98, 74); + this.textBox_cob.Name = "textBox_cob"; + this.textBox_cob.Size = new System.Drawing.Size(96, 20); + this.textBox_cob.TabIndex = 3; + // + // label3 + // + this.label3.AutoSize = true; + this.label3.Location = new System.Drawing.Point(10, 77); + this.label3.Name = "label3"; + this.label3.Size = new System.Drawing.Size(29, 13); + this.label3.TabIndex = 1; + this.label3.Text = "COB"; + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(8, 24); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(79, 13); + this.label2.TabIndex = 0; + this.label2.Text = "Communication"; + // + // button_savepdochanges + // + this.button_savepdochanges.Image = global::ODEditor.Properties.Resources.Save_6530; + this.button_savepdochanges.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_savepdochanges.Location = new System.Drawing.Point(912, 177); + this.button_savepdochanges.Name = "button_savepdochanges"; + this.button_savepdochanges.Size = new System.Drawing.Size(101, 27); + this.button_savepdochanges.TabIndex = 11; + this.button_savepdochanges.Text = "Save "; + this.button_savepdochanges.UseVisualStyleBackColor = true; + this.button_savepdochanges.Click += new System.EventHandler(this.button_savepdochanges_Click_1); + // + // button_deletePDO + // + this.button_deletePDO.Image = global::ODEditor.Properties.Resources.Remove_16xLG; + this.button_deletePDO.ImageAlign = System.Drawing.ContentAlignment.MiddleRight; + this.button_deletePDO.Location = new System.Drawing.Point(912, 138); + this.button_deletePDO.Name = "button_deletePDO"; + this.button_deletePDO.Size = new System.Drawing.Size(101, 27); + this.button_deletePDO.TabIndex = 10; + this.button_deletePDO.Text = "Delete PDO"; + this.button_deletePDO.UseVisualStyleBackColor = true; + this.button_deletePDO.Click += new System.EventHandler(this.button_deletePDO_Click); + // + // listView_TXPDO + // + this.listView_TXPDO.Columns.AddRange(new System.Windows.Forms.ColumnHeader[] { + this.columnHeader13, + this.columnHeader15, + this.columnHeader16, + this.columnHeader17, + this.columnHeader1}); + this.listView_TXPDO.FullRowSelect = true; + this.listView_TXPDO.HideSelection = false; + this.listView_TXPDO.Location = new System.Drawing.Point(6, 19); + this.listView_TXPDO.MultiSelect = false; + this.listView_TXPDO.Name = "listView_TXPDO"; + this.listView_TXPDO.Size = new System.Drawing.Size(587, 182); + this.listView_TXPDO.TabIndex = 0; + this.listView_TXPDO.UseCompatibleStateImageBehavior = false; + this.listView_TXPDO.View = System.Windows.Forms.View.Details; + this.listView_TXPDO.ItemDrag += new System.Windows.Forms.ItemDragEventHandler(this.listView_TXPDO_ItemDrag); + this.listView_TXPDO.SelectedIndexChanged += new System.EventHandler(this.listView_TXPDO_SelectedIndexChanged); + // + // columnHeader13 + // + this.columnHeader13.Text = "Index"; + this.columnHeader13.Width = 55; + // + // columnHeader15 + // + this.columnHeader15.Text = "Sub"; + this.columnHeader15.Width = 40; + // + // columnHeader16 + // + this.columnHeader16.Text = "Name"; + this.columnHeader16.Width = 206; + // + // columnHeader17 + // + this.columnHeader17.Text = "Datatype"; + this.columnHeader17.Width = 183; + // + // columnHeader1 + // + this.columnHeader1.Text = "Bits"; + // + // button_up + // + this.button_up.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.button_up.Location = new System.Drawing.Point(2, 409); + this.button_up.Margin = new System.Windows.Forms.Padding(2); + this.button_up.Name = "button_up"; + this.button_up.Size = new System.Drawing.Size(85, 30); + this.button_up.TabIndex = 13; + this.button_up.Text = "Zoom In"; + this.button_up.UseVisualStyleBackColor = true; + this.button_up.Click += new System.EventHandler(this.button_up_Click); + // + // contextMenuStrip_removeitem + // + this.contextMenuStrip_removeitem.ImageScalingSize = new System.Drawing.Size(20, 20); + this.contextMenuStrip_removeitem.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.toolStripMenuItem_removeitem, + this.toolStripMenuItem_insert}); + this.contextMenuStrip_removeitem.Name = "contextMenuStrip_removeitem"; + this.contextMenuStrip_removeitem.Size = new System.Drawing.Size(145, 48); + this.contextMenuStrip_removeitem.Text = "Remove Item"; + // + // toolStripMenuItem_removeitem + // + this.toolStripMenuItem_removeitem.Name = "toolStripMenuItem_removeitem"; + this.toolStripMenuItem_removeitem.Size = new System.Drawing.Size(144, 22); + this.toolStripMenuItem_removeitem.Tag = "remove"; + this.toolStripMenuItem_removeitem.Text = "Remove Item"; + // + // toolStripMenuItem_insert + // + this.toolStripMenuItem_insert.Name = "toolStripMenuItem_insert"; + this.toolStripMenuItem_insert.Size = new System.Drawing.Size(144, 22); + this.toolStripMenuItem_insert.Tag = "insert"; + this.toolStripMenuItem_insert.Text = "Insert Item"; + // + // grid1 + // + this.grid1.AllowDrop = true; + this.grid1.AutoSize = true; + this.grid1.DefaultWidth = 18; + this.grid1.Dock = System.Windows.Forms.DockStyle.Fill; + this.grid1.EnableSort = false; + this.grid1.Location = new System.Drawing.Point(3, 16); + this.grid1.Margin = new System.Windows.Forms.Padding(2); + this.grid1.Name = "grid1"; + this.grid1.OptimizeMode = SourceGrid.CellOptimizeMode.ForRows; + this.grid1.SelectionMode = SourceGrid.GridSelectionMode.Cell; + this.grid1.Size = new System.Drawing.Size(1004, 166); + this.grid1.TabIndex = 12; + this.grid1.TabStop = true; + this.grid1.ToolTipText = ""; + this.grid1.DragDrop += new System.Windows.Forms.DragEventHandler(this.grid1_DragDrop); + this.grid1.DragEnter += new System.Windows.Forms.DragEventHandler(this.grid1_DragEnter); + this.grid1.DragOver += new System.Windows.Forms.DragEventHandler(this.grid1_DragOver); + // + // button_down + // + this.button_down.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.button_down.Location = new System.Drawing.Point(91, 409); + this.button_down.Margin = new System.Windows.Forms.Padding(2); + this.button_down.Name = "button_down"; + this.button_down.Size = new System.Drawing.Size(102, 31); + this.button_down.TabIndex = 14; + this.button_down.Text = "Zoom Out"; + this.button_down.UseVisualStyleBackColor = true; + this.button_down.Click += new System.EventHandler(this.button_down_Click); + // + // groupBox2 + // + this.groupBox2.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.groupBox2.AutoSize = true; + this.groupBox2.Controls.Add(this.grid1); + this.groupBox2.Location = new System.Drawing.Point(5, 219); + this.groupBox2.Name = "groupBox2"; + this.groupBox2.Size = new System.Drawing.Size(1010, 185); + this.groupBox2.TabIndex = 17; + this.groupBox2.TabStop = false; + // + // groupBox3 + // + this.groupBox3.Controls.Add(this.listView_TXPDO); + this.groupBox3.Location = new System.Drawing.Point(5, 7); + this.groupBox3.Name = "groupBox3"; + this.groupBox3.Size = new System.Drawing.Size(593, 205); + this.groupBox3.TabIndex = 15; + this.groupBox3.TabStop = false; + this.groupBox3.Text = "Available Objects for PDO"; + // + // DevicePDOView2 + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.AutoScroll = true; + this.AutoSize = true; + this.Controls.Add(this.groupBox3); + this.Controls.Add(this.groupBox1); + this.Controls.Add(this.button_addPDO); + this.Controls.Add(this.button_savepdochanges); + this.Controls.Add(this.button_deletePDO); + this.Controls.Add(this.groupBox2); + this.Controls.Add(this.button_up); + this.Controls.Add(this.button_down); + this.Margin = new System.Windows.Forms.Padding(2); + this.Name = "DevicePDOView2"; + this.Size = new System.Drawing.Size(1021, 441); + this.groupBox1.ResumeLayout(false); + this.groupBox1.PerformLayout(); + this.contextMenuStrip_removeitem.ResumeLayout(false); + this.groupBox2.ResumeLayout(false); + this.groupBox2.PerformLayout(); + this.groupBox3.ResumeLayout(false); + this.ResumeLayout(false); + this.PerformLayout(); + } #endregion @@ -444,10 +444,10 @@ private void InitializeComponent() private System.Windows.Forms.TextBox textBox_mapping; private System.Windows.Forms.Label label1; private System.Windows.Forms.Button button_savepdochanges; - private System.Windows.Forms.ColumnHeader columnHeader1; - private SourceGrid.Grid grid1; - private System.Windows.Forms.Button button_down; - private System.Windows.Forms.GroupBox groupBox2; - private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.ColumnHeader columnHeader1; + private SourceGrid.Grid grid1; + private System.Windows.Forms.Button button_down; + private System.Windows.Forms.GroupBox groupBox2; + private System.Windows.Forms.GroupBox groupBox3; } } diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index ed6b2842..71934fce 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -22,9 +22,9 @@ public partial class DevicePDOView2 : MyTabUserControl StringCollection TXchoices = new StringCollection(); string[] srray; - PDOSlot selectedslot = null; - - CellBackColorAlternate viewNormal = new CellBackColorAlternate(Color.Khaki, Color.DarkKhaki); + PDOSlot selectedslot = null; + + CellBackColorAlternate viewNormal = new CellBackColorAlternate(Color.Khaki, Color.DarkKhaki); CellBackColorAlternate viewEmpty = new CellBackColorAlternate(Color.Gray, Color.Gray); CellBackColorAlternate viewCOB = new CellBackColorAlternate(Color.LightBlue, Color.Blue); @@ -66,8 +66,8 @@ public DevicePDOView2() } - grid1.Rows[0].Height = 30; - + grid1.Rows[0].Height = 30; + contextMenuStrip_removeitem.ItemClicked += ContextMenuStrip_removeitem_ItemClicked; Invalidated += DevicePDOView2_Invalidated; @@ -97,13 +97,13 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte switch (e.ClickedItem.Tag) { - case "remove": - location.slot.Mapping.Remove(location.entry); - + case "remove": + location.slot.Mapping.Remove(location.entry); + break; - case "insert": - ODentry od = new ODentry(); + case "insert": + ODentry od = new ODentry(); location.slot.Mapping.Insert(location.ordinal, eds.dummy_ods[0x002]); break; @@ -118,9 +118,9 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte private void Vcc_ValueChangedEvent(object sender, EventArgs e) { - SourceGrid.CellContext cell = (SourceGrid.CellContext)sender; - - // "0x3100/05/BUTTONS2" + SourceGrid.CellContext cell = (SourceGrid.CellContext)sender; + + // "0x3100/05/BUTTONS2" string[] bits = cell.Value.ToString().Split('/'); UInt16 newindex = EDSsharp.ConvertToUInt16(bits[0]); @@ -133,12 +133,12 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) PDOlocator location = (PDOlocator)((SourceGrid.Cells.Cell)cell.Cell).Tag; PDOSlot slot = location.slot; - ODentry newentry = null; - + ODentry newentry = null; + if (eds.tryGetODEntry(newindex, out newentry)) { if (newsubindex != 0) - newentry = newentry.subobjects[newsubindex]; + newentry = newentry.subobjects[newsubindex]; } else { @@ -179,9 +179,9 @@ SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P, out int foundrow, out int x2 = 0; foundcol = 0; int outofview = 0; - for (int i = 0; i < grid1.HScrollBar.Value; i++) - { - outofview += grid1.Columns.GetWidth(i); + for (int i = 0; i < grid1.HScrollBar.Value; i++) + { + outofview += grid1.Columns.GetWidth(i); } x2 = -outofview; @@ -194,8 +194,8 @@ SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P, out int foundrow, out foundcol = col.Index; } x2 += col.Width; - } - + } + Console.WriteLine(string.Format("Found grid at {0}x{1}", foundcol, foundrow)); SourceGrid.Cells.ICellVirtual v = grid1.GetCell(foundrow, foundcol); @@ -212,19 +212,19 @@ private void Grid1_Click(object sender, EventArgs e) int foundrow, foundcol; SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(ma.Location, out foundrow, out foundcol); - - //// DEBUG code: Create ToolTip with col, row and hscroll.value - //ToolTip toolTip1 = new ToolTip(); - //if (ma.Button == MouseButtons.Left) - //{ - // Point loc = new Point(0, 0); - // loc.X = foundcol; - // loc.Y = foundrow; - // // Force the ToolTip text to be displayed whether or not the form is active. - // toolTip1.ShowAlways = true; - // toolTip1.Show(loc.ToString() + ", " + grid1.HScrollBar.Value.ToString(), grid1, ma.Location); - //} - + + //// DEBUG code: Create ToolTip with col, row and hscroll.value + //ToolTip toolTip1 = new ToolTip(); + //if (ma.Button == MouseButtons.Left) + //{ + // Point loc = new Point(0, 0); + // loc.X = foundcol; + // loc.Y = foundrow; + // // Force the ToolTip text to be displayed whether or not the form is active. + // toolTip1.ShowAlways = true; + // toolTip1.Show(loc.ToString() + ", " + grid1.HScrollBar.Value.ToString(), grid1, ma.Location); + //} + grid1.Selection.ResetSelection(false); grid1.Selection.SelectRow(foundrow, true); @@ -249,7 +249,7 @@ private void Grid1_Click(object sender, EventArgs e) { textBox_inhibit.Enabled = true; textBox_syncstart.Enabled = true; - } + } textBox_eventtimer.Enabled = true; textBox_type.Enabled = true; textBox_cob.Enabled = true; @@ -258,10 +258,10 @@ private void Grid1_Click(object sender, EventArgs e) button_savepdochanges.Enabled = true; //Is invalid bit set - checkBox_invalidpdo.Checked = slot.invalid; - - - + checkBox_invalidpdo.Checked = slot.invalid; + + + } } @@ -280,9 +280,9 @@ public void Init(bool isTX) } } - public libEDSsharp.EDSsharp eds; - - + public libEDSsharp.EDSsharp eds; + + public void addPDOchoices() { @@ -363,11 +363,11 @@ public void UpdatePDOinfo(bool updatechoices = true) { int savVScrollValue = 0; - if (!updatechoices) - savVScrollValue = grid1.VScrollBar.Value; - - button_savepdochanges.Enabled = (textBox_slot.Text != ""); - + if (!updatechoices) + savVScrollValue = grid1.VScrollBar.Value; + + button_savepdochanges.Enabled = (textBox_slot.Text != ""); + updateslotdisplay(); if (eds == null) @@ -377,9 +377,9 @@ public void UpdatePDOinfo(bool updatechoices = true) addPDOchoices(); if (grid1.RowsCount > 2) - grid1.Rows.RemoveRange(2, grid1.RowsCount - 2); - - + grid1.Rows.RemoveRange(2, grid1.RowsCount - 2); + + TXchoices.Clear(); foreach (ODentry od in eds.dummy_ods.Values) @@ -458,7 +458,7 @@ public void UpdatePDOinfo(bool updatechoices = true) int ordinal = 0; foreach (ODentry entry in slot.Mapping) { - { + { string target = slot.getTargetName(entry); grid1[row + 2, bitoff + 3] = new SourceGrid.Cells.Cell(target, comboStandard); grid1[row + 2, bitoff + 3].ColumnSpan = entry.Sizeofdatatype(); @@ -478,12 +478,12 @@ public void UpdatePDOinfo(bool updatechoices = true) grid1[row + 2, bitoff + 3].AddController(vcc); bitoff += entry.Sizeofdatatype(); - } - + } + ordinal++; - if (bitoff > 64) { - MessageBox.Show(string.Format("Invalid TXPDO mapping parameters in 0x{0:X}. Trying to map more than 64 bit (8 Bytes). CAN message maximum lenght is 8 Byte", slot.ConfigurationIndex)); + if (bitoff > 64) { + MessageBox.Show(string.Format("Invalid TXPDO mapping parameters in 0x{0:X}. Trying to map more than 64 bit (8 Bytes). CAN message maximum lenght is 8 Byte", slot.ConfigurationIndex)); break; } @@ -513,9 +513,9 @@ public void UpdatePDOinfo(bool updatechoices = true) } row++; - } - - if (!updatechoices) + } + + if (!updatechoices) grid1.VScrollBar.Value = savVScrollValue; } @@ -526,8 +526,8 @@ private void ComboStandard_Changed(object sender, EventArgs e) } public void redrawtable() - { - + { + } private class MyHeader : SourceGrid.Cells.ColumnHeader @@ -637,9 +637,9 @@ protected override void PrepareView(SourceGrid.CellContext context) } private void listView_TXPDO_ItemDrag(object sender, ItemDragEventArgs e) - { - - + { + + List entries = new List(); foreach (ListViewItem item in listView_TXPDO.SelectedItems) @@ -652,10 +652,10 @@ private void listView_TXPDO_ItemDrag(object sender, ItemDragEventArgs e) data.SetData(entries.ToArray()); listView_TXPDO.DoDragDrop(data, DragDropEffects.Copy); - } - - - + } + + + private void grid1_DragOver(object sender, DragEventArgs e) { Point p = grid1.PointToClient(new Point(e.X, e.Y)); @@ -692,7 +692,7 @@ private void grid1_DragDrop(object sender, DragEventArgs e) foreach (ODentry entry in entries) { - location.slot.insertMapping(location.ordinal, entry); + location.slot.insertMapping(location.ordinal, entry); } helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); @@ -716,8 +716,8 @@ public override void OnValueChanged(CellContext sender, EventArgs e) handler?.Invoke(sender, e); base.OnValueChanged(sender, e); - } - + } + } private void button_deletePDO_Click(object sender, EventArgs e) @@ -817,12 +817,12 @@ private void button_savepdochanges_Click_1(object sender, EventArgs e) doUpdateOD(); UpdatePDOinfo(); - } - - private void listView_TXPDO_SelectedIndexChanged(object sender, EventArgs e) - { - } - } + + private void listView_TXPDO_SelectedIndexChanged(object sender, EventArgs e) + { + + } + } } \ No newline at end of file diff --git a/EDSEditorGUI/DeviceView.Designer.cs b/EDSEditorGUI/DeviceView.Designer.cs index 946aa401..80cde950 100644 --- a/EDSEditorGUI/DeviceView.Designer.cs +++ b/EDSEditorGUI/DeviceView.Designer.cs @@ -1,195 +1,195 @@ -namespace ODEditor -{ - partial class DeviceView - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Component Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeviceView)); - this.imageList1 = new System.Windows.Forms.ImageList(this.components); - this.tabPage4 = new System.Windows.Forms.TabPage(); - this.devicePDOView2 = new ODEditor.DevicePDOView2(); - this.tabPage3 = new System.Windows.Forms.TabPage(); - this.devicePDOView1 = new ODEditor.DevicePDOView2(); - this.tabPage2 = new System.Windows.Forms.TabPage(); - this.deviceODView1 = new ODEditor.DeviceODView(); - this.tabPage1 = new System.Windows.Forms.TabPage(); - this.deviceInfoView = new ODEditor.DeviceInfoView(); - this.tabControl1 = new System.Windows.Forms.TabControl(); - this.tabPage4.SuspendLayout(); - this.tabPage3.SuspendLayout(); - this.tabPage2.SuspendLayout(); - this.tabPage1.SuspendLayout(); - this.tabControl1.SuspendLayout(); - this.SuspendLayout(); - // - // imageList1 - // - this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream"))); - this.imageList1.TransparentColor = System.Drawing.Color.Transparent; - this.imageList1.Images.SetKeyName(0, "ListBox_686.png"); - this.imageList1.Images.SetKeyName(1, "notebook_16xLG.png"); - this.imageList1.Images.SetKeyName(2, "Output_16xLG.png"); - this.imageList1.Images.SetKeyName(3, "SingleInput_8170_16x.png"); - // - // tabPage4 - // - this.tabPage4.Controls.Add(this.devicePDOView2); - this.tabPage4.ImageIndex = 3; - this.tabPage4.Location = new System.Drawing.Point(4, 25); - this.tabPage4.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage4.Name = "tabPage4"; - this.tabPage4.Size = new System.Drawing.Size(1114, 746); - this.tabPage4.TabIndex = 3; - this.tabPage4.Text = "RX PDO Mapping"; - this.tabPage4.UseVisualStyleBackColor = true; - // - // devicePDOView2 - // - this.devicePDOView2.AutoScroll = true; - this.devicePDOView2.AutoSize = true; - this.devicePDOView2.Dock = System.Windows.Forms.DockStyle.Fill; - this.devicePDOView2.Location = new System.Drawing.Point(0, 0); - this.devicePDOView2.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); - this.devicePDOView2.Name = "devicePDOView2"; - this.devicePDOView2.Size = new System.Drawing.Size(1114, 746); - this.devicePDOView2.TabIndex = 0; - // - // tabPage3 - // - this.tabPage3.Controls.Add(this.devicePDOView1); - this.tabPage3.ImageIndex = 2; - this.tabPage3.Location = new System.Drawing.Point(4, 25); - this.tabPage3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage3.Name = "tabPage3"; - this.tabPage3.Size = new System.Drawing.Size(1030, 746); - this.tabPage3.TabIndex = 2; - this.tabPage3.Text = "TX PDO Mapping"; - this.tabPage3.UseVisualStyleBackColor = true; - // - // devicePDOView1 - // - this.devicePDOView1.AutoScroll = true; - this.devicePDOView1.AutoSize = true; - this.devicePDOView1.Dock = System.Windows.Forms.DockStyle.Fill; - this.devicePDOView1.Location = new System.Drawing.Point(0, 0); - this.devicePDOView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); - this.devicePDOView1.Name = "devicePDOView1"; - this.devicePDOView1.Size = new System.Drawing.Size(1030, 746); - this.devicePDOView1.TabIndex = 0; - // - // tabPage2 - // - this.tabPage2.Controls.Add(this.deviceODView1); - this.tabPage2.ImageIndex = 0; - this.tabPage2.Location = new System.Drawing.Point(4, 25); - this.tabPage2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage2.Name = "tabPage2"; - this.tabPage2.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage2.Size = new System.Drawing.Size(1114, 746); - this.tabPage2.TabIndex = 0; - this.tabPage2.Text = "Object Dictionary"; - this.tabPage2.UseVisualStyleBackColor = true; - // - // deviceODView1 - // - this.deviceODView1.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceODView1.Location = new System.Drawing.Point(4, 4); - this.deviceODView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); - this.deviceODView1.Name = "deviceODView1"; - this.deviceODView1.Size = new System.Drawing.Size(1108, 740); - this.deviceODView1.TabIndex = 0; - // - // tabPage1 - // - this.tabPage1.Controls.Add(this.deviceInfoView); - this.tabPage1.ImageIndex = 1; - this.tabPage1.Location = new System.Drawing.Point(4, 25); - this.tabPage1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage1.Name = "tabPage1"; - this.tabPage1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabPage1.Size = new System.Drawing.Size(1114, 746); - this.tabPage1.TabIndex = 1; - this.tabPage1.Text = "Device Info"; - this.tabPage1.UseVisualStyleBackColor = true; - // - // deviceInfoView - // - this.deviceInfoView.Dock = System.Windows.Forms.DockStyle.Fill; - this.deviceInfoView.Location = new System.Drawing.Point(4, 4); - this.deviceInfoView.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); - this.deviceInfoView.Name = "deviceInfoView"; - this.deviceInfoView.Size = new System.Drawing.Size(1108, 740); - this.deviceInfoView.TabIndex = 0; - // - // tabControl1 - // - this.tabControl1.Controls.Add(this.tabPage1); - this.tabControl1.Controls.Add(this.tabPage2); - this.tabControl1.Controls.Add(this.tabPage3); - this.tabControl1.Controls.Add(this.tabPage4); - this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabControl1.ImageList = this.imageList1; - this.tabControl1.Location = new System.Drawing.Point(0, 0); - this.tabControl1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.tabControl1.Name = "tabControl1"; - this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(1038, 773); - this.tabControl1.TabIndex = 1; - // - // DeviceView - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.Controls.Add(this.tabControl1); - this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); - this.Name = "DeviceView"; - this.Size = new System.Drawing.Size(1038, 773); - this.tabPage4.ResumeLayout(false); - this.tabPage4.PerformLayout(); - this.tabPage3.ResumeLayout(false); - this.tabPage3.PerformLayout(); - this.tabPage2.ResumeLayout(false); - this.tabPage1.ResumeLayout(false); - this.tabControl1.ResumeLayout(false); - this.ResumeLayout(false); - - } - - #endregion - private System.Windows.Forms.ImageList imageList1; - private System.Windows.Forms.TabPage tabPage4; - private DevicePDOView2 devicePDOView2; - private System.Windows.Forms.TabPage tabPage3; - private DevicePDOView2 devicePDOView1; - private System.Windows.Forms.TabPage tabPage2; - private DeviceODView deviceODView1; - private System.Windows.Forms.TabPage tabPage1; - private DeviceInfoView deviceInfoView; - private System.Windows.Forms.TabControl tabControl1; - } -} +namespace ODEditor +{ + partial class DeviceView + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Component Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DeviceView)); + this.imageList1 = new System.Windows.Forms.ImageList(this.components); + this.tabPage4 = new System.Windows.Forms.TabPage(); + this.devicePDOView2 = new ODEditor.DevicePDOView2(); + this.tabPage3 = new System.Windows.Forms.TabPage(); + this.devicePDOView1 = new ODEditor.DevicePDOView2(); + this.tabPage2 = new System.Windows.Forms.TabPage(); + this.deviceODView1 = new ODEditor.DeviceODView(); + this.tabPage1 = new System.Windows.Forms.TabPage(); + this.deviceInfoView = new ODEditor.DeviceInfoView(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage4.SuspendLayout(); + this.tabPage3.SuspendLayout(); + this.tabPage2.SuspendLayout(); + this.tabPage1.SuspendLayout(); + this.tabControl1.SuspendLayout(); + this.SuspendLayout(); + // + // imageList1 + // + this.imageList1.ImageStream = ((System.Windows.Forms.ImageListStreamer)(resources.GetObject("imageList1.ImageStream"))); + this.imageList1.TransparentColor = System.Drawing.Color.Transparent; + this.imageList1.Images.SetKeyName(0, "ListBox_686.png"); + this.imageList1.Images.SetKeyName(1, "notebook_16xLG.png"); + this.imageList1.Images.SetKeyName(2, "Output_16xLG.png"); + this.imageList1.Images.SetKeyName(3, "SingleInput_8170_16x.png"); + // + // tabPage4 + // + this.tabPage4.Controls.Add(this.devicePDOView2); + this.tabPage4.ImageIndex = 3; + this.tabPage4.Location = new System.Drawing.Point(4, 25); + this.tabPage4.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage4.Name = "tabPage4"; + this.tabPage4.Size = new System.Drawing.Size(1114, 746); + this.tabPage4.TabIndex = 3; + this.tabPage4.Text = "RX PDO Mapping"; + this.tabPage4.UseVisualStyleBackColor = true; + // + // devicePDOView2 + // + this.devicePDOView2.AutoScroll = true; + this.devicePDOView2.AutoSize = true; + this.devicePDOView2.Dock = System.Windows.Forms.DockStyle.Fill; + this.devicePDOView2.Location = new System.Drawing.Point(0, 0); + this.devicePDOView2.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.devicePDOView2.Name = "devicePDOView2"; + this.devicePDOView2.Size = new System.Drawing.Size(1114, 746); + this.devicePDOView2.TabIndex = 0; + // + // tabPage3 + // + this.tabPage3.Controls.Add(this.devicePDOView1); + this.tabPage3.ImageIndex = 2; + this.tabPage3.Location = new System.Drawing.Point(4, 25); + this.tabPage3.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage3.Name = "tabPage3"; + this.tabPage3.Size = new System.Drawing.Size(1030, 746); + this.tabPage3.TabIndex = 2; + this.tabPage3.Text = "TX PDO Mapping"; + this.tabPage3.UseVisualStyleBackColor = true; + // + // devicePDOView1 + // + this.devicePDOView1.AutoScroll = true; + this.devicePDOView1.AutoSize = true; + this.devicePDOView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.devicePDOView1.Location = new System.Drawing.Point(0, 0); + this.devicePDOView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.devicePDOView1.Name = "devicePDOView1"; + this.devicePDOView1.Size = new System.Drawing.Size(1030, 746); + this.devicePDOView1.TabIndex = 0; + // + // tabPage2 + // + this.tabPage2.Controls.Add(this.deviceODView1); + this.tabPage2.ImageIndex = 0; + this.tabPage2.Location = new System.Drawing.Point(4, 25); + this.tabPage2.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage2.Name = "tabPage2"; + this.tabPage2.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage2.Size = new System.Drawing.Size(1114, 746); + this.tabPage2.TabIndex = 0; + this.tabPage2.Text = "Object Dictionary"; + this.tabPage2.UseVisualStyleBackColor = true; + // + // deviceODView1 + // + this.deviceODView1.Dock = System.Windows.Forms.DockStyle.Fill; + this.deviceODView1.Location = new System.Drawing.Point(4, 4); + this.deviceODView1.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.deviceODView1.Name = "deviceODView1"; + this.deviceODView1.Size = new System.Drawing.Size(1108, 740); + this.deviceODView1.TabIndex = 0; + // + // tabPage1 + // + this.tabPage1.Controls.Add(this.deviceInfoView); + this.tabPage1.ImageIndex = 1; + this.tabPage1.Location = new System.Drawing.Point(4, 25); + this.tabPage1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage1.Name = "tabPage1"; + this.tabPage1.Padding = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabPage1.Size = new System.Drawing.Size(1114, 746); + this.tabPage1.TabIndex = 1; + this.tabPage1.Text = "Device Info"; + this.tabPage1.UseVisualStyleBackColor = true; + // + // deviceInfoView + // + this.deviceInfoView.Dock = System.Windows.Forms.DockStyle.Fill; + this.deviceInfoView.Location = new System.Drawing.Point(4, 4); + this.deviceInfoView.Margin = new System.Windows.Forms.Padding(5, 5, 5, 5); + this.deviceInfoView.Name = "deviceInfoView"; + this.deviceInfoView.Size = new System.Drawing.Size(1108, 740); + this.deviceInfoView.TabIndex = 0; + // + // tabControl1 + // + this.tabControl1.Controls.Add(this.tabPage1); + this.tabControl1.Controls.Add(this.tabPage2); + this.tabControl1.Controls.Add(this.tabPage3); + this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.ImageList = this.imageList1; + this.tabControl1.Location = new System.Drawing.Point(0, 0); + this.tabControl1.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(1038, 773); + this.tabControl1.TabIndex = 1; + // + // DeviceView + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.Controls.Add(this.tabControl1); + this.Margin = new System.Windows.Forms.Padding(4, 4, 4, 4); + this.Name = "DeviceView"; + this.Size = new System.Drawing.Size(1038, 773); + this.tabPage4.ResumeLayout(false); + this.tabPage4.PerformLayout(); + this.tabPage3.ResumeLayout(false); + this.tabPage3.PerformLayout(); + this.tabPage2.ResumeLayout(false); + this.tabPage1.ResumeLayout(false); + this.tabControl1.ResumeLayout(false); + this.ResumeLayout(false); + + } + + #endregion + private System.Windows.Forms.ImageList imageList1; + private System.Windows.Forms.TabPage tabPage4; + private DevicePDOView2 devicePDOView2; + private System.Windows.Forms.TabPage tabPage3; + private DevicePDOView2 devicePDOView1; + private System.Windows.Forms.TabPage tabPage2; + private DeviceODView deviceODView1; + private System.Windows.Forms.TabPage tabPage1; + private DeviceInfoView deviceInfoView; + private System.Windows.Forms.TabControl tabControl1; + } +} diff --git a/EDSEditorGUI/Form1.Designer.cs b/EDSEditorGUI/Form1.Designer.cs index 21d3b870..6ef5774d 100644 --- a/EDSEditorGUI/Form1.Designer.cs +++ b/EDSEditorGUI/Form1.Designer.cs @@ -28,308 +28,308 @@ protected override void Dispose(bool disposing) /// private void InitializeComponent() { - this.components = new System.ComponentModel.Container(); - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ODEditor_MainForm)); - this.menuStrip1 = new System.Windows.Forms.MenuStrip(); - this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.openCanOpenNodeXMLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveProjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); - this.loadNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); - this.mnuRecentlyUsed = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); - this.exportDeviceFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.exportCanOpenNodeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.saveExportAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); - this.closeFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); - this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.insertToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.reportsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.documentationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.networkPDOToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); - this.tabControl1 = new System.Windows.Forms.TabControl(); - this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); - this.menuStrip1.SuspendLayout(); - this.SuspendLayout(); - // - // menuStrip1 - // - this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); - this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.fileToolStripMenuItem, - this.insertToolStripMenuItem, - this.reportsToolStripMenuItem, - this.toolsToolStripMenuItem}); - this.menuStrip1.Location = new System.Drawing.Point(0, 0); - this.menuStrip1.Name = "menuStrip1"; - this.menuStrip1.Size = new System.Drawing.Size(1599, 28); - this.menuStrip1.TabIndex = 1; - this.menuStrip1.Text = "menuStrip1"; - // - // fileToolStripMenuItem - // - this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.newToolStripMenuItem, - this.openCanOpenNodeXMLToolStripMenuItem, - this.saveProjectToolStripMenuItem, - this.saveAsToolStripMenuItem, - this.toolStripSeparator3, - this.loadNetworkXmlToolStripMenuItem, - this.saveNetworkXmlToolStripMenuItem, - this.toolStripSeparator6, - this.mnuRecentlyUsed, - this.toolStripSeparator1, - this.exportDeviceFileToolStripMenuItem, - this.exportCanOpenNodeToolStripMenuItem, - this.saveExportAllToolStripMenuItem, - this.toolStripSeparator2, - this.closeFileToolStripMenuItem, - this.toolStripSeparator4, - this.quitToolStripMenuItem}); - this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; - this.fileToolStripMenuItem.Size = new System.Drawing.Size(46, 24); - this.fileToolStripMenuItem.Text = "&File"; - // - // newToolStripMenuItem - // - this.newToolStripMenuItem.Image = global::ODEditor.Properties.Resources.NewFile_6276; - this.newToolStripMenuItem.Name = "newToolStripMenuItem"; - this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); - this.newToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.newToolStripMenuItem.Text = "&New"; - this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click); - // - // openCanOpenNodeXMLToolStripMenuItem - // - this.openCanOpenNodeXMLToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; - this.openCanOpenNodeXMLToolStripMenuItem.Name = "openCanOpenNodeXMLToolStripMenuItem"; - this.openCanOpenNodeXMLToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); - this.openCanOpenNodeXMLToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.openCanOpenNodeXMLToolStripMenuItem.Text = "&Open"; - this.openCanOpenNodeXMLToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); - // - // saveProjectToolStripMenuItem - // - this.saveProjectToolStripMenuItem.Enabled = false; - this.saveProjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; - this.saveProjectToolStripMenuItem.Name = "saveProjectToolStripMenuItem"; - this.saveProjectToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); - this.saveProjectToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.saveProjectToolStripMenuItem.Text = "&Save Project"; - this.saveProjectToolStripMenuItem.Click += new System.EventHandler(this.saveProjectToolStripMenuItem_Click); - // - // saveAsToolStripMenuItem - // - this.saveAsToolStripMenuItem.Enabled = false; - this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem"; - this.saveAsToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) - | System.Windows.Forms.Keys.S))); - this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.saveAsToolStripMenuItem.Text = "Save &Project As..."; - this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click); - // - // toolStripSeparator3 - // - this.toolStripSeparator3.Name = "toolStripSeparator3"; - this.toolStripSeparator3.Size = new System.Drawing.Size(356, 6); - // - // loadNetworkXmlToolStripMenuItem - // - this.loadNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; - this.loadNetworkXmlToolStripMenuItem.Name = "loadNetworkXmlToolStripMenuItem"; - this.loadNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.loadNetworkXmlToolStripMenuItem.Text = "Open &Network XML"; - this.loadNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.loadNetworkXmlToolStripMenuItem_Click); - // - // saveNetworkXmlToolStripMenuItem - // - this.saveNetworkXmlToolStripMenuItem.Enabled = false; - this.saveNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; - this.saveNetworkXmlToolStripMenuItem.Name = "saveNetworkXmlToolStripMenuItem"; - this.saveNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.saveNetworkXmlToolStripMenuItem.Text = "Save Networ&k XML"; - this.saveNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.saveNetworkXmlToolStripMenuItem_Click); - // - // toolStripSeparator6 - // - this.toolStripSeparator6.Name = "toolStripSeparator6"; - this.toolStripSeparator6.Size = new System.Drawing.Size(356, 6); - // - // mnuRecentlyUsed - // - this.mnuRecentlyUsed.Name = "mnuRecentlyUsed"; - this.mnuRecentlyUsed.Size = new System.Drawing.Size(359, 26); - this.mnuRecentlyUsed.Text = "&Recent Files"; - // - // toolStripSeparator1 - // - this.toolStripSeparator1.Name = "toolStripSeparator1"; - this.toolStripSeparator1.Size = new System.Drawing.Size(356, 6); - // - // exportDeviceFileToolStripMenuItem - // - this.exportDeviceFileToolStripMenuItem.Enabled = false; - this.exportDeviceFileToolStripMenuItem.Name = "exportDeviceFileToolStripMenuItem"; - this.exportDeviceFileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); - this.exportDeviceFileToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.exportDeviceFileToolStripMenuItem.Text = "&Export..."; - this.exportDeviceFileToolStripMenuItem.Click += new System.EventHandler(this.exportDeviceFileToolStripMenuItem_Click); - // - // exportCanOpenNodeToolStripMenuItem - // - this.exportCanOpenNodeToolStripMenuItem.Enabled = false; - this.exportCanOpenNodeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("exportCanOpenNodeToolStripMenuItem.Image"))); - this.exportCanOpenNodeToolStripMenuItem.Name = "exportCanOpenNodeToolStripMenuItem"; - this.exportCanOpenNodeToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.exportCanOpenNodeToolStripMenuItem.Text = "E&xport CanOpenNode..."; - this.exportCanOpenNodeToolStripMenuItem.Click += new System.EventHandler(this.exportCanOpenNodeToolStripMenuItem_Click); - // - // saveExportAllToolStripMenuItem - // - this.saveExportAllToolStripMenuItem.Enabled = false; - this.saveExportAllToolStripMenuItem.Name = "saveExportAllToolStripMenuItem"; - this.saveExportAllToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.saveExportAllToolStripMenuItem.Text = "Save &All"; - this.saveExportAllToolStripMenuItem.Click += new System.EventHandler(this.saveExportAllToolStripMenuItem_Click); - // - // toolStripSeparator2 - // - this.toolStripSeparator2.Name = "toolStripSeparator2"; - this.toolStripSeparator2.Size = new System.Drawing.Size(356, 6); - // - // closeFileToolStripMenuItem - // - this.closeFileToolStripMenuItem.Enabled = false; - this.closeFileToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Close_6519; - this.closeFileToolStripMenuItem.Name = "closeFileToolStripMenuItem"; - this.closeFileToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.closeFileToolStripMenuItem.Text = "&Close file"; - this.closeFileToolStripMenuItem.Click += new System.EventHandler(this.closeFileToolStripMenuItem_Click); - // - // toolStripSeparator4 - // - this.toolStripSeparator4.Name = "toolStripSeparator4"; - this.toolStripSeparator4.Size = new System.Drawing.Size(356, 6); - // - // quitToolStripMenuItem - // - this.quitToolStripMenuItem.Image = global::ODEditor.Properties.Resources._305_Close_16x16_72; - this.quitToolStripMenuItem.Name = "quitToolStripMenuItem"; - this.quitToolStripMenuItem.Size = new System.Drawing.Size(359, 26); - this.quitToolStripMenuItem.Text = "&Quit"; - this.quitToolStripMenuItem.Click += new System.EventHandler(this.quitToolStripMenuItem_Click); - // - // insertToolStripMenuItem - // - this.insertToolStripMenuItem.Name = "insertToolStripMenuItem"; - this.insertToolStripMenuItem.Size = new System.Drawing.Size(106, 24); - this.insertToolStripMenuItem.Text = "&Insert Profile"; - // - // reportsToolStripMenuItem - // - this.reportsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.documentationToolStripMenuItem, - this.networkPDOToolStripMenuItem}); - this.reportsToolStripMenuItem.Name = "reportsToolStripMenuItem"; - this.reportsToolStripMenuItem.Size = new System.Drawing.Size(74, 24); - this.reportsToolStripMenuItem.Text = "&Reports"; - // - // documentationToolStripMenuItem - // - this.documentationToolStripMenuItem.Enabled = false; - this.documentationToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; - this.documentationToolStripMenuItem.Name = "documentationToolStripMenuItem"; - this.documentationToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); - this.documentationToolStripMenuItem.Size = new System.Drawing.Size(339, 26); - this.documentationToolStripMenuItem.Text = "&Documentation"; - this.documentationToolStripMenuItem.Click += new System.EventHandler(this.documentationToolStripMenuItem_Click); - // - // networkPDOToolStripMenuItem - // - this.networkPDOToolStripMenuItem.Enabled = false; - this.networkPDOToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; - this.networkPDOToolStripMenuItem.Name = "networkPDOToolStripMenuItem"; - this.networkPDOToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) - | System.Windows.Forms.Keys.P))); - this.networkPDOToolStripMenuItem.Size = new System.Drawing.Size(339, 26); - this.networkPDOToolStripMenuItem.Text = "&Network PDO"; - this.networkPDOToolStripMenuItem.Click += new System.EventHandler(this.networkPDOToolStripMenuItem_Click); - // - // toolsToolStripMenuItem - // - this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { - this.preferencesToolStripMenuItem}); - this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; - this.toolsToolStripMenuItem.Size = new System.Drawing.Size(58, 24); - this.toolsToolStripMenuItem.Text = "Tools"; - // - // preferencesToolStripMenuItem - // - this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; - this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(168, 26); - this.preferencesToolStripMenuItem.Text = "Preferences"; - this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); - // - // tabControl1 - // - this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Left; - this.tabControl1.AllowDrop = true; - this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; - this.tabControl1.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed; - this.tabControl1.ItemSize = new System.Drawing.Size(24, 120); - this.tabControl1.Location = new System.Drawing.Point(0, 28); - this.tabControl1.Margin = new System.Windows.Forms.Padding(4); - this.tabControl1.Multiline = true; - this.tabControl1.Name = "tabControl1"; - this.tabControl1.SelectedIndex = 0; - this.tabControl1.Size = new System.Drawing.Size(1599, 909); - this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; - this.tabControl1.TabIndex = 2; - this.tabControl1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabControl1_DrawItem); - this.tabControl1.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.tabControl1_ControlsChanged); - this.tabControl1.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.tabControl1_Controlsremoved); - this.tabControl1.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); - this.tabControl1.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); - this.tabControl1.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); - this.tabControl1.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); - this.tabControl1.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); - // - // ODEditor_MainForm - // - this.AllowDrop = true; - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(1599, 937); - this.Controls.Add(this.tabControl1); - this.Controls.Add(this.menuStrip1); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Margin = new System.Windows.Forms.Padding(4); - this.MinimumSize = new System.Drawing.Size(1560, 750); - this.Name = "ODEditor_MainForm"; - this.Text = "Object Dictionary Editor "; - this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ODEditor_MainForm_FormClosing); - this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ODEditor_MainForm_FormClosed); - this.Load += new System.EventHandler(this.ODEditor_MainForm_Load); - this.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); - this.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); - this.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); - this.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); - this.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); - this.MouseCaptureChanged += new System.EventHandler(this.ODEditor_MainForm_Leave); - this.MouseLeave += new System.EventHandler(this.ODEditor_MainForm_Leave); - this.menuStrip1.ResumeLayout(false); - this.menuStrip1.PerformLayout(); - this.ResumeLayout(false); - this.PerformLayout(); - + this.components = new System.ComponentModel.Container(); + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ODEditor_MainForm)); + this.menuStrip1 = new System.Windows.Forms.MenuStrip(); + this.fileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.newToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.openCanOpenNodeXMLToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveProjectToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveAsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator3 = new System.Windows.Forms.ToolStripSeparator(); + this.loadNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveNetworkXmlToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator6 = new System.Windows.Forms.ToolStripSeparator(); + this.mnuRecentlyUsed = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator1 = new System.Windows.Forms.ToolStripSeparator(); + this.exportDeviceFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.exportCanOpenNodeToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.saveExportAllToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator2 = new System.Windows.Forms.ToolStripSeparator(); + this.closeFileToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripSeparator4 = new System.Windows.Forms.ToolStripSeparator(); + this.quitToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.insertToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.reportsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.documentationToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.networkPDOToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.toolsToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.preferencesToolStripMenuItem = new System.Windows.Forms.ToolStripMenuItem(); + this.tabControl1 = new System.Windows.Forms.TabControl(); + this.toolTip1 = new System.Windows.Forms.ToolTip(this.components); + this.menuStrip1.SuspendLayout(); + this.SuspendLayout(); + // + // menuStrip1 + // + this.menuStrip1.ImageScalingSize = new System.Drawing.Size(20, 20); + this.menuStrip1.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.fileToolStripMenuItem, + this.insertToolStripMenuItem, + this.reportsToolStripMenuItem, + this.toolsToolStripMenuItem}); + this.menuStrip1.Location = new System.Drawing.Point(0, 0); + this.menuStrip1.Name = "menuStrip1"; + this.menuStrip1.Size = new System.Drawing.Size(1599, 28); + this.menuStrip1.TabIndex = 1; + this.menuStrip1.Text = "menuStrip1"; + // + // fileToolStripMenuItem + // + this.fileToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.newToolStripMenuItem, + this.openCanOpenNodeXMLToolStripMenuItem, + this.saveProjectToolStripMenuItem, + this.saveAsToolStripMenuItem, + this.toolStripSeparator3, + this.loadNetworkXmlToolStripMenuItem, + this.saveNetworkXmlToolStripMenuItem, + this.toolStripSeparator6, + this.mnuRecentlyUsed, + this.toolStripSeparator1, + this.exportDeviceFileToolStripMenuItem, + this.exportCanOpenNodeToolStripMenuItem, + this.saveExportAllToolStripMenuItem, + this.toolStripSeparator2, + this.closeFileToolStripMenuItem, + this.toolStripSeparator4, + this.quitToolStripMenuItem}); + this.fileToolStripMenuItem.Name = "fileToolStripMenuItem"; + this.fileToolStripMenuItem.Size = new System.Drawing.Size(46, 24); + this.fileToolStripMenuItem.Text = "&File"; + // + // newToolStripMenuItem + // + this.newToolStripMenuItem.Image = global::ODEditor.Properties.Resources.NewFile_6276; + this.newToolStripMenuItem.Name = "newToolStripMenuItem"; + this.newToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.N))); + this.newToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.newToolStripMenuItem.Text = "&New"; + this.newToolStripMenuItem.Click += new System.EventHandler(this.newToolStripMenuItem_Click); + // + // openCanOpenNodeXMLToolStripMenuItem + // + this.openCanOpenNodeXMLToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; + this.openCanOpenNodeXMLToolStripMenuItem.Name = "openCanOpenNodeXMLToolStripMenuItem"; + this.openCanOpenNodeXMLToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.O))); + this.openCanOpenNodeXMLToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.openCanOpenNodeXMLToolStripMenuItem.Text = "&Open"; + this.openCanOpenNodeXMLToolStripMenuItem.Click += new System.EventHandler(this.openToolStripMenuItem_Click); + // + // saveProjectToolStripMenuItem + // + this.saveProjectToolStripMenuItem.Enabled = false; + this.saveProjectToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; + this.saveProjectToolStripMenuItem.Name = "saveProjectToolStripMenuItem"; + this.saveProjectToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.S))); + this.saveProjectToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveProjectToolStripMenuItem.Text = "&Save Project"; + this.saveProjectToolStripMenuItem.Click += new System.EventHandler(this.saveProjectToolStripMenuItem_Click); + // + // saveAsToolStripMenuItem + // + this.saveAsToolStripMenuItem.Enabled = false; + this.saveAsToolStripMenuItem.Name = "saveAsToolStripMenuItem"; + this.saveAsToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.S))); + this.saveAsToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveAsToolStripMenuItem.Text = "Save &Project As..."; + this.saveAsToolStripMenuItem.Click += new System.EventHandler(this.saveAsToolStripMenuItem_Click); + // + // toolStripSeparator3 + // + this.toolStripSeparator3.Name = "toolStripSeparator3"; + this.toolStripSeparator3.Size = new System.Drawing.Size(356, 6); + // + // loadNetworkXmlToolStripMenuItem + // + this.loadNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Open_6529; + this.loadNetworkXmlToolStripMenuItem.Name = "loadNetworkXmlToolStripMenuItem"; + this.loadNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.loadNetworkXmlToolStripMenuItem.Text = "Open &Network XML"; + this.loadNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.loadNetworkXmlToolStripMenuItem_Click); + // + // saveNetworkXmlToolStripMenuItem + // + this.saveNetworkXmlToolStripMenuItem.Enabled = false; + this.saveNetworkXmlToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Save_6530; + this.saveNetworkXmlToolStripMenuItem.Name = "saveNetworkXmlToolStripMenuItem"; + this.saveNetworkXmlToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveNetworkXmlToolStripMenuItem.Text = "Save Networ&k XML"; + this.saveNetworkXmlToolStripMenuItem.Click += new System.EventHandler(this.saveNetworkXmlToolStripMenuItem_Click); + // + // toolStripSeparator6 + // + this.toolStripSeparator6.Name = "toolStripSeparator6"; + this.toolStripSeparator6.Size = new System.Drawing.Size(356, 6); + // + // mnuRecentlyUsed + // + this.mnuRecentlyUsed.Name = "mnuRecentlyUsed"; + this.mnuRecentlyUsed.Size = new System.Drawing.Size(359, 26); + this.mnuRecentlyUsed.Text = "&Recent Files"; + // + // toolStripSeparator1 + // + this.toolStripSeparator1.Name = "toolStripSeparator1"; + this.toolStripSeparator1.Size = new System.Drawing.Size(356, 6); + // + // exportDeviceFileToolStripMenuItem + // + this.exportDeviceFileToolStripMenuItem.Enabled = false; + this.exportDeviceFileToolStripMenuItem.Name = "exportDeviceFileToolStripMenuItem"; + this.exportDeviceFileToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.E))); + this.exportDeviceFileToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.exportDeviceFileToolStripMenuItem.Text = "&Export..."; + this.exportDeviceFileToolStripMenuItem.Click += new System.EventHandler(this.exportDeviceFileToolStripMenuItem_Click); + // + // exportCanOpenNodeToolStripMenuItem + // + this.exportCanOpenNodeToolStripMenuItem.Enabled = false; + this.exportCanOpenNodeToolStripMenuItem.Image = ((System.Drawing.Image)(resources.GetObject("exportCanOpenNodeToolStripMenuItem.Image"))); + this.exportCanOpenNodeToolStripMenuItem.Name = "exportCanOpenNodeToolStripMenuItem"; + this.exportCanOpenNodeToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.exportCanOpenNodeToolStripMenuItem.Text = "E&xport CanOpenNode..."; + this.exportCanOpenNodeToolStripMenuItem.Click += new System.EventHandler(this.exportCanOpenNodeToolStripMenuItem_Click); + // + // saveExportAllToolStripMenuItem + // + this.saveExportAllToolStripMenuItem.Enabled = false; + this.saveExportAllToolStripMenuItem.Name = "saveExportAllToolStripMenuItem"; + this.saveExportAllToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.saveExportAllToolStripMenuItem.Text = "Save &All"; + this.saveExportAllToolStripMenuItem.Click += new System.EventHandler(this.saveExportAllToolStripMenuItem_Click); + // + // toolStripSeparator2 + // + this.toolStripSeparator2.Name = "toolStripSeparator2"; + this.toolStripSeparator2.Size = new System.Drawing.Size(356, 6); + // + // closeFileToolStripMenuItem + // + this.closeFileToolStripMenuItem.Enabled = false; + this.closeFileToolStripMenuItem.Image = global::ODEditor.Properties.Resources.Close_6519; + this.closeFileToolStripMenuItem.Name = "closeFileToolStripMenuItem"; + this.closeFileToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.closeFileToolStripMenuItem.Text = "&Close file"; + this.closeFileToolStripMenuItem.Click += new System.EventHandler(this.closeFileToolStripMenuItem_Click); + // + // toolStripSeparator4 + // + this.toolStripSeparator4.Name = "toolStripSeparator4"; + this.toolStripSeparator4.Size = new System.Drawing.Size(356, 6); + // + // quitToolStripMenuItem + // + this.quitToolStripMenuItem.Image = global::ODEditor.Properties.Resources._305_Close_16x16_72; + this.quitToolStripMenuItem.Name = "quitToolStripMenuItem"; + this.quitToolStripMenuItem.Size = new System.Drawing.Size(359, 26); + this.quitToolStripMenuItem.Text = "&Quit"; + this.quitToolStripMenuItem.Click += new System.EventHandler(this.quitToolStripMenuItem_Click); + // + // insertToolStripMenuItem + // + this.insertToolStripMenuItem.Name = "insertToolStripMenuItem"; + this.insertToolStripMenuItem.Size = new System.Drawing.Size(106, 24); + this.insertToolStripMenuItem.Text = "&Insert Profile"; + // + // reportsToolStripMenuItem + // + this.reportsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.documentationToolStripMenuItem, + this.networkPDOToolStripMenuItem}); + this.reportsToolStripMenuItem.Name = "reportsToolStripMenuItem"; + this.reportsToolStripMenuItem.Size = new System.Drawing.Size(74, 24); + this.reportsToolStripMenuItem.Text = "&Reports"; + // + // documentationToolStripMenuItem + // + this.documentationToolStripMenuItem.Enabled = false; + this.documentationToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; + this.documentationToolStripMenuItem.Name = "documentationToolStripMenuItem"; + this.documentationToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.P))); + this.documentationToolStripMenuItem.Size = new System.Drawing.Size(339, 26); + this.documentationToolStripMenuItem.Text = "&Documentation"; + this.documentationToolStripMenuItem.Click += new System.EventHandler(this.documentationToolStripMenuItem_Click); + // + // networkPDOToolStripMenuItem + // + this.networkPDOToolStripMenuItem.Enabled = false; + this.networkPDOToolStripMenuItem.Image = global::ODEditor.Properties.Resources.ExporttoScript_9881; + this.networkPDOToolStripMenuItem.Name = "networkPDOToolStripMenuItem"; + this.networkPDOToolStripMenuItem.ShortcutKeys = ((System.Windows.Forms.Keys)(((System.Windows.Forms.Keys.Control | System.Windows.Forms.Keys.Shift) + | System.Windows.Forms.Keys.P))); + this.networkPDOToolStripMenuItem.Size = new System.Drawing.Size(339, 26); + this.networkPDOToolStripMenuItem.Text = "&Network PDO"; + this.networkPDOToolStripMenuItem.Click += new System.EventHandler(this.networkPDOToolStripMenuItem_Click); + // + // toolsToolStripMenuItem + // + this.toolsToolStripMenuItem.DropDownItems.AddRange(new System.Windows.Forms.ToolStripItem[] { + this.preferencesToolStripMenuItem}); + this.toolsToolStripMenuItem.Name = "toolsToolStripMenuItem"; + this.toolsToolStripMenuItem.Size = new System.Drawing.Size(58, 24); + this.toolsToolStripMenuItem.Text = "Tools"; + // + // preferencesToolStripMenuItem + // + this.preferencesToolStripMenuItem.Name = "preferencesToolStripMenuItem"; + this.preferencesToolStripMenuItem.Size = new System.Drawing.Size(168, 26); + this.preferencesToolStripMenuItem.Text = "Preferences"; + this.preferencesToolStripMenuItem.Click += new System.EventHandler(this.preferencesToolStripMenuItem_Click); + // + // tabControl1 + // + this.tabControl1.Alignment = System.Windows.Forms.TabAlignment.Left; + this.tabControl1.AllowDrop = true; + this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; + this.tabControl1.DrawMode = System.Windows.Forms.TabDrawMode.OwnerDrawFixed; + this.tabControl1.ItemSize = new System.Drawing.Size(24, 120); + this.tabControl1.Location = new System.Drawing.Point(0, 28); + this.tabControl1.Margin = new System.Windows.Forms.Padding(4); + this.tabControl1.Multiline = true; + this.tabControl1.Name = "tabControl1"; + this.tabControl1.SelectedIndex = 0; + this.tabControl1.Size = new System.Drawing.Size(1599, 909); + this.tabControl1.SizeMode = System.Windows.Forms.TabSizeMode.Fixed; + this.tabControl1.TabIndex = 2; + this.tabControl1.DrawItem += new System.Windows.Forms.DrawItemEventHandler(this.tabControl1_DrawItem); + this.tabControl1.ControlAdded += new System.Windows.Forms.ControlEventHandler(this.tabControl1_ControlsChanged); + this.tabControl1.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.tabControl1_Controlsremoved); + this.tabControl1.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); + this.tabControl1.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); + this.tabControl1.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); + this.tabControl1.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); + this.tabControl1.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); + // + // ODEditor_MainForm + // + this.AllowDrop = true; + this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(1599, 937); + this.Controls.Add(this.tabControl1); + this.Controls.Add(this.menuStrip1); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Margin = new System.Windows.Forms.Padding(4); + this.MinimumSize = new System.Drawing.Size(1560, 750); + this.Name = "ODEditor_MainForm"; + this.Text = "Object Dictionary Editor "; + this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.ODEditor_MainForm_FormClosing); + this.FormClosed += new System.Windows.Forms.FormClosedEventHandler(this.ODEditor_MainForm_FormClosed); + this.Load += new System.EventHandler(this.ODEditor_MainForm_Load); + this.DragDrop += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragDrop); + this.DragEnter += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragEnter); + this.DragOver += new System.Windows.Forms.DragEventHandler(this.ODEditor_MainForm_DragOver); + this.DragLeave += new System.EventHandler(this.ODEditor_MainForm_DragLeave); + this.QueryContinueDrag += new System.Windows.Forms.QueryContinueDragEventHandler(this.ODEditor_MainForm_QueryContinueDrag); + this.MouseCaptureChanged += new System.EventHandler(this.ODEditor_MainForm_Leave); + this.MouseLeave += new System.EventHandler(this.ODEditor_MainForm_Leave); + this.menuStrip1.ResumeLayout(false); + this.menuStrip1.PerformLayout(); + this.ResumeLayout(false); + this.PerformLayout(); + } #endregion diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index c54cf88f..46b40837 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -26,7 +26,7 @@ You should have received a copy of the GNU General Public License using System.IO; using libEDSsharp; using Xml2CSharp; -using static System.Windows.Forms.VisualStyles.VisualStyleElement; +using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace ODEditor { @@ -155,37 +155,37 @@ void ProfileAddClick(object sender, EventArgs e) return; } - InsertObjects insObjForm = new InsertObjects(dv.eds, network, eds.ods, "0"); + InsertObjects insObjForm = new InsertObjects(dv.eds, network, eds.ods, "0"); if (insObjForm.ShowDialog() == DialogResult.OK) { - EDSsharp modifiedEds = insObjForm.GetModifiedEDS(); - modifiedEds.Dirty = true; - - if(modifiedEds == dv.eds) - { + EDSsharp modifiedEds = insObjForm.GetModifiedEDS(); + modifiedEds.Dirty = true; + + if(modifiedEds == dv.eds) + { dv.dispatch_updateOD(); dv.dispatch_updatePDOinfo(); dv.eds.UpdatePDOcount(); dv.dispatch_updatedevice(); } - else - { - foreach(TabPage page in tabControl1.TabPages) - { - DeviceView devView = (DeviceView)page.Controls[0]; - if(devView.eds == modifiedEds) - { - devView.dispatch_updateOD(); - devView.dispatch_updatePDOinfo(); - - devView.eds.UpdatePDOcount(); - devView.dispatch_updatedevice(); - } - } - } - } + else + { + foreach(TabPage page in tabControl1.TabPages) + { + DeviceView devView = (DeviceView)page.Controls[0]; + if(devView.eds == modifiedEds) + { + devView.dispatch_updateOD(); + devView.dispatch_updatePDOinfo(); + + devView.eds.UpdatePDOcount(); + devView.dispatch_updatedevice(); + } + } + } + } } } @@ -202,9 +202,9 @@ private void openEDSfile(string path,InfoSection.Filetype ft) Bridge bridge = new Bridge(); //tell me again why bridge is not static? dev = bridge.convert(eds); - DeviceView device = new DeviceView(eds, network); + DeviceView device = new DeviceView(eds, network); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; tabControl1.TabPages.Add(eds.di.ProductName); @@ -357,9 +357,9 @@ private void openXDDfile(string path) tabControl1.TabPages.Add(eds.di.ProductName); - DeviceView device = new DeviceView(eds, network); + DeviceView device = new DeviceView(eds, network); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); @@ -404,8 +404,8 @@ private void openXMLfile(string path) tabControl1.TabPages.Add(eds.di.ProductName); - DeviceView device = new DeviceView(eds, network); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + DeviceView device = new DeviceView(eds, network); + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); @@ -428,26 +428,26 @@ private void openXMLfile(string path) } - private void Device_UpdateODViewForEDS(object sender, UpdateODViewEventArgs e) - { - foreach (TabPage page in tabControl1.TabPages) - { - foreach (Control c in page.Controls) - { - if (c.GetType() == typeof(DeviceView)) - { - DeviceView d = (DeviceView)c; - if (d.eds == e.EDS) - { - d.dispatch_updateOD(); - } - } - - } - } - } - - + private void Device_UpdateODViewForEDS(object sender, UpdateODViewEventArgs e) + { + foreach (TabPage page in tabControl1.TabPages) + { + foreach (Control c in page.Controls) + { + if (c.GetType() == typeof(DeviceView)) + { + DeviceView d = (DeviceView)c; + if (d.eds == e.EDS) + { + d.dispatch_updateOD(); + } + } + + } + } + } + + private void Eds_onDataDirty(bool dirty, EDSsharp sender) { foreach(TabPage page in tabControl1.TabPages) @@ -588,16 +588,16 @@ private void saveAsToolStripMenuItem_Click(object sender, EventArgs e) sfd.Filter = "CANopen XDD v1.1 (*.xdd)|*.xdd|" + "CANopen XDC v1.1 (*.xdc)|*.xdc|" - + "CANopen XPD v1.1 (*.xpd)|*.xpd"; - + + "CANopen XPD v1.1 (*.xpd)|*.xpd"; + if (dv.eds.projectFilename == "") { sfd.FileName = Path.GetFileNameWithoutExtension(networkfilename); } else - { - sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); - sfd.RestoreDirectory = true; + { + sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); + sfd.RestoreDirectory = true; sfd.FileName = Path.GetFileNameWithoutExtension(dv.eds.projectFilename); } @@ -691,8 +691,8 @@ private void newToolStripMenuItem_Click(object sender, EventArgs e) tabControl1.TabPages.Add(eds.di.ProductName); - DeviceView device = new DeviceView(eds, network); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + DeviceView device = new DeviceView(eds, network); + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; @@ -703,16 +703,16 @@ private void newToolStripMenuItem_Click(object sender, EventArgs e) network.Add(eds); } - private void TabControl1_Selected(Object sender, TabControlEventArgs e) - { - if(tabControl1.SelectedIndex == 0) - { - DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; - dv.dispatch_updateOD(); - dv.dispatch_updatePDOinfo(); - dv.eds.UpdatePDOcount(); - dv.dispatch_updatedevice(); - } + private void TabControl1_Selected(Object sender, TabControlEventArgs e) + { + if(tabControl1.SelectedIndex == 0) + { + DeviceView dv = (DeviceView)tabControl1.SelectedTab.Controls[0]; + dv.dispatch_updateOD(); + dv.dispatch_updatePDOinfo(); + dv.eds.UpdatePDOcount(); + dv.dispatch_updatedevice(); + } } private void tabControl1_ControlsChanged(object sender, ControlEventArgs e) { @@ -936,13 +936,13 @@ private void openXDDNetworkfile(string file) tabControl1.TabPages.Add(eds.di.ProductName); - DeviceView device = new DeviceView(eds, network); + DeviceView device = new DeviceView(eds, network); tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); device.Dock = DockStyle.Fill; network.Add(eds); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; device.dispatch_updateOD(); @@ -968,13 +968,13 @@ private void openNetworkfile(string file) tabControl1.TabPages.Add(eds.di.ProductName); - DeviceView device = new DeviceView(eds, network); + DeviceView device = new DeviceView(eds, network); tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); device.Dock = DockStyle.Fill; network.Add(eds); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; eds.OnDataDirty += Eds_onDataDirty; device.dispatch_updateOD(); @@ -1216,7 +1216,7 @@ private bool fileTypeSupported(string fileName) return typeSupported; - } + } private void ODEditor_MainForm_DragEnter(object sender, DragEventArgs e) { diff --git a/EDSEditorGUI/InsertObjects.Designer.cs b/EDSEditorGUI/InsertObjects.Designer.cs index 10194b99..2791c038 100644 --- a/EDSEditorGUI/InsertObjects.Designer.cs +++ b/EDSEditorGUI/InsertObjects.Designer.cs @@ -1,165 +1,165 @@ -namespace ODEditor -{ - partial class InsertObjects - { - /// - /// Required designer variable. - /// - private System.ComponentModel.IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) - { - if (disposing && (components != null)) - { - components.Dispose(); - } - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() - { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InsertObjects)); - this.label2 = new System.Windows.Forms.Label(); - this.textBox_offsets = new System.Windows.Forms.TextBox(); - this.button_insert = new System.Windows.Forms.Button(); - this.button_cancel = new System.Windows.Forms.Button(); - this.dataGridView = new System.Windows.Forms.DataGridView(); - this.button_uncheck = new System.Windows.Forms.Button(); - this.label1 = new System.Windows.Forms.Label(); - this.cbox_Target = new System.Windows.Forms.ComboBox(); - ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit(); - this.SuspendLayout(); - // - // label2 - // - this.label2.AutoSize = true; - this.label2.Location = new System.Drawing.Point(12, 54); - this.label2.Name = "label2"; - this.label2.Size = new System.Drawing.Size(290, 13); - this.label2.TabIndex = 4; - this.label2.Text = "Index Offset (single or space separated list for multiple insert)"; - // - // textBox_offsets - // - this.textBox_offsets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.textBox_offsets.Location = new System.Drawing.Point(12, 70); - this.textBox_offsets.Name = "textBox_offsets"; - this.textBox_offsets.Size = new System.Drawing.Size(432, 20); - this.textBox_offsets.TabIndex = 2; - this.textBox_offsets.Text = "1"; - this.textBox_offsets.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.TextBox_offsets_KeyPress); - this.textBox_offsets.Leave += new System.EventHandler(this.TextBox_offsets_Leave); - // - // button_insert - // - this.button_insert.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.button_insert.Location = new System.Drawing.Point(154, 401); - this.button_insert.Name = "button_insert"; - this.button_insert.Size = new System.Drawing.Size(130, 37); - this.button_insert.TabIndex = 6; - this.button_insert.Text = "Insert"; - this.button_insert.UseVisualStyleBackColor = true; - this.button_insert.Click += new System.EventHandler(this.Button_create_Click); - // - // button_cancel - // - this.button_cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); - this.button_cancel.Location = new System.Drawing.Point(314, 401); - this.button_cancel.Name = "button_cancel"; - this.button_cancel.Size = new System.Drawing.Size(130, 37); - this.button_cancel.TabIndex = 7; - this.button_cancel.Text = "Cancel"; - this.button_cancel.UseVisualStyleBackColor = true; - this.button_cancel.Click += new System.EventHandler(this.Button_cancel_Click); - // - // dataGridView - // - this.dataGridView.AllowUserToAddRows = false; - this.dataGridView.AllowUserToDeleteRows = false; - this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) - | System.Windows.Forms.AnchorStyles.Left) - | System.Windows.Forms.AnchorStyles.Right))); - this.dataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells; - this.dataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells; - this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; - this.dataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; - this.dataGridView.Location = new System.Drawing.Point(12, 96); - this.dataGridView.Name = "dataGridView"; - this.dataGridView.Size = new System.Drawing.Size(432, 294); - this.dataGridView.TabIndex = 10; - this.dataGridView.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.DataGridView_ColumnHeaderMouseClick); - this.dataGridView.Leave += new System.EventHandler(this.DataGridView_Leave); - // - // button_uncheck - // - this.button_uncheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); - this.button_uncheck.Location = new System.Drawing.Point(12, 401); - this.button_uncheck.Name = "button_uncheck"; - this.button_uncheck.Size = new System.Drawing.Size(130, 37); - this.button_uncheck.TabIndex = 11; - this.button_uncheck.Text = "Uncheck all"; - this.button_uncheck.UseVisualStyleBackColor = true; - this.button_uncheck.Click += new System.EventHandler(this.button_uncheck_Click); - // - // label1 - // - this.label1.AutoSize = true; - this.label1.Location = new System.Drawing.Point(12, 9); - this.label1.Name = "label1"; - this.label1.Size = new System.Drawing.Size(38, 13); - this.label1.TabIndex = 12; - this.label1.Text = "Target"; - // - // cbox_Target - // - this.cbox_Target.FormattingEnabled = true; - this.cbox_Target.Location = new System.Drawing.Point(12, 25); - this.cbox_Target.Name = "cbox_Target"; - this.cbox_Target.Size = new System.Drawing.Size(432, 21); - this.cbox_Target.TabIndex = 13; - this.cbox_Target.SelectedIndexChanged += new System.EventHandler(this.cbox_Target_SelectedIndexChanged); - // - // InsertObjects - // - this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(456, 450); - this.Controls.Add(this.cbox_Target); - this.Controls.Add(this.label1); - this.Controls.Add(this.button_uncheck); - this.Controls.Add(this.dataGridView); - this.Controls.Add(this.button_cancel); - this.Controls.Add(this.button_insert); - this.Controls.Add(this.textBox_offsets); - this.Controls.Add(this.label2); - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.Name = "InsertObjects"; - this.Text = "Insert OD Objects"; - ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit(); - this.ResumeLayout(false); - this.PerformLayout(); - - } - - #endregion - private System.Windows.Forms.Label label2; - private System.Windows.Forms.TextBox textBox_offsets; - private System.Windows.Forms.Button button_insert; - private System.Windows.Forms.Button button_cancel; - private System.Windows.Forms.DataGridView dataGridView; - private System.Windows.Forms.Button button_uncheck; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.ComboBox cbox_Target; - } +namespace ODEditor +{ + partial class InsertObjects + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(InsertObjects)); + this.label2 = new System.Windows.Forms.Label(); + this.textBox_offsets = new System.Windows.Forms.TextBox(); + this.button_insert = new System.Windows.Forms.Button(); + this.button_cancel = new System.Windows.Forms.Button(); + this.dataGridView = new System.Windows.Forms.DataGridView(); + this.button_uncheck = new System.Windows.Forms.Button(); + this.label1 = new System.Windows.Forms.Label(); + this.cbox_Target = new System.Windows.Forms.ComboBox(); + ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).BeginInit(); + this.SuspendLayout(); + // + // label2 + // + this.label2.AutoSize = true; + this.label2.Location = new System.Drawing.Point(12, 54); + this.label2.Name = "label2"; + this.label2.Size = new System.Drawing.Size(290, 13); + this.label2.TabIndex = 4; + this.label2.Text = "Index Offset (single or space separated list for multiple insert)"; + // + // textBox_offsets + // + this.textBox_offsets.Anchor = ((System.Windows.Forms.AnchorStyles)(((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.textBox_offsets.Location = new System.Drawing.Point(12, 70); + this.textBox_offsets.Name = "textBox_offsets"; + this.textBox_offsets.Size = new System.Drawing.Size(432, 20); + this.textBox_offsets.TabIndex = 2; + this.textBox_offsets.Text = "1"; + this.textBox_offsets.KeyPress += new System.Windows.Forms.KeyPressEventHandler(this.TextBox_offsets_KeyPress); + this.textBox_offsets.Leave += new System.EventHandler(this.TextBox_offsets_Leave); + // + // button_insert + // + this.button_insert.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button_insert.Location = new System.Drawing.Point(154, 401); + this.button_insert.Name = "button_insert"; + this.button_insert.Size = new System.Drawing.Size(130, 37); + this.button_insert.TabIndex = 6; + this.button_insert.Text = "Insert"; + this.button_insert.UseVisualStyleBackColor = true; + this.button_insert.Click += new System.EventHandler(this.Button_create_Click); + // + // button_cancel + // + this.button_cancel.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right))); + this.button_cancel.Location = new System.Drawing.Point(314, 401); + this.button_cancel.Name = "button_cancel"; + this.button_cancel.Size = new System.Drawing.Size(130, 37); + this.button_cancel.TabIndex = 7; + this.button_cancel.Text = "Cancel"; + this.button_cancel.UseVisualStyleBackColor = true; + this.button_cancel.Click += new System.EventHandler(this.Button_cancel_Click); + // + // dataGridView + // + this.dataGridView.AllowUserToAddRows = false; + this.dataGridView.AllowUserToDeleteRows = false; + this.dataGridView.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom) + | System.Windows.Forms.AnchorStyles.Left) + | System.Windows.Forms.AnchorStyles.Right))); + this.dataGridView.AutoSizeColumnsMode = System.Windows.Forms.DataGridViewAutoSizeColumnsMode.AllCells; + this.dataGridView.AutoSizeRowsMode = System.Windows.Forms.DataGridViewAutoSizeRowsMode.AllCells; + this.dataGridView.ColumnHeadersHeightSizeMode = System.Windows.Forms.DataGridViewColumnHeadersHeightSizeMode.AutoSize; + this.dataGridView.EditMode = System.Windows.Forms.DataGridViewEditMode.EditOnKeystroke; + this.dataGridView.Location = new System.Drawing.Point(12, 96); + this.dataGridView.Name = "dataGridView"; + this.dataGridView.Size = new System.Drawing.Size(432, 294); + this.dataGridView.TabIndex = 10; + this.dataGridView.ColumnHeaderMouseClick += new System.Windows.Forms.DataGridViewCellMouseEventHandler(this.DataGridView_ColumnHeaderMouseClick); + this.dataGridView.Leave += new System.EventHandler(this.DataGridView_Leave); + // + // button_uncheck + // + this.button_uncheck.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Left))); + this.button_uncheck.Location = new System.Drawing.Point(12, 401); + this.button_uncheck.Name = "button_uncheck"; + this.button_uncheck.Size = new System.Drawing.Size(130, 37); + this.button_uncheck.TabIndex = 11; + this.button_uncheck.Text = "Uncheck all"; + this.button_uncheck.UseVisualStyleBackColor = true; + this.button_uncheck.Click += new System.EventHandler(this.button_uncheck_Click); + // + // label1 + // + this.label1.AutoSize = true; + this.label1.Location = new System.Drawing.Point(12, 9); + this.label1.Name = "label1"; + this.label1.Size = new System.Drawing.Size(38, 13); + this.label1.TabIndex = 12; + this.label1.Text = "Target"; + // + // cbox_Target + // + this.cbox_Target.FormattingEnabled = true; + this.cbox_Target.Location = new System.Drawing.Point(12, 25); + this.cbox_Target.Name = "cbox_Target"; + this.cbox_Target.Size = new System.Drawing.Size(432, 21); + this.cbox_Target.TabIndex = 13; + this.cbox_Target.SelectedIndexChanged += new System.EventHandler(this.cbox_Target_SelectedIndexChanged); + // + // InsertObjects + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(456, 450); + this.Controls.Add(this.cbox_Target); + this.Controls.Add(this.label1); + this.Controls.Add(this.button_uncheck); + this.Controls.Add(this.dataGridView); + this.Controls.Add(this.button_cancel); + this.Controls.Add(this.button_insert); + this.Controls.Add(this.textBox_offsets); + this.Controls.Add(this.label2); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "InsertObjects"; + this.Text = "Insert OD Objects"; + ((System.ComponentModel.ISupportInitialize)(this.dataGridView)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + private System.Windows.Forms.Label label2; + private System.Windows.Forms.TextBox textBox_offsets; + private System.Windows.Forms.Button button_insert; + private System.Windows.Forms.Button button_cancel; + private System.Windows.Forms.DataGridView dataGridView; + private System.Windows.Forms.Button button_uncheck; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.ComboBox cbox_Target; + } } \ No newline at end of file diff --git a/EDSEditorGUI/InsertObjects.cs b/EDSEditorGUI/InsertObjects.cs index cb03e41a..e91e6219 100644 --- a/EDSEditorGUI/InsertObjects.cs +++ b/EDSEditorGUI/InsertObjects.cs @@ -1,335 +1,335 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius - Copyright(c) 2020 Janez Paternoster -*/ - -using System; -using System.Collections.Generic; -using System.Drawing; -using System.Linq.Expressions; -using System.Text.RegularExpressions; -using System.Windows.Forms; -using libEDSsharp; - -namespace ODEditor -{ - public partial class InsertObjects : Form - { - private EDSsharp eds; - readonly SortedDictionary srcObjects; - readonly bool[] enabled; - readonly int dataGridView_InitialColumnCount; - List network; - List offsets; - - /// - /// Display form to: specify offset(s), insert clone of selected srcObjects into existing eds - /// - /// - /// - public InsertObjects(EDSsharp eds, List network, SortedDictionary srcObjects, string initialOffset) - { - this.eds = eds; - this.srcObjects = srcObjects; - this.network = network; - - InitializeComponent(); - - cbox_Target.Items.Clear(); - foreach(var item in network) - { - cbox_Target.Items.Add(item.di.ProductName); - } - cbox_Target.SelectedItem = eds.di.ProductName; - - textBox_offsets.Text = initialOffset; - - dataGridView.Columns.Add(new DataGridViewCheckBoxColumn() - { - Name = "Insert", - FalseValue = false, - TrueValue = true, - Visible = true - }); - int idx = dataGridView.Columns.Add("Original Object", "Original Object"); - dataGridView.Columns[idx].ReadOnly = true; - dataGridView_InitialColumnCount = dataGridView.ColumnCount; - - enabled = new bool[srcObjects.Count]; - for(int i = 0; i < enabled.Length; i++) - enabled[i] = true; - - Verify(initialOffset == "0"); - - DialogResult = DialogResult.Cancel; - } - - private void Button_cancel_Click(object sender, EventArgs e) - { - Close(); - } - - private bool Verify(bool InitiallyDisableIfError = false) - { - String pattern = @"(\d+)\s*([-])\s*(\d+)"; - /* get offests */ - offsets = new List(); - - if (textBox_offsets.Text.Contains("-")) - { - MatchCollection matches = System.Text.RegularExpressions.Regex.Matches(textBox_offsets.Text, pattern); - if (matches.Count != 0) - { - foreach (System.Text.RegularExpressions.Match m in matches) - { - int value1 = Int32.Parse(m.Groups[1].Value); - int value2 = Int32.Parse(m.Groups[3].Value); - - if ((value2 > value1) && (m.Groups[2].Value == "-")) - { - for (int i = value1; i <= value2; i++) - { - try - { - offsets.Add(i); - } - catch (Exception) - { - MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); - return false; - } - } - } - } - } - } - else - { - string[] str = textBox_offsets.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string s in str) - { - try - { - int value = (int)new System.ComponentModel.Int32Converter().ConvertFromString(s); - offsets.Add(value); - } - catch (Exception) - { - MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); - return false; - } - } - } - // write column headers - int colIdx = dataGridView_InitialColumnCount; - dataGridView.ColumnCount = colIdx + offsets.Count; - foreach (int o in offsets) - { - dataGridView.Columns[colIdx].Name = $"Offset {o}"; - dataGridView.Columns[colIdx++].ReadOnly = true; - } - - // write rows and verify errors - bool newIndexesValid = true; - var newIndexes = new List(); - DataGridViewCellStyle styleErr = new DataGridViewCellStyle - { - Font = new Font(dataGridView.Font, FontStyle.Bold), - ForeColor = Color.Red - }; - - dataGridView.Rows.Clear(); - - int odIdx = 0; - int j = 1; - foreach (ODentry od in srcObjects.Values) - { - String numpattern = @"(\w*\d+\Z)"; - string newname; - - string[] words = Regex.Split(od.parameter_name, numpattern); - // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); - if (words.Length > 1) - { - - // value1 = Int32.Parse(m.Groups[1].Value); - int nameidx = Int32.Parse(words[1]) + j++; - - newname = words[0] + nameidx;// nameidx.ToString ; - - } - else { - newname = od.parameter_name; - } - int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {newname}"); - int cellIdx = dataGridView_InitialColumnCount; - - foreach (int o in offsets) - { - int newIndex = (int)od.Index + o; - bool err = newIndex <= 0 || newIndex > 0xFFFF; - - dataGridView.Rows[rowIdx].Cells[cellIdx].Value = err ? $"{newIndex}" : $"0x{newIndex:X4}"; - - if (!err) - err = newIndexes.Contains(newIndex); - - if (!err) - { - - newIndexes.Add(newIndex); - err = eds.ods.ContainsKey((UInt16)newIndex); - } - - if (err) - { - if (enabled[odIdx] && InitiallyDisableIfError) - { - dataGridView.Rows[rowIdx].Cells[0].Value = false; - enabled[odIdx] = false; - } - else if (enabled[odIdx]) - { - newIndexesValid = false; - } - dataGridView.Rows[rowIdx].Cells[cellIdx].Style = styleErr; - } - cellIdx++; - } - odIdx++; - } - - dataGridView.ClearSelection(); - - return newIndexesValid; - } - - private void Button_create_Click(object sender, EventArgs e) - { - if (Verify()) - { - // clone OD objects - int odIdx = 0; - int i = 1; - foreach (ODentry od in srcObjects.Values) - { - if (enabled[odIdx]) - { - foreach (int o in offsets) - { - UInt16 newIndex = (UInt16)(od.Index + o); - ODentry newObject = od.Clone(); - - String pattern = @"(\w*\d+\Z)"; - - string[] words = Regex.Split(od.parameter_name, pattern); - // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); - if (words.Length > 1) - { - int nameidx = Int32.Parse(words[1]) + i++; - newObject.parameter_name = words[0] + nameidx;// nameidx.ToString ; - - } - - newObject.Index = newIndex; - - eds.ods.Add(newIndex, newObject); - } - } - odIdx++; - } - - DialogResult = DialogResult.OK; - Close(); - } - } - - private void TextBox_offsets_KeyPress(object sender, KeyPressEventArgs e) - { - if (e.KeyChar == ' ' || e.KeyChar == '\r') - { - Verify(); - } - } - - private void TextBox_offsets_Leave(object sender, EventArgs e) - { - Verify(); - } - - private void DataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) - { - // toggle selection on click on first column - if (e.ColumnIndex == 0) - { - dataGridView.ClearSelection(); - dataGridView.CurrentCell = null; - foreach (DataGridViewRow row in dataGridView.Rows) - { - row.Cells[0].Value = !((bool)row.Cells[0].Value); - } - } - } - - private void DataGridView_Leave(object sender, EventArgs e) - { - // recalculate enabled[] - dataGridView.ClearSelection(); - dataGridView.CurrentCell = null; - int odIdx = 0; - foreach (DataGridViewRow row in dataGridView.Rows) - { - enabled[odIdx++] = (bool)row.Cells[0].Value; - } - } - - private void button_uncheck_Click(object sender, EventArgs e) - { - int odIdx = 0; - foreach (DataGridViewRow item in dataGridView.Rows) - { - DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)item.Cells[0]; - - cell.Value = false; - enabled[odIdx++] = false; - } - } - - private void cbox_Target_SelectedIndexChanged(object sender, EventArgs e) - { - EDSsharp edsBefore = eds; - foreach (var item in network) - { - if((string)cbox_Target.SelectedItem == item.di.ProductName) - { - this.eds = item; - break; - } - } - if(this.eds != null && this.eds != edsBefore) - { - Verify(false); - } - } - - public EDSsharp GetModifiedEDS() - { - return this.eds; - } - } -} +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius + Copyright(c) 2020 Janez Paternoster +*/ + +using System; +using System.Collections.Generic; +using System.Drawing; +using System.Linq.Expressions; +using System.Text.RegularExpressions; +using System.Windows.Forms; +using libEDSsharp; + +namespace ODEditor +{ + public partial class InsertObjects : Form + { + private EDSsharp eds; + readonly SortedDictionary srcObjects; + readonly bool[] enabled; + readonly int dataGridView_InitialColumnCount; + List network; + List offsets; + + /// + /// Display form to: specify offset(s), insert clone of selected srcObjects into existing eds + /// + /// + /// + public InsertObjects(EDSsharp eds, List network, SortedDictionary srcObjects, string initialOffset) + { + this.eds = eds; + this.srcObjects = srcObjects; + this.network = network; + + InitializeComponent(); + + cbox_Target.Items.Clear(); + foreach(var item in network) + { + cbox_Target.Items.Add(item.di.ProductName); + } + cbox_Target.SelectedItem = eds.di.ProductName; + + textBox_offsets.Text = initialOffset; + + dataGridView.Columns.Add(new DataGridViewCheckBoxColumn() + { + Name = "Insert", + FalseValue = false, + TrueValue = true, + Visible = true + }); + int idx = dataGridView.Columns.Add("Original Object", "Original Object"); + dataGridView.Columns[idx].ReadOnly = true; + dataGridView_InitialColumnCount = dataGridView.ColumnCount; + + enabled = new bool[srcObjects.Count]; + for(int i = 0; i < enabled.Length; i++) + enabled[i] = true; + + Verify(initialOffset == "0"); + + DialogResult = DialogResult.Cancel; + } + + private void Button_cancel_Click(object sender, EventArgs e) + { + Close(); + } + + private bool Verify(bool InitiallyDisableIfError = false) + { + String pattern = @"(\d+)\s*([-])\s*(\d+)"; + /* get offests */ + offsets = new List(); + + if (textBox_offsets.Text.Contains("-")) + { + MatchCollection matches = System.Text.RegularExpressions.Regex.Matches(textBox_offsets.Text, pattern); + if (matches.Count != 0) + { + foreach (System.Text.RegularExpressions.Match m in matches) + { + int value1 = Int32.Parse(m.Groups[1].Value); + int value2 = Int32.Parse(m.Groups[3].Value); + + if ((value2 > value1) && (m.Groups[2].Value == "-")) + { + for (int i = value1; i <= value2; i++) + { + try + { + offsets.Add(i); + } + catch (Exception) + { + MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); + return false; + } + } + } + } + } + } + else + { + string[] str = textBox_offsets.Text.Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries); + foreach (string s in str) + { + try + { + int value = (int)new System.ComponentModel.Int32Converter().ConvertFromString(s); + offsets.Add(value); + } + catch (Exception) + { + MessageBox.Show("Syntax error in Index Offset!\n\nValid value is single signed number or space separated list of multiple signed numbers or a range seprated by '-'."); + return false; + } + } + } + // write column headers + int colIdx = dataGridView_InitialColumnCount; + dataGridView.ColumnCount = colIdx + offsets.Count; + foreach (int o in offsets) + { + dataGridView.Columns[colIdx].Name = $"Offset {o}"; + dataGridView.Columns[colIdx++].ReadOnly = true; + } + + // write rows and verify errors + bool newIndexesValid = true; + var newIndexes = new List(); + DataGridViewCellStyle styleErr = new DataGridViewCellStyle + { + Font = new Font(dataGridView.Font, FontStyle.Bold), + ForeColor = Color.Red + }; + + dataGridView.Rows.Clear(); + + int odIdx = 0; + int j = 1; + foreach (ODentry od in srcObjects.Values) + { + String numpattern = @"(\w*\d+\Z)"; + string newname; + + string[] words = Regex.Split(od.parameter_name, numpattern); + // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); + if (words.Length > 1) + { + + // value1 = Int32.Parse(m.Groups[1].Value); + int nameidx = Int32.Parse(words[1]) + j++; + + newname = words[0] + nameidx;// nameidx.ToString ; + + } + else { + newname = od.parameter_name; + } + int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {newname}"); + int cellIdx = dataGridView_InitialColumnCount; + + foreach (int o in offsets) + { + int newIndex = (int)od.Index + o; + bool err = newIndex <= 0 || newIndex > 0xFFFF; + + dataGridView.Rows[rowIdx].Cells[cellIdx].Value = err ? $"{newIndex}" : $"0x{newIndex:X4}"; + + if (!err) + err = newIndexes.Contains(newIndex); + + if (!err) + { + + newIndexes.Add(newIndex); + err = eds.ods.ContainsKey((UInt16)newIndex); + } + + if (err) + { + if (enabled[odIdx] && InitiallyDisableIfError) + { + dataGridView.Rows[rowIdx].Cells[0].Value = false; + enabled[odIdx] = false; + } + else if (enabled[odIdx]) + { + newIndexesValid = false; + } + dataGridView.Rows[rowIdx].Cells[cellIdx].Style = styleErr; + } + cellIdx++; + } + odIdx++; + } + + dataGridView.ClearSelection(); + + return newIndexesValid; + } + + private void Button_create_Click(object sender, EventArgs e) + { + if (Verify()) + { + // clone OD objects + int odIdx = 0; + int i = 1; + foreach (ODentry od in srcObjects.Values) + { + if (enabled[odIdx]) + { + foreach (int o in offsets) + { + UInt16 newIndex = (UInt16)(od.Index + o); + ODentry newObject = od.Clone(); + + String pattern = @"(\w*\d+\Z)"; + + string[] words = Regex.Split(od.parameter_name, pattern); + // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); + if (words.Length > 1) + { + int nameidx = Int32.Parse(words[1]) + i++; + newObject.parameter_name = words[0] + nameidx;// nameidx.ToString ; + + } + + newObject.Index = newIndex; + + eds.ods.Add(newIndex, newObject); + } + } + odIdx++; + } + + DialogResult = DialogResult.OK; + Close(); + } + } + + private void TextBox_offsets_KeyPress(object sender, KeyPressEventArgs e) + { + if (e.KeyChar == ' ' || e.KeyChar == '\r') + { + Verify(); + } + } + + private void TextBox_offsets_Leave(object sender, EventArgs e) + { + Verify(); + } + + private void DataGridView_ColumnHeaderMouseClick(object sender, DataGridViewCellMouseEventArgs e) + { + // toggle selection on click on first column + if (e.ColumnIndex == 0) + { + dataGridView.ClearSelection(); + dataGridView.CurrentCell = null; + foreach (DataGridViewRow row in dataGridView.Rows) + { + row.Cells[0].Value = !((bool)row.Cells[0].Value); + } + } + } + + private void DataGridView_Leave(object sender, EventArgs e) + { + // recalculate enabled[] + dataGridView.ClearSelection(); + dataGridView.CurrentCell = null; + int odIdx = 0; + foreach (DataGridViewRow row in dataGridView.Rows) + { + enabled[odIdx++] = (bool)row.Cells[0].Value; + } + } + + private void button_uncheck_Click(object sender, EventArgs e) + { + int odIdx = 0; + foreach (DataGridViewRow item in dataGridView.Rows) + { + DataGridViewCheckBoxCell cell = (DataGridViewCheckBoxCell)item.Cells[0]; + + cell.Value = false; + enabled[odIdx++] = false; + } + } + + private void cbox_Target_SelectedIndexChanged(object sender, EventArgs e) + { + EDSsharp edsBefore = eds; + foreach (var item in network) + { + if((string)cbox_Target.SelectedItem == item.di.ProductName) + { + this.eds = item; + break; + } + } + if(this.eds != null && this.eds != edsBefore) + { + Verify(false); + } + } + + public EDSsharp GetModifiedEDS() + { + return this.eds; + } + } +} diff --git a/EDSEditorGUI/NewIndex.Designer.cs b/EDSEditorGUI/NewIndex.Designer.cs index 3ca563bb..e85375df 100644 --- a/EDSEditorGUI/NewIndex.Designer.cs +++ b/EDSEditorGUI/NewIndex.Designer.cs @@ -1,5 +1,5 @@ -using libEDSsharp; - +using libEDSsharp; + namespace ODEditor { partial class NewIndex diff --git a/EDSEditorGUI/Properties/Resources.Designer.cs b/EDSEditorGUI/Properties/Resources.Designer.cs index 734f92bf..2295eb4a 100644 --- a/EDSEditorGUI/Properties/Resources.Designer.cs +++ b/EDSEditorGUI/Properties/Resources.Designer.cs @@ -1,253 +1,253 @@ -//------------------------------------------------------------------------------ -// -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 -// -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. -// -//------------------------------------------------------------------------------ - -namespace ODEditor.Properties { - using System; - - - /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. - /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ODEditor.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap _305_Close_16x16_72 { - get { - object obj = ResourceManager.GetObject("_305_Close_16x16_72", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap action_add_16xLG { - get { - object obj = ResourceManager.GetObject("action_add_16xLG", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Close_6519 { - get { - object obj = ResourceManager.GetObject("Close_6519", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Compile_191 { - get { - object obj = ResourceManager.GetObject("Compile_191", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap DriverTemplate_32x { - get { - object obj = ResourceManager.GetObject("DriverTemplate_32x", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap EventLog_5735 { - get { - object obj = ResourceManager.GetObject("EventLog_5735", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap ExporttoScript_9881 { - get { - object obj = ResourceManager.GetObject("ExporttoScript_9881", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap GenerateAll { - get { - object obj = ResourceManager.GetObject("GenerateAll", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap GenericVSEditor_9905 { - get { - object obj = ResourceManager.GetObject("GenericVSEditor_9905", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Index_8287_16x { - get { - object obj = ResourceManager.GetObject("Index_8287_16x", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap InsertColumn_5626 { - get { - object obj = ResourceManager.GetObject("InsertColumn_5626", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap ListBox_686 { - get { - object obj = ResourceManager.GetObject("ListBox_686", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap NewFile_6276 { - get { - object obj = ResourceManager.GetObject("NewFile_6276", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Open_6529 { - get { - object obj = ResourceManager.GetObject("Open_6529", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Print_11009 { - get { - object obj = ResourceManager.GetObject("Print_11009", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap PrintPreviewControl_698 { - get { - object obj = ResourceManager.GetObject("PrintPreviewControl_698", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap PrintSetup_11011 { - get { - object obj = ResourceManager.GetObject("PrintSetup_11011", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Remove_16xLG { - get { - object obj = ResourceManager.GetObject("Remove_16xLG", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - - /// - /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. - /// - internal static System.Drawing.Bitmap Save_6530 { - get { - object obj = ResourceManager.GetObject("Save_6530", resourceCulture); - return ((System.Drawing.Bitmap)(obj)); - } - } - } -} +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace ODEditor.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("ODEditor.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap _305_Close_16x16_72 { + get { + object obj = ResourceManager.GetObject("_305_Close_16x16_72", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap action_add_16xLG { + get { + object obj = ResourceManager.GetObject("action_add_16xLG", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Close_6519 { + get { + object obj = ResourceManager.GetObject("Close_6519", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Compile_191 { + get { + object obj = ResourceManager.GetObject("Compile_191", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap DriverTemplate_32x { + get { + object obj = ResourceManager.GetObject("DriverTemplate_32x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap EventLog_5735 { + get { + object obj = ResourceManager.GetObject("EventLog_5735", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ExporttoScript_9881 { + get { + object obj = ResourceManager.GetObject("ExporttoScript_9881", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap GenerateAll { + get { + object obj = ResourceManager.GetObject("GenerateAll", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap GenericVSEditor_9905 { + get { + object obj = ResourceManager.GetObject("GenericVSEditor_9905", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Index_8287_16x { + get { + object obj = ResourceManager.GetObject("Index_8287_16x", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap InsertColumn_5626 { + get { + object obj = ResourceManager.GetObject("InsertColumn_5626", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap ListBox_686 { + get { + object obj = ResourceManager.GetObject("ListBox_686", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap NewFile_6276 { + get { + object obj = ResourceManager.GetObject("NewFile_6276", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Open_6529 { + get { + object obj = ResourceManager.GetObject("Open_6529", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Print_11009 { + get { + object obj = ResourceManager.GetObject("Print_11009", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap PrintPreviewControl_698 { + get { + object obj = ResourceManager.GetObject("PrintPreviewControl_698", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap PrintSetup_11011 { + get { + object obj = ResourceManager.GetObject("PrintSetup_11011", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Remove_16xLG { + get { + object obj = ResourceManager.GetObject("Remove_16xLG", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + + /// + /// Sucht eine lokalisierte Ressource vom Typ System.Drawing.Bitmap. + /// + internal static System.Drawing.Bitmap Save_6530 { + get { + object obj = ResourceManager.GetObject("Save_6530", resourceCulture); + return ((System.Drawing.Bitmap)(obj)); + } + } + } +} diff --git a/EDSEditorGUI/Properties/Settings.Designer.cs b/EDSEditorGUI/Properties/Settings.Designer.cs index 04412fe2..baa3be85 100644 --- a/EDSEditorGUI/Properties/Settings.Designer.cs +++ b/EDSEditorGUI/Properties/Settings.Designer.cs @@ -1,50 +1,50 @@ -//------------------------------------------------------------------------------ -// -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 -// -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. -// -//------------------------------------------------------------------------------ - -namespace ODEditor.Properties { - - - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - - private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { - return defaultInstance; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("0")] - public int ExporterType { - get { - return ((int)(this["ExporterType"])); - } - set { - this["ExporterType"] = value; - } - } - - [global::System.Configuration.UserScopedSettingAttribute()] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Configuration.DefaultSettingValueAttribute("65535")] - public uint WarningMask { - get { - return ((uint)(this["WarningMask"])); - } - set { - this["WarningMask"] = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace ODEditor.Properties { + + + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "17.7.0.0")] + internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { + + private static Settings defaultInstance = ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); + + public static Settings Default { + get { + return defaultInstance; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("0")] + public int ExporterType { + get { + return ((int)(this["ExporterType"])); + } + set { + this["ExporterType"] = value; + } + } + + [global::System.Configuration.UserScopedSettingAttribute()] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Configuration.DefaultSettingValueAttribute("65535")] + public uint WarningMask { + get { + return ((uint)(this["WarningMask"])); + } + set { + this["WarningMask"] = value; + } + } + } +} diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index f779d4e8..4f13a71f 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -1,1720 +1,1720 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius - based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are - Copyright(c) 2010 - 2016 Janez Paternoster -*/ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using System.IO; - - - -namespace libEDSsharp -{ - - public class CanOpenNodeExporter : IExporter - { - - private string folderpath; - private string gitVersion; - protected EDSsharp eds; - - private int enabledcount = 0; - - Dictionary acceptable_canopen_names = new Dictionary(); - - //Used for array tracking - Dictionary au = new Dictionary(); - List openings = new List(); - List closings = new List(); - - private byte maxRXmappingsize = 0; - private byte maxTXmappingsize = 0; - ODentry maxRXmappingsOD=null; - ODentry maxTXmappingsOD=null; - - - public void prepareCanOpenNames() - { - acceptable_canopen_names.Add(0x101800, "identity"); - - acceptable_canopen_names.Add(0x140000, "RPDOCommunicationParameter"); - acceptable_canopen_names.Add(0x160000, "RPDOMappingParameter"); - acceptable_canopen_names.Add(0x180000, "TPDOCommunicationParameter"); - acceptable_canopen_names.Add(0x1a0000, "TPDOMappingParameter"); - - acceptable_canopen_names.Add(0x100500, "COB_ID_SYNCMessage"); - - - - acceptable_canopen_names.Add(0x101801, "vendorID"); - acceptable_canopen_names.Add(0x101802, "productCode"); - acceptable_canopen_names.Add(0x101803, "revisionNumber"); - acceptable_canopen_names.Add(0x101804, "serialNumber"); - - acceptable_canopen_names.Add(0x120000, "SDOServerParameter"); - acceptable_canopen_names.Add(0x120001, "COB_IDClientToServer"); - acceptable_canopen_names.Add(0x120002, "COB_IDServerToClient"); - - acceptable_canopen_names.Add(0x128000, "SDOClientParameter"); - acceptable_canopen_names.Add(0x128001, "COB_IDClientToServer"); - acceptable_canopen_names.Add(0x128002, "COB_IDServerToClient"); - - acceptable_canopen_names.Add(0x102900, "errorBehavior"); - - } - - - public void export(string folderpath, string filename, string gitVersion, EDSsharp eds,string odname) - { - this.folderpath = folderpath; - this.gitVersion = gitVersion; - this.eds = eds; - - - enabledcount = eds.GetNoEnabledObjects(); - - prepareCanOpenNames(); - - countPDOS(); - - - fixcompatentry(); - - prewalkArrays(); - - export_h(filename); - export_c(filename); - - } - - private void fixcompatentry() - { - // Handle the TPDO communication parameters in a special way, because of - // sizeof(OD_TPDOCommunicationParameter_t) != sizeof(CO_TPDOCommPar_t) in CANopen.c - // the existing CO_TPDOCommPar_t has a compatibility entry so we must export one regardless - // of if its in the OD or not - - for (UInt16 idx = 0x1800; idx < 0x1900; idx++) - { - if (ObjectActive(idx)) - { - ODentry od = eds.ods[idx]; - - if (!od.Containssubindex(0x04)) - { - ODentry compatibility = new ODentry("compatibility entry", idx, DataType.UNSIGNED8, "0", EDSsharp.AccessType.ro, PDOMappingType.no, od); - od.subobjects.Add(0x04, compatibility); - } - } - } - - } - - private void specialarraysearch(UInt16 start, UInt16 end) - { - UInt16 lowest = 0xffff; - UInt16 highest = 0x0000; - - foreach (KeyValuePair kvp in eds.ods) - { - - if (kvp.Value.prop.CO_disabled == true) - continue; - - if (kvp.Key >= start && kvp.Key <= end) - { - if (kvp.Key > highest) - highest = kvp.Key; - - if (kvp.Key < lowest) - lowest = kvp.Key; - } - } - - if(lowest!=0xffff && highest!=0x0000) - { - openings.Add(lowest); - closings.Add(highest); - - Console.WriteLine(string.Format("New special array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); - } - } - - public bool ObjectActive(UInt16 index) - { - if (eds.ods.ContainsKey(index)) - { - return !eds.ods[index].prop.CO_disabled; - } - else return false; - } - - protected void prewalkArrays() - { - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - if (od.prop.CO_disabled == true) - continue; - - string name = make_cname(od.parameter_name,od); - if (au.ContainsKey(name)) - { - au[name]++; - } - else - { - au[name] = 1; - } - } - - - //Handle special arrays - - specialarraysearch(0x1301, 0x1340); - specialarraysearch(0x1381, 0x13C0); - - - //SDO Client parameters - specialarraysearch(0x1200, 0x127F); - //SDO Server Parameters - specialarraysearch(0x1280, 0x12FF); - - //PDO Mappings and configs - specialarraysearch(0x1400, 0x15FF); - specialarraysearch(0x1600, 0x17FF); - specialarraysearch(0x1800, 0x19FF); - specialarraysearch(0x1A00, 0x1BFF); - - //now find opening and closing points for these arrays - foreach (KeyValuePair kvp in au) - { - if ( kvp.Value > 1) - { - string targetname = kvp.Key; - UInt16 lowest=0xffff; - UInt16 highest=0x0000; - foreach (KeyValuePair kvp2 in eds.ods) - { - - string name = make_cname(kvp2.Value.parameter_name,kvp2.Value); - if(name==targetname) - { - if (kvp2.Key > highest) - highest = kvp2.Key; - - if (kvp2.Key < lowest) - lowest = kvp2.Key; - } - - } - - if (!openings.Contains(lowest)) - { - openings.Add(lowest); - closings.Add(highest); - Console.WriteLine(string.Format("New array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); - } - - } - - } - - //Find maximum no entries in a mapping config to define an appropriate array - maxRXmappingsize = 0; - maxTXmappingsize = 0; - - for (ushort x=0x1600;x<0x1800;x++) - { - if(ObjectActive(x)) - { - byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); - - if(maxcount > maxRXmappingsize) - { - maxRXmappingsize = maxcount; - maxRXmappingsOD = eds.ods[x]; - } - } - } - - for (ushort x = 0x1a00; x < 0x1c00; x++) - { - if (ObjectActive(x)) - { - byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); - - if (maxcount > maxTXmappingsize) - { - maxTXmappingsize = maxcount; - maxTXmappingsOD = eds.ods[x]; - } - } - } - } - - string lastname = ""; - - private string print_h_bylocation(string location) - { - - StringBuilder sb = new StringBuilder(); - - lastname = ""; - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) - continue; - - sb.Append(print_h_entry(od)); - - } - - return sb.ToString(); - } - - - protected string print_h_entry(ODentry od) - { - StringBuilder sb = new StringBuilder(); - - if (od.Nosubindexes == 0) - { - string specialarraylength = ""; - if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) - { - - if (od.Lengthofstring == 0) - { - Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex),Warnings.warning_class.WARNING_STRING); - specialarraylength = "[1]"; - } - else - { - specialarraylength = string.Format("[{0}]", od.Lengthofstring); - } - } - - sb.AppendLine($"/*{od.Index:X4} */ {od.datatype.ToString(),-14} {make_cname(od.parameter_name,od)}{specialarraylength};"); - } - else - { - //fixme why is this not od.datatype? - DataType t = eds.Getdatatype(od); - - //If it not a defined type, and it probably is not for a REC, we must generate a name, this is - //related to the previous code that generated the actual structures. - - string objecttypewords = ""; - - switch (od.objecttype) - { - - case ObjectType.RECORD: - objecttypewords = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); - break; - case ObjectType.ARRAY: - objecttypewords = t.ToString(); //this case is handled by the logic in eds.getdatatype(); - break; - default: - objecttypewords = t.ToString(); - break; - } - - string name = make_cname(od.parameter_name,od); - if (au[name] > 1) - { - if (lastname == name) - return ""; - - lastname = name; - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{au[name]}];"); - } - else - { - //Don't put sub indexes on record type in h file unless there are multiples of the same - //in which case its not handled here, we need a special case for the predefined special - //values that arrayspecial() checks for, to generate 1 element arrays if needed - if (od.objecttype == ObjectType.RECORD) - { - if (arrayspecial(od.Index, true)) - { - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[1];"); - } - else - { - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)};"); - } - } - else - { - string specialarraylength = ""; - - if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) - { - int maxlength = 0; - foreach (ODentry sub in od.subobjects.Values) - { - if (sub.Lengthofstring> maxlength) - maxlength = sub.Lengthofstring; - } - - if (maxlength == 0) - { - Warnings.AddWarning(string.Format(" Object children of 0x{0:X4} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index),Warnings.warning_class.WARNING_STRING); - maxlength = 1; - } - - - specialarraylength = string.Format("[{0}]", maxlength); - } - - sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{od.Nosubindexes - 1}]{specialarraylength};"); - } - } - } - - return sb.ToString(); - } - - private void addHeader(StreamWriter file) - { - file.WriteLine(string.Format( -@"/******************************************************************************* - CANopen Object Dictionary definition for CANopenNode v1 to v2 - - This file was automatically generated by CANopenEditor {0} - - https://github.com/CANopenNode/CANopenNode - https://github.com/CANopenNode/CANopenEditor - - DON'T EDIT THIS FILE MANUALLY !!!! -*******************************************************************************/", this.gitVersion)); - } - - private void export_h(string filename) - { - if (filename == "") - filename = "CO_OD"; - - StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".h"); - - file.WriteLine("// clang-format off"); - addHeader(file); - - file.WriteLine("#ifndef CO_OD_H_"); - file.WriteLine("#define CO_OD_H_"); - file.WriteLine(""); - - file.WriteLine(@"/******************************************************************************* - CANopen DATA TYPES -*******************************************************************************/ - typedef bool_t BOOLEAN; - typedef uint8_t UNSIGNED8; - typedef uint16_t UNSIGNED16; - typedef uint32_t UNSIGNED32; - typedef uint64_t UNSIGNED64; - typedef int8_t INTEGER8; - typedef int16_t INTEGER16; - typedef int32_t INTEGER32; - typedef int64_t INTEGER64; - typedef float32_t REAL32; - typedef float64_t REAL64; - typedef char_t VISIBLE_STRING; - typedef oChar_t OCTET_STRING; - - #ifdef DOMAIN - #undef DOMAIN - #endif - - typedef domain_t DOMAIN; - -"); - - file.WriteLine("/*******************************************************************************"); - file.WriteLine(" FILE INFO:"); - file.WriteLine(string.Format(" FileName: {0}", Path.GetFileName(eds.projectFilename))); - file.WriteLine(string.Format(" FileVersion: {0}", eds.fi.FileVersion)); - file.WriteLine(string.Format(" CreationTime: {0}", eds.fi.CreationTime)); - file.WriteLine(string.Format(" CreationDate: {0}", eds.fi.CreationDate)); - file.WriteLine(string.Format(" CreatedBy: {0}", eds.fi.CreatedBy)); - file.WriteLine("*******************************************************************************/"); - file.WriteLine(""); - file.WriteLine(""); - - file.WriteLine("/*******************************************************************************"); - file.WriteLine(" DEVICE INFO:"); - file.WriteLine(string.Format(" VendorName: {0}", eds.di.VendorName)); - file.WriteLine(string.Format(" VendorNumber: {0}", eds.di.VendorNumber)); - file.WriteLine(string.Format(" ProductName: {0}", eds.di.ProductName)); - file.WriteLine(string.Format(" ProductNumber: {0}", eds.di.ProductNumber)); - file.WriteLine("*******************************************************************************/"); - file.WriteLine(""); - file.WriteLine(""); - - file.WriteLine(@"/******************************************************************************* - FEATURES -*******************************************************************************/"); - - file.WriteLine(string.Format(" #define CO_NO_SYNC {0} //Associated objects: 1005-1007", noSYNC)); - - file.WriteLine(string.Format(" #define CO_NO_EMERGENCY {0} //Associated objects: 1014, 1015", noEMCY)); - - file.WriteLine(string.Format(" #define CO_NO_TIME {0} //Associated objects: 1012, 1013", noTIME)); - - file.WriteLine(string.Format(" #define CO_NO_SDO_SERVER {0} //Associated objects: 1200-127F", noSDOservers)); - file.WriteLine(string.Format(" #define CO_NO_SDO_CLIENT {0} //Associated objects: 1280-12FF", noSDOclients)); - - file.WriteLine(string.Format(" #define CO_NO_GFC {0} //Associated objects: 1300", noGFC)); - file.WriteLine(string.Format(" #define CO_NO_SRDO {0} //Associated objects: 1301-1341, 1381-13C0", noSRDO)); - - int lssServer = 0; - if (eds.di.LSS_Supported == true) - { - lssServer = 1; - } - file.WriteLine(string.Format(" #define CO_NO_LSS_SERVER {0} //LSS Slave", lssServer)); - int lssClient = 0; - if (eds.di.LSS_Master == true) - { - lssClient = 1; - } - file.WriteLine(string.Format(" #define CO_NO_LSS_CLIENT {0} //LSS Master", lssClient)); - - int ngSlave = 0; - if (eds.di.NG_Slave == true) - { - ngSlave = 1; - } - file.WriteLine(string.Format(" #define CO_NODE_GUARDING_SLAVE {0} //NG Slave", ngSlave)); - - file.WriteLine(string.Format(" #define CO_NODE_GUARDING_MASTER {0} //NG Master", eds.di.NrOfNG_MonitoredNodes)); - - file.WriteLine(string.Format(" #define CO_NO_RPDO {0} //Associated objects: 14xx, 16xx", noRXpdos)); - file.WriteLine(string.Format(" #define CO_NO_TPDO {0} //Associated objects: 18xx, 1Axx", noTXpdos)); - - bool ismaster = false; - if(ObjectActive(0x1f80)) - { - ODentry master = eds.ods[0x1f80]; - - // we could do with a cut down function that returns a value rather than a string - string meh = formatvaluewithdatatype(master.defaultvalue, master.datatype); - meh = meh.Replace("L", ""); - - UInt32 NMTStartup = Convert.ToUInt32(meh, 16); - if ((NMTStartup & 0x01) == 0x01) - ismaster = true; - } - - file.WriteLine(string.Format(" #define CO_NO_NMT_MASTER {0}", ismaster==true?1:0)); - file.WriteLine(string.Format(" #define CO_NO_TRACE 0")); - file.WriteLine(""); - file.WriteLine(""); - file.WriteLine(@"/******************************************************************************* - OBJECT DICTIONARY -*******************************************************************************/"); - - file.WriteLine(string.Format(" #define CO_OD_NoOfElements {0}", enabledcount)); - file.WriteLine(""); - file.WriteLine(""); - - file.WriteLine(@"/******************************************************************************* - TYPE DEFINITIONS FOR RECORDS -*******************************************************************************/"); - - //We need to identify all the record types used and generate a struct for each one - //FIXME the original CANopenNode exporter said how many items used this struct in the comments - - List structnamelist = new List(); - - /* make sure, we have all storage groups */ - eds.CO_storageGroups.Add("ROM"); - eds.CO_storageGroups.Add("EEPROM"); - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - /* make sure, we have all storage groups */ - eds.CO_storageGroups.Add(od.prop.CO_storageGroup); - - if (od.objecttype != ObjectType.RECORD) - continue; - - string structname = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); - - if (structnamelist.Contains(structname)) - continue; - - structnamelist.Add(structname); - - // we need to search the mappings to find the largest or this will not generate correctly - // as can opennode only has 1 structure defined for all mappings see #220 - - if (kvp.Key>=0x1600 && kvp.Key<0x1800) - { - //switch the OD entry to the largest - od = maxRXmappingsOD; - } - - if (kvp.Key >= 0x1A00 && kvp.Key < 0x1C00) - { - //switch the OD entry to the largest - od = maxTXmappingsOD; - } - - if (od == null) - continue; - - List structmemberlist = new List(); - - file.WriteLine(string.Format("/*{0:X4} */ typedef struct {{", kvp.Key)); - foreach (KeyValuePair kvp2 in od.subobjects) // kvp.Value.subobjects) - { - string paramaterarrlen = ""; - ODentry subod = kvp2.Value; - - string proposedname = make_cname(subod.parameter_name,subod); - - int suffix=1; - while (structmemberlist.Contains(proposedname)) - { - Warnings.AddWarning(string.Format("STRUCT WARNING; in 0x{0:X4}/{1:X2} Duplicate struct entry name, it has been auto numbered",subod.Index,subod.Subindex),Warnings.warning_class.WARNING_STRUCT); - proposedname = make_cname(subod.parameter_name,subod) + suffix.ToString(); - suffix++; - } - - structmemberlist.Add(proposedname); - - if (subod.datatype==DataType.VISIBLE_STRING || subod.datatype==DataType.OCTET_STRING) - { - paramaterarrlen = String.Format("[{0}]", subod.Lengthofstring); - } - - file.WriteLine(string.Format(" {0,-15}{1}{2};", subod.datatype.ToString(), proposedname,paramaterarrlen)); - - } - - file.WriteLine(string.Format(" }} {0};", structname)); - - } - - - - file.WriteLine(@" -/******************************************************************************* - TYPE DEFINITIONS FOR OBJECT DICTIONARY INDEXES - - some of those are redundant with CO_SDO.h CO_ObjDicId_t -*******************************************************************************/"); - - //FIXME how can we get rid of that redundancy? - - foreach (KeyValuePair kvp in eds.ods) - { - - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true) - continue; - - DataType t = eds.Getdatatype(od); - - - switch (od.objecttype) - { - default: - { - file.WriteLine(string.Format("/*{0:X4} */", od.Index)); - file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); - - file.WriteLine(""); - } - break; - - case ObjectType.ARRAY: - case ObjectType.RECORD: - { - file.WriteLine(string.Format("/*{0:X4} */", od.Index)); - file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); - - file.WriteLine(""); - - //sub indexes - file.WriteLine(string.Format(" #define {0,-51} 0", string.Format("OD_{0:X4}_0_{1}_maxSubIndex", od.Index, make_cname(od.parameter_name,od)))); - - List ODSIs = new List(); - - string ODSIout = ""; - - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry sub = kvp2.Value; - - if (kvp2.Key == 0) - continue; - - string ODSI = string.Format("{0}", string.Format("OD_{0:X4}_{1}_{2}_{3}", od.Index, kvp2.Key, make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); - - if (ODSIs.Contains(ODSI)) - { - continue; - } - - ODSIs.Add(ODSI); - - ODSIout += ($" #define {ODSI,-51} {kvp2.Key}{Environment.NewLine}"); - } - - file.Write(ODSIout); - file.WriteLine(""); - } - break; - } - } - - file.WriteLine(@"/******************************************************************************* - STRUCTURES FOR VARIABLES IN DIFFERENT MEMORY LOCATIONS -*******************************************************************************/ -#define CO_OD_FIRST_LAST_WORD 0x55 //Any value from 0x01 to 0xFE. If changed, EEPROM will be reinitialized. -"); - foreach (string location in eds.CO_storageGroups) - { - if (location == "Unused") - { - continue; - } - - file.Write("/***** Structure for "); - file.Write(location); - file.WriteLine(" variables ********************************************/"); - file.Write("struct sCO_OD_"); - file.Write(location); - file.Write(@"{ - UNSIGNED32 FirstWord; - -"); - - file.Write(print_h_bylocation(location)); - - file.WriteLine(@" - UNSIGNED32 LastWord; -}; -"); - } - - file.WriteLine(@"/***** Declaration of Object Dictionary variables *****************************/"); - - foreach (string location in eds.CO_storageGroups) - { - if (location == "Unused") - { - continue; - } - - file.Write("extern struct sCO_OD_"); - file.Write(location); - file.Write(" CO_OD_"); - file.Write(location); - file.WriteLine(@"; -"); - } - -file.WriteLine(@"/******************************************************************************* - ALIASES FOR OBJECT DICTIONARY VARIABLES -*******************************************************************************/"); - - List constructed_rec_types = new List(); - - foreach (KeyValuePair kvp in eds.ods) - { - - - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true) - continue; - - string loc = "CO_OD_" + od.prop.CO_storageGroup; - - DataType t = eds.Getdatatype(od); - - - switch (od.objecttype) - { - default: - { - file.WriteLine(string.Format("/*{0:X4}, Data Type: {1} */", od.Index, t.ToString())); - file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); - file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", make_cname(od.parameter_name,od)), loc, make_cname(od.parameter_name,od))); - - DataType dt = od.datatype; - - if (dt == DataType.OCTET_STRING || dt == DataType.VISIBLE_STRING) - { - file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_stringLength", make_cname(od.parameter_name,od)), od.Lengthofstring)); - } - file.WriteLine(""); - } - break; - - case ObjectType.ARRAY: - { - DataType dt = od.datatype; - - file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}, Array[{2}] */", od.Index, t.ToString(), od.Nosubindexes - 1)); - file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); - file.WriteLine(string.Format(" #define OD_{0,-48} {1}.{2}", make_cname(od.parameter_name,od), loc, make_cname(od.parameter_name,od))); - file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_arrayLength", make_cname(od.parameter_name,od)), od.Nosubindexes - 1)); - - - List ODAs = new List(); - - string ODAout = ""; - - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry sub = kvp2.Value; - - if (kvp2.Key == 0) - continue; - - string ODA = string.Format("{0}", string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); - - if (ODAs.Contains(ODA)) - { - continue; - } - - ODAs.Add(ODA); - - //Arrays do not have a size in the raw CO objects, Records do - //so offset by one - if (od.objecttype == ObjectType.ARRAY) - { - ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key - 1}{Environment.NewLine}"); - } - else - { - ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key}{Environment.NewLine}"); - } - } - - file.Write(ODAout); - file.WriteLine(""); - } - break; - - case ObjectType.RECORD: - { - string rectype = make_cname(od.parameter_name,od); - - if (!constructed_rec_types.Contains(rectype)) - { - file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}_t */", od.Index, rectype)); - file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); - file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", rectype), loc, rectype)); - constructed_rec_types.Add(rectype); - file.WriteLine(""); - } - - } - break; - } - } - file.WriteLine("#endif"); - file.WriteLine("// clang-format on"); - file.Close(); - - } - - private void export_c(string filename) - { - if (filename == "") - filename = "CO_OD"; - StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".c"); - - file.WriteLine("// clang-format off"); - addHeader(file); - file.WriteLine(@"// For CANopenNode V2 users, C macro `CO_VERSION_MAJOR=2` has to be added to project options -#ifndef CO_VERSION_MAJOR - #include ""CO_driver.h"" - #include """ + Path.GetFileNameWithoutExtension(filename) + @".h"" - #include ""CO_SDO.h"" -#elif CO_VERSION_MAJOR < 4 - #include ""301/CO_driver.h"" - #include """ + Path.GetFileNameWithoutExtension(filename) + @".h"" - #include ""301/CO_SDOserver.h"" -#else - #error This Object dictionary is not compatible with CANopenNode v4.0 and up! -#endif - -/******************************************************************************* - DEFINITION AND INITIALIZATION OF OBJECT DICTIONARY VARIABLES -*******************************************************************************/ - -"); - foreach (string location in eds.CO_storageGroups) - { - if (location == "Unused") - { - continue; - } - - file.Write("/***** Definition for "); - file.Write(location); - file.WriteLine(" variables *******************************************/"); - file.Write("struct sCO_OD_"); - file.Write(location); - file.Write(" CO_OD_"); - file.Write(location); - file.Write(@" = { - CO_OD_FIRST_LAST_WORD, - -"); - - file.Write(export_OD_def_array(location)); - - file.WriteLine(@" - CO_OD_FIRST_LAST_WORD, -}; - -"); - } - - - file.WriteLine(@" - -/******************************************************************************* - STRUCTURES FOR RECORD TYPE OBJECTS -*******************************************************************************/ - -"); - - file.Write(export_record_types()); - - file.Write(@"/******************************************************************************* - OBJECT DICTIONARY -*******************************************************************************/ -const CO_OD_entry_t CO_OD[CO_OD_NoOfElements] = { -"); - - file.Write(write_od()); - - file.WriteLine("};"); - file.WriteLine("// clang-format on"); - - file.Close(); - } - - bool arrayspecialcase = false; - int arrayspecialcasecount = 0; - - string write_od() - { - - StringBuilder returndata = new StringBuilder(); - - foreach (KeyValuePair kvp in eds.ods) - { - - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true) - continue; - - returndata.Append(write_od_line(od)); - - - } - - return returndata.ToString(); - } - - protected string write_od_line(ODentry od) - { - StringBuilder sb = new StringBuilder(); - - string loc = "CO_OD_" + od.prop.CO_storageGroup; - - byte flags = getflags(od); - - int datasize = od.objecttype == ObjectType.RECORD ? 0 : (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); - - string array = ""; - - //only needed for array objects - if (od.objecttype == ObjectType.ARRAY && od.Nosubindexes > 0) - array = string.Format("[0]"); - - - if (arrayspecial(od.Index, true)) - { - arrayspecialcase = true; - arrayspecialcasecount = 0; - } - - if (arrayspecialcase) - { - array = string.Format("[{0}]", arrayspecialcasecount); - arrayspecialcasecount++; - } - - //Arrays and Recs have 1 less subindex than actually present in the od.subobjects - int nosubindexs = od.Nosubindexes; - if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) - { - if (nosubindexs > 0) - nosubindexs--; - } - - //Arrays really should obey the max subindex parameter not the physical number of elements - if (od.objecttype == ObjectType.ARRAY) - { - if ((od.Getmaxsubindex() != nosubindexs)) - { - if (od.Index != 0x1003 && od.Index != 0x1011)//ignore 0x1003, it is a special case as per CANopen specs, and ignore 0x1011 CANopenNode uses special sub indexes for eeprom resets - { - Warnings.AddWarning(String.Format("Subindex discrepancy on object 0x{0:X4} arraysize: {1} vs max sub-index: {2}", od.Index, nosubindexs, od.Getmaxsubindex())); - } - - //0x1003 is a special case for CANopenNode - //SubIndex 0 will probably be 0 for no errors - //so we cannot read that to determine max subindex size, which is required to set up CANopenNode so we leave it alone here - //as its already set to subod.count - if (od.Index != 0x1003) - { - nosubindexs = od.Getmaxsubindex(); - } - } - } - - string pdata; //CO_OD_entry_t pData generator - - if (od.objecttype == ObjectType.RECORD) - { - - pdata = string.Format("&OD_record{0:X4}", od.Index); - } - else - { - pdata = string.Format("&{0}.{1}{2}", loc, make_cname(od.parameter_name,od), array); - } - - if ((od.objecttype == ObjectType.VAR || od.objecttype == ObjectType.ARRAY) && od.datatype == DataType.DOMAIN) - { - //NB domain MUST have a data pointer of 0, can open node requires this and makes checks - //against null to determine this is a DOMAIN type. - pdata = "0"; - } - - sb.AppendLine($"{{0x{od.Index:X4}, 0x{nosubindexs:X2}, 0x{flags:X2}, {datasize,2:#0}, (void*){pdata}}},"); - - if (arrayspecial(od.Index, false)) - { - arrayspecialcase = false; - } - - return sb.ToString(); - } - - /// - /// Get the CANopenNode specific flags, these flags are used internally in CANopenNode to determine details about the object variable - /// - /// An odentry to access - /// byte containing the flag value - public byte getflags(ODentry od) - { - byte flags = 0; - byte mapping = 0; //mapping flags, if pdo is enabled - - //aways return 0 for REC objects as CO_OD_getDataPointer() uses this to pickup the details - if (od.objecttype == ObjectType.RECORD) - return 0; - - switch((od.parent == null ? od : od.parent).prop.CO_storageGroup.ToUpper()) - { - case "ROM": - flags = 0x01; - break; - - case "RAM": - flags = 0x02; - break; - - case "EEPROM": - default: - flags = 0x03; - break; - } - - /* some exceptions for rwr/rww. Those are entries that are always r/w via SDO transfer, - * but can only be read -or- written via PDO */ - if (od.accesstype == EDSsharp.AccessType.ro - || od.accesstype == EDSsharp.AccessType.rw - || od.accesstype == EDSsharp.AccessType.rwr - || od.accesstype == EDSsharp.AccessType.rww - || od.accesstype == EDSsharp.AccessType.@const) - { - /* SDO server may read from the variable */ - flags |= 0x04; - - if (od.accesstype != EDSsharp.AccessType.rww) - { - /* Variable is mappable for TPDO */ - mapping |= 0x20; - } - } - if (od.accesstype == EDSsharp.AccessType.wo - || od.accesstype == EDSsharp.AccessType.rw - || od.accesstype == EDSsharp.AccessType.rwr - || od.accesstype == EDSsharp.AccessType.rww) - { - /* SDO server may write to the variable */ - flags |= 0x08; - - if (od.accesstype != EDSsharp.AccessType.rwr) - { - /* Variable is mappable for RPDO */ - mapping |= 0x10; - } - } - - if (od.Index == 0x1003) - { - /* SDO server may write to the variable */ - flags |= 0x08; - } - - switch (od.PDOtype) - { - case libEDSsharp.PDOMappingType.RPDO: mapping |= 0x10; break; - case libEDSsharp.PDOMappingType.TPDO: mapping |= 0x20; break; - case libEDSsharp.PDOMappingType.optional: mapping |= 0x30; break; - } - - if (od.PDOMapping) - { - flags |= mapping; - } - - if(od.prop.CO_flagsPDO) - { - /* If variable is mapped to any PDO, then is automatically send, if variable its value */ - flags |=0x40; - } - - if(od.parent!=null && od.parent.prop.CO_flagsPDO) - { - //parent types are storing the prop in the ODeditor in the parent object but the child object is tested to set the flag - //this is breaking legacy export - flags |= 0x40; - } - - - int datasize = (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); - - if (datasize > 1) - { - if (od.datatype == DataType.VISIBLE_STRING || - od.datatype == DataType.OCTET_STRING) - { - //#149 VISIBLE_STRING and OCTET_STRING are an arrays of 8 bit values, either VISIBLE_CHAR or UNSIGNED8 - //and therefor are NOT multi-byte - } - else - { - /* variable is a multi-byte value */ - flags |= 0x80; - } - } - - return flags; - } - - string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring=false) - { - try - { - int nobase = 10; - bool nodeidreplace = false; - - - if (defaultvalue == null || defaultvalue == "") - { - //No default value, we better supply one for sensible data types - if (dt == DataType.VISIBLE_STRING || - dt == DataType.OCTET_STRING || - dt == DataType.UNKNOWN || - dt == DataType.UNICODE_STRING) - { - - if (fixstring == true) - return "'X'"; - - return ""; - } - - Console.WriteLine("Warning assuming a 0 default"); - defaultvalue = "0"; - } - - if (defaultvalue.Contains("$NODEID", StringComparison.OrdinalIgnoreCase)) // fetch different case of "NODeID" (allowed according DS301) - { - defaultvalue = defaultvalue.ToUpper().Replace("$NODEID", ""); - defaultvalue = defaultvalue.Replace("+", ""); - defaultvalue = defaultvalue.Trim(); - nodeidreplace = true; - } - - String pat = @"^0[xX][0-9a-fA-FL]+"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 16; - defaultvalue = defaultvalue.Replace("L", ""); - } - - pat = @"^0[0-7]+"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(defaultvalue); - if (m.Success) - { - nobase = 8; - } - - if (nodeidreplace) - { - UInt32 data = Convert.ToUInt32(defaultvalue.Trim(), nobase); - data += eds.NodeID; - defaultvalue = string.Format("0x{0:X}", data); - nobase = 16; - } - - - switch (dt) - { - case DataType.UNSIGNED24: - case DataType.UNSIGNED32: - return String.Format("0x{0:X4}L", Convert.ToUInt32(defaultvalue, nobase)); - - case DataType.INTEGER24: - case DataType.INTEGER32: - return String.Format("0x{0:X4}L", Convert.ToInt32(defaultvalue, nobase)); - - case DataType.REAL32: - case DataType.REAL64: - return (String.Format("{0}", defaultvalue)); - - - //fix me this looks wrong - case DataType.UNICODE_STRING: - return (String.Format("'{0}'", defaultvalue)); - - case DataType.VISIBLE_STRING: - { - - ASCIIEncoding a = new ASCIIEncoding(); - string unescape = StringUnescape.Unescape(defaultvalue); - char[] chars = unescape.ToCharArray(); - - string array = "{"; - - foreach (char c in chars) - { - - array += "'" + StringUnescape.Escape(c) + "', "; - } - - array = array.Substring(0, array.Length - 2); - - array += "}"; - return array; - - } - - - case DataType.OCTET_STRING: - { - string[] bits = defaultvalue.Split(' '); - string octet = "{"; - foreach (string s in bits) - { - octet += formatvaluewithdatatype(s, DataType.UNSIGNED8); - - if (!object.ReferenceEquals(s, bits.Last())) - { - octet += ", "; - } - } - octet += "}"; - return octet; - } - - case DataType.INTEGER8: - return String.Format("0x{0:X1}", Convert.ToSByte(defaultvalue, nobase)); - - case DataType.INTEGER16: - return String.Format("0x{0:X2}", Convert.ToInt16(defaultvalue, nobase)); - - case DataType.UNSIGNED8: - return String.Format("0x{0:X1}L", Convert.ToByte(defaultvalue, nobase)); - - case DataType.UNSIGNED16: - return String.Format("0x{0:X2}", Convert.ToUInt16(defaultvalue, nobase)); - - case DataType.INTEGER64: - return String.Format("0x{0:X8}L", Convert.ToInt64(defaultvalue, nobase)); - - case DataType.UNSIGNED64: - return String.Format("0x{0:X8}L", Convert.ToUInt64(defaultvalue, nobase)); - - case DataType.TIME_DIFFERENCE: - case DataType.TIME_OF_DAY: - return String.Format("{{{0}}}", Convert.ToUInt64(defaultvalue, nobase)); - - default: - return (String.Format("{0:X}", defaultvalue)); - - } - } - catch(Exception) - { - Warnings.AddWarning(String.Format("Error converting value {0} to type {1}", defaultvalue, dt.ToString()),Warnings.warning_class.WARNING_BUILD); - return ""; - } - } - - public static string ParseString(string input) - { - var provider = new Microsoft.CSharp.CSharpCodeProvider(); - var parameters = new System.CodeDom.Compiler.CompilerParameters() - { - GenerateExecutable = false, - GenerateInMemory = true, - }; - - var code = @" - namespace Tmp - { - public class TmpClass - { - public static string GetValue() - { - return """ + input + @"""; - } - } - }"; - - var compileResult = provider.CompileAssemblyFromSource(parameters, code); - - if (compileResult.Errors.HasErrors) - { - throw new ArgumentException(compileResult.Errors.Cast().First(e => !e.IsWarning).ErrorText); - } - - var asmb = compileResult.CompiledAssembly; - var method = asmb.GetType("Tmp.TmpClass").GetMethod("GetValue"); - - return method.Invoke(null, null) as string; - } - - protected string make_cname(string name,ODentry entry) - { - if (name == null) - return null; - - if (name == "") - return ""; - - Regex splitter = new Regex(@"[\W]+"); - - //string[] bits = Regex.Split(name,@"[\W]+"); - var bits = splitter.Split(name).Where(s => s != String.Empty); - - string output = ""; - - char lastchar = ' '; - foreach (string s in bits) - { - if(Char.IsUpper(lastchar) && Char.IsUpper(s.First())) - output+="_"; - - if (s.Length > 1) - { - output += char.ToUpper(s[0]) + s.Substring(1); - } - else - { - output += s; - } - - if(output.Length>0) - lastchar = output.Last(); - - } - - if (output.Length > 1) - { - if (Char.IsLower(output[1])) - output = Char.ToLowerInvariant(output[0]) + output.Substring(1); - } - else - output = output.ToLowerInvariant(); //single character - - - UInt32 key = (UInt32)((entry.Index << 8) + entry.Subindex ); - - if ((entry.Index >= 0x1200) && (entry.Index < 0x1280)) - key = (UInt32)((0x1200 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1280) && (entry.Index < 0x1300)) - key = (UInt32)((0x1280 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1400) && (entry.Index < 0x1600)) - key = (UInt32)((0x1400 <<8) + entry.Subindex); - - if ((entry.Index >= 0x1600) && (entry.Index < 0x1800)) - key = (UInt32)((0x1600 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1800) && (entry.Index < 0x1a00)) - key = (UInt32)((0x1800 << 8) + entry.Subindex); - - if ((entry.Index >= 0x1a00) && (entry.Index < 0x1c00)) - key = (UInt32)((0x1a00 << 8) + entry.Subindex); - - if (acceptable_canopen_names.ContainsKey(key) && !(entry.parent != null && entry.Subindex == 0)) - { - string newname = acceptable_canopen_names[key]; - if (output != newname) - Warnings.AddWarning(string.Format("Warning: index 0x{0:X4}/{1:X2} correcting name for CanOpenNode compatibility from {2} to {3}", entry.Index, entry.Subindex, output, newname),Warnings.warning_class.WARNING_RENAME); - output = newname; - } - - return output; - } - - /// - /// Export the record type objects in the CO_OD.c file - /// - /// string - protected string export_record_types() - { - StringBuilder returndata = new StringBuilder(); - - bool arrayopen = false; - int arrayindex = 0; - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - if (od.objecttype != ObjectType.RECORD) - continue; - - if (od.prop.CO_disabled == true) - continue; - - int count = od.subobjects.Count; //don't include index - - if(od.Index>=0x1400 && od.Index<0x1600) - { - //what is this doing for us? - //count = 3; //CANopenNode Fudging. Its only 3 parameters for RX PDOS in the c code despite being a PDO_COMMUNICATION_PARAMETER - } - - returndata.AppendLine($"/*0x{od.Index:X4}*/ const CO_OD_entryRecord_t OD_record{od.Index:X4}[{count}] = {{"); - - string arrayaccess = ""; - - if (arrayspecial(od.Index, true) || arrayopen) - { - arrayaccess = string.Format("[{0}]",arrayindex); - arrayindex++; - arrayopen = true; - } - - foreach (KeyValuePair kvpsub in od.subobjects) - { - returndata.Append(export_one_record_type(kvpsub.Value,arrayaccess)); - } - - if (arrayspecial(od.Index, false)) - { - arrayindex=0; - arrayopen = false; - } - - returndata.AppendLine($"}};{Environment.NewLine}"); - } - - return returndata.ToString(); - } - - /// - /// Exports a sub object line in a record object - /// - /// sub ODentry object to export - /// string forming current array level or empty string for none - /// string forming one line of CO_OD.c record objects - protected string export_one_record_type(ODentry sub,string arrayaccess) - { - - if (sub == null || sub.parent == null) - return ""; - - StringBuilder sb = new StringBuilder(); - - string cname = make_cname(sub.parent.parameter_name,sub.parent); - - string subcname = make_cname(sub.parameter_name,sub); - int datasize = (int)Math.Ceiling((double)sub.Sizeofdatatype() / (double)8.0); - - if (sub.datatype != DataType.DOMAIN) - { - sb.AppendLine($" {{(void*)&{"CO_OD_" + sub.parent.prop.CO_storageGroup}.{cname}{arrayaccess}.{subcname}, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); - } - else - { - //Domain type MUST have its data pointer set to 0 for CANopenNode - sb.AppendLine($" {{(void*)0, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); - } - - return sb.ToString(); - } - - - int noTXpdos = 0; - int noRXpdos = 0; - int noSDOclients = 0; - int noSDOservers = 0; - int distTXpdo = 0; - int distRXpdo = 0; - int noSYNC = 0; - int noEMCY = 0; - int noTIME = 0; - int noGFC = 0; - int noSRDO = 0; - - void countPDOS() - { - noRXpdos = 0; - noTXpdos = 0; - - //feature tests for default CanOpenNode build - //if you have a custom CanOpen.c then you may not require all these features - - //check the SYNC feature - int checkfeature = 0; - if (ObjectActive(0x1005)) - checkfeature++; - if (ObjectActive(0x1006)) - checkfeature++; - if (ObjectActive(0x1007)) - checkfeature++; - if (ObjectActive(0x1019)) - checkfeature++; - if (checkfeature == 4) - { - noSYNC = 1; - } - else - { - Warnings.AddWarning("BUILD WARNING, required objects for SYNC are not present 0x1005,0x1006,0x1007,0x1019",Warnings.warning_class.WARNING_BUILD); - } - - //EMCY - checkfeature = 0; - if (ObjectActive(0x1003)) - checkfeature++; - if (ObjectActive(0x1014)) - checkfeature++; - if (ObjectActive(0x1015)) - checkfeature++; - if (checkfeature == 3) - { - noEMCY = 1; - } - else - { - Warnings.AddWarning("BUILD WARNING, required objects for EMCY are not present 0x1003,0x1014,0x1015",Warnings.warning_class.WARNING_BUILD); - } - - //TIME - if (ObjectActive(0x1012)) - { - noTIME = 1; - } - else - { - //TIME is optional - } - - //NMT CLIENT - checkfeature = 0; - if (ObjectActive(0x1f80)) - checkfeature ++; - if (ObjectActive(0x1029)) - checkfeature ++; - if (ObjectActive(0x1017)) - checkfeature ++; - if (ObjectActive(0x1001)) - checkfeature ++; - if (checkfeature == 4) - { - //NMT Client is not optional - } - else - { - Warnings.AddWarning("BUILD WARNING, required objects for NMT Client are not present 0x1f80,0x1029,0x1017,0x1001",Warnings.warning_class.WARNING_BUILD); - } - - foreach (KeyValuePair kvp in eds.ods) - { - UInt16 index = kvp.Key; - - if (kvp.Value.prop.CO_disabled == true) - continue; - - if (index >= 0x1400 && index < 0x1600) - { - noRXpdos++; - distRXpdo = index - 0x1400; - } - - if (index >= 0x1800 && index < 0x1A00) - { - noTXpdos++; - distTXpdo = index - 0x1800; - } - - if((index & 0xFF80) == 0x1200) - { - noSDOservers++; - } - - if ((index & 0xFF80) == 0x1280) - { - noSDOclients++; - } - - if (index == 0x1300) - noGFC = 1; - - if (index >= 0x1301 && index <= 0x1340) - noSRDO++; - } - } - - bool arrayspecial(UInt16 index, bool open) - { - - if (open) - { - - if (openings.Contains(index)) - return true; - } - else - { - - if (closings.Contains(index)) - return true; - } - - return false; - } - - - string export_OD_def_array(string location) - { - - StringBuilder sb = new StringBuilder(); - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) - continue; - - if (od.Nosubindexes == 0) - { - sb.AppendLine($"/*{od.Index:X4}*/ {formatvaluewithdatatype(od.defaultvalue, od.datatype,true)},"); - } - else - { - if (arrayspecial(od.Index, true)) - { - sb.AppendFormat("/*{0:X4}*/ {{{{", od.Index); - } - else - { - sb.AppendFormat("/*{0:X4}*/ {{", od.Index); - } - - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry sub = kvp2.Value; - - DataType dt = sub.datatype; - - if ((od.objecttype==ObjectType.ARRAY) && kvp2.Key == 0) - continue; - - sb.Append(formatvaluewithdatatype(sub.defaultvalue, dt,true)); - - if (od.subobjects.Keys.Last() != kvp2.Key) - sb.Append(", "); - } - - if (arrayspecial(od.Index, false)) - { - sb.AppendLine("}},"); - } - else - { - sb.AppendLine("},"); - } - } - } - - return sb.ToString(); - } - } - - - - - - -} +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius + based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are + Copyright(c) 2010 - 2016 Janez Paternoster +*/ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using System.IO; + + + +namespace libEDSsharp +{ + + public class CanOpenNodeExporter : IExporter + { + + private string folderpath; + private string gitVersion; + protected EDSsharp eds; + + private int enabledcount = 0; + + Dictionary acceptable_canopen_names = new Dictionary(); + + //Used for array tracking + Dictionary au = new Dictionary(); + List openings = new List(); + List closings = new List(); + + private byte maxRXmappingsize = 0; + private byte maxTXmappingsize = 0; + ODentry maxRXmappingsOD=null; + ODentry maxTXmappingsOD=null; + + + public void prepareCanOpenNames() + { + acceptable_canopen_names.Add(0x101800, "identity"); + + acceptable_canopen_names.Add(0x140000, "RPDOCommunicationParameter"); + acceptable_canopen_names.Add(0x160000, "RPDOMappingParameter"); + acceptable_canopen_names.Add(0x180000, "TPDOCommunicationParameter"); + acceptable_canopen_names.Add(0x1a0000, "TPDOMappingParameter"); + + acceptable_canopen_names.Add(0x100500, "COB_ID_SYNCMessage"); + + + + acceptable_canopen_names.Add(0x101801, "vendorID"); + acceptable_canopen_names.Add(0x101802, "productCode"); + acceptable_canopen_names.Add(0x101803, "revisionNumber"); + acceptable_canopen_names.Add(0x101804, "serialNumber"); + + acceptable_canopen_names.Add(0x120000, "SDOServerParameter"); + acceptable_canopen_names.Add(0x120001, "COB_IDClientToServer"); + acceptable_canopen_names.Add(0x120002, "COB_IDServerToClient"); + + acceptable_canopen_names.Add(0x128000, "SDOClientParameter"); + acceptable_canopen_names.Add(0x128001, "COB_IDClientToServer"); + acceptable_canopen_names.Add(0x128002, "COB_IDServerToClient"); + + acceptable_canopen_names.Add(0x102900, "errorBehavior"); + + } + + + public void export(string folderpath, string filename, string gitVersion, EDSsharp eds,string odname) + { + this.folderpath = folderpath; + this.gitVersion = gitVersion; + this.eds = eds; + + + enabledcount = eds.GetNoEnabledObjects(); + + prepareCanOpenNames(); + + countPDOS(); + + + fixcompatentry(); + + prewalkArrays(); + + export_h(filename); + export_c(filename); + + } + + private void fixcompatentry() + { + // Handle the TPDO communication parameters in a special way, because of + // sizeof(OD_TPDOCommunicationParameter_t) != sizeof(CO_TPDOCommPar_t) in CANopen.c + // the existing CO_TPDOCommPar_t has a compatibility entry so we must export one regardless + // of if its in the OD or not + + for (UInt16 idx = 0x1800; idx < 0x1900; idx++) + { + if (ObjectActive(idx)) + { + ODentry od = eds.ods[idx]; + + if (!od.Containssubindex(0x04)) + { + ODentry compatibility = new ODentry("compatibility entry", idx, DataType.UNSIGNED8, "0", EDSsharp.AccessType.ro, PDOMappingType.no, od); + od.subobjects.Add(0x04, compatibility); + } + } + } + + } + + private void specialarraysearch(UInt16 start, UInt16 end) + { + UInt16 lowest = 0xffff; + UInt16 highest = 0x0000; + + foreach (KeyValuePair kvp in eds.ods) + { + + if (kvp.Value.prop.CO_disabled == true) + continue; + + if (kvp.Key >= start && kvp.Key <= end) + { + if (kvp.Key > highest) + highest = kvp.Key; + + if (kvp.Key < lowest) + lowest = kvp.Key; + } + } + + if(lowest!=0xffff && highest!=0x0000) + { + openings.Add(lowest); + closings.Add(highest); + + Console.WriteLine(string.Format("New special array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); + } + } + + public bool ObjectActive(UInt16 index) + { + if (eds.ods.ContainsKey(index)) + { + return !eds.ods[index].prop.CO_disabled; + } + else return false; + } + + protected void prewalkArrays() + { + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + if (od.prop.CO_disabled == true) + continue; + + string name = make_cname(od.parameter_name,od); + if (au.ContainsKey(name)) + { + au[name]++; + } + else + { + au[name] = 1; + } + } + + + //Handle special arrays + + specialarraysearch(0x1301, 0x1340); + specialarraysearch(0x1381, 0x13C0); + + + //SDO Client parameters + specialarraysearch(0x1200, 0x127F); + //SDO Server Parameters + specialarraysearch(0x1280, 0x12FF); + + //PDO Mappings and configs + specialarraysearch(0x1400, 0x15FF); + specialarraysearch(0x1600, 0x17FF); + specialarraysearch(0x1800, 0x19FF); + specialarraysearch(0x1A00, 0x1BFF); + + //now find opening and closing points for these arrays + foreach (KeyValuePair kvp in au) + { + if ( kvp.Value > 1) + { + string targetname = kvp.Key; + UInt16 lowest=0xffff; + UInt16 highest=0x0000; + foreach (KeyValuePair kvp2 in eds.ods) + { + + string name = make_cname(kvp2.Value.parameter_name,kvp2.Value); + if(name==targetname) + { + if (kvp2.Key > highest) + highest = kvp2.Key; + + if (kvp2.Key < lowest) + lowest = kvp2.Key; + } + + } + + if (!openings.Contains(lowest)) + { + openings.Add(lowest); + closings.Add(highest); + Console.WriteLine(string.Format("New array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); + } + + } + + } + + //Find maximum no entries in a mapping config to define an appropriate array + maxRXmappingsize = 0; + maxTXmappingsize = 0; + + for (ushort x=0x1600;x<0x1800;x++) + { + if(ObjectActive(x)) + { + byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); + + if(maxcount > maxRXmappingsize) + { + maxRXmappingsize = maxcount; + maxRXmappingsOD = eds.ods[x]; + } + } + } + + for (ushort x = 0x1a00; x < 0x1c00; x++) + { + if (ObjectActive(x)) + { + byte maxcount = EDSsharp.ConvertToByte(eds.ods[x].subobjects[0].defaultvalue); + + if (maxcount > maxTXmappingsize) + { + maxTXmappingsize = maxcount; + maxTXmappingsOD = eds.ods[x]; + } + } + } + } + + string lastname = ""; + + private string print_h_bylocation(string location) + { + + StringBuilder sb = new StringBuilder(); + + lastname = ""; + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) + continue; + + sb.Append(print_h_entry(od)); + + } + + return sb.ToString(); + } + + + protected string print_h_entry(ODentry od) + { + StringBuilder sb = new StringBuilder(); + + if (od.Nosubindexes == 0) + { + string specialarraylength = ""; + if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) + { + + if (od.Lengthofstring == 0) + { + Warnings.AddWarning(string.Format(" Object 0x{0:X4}/{1:X2} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index, od.Subindex),Warnings.warning_class.WARNING_STRING); + specialarraylength = "[1]"; + } + else + { + specialarraylength = string.Format("[{0}]", od.Lengthofstring); + } + } + + sb.AppendLine($"/*{od.Index:X4} */ {od.datatype.ToString(),-14} {make_cname(od.parameter_name,od)}{specialarraylength};"); + } + else + { + //fixme why is this not od.datatype? + DataType t = eds.Getdatatype(od); + + //If it not a defined type, and it probably is not for a REC, we must generate a name, this is + //related to the previous code that generated the actual structures. + + string objecttypewords = ""; + + switch (od.objecttype) + { + + case ObjectType.RECORD: + objecttypewords = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); + break; + case ObjectType.ARRAY: + objecttypewords = t.ToString(); //this case is handled by the logic in eds.getdatatype(); + break; + default: + objecttypewords = t.ToString(); + break; + } + + string name = make_cname(od.parameter_name,od); + if (au[name] > 1) + { + if (lastname == name) + return ""; + + lastname = name; + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{au[name]}];"); + } + else + { + //Don't put sub indexes on record type in h file unless there are multiples of the same + //in which case its not handled here, we need a special case for the predefined special + //values that arrayspecial() checks for, to generate 1 element arrays if needed + if (od.objecttype == ObjectType.RECORD) + { + if (arrayspecial(od.Index, true)) + { + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[1];"); + } + else + { + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)};"); + } + } + else + { + string specialarraylength = ""; + + if (od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.OCTET_STRING || od.datatype == DataType.UNICODE_STRING) + { + int maxlength = 0; + foreach (ODentry sub in od.subobjects.Values) + { + if (sub.Lengthofstring> maxlength) + maxlength = sub.Lengthofstring; + } + + if (maxlength == 0) + { + Warnings.AddWarning(string.Format(" Object children of 0x{0:X4} A string must have a default value to set the required datasize for canopen node, i have set this to [1] byte to prevent compile errors", od.Index),Warnings.warning_class.WARNING_STRING); + maxlength = 1; + } + + + specialarraylength = string.Format("[{0}]", maxlength); + } + + sb.AppendLine($"/*{od.Index:X4} */ {objecttypewords,-15} {make_cname(od.parameter_name,od)}[{od.Nosubindexes - 1}]{specialarraylength};"); + } + } + } + + return sb.ToString(); + } + + private void addHeader(StreamWriter file) + { + file.WriteLine(string.Format( +@"/******************************************************************************* + CANopen Object Dictionary definition for CANopenNode v1 to v2 + + This file was automatically generated by CANopenEditor {0} + + https://github.com/CANopenNode/CANopenNode + https://github.com/CANopenNode/CANopenEditor + + DON'T EDIT THIS FILE MANUALLY !!!! +*******************************************************************************/", this.gitVersion)); + } + + private void export_h(string filename) + { + if (filename == "") + filename = "CO_OD"; + + StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".h"); + + file.WriteLine("// clang-format off"); + addHeader(file); + + file.WriteLine("#ifndef CO_OD_H_"); + file.WriteLine("#define CO_OD_H_"); + file.WriteLine(""); + + file.WriteLine(@"/******************************************************************************* + CANopen DATA TYPES +*******************************************************************************/ + typedef bool_t BOOLEAN; + typedef uint8_t UNSIGNED8; + typedef uint16_t UNSIGNED16; + typedef uint32_t UNSIGNED32; + typedef uint64_t UNSIGNED64; + typedef int8_t INTEGER8; + typedef int16_t INTEGER16; + typedef int32_t INTEGER32; + typedef int64_t INTEGER64; + typedef float32_t REAL32; + typedef float64_t REAL64; + typedef char_t VISIBLE_STRING; + typedef oChar_t OCTET_STRING; + + #ifdef DOMAIN + #undef DOMAIN + #endif + + typedef domain_t DOMAIN; + +"); + + file.WriteLine("/*******************************************************************************"); + file.WriteLine(" FILE INFO:"); + file.WriteLine(string.Format(" FileName: {0}", Path.GetFileName(eds.projectFilename))); + file.WriteLine(string.Format(" FileVersion: {0}", eds.fi.FileVersion)); + file.WriteLine(string.Format(" CreationTime: {0}", eds.fi.CreationTime)); + file.WriteLine(string.Format(" CreationDate: {0}", eds.fi.CreationDate)); + file.WriteLine(string.Format(" CreatedBy: {0}", eds.fi.CreatedBy)); + file.WriteLine("*******************************************************************************/"); + file.WriteLine(""); + file.WriteLine(""); + + file.WriteLine("/*******************************************************************************"); + file.WriteLine(" DEVICE INFO:"); + file.WriteLine(string.Format(" VendorName: {0}", eds.di.VendorName)); + file.WriteLine(string.Format(" VendorNumber: {0}", eds.di.VendorNumber)); + file.WriteLine(string.Format(" ProductName: {0}", eds.di.ProductName)); + file.WriteLine(string.Format(" ProductNumber: {0}", eds.di.ProductNumber)); + file.WriteLine("*******************************************************************************/"); + file.WriteLine(""); + file.WriteLine(""); + + file.WriteLine(@"/******************************************************************************* + FEATURES +*******************************************************************************/"); + + file.WriteLine(string.Format(" #define CO_NO_SYNC {0} //Associated objects: 1005-1007", noSYNC)); + + file.WriteLine(string.Format(" #define CO_NO_EMERGENCY {0} //Associated objects: 1014, 1015", noEMCY)); + + file.WriteLine(string.Format(" #define CO_NO_TIME {0} //Associated objects: 1012, 1013", noTIME)); + + file.WriteLine(string.Format(" #define CO_NO_SDO_SERVER {0} //Associated objects: 1200-127F", noSDOservers)); + file.WriteLine(string.Format(" #define CO_NO_SDO_CLIENT {0} //Associated objects: 1280-12FF", noSDOclients)); + + file.WriteLine(string.Format(" #define CO_NO_GFC {0} //Associated objects: 1300", noGFC)); + file.WriteLine(string.Format(" #define CO_NO_SRDO {0} //Associated objects: 1301-1341, 1381-13C0", noSRDO)); + + int lssServer = 0; + if (eds.di.LSS_Supported == true) + { + lssServer = 1; + } + file.WriteLine(string.Format(" #define CO_NO_LSS_SERVER {0} //LSS Slave", lssServer)); + int lssClient = 0; + if (eds.di.LSS_Master == true) + { + lssClient = 1; + } + file.WriteLine(string.Format(" #define CO_NO_LSS_CLIENT {0} //LSS Master", lssClient)); + + int ngSlave = 0; + if (eds.di.NG_Slave == true) + { + ngSlave = 1; + } + file.WriteLine(string.Format(" #define CO_NODE_GUARDING_SLAVE {0} //NG Slave", ngSlave)); + + file.WriteLine(string.Format(" #define CO_NODE_GUARDING_MASTER {0} //NG Master", eds.di.NrOfNG_MonitoredNodes)); + + file.WriteLine(string.Format(" #define CO_NO_RPDO {0} //Associated objects: 14xx, 16xx", noRXpdos)); + file.WriteLine(string.Format(" #define CO_NO_TPDO {0} //Associated objects: 18xx, 1Axx", noTXpdos)); + + bool ismaster = false; + if(ObjectActive(0x1f80)) + { + ODentry master = eds.ods[0x1f80]; + + // we could do with a cut down function that returns a value rather than a string + string meh = formatvaluewithdatatype(master.defaultvalue, master.datatype); + meh = meh.Replace("L", ""); + + UInt32 NMTStartup = Convert.ToUInt32(meh, 16); + if ((NMTStartup & 0x01) == 0x01) + ismaster = true; + } + + file.WriteLine(string.Format(" #define CO_NO_NMT_MASTER {0}", ismaster==true?1:0)); + file.WriteLine(string.Format(" #define CO_NO_TRACE 0")); + file.WriteLine(""); + file.WriteLine(""); + file.WriteLine(@"/******************************************************************************* + OBJECT DICTIONARY +*******************************************************************************/"); + + file.WriteLine(string.Format(" #define CO_OD_NoOfElements {0}", enabledcount)); + file.WriteLine(""); + file.WriteLine(""); + + file.WriteLine(@"/******************************************************************************* + TYPE DEFINITIONS FOR RECORDS +*******************************************************************************/"); + + //We need to identify all the record types used and generate a struct for each one + //FIXME the original CANopenNode exporter said how many items used this struct in the comments + + List structnamelist = new List(); + + /* make sure, we have all storage groups */ + eds.CO_storageGroups.Add("ROM"); + eds.CO_storageGroups.Add("EEPROM"); + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + /* make sure, we have all storage groups */ + eds.CO_storageGroups.Add(od.prop.CO_storageGroup); + + if (od.objecttype != ObjectType.RECORD) + continue; + + string structname = String.Format("OD_{0}_t", make_cname(od.parameter_name,od)); + + if (structnamelist.Contains(structname)) + continue; + + structnamelist.Add(structname); + + // we need to search the mappings to find the largest or this will not generate correctly + // as can opennode only has 1 structure defined for all mappings see #220 + + if (kvp.Key>=0x1600 && kvp.Key<0x1800) + { + //switch the OD entry to the largest + od = maxRXmappingsOD; + } + + if (kvp.Key >= 0x1A00 && kvp.Key < 0x1C00) + { + //switch the OD entry to the largest + od = maxTXmappingsOD; + } + + if (od == null) + continue; + + List structmemberlist = new List(); + + file.WriteLine(string.Format("/*{0:X4} */ typedef struct {{", kvp.Key)); + foreach (KeyValuePair kvp2 in od.subobjects) // kvp.Value.subobjects) + { + string paramaterarrlen = ""; + ODentry subod = kvp2.Value; + + string proposedname = make_cname(subod.parameter_name,subod); + + int suffix=1; + while (structmemberlist.Contains(proposedname)) + { + Warnings.AddWarning(string.Format("STRUCT WARNING; in 0x{0:X4}/{1:X2} Duplicate struct entry name, it has been auto numbered",subod.Index,subod.Subindex),Warnings.warning_class.WARNING_STRUCT); + proposedname = make_cname(subod.parameter_name,subod) + suffix.ToString(); + suffix++; + } + + structmemberlist.Add(proposedname); + + if (subod.datatype==DataType.VISIBLE_STRING || subod.datatype==DataType.OCTET_STRING) + { + paramaterarrlen = String.Format("[{0}]", subod.Lengthofstring); + } + + file.WriteLine(string.Format(" {0,-15}{1}{2};", subod.datatype.ToString(), proposedname,paramaterarrlen)); + + } + + file.WriteLine(string.Format(" }} {0};", structname)); + + } + + + + file.WriteLine(@" +/******************************************************************************* + TYPE DEFINITIONS FOR OBJECT DICTIONARY INDEXES + + some of those are redundant with CO_SDO.h CO_ObjDicId_t +*******************************************************************************/"); + + //FIXME how can we get rid of that redundancy? + + foreach (KeyValuePair kvp in eds.ods) + { + + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true) + continue; + + DataType t = eds.Getdatatype(od); + + + switch (od.objecttype) + { + default: + { + file.WriteLine(string.Format("/*{0:X4} */", od.Index)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); + + file.WriteLine(""); + } + break; + + case ObjectType.ARRAY: + case ObjectType.RECORD: + { + file.WriteLine(string.Format("/*{0:X4} */", od.Index)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0:X4}_{1}", od.Index, make_cname(od.parameter_name,od)), od.Index, t.ToString())); + + file.WriteLine(""); + + //sub indexes + file.WriteLine(string.Format(" #define {0,-51} 0", string.Format("OD_{0:X4}_0_{1}_maxSubIndex", od.Index, make_cname(od.parameter_name,od)))); + + List ODSIs = new List(); + + string ODSIout = ""; + + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry sub = kvp2.Value; + + if (kvp2.Key == 0) + continue; + + string ODSI = string.Format("{0}", string.Format("OD_{0:X4}_{1}_{2}_{3}", od.Index, kvp2.Key, make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); + + if (ODSIs.Contains(ODSI)) + { + continue; + } + + ODSIs.Add(ODSI); + + ODSIout += ($" #define {ODSI,-51} {kvp2.Key}{Environment.NewLine}"); + } + + file.Write(ODSIout); + file.WriteLine(""); + } + break; + } + } + + file.WriteLine(@"/******************************************************************************* + STRUCTURES FOR VARIABLES IN DIFFERENT MEMORY LOCATIONS +*******************************************************************************/ +#define CO_OD_FIRST_LAST_WORD 0x55 //Any value from 0x01 to 0xFE. If changed, EEPROM will be reinitialized. +"); + foreach (string location in eds.CO_storageGroups) + { + if (location == "Unused") + { + continue; + } + + file.Write("/***** Structure for "); + file.Write(location); + file.WriteLine(" variables ********************************************/"); + file.Write("struct sCO_OD_"); + file.Write(location); + file.Write(@"{ + UNSIGNED32 FirstWord; + +"); + + file.Write(print_h_bylocation(location)); + + file.WriteLine(@" + UNSIGNED32 LastWord; +}; +"); + } + + file.WriteLine(@"/***** Declaration of Object Dictionary variables *****************************/"); + + foreach (string location in eds.CO_storageGroups) + { + if (location == "Unused") + { + continue; + } + + file.Write("extern struct sCO_OD_"); + file.Write(location); + file.Write(" CO_OD_"); + file.Write(location); + file.WriteLine(@"; +"); + } + +file.WriteLine(@"/******************************************************************************* + ALIASES FOR OBJECT DICTIONARY VARIABLES +*******************************************************************************/"); + + List constructed_rec_types = new List(); + + foreach (KeyValuePair kvp in eds.ods) + { + + + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true) + continue; + + string loc = "CO_OD_" + od.prop.CO_storageGroup; + + DataType t = eds.Getdatatype(od); + + + switch (od.objecttype) + { + default: + { + file.WriteLine(string.Format("/*{0:X4}, Data Type: {1} */", od.Index, t.ToString())); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); + file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", make_cname(od.parameter_name,od)), loc, make_cname(od.parameter_name,od))); + + DataType dt = od.datatype; + + if (dt == DataType.OCTET_STRING || dt == DataType.VISIBLE_STRING) + { + file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_stringLength", make_cname(od.parameter_name,od)), od.Lengthofstring)); + } + file.WriteLine(""); + } + break; + + case ObjectType.ARRAY: + { + DataType dt = od.datatype; + + file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}, Array[{2}] */", od.Index, t.ToString(), od.Nosubindexes - 1)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); + file.WriteLine(string.Format(" #define OD_{0,-48} {1}.{2}", make_cname(od.parameter_name,od), loc, make_cname(od.parameter_name,od))); + file.WriteLine(string.Format(" #define {0,-51} {1}", string.Format("ODL_{0}_arrayLength", make_cname(od.parameter_name,od)), od.Nosubindexes - 1)); + + + List ODAs = new List(); + + string ODAout = ""; + + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry sub = kvp2.Value; + + if (kvp2.Key == 0) + continue; + + string ODA = string.Format("{0}", string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub))); + + if (ODAs.Contains(ODA)) + { + continue; + } + + ODAs.Add(ODA); + + //Arrays do not have a size in the raw CO objects, Records do + //so offset by one + if (od.objecttype == ObjectType.ARRAY) + { + ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key - 1}{Environment.NewLine}"); + } + else + { + ODAout += ($" #define {string.Format("ODA_{0}_{1}", make_cname(od.parameter_name,od), make_cname(sub.parameter_name,sub)),-51} {kvp2.Key}{Environment.NewLine}"); + } + } + + file.Write(ODAout); + file.WriteLine(""); + } + break; + + case ObjectType.RECORD: + { + string rectype = make_cname(od.parameter_name,od); + + if (!constructed_rec_types.Contains(rectype)) + { + file.WriteLine(string.Format("/*{0:X4}, Data Type: {1}_t */", od.Index, rectype)); + file.WriteLine(string.Format(" #define {0,-51} 0x{1:X4}", string.Format("OD_{0}_idx", make_cname(od.parameter_name, od)), od.Index, t.ToString())); + file.WriteLine(string.Format(" #define {0,-51} {1}.{2}", string.Format("OD_{0}", rectype), loc, rectype)); + constructed_rec_types.Add(rectype); + file.WriteLine(""); + } + + } + break; + } + } + file.WriteLine("#endif"); + file.WriteLine("// clang-format on"); + file.Close(); + + } + + private void export_c(string filename) + { + if (filename == "") + filename = "CO_OD"; + StreamWriter file = new StreamWriter(folderpath + Path.DirectorySeparatorChar + filename + ".c"); + + file.WriteLine("// clang-format off"); + addHeader(file); + file.WriteLine(@"// For CANopenNode V2 users, C macro `CO_VERSION_MAJOR=2` has to be added to project options +#ifndef CO_VERSION_MAJOR + #include ""CO_driver.h"" + #include """ + Path.GetFileNameWithoutExtension(filename) + @".h"" + #include ""CO_SDO.h"" +#elif CO_VERSION_MAJOR < 4 + #include ""301/CO_driver.h"" + #include """ + Path.GetFileNameWithoutExtension(filename) + @".h"" + #include ""301/CO_SDOserver.h"" +#else + #error This Object dictionary is not compatible with CANopenNode v4.0 and up! +#endif + +/******************************************************************************* + DEFINITION AND INITIALIZATION OF OBJECT DICTIONARY VARIABLES +*******************************************************************************/ + +"); + foreach (string location in eds.CO_storageGroups) + { + if (location == "Unused") + { + continue; + } + + file.Write("/***** Definition for "); + file.Write(location); + file.WriteLine(" variables *******************************************/"); + file.Write("struct sCO_OD_"); + file.Write(location); + file.Write(" CO_OD_"); + file.Write(location); + file.Write(@" = { + CO_OD_FIRST_LAST_WORD, + +"); + + file.Write(export_OD_def_array(location)); + + file.WriteLine(@" + CO_OD_FIRST_LAST_WORD, +}; + +"); + } + + + file.WriteLine(@" + +/******************************************************************************* + STRUCTURES FOR RECORD TYPE OBJECTS +*******************************************************************************/ + +"); + + file.Write(export_record_types()); + + file.Write(@"/******************************************************************************* + OBJECT DICTIONARY +*******************************************************************************/ +const CO_OD_entry_t CO_OD[CO_OD_NoOfElements] = { +"); + + file.Write(write_od()); + + file.WriteLine("};"); + file.WriteLine("// clang-format on"); + + file.Close(); + } + + bool arrayspecialcase = false; + int arrayspecialcasecount = 0; + + string write_od() + { + + StringBuilder returndata = new StringBuilder(); + + foreach (KeyValuePair kvp in eds.ods) + { + + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true) + continue; + + returndata.Append(write_od_line(od)); + + + } + + return returndata.ToString(); + } + + protected string write_od_line(ODentry od) + { + StringBuilder sb = new StringBuilder(); + + string loc = "CO_OD_" + od.prop.CO_storageGroup; + + byte flags = getflags(od); + + int datasize = od.objecttype == ObjectType.RECORD ? 0 : (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); + + string array = ""; + + //only needed for array objects + if (od.objecttype == ObjectType.ARRAY && od.Nosubindexes > 0) + array = string.Format("[0]"); + + + if (arrayspecial(od.Index, true)) + { + arrayspecialcase = true; + arrayspecialcasecount = 0; + } + + if (arrayspecialcase) + { + array = string.Format("[{0}]", arrayspecialcasecount); + arrayspecialcasecount++; + } + + //Arrays and Recs have 1 less subindex than actually present in the od.subobjects + int nosubindexs = od.Nosubindexes; + if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) + { + if (nosubindexs > 0) + nosubindexs--; + } + + //Arrays really should obey the max subindex parameter not the physical number of elements + if (od.objecttype == ObjectType.ARRAY) + { + if ((od.Getmaxsubindex() != nosubindexs)) + { + if (od.Index != 0x1003 && od.Index != 0x1011)//ignore 0x1003, it is a special case as per CANopen specs, and ignore 0x1011 CANopenNode uses special sub indexes for eeprom resets + { + Warnings.AddWarning(String.Format("Subindex discrepancy on object 0x{0:X4} arraysize: {1} vs max sub-index: {2}", od.Index, nosubindexs, od.Getmaxsubindex())); + } + + //0x1003 is a special case for CANopenNode + //SubIndex 0 will probably be 0 for no errors + //so we cannot read that to determine max subindex size, which is required to set up CANopenNode so we leave it alone here + //as its already set to subod.count + if (od.Index != 0x1003) + { + nosubindexs = od.Getmaxsubindex(); + } + } + } + + string pdata; //CO_OD_entry_t pData generator + + if (od.objecttype == ObjectType.RECORD) + { + + pdata = string.Format("&OD_record{0:X4}", od.Index); + } + else + { + pdata = string.Format("&{0}.{1}{2}", loc, make_cname(od.parameter_name,od), array); + } + + if ((od.objecttype == ObjectType.VAR || od.objecttype == ObjectType.ARRAY) && od.datatype == DataType.DOMAIN) + { + //NB domain MUST have a data pointer of 0, can open node requires this and makes checks + //against null to determine this is a DOMAIN type. + pdata = "0"; + } + + sb.AppendLine($"{{0x{od.Index:X4}, 0x{nosubindexs:X2}, 0x{flags:X2}, {datasize,2:#0}, (void*){pdata}}},"); + + if (arrayspecial(od.Index, false)) + { + arrayspecialcase = false; + } + + return sb.ToString(); + } + + /// + /// Get the CANopenNode specific flags, these flags are used internally in CANopenNode to determine details about the object variable + /// + /// An odentry to access + /// byte containing the flag value + public byte getflags(ODentry od) + { + byte flags = 0; + byte mapping = 0; //mapping flags, if pdo is enabled + + //aways return 0 for REC objects as CO_OD_getDataPointer() uses this to pickup the details + if (od.objecttype == ObjectType.RECORD) + return 0; + + switch((od.parent == null ? od : od.parent).prop.CO_storageGroup.ToUpper()) + { + case "ROM": + flags = 0x01; + break; + + case "RAM": + flags = 0x02; + break; + + case "EEPROM": + default: + flags = 0x03; + break; + } + + /* some exceptions for rwr/rww. Those are entries that are always r/w via SDO transfer, + * but can only be read -or- written via PDO */ + if (od.accesstype == EDSsharp.AccessType.ro + || od.accesstype == EDSsharp.AccessType.rw + || od.accesstype == EDSsharp.AccessType.rwr + || od.accesstype == EDSsharp.AccessType.rww + || od.accesstype == EDSsharp.AccessType.@const) + { + /* SDO server may read from the variable */ + flags |= 0x04; + + if (od.accesstype != EDSsharp.AccessType.rww) + { + /* Variable is mappable for TPDO */ + mapping |= 0x20; + } + } + if (od.accesstype == EDSsharp.AccessType.wo + || od.accesstype == EDSsharp.AccessType.rw + || od.accesstype == EDSsharp.AccessType.rwr + || od.accesstype == EDSsharp.AccessType.rww) + { + /* SDO server may write to the variable */ + flags |= 0x08; + + if (od.accesstype != EDSsharp.AccessType.rwr) + { + /* Variable is mappable for RPDO */ + mapping |= 0x10; + } + } + + if (od.Index == 0x1003) + { + /* SDO server may write to the variable */ + flags |= 0x08; + } + + switch (od.PDOtype) + { + case libEDSsharp.PDOMappingType.RPDO: mapping |= 0x10; break; + case libEDSsharp.PDOMappingType.TPDO: mapping |= 0x20; break; + case libEDSsharp.PDOMappingType.optional: mapping |= 0x30; break; + } + + if (od.PDOMapping) + { + flags |= mapping; + } + + if(od.prop.CO_flagsPDO) + { + /* If variable is mapped to any PDO, then is automatically send, if variable its value */ + flags |=0x40; + } + + if(od.parent!=null && od.parent.prop.CO_flagsPDO) + { + //parent types are storing the prop in the ODeditor in the parent object but the child object is tested to set the flag + //this is breaking legacy export + flags |= 0x40; + } + + + int datasize = (int)Math.Ceiling((double)od.Sizeofdatatype() / (double)8.0); + + if (datasize > 1) + { + if (od.datatype == DataType.VISIBLE_STRING || + od.datatype == DataType.OCTET_STRING) + { + //#149 VISIBLE_STRING and OCTET_STRING are an arrays of 8 bit values, either VISIBLE_CHAR or UNSIGNED8 + //and therefor are NOT multi-byte + } + else + { + /* variable is a multi-byte value */ + flags |= 0x80; + } + } + + return flags; + } + + string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring=false) + { + try + { + int nobase = 10; + bool nodeidreplace = false; + + + if (defaultvalue == null || defaultvalue == "") + { + //No default value, we better supply one for sensible data types + if (dt == DataType.VISIBLE_STRING || + dt == DataType.OCTET_STRING || + dt == DataType.UNKNOWN || + dt == DataType.UNICODE_STRING) + { + + if (fixstring == true) + return "'X'"; + + return ""; + } + + Console.WriteLine("Warning assuming a 0 default"); + defaultvalue = "0"; + } + + if (defaultvalue.Contains("$NODEID", StringComparison.OrdinalIgnoreCase)) // fetch different case of "NODeID" (allowed according DS301) + { + defaultvalue = defaultvalue.ToUpper().Replace("$NODEID", ""); + defaultvalue = defaultvalue.Replace("+", ""); + defaultvalue = defaultvalue.Trim(); + nodeidreplace = true; + } + + String pat = @"^0[xX][0-9a-fA-FL]+"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 16; + defaultvalue = defaultvalue.Replace("L", ""); + } + + pat = @"^0[0-7]+"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(defaultvalue); + if (m.Success) + { + nobase = 8; + } + + if (nodeidreplace) + { + UInt32 data = Convert.ToUInt32(defaultvalue.Trim(), nobase); + data += eds.NodeID; + defaultvalue = string.Format("0x{0:X}", data); + nobase = 16; + } + + + switch (dt) + { + case DataType.UNSIGNED24: + case DataType.UNSIGNED32: + return String.Format("0x{0:X4}L", Convert.ToUInt32(defaultvalue, nobase)); + + case DataType.INTEGER24: + case DataType.INTEGER32: + return String.Format("0x{0:X4}L", Convert.ToInt32(defaultvalue, nobase)); + + case DataType.REAL32: + case DataType.REAL64: + return (String.Format("{0}", defaultvalue)); + + + //fix me this looks wrong + case DataType.UNICODE_STRING: + return (String.Format("'{0}'", defaultvalue)); + + case DataType.VISIBLE_STRING: + { + + ASCIIEncoding a = new ASCIIEncoding(); + string unescape = StringUnescape.Unescape(defaultvalue); + char[] chars = unescape.ToCharArray(); + + string array = "{"; + + foreach (char c in chars) + { + + array += "'" + StringUnescape.Escape(c) + "', "; + } + + array = array.Substring(0, array.Length - 2); + + array += "}"; + return array; + + } + + + case DataType.OCTET_STRING: + { + string[] bits = defaultvalue.Split(' '); + string octet = "{"; + foreach (string s in bits) + { + octet += formatvaluewithdatatype(s, DataType.UNSIGNED8); + + if (!object.ReferenceEquals(s, bits.Last())) + { + octet += ", "; + } + } + octet += "}"; + return octet; + } + + case DataType.INTEGER8: + return String.Format("0x{0:X1}", Convert.ToSByte(defaultvalue, nobase)); + + case DataType.INTEGER16: + return String.Format("0x{0:X2}", Convert.ToInt16(defaultvalue, nobase)); + + case DataType.UNSIGNED8: + return String.Format("0x{0:X1}L", Convert.ToByte(defaultvalue, nobase)); + + case DataType.UNSIGNED16: + return String.Format("0x{0:X2}", Convert.ToUInt16(defaultvalue, nobase)); + + case DataType.INTEGER64: + return String.Format("0x{0:X8}L", Convert.ToInt64(defaultvalue, nobase)); + + case DataType.UNSIGNED64: + return String.Format("0x{0:X8}L", Convert.ToUInt64(defaultvalue, nobase)); + + case DataType.TIME_DIFFERENCE: + case DataType.TIME_OF_DAY: + return String.Format("{{{0}}}", Convert.ToUInt64(defaultvalue, nobase)); + + default: + return (String.Format("{0:X}", defaultvalue)); + + } + } + catch(Exception) + { + Warnings.AddWarning(String.Format("Error converting value {0} to type {1}", defaultvalue, dt.ToString()),Warnings.warning_class.WARNING_BUILD); + return ""; + } + } + + public static string ParseString(string input) + { + var provider = new Microsoft.CSharp.CSharpCodeProvider(); + var parameters = new System.CodeDom.Compiler.CompilerParameters() + { + GenerateExecutable = false, + GenerateInMemory = true, + }; + + var code = @" + namespace Tmp + { + public class TmpClass + { + public static string GetValue() + { + return """ + input + @"""; + } + } + }"; + + var compileResult = provider.CompileAssemblyFromSource(parameters, code); + + if (compileResult.Errors.HasErrors) + { + throw new ArgumentException(compileResult.Errors.Cast().First(e => !e.IsWarning).ErrorText); + } + + var asmb = compileResult.CompiledAssembly; + var method = asmb.GetType("Tmp.TmpClass").GetMethod("GetValue"); + + return method.Invoke(null, null) as string; + } + + protected string make_cname(string name,ODentry entry) + { + if (name == null) + return null; + + if (name == "") + return ""; + + Regex splitter = new Regex(@"[\W]+"); + + //string[] bits = Regex.Split(name,@"[\W]+"); + var bits = splitter.Split(name).Where(s => s != String.Empty); + + string output = ""; + + char lastchar = ' '; + foreach (string s in bits) + { + if(Char.IsUpper(lastchar) && Char.IsUpper(s.First())) + output+="_"; + + if (s.Length > 1) + { + output += char.ToUpper(s[0]) + s.Substring(1); + } + else + { + output += s; + } + + if(output.Length>0) + lastchar = output.Last(); + + } + + if (output.Length > 1) + { + if (Char.IsLower(output[1])) + output = Char.ToLowerInvariant(output[0]) + output.Substring(1); + } + else + output = output.ToLowerInvariant(); //single character + + + UInt32 key = (UInt32)((entry.Index << 8) + entry.Subindex ); + + if ((entry.Index >= 0x1200) && (entry.Index < 0x1280)) + key = (UInt32)((0x1200 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1280) && (entry.Index < 0x1300)) + key = (UInt32)((0x1280 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1400) && (entry.Index < 0x1600)) + key = (UInt32)((0x1400 <<8) + entry.Subindex); + + if ((entry.Index >= 0x1600) && (entry.Index < 0x1800)) + key = (UInt32)((0x1600 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1800) && (entry.Index < 0x1a00)) + key = (UInt32)((0x1800 << 8) + entry.Subindex); + + if ((entry.Index >= 0x1a00) && (entry.Index < 0x1c00)) + key = (UInt32)((0x1a00 << 8) + entry.Subindex); + + if (acceptable_canopen_names.ContainsKey(key) && !(entry.parent != null && entry.Subindex == 0)) + { + string newname = acceptable_canopen_names[key]; + if (output != newname) + Warnings.AddWarning(string.Format("Warning: index 0x{0:X4}/{1:X2} correcting name for CanOpenNode compatibility from {2} to {3}", entry.Index, entry.Subindex, output, newname),Warnings.warning_class.WARNING_RENAME); + output = newname; + } + + return output; + } + + /// + /// Export the record type objects in the CO_OD.c file + /// + /// string + protected string export_record_types() + { + StringBuilder returndata = new StringBuilder(); + + bool arrayopen = false; + int arrayindex = 0; + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + if (od.objecttype != ObjectType.RECORD) + continue; + + if (od.prop.CO_disabled == true) + continue; + + int count = od.subobjects.Count; //don't include index + + if(od.Index>=0x1400 && od.Index<0x1600) + { + //what is this doing for us? + //count = 3; //CANopenNode Fudging. Its only 3 parameters for RX PDOS in the c code despite being a PDO_COMMUNICATION_PARAMETER + } + + returndata.AppendLine($"/*0x{od.Index:X4}*/ const CO_OD_entryRecord_t OD_record{od.Index:X4}[{count}] = {{"); + + string arrayaccess = ""; + + if (arrayspecial(od.Index, true) || arrayopen) + { + arrayaccess = string.Format("[{0}]",arrayindex); + arrayindex++; + arrayopen = true; + } + + foreach (KeyValuePair kvpsub in od.subobjects) + { + returndata.Append(export_one_record_type(kvpsub.Value,arrayaccess)); + } + + if (arrayspecial(od.Index, false)) + { + arrayindex=0; + arrayopen = false; + } + + returndata.AppendLine($"}};{Environment.NewLine}"); + } + + return returndata.ToString(); + } + + /// + /// Exports a sub object line in a record object + /// + /// sub ODentry object to export + /// string forming current array level or empty string for none + /// string forming one line of CO_OD.c record objects + protected string export_one_record_type(ODentry sub,string arrayaccess) + { + + if (sub == null || sub.parent == null) + return ""; + + StringBuilder sb = new StringBuilder(); + + string cname = make_cname(sub.parent.parameter_name,sub.parent); + + string subcname = make_cname(sub.parameter_name,sub); + int datasize = (int)Math.Ceiling((double)sub.Sizeofdatatype() / (double)8.0); + + if (sub.datatype != DataType.DOMAIN) + { + sb.AppendLine($" {{(void*)&{"CO_OD_" + sub.parent.prop.CO_storageGroup}.{cname}{arrayaccess}.{subcname}, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); + } + else + { + //Domain type MUST have its data pointer set to 0 for CANopenNode + sb.AppendLine($" {{(void*)0, 0x{getflags(sub):X2}, 0x{datasize:X} }},"); + } + + return sb.ToString(); + } + + + int noTXpdos = 0; + int noRXpdos = 0; + int noSDOclients = 0; + int noSDOservers = 0; + int distTXpdo = 0; + int distRXpdo = 0; + int noSYNC = 0; + int noEMCY = 0; + int noTIME = 0; + int noGFC = 0; + int noSRDO = 0; + + void countPDOS() + { + noRXpdos = 0; + noTXpdos = 0; + + //feature tests for default CanOpenNode build + //if you have a custom CanOpen.c then you may not require all these features + + //check the SYNC feature + int checkfeature = 0; + if (ObjectActive(0x1005)) + checkfeature++; + if (ObjectActive(0x1006)) + checkfeature++; + if (ObjectActive(0x1007)) + checkfeature++; + if (ObjectActive(0x1019)) + checkfeature++; + if (checkfeature == 4) + { + noSYNC = 1; + } + else + { + Warnings.AddWarning("BUILD WARNING, required objects for SYNC are not present 0x1005,0x1006,0x1007,0x1019",Warnings.warning_class.WARNING_BUILD); + } + + //EMCY + checkfeature = 0; + if (ObjectActive(0x1003)) + checkfeature++; + if (ObjectActive(0x1014)) + checkfeature++; + if (ObjectActive(0x1015)) + checkfeature++; + if (checkfeature == 3) + { + noEMCY = 1; + } + else + { + Warnings.AddWarning("BUILD WARNING, required objects for EMCY are not present 0x1003,0x1014,0x1015",Warnings.warning_class.WARNING_BUILD); + } + + //TIME + if (ObjectActive(0x1012)) + { + noTIME = 1; + } + else + { + //TIME is optional + } + + //NMT CLIENT + checkfeature = 0; + if (ObjectActive(0x1f80)) + checkfeature ++; + if (ObjectActive(0x1029)) + checkfeature ++; + if (ObjectActive(0x1017)) + checkfeature ++; + if (ObjectActive(0x1001)) + checkfeature ++; + if (checkfeature == 4) + { + //NMT Client is not optional + } + else + { + Warnings.AddWarning("BUILD WARNING, required objects for NMT Client are not present 0x1f80,0x1029,0x1017,0x1001",Warnings.warning_class.WARNING_BUILD); + } + + foreach (KeyValuePair kvp in eds.ods) + { + UInt16 index = kvp.Key; + + if (kvp.Value.prop.CO_disabled == true) + continue; + + if (index >= 0x1400 && index < 0x1600) + { + noRXpdos++; + distRXpdo = index - 0x1400; + } + + if (index >= 0x1800 && index < 0x1A00) + { + noTXpdos++; + distTXpdo = index - 0x1800; + } + + if((index & 0xFF80) == 0x1200) + { + noSDOservers++; + } + + if ((index & 0xFF80) == 0x1280) + { + noSDOclients++; + } + + if (index == 0x1300) + noGFC = 1; + + if (index >= 0x1301 && index <= 0x1340) + noSRDO++; + } + } + + bool arrayspecial(UInt16 index, bool open) + { + + if (open) + { + + if (openings.Contains(index)) + return true; + } + else + { + + if (closings.Contains(index)) + return true; + } + + return false; + } + + + string export_OD_def_array(string location) + { + + StringBuilder sb = new StringBuilder(); + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + + if (od.prop.CO_disabled == true || od.prop.CO_storageGroup != location) + continue; + + if (od.Nosubindexes == 0) + { + sb.AppendLine($"/*{od.Index:X4}*/ {formatvaluewithdatatype(od.defaultvalue, od.datatype,true)},"); + } + else + { + if (arrayspecial(od.Index, true)) + { + sb.AppendFormat("/*{0:X4}*/ {{{{", od.Index); + } + else + { + sb.AppendFormat("/*{0:X4}*/ {{", od.Index); + } + + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry sub = kvp2.Value; + + DataType dt = sub.datatype; + + if ((od.objecttype==ObjectType.ARRAY) && kvp2.Key == 0) + continue; + + sb.Append(formatvaluewithdatatype(sub.defaultvalue, dt,true)); + + if (od.subobjects.Keys.Last() != kvp2.Key) + sb.Append(", "); + } + + if (arrayspecial(od.Index, false)) + { + sb.AppendLine("}},"); + } + else + { + sb.AppendLine("},"); + } + } + } + + return sb.ToString(); + } + } + + + + + + +} diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index a10f41e9..57ca7eca 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -194,14 +194,14 @@ private int Prepare_var(ODentry od, string indexH, string varName, string group) string attr = Get_attributes(od, data.cTypeMultibyte, data.cTypeString); // data storage - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { ODStorage_t[group].Add($"{data.cType} x{varName}{data.cTypeArray};"); ODStorage[group].Add($".x{varName} = {data.cValue}"); dataPtr = $"&{odname}_{group}.x{varName}{data.cTypeArray0}"; - } - + } + // objects ODObjs_t.Add($"OD_obj_var_t o_{varName};"); ODObjs.Add($" .o_{varName} = {{"); @@ -345,7 +345,7 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) Warnings.AddWarning($"Error in 0x{indexH}: Data type in RECORD, subIndex 0 must be UNSIGNED8, not {sub.datatype}!", Warnings.warning_class.WARNING_BUILD); string subcName = Make_cname(sub.parameter_name); - string dataPtr = "NULL"; + string dataPtr = "NULL"; if (data.cValue != null) { subODStorage_t.Add($"{data.cType} {subcName}{data.cTypeArray};"); diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 9b8bf1ee..13b40334 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -639,8 +639,8 @@ public ISO15745ProfileContainer convert(EDSsharp eds) NetworkManagement.CANopenGeneralFeatures.bootUpSlave = eds.di.SimpleBootUpSlave; //NetworkManagment.CANopenGeneralFeatures.dynamicChannels = eds.di.DynamicChannelsSupported; //fix me count of dynamic channels not handled yet eds only has bool NetworkManagement.CANopenGeneralFeatures.granularity = eds.di.Granularity; - NetworkManagement.CANopenGeneralFeatures.groupMessaging = eds.di.GroupMessaging; - + NetworkManagement.CANopenGeneralFeatures.groupMessaging = eds.di.GroupMessaging; + NetworkManagement.CANopenGeneralFeatures.ngMaster = eds.di.NG_Master; NetworkManagement.CANopenGeneralFeatures.ngSlave = eds.di.NG_Slave; NetworkManagement.CANopenGeneralFeatures.NrOfNG_MonitoredNodes = eds.di.NrOfNG_MonitoredNodes; @@ -918,9 +918,9 @@ public EDSsharp convert(ISO15745ProfileContainer container) } eds.di.NG_Master = NetworkManagment.CANopenGeneralFeatures.ngMaster; - eds.di.NG_Slave = NetworkManagment.CANopenGeneralFeatures.ngSlave; - eds.di.NrOfNG_MonitoredNodes = NetworkManagment.CANopenGeneralFeatures.NrOfNG_MonitoredNodes; - + eds.di.NG_Slave = NetworkManagment.CANopenGeneralFeatures.ngSlave; + eds.di.NrOfNG_MonitoredNodes = NetworkManagment.CANopenGeneralFeatures.NrOfNG_MonitoredNodes; + eds.di.NrOfRXPDO = NetworkManagment.CANopenGeneralFeatures.nrOfRxPDO; eds.di.NrOfTXPDO = NetworkManagment.CANopenGeneralFeatures.nrOfTxPDO; @@ -3832,8 +3832,8 @@ public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementCA private ushort nrOfTxPDOField; private bool ngMasterField; - private bool ngSlaveField; - private ushort NrOfNG_MonitoredNodesField; + private bool ngSlaveField; + private ushort NrOfNG_MonitoredNodesField; private bool bootUpSlaveField; private bool layerSettingServiceSlaveField; @@ -4001,18 +4001,18 @@ public bool ngMaster { this.ngMasterField = value; } - } - + } + /// [System.Xml.Serialization.XmlAttributeAttribute()] [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] - public ushort NrOfNG_MonitoredNodes + public ushort NrOfNG_MonitoredNodes { - get + get { return this.NrOfNG_MonitoredNodesField; } - set + set { this.NrOfNG_MonitoredNodesField = value; } diff --git a/libEDSsharp/CanOpenXSD_1_1.cs b/libEDSsharp/CanOpenXSD_1_1.cs index 5e6d8264..21730392 100644 --- a/libEDSsharp/CanOpenXSD_1_1.cs +++ b/libEDSsharp/CanOpenXSD_1_1.cs @@ -2461,7 +2461,7 @@ public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementCA private bool bootUpSlaveField; - private bool ngSlaveField; + private bool ngSlaveField; private bool ngMasterField; private ushort NrOfNG_MonitoredNodesField; @@ -2597,13 +2597,13 @@ public bool ngMaster /// [System.Xml.Serialization.XmlAttributeAttribute()] [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] - public ushort NrOfNG_MonitoredNodes + public ushort NrOfNG_MonitoredNodes { - get + get { return this.NrOfNG_MonitoredNodesField; } - set + set { this.NrOfNG_MonitoredNodesField = value; } diff --git a/libEDSsharp/NetworkPDOreport.cs b/libEDSsharp/NetworkPDOreport.cs index 484f598a..2f65b26d 100644 --- a/libEDSsharp/NetworkPDOreport.cs +++ b/libEDSsharp/NetworkPDOreport.cs @@ -31,7 +31,7 @@ public class NetworkPDOreport public void gennetpdodoc(string filepath, List network) { - file = new StreamWriter(filepath, false); + file = new StreamWriter(filepath, false); file.NewLine = "\n"; file.Write(" Network PDO report"); diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index f8fbba08..4e6b640e 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -11,7 +11,7 @@ public class PDOSlot { private UInt16 _MappingIndex; - private UInt16 _ConfigurationIndex; + private UInt16 _ConfigurationIndex; public bool nodeidpresent; public ushort ConfigurationIndex { @@ -82,17 +82,17 @@ public bool invalid public UInt16 eventtimer; public byte syncstart; public byte transmissiontype; - public string DescriptionComm; - public string DescriptionMap; - + public string DescriptionComm; + public string DescriptionMap; + public PDOSlot() { configloc = "PERSIST_COMM"; mappingloc = "PERSIST_COMM"; transmissiontype = 254; Mapping = new List(); - DescriptionComm = ""; - DescriptionMap = ""; + DescriptionComm = ""; + DescriptionMap = ""; } public string getTargetName(ODentry od) @@ -215,8 +215,8 @@ public void build_PDOlist(UInt16 startcob, List slots) //Look at mappings - ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); - + ODentry mapping = eds.Getobject((ushort)(idx + 0x200)); + if (mapping != null) { slot.DescriptionMap = mapping.Description; }else @@ -323,19 +323,19 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) if (slot.isTXPDO()) { config.parameter_name = "TPDO communication parameter"; - config.prop.CO_countLabel = "TPDO"; - - sub = new ODentry("Highest sub-index supported", (ushort)slot.ConfigurationIndex, 0); - sub.defaultvalue = "0x06"; - sub.datatype = DataType.UNSIGNED8; - sub.accesstype = EDSsharp.AccessType.ro; + config.prop.CO_countLabel = "TPDO"; + + sub = new ODentry("Highest sub-index supported", (ushort)slot.ConfigurationIndex, 0); + sub.defaultvalue = "0x06"; + sub.datatype = DataType.UNSIGNED8; + sub.accesstype = EDSsharp.AccessType.ro; config.addsubobject(0x00, sub); sub = new ODentry("COB-ID used by TPDO", (ushort)slot.ConfigurationIndex, 1); - sub.datatype = DataType.UNSIGNED32; - if (slot.nodeidpresent) - sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. - sub.defaultvalue += String.Format("0x{0:X}", slot.COB); + sub.datatype = DataType.UNSIGNED32; + if (slot.nodeidpresent) + sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. + sub.defaultvalue += String.Format("0x{0:X}", slot.COB); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -351,15 +351,15 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x03, sub); - if (!isCANopenNode_V4) - { - sub = new ODentry("compatibility entry", (ushort)slot.ConfigurationIndex, 4); - sub.datatype = DataType.UNSIGNED8; - sub.defaultvalue = "0"; - sub.accesstype = EDSsharp.AccessType.rw; + if (!isCANopenNode_V4) + { + sub = new ODentry("compatibility entry", (ushort)slot.ConfigurationIndex, 4); + sub.datatype = DataType.UNSIGNED8; + sub.defaultvalue = "0"; + sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x04, sub); - } - + } + sub = new ODentry("Event timer", (ushort)slot.ConfigurationIndex, 5); sub.datatype = DataType.UNSIGNED16; sub.defaultvalue = slot.eventtimer.ToString(); @@ -376,18 +376,18 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) else { config.parameter_name = "RPDO communication parameter"; - config.prop.CO_countLabel = "RPDO"; - - sub = new ODentry("Highest sub-index supported", (ushort)slot.ConfigurationIndex, 0); - sub.defaultvalue = isCANopenNode_V4 ? "0x05" : "0x02"; - sub.datatype = DataType.UNSIGNED8; - sub.accesstype = EDSsharp.AccessType.ro; + config.prop.CO_countLabel = "RPDO"; + + sub = new ODentry("Highest sub-index supported", (ushort)slot.ConfigurationIndex, 0); + sub.defaultvalue = isCANopenNode_V4 ? "0x05" : "0x02"; + sub.datatype = DataType.UNSIGNED8; + sub.accesstype = EDSsharp.AccessType.ro; config.addsubobject(0x00, sub); sub = new ODentry("COB-ID used by RPDO", (ushort)slot.ConfigurationIndex, 1); - sub.datatype = DataType.UNSIGNED32; - if (slot.nodeidpresent) - sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. + sub.datatype = DataType.UNSIGNED32; + if (slot.nodeidpresent) + sub.defaultvalue = "$NODEID+"; // DSP306: "The $NODEID must appear at the beginning of the expression. Otherwise the line is interpreted as without a formula. sub.defaultvalue += String.Format("0x{0:X}", slot.COB); sub.accesstype = EDSsharp.AccessType.rw; config.addsubobject(0x01, sub); @@ -396,15 +396,15 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) sub.datatype = DataType.UNSIGNED8; sub.defaultvalue = slot.transmissiontype.ToString(); sub.accesstype = EDSsharp.AccessType.rw; - config.addsubobject(0x02, sub); - - if (isCANopenNode_V4) - { - sub = new ODentry("Event timer", (ushort)slot.ConfigurationIndex, 5); - sub.datatype = DataType.UNSIGNED16; - sub.defaultvalue = slot.eventtimer.ToString(); - sub.accesstype = EDSsharp.AccessType.rw; - config.addsubobject(0x05, sub); + config.addsubobject(0x02, sub); + + if (isCANopenNode_V4) + { + sub = new ODentry("Event timer", (ushort)slot.ConfigurationIndex, 5); + sub.datatype = DataType.UNSIGNED16; + sub.defaultvalue = slot.eventtimer.ToString(); + sub.accesstype = EDSsharp.AccessType.rw; + config.addsubobject(0x05, sub); } } @@ -479,43 +479,43 @@ public void addPDOslot(UInt16 configindex) PDOSlot newslot = new PDOSlot(); newslot.ConfigurationIndex = configindex; - switch (configindex) - { - case 0x1400: - newslot.COB = 0x80000200; - newslot.nodeidpresent = true; - break; - case 0x1401: - newslot.COB = 0x80000300; - newslot.nodeidpresent = true; - break; - case 0x1402: - newslot.COB = 0x80000400; - newslot.nodeidpresent = true; - break; - case 0x1403: - newslot.COB = 0x80000500; - newslot.nodeidpresent = true; - break; - case 0x1800: - newslot.COB = 0xC0000180; - newslot.nodeidpresent = true; - break; - case 0x1801: - newslot.COB = 0xC0000280; - newslot.nodeidpresent = true; - break; - case 0x1802: - newslot.COB = 0xC0000380; - newslot.nodeidpresent = true; - break; - case 0x1803: - newslot.COB = 0xC0000480; - newslot.nodeidpresent = true; - break; - default: - newslot.COB = 0xC0000000; - break; + switch (configindex) + { + case 0x1400: + newslot.COB = 0x80000200; + newslot.nodeidpresent = true; + break; + case 0x1401: + newslot.COB = 0x80000300; + newslot.nodeidpresent = true; + break; + case 0x1402: + newslot.COB = 0x80000400; + newslot.nodeidpresent = true; + break; + case 0x1403: + newslot.COB = 0x80000500; + newslot.nodeidpresent = true; + break; + case 0x1800: + newslot.COB = 0xC0000180; + newslot.nodeidpresent = true; + break; + case 0x1801: + newslot.COB = 0xC0000280; + newslot.nodeidpresent = true; + break; + case 0x1802: + newslot.COB = 0xC0000380; + newslot.nodeidpresent = true; + break; + case 0x1803: + newslot.COB = 0xC0000480; + newslot.nodeidpresent = true; + break; + default: + newslot.COB = 0xC0000000; + break; } newslot.configloc = "PERSIST_COMM"; @@ -565,14 +565,14 @@ public UInt16 findPDOslotgap(bool isTXPDO) /// public void removePDOslot(UInt16 configindex) { - foreach (PDOSlot slot in pdoslots) - { - if (slot.ConfigurationIndex == configindex) - { - pdoslots.Remove(slot); - break; - } - } + foreach (PDOSlot slot in pdoslots) + { + if (slot.ConfigurationIndex == configindex) + { + pdoslots.Remove(slot); + break; + } + } } } } diff --git a/libEDSsharp/Properties/Resources.Designer.cs b/libEDSsharp/Properties/Resources.Designer.cs index a5a81006..60a83da3 100644 --- a/libEDSsharp/Properties/Resources.Designer.cs +++ b/libEDSsharp/Properties/Resources.Designer.cs @@ -1,63 +1,63 @@ -//------------------------------------------------------------------------------ -// -// Dieser Code wurde von einem Tool generiert. -// Laufzeitversion:4.0.30319.42000 -// -// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn -// der Code erneut generiert wird. -// -//------------------------------------------------------------------------------ - -namespace libEDSsharp.Properties { - using System; - - - /// - /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. - /// - // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert - // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. - // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen - // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if (object.ReferenceEquals(resourceMan, null)) { - global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("libEDSsharp.Properties.Resources", typeof(Resources).Assembly); - resourceMan = temp; - } - return resourceMan; - } - } - - /// - /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { - return resourceCulture; - } - set { - resourceCulture = value; - } - } - } -} +//------------------------------------------------------------------------------ +// +// Dieser Code wurde von einem Tool generiert. +// Laufzeitversion:4.0.30319.42000 +// +// Änderungen an dieser Datei können falsches Verhalten verursachen und gehen verloren, wenn +// der Code erneut generiert wird. +// +//------------------------------------------------------------------------------ + +namespace libEDSsharp.Properties { + using System; + + + /// + /// Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. + /// + // Diese Klasse wurde von der StronglyTypedResourceBuilder automatisch generiert + // -Klasse über ein Tool wie ResGen oder Visual Studio automatisch generiert. + // Um einen Member hinzuzufügen oder zu entfernen, bearbeiten Sie die .ResX-Datei und führen dann ResGen + // mit der /str-Option erneut aus, oder Sie erstellen Ihr VS-Projekt neu. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + internal class Resources { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Resources() { + } + + /// + /// Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("libEDSsharp.Properties.Resources", typeof(Resources).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle + /// Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + internal static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + } +} diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index f88ea3a4..e5ef6dd3 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -25,11 +25,11 @@ You should have received a copy of the GNU General Public License using System.Globalization; using System.Reflection; using CanOpenXSD_1_1; -using System.Runtime.Remoting.Messaging; -using System.Net.NetworkInformation; -using System.Security.Cryptography; -using Xml2CSharp; - +using System.Runtime.Remoting.Messaging; +using System.Net.NetworkInformation; +using System.Security.Cryptography; +using Xml2CSharp; + namespace libEDSsharp { @@ -751,21 +751,21 @@ public class DeviceInfo : InfoSection public UInt32 RevisionNumber; [EdsExport] - public bool BaudRate_10 = false; + public bool BaudRate_10 = false; [EdsExport] - public bool BaudRate_20 = false; + public bool BaudRate_20 = false; [EdsExport] - public bool BaudRate_50 = false; + public bool BaudRate_50 = false; [EdsExport] - public bool BaudRate_125 = false; + public bool BaudRate_125 = false; [EdsExport] - public bool BaudRate_250 = false; + public bool BaudRate_250 = false; [EdsExport] - public bool BaudRate_500 = false; + public bool BaudRate_500 = false; [EdsExport] - public bool BaudRate_800 = false; + public bool BaudRate_800 = false; [EdsExport] - public bool BaudRate_1000 = false; + public bool BaudRate_1000 = false; public bool BaudRate_auto = false; @@ -794,12 +794,12 @@ public class DeviceInfo : InfoSection [EdsExport] public bool LSS_Supported; - public bool LSS_Master; - + public bool LSS_Master; + [EdsExport] public bool NG_Slave; - public bool NG_Master; + public bool NG_Master; public UInt16 NrOfNG_MonitoredNodes; @@ -1269,7 +1269,7 @@ public override string ToString() public string ObjectTypeString() { return Enum.IsDefined(typeof(ObjectType), objecttype) ? objecttype.ToString() : ObjectType.VAR.ToString(); - } + } public void ObjectTypeString(string objectType) { @@ -1369,15 +1369,15 @@ public ODentry AddSubEntry() return null; ODentry newOd; - - if ((baseObject.Nosubindexes == 0) && ((baseObject.objecttype == ObjectType.ARRAY) || (baseObject.objecttype == ObjectType.RECORD))) { + + if ((baseObject.Nosubindexes == 0) && ((baseObject.objecttype == ObjectType.ARRAY) || (baseObject.objecttype == ObjectType.RECORD))) { baseObject.subobjects.Add(0, new ODentry - { - parent = baseObject, - parameter_name = "Highest sub-index supported", - accesstype = EDSsharp.AccessType.ro, - objecttype = ObjectType.VAR, - datatype = DataType.UNSIGNED8, + { + parent = baseObject, + parameter_name = "Highest sub-index supported", + accesstype = EDSsharp.AccessType.ro, + objecttype = ObjectType.VAR, + datatype = DataType.UNSIGNED8, defaultvalue = "0x01" }); } @@ -2146,9 +2146,9 @@ public void ParseEDSentry(KeyValuePair> kvp) Match m2 = r2.Match(m.Groups[0].ToString()); if (m2.Success) - { - UInt16 modindex=0, odindex=0; - + { + UInt16 modindex=0, odindex=0; + try { modindex = Convert.ToUInt16(m2.Groups[1].Value); } catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + m2.Groups[1].Value); } //Indexes in the EDS are always in hex format without the pre 0x @@ -2225,32 +2225,32 @@ public void ParseEDSentry(KeyValuePair> kvp) } if (kvp.Value.ContainsKey("Count")) - { - /* FIXME: The format of "Count" is Unsigned8[; Unsigned8] according DS306 - * Count: - Number of extended Sub-Indexes with this description that are created per module. The format is Unsigned8 [; Unsigned8]. - If one or more Sub - Indexes are created per attached module to build a new sub- index, then Count is that Number. In example 32 bit module creates 4 Sub - Indexes each having 8 Bit: Count = 4 + { + /* FIXME: The format of "Count" is Unsigned8[; Unsigned8] according DS306 + * Count: + Number of extended Sub-Indexes with this description that are created per module. The format is Unsigned8 [; Unsigned8]. + If one or more Sub - Indexes are created per attached module to build a new sub- index, then Count is that Number. In example 32 bit module creates 4 Sub - Indexes each having 8 Bit: Count = 4 If several modules are gathered to form a new Sub- Index, then the number is 0, followed by semicolon and the number of bits that are created per module to build a new Sub-Index.In example 2 bit modules with 8 bit objects: The first Sub - Index is built upon modules 1 - 4, the next upon modules 5 - 8 etc.: Count = 0; 2.The objects are created, when a new byte begins: Module 1 creates the Sub - Index 1; modules 2 - 4 fill it up; module 5 creates Sub-Index 2 and so forth. - */ - pat2 = @"\s*([0-9a-fA-F]+)\s*;\s*([0-9a-fA-F]+)"; - r2 = new Regex(pat2, RegexOptions.IgnoreCase); - m2 = r2.Match(kvp.Value["Count"]); - - - - if (m2.Success) - { - Console.WriteLine("** FIXME Count format not supported ** Count: " + kvp.Value["Count"]); - int found = kvp.Value["Count"].IndexOf(";"); - string s = kvp.Value["Count"].Substring(found + 1); - try { od.count = Convert.ToByte(s, Getbase(s)); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } - } - else - { - - try { od.count = Convert.ToByte(kvp.Value["Count"], Getbase(kvp.Value["Count"])); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } + */ + pat2 = @"\s*([0-9a-fA-F]+)\s*;\s*([0-9a-fA-F]+)"; + r2 = new Regex(pat2, RegexOptions.IgnoreCase); + m2 = r2.Match(kvp.Value["Count"]); + + + + if (m2.Success) + { + Console.WriteLine("** FIXME Count format not supported ** Count: " + kvp.Value["Count"]); + int found = kvp.Value["Count"].IndexOf(";"); + string s = kvp.Value["Count"].Substring(found + 1); + try { od.count = Convert.ToByte(s, Getbase(s)); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } + } + else + { + + try { od.count = Convert.ToByte(kvp.Value["Count"], Getbase(kvp.Value["Count"])); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } } } @@ -2270,29 +2270,29 @@ public void ParseEDSentry(KeyValuePair> kvp) throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); if (kvp.Value.ContainsKey("ParameterValue")) - { - - try { od.actualvalue = kvp.Value["ParameterValue"]; } + { + + try { od.actualvalue = kvp.Value["ParameterValue"]; } catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** ParameterValue:" + kvp.Value["ParameterValue"]); } } if (kvp.Value.ContainsKey("HighLimit")) - { - try { od.HighLimit = kvp.Value["HighLimit"]; } + { + try { od.HighLimit = kvp.Value["HighLimit"]; } catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** HighLimit:" + kvp.Value["HighLimit"]); } } if (kvp.Value.ContainsKey("LowLimit")) - { - try { od.LowLimit = kvp.Value["LowLimit"]; } + { + try { od.LowLimit = kvp.Value["LowLimit"]; } catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** LowLimit:" + kvp.Value["LowLimit"]); } } if (kvp.Value.ContainsKey("Denotation")) - { - try { od.denotation = kvp.Value["Denotation"]; } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Denotation:" + kvp.Value["Denotation"]); } - + { + try { od.denotation = kvp.Value["Denotation"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Denotation:" + kvp.Value["Denotation"]); } + } @@ -2439,8 +2439,8 @@ public void Loadfile(string filename) di = new DeviceInfo(eds["DeviceInfo"]); foreach (KeyValuePair> kvp in eds) - { - + { + try { ParseEDSentry(kvp); } catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + kvp); } @@ -2466,7 +2466,7 @@ public void Loadfile(string filename) string strSection = ""; if (eds.ContainsKey("DeviceCommissioning")) // wrong section name as defined in the DSP302, but right spelling (for compabiltiy to some tools) strSection = "DeviceCommissioning"; - else if (eds.ContainsKey("DeviceComissioning")) // right section name as defined in the DSP302, (wrong spelling) + else if (eds.ContainsKey("DeviceComissioning")) // right section name as defined in the DSP302, (wrong spelling) strSection = "DeviceComissioning"; if (strSection != ""){ @@ -2492,7 +2492,7 @@ public void Loadfile(string filename) foreach (string s in eds.Keys) { - String pat = @"M([0-9]+)ModuleInfo"; + String pat = @"M([0-9]+)ModuleInfo"; Regex r = new Regex(pat, RegexOptions.IgnoreCase); Match m = r.Match(s); @@ -2710,7 +2710,7 @@ public void Savefile(string filename, InfoSection.Filetype ft) fi.EDSVersionMajor = 4; fi.EDSVersionMinor = 0; - StreamWriter writer = System.IO.File.CreateText(filename); + StreamWriter writer = System.IO.File.CreateText(filename); writer.NewLine = "\n"; fi.Write(writer,ft); di.Write(writer,ft); @@ -2989,7 +2989,7 @@ public UInt32 GetNodeID(string input, out bool nodeidpresent) input = input.Replace(" ", ""); return Convert.ToUInt32(input.Trim(), Getbase(input)); } - + input = input.Replace("$NODEID", dc.NodeID.ToString()); // dc.NodeID is decimal string[] bits = Array.ConvertAll(input.Split('+'), p => p.Trim()); // Split and Trim the value if (bits.Length==1) @@ -3033,7 +3033,7 @@ public bool tryGetODEntry(UInt16 index, out ODentry od) } return false; - } + } //RX COM 0x1400 //RX Map 0x1600 @@ -3044,11 +3044,11 @@ public bool tryGetODEntry(UInt16 index, out ODentry od) public bool CreatePDO(bool rx,UInt16 index) { //check if we are creating an RX PDO it is a valid index - if (rx && (index < 0x1400 || index >= 0x1600)) + if (rx && (index < 0x1400 || index >= 0x1600)) return false; //check if we are creating an PDO TX it is a valid index - if (!rx & (index < 0x1800 || index >= 0x1A00)) + if (!rx & (index < 0x1800 || index >= 0x1A00)) return false; //Check it does not already exist diff --git a/libEDSsharp/extensions.cs b/libEDSsharp/extensions.cs index 6619e303..b76bdbe0 100644 --- a/libEDSsharp/extensions.cs +++ b/libEDSsharp/extensions.cs @@ -25,19 +25,19 @@ public static string ToHexString(this UInt32 val) } - public static class StringExtensions - { - public static bool Contains(this String str, String substring, - StringComparison comp) - { - if (substring == null) - throw new ArgumentNullException("substring", - "substring cannot be null."); - else if (!Enum.IsDefined(typeof(StringComparison), comp)) - throw new ArgumentException("comp is not a member of StringComparison", - "comp"); - - return str.IndexOf(substring, comp) >= 0; - } + public static class StringExtensions + { + public static bool Contains(this String str, String substring, + StringComparison comp) + { + if (substring == null) + throw new ArgumentNullException("substring", + "substring cannot be null."); + else if (!Enum.IsDefined(typeof(StringComparison), comp)) + throw new ArgumentException("comp is not a member of StringComparison", + "comp"); + + return str.IndexOf(substring, comp) >= 0; + } } } From 7ae49787290ef846ce7383cbf94bb111f16b3c1f Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Tue, 12 Mar 2024 19:29:42 +0100 Subject: [PATCH 113/226] cleanup --- .gitattributes | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitattributes b/.gitattributes index 0d03288a..63052248 100644 --- a/.gitattributes +++ b/.gitattributes @@ -3,4 +3,4 @@ # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. -*.cs text \ No newline at end of file +*.cs text From 1b635d699fbb36ab8db52f20fb1faad768be45df Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:17:14 +0100 Subject: [PATCH 114/226] TPDO does no longer have subindex 0x04 (the reserved byte) --- Tests/PDOHelperTests.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Tests/PDOHelperTests.cs b/Tests/PDOHelperTests.cs index 6db83077..b659687b 100644 --- a/Tests/PDOHelperTests.cs +++ b/Tests/PDOHelperTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using Xunit; using libEDSsharp; @@ -53,10 +53,10 @@ public void Test_TPDO() throw new Exception("Mapping paramaters not generated"); } - if (comparamOD.subobjects.Count != 7) + if (comparamOD.subobjects.Count != 6) throw new Exception("Wrong number of sub objects generated"); - if(comparamOD.Nosubindexes!=7) + if(comparamOD.Nosubindexes!=6) throw new Exception("Wrong number of sub objects generated"); if (comparamOD.subobjects[1].datatype != DataType.UNSIGNED32) @@ -65,8 +65,6 @@ public void Test_TPDO() throw new Exception("Wrong data type for Transmission type"); if (comparamOD.subobjects[3].datatype != DataType.UNSIGNED16) throw new Exception("Wrong data type for Inhibit time"); - if (comparamOD.subobjects[4].datatype != DataType.UNSIGNED8) - throw new Exception("Wrong data type for Compatibility Entry"); if (comparamOD.subobjects[5].datatype != DataType.UNSIGNED16) throw new Exception("Wrong data type for Event timer"); if (comparamOD.subobjects[6].datatype != DataType.UNSIGNED8) From 2dfbb9182177b8c6b2bd08733f3332e75e20b606 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Wed, 13 Mar 2024 16:18:21 +0100 Subject: [PATCH 115/226] fixed test after adding TPDO event timer subindex --- Tests/PDOHelperTests.cs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/Tests/PDOHelperTests.cs b/Tests/PDOHelperTests.cs index b659687b..df940964 100644 --- a/Tests/PDOHelperTests.cs +++ b/Tests/PDOHelperTests.cs @@ -130,22 +130,25 @@ public void Test_RPDO() throw new Exception("Mapping paramaters not generated"); } - if (comparamOD.subobjects.Count != 3) + if (comparamOD.subobjects.Count != 4) throw new Exception("Wrong number of sub objects generated"); - if (comparamOD.Nosubindexes != 3) + if (comparamOD.Nosubindexes != 4) throw new Exception("Wrong number of sub objects generated"); if (comparamOD.subobjects[1].datatype != DataType.UNSIGNED32) throw new Exception("Wrong data type for COB"); if (comparamOD.subobjects[2].datatype != DataType.UNSIGNED8) throw new Exception("Wrong data type for Transmission type"); + if (comparamOD.subobjects[5].datatype != DataType.UNSIGNED16) + throw new Exception("Wrong data type for Transmission type"); if (comparamOD.subobjects[1].defaultvalue != "0x401") //481 hex throw new Exception("TPDO COB wrong"); if (comparamOD.subobjects[2].defaultvalue != "254") throw new Exception("TPDO transmission type wrong"); - + if (comparamOD.subobjects[5].defaultvalue != "20") + throw new Exception("TPDO event timer wrong default value"); } From 08f4088f3e8ad91ce167286c1159260549c62f58 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:26:01 +0100 Subject: [PATCH 116/226] Fix test as getflags got a spesial case for index 1003 --- Tests/ExporterTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/ExporterTests.cs b/Tests/ExporterTests.cs index 16f53eeb..2cc37a8a 100644 --- a/Tests/ExporterTests.cs +++ b/Tests/ExporterTests.cs @@ -1,4 +1,4 @@ -using System; +using System; using Xunit; using libEDSsharp; @@ -151,7 +151,7 @@ public void TestArrayNoEntries() od.subobjects.Add(0x03, new ODentry("LINE1", 0x03, DataType.UNSIGNED32, "0x01", EDSsharp.AccessType.ro, PDOMappingType.optional)); test = write_od_line(od); - if (test != "{0x1003, 0x03, 0x06, 0, (void*)&CO_OD_RAM.testArray[0]}," + Environment.NewLine) + if (test != "{0x1003, 0x03, 0x0E, 0, (void*)&CO_OD_RAM.testArray[0]}," + Environment.NewLine) throw (new Exception("TestArrayNoEntries() failed")); From 908c78d10e11ffd9d0ad5b1964a666c80f2f2051 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:34:33 +0100 Subject: [PATCH 117/226] fix test as getflags has added code that makes PDOtype change the flag value --- Tests/ExporterTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ExporterTests.cs b/Tests/ExporterTests.cs index 2cc37a8a..f3fe66de 100644 --- a/Tests/ExporterTests.cs +++ b/Tests/ExporterTests.cs @@ -44,7 +44,7 @@ public void Test_record_objects() subod = new ODentry("Test String 2", 0x01, DataType.VISIBLE_STRING, new string('*', 255), EDSsharp.AccessType.ro, PDOMappingType.optional, od); test = export_one_record_type(subod, ""); - if (test != " {(void*)&CO_OD_RAM.testRecord.testString2, 0x26, 0xFF }," + Environment.NewLine) + if (test != " {(void*)&CO_OD_RAM.testRecord.testString2, 0x36, 0xFF }," + Environment.NewLine) throw (new Exception("export_one_record_type() error test 2")); } From d6bdaf842490f293d51da34b993c42aa61050765 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Wed, 13 Mar 2024 19:42:57 +0100 Subject: [PATCH 118/226] Fixed test that i think is wrong, changing from 32 arrays of 4 to 4 arrays of 32 --- Tests/ExporterTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Tests/ExporterTests.cs b/Tests/ExporterTests.cs index f3fe66de..062b2345 100644 --- a/Tests/ExporterTests.cs +++ b/Tests/ExporterTests.cs @@ -78,7 +78,7 @@ public void TestArrays() string test = print_h_entry(od); - if (test != "/*2000 */ VISIBLE_STRING testArray[32][4];" + Environment.NewLine) + if (test != "/*2000 */ VISIBLE_STRING testArray[4][32];" + Environment.NewLine) throw (new Exception("TestArrays() test 1 failed")); From caf97145043003204a77a916adf0b37b92423011 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Wed, 13 Mar 2024 21:26:07 +0100 Subject: [PATCH 119/226] Not sure if this is the correct fix --- libEDSsharp/CanOpenXDD.cs | 28 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 14 deletions(-) diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 9b8bf1ee..b13c3834 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -1,4 +1,4 @@ -/* +/* This file is part of libEDSsharp. libEDSsharp is free software: you can redistribute it and/or modify @@ -639,8 +639,8 @@ public ISO15745ProfileContainer convert(EDSsharp eds) NetworkManagement.CANopenGeneralFeatures.bootUpSlave = eds.di.SimpleBootUpSlave; //NetworkManagment.CANopenGeneralFeatures.dynamicChannels = eds.di.DynamicChannelsSupported; //fix me count of dynamic channels not handled yet eds only has bool NetworkManagement.CANopenGeneralFeatures.granularity = eds.di.Granularity; - NetworkManagement.CANopenGeneralFeatures.groupMessaging = eds.di.GroupMessaging; - + NetworkManagement.CANopenGeneralFeatures.groupMessaging = eds.di.GroupMessaging; + NetworkManagement.CANopenGeneralFeatures.ngMaster = eds.di.NG_Master; NetworkManagement.CANopenGeneralFeatures.ngSlave = eds.di.NG_Slave; NetworkManagement.CANopenGeneralFeatures.NrOfNG_MonitoredNodes = eds.di.NrOfNG_MonitoredNodes; @@ -918,9 +918,9 @@ public EDSsharp convert(ISO15745ProfileContainer container) } eds.di.NG_Master = NetworkManagment.CANopenGeneralFeatures.ngMaster; - eds.di.NG_Slave = NetworkManagment.CANopenGeneralFeatures.ngSlave; - eds.di.NrOfNG_MonitoredNodes = NetworkManagment.CANopenGeneralFeatures.NrOfNG_MonitoredNodes; - + eds.di.NG_Slave = NetworkManagment.CANopenGeneralFeatures.ngSlave; + eds.di.NrOfNG_MonitoredNodes = NetworkManagment.CANopenGeneralFeatures.NrOfNG_MonitoredNodes; + eds.di.NrOfRXPDO = NetworkManagment.CANopenGeneralFeatures.nrOfRxPDO; eds.di.NrOfTXPDO = NetworkManagment.CANopenGeneralFeatures.nrOfTxPDO; @@ -1118,7 +1118,7 @@ public EDSsharp convert(ISO15745ProfileContainer container) subentry.uniqueID = subobj.uniqueIDRef; - entry.subobjects.Add(subobj.subIndex[0], subentry); + entry.subobjects.Add(subobj.subIndex[1], subentry); } } @@ -3832,8 +3832,8 @@ public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementCA private ushort nrOfTxPDOField; private bool ngMasterField; - private bool ngSlaveField; - private ushort NrOfNG_MonitoredNodesField; + private bool ngSlaveField; + private ushort NrOfNG_MonitoredNodesField; private bool bootUpSlaveField; private bool layerSettingServiceSlaveField; @@ -4001,18 +4001,18 @@ public bool ngMaster { this.ngMasterField = value; } - } - + } + /// [System.Xml.Serialization.XmlAttributeAttribute()] [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] - public ushort NrOfNG_MonitoredNodes + public ushort NrOfNG_MonitoredNodes { - get + get { return this.NrOfNG_MonitoredNodesField; } - set + set { this.NrOfNG_MonitoredNodesField = value; } From 8c21a1ab5a2b89a571241ca6cf6cd8c92d9c5644 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Fri, 15 Mar 2024 13:51:01 +0100 Subject: [PATCH 120/226] impliment hack to make it work with file from issue 29 and test --- libEDSsharp/CanOpenXDD.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index b13c3834..616b534f 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -1,4 +1,4 @@ -/* +/* This file is part of libEDSsharp. libEDSsharp is free software: you can redistribute it and/or modify @@ -1118,7 +1118,7 @@ public EDSsharp convert(ISO15745ProfileContainer container) subentry.uniqueID = subobj.uniqueIDRef; - entry.subobjects.Add(subobj.subIndex[1], subentry); + entry.subobjects.Add(subobj.subIndex[subobj.subIndex.Length - 1], subentry); } } From 52384a59957feb1cab9fd2cb950d1518caf65c4b Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Fri, 15 Mar 2024 15:45:17 +0100 Subject: [PATCH 121/226] enable unittests (#81) * fixed the action to use run the tests * change Tests project to also use .net 4.8.1 (like the rest) --- .github/workflows/dotnet.yml | 11 +++++++---- Tests/Tests.csproj | 14 +++++++------- 2 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 5e96e36f..7a7e9bcd 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -24,13 +24,16 @@ jobs: - name: Add Packages run: | nuget install EDSEditorGUI/packages.config -OutputDirectory packages -# nuget install Tests/packages.config -OutputDirectory packages + nuget install Tests/packages.config -OutputDirectory packages - name: Build # run: make all # builds the Debug configuration - run: msbuild EDSEditorGUI /property:Configuration=Release + run: | + msbuild /property:Configuration=Release + msbuild /property:Configuration=Debug # run: dotnet build --no-restore -# - name: Test -# run: dotnet test --no-build --verbosity normal + - name: Test + run: | + dotnet test --no-build --verbosity normal - name: Upload Artifact uses: actions/upload-artifact@v3 with: diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 77ded76c..cf64956a 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -11,7 +11,7 @@ Properties Tests Tests - v4.8 + v4.8.1 512 {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} 10.0 @@ -114,11 +114,11 @@ - \ No newline at end of file From df0c5c72780dfc056fac046fe5271b844fd2f79e Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 16 Mar 2024 13:20:50 +0100 Subject: [PATCH 122/226] add dependabot to keep gh action up-to-date (#83) --- .github/dependabot.yml | 11 +++++++++++ 1 file changed, 11 insertions(+) create mode 100644 .github/dependabot.yml diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 00000000..92c44a82 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +# To get started with Dependabot version updates, you'll need to specify which +# package ecosystems to update and where the package manifests are located. +# Please see the documentation for all configuration options: +# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" From 988dd3726f2afcff3a71b0e22679768d593890f7 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 16 Mar 2024 13:21:18 +0100 Subject: [PATCH 123/226] gh action cs problem matcher (#84) * added c# problem matcher --- .github/workflows/dotnet.yml | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 7a7e9bcd..b13d206b 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -16,6 +16,10 @@ jobs: uses: actions/checkout@v3 - name: Setup .NET uses: microsoft/setup-msbuild@v1.1 + - name: C# problem matcher + run: | + Invoke-WebRequest "https://raw.githubusercontent.com/actions/setup-dotnet/main/.github/csc.json" -OutFile "csc.json" + echo "::add-matcher::csc.json" # uses: actions/setup-dotnet@v2 # with: # dotnet-version: 5.0.x From 140f4539d3c83e85d708a080659d5214602c9004 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 19:33:40 +0000 Subject: [PATCH 124/226] Bump actions/upload-artifact from 3 to 4 Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 3 to 4. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index b13d206b..013891da 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -39,7 +39,7 @@ jobs: run: | dotnet test --no-build --verbosity normal - name: Upload Artifact - uses: actions/upload-artifact@v3 + uses: actions/upload-artifact@v4 with: name: EDSEditor path: EDSEditorGUI\bin\Release\ From 84d393659755e18db7c1d64515dec0d85b2c9327 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 19:33:43 +0000 Subject: [PATCH 125/226] Bump microsoft/setup-msbuild from 1.1 to 1.3 Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.1 to 1.3. - [Release notes](https://github.com/microsoft/setup-msbuild/releases) - [Changelog](https://github.com/microsoft/setup-msbuild/blob/main/building-release.md) - [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.1...v1.3) --- updated-dependencies: - dependency-name: microsoft/setup-msbuild dependency-type: direct:production update-type: version-update:semver-minor ... Signed-off-by: dependabot[bot] --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index b13d206b..406e1873 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -15,7 +15,7 @@ jobs: - name: Checkout uses: actions/checkout@v3 - name: Setup .NET - uses: microsoft/setup-msbuild@v1.1 + uses: microsoft/setup-msbuild@v1.3 - name: C# problem matcher run: | Invoke-WebRequest "https://raw.githubusercontent.com/actions/setup-dotnet/main/.github/csc.json" -OutFile "csc.json" From 4e1e9294a5e200d3b533d3ffb6193db6a43fc13a Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Sun, 17 Mar 2024 20:02:51 +0000 Subject: [PATCH 126/226] Bump actions/checkout from 3 to 4 Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v3...v4) --- updated-dependencies: - dependency-name: actions/checkout dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 406e1873..5b8e47ad 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -13,7 +13,7 @@ jobs: # runs-on: ubuntu-latest # Error: setup-msbuild can only be run on Windows runners steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Setup .NET uses: microsoft/setup-msbuild@v1.3 - name: C# problem matcher From 2f3afd76c721e01e712078f02dce0300bf03585e Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sun, 24 Mar 2024 15:20:38 +0100 Subject: [PATCH 127/226] Switch to sdk project style to allow building with multiple .net versions (#89) * ran the upgrade tool * Fixed build net 481 * Set EmbeddedResourceUseDependentUponConvention to true to fix embedded resource exception ref: https://stackoverflow.com/questions/67745025/resource-exceptions-in-forms-after-converting-project-to-netsdk-format * switched to dotnet restore to install dependencies --- .github/workflows/dotnet.yml | 3 +- EDSEditorGUI/EDSEditorGUI.csproj | 236 +++---------------------------- EDSSharp/EDSSharp.csproj | 57 +------- Tests/Tests.csproj | 102 +++---------- libEDSsharp/libEDSsharp.csproj | 74 ++-------- 5 files changed, 54 insertions(+), 418 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index e1b4d4c9..9a56aada 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -27,8 +27,7 @@ jobs: # run: dotnet restore - name: Add Packages run: | - nuget install EDSEditorGUI/packages.config -OutputDirectory packages - nuget install Tests/packages.config -OutputDirectory packages + dotnet restore - name: Build # run: make all # builds the Debug configuration run: | diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index bd713c33..9c5918cf 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -1,18 +1,10 @@ - - - + - Debug - AnyCPU - {13D2D8ED-242B-4283-BF14-AA79FE875F7C} + net481 WinExe - Properties ODEditor EDSEditor - v4.8.1 - 512 false - publish\ true Disk @@ -27,28 +19,10 @@ 1.0.0.%2a false true - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false - false + false + true + true + true Index_8287_16x.ico @@ -62,178 +36,38 @@ True .\Microsoft.mshtml.dll - - ..\packages\SourceGrid.4.4.0\lib\net35\SourceGrid.dll - - - - - - - - - - - - + UserControl - - DeviceInfoView.cs - - + UserControl - - DeviceODView.cs - - + UserControl - - DevicePDOView2.cs - - + UserControl - - DeviceView.cs - - - Form - - - Form1.cs - - + Component - + UserControl - - ModuleInfo.cs - - + UserControl - - Form - - - InsertObjects.cs - - - Form - - - NewIndex.cs - - - Form - - - NewItem.cs - - - Form - - - Preferences.cs - - - - - Form - - - ReportView.cs - - + Component - - - Form - - - Warnings.cs - - - DeviceInfoView.cs - - - DeviceODView.cs - - - DevicePDOView2.cs - - - DeviceView.cs - - - Form1.cs - - - ModuleInfo.cs - - - MyTabUserControl.cs - - - InsertObjects.cs - - - NewIndex.cs - - - NewItem.cs - - - Preferences.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - ReportView.cs - - - Warnings.cs - - - - + PreserveNewest - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - + @@ -258,42 +92,16 @@ Always - - - - - - - - - - PreserveNewest - - - - - - - - - - - - - - + + + + + - git describe --tags --long --dirty > "$(ProjectDir)version.txt" || exit 0 + git describe --tags --long --dirty > "$(MSBuildProjectDirectory)\version.txt" || exit 0 - \ No newline at end of file diff --git a/EDSSharp/EDSSharp.csproj b/EDSSharp/EDSSharp.csproj index 6e4cebd6..66e70fc1 100644 --- a/EDSSharp/EDSSharp.csproj +++ b/EDSSharp/EDSSharp.csproj @@ -1,59 +1,14 @@ - - - + - Debug - AnyCPU - {8B7A7545-6257-44BF-8868-F429E1B72C77} + net481 Exe - EDSSharp - EDSSharp - v4.8.1 - 512 - true - + false - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - - - - - - - - - - - - + - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - + + - \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index cf64956a..e21101b0 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,60 +1,9 @@ - - - - - + - Debug - AnyCPU - {2A479BF3-7628-409B-8A29-9314C308445E} + net481 Library - Properties - Tests - Tests - v4.8.1 - 512 - {3AC096D0-A1C2-E12C-1390-A8335801FDAB};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} - 10.0 - $(MSBuildExtensionsPath32)\Microsoft\VisualStudio\v$(VisualStudioVersion) - $(ProgramFiles)\Common Files\microsoft shared\VSTT\$(VisualStudioVersion)\UITestExtensionPackages - False - UnitTest - - - + false - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - - - ..\packages\xunit.abstractions.2.0.3\lib\net35\xunit.abstractions.dll - - - ..\packages\xunit.assert.2.4.2\lib\netstandard1.1\xunit.assert.dll - - - ..\packages\xunit.extensibility.core.2.4.2\lib\net452\xunit.core.dll - - - ..\packages\xunit.extensibility.execution.2.4.2\lib\net452\xunit.execution.desktop.dll - - @@ -64,25 +13,25 @@ - - - - - - + - - {cc0fa4b1-2bfc-43b3-8c56-b428df2d24e7} - libEDSsharp - + + - + + + + + + + + + - - + @@ -102,23 +51,4 @@ - - - - - This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}. - - - - - - - - \ No newline at end of file diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 5b6c3000..e46aeff5 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -1,83 +1,27 @@ - - - + - Debug - AnyCPU - {CC0FA4B1-2BFC-43B3-8C56-B428DF2D24E7} + net481 Library - Properties - libEDSsharp - libEDSsharp - v4.8.1 - 512 - - - - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false + false - pdbonly - true - bin\Release\ - TRACE - prompt - 4 docs\libEDSsharp.xml - false - - - - - - - - - - - - - - - - - - - - - - - - + True True Resources.resx - - - - + ResXFileCodeGenerator Resources.Designer.cs - - + + + + \ No newline at end of file From dc2ead8bca35484c557ff6dea7b43e4d1b76666a Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Tue, 26 Mar 2024 15:04:30 +0100 Subject: [PATCH 128/226] unittests: exporters of string (#90) --- Tests/ExporterTests.cs | 21 ++++ Tests/ExporterTestsV4.cs | 250 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 270 insertions(+), 1 deletion(-) diff --git a/Tests/ExporterTests.cs b/Tests/ExporterTests.cs index 062b2345..70b89821 100644 --- a/Tests/ExporterTests.cs +++ b/Tests/ExporterTests.cs @@ -158,6 +158,27 @@ public void TestArrayNoEntries() } + /// + /// Check the var string is exportet correctly + /// + [Theory] + [InlineData(1, "")] + [InlineData(5, "12345")] + void TestVarString(int expectedLength, string defaultvalue) + { + var od = new ODentry + { + objecttype = ObjectType.VAR, + datatype = DataType.VISIBLE_STRING, + parameter_name = "test string", + accesstype = EDSsharp.AccessType.ro, + Index = 0x2000 + }; + od.defaultvalue = defaultvalue; + var test = print_h_entry(od); + Assert.Equal(test, $"/*{od.Index:X} */ VISIBLE_STRING testString[{expectedLength}];" + Environment.NewLine); + } + /// /// Check size of objects is correct /// diff --git a/Tests/ExporterTestsV4.cs b/Tests/ExporterTestsV4.cs index 46cc1cb8..1d040355 100644 --- a/Tests/ExporterTestsV4.cs +++ b/Tests/ExporterTestsV4.cs @@ -1,4 +1,6 @@ -using System; +using System; +using System.Collections.Generic; +using System.IO; using Xunit; using libEDSsharp; @@ -6,6 +8,43 @@ namespace Tests { public class ExporterTestsV4 : CanOpenNodeExporter_V4 { + readonly EDSsharp _eds; + public ExporterTestsV4() + { + _eds = new EDSsharp(); + } + + void GetExportResult(EDSsharp eds, out IEnumerable cfile, out IEnumerable hfile) + { + var fullPath = Path.GetTempFileName(); + var tempfile = Path.GetFileName(fullPath); + var path = Path.GetTempPath(); + + var cfilePath = fullPath + ".c"; + var hfilePath = fullPath + ".h"; + export(path, tempfile, ".", eds, "OD_Test"); + cfile = File.ReadLines(cfilePath); + hfile = File.ReadLines(hfilePath); + } + + bool FindExpectedLines(IEnumerable lines, List expectedLines) + { + var expectedMatchCount = expectedLines.Count; + var matchedCounter = 0; + + foreach (var line in lines) + { + if (line == expectedLines[matchedCounter]) + { + matchedCounter++; + + if (expectedMatchCount == matchedCounter) + return true; + } + } + return false; + } + [Fact] public void Test_Make_cname_conversion() { @@ -31,5 +70,214 @@ public void Test_Make_cname_conversion() throw (new Exception("Make_cname Conversion error")); } + + [Fact] + public void TestVariableStringZeroData() + { + ODentry od = new ODentry + { + objecttype = ObjectType.VAR, + datatype = DataType.VISIBLE_STRING, + parameter_name = "test string", + accesstype = EDSsharp.AccessType.ro, + Index = 0x2000 + }; + + _eds.ods.Add(0x2000, od); + + GetExportResult(_eds, out var cfile, out var hfile); + Assert.True(FindExpectedLines(hfile, new List { "#define OD_Test_ENTRY_H2000 &OD_Test->list[0]" })); + Assert.True(FindExpectedLines(hfile, new List { "#define OD_Test_ENTRY_H2000_testString &OD_Test->list[0]" })); + + Assert.True(FindExpectedLines(cfile, new List { + "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + " .o_2000_testString = {", + " .dataOrig = NULL,", + " .attribute = ODA_SDO_R | ODA_STR,", + " .dataLength = 0", + " }", + "};"})); + + Assert.True(FindExpectedLines(cfile, new List { + "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", + " {0x2000, 0x01, ODT_VAR, &OD_TestObjs.o_2000_testString, NULL},", + " {0x0000, 0x00, 0, NULL, NULL}", + "};"})); + } + + [Theory] + [InlineData("12345", 0, 5, "'1', '2', '3', '4', '5', 0")] + [InlineData("12345", 10, 10, "'1', '2', '3', '4', '5', 0, 0, 0, 0, 0, 0")] + public void TestVariableString(string defaultValue, uint stringLengthMin, int expectedLength, string expectedInitialValues) + { + ODentry od = new ODentry + { + objecttype = ObjectType.VAR, + datatype = DataType.VISIBLE_STRING, + parameter_name = "test string", + accesstype = EDSsharp.AccessType.ro, + Index = 0x2000, + defaultvalue = defaultValue + }; + od.prop.CO_stringLengthMin = stringLengthMin; + + _eds.ods.Add(0x2000, od); + + GetExportResult(_eds, out var cfile, out var _); + + Assert.True(FindExpectedLines(cfile, new List { + "OD_Test_ATTR_RAM OD_Test_RAM_t OD_Test_RAM = {", + $" .x2000_testString = {{{expectedInitialValues}}}", + "};"})); + + Assert.True(FindExpectedLines(cfile, new List { + "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + " .o_2000_testString = {", + " .dataOrig = &OD_Test_RAM.x2000_testString[0],", + " .attribute = ODA_SDO_R | ODA_STR,", + $" .dataLength = {expectedLength}", + " }", + "};"})); + + Assert.True(FindExpectedLines(cfile, new List { + "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", + " {0x2000, 0x01, ODT_VAR, &OD_TestObjs.o_2000_testString, NULL},", + " {0x0000, 0x00, 0, NULL, NULL}", + "};"})); + } + + [Theory] + [InlineData("", 10, 10, "0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0")] // only min length + [InlineData("12345", 10, 10, "'1', '2', '3', '4', '5', 0, 0, 0, 0, 0, 0")] // default & min length + [InlineData("12345", 0, 5, "'1', '2', '3', '4', '5', 0")] // default only + public void TestRecordWithString(string defaultValue, uint stringLengthMin, int expectedLength, string expectedInitialValues) + { + ODentry od = new ODentry + { + objecttype = ObjectType.RECORD, + parameter_name = "test rec", + accesstype = EDSsharp.AccessType.ro, + Index = 0x2000 + }; + + od.addsubobject(0, new ODentry("numElements", 0x2000, DataType.UNSIGNED8, "0", EDSsharp.AccessType.rw, PDOMappingType.optional)); + od.addsubobject(1, new ODentry("str", 0x2000, DataType.VISIBLE_STRING, defaultValue, EDSsharp.AccessType.rw, PDOMappingType.optional)); + od.subobjects[1].prop.CO_stringLengthMin = stringLengthMin; + _eds.ods.Add(0x2000, od); + + GetExportResult(_eds, out var cfile, out var hfile); + Assert.True(FindExpectedLines(hfile, new List { + "typedef struct {", + " struct {", + " uint8_t numElements;", + $" char str[{expectedLength+1}];", + " } x2000_testRec;", + "} OD_Test_RAM_t;"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "OD_Test_ATTR_RAM OD_Test_RAM_t OD_Test_RAM = {", + " .x2000_testRec = {", + " .numElements = 0x00,", + $" .str = {{{expectedInitialValues}}}", + " }", + "};"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "typedef struct {", + " OD_obj_record_t o_2000_testRec[2];", + "} OD_TestObjs_t;"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + " .o_2000_testRec = {", + " {", + " .dataOrig = &OD_Test_RAM.x2000_testRec.numElements,", + " .subIndex = 0,", + " .attribute = ODA_SDO_RW | ODA_TRPDO,", + " .dataLength = 1", + " },", + " {", + " .dataOrig = &OD_Test_RAM.x2000_testRec.str[0],", + " .subIndex = 1,", + " .attribute = ODA_SDO_RW | ODA_TRPDO | ODA_STR,", + $" .dataLength = {expectedLength}", + " }", + " }", + "};"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", + " {0x2000, 0x02, ODT_REC, &OD_TestObjs.o_2000_testRec, NULL},", + " {0x0000, 0x00, 0, NULL, NULL}", + "};"})); + } + + [Fact] + public void TestRecordWithZeroLengthString() + { + ODentry od = new ODentry + { + objecttype = ObjectType.RECORD, + parameter_name = "test rec", + accesstype = EDSsharp.AccessType.ro, + Index = 0x2000 + }; + + od.addsubobject(0, new ODentry("numElements", 0x2000, DataType.UNSIGNED8, "0", EDSsharp.AccessType.rw, PDOMappingType.optional)); + od.addsubobject(1, new ODentry("str", 0x2000, DataType.VISIBLE_STRING, "", EDSsharp.AccessType.rw, PDOMappingType.optional)); + _eds.ods.Add(0x2000, od); + + GetExportResult(_eds, out var cfile, out var hfile); + Assert.True(FindExpectedLines(hfile, new List { + "typedef struct {", + " struct {", + " uint8_t numElements;", + " } x2000_testRec;", + "} OD_Test_RAM_t;"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "OD_Test_ATTR_RAM OD_Test_RAM_t OD_Test_RAM = {", + " .x2000_testRec = {", + " .numElements = 0x00", + " }", + "};"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "typedef struct {", + " OD_obj_record_t o_2000_testRec[2];", + "} OD_TestObjs_t;"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + " .o_2000_testRec = {", + " {", + " .dataOrig = &OD_Test_RAM.x2000_testRec.numElements,", + " .subIndex = 0,", + " .attribute = ODA_SDO_RW | ODA_TRPDO,", + " .dataLength = 1", + " },", + " {", + " .dataOrig = NULL,", + " .subIndex = 1,", + " .attribute = ODA_SDO_RW | ODA_TRPDO | ODA_STR,", + " .dataLength = 0", + " }", + " }", + "};"})); + + Assert.True(FindExpectedLines(cfile, new List + { + "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", + " {0x2000, 0x02, ODT_REC, &OD_TestObjs.o_2000_testRec, NULL},", + " {0x0000, 0x00, 0, NULL, NULL}", + "};"})); + } } } From 219eb3fdece2f4ff791e47ab7c714cf66cfafbeb Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Wed, 27 Mar 2024 16:20:33 +0100 Subject: [PATCH 129/226] Included import export test (#91) * fixed,updated and included ImportExporttest changed to xunit updated the tests so it compiles included it in the project * formating & cleanup * switch from throw exception to xunit assert on test fail * Moved code from ImportExportTest into ExportTests --- Tests/ExporterTests.cs | 160 ++++++++++++++++++++++++++++++++ Tests/ImportExportTest.cs | 189 -------------------------------------- Tests/Tests.csproj | 3 - 3 files changed, 160 insertions(+), 192 deletions(-) delete mode 100644 Tests/ImportExportTest.cs diff --git a/Tests/ExporterTests.cs b/Tests/ExporterTests.cs index 70b89821..7c10657b 100644 --- a/Tests/ExporterTests.cs +++ b/Tests/ExporterTests.cs @@ -226,5 +226,165 @@ public void TestExportSizes() } + [Fact] + public void TestImportExportVar() + { + eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + + ODentry od = new ODentry + { + objecttype = ObjectType.VAR, + datatype = DataType.UNSIGNED8, + parameter_name = "Test VAR", + accesstype = EDSsharp.AccessType.ro, + PDOtype = PDOMappingType.optional, + Index = 0x2000 + }; + + eds.ods.Add(0x2000, od); + + string tempfile = System.IO.Path.GetTempFileName(); + eds.Savefile(tempfile, InfoSection.Filetype.File_EDS); + + eds = new EDSsharp(); + eds.Loadfile(tempfile); + + od = eds.ods[0x2000]; + + Assert.True(od.PDOtype == PDOMappingType.optional, "TPDOMappingType.optional not set in EDS for VAR"); + } + + /// + [Fact] + public void TestImportExportRecord() + { + eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + + ODentry od = new ODentry + { + objecttype = ObjectType.RECORD, + parameter_name = "Test REC", + Index = 0x2000 + }; + + ODentry sub = new ODentry + { + parameter_name = "max sub-index", + datatype = DataType.UNSIGNED8, + parent = od, + accesstype = EDSsharp.AccessType.ro, + defaultvalue = "1", + PDOtype = PDOMappingType.no, + objecttype = ObjectType.VAR + }; + + od.subobjects.Add(0x00, sub); + + sub = new ODentry + { + parameter_name = "entry 1", + datatype = DataType.UNSIGNED8, + parent = od, + accesstype = EDSsharp.AccessType.rw, + defaultvalue = "0", + PDOtype = PDOMappingType.optional, + objecttype = ObjectType.VAR + }; + + od.subobjects.Add(0x01, sub); + + eds.ods.Add(0x2000, od); + + string tempfile = System.IO.Path.GetTempFileName(); + eds.Savefile(tempfile, InfoSection.Filetype.File_EDS); + + eds = new EDSsharp(); + eds.Loadfile(tempfile); + + od = eds.ods[0x2000]; + + Assert.True(od.subobjects[1].PDOtype == PDOMappingType.optional, "TPDOMappingType.optional not set in EDS for REC"); + } + + [Fact] + public void TestImportExportArray() + { + + // NOTE although can opennode does not support per array entry flags, they are supported in EDS + // so the PDOtype and TPDODetectCos flags are set per array entry (every VAR sub object) but + // they all must be the same + // and they should not exist on the parent object. + + eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + + ODentry od = new ODentry + { + objecttype = ObjectType.ARRAY, + datatype = DataType.UNSIGNED32, + parameter_name = "Test Array", + accesstype = EDSsharp.AccessType.rw, + Index = 0x2000 + }; + + ODentry sub = new ODentry + { + parameter_name = "max sub-index", + datatype = DataType.UNSIGNED8, + parent = od, + accesstype = EDSsharp.AccessType.ro, + PDOtype = PDOMappingType.no, + defaultvalue = "2", + objecttype = ObjectType.VAR + }; + + od.subobjects.Add(0x00, sub); + + sub = new ODentry + { + parameter_name = "entry 1", + datatype = DataType.UNSIGNED32, + parent = od, + accesstype = EDSsharp.AccessType.rw, + defaultvalue = "0", + objecttype = ObjectType.VAR, + PDOtype = PDOMappingType.optional + }; + + od.subobjects.Add(0x01, sub); + + sub = new ODentry + { + parameter_name = "entry 2", + datatype = DataType.UNSIGNED32, + parent = od, + accesstype = EDSsharp.AccessType.rw, + defaultvalue = "0", + objecttype = ObjectType.VAR, + PDOtype = PDOMappingType.optional + }; + + od.subobjects.Add(0x02, sub); + + eds.ods.Add(0x2000, od); + + string tempfile = System.IO.Path.GetTempFileName(); + eds.Savefile(tempfile, InfoSection.Filetype.File_EDS); + + eds = new EDSsharp(); + eds.Loadfile(tempfile); + + od = eds.ods[0x2000]; + + Assert.True(od.subobjects[1].PDOtype == PDOMappingType.optional, "TPDOMappingType.optional not set in EDS for ARRAY"); + } } } diff --git a/Tests/ImportExportTest.cs b/Tests/ImportExportTest.cs deleted file mode 100644 index 2b537e1b..00000000 --- a/Tests/ImportExportTest.cs +++ /dev/null @@ -1,189 +0,0 @@ -using System; -using Microsoft.VisualStudio.TestTools.UnitTesting; -using libEDSsharp; - -namespace Tests -{ - [TestClass] - public class EdsImportExportTest : CanOpenNodeExporter - { - /// - [TestMethod] - public void TestImportExportVar() - { - - eds = new EDSsharp - { - ods = new System.Collections.Generic.SortedDictionary() - }; - - ODentry od = new ODentry - { - objecttype = ObjectType.VAR, - datatype = DataType.UNSIGNED8, - parameter_name = "Test VAR", - accesstype = EDSsharp.AccessType.ro, - TPDODetectCos = true, - PDOtype = PDOMappingType.optional, - Index = 0x2000 - }; - - eds.ods.Add(0x2000, od); - - string tempfile = System.IO.Path.GetTempFileName(); - eds.Savefile(tempfile,InfoSection.Filetype.File_EDS); - - eds = new EDSsharp(); - eds.Loadfile(tempfile); - - od = eds.ods[0x2000]; - - if (od.TPDODetectCos == false) - throw new Exception("TPDODetect not set in EDS for VAR"); - - if (od.PDOtype != PDOMappingType.optional) - throw new Exception("TPDOMappingType.optional not set in EDS for VAR"); - - } - - /// - [TestMethod] - public void TestImportExportRecord() - { - - eds = new EDSsharp - { - ods = new System.Collections.Generic.SortedDictionary() - }; - - ODentry od = new ODentry - { - objecttype = ObjectType.REC, - parameter_name = "Test REC", - Index = 0x2000 - }; - - ODentry sub = new ODentry(); - sub.parameter_name = "max sub-index"; - sub.datatype = DataType.UNSIGNED8; - sub.parent = od; - sub.accesstype = EDSsharp.AccessType.ro; - sub.defaultvalue = "1"; - sub.PDOtype = PDOMappingType.no; - sub.objecttype = ObjectType.VAR; - - od.subobjects.Add(0x00, sub); - - sub = new ODentry(); - sub.parameter_name = "entry 1"; - sub.datatype = DataType.UNSIGNED8; - sub.parent = od; - sub.accesstype = EDSsharp.AccessType.rw; - sub.defaultvalue = "0"; - sub.PDOtype = PDOMappingType.optional; - sub.objecttype = ObjectType.VAR; - sub.TPDODetectCos = true; - - od.subobjects.Add(0x01, sub); - - eds.ods.Add(0x2000, od); - - string tempfile = System.IO.Path.GetTempFileName(); - eds.Savefile(tempfile, InfoSection.Filetype.File_EDS); - - eds = new EDSsharp(); - eds.Loadfile(tempfile); - - od = eds.ods[0x2000]; - - if (od.subobjects[1].TPDODetectCos == false) - throw new Exception("TPDODetect not set in EDS for REC"); - - if (od.subobjects[1].PDOtype != PDOMappingType.optional) - throw new Exception("TPDOMappingType.optional not set in EDS for REC"); - - } - - [TestMethod] - public void TestImportExportArray() - { - - // NOTE although can opennode does not support per array entry flags, they are supported in EDS - // so the PDOtype and TPDODetectCos flags are set per array entry (every VAR sub object) but - // they all must be the same - // and they should not exist on the parent object. - - eds = new EDSsharp - { - ods = new System.Collections.Generic.SortedDictionary() - }; - - ODentry od = new ODentry - { - objecttype = ObjectType.ARRAY, - datatype = DataType.UNSIGNED32, - parameter_name = "Test Array", - accesstype = EDSsharp.AccessType.rw, - Index = 0x2000 - }; - - ODentry sub = new ODentry(); - sub.parameter_name = "max sub-index"; - sub.datatype = DataType.UNSIGNED8; - sub.parent = od; - sub.accesstype = EDSsharp.AccessType.ro; - sub.PDOtype = PDOMappingType.no; - - - sub.defaultvalue = "2"; - sub.objecttype = ObjectType.VAR; - - od.subobjects.Add(0x00, sub); - - sub = new ODentry(); - sub.parameter_name = "entry 1"; - sub.datatype = DataType.UNSIGNED32; - sub.parent = od; - sub.accesstype = EDSsharp.AccessType.rw; - sub.defaultvalue = "0"; - sub.objecttype = ObjectType.VAR; - sub.PDOtype = PDOMappingType.optional; - sub.TPDODetectCos = true; - - od.subobjects.Add(0x01, sub); - - sub = new ODentry(); - sub.parameter_name = "entry 2"; - sub.datatype = DataType.UNSIGNED32; - sub.parent = od; - sub.accesstype = EDSsharp.AccessType.rw; - sub.defaultvalue = "0"; - sub.objecttype = ObjectType.VAR; - sub.PDOtype = PDOMappingType.optional; - sub.TPDODetectCos = true; - - od.subobjects.Add(0x02, sub); - - eds.ods.Add(0x2000, od); - - string tempfile = System.IO.Path.GetTempFileName(); - eds.Savefile(tempfile, InfoSection.Filetype.File_EDS); - - eds = new EDSsharp(); - eds.Loadfile(tempfile); - - od = eds.ods[0x2000]; - - if (od.subobjects[1].TPDODetectCos == false) - throw new Exception("TPDODetect not set in EDS for ARRAY"); - - if (od.subobjects[1].PDOtype != PDOMappingType.optional) - throw new Exception("TPDOMappingType.optional not set in EDS for ARRAY"); - - - - } - - - } -} diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index e21101b0..be5426a3 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -30,9 +30,6 @@ - - - From 879f0f1b967c32508f0ed90e49f82fc5f77d961f Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Wed, 27 Mar 2024 17:28:57 +0100 Subject: [PATCH 130/226] cleanup & upgrade of the test project and its nugets (#92) --- Tests/Tests.csproj | 50 ++++++++++------------------------------------ 1 file changed, 11 insertions(+), 39 deletions(-) diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index be5426a3..bfdc6680 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -4,48 +4,20 @@ Library false - - - - - - - - - - + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + - - - - - - - - - - - - - - - - False - - - False - - - False - - - False - - - - \ No newline at end of file From 10c759a0239a3cdf3a944cfa93b8bfaeee1c1330 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Thu, 28 Mar 2024 09:36:12 +0100 Subject: [PATCH 131/226] Normalize line ending *.csproj (#93) * changed gitattributes to include csproj * checked in all csproj again. Just line ending changes --- .gitattributes | 1 + EDSEditorGUI/EDSEditorGUI.csproj | 212 +++++++++++++++---------------- EDSSharp/EDSSharp.csproj | 26 ++-- Tests/Tests.csproj | 44 +++---- libEDSsharp/libEDSsharp.csproj | 52 ++++---- 5 files changed, 168 insertions(+), 167 deletions(-) diff --git a/.gitattributes b/.gitattributes index 63052248..6bf80d41 100644 --- a/.gitattributes +++ b/.gitattributes @@ -4,3 +4,4 @@ # Explicitly declare text files you want to always be normalized and converted # to native line endings on checkout. *.cs text +*.csproj text diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 9c5918cf..9f52906e 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -1,107 +1,107 @@ - - - net481 - WinExe - ODEditor - EDSEditor - false - publish\ - true - Disk - false - Foreground - 7 - Days - false - false - true - 0 - 1.0.0.%2a - false - true - false - true - true - true - - - Index_8287_16x.ico - - - app.manifest - - - - False - True - .\Microsoft.mshtml.dll - - - - - UserControl - - - UserControl - - - UserControl - - - UserControl - - - Component - - - UserControl - - - UserControl - - - Component - - - PreserveNewest - - - - - - - - False - Microsoft .NET Framework 4.8 %28x86 und x64%29 - true - - - False - .NET Framework 3.5 SP1 - false - - - - - - PreserveNewest - - - PreserveNewest - - - Always - - - PreserveNewest - - - - - - - - - git describe --tags --long --dirty > "$(MSBuildProjectDirectory)\version.txt" || exit 0 - + + + net481 + WinExe + ODEditor + EDSEditor + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + false + true + true + true + + + Index_8287_16x.ico + + + app.manifest + + + + False + True + .\Microsoft.mshtml.dll + + + + + UserControl + + + UserControl + + + UserControl + + + UserControl + + + Component + + + UserControl + + + UserControl + + + Component + + + PreserveNewest + + + + + + + + False + Microsoft .NET Framework 4.8 %28x86 und x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + + + + PreserveNewest + + + PreserveNewest + + + Always + + + PreserveNewest + + + + + + + + + git describe --tags --long --dirty > "$(MSBuildProjectDirectory)\version.txt" || exit 0 + \ No newline at end of file diff --git a/EDSSharp/EDSSharp.csproj b/EDSSharp/EDSSharp.csproj index 66e70fc1..d7ce97e3 100644 --- a/EDSSharp/EDSSharp.csproj +++ b/EDSSharp/EDSSharp.csproj @@ -1,14 +1,14 @@ - - - net481 - Exe - false - - - - - - - - + + + net481 + Exe + false + + + + + + + + \ No newline at end of file diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index bfdc6680..5de7f6ab 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,23 +1,23 @@ - - - net481 - Library - false - - - - - - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - - + + + net481 + Library + false + + + + + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + \ No newline at end of file diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index e46aeff5..4a5a9412 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -1,27 +1,27 @@ - - - net481 - Library - false - - - docs\libEDSsharp.xml - - - - True - True - Resources.resx - - - - - ResXFileCodeGenerator - Resources.Designer.cs - - - - - - + + + net481 + Library + false + + + docs\libEDSsharp.xml + + + + True + True + Resources.resx + + + + + ResXFileCodeGenerator + Resources.Designer.cs + + + + + + \ No newline at end of file From 0c3f6ae16e15167b44840e509413069ff528deda Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 30 Mar 2024 07:06:00 +0100 Subject: [PATCH 132/226] Adding some missing comments (#96) --- libEDSsharp/Bridge.cs | 15 +- libEDSsharp/CanOpenNodeExporter.cs | 11 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 18 +- libEDSsharp/DocumentationGen.cs | 61 ++++-- libEDSsharp/ExporterFactory.cs | 17 ++ libEDSsharp/IExporter.cs | 11 + libEDSsharp/NetworkPDOreport.cs | 23 ++- libEDSsharp/eds.cs | 277 +++++++++++++++++++++++--- 8 files changed, 373 insertions(+), 60 deletions(-) diff --git a/libEDSsharp/Bridge.cs b/libEDSsharp/Bridge.cs index f320313a..3e6a3570 100644 --- a/libEDSsharp/Bridge.cs +++ b/libEDSsharp/Bridge.cs @@ -33,10 +33,16 @@ You should have received a copy of the GNU General Public License namespace libEDSsharp { + /// + /// Converts between CanOpenXML and EDSsharp + /// public class Bridge { - - + /// + /// Convert from EDSsharp to CanOpenXML + /// + /// the eds data + /// CanOpenXML device containing data from eds public Device convert(EDSsharp eds) { eds.UpdatePDOcount(); @@ -269,6 +275,11 @@ public Xml2CSharp.Characteristic makecharcteristic(string name, string content) return cl; } + /// + /// Convert from CanOpenXML to EDSsharp + /// + /// CanOpenXML device + /// EDSsharp object containing data from dev public EDSsharp convert(Device dev) { EDSsharp eds = new EDSsharp(); diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 4f13a71f..7de083bc 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -31,7 +31,9 @@ based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are namespace libEDSsharp { - + /// + /// Export .c and .h files for CanOpenNode v1-3 + /// public class CanOpenNodeExporter : IExporter { @@ -1347,7 +1349,12 @@ public static string GetValue() return method.Invoke(null, null) as string; } - + /// + /// Generates a valid C language variable name using input + /// + /// base name that will be used to make a variable name + /// the OD entry for the variable + /// protected string make_cname(string name,ODentry entry) { if (name == null) diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 57ca7eca..c5e86043 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -68,7 +68,7 @@ public void export(string folderpath, string filename, string gitVersion, EDSsha /// /// Generate ODStorage, ODObjs, ODList, ODDefines and ODCnt entries /// - /// + /// EDS object private void Prepare(EDSsharp eds) { ODStorageGroups = new List(); @@ -380,11 +380,10 @@ private int Prepare_rec(ODentry od, string indexH, string varName, string group) /// /// Export the header file /// - /// - /// - /// - /// - /// + /// path to folder that will contain the file + /// filename + /// git version that will be added to file comment + /// data that contain the data that will be exported private void Export_h(string folderpath, string filename, string gitVersion, EDSsharp eds) { @@ -558,9 +557,10 @@ OD config structure /// /// Export the c file /// - /// - /// - /// + /// path to folder that will contain the file + /// filename + /// git version that will be added to file comment + /// data that contain the data that will be exported private void Export_c(string folderpath, string filename, string gitVersion, EDSsharp eds) { diff --git a/libEDSsharp/DocumentationGen.cs b/libEDSsharp/DocumentationGen.cs index 9b18e144..b5aef6a1 100644 --- a/libEDSsharp/DocumentationGen.cs +++ b/libEDSsharp/DocumentationGen.cs @@ -24,10 +24,18 @@ You should have received a copy of the GNU General Public License namespace libEDSsharp { + /// + /// Documentation generator + /// public class DocumentationGen { StreamWriter file = null; + /// + /// Generate html documentation + /// + /// where the documentation should be saved + /// data to generate the documentation from public void genhtmldoc(string filepath, EDSsharp eds) { @@ -96,8 +104,11 @@ public void genhtmldoc(string filepath, EDSsharp eds) } - - public void writeODentryhtml(ODentry od) + /// + /// Write a object dictionary html entry to file + /// + /// Object dictionary entry + void writeODentryhtml(ODentry od) { if (od.parent == null) { @@ -142,19 +153,32 @@ public void writeODentryhtml(ODentry od) } } - - public void write2linetablerow(string a,object b) + /// + /// Write a html table row with 2 elements to file + /// + /// element a + /// element b + void write2linetablerow(string a,object b) { if (b == null) b = ""; file.Write("{0}{1}", a, b.ToString()); } - - public void write2linetableheader(string a, object b) + /// + /// Write a html table header with 2 elements to file + /// + /// + /// + void write2linetableheader(string a, object b) { file.Write("{0}{1}",a,b.ToString()); } - + /// + /// Generate markup documentation + /// + /// where the documentation should be created + /// data to generate the documentation from + /// git version of this software public void genmddoc(string filepath, EDSsharp eds, string gitVersion) { file = new StreamWriter(filepath, false); @@ -253,8 +277,12 @@ Device Information file.Close(); } - - private void PrintPdoMd(EDSsharp eds, bool skipDisabled = false) + /// + /// Write a all PDO information in markup + /// + /// data containing the information + /// skip disabled PDOs + void PrintPdoMd(EDSsharp eds, bool skipDisabled = false) { var parameters = new SortedDictionary(); var mappings = new SortedDictionary(); @@ -361,8 +389,11 @@ private void PrintPdoMd(EDSsharp eds, bool skipDisabled = false) file.WriteLine(); } } - - private void PrintODentryMd(ODentry od) + /// + /// Write a object dictionary markup entry to file + /// + /// Object dictionary entry + void PrintODentryMd(ODentry od) { var descriptions = new List(); @@ -410,8 +441,12 @@ private void PrintODentryMd(ODentry od) file.WriteLine(string.Join("\n", descriptions)); } } - - private string PrintDataType(ODentry od) + /// + /// Returns the datatype of a object dictionary + /// + /// the object dictionary entry + /// datatype of the OD entry + string PrintDataType(ODentry od) { string dt = od.datatype.ToString(); if ((od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.UNICODE_STRING) diff --git a/libEDSsharp/ExporterFactory.cs b/libEDSsharp/ExporterFactory.cs index d4908fc2..56196964 100644 --- a/libEDSsharp/ExporterFactory.cs +++ b/libEDSsharp/ExporterFactory.cs @@ -1,14 +1,31 @@  namespace libEDSsharp { + /// + /// Factory for making different canopennode exporter + /// public static class ExporterFactory { + /// + /// CanOpenNode exporter types + /// public enum Exporter { + /// + /// CanOpenNode exporter v4 (latest) + /// CANOPENNODE_V4 = 0, + /// + /// CanOpenNode exporter for v1-3 (legacy) + /// CANOPENNODE_LEGACY = 1 } + /// + /// Returns exporter based on ex parameter + /// + /// what exporter version you want. Default is CANOPENNODE_LEGACY + /// A exporter public static IExporter getExporter(Exporter ex = Exporter.CANOPENNODE_LEGACY) { IExporter exporter; diff --git a/libEDSsharp/IExporter.cs b/libEDSsharp/IExporter.cs index 5f7a11ad..53b94b10 100644 --- a/libEDSsharp/IExporter.cs +++ b/libEDSsharp/IExporter.cs @@ -6,8 +6,19 @@ namespace libEDSsharp { + /// + /// Interface for exporting CanOpenNode OD files + /// public interface IExporter { + /// + /// Export file(s) + /// + /// Path to the folder that will contain the new files + /// base filename for the new files + /// version that will be saved to the file + /// The eds that will be exported + /// The object dictionary name void export(string folderpath, string filename, string gitVersion, EDSsharp eds , string odname="OD"); } } diff --git a/libEDSsharp/NetworkPDOreport.cs b/libEDSsharp/NetworkPDOreport.cs index 2f65b26d..a7318011 100644 --- a/libEDSsharp/NetworkPDOreport.cs +++ b/libEDSsharp/NetworkPDOreport.cs @@ -23,11 +23,18 @@ You should have received a copy of the GNU General Public License namespace libEDSsharp { + /// + /// Generate a PDO network report + /// public class NetworkPDOreport { StreamWriter file = null; - + /// + /// Generate a PDO network report + /// + /// where the doc should be saved + /// Data from the different nodes in the network public void gennetpdodoc(string filepath, List network) { @@ -320,15 +327,23 @@ public void gennetpdodoc(string filepath, List network) } - + /// + /// Write a html table row with 2 elements to file + /// + /// element a + /// element b public void write2linetablerow(string a, object b) { if (b == null) b = ""; file.Write("{0}{1}", a, b.ToString()); } - - public void write2linetableheader(string a, object b) + /// + /// Write a html table header with 2 elements to file + /// + /// + /// + void write2linetableheader(string a, object b) { file.Write("{0}{1}", a, b.ToString()); } diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index e5ef6dd3..a13b8de5 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -33,7 +33,9 @@ You should have received a copy of the GNU General Public License namespace libEDSsharp { - + /// + /// Object dictionary data types from CiA 301 + /// public enum DataType { UNKNOWN = 0, @@ -69,16 +71,43 @@ public enum DataType IDENTITY = 0x23, } - + /// + /// Object Dictionary object definitions from CiA 301 + /// public enum ObjectType { UNKNOWN = -1, + /// + /// An object with no data fields + /// NULL = 0, + /// + /// Large variable amount of data e.g. executable program code + /// DOMAIN =2, + /// + /// Denotes a type definition such as a BOOLEAN, UNSIGNED16, FLOAT and so on + /// DEFTYPE=5, + /// + /// Defines a new record type e.g. the PDO mapping structure at 21h + /// DEFSTRUCT=6, + /// + /// A single value such as an UNSIGNED8, BOOLEAN, FLOAT, INTEGER16, VISIBLE STRING etc. + /// VAR = 7, + /// + /// A multiple data field object where each data field is a + /// simple variable of the SAME basic data type e.g. array of UNSIGNED16 etc. + /// Sub-index 0 is of UNSIGNED8 and therefore not part of the ARRAY data + /// ARRAY = 8, + /// + /// A multiple data field object where the data fields may be any combination of + /// simple variables. Sub-index 0 is of UNSIGNED8 and sub-index 255 is of UNSIGNED32 and + /// therefore not part of the RECORD data + /// RECORD = 9, } @@ -91,19 +120,49 @@ public enum PDOMappingType @default=4, } + /// + /// Defines how the object can be changed from SDO + /// public enum AccessSDO { + /// + /// no access + /// no, + /// + /// read only access + /// ro, + /// + /// write only access + /// wo, + /// + /// read and write access + /// rw } + /// + /// Defines how the object can be changed from PDO + /// public enum AccessPDO { + /// + /// no access + /// no, + /// + /// TPDO access + /// t, + /// + /// RPDO access + /// r, + /// + /// TPDO and RPDO access + /// tr } @@ -120,13 +179,23 @@ public enum AccessSRDO /// public class CustomProperties { - public bool CO_disabled = false; // If true, object is completelly skipped by CANopenNode exporters, etc. + /// + /// If true, object is completelly skipped by CANopenNode exporters, etc. + /// + public bool CO_disabled = false; public string CO_countLabel = ""; public string CO_storageGroup = "RAM"; public bool CO_flagsPDO = false; public AccessSRDO CO_accessSRDO = AccessSRDO.no; + /// + /// Minimum length of a string that can be stored + /// public UInt32 CO_stringLengthMin = 0; + /// + /// Deep clone + /// + /// a deep clone public CustomProperties Clone() { return new CustomProperties @@ -139,7 +208,10 @@ public CustomProperties Clone() CO_stringLengthMin = CO_stringLengthMin }; } - + /// + /// Convert from XSD to EDS + /// + /// raw custom properties from XSD public void OdeXdd(property[] properties) { if (properties != null) @@ -164,7 +236,10 @@ public void OdeXdd(property[] properties) } } } - + /// + /// Convert custom properties from EDS to XSD + /// + /// XSD properties ready to use public property[] OdeXdd() { var props = new List(); @@ -240,6 +315,9 @@ public class DcfExport : EdsExport { } + /// + /// Section of info in EDS or DCF file + /// public class InfoSection { protected Dictionary section; @@ -337,7 +415,10 @@ public bool GetField(string name, string varname) return false; } - + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. public override string ToString() { string msg; @@ -356,7 +437,11 @@ public override string ToString() return msg; } - + /// + /// Write object to stream + /// + /// stream to write the data to + /// file type public void Write(StreamWriter writer, Filetype ft) { writer.WriteLine("[" + edssection + "]"); @@ -487,7 +572,10 @@ public virtual void Parse(Dictionary section) objectlist.Add(count, target); } } - + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. public override string ToString() { string msg; @@ -504,7 +592,10 @@ public override string ToString() return msg; } - + /// + /// Write object to stream + /// + /// stream to write the data to public void Write(StreamWriter writer) { writer.WriteLine("[" + edssection + "]"); @@ -548,7 +639,10 @@ public virtual void Parse(Dictionary section) } } - + /// + /// Returns a string that represents the current object. + /// + /// A string that represents the current object. public override string ToString() { string msg; @@ -565,7 +659,10 @@ public override string ToString() return msg; } - + /// + /// Write object to stream + /// + /// stream to write the data to public void Write(StreamWriter writer) { if(comments == null) @@ -619,13 +716,25 @@ public Dummyusage(Dictionary section) : this() } } + /// + /// FileInfo section as described in CiA 306 + /// public class FileInfo : InfoSection { // Only for internal usage, use Path.GetFileName(eds.projectFilename) instead. + /// + /// indicate the file name (according to OS restrictions) + /// [EdsExport] public string FileName=""; + /// + /// indicate the actual file version (Unsigned8) + /// [EdsExport] public string FileVersion=""; + /// + /// indicate the actual file revision (Unsigned8) + /// [EdsExport] public byte FileRevision;//=1 @@ -635,28 +744,48 @@ public class FileInfo : InfoSection public byte EDSVersionMajor;//=4.0 public byte EDSVersionMinor;//=4.0 + /// + /// indicate the version of the specification (3 characters) in the format x.y + /// [EdsExport] public string EDSVersion=""; - + /// + /// file description (max 243 characters) + /// [EdsExport(maxlength=243)] public string Description="";//= //max 243 characters - public DateTime CreationDateTime;// + /// + /// file creation time (characters in format hh:mm(AM|PM)), + /// [EdsExport] public string CreationTime=""; + /// + /// provide the date of file creation (characters in format mm-dd-yyyy) + /// [EdsExport] public string CreationDate=""; - + /// + /// name or a description of the file creator (max. 245 characters) + /// [EdsExport(maxlength = 245)] public string CreatedBy = "";//=CANFestival //max245 public DateTime ModificationDateTime;// + /// + /// time of last modification (characters in format hh:mm(AM|PM)) + /// [EdsExport] public string ModificationTime=""; + /// + /// date of the last file modification (characters in format mm-dd-yyyy) + /// [EdsExport] public string ModificationDate=""; - + /// + /// name or a description of the creator (max. 244 characters) + /// [EdsExport(maxlength = 244)] public string ModifiedBy="";//=CANFestival //max244 @@ -735,62 +864,122 @@ override public void Parse(Dictionary section, string sectionnam } } + /// + /// DeviceInfo section as described in CiA 306 + /// public class DeviceInfo : InfoSection { - + /// + /// vendor name (max. 244 characters) + /// [EdsExport] public string VendorName=""; + /// + /// unique vendor ID according to identity object sub-index 01h (Unsigned32) + /// [EdsExport] public string VendorNumber=""; - + /// + /// product name (max. 243 characters) + /// [EdsExport] public string ProductName=""; + /// + /// product code according to identity object sub-index 02h (Unsigned32) + /// [EdsExport] public string ProductNumber=""; + /// + /// product revision number according to identity object sub-index 03h (Unsigned32) + /// [EdsExport] public UInt32 RevisionNumber; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_10 = false; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_20 = false; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_50 = false; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_125 = false; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_250 = false; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_500 = false; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_800 = false; + /// + /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + /// [EdsExport] public bool BaudRate_1000 = false; public bool BaudRate_auto = false; + /// + /// indicate the simple boot-up master functionality (Boolean, 0 = not supported, 1 = supported), + /// [EdsExport] public bool SimpleBootUpMaster; + /// + /// indicate the simple boot-up slave functionality (Boolean, 0 = not supported, 1 = supported), + /// [EdsExport] public bool SimpleBootUpSlave; - + /// + /// granularity allowed for the mapping on this device - + /// most of the existing devices support a granularity of 8 (Unsigned8; 0 - mapping not modifiable, 1-64 granularity) + /// [EdsExport] public byte Granularity = 8; + /// + /// Indicate the facility of dynamic variable generation. If the value is unequal to 0, the additional section DynamicChannels exists (CiA302 and CiA405) + /// [EdsExport] public bool DynamicChannelsSupported; [EdsExport] public byte CompactPDO; - + /// + /// indicate the facility of multiplexed PDOs. (Boolean, 0 = not supported, 1 = supported) + /// [EdsExport] public bool GroupMessaging; - + /// + /// indicate the number of supported receive PDOs. (Unsigned16) + /// [EdsExport] public UInt16 NrOfRXPDO; - + /// + /// indicate the number of supported transmit PDOs. (Unsigned16) + /// [EdsExport] public UInt16 NrOfTXPDO; - + /// + /// indicate if LSS functionality is supported (Boolean, 0 = not supported, 1 = supported) + /// [EdsExport] public bool LSS_Supported; @@ -1493,7 +1682,8 @@ public string Formatoctetstring(string value) /// /// Handle to the stream writer to write to /// File type being written - /// + /// OD type to write + /// module public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odtype.NORMAL, int module=0) { @@ -1850,7 +2040,9 @@ public enum AccessType // for opened project file, but project is always saved as xdd_v1.1 // Filename within the FileInfo structure has only limited usage. public string projectFilename = ""; - // File name, when project is opened in xdd_v1.1 or project is saved + /// + /// File name, when project is opened in xdd_v1.1 or project is saved + /// public string xddfilename_1_1 = ""; // File names for exported files public string xddfilenameStripped = ""; @@ -2889,7 +3081,11 @@ static public byte ConvertToByte(string defaultvalue) return (Convert.ToByte(defaultvalue, Getbase(defaultvalue))); } - + /// + /// Convert two bytes into Uint16 (big endian) + /// + /// bytes to convert to Uint16, only the 2 first will be used + /// value of the 2 bytes combined (big endian) static public UInt16 ConvertToUInt16(byte [] bytes) { @@ -2900,7 +3096,11 @@ static public UInt16 ConvertToUInt16(byte [] bytes) return value; } - + /// + /// Try to convert a string to UInt16 + /// + /// string containing a number + /// the value or 0 if unable to read it static public UInt16 ConvertToUInt16(string defaultvalue) { if (defaultvalue == null || defaultvalue == "" ) @@ -2908,7 +3108,11 @@ static public UInt16 ConvertToUInt16(string defaultvalue) return (Convert.ToUInt16(defaultvalue, Getbase(defaultvalue))); } - + /// + /// Try to convert a string to UInt32 + /// + /// string containing a number + /// the value or 0 if unable to read it static public UInt32 ConvertToUInt32(string defaultvalue) { if (defaultvalue == null || defaultvalue == "" ) @@ -2916,7 +3120,11 @@ static public UInt32 ConvertToUInt32(string defaultvalue) return (Convert.ToUInt32(defaultvalue, Getbase(defaultvalue))); } - + /// + /// Return number base of a string (10 for desimal, 16 for hex and 8 for octal) + /// + /// a string that will be read to try to find its base number + /// 16 if hex, 8 if octal else 10 static public int Getbase(string defaultvalue) { @@ -3016,7 +3224,12 @@ public UInt32 GetNodeID(string input, out bool nodeidpresent) return 0; } - + /// + /// Try to get a OD entry + /// + /// the index + /// null if not found + /// true if found, false if not public bool tryGetODEntry(UInt16 index, out ODentry od) { od = null; @@ -3247,7 +3460,11 @@ public ODentry Getobject(string uniqueID) return null; } - + /// + /// Return the number of enabled objects + /// + /// Include subindexes in the counting + /// public int GetNoEnabledObjects(bool includesub=false) { int enabledcount = 0; From c159e92f4201e3173d03558bfcc1cd8b39d3de2e Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 30 Mar 2024 14:12:04 +0100 Subject: [PATCH 133/226] Cleanup generated and dependencies (#95) * removed travis file, its not in use * removed csproj.user file, they are user settings * Removed experimental code? No idea what this is for but, it is not called and looks like some very early test code for runtime compilation that somehow got included by mistake * removed auto-generated documentation file * removed unused packages csharp was used by some experimental code, no idea what DataSetExtensions was used for --- .travis.yml | 26 - EDSEditorGUI/EDSEditorGUI.csproj | 2 - EDSEditorGUI/EDSEditorGUI.csproj.user | 13 - EDSSharp/EDSSharp.csproj | 4 - EDSSharp/EDSSharp.csproj.user | 7 - libEDSsharp/CanOpenNodeExporter.cs | 34 - libEDSsharp/docs/libEDSsharp.xml | 5182 ------------------------- libEDSsharp/libEDSsharp.csproj | 4 - 8 files changed, 5272 deletions(-) delete mode 100644 .travis.yml delete mode 100644 EDSEditorGUI/EDSEditorGUI.csproj.user delete mode 100644 EDSSharp/EDSSharp.csproj.user delete mode 100644 libEDSsharp/docs/libEDSsharp.xml diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index bd206953..00000000 --- a/.travis.yml +++ /dev/null @@ -1,26 +0,0 @@ -language: csharp -solution: EDSEditor.sln -mono: - - 6.10.0 - -notifications: - slack: - rooms: - - secure: "FId7MhkC2Fq8T9ETn5XrWw1STQusuhR7MbOz/YaCPLAvxvo4pPMyGKVu+1urrbvS9eW+o15xqL0dZow2/JG+6vxPgQIyHBcJT0LYfLROrHC22DhR2oydPO0Y4wejxWwcj4LzAXrI/09zynbX6tWphMM0MVbLRKL+WpJRVhAsCHB2FXHZxF2uT6774J+7dEpY2gtW676ShO4gU7DmD/bEOgasyvDqtpGtM4bxEQJubJr4iaUlxvGlQ8CJyBXfBxcviL5ufMjJxGmuDYHzKu2pxN1v6adfRA53CrgSlb2JIx+ubNx/xGJQN+XeGrnA6aRU15CE/6iC8qZ6CW5FBfcCESp6/JPpVeom3WHbYoXZBQbAOXDuLg+zHxF5N4kwSuZLapOcfIm7wppVlrSbY6cUZ5cNUnbVCfml+1BGC6R1++80wOaBG6g/IkHsbo3ZMtqibutg2BDEYoJeFq0GORySYPp5MTt2+iuKngLjtY4z9q2RWF+0e9/5rcYkUysUT7M0pP9SmKnI3Xvyxl853KY4xH7IiN+hZ4qoAGw4yQKJggPtUka9zihCxnxDyDOKnf6XVcZrPFucW2k2qwwZI9BMX5thNi2sB/3pAcA0kRC7yOGwLWLY21sTObB5QpDKJKeDYK1n9iss+xyIV2OoD7vwTw+sIeFFTTxyWA50AIdtmYU=" - -before_deploy: -- cp $TRAVIS_BUILD_DIR/EDSSharp/bin/Release/EDSSharp.* $TRAVIS_BUILD_DIR/EDSEditorGUI/bin/Release/ -- cd $TRAVIS_BUILD_DIR/EDSEditorGUI/bin/Release/ -- zip -r $TRAVIS_BUILD_DIR/build/CANopenEditor-latest.zip * -- cd $TRAVIS_BUILD_DIR - -deploy: - provider: pages - skip_cleanup: true - github_token: $GITHUB_TOKEN # Set in the settings page of your repository, as a secure variable - keep_history: false - target_branch: gh-pages - directory: $TRAVIS_BUILD_DIR/build/ - - on: - branch: main diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 9f52906e..0f41ac76 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -97,9 +97,7 @@ - - git describe --tags --long --dirty > "$(MSBuildProjectDirectory)\version.txt" || exit 0 diff --git a/EDSEditorGUI/EDSEditorGUI.csproj.user b/EDSEditorGUI/EDSEditorGUI.csproj.user deleted file mode 100644 index 7937b018..00000000 --- a/EDSEditorGUI/EDSEditorGUI.csproj.user +++ /dev/null @@ -1,13 +0,0 @@ - - - - publish\ - - - - - - en-US - false - - \ No newline at end of file diff --git a/EDSSharp/EDSSharp.csproj b/EDSSharp/EDSSharp.csproj index d7ce97e3..7b44195d 100644 --- a/EDSSharp/EDSSharp.csproj +++ b/EDSSharp/EDSSharp.csproj @@ -7,8 +7,4 @@ - - - - \ No newline at end of file diff --git a/EDSSharp/EDSSharp.csproj.user b/EDSSharp/EDSSharp.csproj.user deleted file mode 100644 index d14eb3bf..00000000 --- a/EDSSharp/EDSSharp.csproj.user +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - \ No newline at end of file diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 7de083bc..b73f1582 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -1315,40 +1315,6 @@ string formatvaluewithdatatype(string defaultvalue, DataType dt, bool fixstring= return ""; } } - - public static string ParseString(string input) - { - var provider = new Microsoft.CSharp.CSharpCodeProvider(); - var parameters = new System.CodeDom.Compiler.CompilerParameters() - { - GenerateExecutable = false, - GenerateInMemory = true, - }; - - var code = @" - namespace Tmp - { - public class TmpClass - { - public static string GetValue() - { - return """ + input + @"""; - } - } - }"; - - var compileResult = provider.CompileAssemblyFromSource(parameters, code); - - if (compileResult.Errors.HasErrors) - { - throw new ArgumentException(compileResult.Errors.Cast().First(e => !e.IsWarning).ErrorText); - } - - var asmb = compileResult.CompiledAssembly; - var method = asmb.GetType("Tmp.TmpClass").GetMethod("GetValue"); - - return method.Invoke(null, null) as string; - } /// /// Generates a valid C language variable name using input /// diff --git a/libEDSsharp/docs/libEDSsharp.xml b/libEDSsharp/docs/libEDSsharp.xml deleted file mode 100644 index b31722ad..00000000 --- a/libEDSsharp/docs/libEDSsharp.xml +++ /dev/null @@ -1,5182 +0,0 @@ - - - - libEDSsharp - - - - - Exporter for CanOpenNode_V4 - - - - - export the current data set in the CanOpen Node format V4 - - - - - - - - - - Generate ODStorage, ODObjs, ODList, ODDefines and ODCnt entries - - - - - - Verify "Count Label" of the object and raise warning if uncorrect. - - - - - - - - - - Generate ODStorage and ODObjs entries for VAR - - - - - - - - - - Generate ODStorage and ODObjs entries for ARRAY - - - - - - - - - - Generate ODStorage and ODObjs entries for RECORD - - - - - - - - - - Export the header file - - - - - - - - - - Export the c file - - - - - - - - Take a paramater name from the object dictionary and make it acceptable - for use in c variables/structs etc - - string, name to convert - string - - - - Return from Get_dataProperties - - - - - Get the correct c data type, length and default value, based on CANopen data type - - - - - - Structure filled with data - - - - Get attributes from OD entry or sub-entry - - - - - - - - - Read XDD file into EDSsharp object - - Name of the xdd file - EDSsharp object - - - - Read custom multi xdd file (multiple standard xdd files inside one xml container) - - Name of the multi xdd file - List of EDSsharp objects - - - - Write custom multi xdd file (multiple standard xdd files inside one xml container) - - Name of the multi xdd file - List of EDSsharp objects - Git version string for documentation field - If true, device commisioning, denotations and actual values will be included - - - - Write XDD file from EDSsharp object - - Name of the xdd file - EDSsharp object - Git version string for documentation field - If true, device commisioning, denotations and actual values will be included - If true, then all CANopenNode specific parameters and all disabled objects will be stripped - - - - Get the CANopenNode specific flags, these flags are used internally in CANopenNode to determine details about the object variable - - An odentry to access - byte containing the flag value - - - - Export the record type objects in the CO_OD.c file - - string - - - - Exports a sub object line in a record object - - sub ODentry object to export - string forming current array level or empty string for none - string forming one line of CO_OD.c record objects - - - - Custom properties for OD entry or sub-entry, which are saved into xdd file v1.1 - - - - - List of multiple CO_storageGroup strings available in project - - - - - The index of the object in the Object Dictionary - This cannot be set for child objects, if you read a child object you get the parents index - - - - - Used when writing out objects to know if we are writing the normal or the module parts out - Two module parts subext and fixed are available. - - - - - Empty object constructor - - - - - ODentry constructor for a simple VAR type - - Name of Object Dictionary Entry - Index of object in object dictionary - Type of this objects data - Default value (always set as a string) - Allowed CANopen access permissions - Allowed PDO mapping options - - - - ODConstructor useful for subobjects - - - NOT USED - - - - - - - - - ODEntry constructor for array subobjects - - - - - - - - Make a deep clone of this ODentry - - - - - - Provide a simple string representation of the object, only parameters index, no subindexes/subindex parameter name and data type are included - Useful for debug and also appears in debugger when you inspect this object - - string summary of object - - - - Provide a simple string representation of the object type. Returns the string of the ENUM ObjectType.VAR if objecttype is not enumed - - string representation of object type - - - - Duplicate current sub entry and add it to parent - - true on successfull addition - - - - Remove current sub entry - - Renumber subentries - true on successfull removal - - - - If data type is an octet string we must remove all spaces when writing out to a EDS/DCF file - - Value to be processed - value if not octet string or value with spaces removed if octet string - - - - Write out this Object dictionary entry to an EDS/DCF file using correct formatting - - Handle to the stream writer to write to - File type being written - - - - - Returns a c compatible string that represents the name of the object, - is replaced with _ - words separated by a space are replaced with _ for a separator eg ONE TWO becomes ONE_TWO - - - - - - Return the size in bytes for the given CANopen datatype of this object, eg the size of what ever the datatype field is set to - - no of bytes - - - - This is the no of subindexes present in the object, it is NOT the maximum subobject index - - - - - Add an existing entry as a subobject of this OD - - - - - - - Verify PDO mapping parameters in Object Dictionary. Every mapped OD entry must exist and mapping must be allowed - - List of error strings, empty if no errors found. - - - - This function scans the PDO list and compares it to NrOfRXPDO and NrOfTXPDO - if these do not match in count then implicit PDOs are present and they are - filled in with default values from the lowest possible index - - - - - Rebuild the communication and mapping paramaters from the - lists the PDOhelper currently has. These live in the list pdoslots - - - - - Add a PDO slot as set by index - - - - - - This finds a gap in the PDO slots - - - - - Remove existing PDO slot as set by index - - - - - - Eine stark typisierte Ressourcenklasse zum Suchen von lokalisierten Zeichenfolgen usw. - - - - - Gibt die zwischengespeicherte ResourceManager-Instanz zurück, die von dieser Klasse verwendet wird. - - - - - Überschreibt die CurrentUICulture-Eigenschaft des aktuellen Threads für alle - Ressourcenzuordnungen, die diese stark typisierte Ressourcenklasse verwenden. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 4a5a9412..751d3325 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -20,8 +20,4 @@ Resources.Designer.cs - - - - \ No newline at end of file From 4aabc481bf46c3d9d772cadd72595e3516c46aa1 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 1 Apr 2024 09:26:45 +0200 Subject: [PATCH 134/226] Created github action that will make github release on tag (#97) --- .github/workflows/release.yml | 37 +++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 .github/workflows/release.yml diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml new file mode 100644 index 00000000..5ad0e674 --- /dev/null +++ b/.github/workflows/release.yml @@ -0,0 +1,37 @@ +name: make release + +on: + push: + tags: + - "v*.*.*" + +jobs: + build: + runs-on: windows-latest + permissions: + contents: write + steps: + - name: Checkout + uses: actions/checkout@v4 + - name: Setup .NET + uses: microsoft/setup-msbuild@v1.3 + - name: Add Packages + run: | + dotnet restore + - name: Build + run: | + msbuild /property:Configuration=Release + - name: Check for release tag + run: | + $release = "${{ github.ref_name }}" -match "v[\d]*[.][\d]*[.][\d]*$" + $prerelease = If ($release) {"false"} else {"true"} + echo "prerelease=$prerelease" >> $env:GITHUB_ENV + - name: Make release package + run: | + Compress-Archive -CompressionLevel Optimal -Path "EDSEditorGUI\bin\Release\*" -DestinationPath ".\binary.zip" + - name: make release + uses: softprops/action-gh-release@v2 + with: + prerelease: ${{ env.prerelease }} + files: | + binary.zip From 01b5180309f869270ff6ea00d5d8274cb7301c52 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 1 Apr 2024 11:46:28 +0200 Subject: [PATCH 135/226] Fix two xunit1013 warnings (#98) --- Tests/EDSParserTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Tests/EDSParserTests.cs b/Tests/EDSParserTests.cs index ede05471..917f6eb4 100644 --- a/Tests/EDSParserTests.cs +++ b/Tests/EDSParserTests.cs @@ -38,7 +38,7 @@ public void Test_parser() } - public void injectobject(string testobject) + void injectobject(string testobject) { eds.Clear(); @@ -119,7 +119,7 @@ public void Test_CompactSubObj() } - public void test_object_coverage(List AlwaysSet, List MandatorySet, List OptionalSet) + void test_object_coverage(List AlwaysSet, List MandatorySet, List OptionalSet) { int MandatoryBitMask = (int)Math.Pow(2, MandatorySet.Count); From 1d123ecf13ff69d4aae3e5ee22be745bcbad3599 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 1 Apr 2024 18:20:02 +0200 Subject: [PATCH 136/226] More xml comments (#99) --- libEDSsharp/CanOpenNodeExporter.cs | 51 ++++++++++--- libEDSsharp/CanOpenXDD_1_1.cs | 7 ++ libEDSsharp/PDOHelper.cs | 111 ++++++++++++++++++++++++----- libEDSsharp/StringUnescape.cs | 8 +++ libEDSsharp/Warnings.cs | 33 ++++++++- libEDSsharp/eds.cs | 90 ++++++++++++++++++----- libEDSsharp/extensions.cs | 34 ++++++++- 7 files changed, 285 insertions(+), 49 deletions(-) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index b73f1582..92c8eedb 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -39,6 +39,9 @@ public class CanOpenNodeExporter : IExporter private string folderpath; private string gitVersion; + /// + /// The eds file set when calling export + /// protected EDSsharp eds; private int enabledcount = 0; @@ -55,7 +58,9 @@ public class CanOpenNodeExporter : IExporter ODentry maxRXmappingsOD=null; ODentry maxTXmappingsOD=null; - + /// + /// Register names of index and subindex that need to have standard names to be able to work with CanOpenNode + /// public void prepareCanOpenNames() { acceptable_canopen_names.Add(0x101800, "identity"); @@ -86,7 +91,14 @@ public void prepareCanOpenNames() } - + /// + /// Export eds into CanOpenNode v1-3 source files (.h and .c) + /// + /// folder path to save the files into + /// base filename, .c and .h will be added to this + /// git version of this software + /// the eds data to be exported + /// object dictionary name public void export(string folderpath, string filename, string gitVersion, EDSsharp eds,string odname) { this.folderpath = folderpath; @@ -110,13 +122,14 @@ public void export(string folderpath, string filename, string gitVersion, EDSsha } + /// + /// Fixes TPDO compatibility subindex + /// + /// Handle the TPDO communication parameters in a special way, because of + /// sizeof(OD_TPDOCommunicationParameter_t) != sizeof(CO_TPDOCommPar_t) in CANopen.c + /// the existing CO_TPDOCommPar_t has a compatibility entry so we must export one regardless of if its in the OD or not private void fixcompatentry() { - // Handle the TPDO communication parameters in a special way, because of - // sizeof(OD_TPDOCommunicationParameter_t) != sizeof(CO_TPDOCommPar_t) in CANopen.c - // the existing CO_TPDOCommPar_t has a compatibility entry so we must export one regardless - // of if its in the OD or not - for (UInt16 idx = 0x1800; idx < 0x1900; idx++) { if (ObjectActive(idx)) @@ -132,7 +145,11 @@ private void fixcompatentry() } } - + /// + /// + /// + /// + /// private void specialarraysearch(UInt16 start, UInt16 end) { UInt16 lowest = 0xffff; @@ -162,7 +179,11 @@ private void specialarraysearch(UInt16 start, UInt16 end) Console.WriteLine(string.Format("New special array detected start 0x{0:X4} end 0x{1:X4}", lowest, highest)); } } - + /// + /// Returns true of object is not disabled + /// + /// index to check + /// true if index object is not disabled public bool ObjectActive(UInt16 index) { if (eds.ods.ContainsKey(index)) @@ -300,7 +321,11 @@ private string print_h_bylocation(string location) return sb.ToString(); } - + /// + /// Return the header part of one object dictionary entry + /// + /// the OD entry + /// part of the C header file that impliments the od entry protected string print_h_entry(ODentry od) { StringBuilder sb = new StringBuilder(); @@ -959,7 +984,11 @@ string write_od() return returndata.ToString(); } - + /// + /// Returns the c code related to a single object dictionary entry + /// + /// the OD entry + /// string containing c code for the OD entry protected string write_od_line(ODentry od) { StringBuilder sb = new StringBuilder(); diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index f087edb8..31f20d9f 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -29,6 +29,10 @@ You should have received a copy of the GNU General Public License namespace libEDSsharp { + /// + /// Convert to/from EDSsharp and CanOpenXDD v1.1, it uses the generated source file CanOpenXSD_1_1 + /// + /// public class CanOpenXDD_1_1 { /// @@ -1203,6 +1207,9 @@ public class CanOpenProject_1_1 { [XmlElement(ElementName = "ISO15745ProfileContainer", Namespace = "http://www.canopen.org/xml/1.1")] public List ISO15745ProfileContainer { get; set; } + /// + /// XDD version + /// [XmlAttribute(AttributeName = "version")] public string Version { get; set; } } diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 4e6b640e..a476e8be 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -6,13 +6,21 @@ namespace libEDSsharp { - + /// + /// Represent a PDO slot (mapping + communication index) + /// public class PDOSlot { private UInt16 _MappingIndex; private UInt16 _ConfigurationIndex; + /// + /// Indicate that $NODEID is present and the COB-ID should added to the node id when deployed + /// public bool nodeidpresent; + /// + /// The OD index of the PDO configuration (aka. communication parameter) + /// public ushort ConfigurationIndex { get { return _ConfigurationIndex; } @@ -37,30 +45,52 @@ public ushort ConfigurationIndex } } - + /// + /// The OD index of the PDO mapping + /// public ushort MappingIndex { get { return _MappingIndex; } } - + /// + /// PDO Mapping access + /// public EDSsharp.AccessType mappingAccessType; + /// + /// PDO Configuration (aka. communication parameter) access + /// public EDSsharp.AccessType configAccessType; + /// + /// PDO mapping CanOpenNode storage group + /// public string mappingloc; + /// + /// PDO config CanOpenNode storage group + /// public string configloc; - - + /// + /// PDO COB-ID + /// public uint COB; - + /// + /// Returns if true the PDO is a TxPDO (aka TPDO) + /// + /// true if TXPDO public bool isTXPDO() { return ConfigurationIndex >= 0x1800; } - + /// + /// Returns if true the PDO is a RxPDO (aka RPDO) + /// + /// true if RxPDO public bool isRXPDO() { return ConfigurationIndex < 0x1800; } - + /// + /// PDO invalid bit value + /// public bool invalid { get @@ -69,22 +99,44 @@ public bool invalid } set { + if (value == true) COB = COB | 0x80000000; else COB = COB & 0x7FFFFFFF; } } - + /// + /// PDO mapping + /// public List Mapping = new List(); - + /// + /// PDO inhibit time,multiple of 100us + /// public UInt16 inhibit; + /// + /// PDO event time,multiple of 1ms + /// public UInt16 eventtimer; + /// + /// PDO sync start value + /// public byte syncstart; + /// + /// PDO transmission type + /// public byte transmissiontype; + /// + /// Description of PDO communication index (aka configuration) + /// public string DescriptionComm; + /// + /// Description of PDO mapping index + /// public string DescriptionMap; - + /// + /// default constructor + /// public PDOSlot() { configloc = "PERSIST_COMM"; @@ -94,7 +146,11 @@ public PDOSlot() DescriptionComm = ""; DescriptionMap = ""; } - + /// + /// Returns name of a OD entry (including dummy) + /// + /// object dictionary entry + /// name of entry with index and subindex prefixed, or blank string if not found public string getTargetName(ODentry od) { string target = ""; @@ -133,7 +189,11 @@ public string getTargetName(ODentry od) return target; } - + /// + /// Insert a OD entry into the mapping table + /// + /// The zero-based index at which item should be inserted + /// OD entry to be mapped public void insertMapping(int ordinal, ODentry entry) { int size = 0; @@ -150,19 +210,28 @@ public void insertMapping(int ordinal, ODentry entry) } - + /// + /// PDO helper class, control all TPDO and RPDO in a node + /// public class PDOHelper { EDSsharp eds; - + /// + /// Constructor + /// + /// eds data to interact with public PDOHelper(EDSsharp eds) { this.eds = eds; } - + /// + /// List of all T/R PDO + /// public List pdoslots = new List(); - + /// + /// Why is this not called from constructor? + /// public void build_PDOlists() { //List odl = new List(); @@ -170,8 +239,12 @@ public void build_PDOlists() build_PDOlist(0x1400,pdoslots); } - - public void build_PDOlist(UInt16 startcob, List slots) + /// + /// Look through the OD and register PDO + /// + /// OD index to to start looking from, it will stop after 0x1ff indexes + /// list to add found pdo into + void build_PDOlist(UInt16 startcob, List slots) { for (UInt16 idx = startcob; idx < startcob + 0x01ff; idx++) { diff --git a/libEDSsharp/StringUnescape.cs b/libEDSsharp/StringUnescape.cs index 11478976..22529aff 100644 --- a/libEDSsharp/StringUnescape.cs +++ b/libEDSsharp/StringUnescape.cs @@ -6,8 +6,16 @@ namespace libEDSsharp { + /// + /// Provides string escape and unescape functions + /// public static class StringUnescape { + /// + /// Convert litteral special characters like null and tab etc. into there escape sequence '\0' '\t' + /// + /// the spesial character to convert into escape sequence + /// a string containing the escape sequence or c if noe escape sequence was found public static string Escape(char c) { switch (c) diff --git a/libEDSsharp/Warnings.cs b/libEDSsharp/Warnings.cs index f2d2b2fb..ed35aa6f 100644 --- a/libEDSsharp/Warnings.cs +++ b/libEDSsharp/Warnings.cs @@ -6,21 +6,52 @@ namespace libEDSsharp { + /// + /// Logger class used to report problems with import/export + /// public static class Warnings { + /// + /// type of warnings + /// public enum warning_class { + /// + /// Generic warning + /// WARNING_GENERIC = 0x01, + /// + /// index/subindex rename warnings + /// WARNING_RENAME = 0x02, + /// + /// problem with index/subindexes that are needed to make canopennode functions work + /// WARNING_BUILD = 0x04, + /// + /// Problem with strings variable export + /// WARNING_STRING = 0x08, + /// + /// Problem with struct/record export + /// WARNING_STRUCT = 0x10, } + /// + /// List of warnings + /// public static List warning_list = new List(); - + /// + /// bit mask used to stop messages being added to the list + /// public static UInt32 warning_mask = 0xffff; + /// + /// Add warning to the list of warnings + /// + /// string to report + /// type of warning (filter usage) public static void AddWarning(string warning,warning_class c = warning_class.WARNING_GENERIC) { if (((UInt32)c & warning_mask) != 0) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index a13b8de5..17cb39e2 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -184,6 +184,9 @@ public class CustomProperties /// public bool CO_disabled = false; public string CO_countLabel = ""; + /// + /// CanOpenNode storage group + /// public string CO_storageGroup = "RAM"; public bool CO_flagsPDO = false; public AccessSRDO CO_accessSRDO = AccessSRDO.no; @@ -287,17 +290,27 @@ public CO_storageGroups() } } } - + /// + /// Indicate that it should be exported in EDS files and may have some data about how + /// public class EdsExport : Attribute { + /// + /// Max length of the string when exported + /// public UInt16 maxlength; public bool commentonly=false; - //mehmeh + /// + /// default constructor + /// public EdsExport() { } - + /// + /// contstructor with max string length + /// + /// max length of the string when exported public EdsExport(UInt16 maxlength) { this.maxlength = maxlength; @@ -310,7 +323,9 @@ public bool IsReadOnly() } - + /// + /// Indicate that it should be exported in DCF files + /// public class DcfExport : EdsExport { } @@ -1210,7 +1225,9 @@ public ModuleSubExtends(Dictionary section, UInt16 moduleindex) } } - + /// + /// Represent object dictionary index and subindex objects + /// public class ODentry { private UInt16 _index; @@ -1256,22 +1273,39 @@ public UInt16 Index [DcfExport] public string denotation = ""; + /// + /// object type var,rec, array etc. + /// [EdsExport] public ObjectType objecttype = ObjectType.UNKNOWN; + /// + /// data type bool, integer etc. + /// [EdsExport] public DataType datatype = DataType.UNKNOWN; + /// + /// access type + /// [EdsExport] public EDSsharp.AccessType accesstype = EDSsharp.AccessType.UNKNOWN; - + /// + /// default value + /// [EdsExport] public string defaultvalue = ""; - + /// + /// low numeric limit + /// [EdsExport] public string LowLimit = ""; - + /// + /// high numeric limit + /// [EdsExport] public string HighLimit = ""; - + /// + /// actual value + /// [DcfExport] public string actualvalue = ""; @@ -1280,7 +1314,9 @@ public UInt16 Index [EdsExport] public byte CompactSubObj = 0; - + /// + /// true if it is PDO mapping object + /// [EdsExport] public bool PDOMapping { @@ -1887,7 +1923,11 @@ public ODentry Getsubobject(UInt16 no) return subobjects[no]; return null; } - + /// + /// Returns default value for a subindex + /// + /// subindex to get the default value for + /// default value for that subindex or "" if the subindex was not found public string Getsubobjectdefaultvalue(UInt16 no) { if (subobjects.ContainsKey(no)) @@ -1895,7 +1935,11 @@ public string Getsubobjectdefaultvalue(UInt16 no) else return ""; } - + /// + /// Returns true if the object contains a subindex + /// + /// the subindex to look for + /// true if it contains the subindex public bool Containssubindex(UInt16 no) { if (subobjects.ContainsKey(no)) @@ -1904,7 +1948,10 @@ public bool Containssubindex(UInt16 no) return false; } - + /// + /// Return max indicated subindex, or null if not array or record + /// + /// public byte Getmaxsubindex() { //Although subindex 0 should contain the max subindex value @@ -1950,7 +1997,9 @@ public int Lengthofstring } } } - + /// + /// Subindex of this object if it is a subindex object, 0 if not + /// public UInt16 Subindex { get @@ -1963,7 +2012,11 @@ public UInt16 Subindex } } - + /// + /// Look for a entry in the subindexs, return the index if found + /// + /// the OD entry to look for in the subindex objects + /// the subindex if found or 0 if not found public UInt16 Findsubindex(ODentry od) { foreach(KeyValuePairkvp in subobjects ) @@ -3171,7 +3224,12 @@ public void UpdatePDOcount() } - //Split on + , replace $NODEID with concrete value and add together + /// + /// Split on + , replace $NODEID with concrete value and add together + /// + /// input string containing a number maybe prefixed by $NODEID+ + /// if $NODEID is in the string + /// public UInt32 GetNodeID(string input, out bool nodeidpresent) { diff --git a/libEDSsharp/extensions.cs b/libEDSsharp/extensions.cs index b76bdbe0..f6ee903e 100644 --- a/libEDSsharp/extensions.cs +++ b/libEDSsharp/extensions.cs @@ -6,18 +6,34 @@ namespace libEDSsharp { + /// + /// Helper functions to convert integral values into hexadecimal string + /// public static class extensions { + /// + /// returns a string containing the value as hexadecimal + /// + /// the value + /// hexadecimal string representing the value public static string ToHexString(this byte val) { return String.Format("0x{0:x}", val); } - + /// + /// returns a string containing the value as hexadecimal + /// + /// the value + /// hexadecimal string representing the value public static string ToHexString(this UInt16 val) { return String.Format("0x{0:x}",val); } - + /// + /// returns a string containing the value as hexadecimal + /// + /// the value + /// hexadecimal string representing the value public static string ToHexString(this UInt32 val) { return String.Format("0x{0:x}", val); @@ -25,8 +41,22 @@ public static string ToHexString(this UInt32 val) } + /// + /// String extension methodes + /// public static class StringExtensions { + /// + /// Performs a case insensitive Contain function + /// + /// the string to look in + /// the string to look for + /// comparison methode + /// true if substring is found in str + /// substring was null + /// comp methode was not a valid argument + /// This can be replaced with native .net function in .net core + /// public static bool Contains(this String str, String substring, StringComparison comp) { From 910e72b4c0d45d525521a12149a0ae7f022dee7b Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 1 Apr 2024 18:20:25 +0200 Subject: [PATCH 137/226] created git-blame-ignore file (#100) --- .git-blame-ignore-revs | 4 ++++ 1 file changed, 4 insertions(+) create mode 100644 .git-blame-ignore-revs diff --git a/.git-blame-ignore-revs b/.git-blame-ignore-revs new file mode 100644 index 00000000..13d500f4 --- /dev/null +++ b/.git-blame-ignore-revs @@ -0,0 +1,4 @@ +# .git-blame-ignore-revs + +# normalise line endings +6336108d916fe2fe8167255257c71adf2cac062f From fd5c2a5349a7857cb2477bd54b2ad81a866fb85e Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Wed, 3 Apr 2024 22:06:59 +0200 Subject: [PATCH 138/226] Dotnet6 support (#94) * compiling and looks like its working * matrix build * added dotnet version to the artifact name, to avoid duplicated artifact name error --- .github/workflows/dotnet.yml | 11 +++++++---- EDSEditorGUI/DevicePDOView2.cs | 2 ++ EDSEditorGUI/EDSEditorGUI.csproj | 12 +++++++++--- EDSEditorGUI/Form1.cs | 6 +++++- EDSSharp/EDSSharp.csproj | 6 ++++-- Tests/Tests.csproj | 7 +++++-- libEDSsharp/eds.cs | 1 - libEDSsharp/libEDSsharp.csproj | 9 +++++++-- 8 files changed, 39 insertions(+), 15 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 9a56aada..66158f1f 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -8,6 +8,10 @@ on: jobs: build: + strategy: + matrix: + dotnet: [net481, net6] + configuration: [Debug, Release] runs-on: windows-latest # runs-on: ubuntu-latest # Error: setup-msbuild can only be run on Windows runners @@ -31,14 +35,13 @@ jobs: - name: Build # run: make all # builds the Debug configuration run: | - msbuild /property:Configuration=Release - msbuild /property:Configuration=Debug + msbuild -p:Build${{ matrix.dotnet }}=true /property:Configuration=${{ matrix.configuration }} # run: dotnet build --no-restore - name: Test run: | - dotnet test --no-build --verbosity normal + dotnet test --no-build --verbosity normal Tests\bin\${{ matrix.configuration }}\${{ matrix.dotnet }}*\tests.dll - name: Upload Artifact uses: actions/upload-artifact@v4 with: - name: EDSEditor + name: EDSEditor_${{ matrix.dotnet }} path: EDSEditorGUI\bin\Release\ diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 71934fce..20a4bf46 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -422,7 +422,9 @@ public void UpdatePDOinfo(bool updatechoices = true) SourceGrid.Cells.Editors.ComboBox comboStandard = new SourceGrid.Cells.Editors.ComboBox(typeof(string), srray, false); + #if !NETCOREAPP comboStandard.Control.DropDownWidth = 0x100; + #endif comboStandard.Changed += ComboStandard_Changed; //tableLayoutPanel1.SuspendLayout(); diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 0f41ac76..6a83635b 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -1,6 +1,8 @@ - + - net481 + net481 + net6.0-windows + net481;net6.0-windows WinExe ODEditor EDSEditor @@ -97,7 +99,11 @@ - + + + + + git describe --tags --long --dirty > "$(MSBuildProjectDirectory)\version.txt" || exit 0 diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 46b40837..8c54fcaf 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -22,6 +22,7 @@ You should have received a copy of the GNU General Public License using System.Collections.Generic; using System.Drawing; using System.Linq; +using System.Runtime.InteropServices; using System.Windows.Forms; using System.IO; using libEDSsharp; @@ -1075,7 +1076,10 @@ private void documentationToolStripMenuItem_Click(object sender, EventArgs e) DocumentationGen docgen = new DocumentationGen(); docgen.genhtmldoc(temp, dv.eds); docgen.genmddoc(temp2, dv.eds, this.gitVersion); - System.Diagnostics.Process.Start("file://" + temp2); + if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) + { + System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("cmd", $"/c start {temp2}")); + } if (IsRunningOnMono()) { System.Diagnostics.Process.Start("file://" + temp); diff --git a/EDSSharp/EDSSharp.csproj b/EDSSharp/EDSSharp.csproj index 7b44195d..948888fe 100644 --- a/EDSSharp/EDSSharp.csproj +++ b/EDSSharp/EDSSharp.csproj @@ -1,6 +1,8 @@ - + - net481 + net481 + net6.0 + net481;net6.0 Exe false diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 5de7f6ab..5deedc04 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,6 +1,8 @@ - + - net481 + net481 + net6.0 + net481;net6.0 Library false @@ -8,6 +10,7 @@ + diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 17cb39e2..ea6c618d 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -25,7 +25,6 @@ You should have received a copy of the GNU General Public License using System.Globalization; using System.Reflection; using CanOpenXSD_1_1; -using System.Runtime.Remoting.Messaging; using System.Net.NetworkInformation; using System.Security.Cryptography; using Xml2CSharp; diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 751d3325..3bd702cb 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -1,6 +1,8 @@ - + - net481 + net481 + net6.0 + net481;net6.0 Library false @@ -20,4 +22,7 @@ Resources.Designer.cs + + + \ No newline at end of file From addcce3889d315b4c07fd32543c42b85c401ddb0 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Thu, 4 Apr 2024 19:32:02 +0200 Subject: [PATCH 139/226] removed canopen xml support (#101) --- EDSEditorGUI/Form1.cs | 139 +-------- EDSSharp/Program.cs | 21 +- README.md | 6 - libEDSsharp/Bridge.cs | 590 -------------------------------------- libEDSsharp/CanOpenXML.cs | 333 --------------------- libEDSsharp/eds.cs | 1 - 6 files changed, 7 insertions(+), 1083 deletions(-) delete mode 100644 libEDSsharp/Bridge.cs delete mode 100644 libEDSsharp/CanOpenXML.cs diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 8c54fcaf..1d051a94 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -26,7 +26,6 @@ You should have received a copy of the GNU General Public License using System.Windows.Forms; using System.IO; using libEDSsharp; -using Xml2CSharp; using static System.Windows.Forms.VisualStyles.VisualStyleElement; namespace ODEditor @@ -141,13 +140,6 @@ void ProfileAddClick(object sender, EventArgs e) CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); eds = coxml_1_1.ReadXML(filename); break; - - case ".xml": - CanOpenXML coxml = new CanOpenXML(); - coxml.readXML(filename); - Bridge b = new Bridge(); - eds = b.convert(coxml.dev); - break; } if (eds == null) @@ -197,11 +189,8 @@ private void openEDSfile(string path,InfoSection.Filetype ft) try { EDSsharp eds = new EDSsharp(); - Device dev; eds.Loadfile(path); - Bridge bridge = new Bridge(); //tell me again why bridge is not static? - dev = bridge.convert(eds); DeviceView device = new DeviceView(eds, network); @@ -289,13 +278,12 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) Warnings.warning_list.Clear(); OpenFileDialog odf = new OpenFileDialog(); - odf.Filter = "All supported files (*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.xml)|*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.xml|" + odf.Filter = "All supported files (*.xdd;*.xdc;*.xpd;*.eds;*.dcf)|*.xdd;*.xdc;*.xpd;*.eds;*.dcf|" + "CANopen XDD (*.xdd)|*.xdd|" + "CANopen XDC (*.xdc)|*.xdc|" + "CANopen XPD (*.xpd)|*.xpd|" + "Electronic Data Sheet (*.eds)|*.eds|" - + "Device Configuration File (*.dcf)|*.dcf|" - + "CANopenNode XML, old (*.xml)|*.xml"; + + "Device Configuration File (*.dcf)|*.dcf"; if (odf.ShowDialog() == DialogResult.OK) { @@ -308,10 +296,6 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) openXDDfile(odf.FileName); break; - case ".xml": - openXMLfile(odf.FileName); - break; - case ".eds": openEDSfile(odf.FileName, InfoSection.Filetype.File_EDS); break; @@ -383,50 +367,6 @@ private void openXDDfile(string path) - } - - private void openXMLfile(string path) - { - - try - { - EDSsharp eds; - Device dev; //one day this will be multiple devices - - CanOpenXML coxml = new CanOpenXML(); - coxml.readXML(path); - - Bridge b = new Bridge(); - - eds = b.convert(coxml.dev); - eds.projectFilename = path; - - dev = coxml.dev; - - tabControl1.TabPages.Add(eds.di.ProductName); - - DeviceView device = new DeviceView(eds, network); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; - eds.OnDataDirty += Eds_onDataDirty; - - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - - device.Dock = DockStyle.Fill; - device.dispatch_updateOD(); - - network.Add(eds); - } - catch (Exception ex) - { - Warnings.warning_list.Add(ex.ToString()); - } - - if (Warnings.warning_list.Count != 0) - { - WarningsFrm frm = new WarningsFrm(); - frm.Show(); - } - } private void Device_UpdateODViewForEDS(object sender, UpdateODViewEventArgs e) @@ -545,8 +485,7 @@ private void exportDeviceFileToolStripMenuItem_Click(object sender, EventArgs e) + "Electronic Data Sheet (*.eds)|*.eds|" + "Device Configuration File (*.dcf)|*.dcf|" + "Documentation (*.md)|*.md|" - + "CANopen XDD v1.0, old (*.xdd)|*.xdd|" - + "CANopenNode XML, old (*.xml)|*.xml"; + + "CANopen XDD v1.0, old (*.xdd)|*.xdd"; sfd.InitialDirectory = Path.GetDirectoryName(dv.eds.projectFilename); sfd.RestoreDirectory = true; @@ -633,16 +572,6 @@ void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripp dv.eds.mdfilename = FileName; break; - case ".xml": - Bridge b = new Bridge(); - Device d = b.convert(dv.eds); - - CanOpenXML coxml = new CanOpenXML(); - coxml.dev = d; - coxml.writeXML(FileName); - dv.eds.xmlfilename = FileName; - break; - case ".xdd": case ".xdc": case ".xpd": @@ -752,16 +681,12 @@ void OpenRecentFile(object sender, EventArgs e) if (ext != null) ext = ext.ToLower(); - if ( ext == ".xml" ) - openXMLfile(filepath); if (ext == ".xdd" || ext == ".xdc" || ext == ".xpd") openXDDfile(filepath); if ( ext == ".eds" ) openEDSfile(filepath, InfoSection.Filetype.File_EDS); if (ext == ".dcf") openEDSfile(filepath, InfoSection.Filetype.File_DCF); - if (ext == ".nxml") - openNetworkfile(filepath); } @@ -857,8 +782,7 @@ private void saveNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) sfd.Filter = "CANopen Network XDD v1.1 (*.nxdd)|*.nxdd|" + "CANopen Network XDC v1.1 (*.nxdc)|*.nxdc|" - + "CANopen Network XDD v1.0, old (*.nxdd)|*.nxdd|" - + "CANopenNode network XML, old (*.nxml)|*.nxml"; + + "CANopen Network XDD v1.0, old (*.nxdd)|*.nxdd"; sfd.InitialDirectory = Path.GetDirectoryName(networkfilename); sfd.RestoreDirectory = true; @@ -868,12 +792,6 @@ private void saveNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) { switch (sfd.FilterIndex) { - case 4: // .nxml - NetworkXML net = new NetworkXML(); - net.writeXML(sfd.FileName, network); - addtoMRU(sfd.FileName); - break; - case 3: // .nxdd V1.0 CanOpenXDD xdd = new CanOpenXDD(); xdd.writeMultiXML(sfd.FileName, network); @@ -896,19 +814,14 @@ private void loadNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) { OpenFileDialog odf = new OpenFileDialog(); - odf.Filter = "All supported files (*.nxdd;*.nxdc;*.nxml)|*.nxdd;*.nxdc;*.nxml|" + odf.Filter = "All supported files (*.nxdd;*.nxdc)|*.nxdd;*.nxdc|" + "CANopen Network XDD (*.nxdd)|*.nxdd|" - + "CANopen Network XDC (*.nxdc)|*.nxdc|" - + "CANopenNode network XML, old (*.nxml)|*.nxml"; + + "CANopen Network XDC (*.nxdc)|*.nxdc|"; if (odf.ShowDialog() == DialogResult.OK) { switch (Path.GetExtension(odf.FileName).ToLower()) { - case ".nxml": - openNetworkfile(odf.FileName); - break; - case ".nxdd": case ".nxdc": openXDDNetworkfile(odf.FileName); @@ -954,38 +867,6 @@ private void openXDDNetworkfile(string file) } - private void openNetworkfile(string file) - { - NetworkXML net = new NetworkXML(); - List devs = net.readXML(file); - - foreach (Device d in devs) - { - Bridge b = new Bridge(); - - EDSsharp eds = b.convert(d); - //eds.filename = path; //fixme: We need to save the projectfilename or SaveAs will throw an exception - - tabControl1.TabPages.Add(eds.di.ProductName); - - - DeviceView device = new DeviceView(eds, network); - - tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); - device.Dock = DockStyle.Fill; - - network.Add(eds); - device.UpdateODViewForEDS += Device_UpdateODViewForEDS; - eds.OnDataDirty += Eds_onDataDirty; - - device.dispatch_updateOD(); - - addtoMRU(file); - } - - networkfilename = file; - } - private void networkPDOToolStripMenuItem_Click(object sender, EventArgs e) { @@ -1309,10 +1190,6 @@ private void ODEditor_MainForm_DragDrop(object sender, DragEventArgs e) openXDDfile(fileName); break; - case ".xml": - openXMLfile(fileName); - break; - case ".eds": openEDSfile(fileName, InfoSection.Filetype.File_EDS); break; @@ -1321,10 +1198,6 @@ private void ODEditor_MainForm_DragDrop(object sender, DragEventArgs e) openEDSfile(fileName, InfoSection.Filetype.File_DCF); break; - case ".nxml": - openNetworkfile(fileName); - break; - case ".nxdc": case ".nxdd": openXDDNetworkfile(fileName); diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index 41153559..e149a96e 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -60,10 +60,6 @@ static void Main(string[] args) openXDDfile(infile, outfile,type); break; - case ".xml": - openXMLfile(infile,outfile,type); - break; - case ".eds": openEDSfile(infile, outfile,InfoSection.Filetype.File_EDS,type); break; @@ -76,7 +72,7 @@ static void Main(string[] args) } else { - Console.WriteLine("Usage EDSEditor --type [CanOpenNode|CanOpenNodeV4] --infile file.[xdd|eds|xml] --outfile [CO_OD.c|OD]"); + Console.WriteLine("Usage EDSEditor --type [CanOpenNode|CanOpenNodeV4] --infile file.[xdd|eds] --outfile [CO_OD.c|OD]"); } } catch(Exception e) @@ -117,21 +113,6 @@ private static void exportCOOD(string outpath,ExporterFactory.Exporter type) } - private static void openXMLfile(string path,string outpath,ExporterFactory.Exporter exportertype) - { - - CanOpenXML coxml = new CanOpenXML(); - coxml.readXML(path); - - Bridge b = new Bridge(); - - eds = b.convert(coxml.dev); - - eds.projectFilename = path; - exportCOOD(outpath,exportertype); - - } - private static void openXDDfile(string path, string outpath,ExporterFactory.Exporter exportertype) { CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); diff --git a/README.md b/README.md index 955547d4..07e60e0d 100644 --- a/README.md +++ b/README.md @@ -69,10 +69,6 @@ Library * Read EDS/DCF/XDC file and parse contents to approprate classes * Dump EDS/DCF classes via ToString() * Save EDS/DCF classes back to EDS file -* Read CanOpenNode xml project file -* Write CanOpenNode xmlproject file -* Switch formats between EDS/DCF and CanOpenNode XML (note to EDS will result in - data loss as the format supports less information). * Export C and H files in CanOpenNode format CO_OD.c and CO_OD.h * EDS/DCF supports modules * EDS/DCF supports compactPDO (read only) 1* @@ -88,8 +84,6 @@ GUI * Open multiple devices * Open EDS/DCF/XDC files * Save EDS/DCF/XDC files -* Open CanOpenNode XML Project file -* Save CanOpenNode XML File * View OD Entries and explore the Object Dictionary * Add new OD entries * Delete exisiting OD entries diff --git a/libEDSsharp/Bridge.cs b/libEDSsharp/Bridge.cs deleted file mode 100644 index 3e6a3570..00000000 --- a/libEDSsharp/Bridge.cs +++ /dev/null @@ -1,590 +0,0 @@ -/* - This file is part of libEDSsharp. - - libEDSsharp is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - libEDSsharp is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with libEDSsharp. If not, see . - - Copyright(c) 2016 - 2019 Robin Cornelius -*/ - -using System; -using System.Collections.Generic; -using System.Globalization; -using Xml2CSharp; -using System.Text.RegularExpressions; - -/* I know I'm going to regret this - * - * I quite like my eds class as it trys to validate the EDS using typing and enums etc - * but i also want the XML wrappers for the CANOpenXML - * so I'm going to make a converter outside of both classes hence this bridge - * which is more code to manage ;-( - * */ - -namespace libEDSsharp -{ - /// - /// Converts between CanOpenXML and EDSsharp - /// - public class Bridge - { - /// - /// Convert from EDSsharp to CanOpenXML - /// - /// the eds data - /// CanOpenXML device containing data from eds - public Device convert(EDSsharp eds) - { - eds.UpdatePDOcount(); - - Device dev = new Device(); - dev.CANopenObjectList = new Xml2CSharp.CANopenObjectList(); - dev.CANopenObjectList.CANopenObject = new List(); - - /* OBJECT DICTIONARY */ - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - - // if(od.subindex==-1) - { - if (od.objecttype == ObjectType.ARRAY && od.datatype == DataType.UNKNOWN) - { - //add the datatype field to parent objects if they don't have it already - //if the 2nd subobject does not exist then we do nothing. - ODentry sub = od.Getsubobject(1); - if (sub != null) - { - od.datatype = sub.datatype; - } - } - - if (od.objecttype == ObjectType.RECORD && od.accesstype == EDSsharp.AccessType.UNKNOWN) - { - ODentry sub = od.Getsubobject(1); - if (sub != null) - { - od.accesstype = sub.accesstype; - } - } - - Xml2CSharp.CANopenObject coo = new Xml2CSharp.CANopenObject(); - coo.Index = string.Format("{0:x4}", od.Index); - coo.Name = od.parameter_name; - coo.ObjectType = od.objecttype.ToString(); - coo.Disabled = od.prop.CO_disabled.ToString().ToLower(); - coo.MemoryType = od.prop.CO_storageGroup; - eds.CO_storageGroups.Add(od.prop.CO_storageGroup); - coo.AccessType = od.accesstype.ToString(); - coo.DataType = string.Format("0x{0:x2}", (int)od.datatype); - coo.DefaultValue = od.defaultvalue; - coo.HighValue = od.HighLimit; - coo.LowValue = od.LowLimit; - coo.PDOmapping = od.PDOtype.ToString(); - coo.TPDOdetectCOS = od.prop.CO_flagsPDO.ToString().ToLower(); - - coo.Description = new Xml2CSharp.Description(); - coo.Description.Text = od.Description; - - //if (od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.RECORD) - { - coo.SubNumber = od.Nosubindexes.ToString(); //-1?? //check me - coo.CANopenSubObject = new List(); - - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry subod = kvp2.Value; - UInt16 subindex = kvp2.Key; - - Xml2CSharp.CANopenSubObject sub = new Xml2CSharp.CANopenSubObject(); - - sub.Name = subod.parameter_name; - sub.Description = new Xml2CSharp.Description(); - sub.Description.Text = subod.Description; - sub.ObjectType = subod.objecttype.ToString(); - sub.AccessType = subod.accesstype == EDSsharp.AccessType.UNKNOWN ? od.accesstype.ToString() : subod.accesstype.ToString(); - sub.DataType = string.Format("0x{0:x2}", (int)(subod.datatype == DataType.UNKNOWN ? od.datatype : subod.datatype)); - sub.DefaultValue = subod.defaultvalue; - sub.HighValue = subod.HighLimit; - sub.LowValue = subod.LowLimit; - sub.PDOmapping = subod.PDOtype.ToString(); - sub.SubIndex = String.Format("{0:x2}", subindex); - sub.TPDOdetectCOS = (subod.prop.CO_flagsPDO ? subod.prop.CO_flagsPDO : od.prop.CO_flagsPDO).ToString().ToLower(); - coo.CANopenSubObject.Add(sub); - - } - } - - dev.CANopenObjectList.CANopenObject.Add(coo); - } - - } - - - /* DUMMY USAGE */ - - dev.Other = new Xml2CSharp.Other(); - dev.Other.DummyUsage = new Xml2CSharp.DummyUsage(); - dev.Other.DummyUsage.Dummy = new List(); - - Xml2CSharp.Dummy d; - - d = new Xml2CSharp.Dummy(); - d.Entry = eds.du.Dummy0001.ToString(); - dev.Other.DummyUsage.Dummy.Add(d); - d = new Xml2CSharp.Dummy(); - d.Entry = eds.du.Dummy0002.ToString(); - dev.Other.DummyUsage.Dummy.Add(d); - d = new Xml2CSharp.Dummy(); - d.Entry = eds.du.Dummy0003.ToString(); - dev.Other.DummyUsage.Dummy.Add(d); - d = new Xml2CSharp.Dummy(); - d.Entry = eds.du.Dummy0004.ToString(); - dev.Other.DummyUsage.Dummy.Add(d); - d = new Xml2CSharp.Dummy(); - d.Entry = eds.du.Dummy0005.ToString(); - dev.Other.DummyUsage.Dummy.Add(d); - d = new Xml2CSharp.Dummy(); - d.Entry = eds.du.Dummy0006.ToString(); - dev.Other.DummyUsage.Dummy.Add(d); - d = new Xml2CSharp.Dummy(); - d.Entry = eds.du.Dummy0007.ToString(); - dev.Other.DummyUsage.Dummy.Add(d); - - - Xml2CSharp.SupportedBaudRate baud = new Xml2CSharp.SupportedBaudRate(); - dev.Other.Baudrate = new Xml2CSharp.Baudrate(); - dev.Other.Baudrate.SupportedBaudRate = new List(); - - baud.Value = "10 Kbps"; - if (eds.di.BaudRate_10 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - baud = new Xml2CSharp.SupportedBaudRate(); - baud.Value = "20 Kbps"; - if (eds.di.BaudRate_20 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - baud = new Xml2CSharp.SupportedBaudRate(); - baud.Value = "50 Kbps"; - if (eds.di.BaudRate_50 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - baud = new Xml2CSharp.SupportedBaudRate(); - baud.Value = "125 Kbps"; - if (eds.di.BaudRate_125 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - baud = new Xml2CSharp.SupportedBaudRate(); - baud.Value = "250 Kbps"; - if (eds.di.BaudRate_250 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - baud = new Xml2CSharp.SupportedBaudRate(); - baud.Value = "500 Kbps"; - if (eds.di.BaudRate_500 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - baud = new Xml2CSharp.SupportedBaudRate(); - baud.Value = "800 Kbps"; - if (eds.di.BaudRate_800 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - baud = new Xml2CSharp.SupportedBaudRate(); - baud.Value = "1000 Kbps"; - if (eds.di.BaudRate_1000 == true) - dev.Other.Baudrate.SupportedBaudRate.Add(baud); - - - dev.Other.Capabilities = new Xml2CSharp.Capabilities(); - dev.Other.Capabilities.CharacteristicsList = new Xml2CSharp.CharacteristicsList(); - dev.Other.Capabilities.CharacteristicsList.Characteristic = new List(); - - - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("SimpleBootUpSlave", eds.di.SimpleBootUpSlave.ToString())); - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("SimpleBootUpMaster", eds.di.SimpleBootUpMaster.ToString())); - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("DynamicChannelsSupported", eds.di.DynamicChannelsSupported.ToString())); - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("CompactPDO", eds.di.CompactPDO.ToString())); - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("GroupMessaging", eds.di.GroupMessaging.ToString())); - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("LSS_Supported", eds.di.LSS_Supported.ToString())); - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("LSS_Master", eds.di.LSS_Master.ToString())); - - dev.Other.Capabilities.CharacteristicsList.Characteristic.Add(makecharcteristic("Granularity", eds.di.Granularity.ToString())); - - dev.Other.DeviceIdentity = new Xml2CSharp.DeviceIdentity(); - dev.Other.DeviceIdentity.ProductName = eds.di.ProductName; - dev.Other.DeviceIdentity.ProductNumber = eds.di.ProductNumber; - dev.Other.DeviceIdentity.ProductText = new Xml2CSharp.ProductText(); - dev.Other.DeviceIdentity.ProductText.Description = new Xml2CSharp.Description(); - dev.Other.DeviceIdentity.ProductText.Description.Text = eds.fi.Description; - - - if (eds.dc.NodeID != 0) - dev.Other.DeviceIdentity.ConcreteNoideId = eds.dc.NodeID.ToString(); - - dev.Other.DeviceIdentity.VendorName = eds.di.VendorName; - dev.Other.DeviceIdentity.VendorNumber = eds.di.VendorNumber; - - dev.Other.File = new File(); - - dev.Other.File.FileName = System.IO.Path.GetFileName(eds.xmlfilename); - - dev.Other.File.FileCreationDate = eds.fi.CreationDateTime.ToString("MM-dd-yyyy"); - dev.Other.File.FileCreationTime = eds.fi.CreationDateTime.ToString("h:mmtt"); - dev.Other.File.FileCreator = eds.fi.CreatedBy; - - dev.Other.File.FileModificationDate = eds.fi.ModificationDateTime.ToString("MM-dd-yyyy"); - dev.Other.File.FileModificationTime = eds.fi.ModificationDateTime.ToString("h:mmtt"); - dev.Other.File.FileModifedBy = eds.fi.ModifiedBy; - - dev.Other.File.FileVersion = eds.fi.FileVersion; - dev.Other.File.FileRevision = eds.fi.FileRevision; - - dev.Other.File.ExportFolder = eds.fi.exportFolder; - dev.Other.File.EdsFile = eds.edsfilename; - //fixme dcffilename - - - return dev; - } - - - public Xml2CSharp.Characteristic makecharcteristic(string name, string content) - { - Xml2CSharp.Characteristic cl = new Xml2CSharp.Characteristic(); - - cl.CharacteristicName = new Xml2CSharp.CharacteristicName(); - cl.CharacteristicContent = new Xml2CSharp.CharacteristicContent(); - cl.CharacteristicContent.Label = new Xml2CSharp.Label(); - cl.CharacteristicName.Label = new Xml2CSharp.Label(); - - cl.CharacteristicName.Label.Text = name; - cl.CharacteristicContent.Label.Text = content; - - return cl; - } - - /// - /// Convert from CanOpenXML to EDSsharp - /// - /// CanOpenXML device - /// EDSsharp object containing data from dev - public EDSsharp convert(Device dev) - { - EDSsharp eds = new EDSsharp(); - - foreach (Xml2CSharp.CANopenObject coo in dev.CANopenObjectList.CANopenObject) - { - ODentry entry = new ODentry(); - entry.Index = Convert.ToUInt16(coo.Index, 16); - entry.parameter_name = coo.Name; - - if (coo.AccessType != null) - { - string at = coo.AccessType; - - Regex reg = new Regex(@"^cons$"); - at = reg.Replace(at, "const"); - - entry.accesstype = (EDSsharp.AccessType)Enum.Parse(typeof(EDSsharp.AccessType), at); - } - - if (coo.DataType != null) - { - byte datatype = Convert.ToByte(coo.DataType, 16); - entry.datatype = (DataType)datatype; - } - else - { - //CANopenNode Project XML did not correctly set DataTypes for record sets - - if (entry.Index == 0x1018) - entry.datatype = DataType.IDENTITY; - - if (entry.Index >= 0x1200 && entry.Index < 0x1400) //check me is this the correct range?? - entry.datatype = DataType.SDO_PARAMETER; - - - if (entry.Index >= 0x1400 && entry.Index < 0x1600) //check me is this the correct range?? - entry.datatype = DataType.PDO_COMMUNICATION_PARAMETER; - - - if (entry.Index >= 0x1600 && entry.Index < 0x1800) //check me is this the correct range?? - entry.datatype = DataType.PDO_MAPPING; - - - if (entry.Index >= 0x1800 && entry.Index < 0x1a00) //check me is this the correct range?? - entry.datatype = DataType.PDO_COMMUNICATION_PARAMETER; - - - if (entry.Index >= 0x1a00 && entry.Index < 0x1c00) //check me is this the correct range?? - entry.datatype = DataType.PDO_MAPPING; - - - } - - //Fix for old CanOpen XML; - if (coo.ObjectType == "REC") - { - coo.ObjectType = "RECORD"; - } - - ObjectType oType; - if(Enum.TryParse(coo.ObjectType, out oType)) - { - //TDO Parsing failed, we should alert the user - } - entry.objecttype = oType; - - entry.defaultvalue = coo.DefaultValue; - entry.HighLimit = coo.HighValue; - entry.LowLimit = coo.LowValue; - //entry.nosubindexes = Convert.ToInt16(coo.SubNumber); - - if (coo.PDOmapping != null) - entry.PDOtype = (PDOMappingType)Enum.Parse(typeof(PDOMappingType), coo.PDOmapping); - else - entry.PDOtype = PDOMappingType.no; - - entry.prop.CO_flagsPDO = coo.TPDOdetectCOS == "true"; - entry.prop.CO_disabled = coo.Disabled == "true"; - - if (coo.Description != null) - entry.Description = coo.Description.Text; //FIXME URL/LANG - - if (coo.Label != null) - entry.Label = coo.Label.Text; //FIXME LANG - - if (coo.MemoryType != null) - { - entry.prop.CO_storageGroup = coo.MemoryType; - eds.CO_storageGroups.Add(coo.MemoryType); - } - - eds.ods.Add(entry.Index, entry); - - if (entry.Index == 0x1000 || entry.Index == 0x1001 || entry.Index == 0x1018) - { - eds.md.objectlist.Add(eds.md.objectlist.Count + 1, entry.Index); - } - else - if (entry.Index >= 0x2000 && entry.Index < 0x6000) - { - eds.mo.objectlist.Add(eds.mo.objectlist.Count + 1, entry.Index); - } - else - { - eds.oo.objectlist.Add(eds.oo.objectlist.Count + 1, entry.Index); - } - - - foreach (Xml2CSharp.CANopenSubObject coosub in coo.CANopenSubObject) - { - - ODentry subentry = new ODentry(); - - subentry.parameter_name = coosub.Name; - subentry.Index = entry.Index; - - if (coosub.AccessType != null) - subentry.accesstype = (EDSsharp.AccessType)Enum.Parse(typeof(EDSsharp.AccessType), coosub.AccessType); - - if (coosub.DataType != null) - { - byte datatype = Convert.ToByte(coosub.DataType, 16); - subentry.datatype = (DataType)datatype; - } - - if (coosub.Description != null) - subentry.Description = coosub.Description.Text; //FIXME URL/LANG - - subentry.defaultvalue = coosub.DefaultValue; - subentry.HighLimit = coosub.HighValue; - subentry.LowLimit = coosub.LowValue; - - byte subindex = Convert.ToByte(coosub.SubIndex, 16); - - if (coosub.PDOmapping != null) - subentry.PDOtype = (PDOMappingType)Enum.Parse(typeof(PDOMappingType), coosub.PDOmapping); - - if (entry.objecttype == ObjectType.ARRAY) - { - subentry.PDOtype = entry.PDOtype; - } - - subentry.prop.CO_storageGroup = entry.prop.CO_storageGroup; - subentry.parent = entry; - - subentry.objecttype = ObjectType.VAR; - - if (coosub.TPDOdetectCOS != null) - { - subentry.prop.CO_flagsPDO = coosub.TPDOdetectCOS == "true"; - } - else - { - if (coo.TPDOdetectCOS != null) - subentry.prop.CO_flagsPDO = coo.TPDOdetectCOS == "true"; - } - - - entry.subobjects.Add(subindex, subentry); - - } - } - - eds.du.Dummy0001 = dev.Other.DummyUsage.Dummy[0].Entry == "Dummy0001=1"; - eds.du.Dummy0002 = dev.Other.DummyUsage.Dummy[1].Entry == "Dummy0002=1"; - eds.du.Dummy0003 = dev.Other.DummyUsage.Dummy[2].Entry == "Dummy0003=1"; - eds.du.Dummy0004 = dev.Other.DummyUsage.Dummy[3].Entry == "Dummy0004=1"; - eds.du.Dummy0005 = dev.Other.DummyUsage.Dummy[4].Entry == "Dummy0005=1"; - eds.du.Dummy0006 = dev.Other.DummyUsage.Dummy[5].Entry == "Dummy0006=1"; - eds.du.Dummy0007 = dev.Other.DummyUsage.Dummy[6].Entry == "Dummy0007=1"; - - foreach (Xml2CSharp.SupportedBaudRate baud in dev.Other.Baudrate.SupportedBaudRate) - { - if (baud.Value == "10 Kbps") - eds.di.BaudRate_10 = true; - if (baud.Value == "20 Kbps") - eds.di.BaudRate_20 = true; - if (baud.Value == "50 Kbps") - eds.di.BaudRate_50 = true; - if (baud.Value == "125 Kbps") - eds.di.BaudRate_125 = true; - if (baud.Value == "250 Kbps") - eds.di.BaudRate_250 = true; - if (baud.Value == "500 Kbps") - eds.di.BaudRate_500 = true; - if (baud.Value == "800 Kbps") - eds.di.BaudRate_800 = true; - if (baud.Value == "1000 Kbps") - eds.di.BaudRate_1000 = true; - - } - - Dictionary keypairs = new Dictionary(); - - if (dev.Other.Capabilities != null) - { - if (dev.Other.Capabilities.CharacteristicsList != null) - { - foreach (Xml2CSharp.Characteristic c in dev.Other.Capabilities.CharacteristicsList.Characteristic) - { - try - { - keypairs.Add(c.CharacteristicName.Label.Text, c.CharacteristicContent.Label.Text); - } - catch (Exception) - { - // Warnings.warning_list.Add("Parsing characteristics failed " + e.ToString()); - } - } - } - } - - - bool boolout; - byte byteout; - - if (keypairs.ContainsKey("SimpleBootUpSlave") && bool.TryParse(keypairs["SimpleBootUpSlave"], out boolout)) - eds.di.SimpleBootUpSlave = boolout; - if (keypairs.ContainsKey("SimpleBootUpMaster") && bool.TryParse(keypairs["SimpleBootUpMaster"], out boolout)) - eds.di.SimpleBootUpMaster = boolout; - if (keypairs.ContainsKey("DynamicChannelsSupported") && bool.TryParse(keypairs["DynamicChannelsSupported"], out boolout)) - eds.di.DynamicChannelsSupported = boolout; - if (keypairs.ContainsKey("CompactPDO") && byte.TryParse(keypairs["CompactPDO"], out byteout)) - eds.di.CompactPDO = byteout; - if (keypairs.ContainsKey("GroupMessaging") && bool.TryParse(keypairs["GroupMessaging"], out boolout)) - eds.di.GroupMessaging = boolout; - if (keypairs.ContainsKey("LSS_Supported") && bool.TryParse(keypairs["LSS_Supported"], out boolout)) - eds.di.LSS_Supported = boolout; - if (keypairs.ContainsKey("LSS_Master") && bool.TryParse(keypairs["LSS_Master"], out boolout)) - eds.di.LSS_Master = boolout; - else if (keypairs.ContainsKey("LSS_Type") && keypairs["LSS_Type"] != null && keypairs["LSS_Type"].ToString() == "Client") - eds.di.LSS_Master = true; - if (keypairs.ContainsKey("Granularity") && byte.TryParse(keypairs["Granularity"], out byteout)) - eds.di.Granularity = byteout; - - eds.di.ProductName = dev.Other.DeviceIdentity.ProductName; - eds.di.ProductNumber = dev.Other.DeviceIdentity.ProductNumber; - - if (dev.Other.DeviceIdentity.ProductText != null && dev.Other.DeviceIdentity.ProductText.Description != null & dev.Other.DeviceIdentity.ProductText.Description.Text != null) - eds.fi.Description = dev.Other.DeviceIdentity.ProductText.Description.Text; - - eds.di.VendorName = dev.Other.DeviceIdentity.VendorName; - eds.di.VendorNumber = dev.Other.DeviceIdentity.VendorNumber; - - if (dev.Other.DeviceIdentity.ConcreteNoideId != null) - { - eds.dc.NodeID = Convert.ToByte(dev.Other.DeviceIdentity.ConcreteNoideId); - } - else - { - eds.dc.NodeID = 0; - } - - string dtcombined; - - eds.fi.FileName = dev.Other.File.FileName; - eds.edsfilename = dev.Other.File.EdsFile; - //fixme dcffilename - - dtcombined = string.Format("{0} {1}", dev.Other.File.FileCreationTime, dev.Other.File.FileCreationDate); - try - { - eds.fi.CreationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - eds.fi.CreationDate = eds.fi.CreationDateTime.ToString("MM-dd-yyyy"); - eds.fi.CreationTime = eds.fi.CreationDateTime.ToString("h:mmtt"); - - } - catch (Exception) { } - - eds.fi.CreatedBy = dev.Other.File.FileCreator; - eds.fi.exportFolder = dev.Other.File.ExportFolder; - - dtcombined = string.Format("{0} {1}", dev.Other.File.FileModificationTime, dev.Other.File.FileModificationDate); - try - { - eds.fi.ModificationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - eds.fi.ModificationDate = eds.fi.ModificationDateTime.ToString("MM-dd-yyyy"); - eds.fi.ModificationTime = eds.fi.ModificationDateTime.ToString("h:mmtt"); - } - catch (Exception) { } - - - - - eds.fi.ModifiedBy = dev.Other.File.FileModifedBy; - - - dev.Other.Capabilities = dev.Other.Capabilities; - - eds.fi.FileVersion = dev.Other.File.FileVersion; - - eds.fi.FileRevision = dev.Other.File.FileRevision; - - eds.fi.EDSVersion = "4.0"; - - //FIX me any other appropriate defaults for eds here?? - - eds.UpdatePDOcount(); - - return eds; - } - - - - } - -} diff --git a/libEDSsharp/CanOpenXML.cs b/libEDSsharp/CanOpenXML.cs deleted file mode 100644 index d80da611..00000000 --- a/libEDSsharp/CanOpenXML.cs +++ /dev/null @@ -1,333 +0,0 @@ -/* - Licensed under the Apache License, Version 2.0 - * - * The XML contents of this file are auto generated by XML to C# - - http://www.apache.org/licenses/LICENSE-2.0 - */ - -using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; -using System.Threading.Tasks; -using System.Xml; -using System.Xml.Serialization; -using Xml2CSharp; -using System.IO; - -namespace libEDSsharp -{ - public class CanOpenXML - { - public Device dev; - public void readXML(string file) - { - - XmlSerializer serializer = new XmlSerializer(typeof(Device)); - StreamReader reader = new StreamReader(file); - dev = (Device)serializer.Deserialize(reader); - reader.Close(); - } - - public void writeXML(string file) - { - - XmlSerializer serializer = new XmlSerializer(typeof(Device)); - StreamWriter writer = new StreamWriter(file); - serializer.Serialize(writer, dev); - writer.Close(); - } - } - - - public class NetworkXML - { - Network network = new Network(); - - public List readXML(string file) - { - XmlSerializer serializer = new XmlSerializer(typeof(Network)); - StreamReader reader = new StreamReader(file); - network = (Network)serializer.Deserialize(reader); - reader.Close(); - return network.devices; - } - - public void writeXML(string file, List enet) - { - - network.devices = new List(); - foreach(EDSsharp e in enet) - { - Bridge b = new Bridge(); - Device d = b.convert(e); - network.devices.Add(d); - } - - XmlSerializer serializer = new XmlSerializer(typeof(Network)); - StreamWriter writer = new StreamWriter(file); - serializer.Serialize(writer, network); - writer.Close(); - } - } -} - -namespace Xml2CSharp -{ - [XmlRoot(ElementName="label")] - public class Label { - [XmlAttribute(AttributeName="lang")] - public string Lang { get; set; } - [XmlText] - public string Text { get; set; } - } - - [XmlRoot(ElementName="description")] - public class Description { - [XmlAttribute(AttributeName="lang")] - public string Lang { get; set; } - [XmlAttribute(AttributeName="URI")] - public string URI { get; set; } - [XmlText] - public string Text { get; set; } - } - - [XmlRoot(ElementName="associatedObject")] - public class AssociatedObject { - [XmlAttribute(AttributeName="index")] - public string Index { get; set; } - [XmlAttribute(AttributeName="indexMax")] - public string IndexMax { get; set; } - [XmlAttribute(AttributeName="indexStep")] - public string IndexStep { get; set; } - } - - [XmlRoot(ElementName="feature")] - public class Feature { - [XmlElement(ElementName="label")] - public Label Label { get; set; } - [XmlElement(ElementName="description")] - public Description Description { get; set; } - [XmlElement(ElementName="associatedObject")] - public List AssociatedObject { get; set; } - [XmlAttribute(AttributeName="name")] - public string Name { get; set; } - [XmlAttribute(AttributeName="value")] - public string Value { get; set; } - } - - [XmlRoot(ElementName="features")] - public class Features { - [XmlElement(ElementName="feature")] - public List Feature { get; set; } - } - - [XmlRoot(ElementName="CANopenObject")] - public class CANopenObject { - [XmlElement(ElementName="label")] - public Label Label { get; set; } - [XmlElement(ElementName="description")] - public Description Description { get; set; } - [XmlAttribute(AttributeName="index")] - public string Index { get; set; } - [XmlAttribute(AttributeName="name")] - public string Name { get; set; } - [XmlAttribute(AttributeName="objectType")] - public string ObjectType { get; set; } - [XmlAttribute(AttributeName="memoryType")] - public string MemoryType { get; set; } - [XmlAttribute(AttributeName="dataType")] - public string DataType { get; set; } - [XmlAttribute(AttributeName="accessType")] - public string AccessType { get; set; } - [XmlAttribute(AttributeName="PDOmapping")] - public string PDOmapping { get; set; } - [XmlAttribute(AttributeName="defaultValue")] - public string DefaultValue { get; set; } - [XmlAttribute(AttributeName = "highValue")] - public string HighValue { get; set; } - [XmlAttribute(AttributeName = "lowValue")] - public string LowValue { get; set; } - [XmlElement(ElementName="CANopenSubObject")] - public List CANopenSubObject { get; set; } - [XmlAttribute(AttributeName="subNumber")] - public string SubNumber { get; set; } - [XmlAttribute(AttributeName="disabled")] - public string Disabled { get; set; } - [XmlAttribute(AttributeName="TPDOdetectCOS")] - public string TPDOdetectCOS { get; set; } - } - - [XmlRoot(ElementName="CANopenSubObject")] - public class CANopenSubObject { - [XmlAttribute(AttributeName="subIndex")] - public string SubIndex { get; set; } - [XmlAttribute(AttributeName="name")] - public string Name { get; set; } - [XmlElement(ElementName = "description")] - public Description Description { get; set; } - [XmlAttribute(AttributeName="objectType")] - public string ObjectType { get; set; } - [XmlAttribute(AttributeName="dataType")] - public string DataType { get; set; } - [XmlAttribute(AttributeName="accessType")] - public string AccessType { get; set; } - [XmlAttribute(AttributeName="PDOmapping")] - public string PDOmapping { get; set; } - [XmlAttribute(AttributeName="defaultValue")] - public string DefaultValue { get; set; } - [XmlAttribute(AttributeName = "highValue")] - public string HighValue { get; set; } - [XmlAttribute(AttributeName = "lowValue")] - public string LowValue { get; set; } - [XmlAttribute(AttributeName = "TPDOdetectCOS")] - public string TPDOdetectCOS { get; set; } - } - - [XmlRoot(ElementName="CANopenObjectList")] - public class CANopenObjectList { - [XmlElement(ElementName="CANopenObject")] - public List CANopenObject { get; set; } - } - - [XmlRoot(ElementName="file")] - public class File { - [XmlAttribute(AttributeName="fileName")] - public string FileName { get; set; } - [XmlAttribute(AttributeName="fileCreator")] - public string FileCreator { get; set; } - [XmlAttribute(AttributeName="fileCreationDate")] - public string FileCreationDate { get; set; } - [XmlAttribute(AttributeName="fileCreationTime")] - public string FileCreationTime { get; set; } - [XmlAttribute(AttributeName = "fileModifedBy")] - public string FileModifedBy { get; set; } - [XmlAttribute(AttributeName = "fileMotifcationDate")] - public string FileModificationDate { get; set; } - [XmlAttribute(AttributeName = "fileModificationTime")] - public string FileModificationTime { get; set; } - [XmlAttribute(AttributeName="fileVersion")] - public string FileVersion { get; set; } - [XmlAttribute(AttributeName = "fileRevision")] - public byte FileRevision { get; set; } - [XmlAttribute(AttributeName = "exportFolder")] - public string ExportFolder { get; set; } - [XmlAttribute(AttributeName = "EdsFile")] - public string EdsFile { get; set; } - - } - - [XmlRoot(ElementName="productText")] - public class ProductText { - [XmlElement(ElementName="label")] - public Label Label { get; set; } - [XmlElement(ElementName="description")] - public Description Description { get; set; } - } - - [XmlRoot(ElementName="DeviceIdentity")] - public class DeviceIdentity { - [XmlElement(ElementName="vendorName")] - public string VendorName { get; set; } - [XmlElement(ElementName = "vendorNumber")] - public string VendorNumber { get; set; } - [XmlElement(ElementName="productName")] - public string ProductName { get; set; } - [XmlElement(ElementName="productNumber")] - public string ProductNumber { get; set; } - [XmlElement(ElementName = "productText")] - public ProductText ProductText { get; set; } - [XmlElement(ElementName = "concreteNoideId")] - public string ConcreteNoideId { get; set; } - } - - [XmlRoot(ElementName="characteristicName")] - public class CharacteristicName { - [XmlElement(ElementName="label")] - public Label Label { get; set; } - } - - [XmlRoot(ElementName="characteristicContent")] - public class CharacteristicContent { - [XmlElement(ElementName="label")] - public Label Label { get; set; } - } - - [XmlRoot(ElementName="characteristic")] - public class Characteristic { - [XmlElement(ElementName="characteristicName")] - public CharacteristicName CharacteristicName { get; set; } - [XmlElement(ElementName="characteristicContent")] - public CharacteristicContent CharacteristicContent { get; set; } - } - - [XmlRoot(ElementName="characteristicsList")] - public class CharacteristicsList { - [XmlElement(ElementName="characteristic")] - public List Characteristic { get; set; } - } - - [XmlRoot(ElementName="capabilities")] - public class Capabilities { - [XmlElement(ElementName="characteristicsList")] - public CharacteristicsList CharacteristicsList { get; set; } - } - - [XmlRoot(ElementName="supportedBaudRate")] - public class SupportedBaudRate { - [XmlAttribute(AttributeName="value")] - public string Value { get; set; } - } - - [XmlRoot(ElementName="baudRate")] - public class Baudrate { - [XmlElement(ElementName="supportedBaudRate")] - public List SupportedBaudRate { get; set; } - } - - [XmlRoot(ElementName="dummy")] - public class Dummy { - [XmlAttribute(AttributeName="entry")] - public string Entry { get; set; } - } - - [XmlRoot(ElementName="dummyUsage")] - public class DummyUsage { - [XmlElement(ElementName="dummy")] - public List Dummy { get; set; } - } - - [XmlRoot(ElementName="other")] - public class Other { - [XmlElement(ElementName="file")] - public File File { get; set; } - [XmlElement(ElementName="DeviceIdentity")] - public DeviceIdentity DeviceIdentity { get; set; } - [XmlElement(ElementName="capabilities")] - public Capabilities Capabilities { get; set; } - [XmlElement(ElementName="baudRate")] - public Baudrate Baudrate { get; set; } - [XmlElement(ElementName="dummyUsage")] - public DummyUsage DummyUsage { get; set; } - } - - [XmlRoot(ElementName="device")] - public class Device { - [XmlElement(ElementName="features")] - public Features Features { get; set; } - [XmlElement(ElementName="CANopenObjectList")] - public CANopenObjectList CANopenObjectList { get; set; } - [XmlElement(ElementName="other")] - public Other Other { get; set; } - } - - [XmlRoot(ElementName = "network")] - public class Network - { - [XmlElement(ElementName = "devices")] - public List devices { get; set; } - } - - -} diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index ea6c618d..487acf18 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -27,7 +27,6 @@ You should have received a copy of the GNU General Public License using CanOpenXSD_1_1; using System.Net.NetworkInformation; using System.Security.Cryptography; -using Xml2CSharp; namespace libEDSsharp { From 3c0506460742fa4df57ad24b9d75fdcffe55fade Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas <9848846+nimrof@users.noreply.github.com> Date: Thu, 4 Apr 2024 19:35:42 +0200 Subject: [PATCH 140/226] Revert "Merge branch 'robincornelius:xdd' into main" This reverts commit 2ee0f038dc46b3e29057519cd2bd0520df9a76f8, reversing changes made to addcce3889d315b4c07fd32543c42b85c401ddb0. --- README.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 6a715561..07e60e0d 100644 --- a/README.md +++ b/README.md @@ -16,12 +16,14 @@ This is the `main` branch with sources. For binaries see the `build` branch or d ---- -This project went upstream and became a part of CanOpenNode! - -please see https://github.com/CANopenNode/CANopenEditor for the latest version - +Join us on slack +-------- +https://join.slack.com/t/canopennode/shared_invite/zt-ghjhfg12-qGQNWvSEmhqcSedhFaLpuA +(Invite expires 12th Sep 2020) if the link expires before i push this page please ping me (robin.cornelius@gmail.com) +I'm hoping to build a community with canopennode and related tools at the above address. There are channels for this project already +so if you use this tool, or just canopennode please join. EDSSharp -------- From 8dc739ca7bb825c2007ca4fd01e9bec501083914 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sun, 7 Apr 2024 21:20:14 +0200 Subject: [PATCH 141/226] move eds import&export to its own file (#104) * moved the rest and changed name of the file to CanOpenEDS.cs * moved function that are only called called from EDS file export/import --- libEDSsharp/CanOpenEDS.cs | 1389 +++++++++++++++++++++++++++++++++++ libEDSsharp/eds.cs | 1435 +------------------------------------ 2 files changed, 1414 insertions(+), 1410 deletions(-) create mode 100644 libEDSsharp/CanOpenEDS.cs diff --git a/libEDSsharp/CanOpenEDS.cs b/libEDSsharp/CanOpenEDS.cs new file mode 100644 index 00000000..d4be60f6 --- /dev/null +++ b/libEDSsharp/CanOpenEDS.cs @@ -0,0 +1,1389 @@ +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius +*/ + +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; +using System.Text.RegularExpressions; + +namespace libEDSsharp +{ + public partial class InfoSection + { + public virtual void Parse(Dictionary section, string sectionname) + { + this.section = section; + + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + if (Attribute.IsDefined(f, typeof(EdsExport))) + GetField(f.Name, f.Name); + + if (Attribute.IsDefined(f, typeof(DcfExport))) + GetField(f.Name, f.Name); + } + } + + /// + /// Write object to stream + /// + /// stream to write the data to + /// file type + public void Write(StreamWriter writer, Filetype ft) + { + writer.WriteLine("[" + edssection + "]"); + Type tx = this.GetType(); + FieldInfo[] fields = this.GetType().GetFields(); + + foreach (FieldInfo f in fields) + { + if ((ft == Filetype.File_EDS) && (!Attribute.IsDefined(f, typeof(EdsExport)))) + continue; + + if ((ft == Filetype.File_DCF) && (!(Attribute.IsDefined(f, typeof(DcfExport)) || Attribute.IsDefined(f, typeof(EdsExport))))) + continue; + + if (f.GetValue(this) == null) + continue; + + EdsExport ex = (EdsExport)f.GetCustomAttribute(typeof(EdsExport)); + + bool comment = ex.IsReadOnly(); + + if (f.FieldType.Name == "Boolean") + { + writer.WriteLine(string.Format("{2}{0}={1}", f.Name, ((bool)f.GetValue(this)) == true ? 1 : 0, comment == true ? ";" : "")); + } + else + { + writer.WriteLine(string.Format("{2}{0}={1}", f.Name, f.GetValue(this).ToString(), comment == true ? ";" : "")); + } + } + + writer.WriteLine(""); + } + } + + public partial class MandatoryObjects : SupportedObjects + { + public MandatoryObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public partial class OptionalObjects : SupportedObjects + { + public OptionalObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public partial class ManufacturerObjects : SupportedObjects + { + public ManufacturerObjects(Dictionary section) + : this() + { + Parse(section); + } + } + + public partial class TypeDefinitions : SupportedObjects + { + public TypeDefinitions(Dictionary section) + { + Parse(section); + } + } + + public partial class SupportedObjects + { + public virtual void Parse(Dictionary section) + { + objectlist = new Dictionary(); + foreach (KeyValuePair kvp in section) + { + if (kvp.Key.ToLower() == "supportedobjects") + continue; + + if (kvp.Key.ToLower() == "nrofentries") + continue; + + int count = Convert.ToInt16(kvp.Key, EDSsharp.Getbase(kvp.Key)); + int target = Convert.ToInt16(kvp.Value, EDSsharp.Getbase(kvp.Value)); + objectlist.Add(count, target); + } + } + /// + /// Write object to stream + /// + /// stream to write the data to + public void Write(StreamWriter writer) + { + writer.WriteLine("[" + edssection + "]"); + writer.WriteLine(string.Format("{0}={1}", countmsg, objectlist.Count)); + foreach (KeyValuePair kvp in objectlist) + { + writer.WriteLine(string.Format("{0}=0x{1:X4}", kvp.Key, kvp.Value)); + } + writer.WriteLine(""); + } + } + + public partial class Comments + { + public Comments(Dictionary section) + { + Parse(section); + } + + public virtual void Parse(Dictionary section) + { + comments = new List(); + foreach (KeyValuePair kvp in section) + { + if (kvp.Key == "Lines") + continue; + + comments.Add(kvp.Value); + } + } + /// + /// Write object to stream + /// + /// stream to write the data to + public void Write(StreamWriter writer) + { + if (comments == null) + { + comments = new List(); + } + + writer.WriteLine("[" + edssection + "]"); + + writer.WriteLine(string.Format("Lines={0}", comments.Count)); + + int count = 1; + foreach (string s in comments) + { + writer.WriteLine(string.Format("Line{0}={1}", count, s)); + count++; + } + + writer.WriteLine(""); + } + } + public partial class Dummyusage : InfoSection + { + public Dummyusage(Dictionary section) : this() + { + Parse(section, edssection); + } + } + + /// + /// FileInfo section as described in CiA 306 + /// + public partial class FileInfo : InfoSection + { + public FileInfo(Dictionary section) : this() + { + Parse(section, edssection); + } + + override public void Parse(Dictionary section, string sectionname) + { + base.Parse(section, edssection); + + string dtcombined = ""; + try + { + if (section.ContainsKey("CreationTime") && section.ContainsKey("CreationDate")) + { + dtcombined = section["CreationTime"].Replace(" ", "") + " " + section["CreationDate"]; + CreationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + } + } + catch (Exception e) + { + if (e is System.FormatException) + { + Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for CreationTime, not in DS306 format", dtcombined, sectionname)); + } + } + + try + { + if (section.ContainsKey("ModificationTime") && section.ContainsKey("ModificationTime")) + { + dtcombined = section["ModificationTime"].Replace(" ", "") + " " + section["ModificationDate"]; + ModificationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + } + } + catch (Exception e) + { + if (e is System.FormatException) + { + Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for ModificationTime, not in DS306 format", dtcombined, sectionname)); + } + } + + + try + { + if (section.ContainsKey("EDSVersion")) + { + string[] bits = section["EDSVersion"].Split('.'); + if (bits.Length >= 1) + EDSVersionMajor = Convert.ToByte(bits[0]); + if (bits.Length >= 2) + EDSVersionMinor = Convert.ToByte(bits[1]); + //EDSVersion = String.Format("{0}.{1}", EDSVersionMajor, EDSVersionMinor); + } + } + catch + { + Warnings.warning_list.Add(String.Format("Unable to parse EDS version {0}", section["EDSVersion"])); + } + } + } + public partial class DeviceInfo : InfoSection + { + public DeviceInfo(Dictionary section) : this() + { + Parse(section, edssection); + } + } + + public partial class DeviceCommissioning : InfoSection + { + public DeviceCommissioning(Dictionary section) : this() + { + Parse(section, edssection); + } + + } + public partial class SupportedModules : InfoSection + { + public SupportedModules(Dictionary section) : this() + { + Parse(section, edssection); + } + } + + public partial class ConnectedModules : SupportedObjects + { + public ConnectedModules(Dictionary section) : this() + { + Parse(section); + + foreach (KeyValuePair kvp in this.objectlist) + { + UInt16 K = (UInt16)kvp.Value; + UInt16 V = (UInt16)kvp.Key; + + connectedmodulelist.Add(K, V); + } + } + } + public partial class MxFixedObjects : SupportedObjects + { + public MxFixedObjects(Dictionary section, UInt16 modindex) : this(modindex) + { + Parse(section); + + foreach (KeyValuePair kvp in this.objectlist) + { + connectedmodulelist.Add((UInt16)kvp.Value, (UInt16)kvp.Key); + } + } + } + + public partial class ModuleInfo : InfoSection + { + public ModuleInfo(Dictionary section, UInt16 moduleindex) : this(moduleindex) + { + Parse(section, edssection); + } + } + + public partial class ModuleComments : Comments + { + public ModuleComments(Dictionary section, UInt16 moduleindex) : this(moduleindex) + { + Parse(section); + } + } + + public partial class ModuleSubExtends : SupportedObjects + { + public ModuleSubExtends(Dictionary section, UInt16 moduleindex) + : this(moduleindex) + { + Parse(section); + } + } + + public partial class ODentry + { + /// + /// Write out this Object dictionary entry to an EDS/DCF file using correct formatting + /// + /// Handle to the stream writer to write to + /// File type being written + /// OD type to write + /// module + public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt = Odtype.NORMAL, int module = 0) + { + string fixedmodheader = ""; + + if (odt == Odtype.FIXED) + { + fixedmodheader = string.Format("M{0}Fixed", module); + } + + if (odt == Odtype.SUBEXT) + { + fixedmodheader = string.Format("M{0}SubExt", module); + } + + if (parent != null) + { + writer.WriteLine(string.Format("[{0}{1:X}sub{2:X}]", fixedmodheader, Index, Subindex)); + } + else + { + writer.WriteLine(string.Format("[{0}{1:X}]", fixedmodheader, Index)); + } + + writer.WriteLine(string.Format("ParameterName={0}", parameter_name)); + + if (ft == InfoSection.Filetype.File_DCF) + { + writer.WriteLine(string.Format("Denotation={0}", denotation)); + } + + writer.WriteLine(string.Format("ObjectType=0x{0:X}", (int)objecttype)); + writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); + + if (objecttype == ObjectType.ARRAY) + { + writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); + } + + if (objecttype == ObjectType.RECORD) + { + writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); + } + + if (objecttype == ObjectType.VAR) + { + DataType dt = datatype; + if (dt == DataType.UNKNOWN && this.parent != null) + dt = parent.datatype; + writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); + writer.WriteLine(string.Format("AccessType={0}", accesstype.ToString())); + + if (HighLimit != null && HighLimit != "") + { + writer.WriteLine(string.Format("HighLimit={0}", Formatoctetstring(HighLimit))); + } + + if (LowLimit != null && LowLimit != "") + { + writer.WriteLine(string.Format("LowLimit={0}", Formatoctetstring(LowLimit))); + } + + writer.WriteLine(string.Format("DefaultValue={0}", Formatoctetstring(defaultvalue))); + + //TODO If the ObjectType is domain (0x2) the value of the object may be stored in a file,UploadFile and DownloadFile + if (ft == InfoSection.Filetype.File_DCF) + { + writer.WriteLine(string.Format("ParameterValue={0}", Formatoctetstring(actualvalue))); + } + + writer.WriteLine(string.Format("PDOMapping={0}", PDOMapping == true ? 1 : 0)); + + if (prop.CO_flagsPDO == true) + { + writer.WriteLine(";TPDODetectCos=1"); + } + } + + //Count is for modules in the [MxSubExtxxxx] + //Should we export this on EDS only, or DCF or both? + if (odt == Odtype.SUBEXT) + { + writer.WriteLine(string.Format("Count={0}", count)); + writer.WriteLine(string.Format("ObjExtend={0}", ObjExtend)); + } + + //ObjectFlags is always optional (Page 15, DSP306) and used for DCF writing to nodes + //also recommended not to write if it is already 0 + if (ObjFlags != 0) + { + writer.WriteLine(string.Format("ObjFlags={0}", ObjFlags)); + } + + writer.WriteLine(""); + } + } + public partial class EDSsharp + { + public void Parseline(string linex, int no) + { + string key = ""; + string value = ""; + + string line = linex.TrimStart(';'); + bool custom_extension = false; + + if (linex == null || linex == "") + return; + + if (linex[0] == ';') + custom_extension = true; + + //extract sections + { + string pat = @"^\[([a-z0-9]+)\]"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(line); + if (m.Success) + { + Group g = m.Groups[1]; + sectionname = g.ToString(); + + if (!eds.ContainsKey(sectionname)) + { + eds.Add(sectionname, new Dictionary()); + } + else + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {0} : Duplicate section [{1}] ", no, sectionname)); + } + } + } + + //extract keyvalues + { + //Bug #70 Eat whitespace! + string pat = @"^([a-z0-9_]+)[ ]*=[ ]*(.*)"; + + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(line); + if (m.Success) + { + key = m.Groups[1].ToString(); + value = m.Groups[2].ToString(); + value = value.TrimEnd(' ', '\t', '\n', '\r'); + + //not sure how we actually get here with out a section being in the dictionary already.. + //suspect this is dead code. + if (!eds.ContainsKey(sectionname)) + { + eds.Add(sectionname, new Dictionary()); + } + + if (custom_extension == false) + { + try + { + eds[sectionname].Add(key, value); + } + catch (Exception) + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate key \"{0}\" value \"{1}\" in section [{2}]", key, value, sectionname, no)); + } + } + else + //Only allow our own extensions to populate the key/value pair + { + if (key == "StorageLocation" || key == "TPDODetectCos") + { + try + { + eds[sectionname].Add(key, value); + } + catch (Exception) + { + Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate custom key \"{0}\" value \"{1}\" in section [{2}]", key, value, sectionname, no)); + } + } + } + } + } + } + + public void ParseEDSentry(KeyValuePair> kvp) + { + string section = kvp.Key; + + string pat = @"^(M[0-9a-fA-F]+(Fixed|SubExt))?([a-fA-F0-9]+)(sub)?([0-9a-fA-F]*)$"; + + Regex r = new Regex(pat); + Match m = r.Match(section); + if (m.Success) + { + SortedDictionary target = this.ods; + + //** MODULE DCF SUPPORT + + string pat2 = @"^M([0-9a-fA-F]+)(Fixed|SubExt)([0-9a-fA-F]+)"; + Regex r2 = new Regex(pat2, RegexOptions.IgnoreCase); + Match m2 = r2.Match(m.Groups[0].ToString()); + + if (m2.Success) + { + UInt16 modindex = 0, odindex = 0; + + try { modindex = Convert.ToUInt16(m2.Groups[1].Value); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + m2.Groups[1].Value); } + //Indexes in the EDS are always in hex format without the pre 0x + try { odindex = Convert.ToUInt16(m2.Groups[3].Value, 16); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + m2.Groups[3].Value); } + + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + if (m2.Groups[2].ToString() == "SubExt") + { + target = modules[modindex].modulesubext; + } + else + { + target = modules[modindex].modulefixedobjects; + } + } + + ODentry od = new ODentry + { + //Indexes in the EDS are always in hex format without the pre 0x + Index = Convert.ToUInt16(m.Groups[3].ToString(), 16) + }; + + //Parameter name, mandatory always + if (!kvp.Value.ContainsKey("ParameterName")) + throw new ParameterException("Missing required field ParameterName on" + section); + od.parameter_name = kvp.Value["ParameterName"]; + + //Object type, assumed to be VAR unless specified + if (kvp.Value.ContainsKey("ObjectType")) + { + int type = Convert.ToInt16(kvp.Value["ObjectType"], Getbase(kvp.Value["ObjectType"])); + od.objecttype = (ObjectType)type; + } + else + { + od.objecttype = ObjectType.VAR; + } + + if (kvp.Value.ContainsKey("CompactSubObj")) + { + od.CompactSubObj = Convert.ToByte(kvp.Value["CompactSubObj"], Getbase(kvp.Value["CompactSubObj"])); + } + + if (kvp.Value.ContainsKey("ObjFlags")) + { + od.ObjFlags = Convert.ToUInt32(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); + } + else + { + od.ObjFlags = 0; + } + + //Access Type + if (kvp.Value.ContainsKey("StorageLocation")) + { + od.prop.CO_storageGroup = kvp.Value["StorageLocation"]; + } + + if (kvp.Value.ContainsKey("TPDODetectCos")) + { + string test = kvp.Value["TPDODetectCos"].ToLower(); + if (test == "1" || test == "true") + { + od.prop.CO_flagsPDO = true; + } + else + od.prop.CO_flagsPDO = false; + } + + if (kvp.Value.ContainsKey("Count")) + { + /* FIXME: The format of "Count" is Unsigned8[; Unsigned8] according DS306 + * Count: + Number of extended Sub-Indexes with this description that are created per module. The format is Unsigned8 [; Unsigned8]. + If one or more Sub - Indexes are created per attached module to build a new sub- index, then Count is that + Number. In example 32 bit module creates 4 Sub - Indexes each having 8 Bit: Count = 4 + If several modules are gathered to form a new Sub- Index, then the number is 0, followed by semicolon and the + number of bits that are created per module to build a new Sub-Index.In example 2 bit modules with 8 bit objects: The + first Sub - Index is built upon modules 1 - 4, the next upon modules 5 - 8 etc.: Count = 0; 2.The objects are created, + when a new byte begins: Module 1 creates the Sub - Index 1; modules 2 - 4 fill it up; module 5 creates Sub-Index 2 and + so forth. + */ + pat2 = @"\s*([0-9a-fA-F]+)\s*;\s*([0-9a-fA-F]+)"; + r2 = new Regex(pat2, RegexOptions.IgnoreCase); + m2 = r2.Match(kvp.Value["Count"]); + + if (m2.Success) + { + Console.WriteLine("** FIXME Count format not supported ** Count: " + kvp.Value["Count"]); + int found = kvp.Value["Count"].IndexOf(";"); + string s = kvp.Value["Count"].Substring(found + 1); + try { od.count = Convert.ToByte(s, Getbase(s)); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } + } + else + { + try { od.count = Convert.ToByte(kvp.Value["Count"], Getbase(kvp.Value["Count"])); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } + } + } + + if (kvp.Value.ContainsKey("ObjExtend")) + { + try { od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** ObjExtend:" + kvp.Value["ObjExtend"]); } + } + + + if (od.objecttype == ObjectType.VAR) + { + if (kvp.Value.ContainsKey("CompactSubObj")) + throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); + + if (kvp.Value.ContainsKey("ParameterValue")) + { + try { od.actualvalue = kvp.Value["ParameterValue"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** ParameterValue:" + kvp.Value["ParameterValue"]); } + } + + if (kvp.Value.ContainsKey("HighLimit")) + { + try { od.HighLimit = kvp.Value["HighLimit"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** HighLimit:" + kvp.Value["HighLimit"]); } + } + + if (kvp.Value.ContainsKey("LowLimit")) + { + try { od.LowLimit = kvp.Value["LowLimit"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** LowLimit:" + kvp.Value["LowLimit"]); } + } + + if (kvp.Value.ContainsKey("Denotation")) + { + try { od.denotation = kvp.Value["Denotation"]; } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Denotation:" + kvp.Value["Denotation"]); } + } + + if (m.Groups[5].Length != 0) + { + //FIXME are subindexes in hex always? + UInt16 subindex = Convert.ToUInt16(m.Groups[5].ToString(), 16); + od.parent = target[od.Index]; + target[od.Index].subobjects.Add(subindex, od); + } + + if (!kvp.Value.ContainsKey("DataType")) + throw new ParameterException("Missing required field DataType on" + section); + od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); + + if (!kvp.Value.ContainsKey("AccessType")) + throw new ParameterException("Missing required AccessType on" + section); + + string accesstype = kvp.Value["AccessType"].ToLower(); + + if (Enum.IsDefined(typeof(AccessType), accesstype)) + { + od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); + } + else + { + throw new ParameterException("Unknown AccessType on" + section); + } + + if (kvp.Value.ContainsKey("DefaultValue")) + od.defaultvalue = kvp.Value["DefaultValue"]; + + od.PDOtype = PDOMappingType.no; + if (kvp.Value.ContainsKey("PDOMapping")) + { + bool pdo = Convert.ToInt16(kvp.Value["PDOMapping"], Getbase(kvp.Value["PDOMapping"])) == 1; + if (pdo == true) + od.PDOtype = PDOMappingType.optional; + } + } + + if (od.objecttype == ObjectType.RECORD || od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) + { + if (od.CompactSubObj != 0) + { + if (!kvp.Value.ContainsKey("DataType")) + throw new ParameterException("Missing required field DataType on" + section); + od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); + + if (!kvp.Value.ContainsKey("AccessType")) + throw new ParameterException("Missing required AccessType on" + section); + string accesstype = kvp.Value["AccessType"]; + if (Enum.IsDefined(typeof(AccessType), accesstype)) + { + od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); + } + else + { + throw new ParameterException("Unknown AccessType on" + section); + } + + //now we generate CompactSubObj number of var objects below this parent + + if (od.CompactSubObj >= 0xfe) + { + od.CompactSubObj = 0xfe; + } + + ODentry subi = new ODentry("NrOfObjects", od.Index, DataType.UNSIGNED8, String.Format("0x{0:x2}", od.CompactSubObj), AccessType.ro, PDOMappingType.no, od); + od.subobjects.Add(0x00, subi); + + for (int x = 1; x <= od.CompactSubObj; x++) + { + string parameter_name = string.Format("{0}{1:x2}", od.parameter_name, x); + ODentry sub = new ODentry(parameter_name, od.Index, od.datatype, od.defaultvalue, od.accesstype, od.PDOtype, od); + + if (kvp.Value.ContainsKey("HighLimit")) + sub.HighLimit = kvp.Value["HighLimit"]; + + if (kvp.Value.ContainsKey("LowLimit")) + sub.HighLimit = kvp.Value["LowLimit"]; + + od.subobjects.Add((ushort)(x), sub); + } + } + else + { + if (!kvp.Value.ContainsKey("SubNumber")) + throw new ParameterException("Missing SubNumber on Array for" + section); + } + } + + if (od.objecttype == ObjectType.DOMAIN) + { + od.datatype = DataType.DOMAIN; + od.accesstype = AccessType.rw; + + if (kvp.Value.ContainsKey("DefaultValue")) + od.defaultvalue = kvp.Value["DefaultValue"]; + } + + //Only add top level to this list + if (m.Groups[5].Length == 0) + { + target.Add(od.Index, od); + } + } + } + + public void Loadfile(string filename) + { + projectFilename = filename; + + if (Path.GetExtension(filename).ToLower() == ".eds") + { + edsfilename = filename; + } + + if (Path.GetExtension(filename).ToLower() == ".dcf") + { + dcffilename = filename; + } + + int lineno = 1; + foreach (string linex in System.IO.File.ReadLines(filename)) + { + Parseline(linex, lineno); + lineno++; + } + + di = new DeviceInfo(eds["DeviceInfo"]); + + foreach (KeyValuePair> kvp in eds) + { + try { ParseEDSentry(kvp); } + catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + kvp); } + } + + fi = new FileInfo(eds["FileInfo"]); + if (eds.ContainsKey("DummyUsage")) + du = new Dummyusage(eds["DummyUsage"]); + + md = new MandatoryObjects(eds["MandatoryObjects"]); + + if (eds.ContainsKey("OptionalObjects")) + oo = new OptionalObjects(eds["OptionalObjects"]); + + if (eds.ContainsKey("ManufacturerObjects")) + mo = new ManufacturerObjects(eds["ManufacturerObjects"]); + + if (eds.ContainsKey("TypeDefinitions")) + td = new TypeDefinitions(eds["TypeDefinitions"]); + + //Only DCF not EDS files + dc = new DeviceCommissioning(); + string strSection = ""; + if (eds.ContainsKey("DeviceCommissioning")) // wrong section name as defined in the DSP302, but right spelling (for compabiltiy to some tools) + strSection = "DeviceCommissioning"; + else if (eds.ContainsKey("DeviceComissioning")) // right section name as defined in the DSP302, (wrong spelling) + strSection = "DeviceComissioning"; + + if (strSection != "") + { + dc.Parse(eds[strSection], "DeviceCommissioning"); + edsfilename = fi.LastEDS; + } + + c = new Comments(); + + if (eds.ContainsKey("Comments")) + c.Parse(eds["Comments"]); + + //Modules + + //FIXME + //we don't parse or support [MxFixedObjects] with MxFixedxxxx and MxFixedxxxxsubx + + if (eds.ContainsKey("SupportedModules")) + { + sm = new SupportedModules(eds["SupportedModules"]); + + //find MxModuleInfo + + foreach (string s in eds.Keys) + { + String pat = @"M([0-9]+)ModuleInfo"; + Regex r = new Regex(pat, RegexOptions.IgnoreCase); + Match m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleInfo mi = new ModuleInfo(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mi = mi; + } + + pat = @"M([0-9]+)Comments"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleComments mc = new ModuleComments(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mc = mc; + } + pat = @"M([0-9]+)SubExtends"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + ModuleSubExtends mse = new ModuleSubExtends(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mse = mse; + } + + //DCF only + + pat = @"M([0-9]+)FixedObjects"; + r = new Regex(pat, RegexOptions.IgnoreCase); + m = r.Match(s); + + if (m.Success) + { + UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); + MxFixedObjects mxf = new MxFixedObjects(eds[s], modindex); + + if (!modules.ContainsKey(modindex)) + modules.Add(modindex, new Module(modindex)); + + modules[modindex].mxfo = mxf; + } + } + + if (eds.ContainsKey("ConnectedModules")) + { + cm = new ConnectedModules(eds["ConnectedModules"]); + } + + //COMPACT PDO + + if (di.CompactPDO != 0) + { + for (UInt16 index = 0x1400; index < 0x1600; index++) + { + ApplycompactPDO(index); + } + + for (UInt16 index = 0x1800; index < 0x1A00; index++) + { + ApplycompactPDO(index); + } + } + + ApplyimplicitPDO(); + } + // catch(Exception e) + //{ + // Console.WriteLine("** ALL GONE WRONG **" + e.ToString()); + // } + } + + void ApplycompactPDO(UInt16 index) + { + if (ods.ContainsKey(index)) + { + if ((!ods[index].Containssubindex(1)) && ((this.di.CompactPDO & 0x01) == 0)) + { + //Fill in cob ID + //FIX ME i'm really sure this is not correct, what default values should be used??? + string cob = string.Format("$NODEID + 0x180"); + ODentry subod = new ODentry("COB-ID", index, DataType.UNSIGNED32, cob, AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x05, subod); + } + + if ((!ods[index].Containssubindex(2)) && ((this.di.CompactPDO & 0x02) == 0)) + { + //Fill in type + ODentry subod = new ODentry("Type", index, DataType.UNSIGNED8, "0xff", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x02, subod); + } + + if ((!ods[index].Containssubindex(3)) && ((this.di.CompactPDO & 0x04) == 0)) + { + //Fill in inhibit + ODentry subod = new ODentry("Inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x03, subod); + } + + //NOT FOR RX PDO + if (index < 0x1800) + return; + + if ((!ods[index].Containssubindex(4)) && ((this.di.CompactPDO & 0x08) == 0)) + { + //Fill in compatibility entry + ODentry subod = new ODentry("Compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x04, subod); + } + + if ((!ods[index].Containssubindex(5)) && ((this.di.CompactPDO & 0x10) == 0)) + { + //Fill in event timer + ODentry subod = new ODentry("Event Timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); + ods[index].subobjects.Add(0x05, subod); + } + } + } + + /// + /// This function scans the PDO list and compares it to NrOfRXPDO and NrOfTXPDO + /// if these do not match in count then implicit PDOs are present and they are + /// filled in with default values from the lowest possible index + /// + protected void ApplyimplicitPDO() + { + UInt16 totalnorxpdos = di.NrOfRXPDO; + UInt16 totalnotxpdos = di.NrOfTXPDO; + + UpdatePDOcount(); + + UInt16 noexplicitrxpdos = di.NrOfRXPDO; + UInt16 noexplicittxpdos = di.NrOfTXPDO; + + //this is how many PDOS need generating on the fly + UInt16 noimplictrxpdos = (UInt16)(totalnorxpdos - noexplicitrxpdos); + UInt16 noimplicttxpdos = (UInt16)(totalnotxpdos - noexplicittxpdos); + + for (UInt16 index = 0x1400; (index < 0x1600) && (noimplictrxpdos > 0); index++) + { + if (!ods.ContainsKey(index)) + { + CreateRXPDO(index); + noimplictrxpdos--; + } + } + + for (UInt16 index = 0x1800; (index < 0x1A00) && (noimplicttxpdos > 0); index++) + { + if (!ods.ContainsKey(index)) + { + CreateTXPDO(index); + noimplicttxpdos--; + } + } + UpdatePDOcount(); + } + + public void Savefile(string filename, InfoSection.Filetype ft) + { + if (ft == InfoSection.Filetype.File_EDS) + this.edsfilename = filename; + + if (ft == InfoSection.Filetype.File_DCF) + { + this.dcffilename = filename; + fi.LastEDS = edsfilename; + } + + UpdatePDOcount(); + + //generate date times in DS306 format; h:mmtt MM-dd-yyyy + + fi.CreationDate = fi.CreationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); + fi.CreationTime = fi.CreationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); + + fi.ModificationDate = fi.ModificationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); + fi.ModificationTime = fi.ModificationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); + + fi.FileName = Path.GetFileName(filename); + + fi.EDSVersion = "4.0"; + fi.EDSVersionMajor = 4; + fi.EDSVersionMinor = 0; + + StreamWriter writer = System.IO.File.CreateText(filename); + writer.NewLine = "\n"; + fi.Write(writer, ft); + di.Write(writer, ft); + du.Write(writer, ft); + c.Write(writer); + + if (ft == InfoSection.Filetype.File_DCF) + { + dc.Write(writer, ft); + } + + //regenerate the object lists + md.objectlist.Clear(); + mo.objectlist.Clear(); + oo.objectlist.Clear(); + + foreach (KeyValuePair kvp in ods) + { + ODentry entry = kvp.Value; + + if (entry.prop.CO_disabled == true) + continue; + + if (entry.Index == 0x1000 || entry.Index == 0x1001 || entry.Index == 0x1018) + { + md.objectlist.Add(md.objectlist.Count + 1, entry.Index); + } + else + if (entry.Index >= 0x2000 && entry.Index < 0x6000) + { + mo.objectlist.Add(mo.objectlist.Count + 1, entry.Index); + } + else + { + oo.objectlist.Add(oo.objectlist.Count + 1, entry.Index); + } + } + + md.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (md.objectlist.ContainsValue(od.Index)) + { + od.Write(writer, ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer, ft); + } + } + } + + oo.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (oo.objectlist.ContainsValue(od.Index)) + { + od.Write(writer, ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer, ft); + } + } + } + + mo.Write(writer); + + foreach (KeyValuePair kvp in ods) + { + ODentry od = kvp.Value; + if (mo.objectlist.ContainsValue(od.Index)) + { + od.Write(writer, ft); + foreach (KeyValuePair kvp2 in od.subobjects) + { + ODentry od2 = kvp2.Value; + od2.Write(writer, ft); + } + } + } + + //modules + + if (sm.NrOfEntries > 0) + { + sm.Write(writer, ft); + + for (UInt16 moduleid = 1; moduleid <= sm.NrOfEntries; moduleid++) + { + modules[moduleid].mi.Write(writer, ft); + + modules[moduleid].mc.Write(writer); + + modules[moduleid].mse.Write(writer); + + foreach (KeyValuePair kvp2 in modules[moduleid].modulesubext) + { + ODentry od = kvp2.Value; + od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); + } + + modules[moduleid].mxfo.Write(writer); + + foreach (KeyValuePair kvp3 in modules[moduleid].modulefixedobjects) + { + ODentry od = kvp3.Value; + od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); + + foreach (KeyValuePair kvp4 in od.subobjects) + { + ODentry subod = kvp4.Value; + subod.Write(writer, ft, ODentry.Odtype.FIXED, moduleid); + } + } + } + } + + if (ft == InfoSection.Filetype.File_DCF) + { + if (cm.NrOfEntries > 0) + { + cm.Write(writer); + } + } + writer.Close(); + } + + //RX COM 0x1400 + //RX Map 0x1600 + //TX COM 0x1800 + //TX MAP 0x1a00 + + //call this with the comm param index not the mapping + bool CreatePDO(bool rx, UInt16 index) + { + //check if we are creating an RX PDO it is a valid index + if (rx && (index < 0x1400 || index >= 0x1600)) + return false; + + //check if we are creating an PDO TX it is a valid index + if (!rx & (index < 0x1800 || index >= 0x1A00)) + return false; + + //Check it does not already exist + if (ods.ContainsKey(index)) + return false; + + //check the associated mapping index does not exist + if (ods.ContainsKey((UInt16)(index + 0x200))) + return false; + + ODentry od_comparam; + ODentry od_mapping; + + if (rx) + { + od_comparam = new ODentry("RPDO communication parameter", index, 0) + { + Description = @"0x1400 - 0x15FF RPDO communication parameter +max sub-index + +COB - ID + bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set + bit 11 - 29: set to 0 for 11 bit COB - ID + bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO + bit 31: 0(1) - node uses(does NOT use) PDO + +Transmission type + value = 0 - 240: receiving is synchronous, process after next reception of SYNC object + value = 241 - 253: not used + value = 254: manufacturer specific + value = 255: asynchronous" + }; + + od_mapping = new ODentry("RPDO mapping parameter", (UInt16)(index + 0x200), 0) + { + Description = @"0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) +Number of mapped objects + +mapped object (subindex 1...8) + bit 0 - 7: data length in bits + bit 8 - 15: subindex from OD + bit 16 - 31: index from OD" + }; + } + else + { + od_comparam = new ODentry("TPDO communication parameter", index, 0) + { + Description = @"0x1800 - 0x19FF TPDO communication parameter +max sub-index + +COB - ID + bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set + bit 11 - 29: set to 0 for 11 bit COB - ID + bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO + bit 31: 0(1) - node uses(does NOT use) PDO + +Transmission type + value = 0: transmitting is synchronous, specification in device profile + value = 1 - 240: transmitting is synchronous after every N - th SYNC object + value = 241 - 251: not used + value = 252 - 253: Transmitted only on reception of Remote Transmission Request + value = 254: manufacturer specific + value = 255: asynchronous, specification in device profile + +inhibit time + bit 0 - 15: Minimum time between transmissions of the PDO in 100µs.Zero disables functionality. + +event timer + bit 0-15: Time between periodic transmissions of the PDO in ms.Zero disables functionality. + +SYNC start value + value = 0: Counter of the SYNC message shall not be processed. + value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message." + }; + + od_mapping = new ODentry("TPDO mapping parameter", (UInt16)(index + 0x200), 0) + { + Description = @"0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). +Number of mapped objects + +mapped object (subindex 1...8) + bit 0 - 7: data length in bits + bit 8 - 15: subindex from OD + bit 16 - 31: index from OD" + }; + } + + od_comparam.objecttype = ObjectType.RECORD; + od_comparam.prop.CO_storageGroup = "ROM"; + od_comparam.accesstype = AccessType.ro; + od_comparam.PDOtype = PDOMappingType.no; + + ODentry sub; + + if (rx) + { + sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "2", AccessType.ro, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(0, sub); + sub = new ODentry("COB-ID used by RPDO", index, DataType.UNSIGNED32, "$NODEID+0x200", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(1, sub); + sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(2, sub); + } + else + { + sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "6", AccessType.ro, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(0, sub); + sub = new ODentry("COB-ID used by TPDO", index, DataType.UNSIGNED32, "$NODEID+0x180", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(1, sub); + sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(2, sub); + sub = new ODentry("inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(3, sub); + //sub = new ODentry("compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); + //od_comparam.subobjects.Add(4, sub); + sub = new ODentry("event timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(5, sub); + sub = new ODentry("SYNC start value", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); + od_comparam.subobjects.Add(6, sub); + } + + od_mapping.objecttype = ObjectType.RECORD; + od_mapping.prop.CO_storageGroup = "ROM"; + od_mapping.accesstype = AccessType.rw; //Same as default but inconsistent with ROM above + od_mapping.PDOtype = PDOMappingType.no; + + sub = new ODentry("Number of mapped objects", (UInt16)(index + 0x200), DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, od_mapping); + od_mapping.subobjects.Add(0, sub); + + for (int p = 1; p <= 8; p++) + { + sub = new ODentry(string.Format("mapped object {0}", p), (UInt16)(index + 0x200), DataType.UNSIGNED32, "0x00000000", AccessType.ro, PDOMappingType.no, od_mapping); + od_mapping.subobjects.Add((byte)p, sub); + } + + ods.Add(index, od_comparam); + ods.Add((UInt16)(index + 0x200), od_mapping); + + return true; + } + + bool CreateTXPDO(UInt16 index) + { + return CreatePDO(false, index); + } + + bool CreateRXPDO(UInt16 index) + { + return CreatePDO(true, index); + } + } +} diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 487acf18..5df21990 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -331,7 +331,7 @@ public class DcfExport : EdsExport /// /// Section of info in EDS or DCF file /// - public class InfoSection + public partial class InfoSection { protected Dictionary section; @@ -344,24 +344,6 @@ public enum Filetype File_DCF } - public virtual void Parse(Dictionary section,string sectionname) - { - - this.section = section; - - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - if(Attribute.IsDefined(f, typeof(EdsExport))) - GetField(f.Name, f.Name); - - if (Attribute.IsDefined(f, typeof(DcfExport))) - GetField(f.Name, f.Name); - } - - } - public bool GetField(string name, string varname) { FieldInfo f = null; @@ -450,51 +432,10 @@ public override string ToString() return msg; } - /// - /// Write object to stream - /// - /// stream to write the data to - /// file type - public void Write(StreamWriter writer, Filetype ft) - { - writer.WriteLine("[" + edssection + "]"); - Type tx = this.GetType(); - FieldInfo[] fields = this.GetType().GetFields(); - - foreach (FieldInfo f in fields) - { - - if ((ft==Filetype.File_EDS) && (!Attribute.IsDefined(f, typeof(EdsExport)))) - continue; - - if ((ft == Filetype.File_DCF) && (!(Attribute.IsDefined(f, typeof(DcfExport)) || Attribute.IsDefined(f, typeof(EdsExport))))) - continue; - - if (f.GetValue(this) == null) - continue; - - EdsExport ex = (EdsExport)f.GetCustomAttribute(typeof(EdsExport)); - - bool comment = ex.IsReadOnly(); - - if (f.FieldType.Name == "Boolean") - { - writer.WriteLine(string.Format("{2}{0}={1}", f.Name, ((bool)f.GetValue(this)) == true ? 1 : 0,comment==true?";":"")); - } - else - { - writer.WriteLine(string.Format("{2}{0}={1}", f.Name, f.GetValue(this).ToString(), comment == true ? ";" : "")); - } - } - - writer.WriteLine(""); - - } - } - public class MandatoryObjects : SupportedObjects + public partial class MandatoryObjects : SupportedObjects { public MandatoryObjects() : base() @@ -502,15 +443,9 @@ public MandatoryObjects() infoheader = "Mandatory Objects"; edssection = "MandatoryObjects"; } - - public MandatoryObjects(Dictionary section) - : this() - { - Parse(section); - } } - public class OptionalObjects : SupportedObjects + public partial class OptionalObjects : SupportedObjects { public OptionalObjects() : base() @@ -518,45 +453,27 @@ public OptionalObjects() infoheader = "Optional Objects"; edssection = "OptionalObjects"; } - - public OptionalObjects(Dictionary section) - : this() - { - Parse(section); - } } - public class ManufacturerObjects : SupportedObjects + public partial class ManufacturerObjects : SupportedObjects { public ManufacturerObjects() : base() { infoheader = "Manufacturer Objects"; edssection = "ManufacturerObjects"; } - - public ManufacturerObjects(Dictionary section) - : this() - { - Parse(section); - } } - public class TypeDefinitions : SupportedObjects + public partial class TypeDefinitions : SupportedObjects { public TypeDefinitions() : base() { infoheader = "Type Definitions"; edssection = "TypeDefinitions"; } - - public TypeDefinitions(Dictionary section) - { - Parse(section); - } - } - public class SupportedObjects + public partial class SupportedObjects { public Dictionary objectlist; @@ -568,23 +485,6 @@ public SupportedObjects() { objectlist = new Dictionary(); } - - public virtual void Parse(Dictionary section) - { - objectlist = new Dictionary(); - foreach(KeyValuePair kvp in section) - { - if(kvp.Key.ToLower()=="supportedobjects") - continue; - - if (kvp.Key.ToLower() == "nrofentries") - continue; - - int count = Convert.ToInt16(kvp.Key, EDSsharp.Getbase(kvp.Key)); - int target = Convert.ToInt16(kvp.Value, EDSsharp.Getbase(kvp.Value)); - objectlist.Add(count, target); - } - } /// /// Returns a string that represents the current object. /// @@ -605,25 +505,9 @@ public override string ToString() return msg; } - /// - /// Write object to stream - /// - /// stream to write the data to - public void Write(StreamWriter writer) - { - writer.WriteLine("[" + edssection + "]"); - writer.WriteLine(string.Format("{0}={1}", countmsg,objectlist.Count)); - foreach (KeyValuePair kvp in objectlist) - { - writer.WriteLine(string.Format("{0}=0x{1:X4}", kvp.Key, kvp.Value)); - } - - writer.WriteLine(""); - } - } - public class Comments + public partial class Comments { public List comments = new List(); @@ -635,23 +519,6 @@ public Comments() } - public Comments(Dictionary section) - { - Parse(section); - } - - public virtual void Parse(Dictionary section) - { - comments = new List(); - foreach (KeyValuePair kvp in section) - { - if (kvp.Key == "Lines") - continue; - - comments.Add(kvp.Value); - - } - } /// /// Returns a string that represents the current object. /// @@ -672,34 +539,10 @@ public override string ToString() return msg; } - /// - /// Write object to stream - /// - /// stream to write the data to - public void Write(StreamWriter writer) - { - if(comments == null) - { - comments = new List(); - } - - writer.WriteLine("[" + edssection + "]"); - - writer.WriteLine(string.Format("Lines={0}", comments.Count)); - - int count = 1; - foreach (string s in comments) - { - writer.WriteLine(string.Format("Line{0}={1}", count, s)); - count++; - } - - writer.WriteLine(""); - } } - public class Dummyusage : InfoSection + public partial class Dummyusage : InfoSection { [EdsExport] public bool Dummy0001; @@ -722,17 +565,12 @@ public Dummyusage() infoheader = "CAN OPEN Dummy Usage"; edssection = "DummyUsage"; } - - public Dummyusage(Dictionary section) : this() - { - Parse(section,edssection); - } } /// /// FileInfo section as described in CiA 306 /// - public class FileInfo : InfoSection + public partial class FileInfo : InfoSection { // Only for internal usage, use Path.GetFileName(eds.projectFilename) instead. /// @@ -805,82 +643,17 @@ public class FileInfo : InfoSection //Folder CO_OD.c and CO_OD.h will be exported into public string exportFolder = ""; - - public FileInfo(Dictionary section) : this() - { - Parse(section,edssection); - } - public FileInfo() { infoheader = "CAN OPEN FileInfo"; edssection = "FileInfo"; } - - - override public void Parse(Dictionary section, string sectionname) - { - - base.Parse(section,edssection); - - string dtcombined = ""; - try - { - if (section.ContainsKey("CreationTime") && section.ContainsKey("CreationDate")) - { - dtcombined = section["CreationTime"].Replace(" ","") + " " + section["CreationDate"]; - CreationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - } - } - catch(Exception e) - { - if (e is System.FormatException) - { - Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for CreationTime, not in DS306 format", dtcombined,sectionname)); - } - } - - try - { - if (section.ContainsKey("ModificationTime") && section.ContainsKey("ModificationTime")) - { - dtcombined = section["ModificationTime"].Replace(" ", "") + " " + section["ModificationDate"]; - ModificationDateTime = DateTime.ParseExact(dtcombined, "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); - } - } - catch (Exception e) - { - if (e is System.FormatException) - { - Warnings.warning_list.Add(String.Format("EDS Error: Section [{1}] Unable to parse DateTime {0} for ModificationTime, not in DS306 format", dtcombined, sectionname)); - } - } - - - try - { - if (section.ContainsKey("EDSVersion")) - { - string[] bits = section["EDSVersion"].Split('.'); - if (bits.Length >= 1) - EDSVersionMajor = Convert.ToByte(bits[0]); - if (bits.Length >= 2) - EDSVersionMinor = Convert.ToByte(bits[1]); - //EDSVersion = String.Format("{0}.{1}", EDSVersionMajor, EDSVersionMinor); - } - } - catch - { - Warnings.warning_list.Add(String.Format("Unable to parse EDS version {0}", section["EDSVersion"])); - } - - } } /// /// DeviceInfo section as described in CiA 306 /// - public class DeviceInfo : InfoSection + public partial class DeviceInfo : InfoSection { /// /// vendor name (max. 244 characters) @@ -1010,15 +783,10 @@ public DeviceInfo() infoheader = "CAN OPEN DeviceInfo"; edssection = "DeviceInfo"; } - - public DeviceInfo(Dictionary section) : this() - { - Parse(section,edssection); - } } - public class DeviceCommissioning : InfoSection + public partial class DeviceCommissioning : InfoSection { public DeviceCommissioning() @@ -1027,11 +795,6 @@ public DeviceCommissioning() edssection = "DeviceComissioning"; } - public DeviceCommissioning(Dictionary section) : this() - { - Parse(section,edssection); - } - [DcfExport] public byte NodeID = 0; @@ -1055,7 +818,7 @@ public DeviceCommissioning(Dictionary section) : this() } - public class SupportedModules : InfoSection + public partial class SupportedModules : InfoSection { [EdsExport] public UInt16 NrOfEntries; @@ -1065,16 +828,9 @@ public SupportedModules() infoheader = "CAN OPEN Supported Modules"; edssection = "SupportedModules"; } - - public SupportedModules(Dictionary section) : this() - { - Parse(section,edssection); - } - - } - public class ConnectedModules : SupportedObjects + public partial class ConnectedModules : SupportedObjects { [EdsExport] public UInt16 NrOfEntries @@ -1091,29 +847,9 @@ public ConnectedModules() countmsg = "NrOfEntries"; connectedmodulelist = new Dictionary(); } - - public ConnectedModules(Dictionary section) : this() - { - Parse(section); - - - foreach(KeyValuePair kvp in this.objectlist) - { - - - UInt16 K = (UInt16)kvp.Value; - UInt16 V = (UInt16)kvp.Key; - - connectedmodulelist.Add(K, V); - - - } - - } - } - public class MxFixedObjects : SupportedObjects + public partial class MxFixedObjects : SupportedObjects { [EdsExport] public UInt16 NrOfEntries @@ -1138,22 +874,9 @@ public MxFixedObjects(UInt16 modindex) countmsg = "NrOfEntries"; connectedmodulelist = new Dictionary(); } - - public MxFixedObjects(Dictionary section, UInt16 modindex) : this(modindex) - { - Parse(section); - - foreach (KeyValuePair kvp in this.objectlist) - { - connectedmodulelist.Add((UInt16)kvp.Value, (UInt16)kvp.Key); - } - } - } - - - public class ModuleInfo : InfoSection + public partial class ModuleInfo : InfoSection { [EdsExport(maxlength = 248)] public string ProductName; @@ -1175,15 +898,9 @@ public ModuleInfo(UInt16 moduleindex) infoheader = "CAN OPEN Module Info " + moduleindex.ToString(); edssection = string.Format("M{0}{1}", moduleindex, "ModuleInfo"); } - - public ModuleInfo(Dictionary section, UInt16 moduleindex) : this (moduleindex) - { - Parse(section,edssection); - } } - - public class ModuleComments : Comments + public partial class ModuleComments : Comments { UInt16 moduleindex; @@ -1194,16 +911,9 @@ public ModuleComments(UInt16 moduleindex) infoheader = "CAN OPEN Module Comments " + moduleindex.ToString(); edssection = string.Format("M{0}{1}", moduleindex, "Comments"); } - - public ModuleComments(Dictionary section,UInt16 moduleindex) : this (moduleindex) - { - Parse(section); - } - - } - public class ModuleSubExtends : SupportedObjects + public partial class ModuleSubExtends : SupportedObjects { UInt16 moduleindex; @@ -1215,18 +925,11 @@ public ModuleSubExtends(UInt16 moduleindex) infoheader = "CAN OPEN ModuleSubExtends "+moduleindex.ToString(); edssection = string.Format("M{0}{1}", moduleindex, "SubExtends"); } - - public ModuleSubExtends(Dictionary section, UInt16 moduleindex) - : this(moduleindex) - { - Parse(section); - } - } /// /// Represent object dictionary index and subindex objects /// - public class ODentry + public partial class ODentry { private UInt16 _index; @@ -1711,112 +1414,6 @@ public string Formatoctetstring(string value) return ret; } - /// - /// Write out this Object dictionary entry to an EDS/DCF file using correct formatting - /// - /// Handle to the stream writer to write to - /// File type being written - /// OD type to write - /// module - public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt= Odtype.NORMAL, int module=0) - { - - string fixedmodheader = ""; - - if (odt == Odtype.FIXED) - { - fixedmodheader = string.Format("M{0}Fixed", module); - } - - if(odt == Odtype.SUBEXT) - { - fixedmodheader = string.Format("M{0}SubExt", module); - } - - if (parent != null) - { - writer.WriteLine(string.Format("[{0}{1:X}sub{2:X}]", fixedmodheader,Index, Subindex)); - } - else - { - writer.WriteLine(string.Format("[{0}{1:X}]",fixedmodheader,Index)); - } - - writer.WriteLine(string.Format("ParameterName={0}", parameter_name)); - - if(ft == InfoSection.Filetype.File_DCF) - { - writer.WriteLine(string.Format("Denotation={0}", denotation)); - } - - writer.WriteLine(string.Format("ObjectType=0x{0:X}", (int)objecttype)); - writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); - - if (objecttype == ObjectType.ARRAY) - { - writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); - } - - if (objecttype == ObjectType.RECORD) - { - writer.WriteLine(string.Format("SubNumber=0x{0:X}", Nosubindexes)); - } - - if (objecttype == ObjectType.VAR) - { - DataType dt = datatype; - if (dt == DataType.UNKNOWN && this.parent != null) - dt = parent.datatype; - writer.WriteLine(string.Format("DataType=0x{0:X4}", (int)dt)); - writer.WriteLine(string.Format("AccessType={0}", accesstype.ToString())); - - - if(HighLimit != null && HighLimit != "") - { - writer.WriteLine(string.Format("HighLimit={0}", Formatoctetstring(HighLimit))); - } - - if (LowLimit != null && LowLimit != "") - { - writer.WriteLine(string.Format("LowLimit={0}", Formatoctetstring(LowLimit))); - } - - writer.WriteLine(string.Format("DefaultValue={0}", Formatoctetstring(defaultvalue))); - - //TODO If the ObjectType is domain (0x2) the value of the object may be stored in a file,UploadFile and DownloadFile - if (ft == InfoSection.Filetype.File_DCF) - { - writer.WriteLine(string.Format("ParameterValue={0}", Formatoctetstring(actualvalue))); - } - - writer.WriteLine(string.Format("PDOMapping={0}", PDOMapping==true?1:0)); - - if (prop.CO_flagsPDO == true) - { - writer.WriteLine(";TPDODetectCos=1"); - } - - - } - - //Count is for modules in the [MxSubExtxxxx] - //Should we export this on EDS only, or DCF or both? - if (odt == Odtype.SUBEXT ) - { - writer.WriteLine(string.Format("Count={0}", count)); - writer.WriteLine(string.Format("ObjExtend={0}", ObjExtend)); - } - - //ObjectFlags is always optional (Page 15, DSP306) and used for DCF writing to nodes - //also recommended not to write if it is already 0 - if (ObjFlags != 0) - { - writer.WriteLine(string.Format("ObjFlags={0}", ObjFlags)); - } - - writer.WriteLine(""); - } - /// /// Returns a c compatible string that represents the name of the object, - is replaced with _ /// words separated by a space are replaced with _ for a separator eg ONE TWO becomes ONE_TWO @@ -2069,7 +1666,7 @@ public Module(UInt16 moduleindex) } - public class EDSsharp + public partial class EDSsharp { public enum AccessType @@ -2281,829 +1878,19 @@ public List VerifyPDOMapping() return mappingErrors; } - public void Parseline(string linex,int no) + public DataType Getdatatype(ODentry od) { - string key = ""; - string value = ""; - - string line = linex.TrimStart(';'); - bool custom_extension = false; - - if (linex == null || linex == "") - return; - - if (linex[0] == ';') - custom_extension = true; - - - //extract sections + if (od.objecttype == ObjectType.VAR) { - string pat = @"^\[([a-z0-9]+)\]"; - - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(line); - if (m.Success) - { - Group g = m.Groups[1]; - sectionname = g.ToString(); - - if (!eds.ContainsKey(sectionname)) - { - eds.Add(sectionname, new Dictionary()); - } - else - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {0} : Duplicate section [{1}] ", no,sectionname)); - } - } + return od.datatype; } - //extract keyvalues + if (od.objecttype == ObjectType.ARRAY) { - //Bug #70 Eat whitespace! - string pat = @"^([a-z0-9_]+)[ ]*=[ ]*(.*)"; + ODentry sub2 = ods[od.Index]; - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(line); - if (m.Success) - { - key = m.Groups[1].ToString(); - value = m.Groups[2].ToString(); - value = value.TrimEnd(' ','\t','\n','\r'); - - //not sure how we actually get here with out a section being in the dictionary already.. - //suspect this is dead code. - if (!eds.ContainsKey(sectionname)) - { - eds.Add(sectionname, new Dictionary()); - } - - if (custom_extension == false) - { - try - { - eds[sectionname].Add(key, value); - } - catch(Exception) - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate key \"{0}\" value \"{1}\" in section [{2}]", key,value,sectionname, no)); - } - } - else - //Only allow our own extensions to populate the key/value pair - { - if (key == "StorageLocation" || key== "TPDODetectCos") - { - try - { - eds[sectionname].Add(key, value); - } - catch(Exception) - { - Warnings.warning_list.Add(string.Format("EDS Error on Line {3} : Duplicate custom key \"{0}\" value \"{1}\" in section [{2}]", key, value, sectionname, no)); - } - } - } - } - } - } - - public void ParseEDSentry(KeyValuePair> kvp) - { - string section = kvp.Key; - - string pat = @"^(M[0-9a-fA-F]+(Fixed|SubExt))?([a-fA-F0-9]+)(sub)?([0-9a-fA-F]*)$"; - - Regex r = new Regex(pat); - Match m = r.Match(section); - if (m.Success) - { - - SortedDictionary target = this.ods; - - //** MODULE DCF SUPPORT - - string pat2 = @"^M([0-9a-fA-F]+)(Fixed|SubExt)([0-9a-fA-F]+)"; - Regex r2 = new Regex(pat2, RegexOptions.IgnoreCase); - Match m2 = r2.Match(m.Groups[0].ToString()); - - if (m2.Success) - { - UInt16 modindex=0, odindex=0; - - try { modindex = Convert.ToUInt16(m2.Groups[1].Value); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + m2.Groups[1].Value); } - //Indexes in the EDS are always in hex format without the pre 0x - try { odindex = Convert.ToUInt16(m2.Groups[3].Value, 16); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + m2.Groups[3].Value); } - - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - if (m2.Groups[2].ToString() == "SubExt") - { - target = modules[modindex].modulesubext; - - } - else - { - target = modules[modindex].modulefixedobjects; - } - } - - - ODentry od = new ODentry - { - //Indexes in the EDS are always in hex format without the pre 0x - Index = Convert.ToUInt16(m.Groups[3].ToString(), 16) - }; - - //Parameter name, mandatory always - if (!kvp.Value.ContainsKey("ParameterName")) - throw new ParameterException("Missing required field ParameterName on" + section); - od.parameter_name = kvp.Value["ParameterName"]; - - //Object type, assumed to be VAR unless specified - if (kvp.Value.ContainsKey("ObjectType")) - { - int type = Convert.ToInt16(kvp.Value["ObjectType"], Getbase(kvp.Value["ObjectType"])); - od.objecttype = (ObjectType)type; - } - else - { - od.objecttype = ObjectType.VAR; - } - - if(kvp.Value.ContainsKey("CompactSubObj")) - { - od.CompactSubObj = Convert.ToByte(kvp.Value["CompactSubObj"],Getbase(kvp.Value["CompactSubObj"])); - } - - if(kvp.Value.ContainsKey("ObjFlags")) - { - od.ObjFlags = Convert.ToUInt32(kvp.Value["ObjFlags"], Getbase(kvp.Value["ObjFlags"])); - } - else - { - od.ObjFlags = 0; - } - - //Access Type - if(kvp.Value.ContainsKey("StorageLocation")) - { - od.prop.CO_storageGroup = kvp.Value["StorageLocation"]; - } - - if (kvp.Value.ContainsKey("TPDODetectCos")) - { - string test = kvp.Value["TPDODetectCos"].ToLower(); - if (test == "1" || test == "true") - { - od.prop.CO_flagsPDO = true; - } - else - od.prop.CO_flagsPDO = false; - } - - if (kvp.Value.ContainsKey("Count")) - { - /* FIXME: The format of "Count" is Unsigned8[; Unsigned8] according DS306 - * Count: - Number of extended Sub-Indexes with this description that are created per module. The format is Unsigned8 [; Unsigned8]. - If one or more Sub - Indexes are created per attached module to build a new sub- index, then Count is that Number. In example 32 bit module creates 4 Sub - Indexes each having 8 Bit: Count = 4 - If several modules are gathered to form a new Sub- Index, then the number is 0, followed by semicolon and the number of bits that are created per module to build a new Sub-Index.In example 2 bit modules with 8 bit objects: The first Sub - Index is built upon modules 1 - 4, the next upon modules 5 - 8 etc.: Count = 0; 2.The objects are created, when a new byte begins: Module 1 creates the Sub - Index 1; modules 2 - 4 fill it up; module 5 creates Sub-Index 2 and so forth. - */ - pat2 = @"\s*([0-9a-fA-F]+)\s*;\s*([0-9a-fA-F]+)"; - r2 = new Regex(pat2, RegexOptions.IgnoreCase); - m2 = r2.Match(kvp.Value["Count"]); - - - - if (m2.Success) - { - Console.WriteLine("** FIXME Count format not supported ** Count: " + kvp.Value["Count"]); - int found = kvp.Value["Count"].IndexOf(";"); - string s = kvp.Value["Count"].Substring(found + 1); - try { od.count = Convert.ToByte(s, Getbase(s)); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } - } - else - { - - try { od.count = Convert.ToByte(kvp.Value["Count"], Getbase(kvp.Value["Count"])); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Count" + kvp.Value["Count"]); } - } - - } - - if (kvp.Value.ContainsKey("ObjExtend")) - { - try { od.ObjExtend = Convert.ToByte(kvp.Value["ObjExtend"]); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** ObjExtend:" + kvp.Value["ObjExtend"]); } - - } - - - if (od.objecttype == ObjectType.VAR) - { - - if (kvp.Value.ContainsKey("CompactSubObj")) - throw new ParameterException("CompactSubObj not valid for a VAR Object, section: " + section); - - if (kvp.Value.ContainsKey("ParameterValue")) - { - - try { od.actualvalue = kvp.Value["ParameterValue"]; } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** ParameterValue:" + kvp.Value["ParameterValue"]); } - } - - if (kvp.Value.ContainsKey("HighLimit")) - { - try { od.HighLimit = kvp.Value["HighLimit"]; } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** HighLimit:" + kvp.Value["HighLimit"]); } - } - - if (kvp.Value.ContainsKey("LowLimit")) - { - try { od.LowLimit = kvp.Value["LowLimit"]; } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** LowLimit:" + kvp.Value["LowLimit"]); } - } - - if (kvp.Value.ContainsKey("Denotation")) - { - try { od.denotation = kvp.Value["Denotation"]; } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG ** Denotation:" + kvp.Value["Denotation"]); } - - - } - - if (m.Groups[5].Length != 0) - { - //FIXME are subindexes in hex always? - UInt16 subindex = Convert.ToUInt16(m.Groups[5].ToString(),16); - od.parent = target[od.Index]; - target[od.Index].subobjects.Add(subindex, od); - } - - if (!kvp.Value.ContainsKey("DataType")) - throw new ParameterException("Missing required field DataType on" + section); - od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); - - if (!kvp.Value.ContainsKey("AccessType")) - throw new ParameterException("Missing required AccessType on" + section); - - string accesstype = kvp.Value["AccessType"].ToLower(); - - if (Enum.IsDefined(typeof(AccessType), accesstype)) - { - od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); - } - else - { - throw new ParameterException("Unknown AccessType on" + section); - } - - if (kvp.Value.ContainsKey("DefaultValue")) - od.defaultvalue = kvp.Value["DefaultValue"]; - - od.PDOtype = PDOMappingType.no; - if (kvp.Value.ContainsKey("PDOMapping")) - { - - bool pdo = Convert.ToInt16(kvp.Value["PDOMapping"],Getbase(kvp.Value["PDOMapping"])) == 1; - if (pdo == true) - od.PDOtype = PDOMappingType.optional; - } - - } - - - if(od.objecttype == ObjectType.RECORD|| od.objecttype == ObjectType.ARRAY || od.objecttype == ObjectType.DEFSTRUCT) - { - - if (od.CompactSubObj != 0) - { - if (!kvp.Value.ContainsKey("DataType")) - throw new ParameterException("Missing required field DataType on" + section); - od.datatype = (DataType)Convert.ToInt16(kvp.Value["DataType"], Getbase(kvp.Value["DataType"])); - - if (!kvp.Value.ContainsKey("AccessType")) - throw new ParameterException("Missing required AccessType on" + section); - string accesstype = kvp.Value["AccessType"]; - if (Enum.IsDefined(typeof(AccessType), accesstype)) - { - od.accesstype = (AccessType)Enum.Parse(typeof(AccessType), accesstype); - } - else - { - throw new ParameterException("Unknown AccessType on" + section); - } - - //now we generate CompactSubObj number of var objects below this parent - - if(od.CompactSubObj>=0xfe) - { - od.CompactSubObj = 0xfe; - } - - ODentry subi = new ODentry("NrOfObjects", od.Index, DataType.UNSIGNED8, String.Format("0x{0:x2}",od.CompactSubObj), AccessType.ro, PDOMappingType.no, od); - od.subobjects.Add(0x00, subi); - - for (int x=1; x<= od.CompactSubObj; x++) - { - string parameter_name = string.Format("{0}{1:x2}", od.parameter_name, x ); - ODentry sub = new ODentry(parameter_name, od.Index, od.datatype, od.defaultvalue, od.accesstype, od.PDOtype, od); - - if (kvp.Value.ContainsKey("HighLimit")) - sub.HighLimit = kvp.Value["HighLimit"]; - - if (kvp.Value.ContainsKey("LowLimit")) - sub.HighLimit = kvp.Value["LowLimit"]; - - od.subobjects.Add((ushort)(x ), sub); - } - - } - else - { - if (!kvp.Value.ContainsKey("SubNumber")) - throw new ParameterException("Missing SubNumber on Array for" + section); - - - - } - } - - if(od.objecttype == ObjectType.DOMAIN) - { - od.datatype = DataType.DOMAIN; - od.accesstype = AccessType.rw; - - if (kvp.Value.ContainsKey("DefaultValue")) - od.defaultvalue = kvp.Value["DefaultValue"]; - - } - - //Only add top level to this list - if (m.Groups[5].Length == 0) - { - target.Add(od.Index, od); - } - } - - } - - public void Loadfile(string filename) - { - - projectFilename = filename; - - if (Path.GetExtension(filename).ToLower() == ".eds") - { - edsfilename = filename; - } - - if (Path.GetExtension(filename).ToLower() == ".dcf") - { - dcffilename = filename; - } - - //try - { - int lineno = 1; - foreach (string linex in System.IO.File.ReadLines(filename)) - { - Parseline(linex,lineno); - lineno++; - } - - di = new DeviceInfo(eds["DeviceInfo"]); - - foreach (KeyValuePair> kvp in eds) - { - - try { ParseEDSentry(kvp); } - catch (Exception) { Console.WriteLine("** ALL GONE WRONG **" + kvp); } - - } - - fi = new FileInfo(eds["FileInfo"]); - if(eds.ContainsKey("DummyUsage")) - du = new Dummyusage(eds["DummyUsage"]); - - md = new MandatoryObjects(eds["MandatoryObjects"]); - - if(eds.ContainsKey("OptionalObjects")) - oo = new OptionalObjects(eds["OptionalObjects"]); - - if(eds.ContainsKey("ManufacturerObjects")) - mo = new ManufacturerObjects(eds["ManufacturerObjects"]); - - if (eds.ContainsKey("TypeDefinitions")) - td = new TypeDefinitions(eds["TypeDefinitions"]); - - //Only DCF not EDS files - dc = new DeviceCommissioning(); - string strSection = ""; - if (eds.ContainsKey("DeviceCommissioning")) // wrong section name as defined in the DSP302, but right spelling (for compabiltiy to some tools) - strSection = "DeviceCommissioning"; - else if (eds.ContainsKey("DeviceComissioning")) // right section name as defined in the DSP302, (wrong spelling) - strSection = "DeviceComissioning"; - - if (strSection != ""){ - dc.Parse(eds[strSection],"DeviceCommissioning"); - edsfilename = fi.LastEDS; - } - - c = new Comments(); - - if (eds.ContainsKey("Comments")) - c.Parse(eds["Comments"]); - - //Modules - - //FIXME - //we don't parse or support [MxFixedObjects] with MxFixedxxxx and MxFixedxxxxsubx - - if (eds.ContainsKey("SupportedModules")) - { - sm = new SupportedModules(eds["SupportedModules"]); - - //find MxModuleInfo - - foreach (string s in eds.Keys) - { - String pat = @"M([0-9]+)ModuleInfo"; - Regex r = new Regex(pat, RegexOptions.IgnoreCase); - Match m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleInfo mi = new ModuleInfo(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mi = mi; - - } - - - pat = @"M([0-9]+)Comments"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleComments mc = new ModuleComments(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mc = mc; - - } - pat = @"M([0-9]+)SubExtends"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - ModuleSubExtends mse = new ModuleSubExtends(eds[s], modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mse = mse; - } - - - //DCF only - - pat = @"M([0-9]+)FixedObjects"; - r = new Regex(pat, RegexOptions.IgnoreCase); - m = r.Match(s); - - if (m.Success) - { - UInt16 modindex = Convert.ToUInt16(m.Groups[1].Value); - MxFixedObjects mxf = new MxFixedObjects(eds[s],modindex); - - if (!modules.ContainsKey(modindex)) - modules.Add(modindex, new Module(modindex)); - - modules[modindex].mxfo = mxf; - - } - } - } - - - if (eds.ContainsKey("ConnectedModules")) - { - cm = new ConnectedModules(eds["ConnectedModules"]); - } - - //COMPACT PDO - - if (di.CompactPDO != 0) - { - - for (UInt16 index = 0x1400; index < 0x1600; index++) - { - ApplycompactPDO(index); - } - - for (UInt16 index = 0x1800; index < 0x1A00;index ++) - { - ApplycompactPDO(index); - } - } - - ApplyimplicitPDO(); - } - // catch(Exception e) - //{ - // Console.WriteLine("** ALL GONE WRONG **" + e.ToString()); - // } - } - - public void ApplycompactPDO(UInt16 index) - { - if (ods.ContainsKey(index)) - { - if ((!ods[index].Containssubindex(1)) && ((this.di.CompactPDO & 0x01) == 0)) - { - //Fill in cob ID - //FIX ME i'm really sure this is not correct, what default values should be used??? - string cob = string.Format("$NODEID + 0x180"); - ODentry subod = new ODentry("COB-ID", index, DataType.UNSIGNED32, cob, AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x05, subod); - - } - - if ((!ods[index].Containssubindex(2)) && ((this.di.CompactPDO & 0x02) == 0)) - { - //Fill in type - - ODentry subod = new ODentry("Type", index, DataType.UNSIGNED8, "0xff", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x02, subod); - } - - if ((!ods[index].Containssubindex(3)) && ((this.di.CompactPDO & 0x04) == 0)) - { - //Fill in inhibit - - ODentry subod = new ODentry("Inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x03, subod); - } - - //NOT FOR RX PDO - if (index < 0x1800) - return; - - if ((!ods[index].Containssubindex(4)) && ((this.di.CompactPDO & 0x08) == 0)) - { - //Fill in compatibility entry - - ODentry subod = new ODentry("Compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x04, subod); - } - - if ((!ods[index].Containssubindex(5)) && ((this.di.CompactPDO & 0x10) == 0)) - { - //Fill in event timer - - ODentry subod = new ODentry("Event Timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, ods[index]); - ods[index].subobjects.Add(0x05, subod); - } - } - } - - /// - /// This function scans the PDO list and compares it to NrOfRXPDO and NrOfTXPDO - /// if these do not match in count then implicit PDOs are present and they are - /// filled in with default values from the lowest possible index - /// - public void ApplyimplicitPDO() - { - UInt16 totalnorxpdos = di.NrOfRXPDO; - UInt16 totalnotxpdos = di.NrOfTXPDO; - - UpdatePDOcount(); - - UInt16 noexplicitrxpdos = di.NrOfRXPDO; - UInt16 noexplicittxpdos = di.NrOfTXPDO; - - //this is how many PDOS need generating on the fly - UInt16 noimplictrxpdos = (UInt16) (totalnorxpdos - noexplicitrxpdos); - UInt16 noimplicttxpdos = (UInt16) (totalnotxpdos - noexplicittxpdos); - - for(UInt16 index = 0x1400; (index < 0x1600) && (noimplictrxpdos > 0) ;index++) - { - if(!ods.ContainsKey(index)) - { - CreateRXPDO(index); - noimplictrxpdos--; - } - } - - for (UInt16 index = 0x1800; (index < 0x1A00) && (noimplicttxpdos > 0); index++) - { - if (!ods.ContainsKey(index)) - { - CreateTXPDO(index); - noimplicttxpdos--; - } - } - - UpdatePDOcount(); - - } - - public void Savefile(string filename, InfoSection.Filetype ft) - { - if(ft==InfoSection.Filetype.File_EDS) - this.edsfilename = filename; - - if (ft == InfoSection.Filetype.File_DCF) - { - this.dcffilename = filename; - fi.LastEDS = edsfilename; - } - - UpdatePDOcount(); - - //generate date times in DS306 format; h:mmtt MM-dd-yyyy - - fi.CreationDate = fi.CreationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); - fi.CreationTime = fi.CreationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); - - fi.ModificationDate = fi.ModificationDateTime.ToString("MM-dd-yyyy", CultureInfo.InvariantCulture); - fi.ModificationTime = fi.ModificationDateTime.ToString("h:mmtt", CultureInfo.InvariantCulture); - - fi.FileName = Path.GetFileName(filename); - - fi.EDSVersion = "4.0"; - fi.EDSVersionMajor = 4; - fi.EDSVersionMinor = 0; - - StreamWriter writer = System.IO.File.CreateText(filename); - writer.NewLine = "\n"; - fi.Write(writer,ft); - di.Write(writer,ft); - du.Write(writer,ft); - c.Write(writer); - - if(ft == InfoSection.Filetype.File_DCF) - { - dc.Write(writer,ft); - } - - //regenerate the object lists - md.objectlist.Clear(); - mo.objectlist.Clear(); - oo.objectlist.Clear(); - - foreach (KeyValuePair kvp in ods) - { - ODentry entry = kvp.Value; - - if (entry.prop.CO_disabled == true) - continue; - - if (entry.Index == 0x1000 || entry.Index == 0x1001 || entry.Index == 0x1018) - { - md.objectlist.Add(md.objectlist.Count + 1, entry.Index); - } - else - if (entry.Index >= 0x2000 && entry.Index < 0x6000) - { - mo.objectlist.Add(mo.objectlist.Count + 1, entry.Index); - } - else - { - oo.objectlist.Add(oo.objectlist.Count + 1, entry.Index); - } - } - - md.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (md.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - oo.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (oo.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - mo.Write(writer); - - foreach (KeyValuePair kvp in ods) - { - ODentry od = kvp.Value; - if (mo.objectlist.ContainsValue(od.Index)) - { - od.Write(writer,ft); - foreach (KeyValuePair kvp2 in od.subobjects) - { - ODentry od2 = kvp2.Value; - od2.Write(writer,ft); - } - } - } - - //modules - - if (sm.NrOfEntries > 0) - { - sm.Write(writer, ft); - - for (UInt16 moduleid = 1; moduleid <= sm.NrOfEntries; moduleid++) - { - - modules[moduleid].mi.Write(writer, ft); - - modules[moduleid].mc.Write(writer); - - modules[moduleid].mse.Write(writer); - - - foreach (KeyValuePair kvp2 in modules[moduleid].modulesubext) - { - ODentry od = kvp2.Value; - od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); - - } - - modules[moduleid].mxfo.Write(writer); - - foreach (KeyValuePair kvp3 in modules[moduleid].modulefixedobjects) - { - ODentry od = kvp3.Value; - od.Write(writer, ft, ODentry.Odtype.SUBEXT, moduleid); - - foreach (KeyValuePair kvp4 in od.subobjects) - { - ODentry subod = kvp4.Value; - subod.Write(writer, ft, ODentry.Odtype.FIXED, moduleid); - } - } - } - } - - if (ft == InfoSection.Filetype.File_DCF) - { - if (cm.NrOfEntries > 0) - { - cm.Write(writer); - } - } - - writer.Close(); - - } - - public DataType Getdatatype(ODentry od) - { - - if (od.objecttype == ObjectType.VAR) - { - return od.datatype; - } - - if (od.objecttype == ObjectType.ARRAY) - { - ODentry sub2 = ods[od.Index]; - - //FIX ME !!! INCONSISTANT setup of the datatype for arrays when loading xml and eds!! + //FIX ME !!! INCONSISTANT setup of the datatype for arrays when loading xml and eds!! DataType t = sub2.datatype; @@ -3304,178 +2091,6 @@ public bool tryGetODEntry(UInt16 index, out ODentry od) return false; } - //RX COM 0x1400 - //RX Map 0x1600 - //TX COM 0x1800 - //TX MAP 0x1a00 - - //call this with the comm param index not the mapping - public bool CreatePDO(bool rx,UInt16 index) - { - //check if we are creating an RX PDO it is a valid index - if (rx && (index < 0x1400 || index >= 0x1600)) - return false; - - //check if we are creating an PDO TX it is a valid index - if (!rx & (index < 0x1800 || index >= 0x1A00)) - return false; - - //Check it does not already exist - if (ods.ContainsKey(index)) - return false; - - //check the associated mapping index does not exist - if (ods.ContainsKey((UInt16)(index+0x200))) - return false; - - ODentry od_comparam; - ODentry od_mapping; - - if (rx) - { - od_comparam = new ODentry("RPDO communication parameter", index, 0) - { - Description = @"0x1400 - 0x15FF RPDO communication parameter -max sub-index - -COB - ID - bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set - bit 11 - 29: set to 0 for 11 bit COB - ID - bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO - bit 31: 0(1) - node uses(does NOT use) PDO - -Transmission type - value = 0 - 240: receiving is synchronous, process after next reception of SYNC object - value = 241 - 253: not used - value = 254: manufacturer specific - value = 255: asynchronous" - }; - - od_mapping = new ODentry("RPDO mapping parameter", (UInt16)(index + 0x200), 0) - { - Description = @"0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) -Number of mapped objects - -mapped object (subindex 1...8) - bit 0 - 7: data length in bits - bit 8 - 15: subindex from OD - bit 16 - 31: index from OD" - }; - - - } - else - { - od_comparam = new ODentry("TPDO communication parameter", index, 0) - { - Description = @"0x1800 - 0x19FF TPDO communication parameter -max sub-index - -COB - ID - bit 0 - 10: COB - ID for PDO, to change it bit 31 must be set - bit 11 - 29: set to 0 for 11 bit COB - ID - bit 30: 0(1) - rtr are allowed(are NOT allowed) for PDO - bit 31: 0(1) - node uses(does NOT use) PDO - -Transmission type - value = 0: transmitting is synchronous, specification in device profile - value = 1 - 240: transmitting is synchronous after every N - th SYNC object - value = 241 - 251: not used - value = 252 - 253: Transmitted only on reception of Remote Transmission Request - value = 254: manufacturer specific - value = 255: asynchronous, specification in device profile - -inhibit time - bit 0 - 15: Minimum time between transmissions of the PDO in 100µs.Zero disables functionality. - -event timer - bit 0-15: Time between periodic transmissions of the PDO in ms.Zero disables functionality. - -SYNC start value - value = 0: Counter of the SYNC message shall not be processed. - value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message." - }; - - - od_mapping = new ODentry("TPDO mapping parameter", (UInt16)(index + 0x200), 0) - { - Description = @"0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). -Number of mapped objects - -mapped object (subindex 1...8) - bit 0 - 7: data length in bits - bit 8 - 15: subindex from OD - bit 16 - 31: index from OD" - }; - } - - od_comparam.objecttype = ObjectType.RECORD; - od_comparam.prop.CO_storageGroup = "ROM"; - od_comparam.accesstype = AccessType.ro; - od_comparam.PDOtype = PDOMappingType.no; - - ODentry sub; - - - if(rx) - { - sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "2", AccessType.ro, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(0, sub); - sub = new ODentry("COB-ID used by RPDO", index, DataType.UNSIGNED32, "$NODEID+0x200", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(1, sub); - sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(2, sub); - - } - else - { - sub = new ODentry("max sub-index", index, DataType.UNSIGNED8, "6", AccessType.ro, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(0, sub); - sub = new ODentry("COB-ID used by TPDO", index, DataType.UNSIGNED32, "$NODEID+0x180", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(1, sub); - sub = new ODentry("transmission type", index, DataType.UNSIGNED8, "254", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(2, sub); - sub = new ODentry("inhibit time", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(3, sub); - //sub = new ODentry("compatibility entry", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); - //od_comparam.subobjects.Add(4, sub); - sub = new ODentry("event timer", index, DataType.UNSIGNED16, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(5, sub); - sub = new ODentry("SYNC start value", index, DataType.UNSIGNED8, "0", AccessType.rw, PDOMappingType.no, od_comparam); - od_comparam.subobjects.Add(6, sub); - - } - - od_mapping.objecttype = ObjectType.RECORD; - od_mapping.prop.CO_storageGroup = "ROM"; - od_mapping.accesstype = AccessType.rw; //Same as default but inconsistent with ROM above - od_mapping.PDOtype = PDOMappingType.no; - - sub = new ODentry("Number of mapped objects", (UInt16)(index + 0x200), DataType.UNSIGNED8, "0", AccessType.ro, PDOMappingType.no, od_mapping); - od_mapping.subobjects.Add(0, sub); - - for (int p=1;p<=8;p++) - { - sub = new ODentry(string.Format("mapped object {0}",p), (UInt16)(index+0x200), DataType.UNSIGNED32, "0x00000000", AccessType.ro, PDOMappingType.no, od_mapping); - od_mapping.subobjects.Add((byte)p, sub); - } - - ods.Add(index, od_comparam); - ods.Add((UInt16)(index + 0x200), od_mapping); - - return true; - } - - public bool CreateTXPDO(UInt16 index) - { - return CreatePDO(false, index); - } - - public bool CreateRXPDO(UInt16 index) - { - return CreatePDO(true, index); - } - public ODentry Getobject(UInt16 no) { From 39ad96c72946789ce36c961aa164b992b38cb22e Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Thu, 11 Apr 2024 21:47:50 +0200 Subject: [PATCH 142/226] move the generated code from openxddv1.0 to its own file as it is done with v1.1 (#107) --- libEDSsharp/CanOpenXDD.cs | 9383 +-------------------------------- libEDSsharp/CanOpenXSD_1_0.cs | 9376 ++++++++++++++++++++++++++++++++ 2 files changed, 9377 insertions(+), 9382 deletions(-) create mode 100644 libEDSsharp/CanOpenXSD_1_0.cs diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 616b534f..22e85d9e 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -1,4 +1,4 @@ -/* +/* This file is part of libEDSsharp. libEDSsharp is free software: you can redistribute it and/or modify @@ -1302,9384 +1302,3 @@ public class OpenEDSProject public string Version { get; set; } } - - -namespace CanOpenXSD_1_0 -{ - - //------------------------------------------------------------------------------ - // - // This code was generated by a tool. - // Runtime Version:4.0.30319.42000 - // - // Changes to this file may cause incorrect behavior and will be lost if - // the code is regenerated. - // - //------------------------------------------------------------------------------ - - using System.Xml.Serialization; - - // - // This source code was auto-generated by xsd, Version=4.6.1055.0. - // - - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class ISO15745ProfileContainer - { - - private ISO15745Profile[] iSO15745ProfileField; - - /// - [System.Xml.Serialization.XmlElementAttribute("ISO15745Profile")] - public ISO15745Profile[] ISO15745Profile - { - get - { - return this.iSO15745ProfileField; - } - set - { - this.iSO15745ProfileField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class ISO15745Profile - { - - private ProfileHeader_DataType profileHeaderField; - - private ProfileBody_DataType profileBodyField; - - /// - public ProfileHeader_DataType ProfileHeader - { - get - { - return this.profileHeaderField; - } - set - { - this.profileHeaderField = value; - } - } - - /// - public ProfileBody_DataType ProfileBody - { - get - { - return this.profileBodyField; - } - set - { - this.profileBodyField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileHeader_DataType - { - - private string profileIdentificationField; - - private string profileRevisionField; - - private string profileNameField; - - private string profileSourceField; - - private ProfileClassID_DataType profileClassIDField; - - private System.DateTime profileDateField; - - private bool profileDateFieldSpecified; - - private string additionalInformationField; - - private ISO15745Reference_DataType iSO15745ReferenceField; - - private string[] iASInterfaceTypeField; - - /// - public string ProfileIdentification - { - get - { - return this.profileIdentificationField; - } - set - { - this.profileIdentificationField = value; - } - } - - /// - public string ProfileRevision - { - get - { - return this.profileRevisionField; - } - set - { - this.profileRevisionField = value; - } - } - - /// - public string ProfileName - { - get - { - return this.profileNameField; - } - set - { - this.profileNameField = value; - } - } - - /// - public string ProfileSource - { - get - { - return this.profileSourceField; - } - set - { - this.profileSourceField = value; - } - } - - /// - public ProfileClassID_DataType ProfileClassID - { - get - { - return this.profileClassIDField; - } - set - { - this.profileClassIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] - public System.DateTime ProfileDate - { - get - { - return this.profileDateField; - } - set - { - this.profileDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool ProfileDateSpecified - { - get - { - return this.profileDateFieldSpecified; - } - set - { - this.profileDateFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(DataType = "anyURI")] - public string AdditionalInformation - { - get - { - return this.additionalInformationField; - } - set - { - this.additionalInformationField = value; - } - } - - /// - public ISO15745Reference_DataType ISO15745Reference - { - get - { - return this.iSO15745ReferenceField; - } - set - { - this.iSO15745ReferenceField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("IASInterfaceType")] - public string[] IASInterfaceType - { - get - { - return this.iASInterfaceTypeField; - } - set - { - this.iASInterfaceTypeField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] - public enum ProfileClassID_DataType - { - - /// - AIP, - - /// - Process, - - /// - InformationExchange, - - /// - Resource, - - /// - Device, - - /// - CommunicationNetwork, - - /// - Equipment, - - /// - Human, - - /// - Material, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ISO15745Reference_DataType - { - - private string iSO15745PartField; - - private string iSO15745EditionField; - - private string profileTechnologyField; - - /// - [System.Xml.Serialization.XmlElementAttribute(DataType = "positiveInteger")] - public string ISO15745Part - { - get - { - return this.iSO15745PartField; - } - set - { - this.iSO15745PartField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(DataType = "positiveInteger")] - public string ISO15745Edition - { - get - { - return this.iSO15745EditionField; - } - set - { - this.iSO15745EditionField = value; - } - } - - /// - public string ProfileTechnology - { - get - { - return this.profileTechnologyField; - } - set - { - this.profileTechnologyField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileHandle_DataType - { - - private string profileIdentificationField; - - private string profileRevisionField; - - private string profileLocationField; - - /// - public string ProfileIdentification - { - get - { - return this.profileIdentificationField; - } - set - { - this.profileIdentificationField = value; - } - } - - /// - public string ProfileRevision - { - get - { - return this.profileRevisionField; - } - set - { - this.profileRevisionField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(DataType = "anyURI")] - public string ProfileLocation - { - get - { - return this.profileLocationField; - } - set - { - this.profileLocationField = value; - } - } - } - - /// - [System.Xml.Serialization.XmlIncludeAttribute(typeof(ProfileBody_CommunicationNetwork_CANopen))] - [System.Xml.Serialization.XmlIncludeAttribute(typeof(ProfileBody_Device_CANopen))] - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] - public abstract partial class ProfileBody_DataType - { - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopen : ProfileBody_DataType - { - - private object[] itemsField; - - private string formatNameField; - - private string formatVersionField; - - private string fileNameField; - - private string fileCreatorField; - - private System.DateTime fileCreationDateField; - - private System.DateTime fileCreationTimeField; - - private bool fileCreationTimeFieldSpecified; - - private System.DateTime fileModificationDateField; - - private bool fileModificationDateFieldSpecified; - - private System.DateTime fileModificationTimeField; - - private bool fileModificationTimeFieldSpecified; - - private string fileModifiedByField; - - private string fileVersionField; - - private string supportedLanguagesField; - - public ProfileBody_CommunicationNetwork_CANopen() - { - this.formatNameField = "CANopen"; - this.formatVersionField = "1.0"; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("ApplicationLayers", typeof(ProfileBody_CommunicationNetwork_CANopenApplicationLayers))] - [System.Xml.Serialization.XmlElementAttribute("ExternalProfileHandle", typeof(ProfileHandle_DataType))] - [System.Xml.Serialization.XmlElementAttribute("NetworkManagement", typeof(ProfileBody_CommunicationNetwork_CANopenNetworkManagement))] - [System.Xml.Serialization.XmlElementAttribute("TransportLayers", typeof(ProfileBody_CommunicationNetwork_CANopenTransportLayers))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string formatName - { - get - { - return this.formatNameField; - } - set - { - this.formatNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string formatVersion - { - get - { - return this.formatVersionField; - } - set - { - this.formatVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileName - { - get - { - return this.fileNameField; - } - set - { - this.fileNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileCreator - { - get - { - return this.fileCreatorField; - } - set - { - this.fileCreatorField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] - public System.DateTime fileCreationDate - { - get - { - return this.fileCreationDateField; - } - set - { - this.fileCreationDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] - public System.DateTime fileCreationTime - { - get - { - return this.fileCreationTimeField; - } - set - { - this.fileCreationTimeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool fileCreationTimeSpecified - { - get - { - return this.fileCreationTimeFieldSpecified; - } - set - { - this.fileCreationTimeFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] - public System.DateTime fileModificationDate - { - get - { - return this.fileModificationDateField; - } - set - { - this.fileModificationDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool fileModificationDateSpecified - { - get - { - return this.fileModificationDateFieldSpecified; - } - set - { - this.fileModificationDateFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] - public System.DateTime fileModificationTime - { - get - { - return this.fileModificationTimeField; - } - set - { - this.fileModificationTimeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool fileModificationTimeSpecified - { - get - { - return this.fileModificationTimeFieldSpecified; - } - set - { - this.fileModificationTimeFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileModifiedBy - { - get - { - return this.fileModifiedByField; - } - set - { - this.fileModifiedByField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileVersion - { - get - { - return this.fileVersionField; - } - set - { - this.fileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] - public string supportedLanguages - { - get - { - return this.supportedLanguagesField; - } - set - { - this.supportedLanguagesField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayers - { - - private ProfileBody_CommunicationNetwork_CANopenApplicationLayersIdentity identityField; - - private CANopenObjectList cANopenObjectListField; - - private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy[] dummyUsageField; - - private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannel[] dynamicChannelsField; - - private string conformanceClassField; - - private string communicationEntityTypeField; - - public ProfileBody_CommunicationNetwork_CANopenApplicationLayers() - { - this.communicationEntityTypeField = "slave"; - } - - /// - public ProfileBody_CommunicationNetwork_CANopenApplicationLayersIdentity identity - { - get - { - return this.identityField; - } - set - { - this.identityField = value; - } - } - - /// - public CANopenObjectList CANopenObjectList - { - get - { - return this.cANopenObjectListField; - } - set - { - this.cANopenObjectListField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("dummy", IsNullable = false)] - public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy[] dummyUsage - { - get - { - return this.dummyUsageField; - } - set - { - this.dummyUsageField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("dynamicChannel", IsNullable = false)] - public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannel[] dynamicChannels - { - get - { - return this.dynamicChannelsField; - } - set - { - this.dynamicChannelsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string conformanceClass - { - get - { - return this.conformanceClassField; - } - set - { - this.conformanceClassField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] - [System.ComponentModel.DefaultValueAttribute("slave")] - public string communicationEntityType - { - get - { - return this.communicationEntityTypeField; - } - set - { - this.communicationEntityTypeField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayersIdentity - { - - private vendorID vendorIDField; - - private deviceFamily deviceFamilyField; - - private productID productIDField; - - private version[] versionField; - - private System.DateTime buildDateField; - - private bool buildDateFieldSpecified; - - private specificationRevision specificationRevisionField; - - /// - public vendorID vendorID - { - get - { - return this.vendorIDField; - } - set - { - this.vendorIDField = value; - } - } - - /// - public deviceFamily deviceFamily - { - get - { - return this.deviceFamilyField; - } - set - { - this.deviceFamilyField = value; - } - } - - /// - public productID productID - { - get - { - return this.productIDField; - } - set - { - this.productIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("version")] - public version[] version - { - get - { - return this.versionField; - } - set - { - this.versionField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] - public System.DateTime buildDate - { - get - { - return this.buildDateField; - } - set - { - this.buildDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool buildDateSpecified - { - get - { - return this.buildDateFieldSpecified; - } - set - { - this.buildDateFieldSpecified = value; - } - } - - /// - public specificationRevision specificationRevision - { - get - { - return this.specificationRevisionField; - } - set - { - this.specificationRevisionField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class vendorID - { - - private bool readOnlyField; - - private string valueField; - - public vendorID() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class deviceFamily - { - - private object[] itemsField; - - private bool readOnlyField; - - public deviceFamily() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class vendorTextDescription - { - - private string langField; - - private string uRIField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "language")] - public string lang - { - get - { - return this.langField; - } - set - { - this.langField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] - public string URI - { - get - { - return this.uRIField; - } - set - { - this.uRIField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class vendorTextDescriptionRef - { - - private string dictIDField; - - private string textIDField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string dictID - { - get - { - return this.dictIDField; - } - set - { - this.dictIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string textID - { - get - { - return this.textIDField; - } - set - { - this.textIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute(DataType = "anyURI")] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class vendorTextLabel - { - - private string langField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "language")] - public string lang - { - get - { - return this.langField; - } - set - { - this.langField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class vendorTextLabelRef - { - - private string dictIDField; - - private string textIDField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string dictID - { - get - { - return this.dictIDField; - } - set - { - this.dictIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string textID - { - get - { - return this.textIDField; - } - set - { - this.textIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute(DataType = "anyURI")] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class productID - { - - private bool readOnlyField; - - private string valueField; - - public productID() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class version - { - - private versionVersionType versionTypeField; - - private bool readOnlyField; - - private string valueField; - - public version() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public versionVersionType versionType - { - get - { - return this.versionTypeField; - } - set - { - this.versionTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum versionVersionType - { - - /// - SW, - - /// - FW, - - /// - HW, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class specificationRevision - { - - private bool readOnlyField; - - private string valueField; - - public specificationRevision() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class CANopenObjectList - { - - private CANopenObjectListCANopenObject[] cANopenObjectField; - - private uint mandatoryObjectsField; - - private bool mandatoryObjectsFieldSpecified; - - private uint optionalObjectsField; - - private bool optionalObjectsFieldSpecified; - - private uint manufacturerObjectsField; - - private bool manufacturerObjectsFieldSpecified; - - /// - [System.Xml.Serialization.XmlElementAttribute("CANopenObject")] - public CANopenObjectListCANopenObject[] CANopenObject - { - get - { - return this.cANopenObjectField; - } - set - { - this.cANopenObjectField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public uint mandatoryObjects - { - get - { - return this.mandatoryObjectsField; - } - set - { - this.mandatoryObjectsField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool mandatoryObjectsSpecified - { - get - { - return this.mandatoryObjectsFieldSpecified; - } - set - { - this.mandatoryObjectsFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public uint optionalObjects - { - get - { - return this.optionalObjectsField; - } - set - { - this.optionalObjectsField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool optionalObjectsSpecified - { - get - { - return this.optionalObjectsFieldSpecified; - } - set - { - this.optionalObjectsFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public uint manufacturerObjects - { - get - { - return this.manufacturerObjectsField; - } - set - { - this.manufacturerObjectsField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool manufacturerObjectsSpecified - { - get - { - return this.manufacturerObjectsFieldSpecified; - } - set - { - this.manufacturerObjectsFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class CANopenObjectListCANopenObject - { - - private CANopenObjectListCANopenObjectCANopenSubObject[] cANopenSubObjectField; - - private byte[] indexField; - - private string nameField; - - private byte objectTypeField; - - private byte[] dataTypeField; - - private string lowLimitField; - - private string highLimitField; - - private CANopenObjectListCANopenObjectAccessType accessTypeField; - - private bool accessTypeFieldSpecified; - - private string defaultValueField; - - private string actualValueField; - - private string denotationField; - - private string edseditor_extension_storagelocationField; - - private bool edseditor_extension_notifyonchangeField; - - private CANopenObjectListCANopenObjectPDOmapping pDOmappingField; - - private bool pDOmappingFieldSpecified; - - private byte[] objFlagsField; - - private string uniqueIDRefField; - - private byte subNumberField; - - private bool subNumberFieldSpecified; - - /// - [System.Xml.Serialization.XmlElementAttribute("CANopenSubObject")] - public CANopenObjectListCANopenObjectCANopenSubObject[] CANopenSubObject - { - get - { - return this.cANopenSubObjectField; - } - set - { - this.cANopenSubObjectField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] index - { - get - { - return this.indexField; - } - set - { - this.indexField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public byte objectType - { - get - { - return this.objectTypeField; - } - set - { - this.objectTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] dataType - { - get - { - return this.dataTypeField; - } - set - { - this.dataTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string lowLimit - { - get - { - return this.lowLimitField; - } - set - { - this.lowLimitField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string highLimit - { - get - { - return this.highLimitField; - } - set - { - this.highLimitField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public CANopenObjectListCANopenObjectAccessType accessType - { - get - { - return this.accessTypeField; - } - set - { - this.accessTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool accessTypeSpecified - { - get - { - return this.accessTypeFieldSpecified; - } - set - { - this.accessTypeFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string defaultValue - { - get - { - return this.defaultValueField; - } - set - { - this.defaultValueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string actualValue - { - get - { - return this.actualValueField; - } - set - { - this.actualValueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string denotation - { - get - { - return this.denotationField; - } - set - { - this.denotationField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string edseditor_extenstion_storagelocation - { - get - { - return this.edseditor_extension_storagelocationField; - } - set - { - this.edseditor_extension_storagelocationField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool edseditor_extension_notifyonchange - { - get - { - return this.edseditor_extension_notifyonchangeField; - } - set - { - this.edseditor_extension_notifyonchangeField = value; - } - } - - - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public CANopenObjectListCANopenObjectPDOmapping PDOmapping - { - get - { - return this.pDOmappingField; - } - set - { - this.pDOmappingField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool PDOmappingSpecified - { - get - { - return this.pDOmappingFieldSpecified; - } - set - { - this.pDOmappingFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] objFlags - { - get - { - return this.objFlagsField; - } - set - { - this.objFlagsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string uniqueIDRef - { - get - { - return this.uniqueIDRefField; - } - set - { - this.uniqueIDRefField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public byte subNumber - { - get - { - return this.subNumberField; - } - set - { - this.subNumberField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool subNumberSpecified - { - get - { - return this.subNumberFieldSpecified; - } - set - { - this.subNumberFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class CANopenObjectListCANopenObjectCANopenSubObject - { - - private byte[] subIndexField; - - private string nameField; - - private byte objectTypeField; - - private byte[] dataTypeField; - - private string lowLimitField; - - private string highLimitField; - - private CANopenObjectListCANopenObjectCANopenSubObjectAccessType accessTypeField; - - private bool accessTypeFieldSpecified; - - private string defaultValueField; - - private string actualValueField; - - private string denotationField; - - private CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping pDOmappingField; - - private bool pDOmappingFieldSpecified; - - private byte[] objFlagsField; - - private string uniqueIDRefField; - - private bool edseditor_extension_notifyonchangeField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool edseditor_extension_notifyonchange - { - get - { - return this.edseditor_extension_notifyonchangeField; - } - set - { - this.edseditor_extension_notifyonchangeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] subIndex - { - get - { - return this.subIndexField; - } - set - { - this.subIndexField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public byte objectType - { - get - { - return this.objectTypeField; - } - set - { - this.objectTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] dataType - { - get - { - return this.dataTypeField; - } - set - { - this.dataTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string lowLimit - { - get - { - return this.lowLimitField; - } - set - { - this.lowLimitField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string highLimit - { - get - { - return this.highLimitField; - } - set - { - this.highLimitField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public CANopenObjectListCANopenObjectCANopenSubObjectAccessType accessType - { - get - { - return this.accessTypeField; - } - set - { - this.accessTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool accessTypeSpecified - { - get - { - return this.accessTypeFieldSpecified; - } - set - { - this.accessTypeFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string defaultValue - { - get - { - return this.defaultValueField; - } - set - { - this.defaultValueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string actualValue - { - get - { - return this.actualValueField; - } - set - { - this.actualValueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string denotation - { - get - { - return this.denotationField; - } - set - { - this.denotationField = value; - } - } - - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping PDOmapping - { - get - { - return this.pDOmappingField; - } - set - { - this.pDOmappingField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool PDOmappingSpecified - { - get - { - return this.pDOmappingFieldSpecified; - } - set - { - this.pDOmappingFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] objFlags - { - get - { - return this.objFlagsField; - } - set - { - this.objFlagsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string uniqueIDRef - { - get - { - return this.uniqueIDRefField; - } - set - { - this.uniqueIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum CANopenObjectListCANopenObjectCANopenSubObjectAccessType - { - - /// - ro, - - /// - wo, - - /// - rw, - - /// - @const, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping - { - - /// - no, - - /// - @default, - - /// - optional, - - /// - TPDO, - - /// - RPDO, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum CANopenObjectListCANopenObjectAccessType - { - - /// - ro, - - /// - wo, - - /// - rw, - - /// - @const, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum CANopenObjectListCANopenObjectPDOmapping - { - - /// - no, - - /// - @default, - - /// - optional, - - /// - TPDO, - - /// - RPDO, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy - { - - private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry entryField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry entry - { - get - { - return this.entryField; - } - set - { - this.entryField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry - { - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0001=0")] - Dummy00010, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0002=0")] - Dummy00020, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0003=0")] - Dummy00030, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0004=0")] - Dummy00040, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0005=0")] - Dummy00050, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0006=0")] - Dummy00060, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0007=0")] - Dummy00070, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0001=1")] - Dummy00011, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0002=1")] - Dummy00021, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0003=1")] - Dummy00031, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0004=1")] - Dummy00041, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0005=1")] - Dummy00051, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0006=1")] - Dummy00061, - - /// - [System.Xml.Serialization.XmlEnumAttribute("Dummy0007=1")] - Dummy00071, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannel - { - - private byte[] dataTypeField; - - private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannelAccessType accessTypeField; - - private byte[] startIndexField; - - private byte[] endIndexField; - - private uint maxNumberField; - - private byte[] addressOffsetField; - - private byte bitAlignmentField; - - private bool bitAlignmentFieldSpecified; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] dataType - { - get - { - return this.dataTypeField; - } - set - { - this.dataTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannelAccessType accessType - { - get - { - return this.accessTypeField; - } - set - { - this.accessTypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] startIndex - { - get - { - return this.startIndexField; - } - set - { - this.startIndexField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] endIndex - { - get - { - return this.endIndexField; - } - set - { - this.endIndexField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public uint maxNumber - { - get - { - return this.maxNumberField; - } - set - { - this.maxNumberField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] - public byte[] addressOffset - { - get - { - return this.addressOffsetField; - } - set - { - this.addressOffsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public byte bitAlignment - { - get - { - return this.bitAlignmentField; - } - set - { - this.bitAlignmentField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool bitAlignmentSpecified - { - get - { - return this.bitAlignmentFieldSpecified; - } - set - { - this.bitAlignmentFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannelAccessType - { - - /// - readOnly, - - /// - writeOnly, - - /// - readWriteOutput, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagement - { - - private ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures cANopenGeneralFeaturesField; - - private ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures cANopenMasterFeaturesField; - - private ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning deviceCommissioningField; - - /// - public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures CANopenGeneralFeatures - { - get - { - return this.cANopenGeneralFeaturesField; - } - set - { - this.cANopenGeneralFeaturesField = value; - } - } - - /// - public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures CANopenMasterFeatures - { - get - { - return this.cANopenMasterFeaturesField; - } - set - { - this.cANopenMasterFeaturesField = value; - } - } - - /// - public ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning deviceCommissioning - { - get - { - return this.deviceCommissioningField; - } - set - { - this.deviceCommissioningField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures - { - - private bool groupMessagingField; - - private byte dynamicChannelsField; - - private bool selfStartingDeviceField; - - private bool sDORequestingDeviceField; - - private byte granularityField; - - private ushort nrOfRxPDOField; - - private ushort nrOfTxPDOField; - - private bool ngMasterField; - private bool ngSlaveField; - private ushort NrOfNG_MonitoredNodesField; - private bool bootUpSlaveField; - - private bool layerSettingServiceSlaveField; - - public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures() - { - this.groupMessagingField = false; - this.dynamicChannelsField = ((byte)(0)); - this.selfStartingDeviceField = false; - this.sDORequestingDeviceField = false; - this.nrOfRxPDOField = ((ushort)(0)); - this.nrOfTxPDOField = ((ushort)(0)); - this.ngMasterField = false; - this.ngSlaveField = false; - this.NrOfNG_MonitoredNodesField = ((ushort)(0)); - this.bootUpSlaveField = false; - this.layerSettingServiceSlaveField = false; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool groupMessaging - { - get - { - return this.groupMessagingField; - } - set - { - this.groupMessagingField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(typeof(byte), "0")] - public byte dynamicChannels - { - get - { - return this.dynamicChannelsField; - } - set - { - this.dynamicChannelsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool selfStartingDevice - { - get - { - return this.selfStartingDeviceField; - } - set - { - this.selfStartingDeviceField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool SDORequestingDevice - { - get - { - return this.sDORequestingDeviceField; - } - set - { - this.sDORequestingDeviceField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public byte granularity - { - get - { - return this.granularityField; - } - set - { - this.granularityField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] - public ushort nrOfRxPDO - { - get - { - return this.nrOfRxPDOField; - } - set - { - this.nrOfRxPDOField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] - public ushort nrOfTxPDO - { - get - { - return this.nrOfTxPDOField; - } - set - { - this.nrOfTxPDOField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool bootUpSlave - { - get - { - return this.bootUpSlaveField; - } - set - { - this.bootUpSlaveField = value; - } - } - - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool ngSlave - { - get - { - return this.ngSlaveField; - } - set - { - this.ngSlaveField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool ngMaster - { - get - { - return this.ngMasterField; - } - set - { - this.ngMasterField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] - public ushort NrOfNG_MonitoredNodes - { - get - { - return this.NrOfNG_MonitoredNodesField; - } - set - { - this.NrOfNG_MonitoredNodesField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool layerSettingServiceSlave - { - get - { - return this.layerSettingServiceSlaveField; - } - set - { - this.layerSettingServiceSlaveField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures - { - - private bool bootUpMasterField; - - private bool flyingMasterField; - - private bool sDOManagerField; - - private bool configurationManagerField; - - private bool layerSettingServiceMasterField; - - public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures() - { - this.bootUpMasterField = false; - this.flyingMasterField = false; - this.sDOManagerField = false; - this.configurationManagerField = false; - this.layerSettingServiceMasterField = false; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool bootUpMaster - { - get - { - return this.bootUpMasterField; - } - set - { - this.bootUpMasterField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool flyingMaster - { - get - { - return this.flyingMasterField; - } - set - { - this.flyingMasterField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool SDOManager - { - get - { - return this.sDOManagerField; - } - set - { - this.sDOManagerField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool configurationManager - { - get - { - return this.configurationManagerField; - } - set - { - this.configurationManagerField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool layerSettingServiceMaster - { - get - { - return this.layerSettingServiceMasterField; - } - set - { - this.layerSettingServiceMasterField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning - { - - private byte nodeIDField; - - private string nodeNameField; - - private string actualBaudRateField; - - private ulong networkNumberField; - - private string networkNameField; - - private bool cANopenManagerField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public byte NodeID - { - get - { - return this.nodeIDField; - } - set - { - this.nodeIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string nodeName - { - get - { - return this.nodeNameField; - } - set - { - this.nodeNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string actualBaudRate - { - get - { - return this.actualBaudRateField; - } - set - { - this.actualBaudRateField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public ulong networkNumber - { - get - { - return this.networkNumberField; - } - set - { - this.networkNumberField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string networkName - { - get - { - return this.networkNameField; - } - set - { - this.networkNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public bool CANopenManager - { - get - { - return this.cANopenManagerField; - } - set - { - this.cANopenManagerField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayers - { - - private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayer physicalLayerField; - - /// - public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayer PhysicalLayer - { - get - { - return this.physicalLayerField; - } - set - { - this.physicalLayerField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayer - { - - private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate baudRateField; - - /// - public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate baudRate - { - get - { - return this.baudRateField; - } - set - { - this.baudRateField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate - { - - private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate[] supportedBaudRateField; - - private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue defaultValueField; - - public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate() - { - this.defaultValueField = ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue.Item250Kbps; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("supportedBaudRate")] - public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate[] supportedBaudRate - { - get - { - return this.supportedBaudRateField; - } - set - { - this.supportedBaudRateField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue.Item250Kbps)] - public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue defaultValue - { - get - { - return this.defaultValueField; - } - set - { - this.defaultValueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate - { - - private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue - { - - /// - [System.Xml.Serialization.XmlEnumAttribute("10 Kbps")] - Item10Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("20 Kbps")] - Item20Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("50 Kbps")] - Item50Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("100 Kbps")] - Item100Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("125 Kbps")] - Item125Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("250 Kbps")] - Item250Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("500 Kbps")] - Item500Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("800 Kbps")] - Item800Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("1000 Kbps")] - Item1000Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("auto-baudRate")] - autobaudRate, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue - { - - /// - [System.Xml.Serialization.XmlEnumAttribute("10 Kbps")] - Item10Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("20 Kbps")] - Item20Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("50 Kbps")] - Item50Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("100 Kbps")] - Item100Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("125 Kbps")] - Item125Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("250 Kbps")] - Item250Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("500 Kbps")] - Item500Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("800 Kbps")] - Item800Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("1000 Kbps")] - Item1000Kbps, - - /// - [System.Xml.Serialization.XmlEnumAttribute("auto-baudRate")] - autobaudRate, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] - public partial class ProfileBody_Device_CANopen : ProfileBody_DataType - { - - private DeviceIdentity deviceIdentityField; - - private DeviceManager deviceManagerField; - - private DeviceFunction[] deviceFunctionField; - - private ApplicationProcess[] applicationProcessField; - - private ProfileHandle_DataType[] externalProfileHandleField; - - private string formatNameField; - - private string formatVersionField; - - private string fileNameField; - - private string fileCreatorField; - - private System.DateTime fileCreationDateField; - - private System.DateTime fileCreationTimeField; - - private bool fileCreationTimeFieldSpecified; - - private System.DateTime fileModificationDateField; - - private bool fileModificationDateFieldSpecified; - - private System.DateTime fileModificationTimeField; - - private bool fileModificationTimeFieldSpecified; - - private string fileModifiedByField; - - private string fileVersionField; - - private string supportedLanguagesField; - - private ProfileBody_Device_CANopenDeviceClass deviceClassField; - - private bool deviceClassFieldSpecified; - - public ProfileBody_Device_CANopen() - { - this.formatNameField = "CANopen"; - this.formatVersionField = "1.0"; - } - - /// - public DeviceIdentity DeviceIdentity - { - get - { - return this.deviceIdentityField; - } - set - { - this.deviceIdentityField = value; - } - } - - /// - public DeviceManager DeviceManager - { - get - { - return this.deviceManagerField; - } - set - { - this.deviceManagerField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("DeviceFunction")] - public DeviceFunction[] DeviceFunction - { - get - { - return this.deviceFunctionField; - } - set - { - this.deviceFunctionField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("ApplicationProcess")] - public ApplicationProcess[] ApplicationProcess - { - get - { - return this.applicationProcessField; - } - set - { - this.applicationProcessField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("ExternalProfileHandle")] - public ProfileHandle_DataType[] ExternalProfileHandle - { - get - { - return this.externalProfileHandleField; - } - set - { - this.externalProfileHandleField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string formatName - { - get - { - return this.formatNameField; - } - set - { - this.formatNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string formatVersion - { - get - { - return this.formatVersionField; - } - set - { - this.formatVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileName - { - get - { - return this.fileNameField; - } - set - { - this.fileNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileCreator - { - get - { - return this.fileCreatorField; - } - set - { - this.fileCreatorField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] - public System.DateTime fileCreationDate - { - get - { - return this.fileCreationDateField; - } - set - { - this.fileCreationDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] - public System.DateTime fileCreationTime - { - get - { - return this.fileCreationTimeField; - } - set - { - this.fileCreationTimeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool fileCreationTimeSpecified - { - get - { - return this.fileCreationTimeFieldSpecified; - } - set - { - this.fileCreationTimeFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] - public System.DateTime fileModificationDate - { - get - { - return this.fileModificationDateField; - } - set - { - this.fileModificationDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool fileModificationDateSpecified - { - get - { - return this.fileModificationDateFieldSpecified; - } - set - { - this.fileModificationDateFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] - public System.DateTime fileModificationTime - { - get - { - return this.fileModificationTimeField; - } - set - { - this.fileModificationTimeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool fileModificationTimeSpecified - { - get - { - return this.fileModificationTimeFieldSpecified; - } - set - { - this.fileModificationTimeFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileModifiedBy - { - get - { - return this.fileModifiedByField; - } - set - { - this.fileModifiedByField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string fileVersion - { - get - { - return this.fileVersionField; - } - set - { - this.fileVersionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] - public string supportedLanguages - { - get - { - return this.supportedLanguagesField; - } - set - { - this.supportedLanguagesField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public ProfileBody_Device_CANopenDeviceClass deviceClass - { - get - { - return this.deviceClassField; - } - set - { - this.deviceClassField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool deviceClassSpecified - { - get - { - return this.deviceClassFieldSpecified; - } - set - { - this.deviceClassFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class DeviceIdentity - { - - private vendorName vendorNameField; - - private vendorID vendorIDField; - - private vendorText vendorTextField; - - private deviceFamily deviceFamilyField; - - private productFamily productFamilyField; - - private productName productNameField; - - private productID productIDField; - - private productText productTextField; - - private orderNumber[] orderNumberField; - - private version[] versionField; - - private System.DateTime buildDateField; - - private bool buildDateFieldSpecified; - - private specificationRevision specificationRevisionField; - - private instanceName instanceNameField; - - /// - public vendorName vendorName - { - get - { - return this.vendorNameField; - } - set - { - this.vendorNameField = value; - } - } - - /// - public vendorID vendorID - { - get - { - return this.vendorIDField; - } - set - { - this.vendorIDField = value; - } - } - - /// - public vendorText vendorText - { - get - { - return this.vendorTextField; - } - set - { - this.vendorTextField = value; - } - } - - /// - public deviceFamily deviceFamily - { - get - { - return this.deviceFamilyField; - } - set - { - this.deviceFamilyField = value; - } - } - - /// - public productFamily productFamily - { - get - { - return this.productFamilyField; - } - set - { - this.productFamilyField = value; - } - } - - /// - public productName productName - { - get - { - return this.productNameField; - } - set - { - this.productNameField = value; - } - } - - /// - public productID productID - { - get - { - return this.productIDField; - } - set - { - this.productIDField = value; - } - } - - /// - public productText productText - { - get - { - return this.productTextField; - } - set - { - this.productTextField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("orderNumber")] - public orderNumber[] orderNumber - { - get - { - return this.orderNumberField; - } - set - { - this.orderNumberField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("version")] - public version[] version - { - get - { - return this.versionField; - } - set - { - this.versionField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] - public System.DateTime buildDate - { - get - { - return this.buildDateField; - } - set - { - this.buildDateField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool buildDateSpecified - { - get - { - return this.buildDateFieldSpecified; - } - set - { - this.buildDateFieldSpecified = value; - } - } - - /// - public specificationRevision specificationRevision - { - get - { - return this.specificationRevisionField; - } - set - { - this.specificationRevisionField = value; - } - } - - /// - public instanceName instanceName - { - get - { - return this.instanceNameField; - } - set - { - this.instanceNameField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class vendorName - { - - private bool readOnlyField; - - private string valueField; - - public vendorName() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class vendorText - { - - private object[] itemsField; - - private bool readOnlyField; - - public vendorText() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class productFamily - { - - private bool readOnlyField; - - private string valueField; - - public productFamily() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class productName - { - - private bool readOnlyField; - - private string valueField; - - public productName() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class productText - { - - private object[] itemsField; - - private bool readOnlyField; - - public productText() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class orderNumber - { - - private bool readOnlyField; - - private string valueField; - - public orderNumber() - { - this.readOnlyField = true; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(true)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class instanceName - { - - private bool readOnlyField; - - private string valueField; - - public instanceName() - { - this.readOnlyField = false; - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool readOnly - { - get - { - return this.readOnlyField; - } - set - { - this.readOnlyField = value; - } - } - - /// - [System.Xml.Serialization.XmlTextAttribute()] - public string Value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class DeviceManager - { - - private indicatorList indicatorListField; - - /// - public indicatorList indicatorList - { - get - { - return this.indicatorListField; - } - set - { - this.indicatorListField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class indicatorList - { - - private LEDList lEDListField; - - /// - public LEDList LEDList - { - get - { - return this.lEDListField; - } - set - { - this.lEDListField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class LEDList - { - - private LED[] lEDField; - - private combinedState[] combinedStateField; - - /// - [System.Xml.Serialization.XmlElementAttribute("LED")] - public LED[] LED - { - get - { - return this.lEDField; - } - set - { - this.lEDField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("combinedState")] - public combinedState[] combinedState - { - get - { - return this.combinedStateField; - } - set - { - this.combinedStateField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class LED - { - - private object[] itemsField; - - private LEDstate[] lEDstateField; - - private LEDLEDcolors lEDcolorsField; - - private LEDLEDtype lEDtypeField; - - private bool lEDtypeFieldSpecified; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("LEDstate")] - public LEDstate[] LEDstate - { - get - { - return this.lEDstateField; - } - set - { - this.lEDstateField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public LEDLEDcolors LEDcolors - { - get - { - return this.lEDcolorsField; - } - set - { - this.lEDcolorsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public LEDLEDtype LEDtype - { - get - { - return this.lEDtypeField; - } - set - { - this.lEDtypeField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool LEDtypeSpecified - { - get - { - return this.lEDtypeFieldSpecified; - } - set - { - this.lEDtypeFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class LEDstate - { - - private object[] itemsField; - - private string uniqueIDField; - - private LEDstateState stateField; - - private LEDstateLEDcolor lEDcolorField; - - private uint flashingPeriodField; - - private bool flashingPeriodFieldSpecified; - - private byte impulsWidthField; - - private byte numberOfImpulsesField; - - public LEDstate() - { - this.impulsWidthField = ((byte)(50)); - this.numberOfImpulsesField = ((byte)(1)); - } - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public LEDstateState state - { - get - { - return this.stateField; - } - set - { - this.stateField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public LEDstateLEDcolor LEDcolor - { - get - { - return this.lEDcolorField; - } - set - { - this.lEDcolorField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public uint flashingPeriod - { - get - { - return this.flashingPeriodField; - } - set - { - this.flashingPeriodField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool flashingPeriodSpecified - { - get - { - return this.flashingPeriodFieldSpecified; - } - set - { - this.flashingPeriodFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(typeof(byte), "50")] - public byte impulsWidth - { - get - { - return this.impulsWidthField; - } - set - { - this.impulsWidthField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(typeof(byte), "1")] - public byte numberOfImpulses - { - get - { - return this.numberOfImpulsesField; - } - set - { - this.numberOfImpulsesField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum LEDstateState - { - - /// - on, - - /// - off, - - /// - flashing, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum LEDstateLEDcolor - { - - /// - green, - - /// - amber, - - /// - red, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum LEDLEDcolors - { - - /// - monocolor, - - /// - bicolor, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum LEDLEDtype - { - - /// - IO, - - /// - device, - - /// - communication, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class combinedState - { - - private object[] itemsField; - - private combinedStateLEDstateRef[] lEDstateRefField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("LEDstateRef")] - public combinedStateLEDstateRef[] LEDstateRef - { - get - { - return this.lEDstateRefField; - } - set - { - this.lEDstateRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class combinedStateLEDstateRef - { - - private string stateIDRefField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string stateIDRef - { - get - { - return this.stateIDRefField; - } - set - { - this.stateIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class DeviceFunction - { - - private capabilities capabilitiesField; - - private picture[] picturesListField; - - private dictionary[] dictionaryListField; - - /// - public capabilities capabilities - { - get - { - return this.capabilitiesField; - } - set - { - this.capabilitiesField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("picture", IsNullable = false)] - public picture[] picturesList - { - get - { - return this.picturesListField; - } - set - { - this.picturesListField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("dictionary", IsNullable = false)] - public dictionary[] dictionaryList - { - get - { - return this.dictionaryListField; - } - set - { - this.dictionaryListField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class capabilities - { - - private characteristicsList[] characteristicsListField; - - private compliantWith[] standardComplianceListField; - - /// - [System.Xml.Serialization.XmlElementAttribute("characteristicsList")] - public characteristicsList[] characteristicsList - { - get - { - return this.characteristicsListField; - } - set - { - this.characteristicsListField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("compliantWith", IsNullable = false)] - public compliantWith[] standardComplianceList - { - get - { - return this.standardComplianceListField; - } - set - { - this.standardComplianceListField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class characteristicsList - { - - private characteristicsListCategory categoryField; - - private characteristic[] characteristicField; - - /// - public characteristicsListCategory category - { - get - { - return this.categoryField; - } - set - { - this.categoryField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("characteristic")] - public characteristic[] characteristic - { - get - { - return this.characteristicField; - } - set - { - this.characteristicField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class characteristicsListCategory - { - - private object[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class characteristic - { - - private characteristicName characteristicNameField; - - private characteristicContent[] characteristicContentField; - - /// - public characteristicName characteristicName - { - get - { - return this.characteristicNameField; - } - set - { - this.characteristicNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("characteristicContent")] - public characteristicContent[] characteristicContent - { - get - { - return this.characteristicContentField; - } - set - { - this.characteristicContentField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class characteristicName - { - - private object[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class characteristicContent - { - - private object[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class compliantWith - { - - private object[] itemsField; - - private string nameField; - - private compliantWithRange rangeField; - - public compliantWith() - { - this.rangeField = compliantWithRange.international; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(compliantWithRange.international)] - public compliantWithRange range - { - get - { - return this.rangeField; - } - set - { - this.rangeField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum compliantWithRange - { - - /// - international, - - /// - @internal, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class picture - { - - private object[] itemsField; - - private string uRIField; - - private uint numberField; - - private bool numberFieldSpecified; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] - public string URI - { - get - { - return this.uRIField; - } - set - { - this.uRIField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public uint number - { - get - { - return this.numberField; - } - set - { - this.numberField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool numberSpecified - { - get - { - return this.numberFieldSpecified; - } - set - { - this.numberFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class dictionary - { - - private file fileField; - - private string langField; - - private string dictIDField; - - /// - public file file - { - get - { - return this.fileField; - } - set - { - this.fileField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "language")] - public string lang - { - get - { - return this.langField; - } - set - { - this.langField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string dictID - { - get - { - return this.dictIDField; - } - set - { - this.dictIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class file - { - - private string uRIField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] - public string URI - { - get - { - return this.uRIField; - } - set - { - this.uRIField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class ApplicationProcess - { - - private dataTypeList dataTypeListField; - - private functionType[] functionTypeListField; - - private functionInstanceList functionInstanceListField; - - private templateList templateListField; - - private parameter[] parameterListField; - - private parameterGroup[] parameterGroupListField; - - /// - public dataTypeList dataTypeList - { - get - { - return this.dataTypeListField; - } - set - { - this.dataTypeListField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("functionType", IsNullable = false)] - public functionType[] functionTypeList - { - get - { - return this.functionTypeListField; - } - set - { - this.functionTypeListField = value; - } - } - - /// - public functionInstanceList functionInstanceList - { - get - { - return this.functionInstanceListField; - } - set - { - this.functionInstanceListField = value; - } - } - - /// - public templateList templateList - { - get - { - return this.templateListField; - } - set - { - this.templateListField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("parameter", IsNullable = false)] - public parameter[] parameterList - { - get - { - return this.parameterListField; - } - set - { - this.parameterListField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("parameterGroup", IsNullable = false)] - public parameterGroup[] parameterGroupList - { - get - { - return this.parameterGroupListField; - } - set - { - this.parameterGroupListField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class dataTypeList - { - - private array[] arrayField; - - private @struct[] structField; - - private @enum[] enumField; - - private derived[] derivedField; - - /// - [System.Xml.Serialization.XmlElementAttribute("array")] - public array[] array - { - get - { - return this.arrayField; - } - set - { - this.arrayField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("struct")] - public @struct[] @struct - { - get - { - return this.structField; - } - set - { - this.structField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("enum")] - public @enum[] @enum - { - get - { - return this.enumField; - } - set - { - this.enumField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("derived")] - public derived[] derived - { - get - { - return this.derivedField; - } - set - { - this.derivedField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class array - { - - private object[] itemsField; - - private subrange[] subrangeField; - - private object itemField; - - private ItemChoiceType itemElementNameField; - - private string nameField; - - private string uniqueIDField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("subrange")] - public subrange[] subrange - { - get - { - return this.subrangeField; - } - set - { - this.subrangeField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] - [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] - public object Item - { - get - { - return this.itemField; - } - set - { - this.itemField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public ItemChoiceType ItemElementName - { - get - { - return this.itemElementNameField; - } - set - { - this.itemElementNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class subrange - { - - private long lowerLimitField; - - private long upperLimitField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public long lowerLimit - { - get - { - return this.lowerLimitField; - } - set - { - this.lowerLimitField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public long upperLimit - { - get - { - return this.upperLimitField; - } - set - { - this.upperLimitField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class dataTypeIDRef - { - - private string uniqueIDRefField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string uniqueIDRef - { - get - { - return this.uniqueIDRefField; - } - set - { - this.uniqueIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] - public enum ItemChoiceType - { - - /// - BITSTRING, - - /// - BOOL, - - /// - BYTE, - - /// - CHAR, - - /// - DINT, - - /// - DWORD, - - /// - INT, - - /// - LINT, - - /// - LREAL, - - /// - LWORD, - - /// - REAL, - - /// - SINT, - - /// - STRING, - - /// - UDINT, - - /// - UINT, - - /// - ULINT, - - /// - USINT, - - /// - WORD, - - /// - WSTRING, - - /// - dataTypeIDRef, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class @struct - { - - private object[] itemsField; - - private varDeclaration[] varDeclarationField; - - private string nameField; - - private string uniqueIDField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] - public varDeclaration[] varDeclaration - { - get - { - return this.varDeclarationField; - } - set - { - this.varDeclarationField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class varDeclaration - { - - private object[] itemsField; - - private object itemField; - - private ItemChoiceType1 itemElementNameField; - - private string nameField; - - private string uniqueIDField; - - private string sizeField; - - private string initialValueField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] - [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] - public object Item - { - get - { - return this.itemField; - } - set - { - this.itemField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public ItemChoiceType1 ItemElementName - { - get - { - return this.itemElementNameField; - } - set - { - this.itemElementNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string size - { - get - { - return this.sizeField; - } - set - { - this.sizeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string initialValue - { - get - { - return this.initialValueField; - } - set - { - this.initialValueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] - public enum ItemChoiceType1 - { - - /// - BITSTRING, - - /// - BOOL, - - /// - BYTE, - - /// - CHAR, - - /// - DINT, - - /// - DWORD, - - /// - INT, - - /// - LINT, - - /// - LREAL, - - /// - LWORD, - - /// - REAL, - - /// - SINT, - - /// - STRING, - - /// - UDINT, - - /// - UINT, - - /// - ULINT, - - /// - USINT, - - /// - WORD, - - /// - WSTRING, - - /// - dataTypeIDRef, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class @enum - { - - private object[] itemsField; - - private enumValue[] enumValueField; - - private object bOOLField; - - private object bITSTRINGField; - - private object bYTEField; - - private object cHARField; - - private object wORDField; - - private object dWORDField; - - private object lWORDField; - - private object sINTField; - - private object iNTField; - - private object dINTField; - - private object lINTField; - - private object uSINTField; - - private object uINTField; - - private object uDINTField; - - private object uLINTField; - - private object rEALField; - - private object lREALField; - - private object sTRINGField; - - private object wSTRINGField; - - private string nameField; - - private string uniqueIDField; - - private string sizeField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("enumValue")] - public enumValue[] enumValue - { - get - { - return this.enumValueField; - } - set - { - this.enumValueField = value; - } - } - - /// - public object BOOL - { - get - { - return this.bOOLField; - } - set - { - this.bOOLField = value; - } - } - - /// - public object BITSTRING - { - get - { - return this.bITSTRINGField; - } - set - { - this.bITSTRINGField = value; - } - } - - /// - public object BYTE - { - get - { - return this.bYTEField; - } - set - { - this.bYTEField = value; - } - } - - /// - public object CHAR - { - get - { - return this.cHARField; - } - set - { - this.cHARField = value; - } - } - - /// - public object WORD - { - get - { - return this.wORDField; - } - set - { - this.wORDField = value; - } - } - - /// - public object DWORD - { - get - { - return this.dWORDField; - } - set - { - this.dWORDField = value; - } - } - - /// - public object LWORD - { - get - { - return this.lWORDField; - } - set - { - this.lWORDField = value; - } - } - - /// - public object SINT - { - get - { - return this.sINTField; - } - set - { - this.sINTField = value; - } - } - - /// - public object INT - { - get - { - return this.iNTField; - } - set - { - this.iNTField = value; - } - } - - /// - public object DINT - { - get - { - return this.dINTField; - } - set - { - this.dINTField = value; - } - } - - /// - public object LINT - { - get - { - return this.lINTField; - } - set - { - this.lINTField = value; - } - } - - /// - public object USINT - { - get - { - return this.uSINTField; - } - set - { - this.uSINTField = value; - } - } - - /// - public object UINT - { - get - { - return this.uINTField; - } - set - { - this.uINTField = value; - } - } - - /// - public object UDINT - { - get - { - return this.uDINTField; - } - set - { - this.uDINTField = value; - } - } - - /// - public object ULINT - { - get - { - return this.uLINTField; - } - set - { - this.uLINTField = value; - } - } - - /// - public object REAL - { - get - { - return this.rEALField; - } - set - { - this.rEALField = value; - } - } - - /// - public object LREAL - { - get - { - return this.lREALField; - } - set - { - this.lREALField = value; - } - } - - /// - public object STRING - { - get - { - return this.sTRINGField; - } - set - { - this.sTRINGField = value; - } - } - - /// - public object WSTRING - { - get - { - return this.wSTRINGField; - } - set - { - this.wSTRINGField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string size - { - get - { - return this.sizeField; - } - set - { - this.sizeField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class enumValue - { - - private object[] itemsField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class derived - { - - private object[] itemsField; - - private count countField; - - private object itemField; - - private ItemChoiceType2 itemElementNameField; - - private string nameField; - - private string uniqueIDField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - public count count - { - get - { - return this.countField; - } - set - { - this.countField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] - [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] - public object Item - { - get - { - return this.itemField; - } - set - { - this.itemField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public ItemChoiceType2 ItemElementName - { - get - { - return this.itemElementNameField; - } - set - { - this.itemElementNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class count - { - - private object[] itemsField; - - private defaultValue defaultValueField; - - private allowedValues allowedValuesField; - - private string uniqueIDField; - - private countAccess accessField; - - public count() - { - this.accessField = countAccess.read; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - public defaultValue defaultValue - { - get - { - return this.defaultValueField; - } - set - { - this.defaultValueField = value; - } - } - - /// - public allowedValues allowedValues - { - get - { - return this.allowedValuesField; - } - set - { - this.allowedValuesField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(countAccess.read)] - public countAccess access - { - get - { - return this.accessField; - } - set - { - this.accessField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class defaultValue - { - - private object[] itemsField; - - private string valueField; - - private string offsetField; - - private string multiplierField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class allowedValues - { - - private value[] valueField; - - private range[] rangeField; - - private string templateIDRefField; - - /// - [System.Xml.Serialization.XmlElementAttribute("value")] - public value[] value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("range")] - public range[] range - { - get - { - return this.rangeField; - } - set - { - this.rangeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string templateIDRef - { - get - { - return this.templateIDRefField; - } - set - { - this.templateIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class value - { - - private object[] itemsField; - - private string value1Field; - - private string offsetField; - - private string multiplierField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute("value")] - public string value1 - { - get - { - return this.value1Field; - } - set - { - this.value1Field = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class range - { - - private rangeMinValue minValueField; - - private rangeMaxValue maxValueField; - - private rangeStep stepField; - - /// - public rangeMinValue minValue - { - get - { - return this.minValueField; - } - set - { - this.minValueField = value; - } - } - - /// - public rangeMaxValue maxValue - { - get - { - return this.maxValueField; - } - set - { - this.maxValueField = value; - } - } - - /// - public rangeStep step - { - get - { - return this.stepField; - } - set - { - this.stepField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class rangeMinValue - { - - private object[] itemsField; - - private string valueField; - - private string offsetField; - - private string multiplierField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class rangeMaxValue - { - - private object[] itemsField; - - private string valueField; - - private string offsetField; - - private string multiplierField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public partial class rangeStep - { - - private object[] itemsField; - - private string valueField; - - private string offsetField; - - private string multiplierField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum countAccess - { - - /// - @const, - - /// - read, - - /// - write, - - /// - readWrite, - - /// - noAccess, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] - public enum ItemChoiceType2 - { - - /// - BITSTRING, - - /// - BOOL, - - /// - BYTE, - - /// - CHAR, - - /// - DINT, - - /// - DWORD, - - /// - INT, - - /// - LINT, - - /// - LREAL, - - /// - LWORD, - - /// - REAL, - - /// - SINT, - - /// - STRING, - - /// - UDINT, - - /// - UINT, - - /// - ULINT, - - /// - USINT, - - /// - WORD, - - /// - WSTRING, - - /// - dataTypeIDRef, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class functionType - { - - private object[] itemsField; - - private versionInfo[] versionInfoField; - - private interfaceList interfaceListField; - - private functionInstanceList functionInstanceListField; - - private string nameField; - - private string uniqueIDField; - - private string packageField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("versionInfo")] - public versionInfo[] versionInfo - { - get - { - return this.versionInfoField; - } - set - { - this.versionInfoField = value; - } - } - - /// - public interfaceList interfaceList - { - get - { - return this.interfaceListField; - } - set - { - this.interfaceListField = value; - } - } - - /// - public functionInstanceList functionInstanceList - { - get - { - return this.functionInstanceListField; - } - set - { - this.functionInstanceListField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string package - { - get - { - return this.packageField; - } - set - { - this.packageField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class versionInfo - { - - private object[] itemsField; - - private string organizationField; - - private string versionField; - - private string authorField; - - private System.DateTime dateField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string organization - { - get - { - return this.organizationField; - } - set - { - this.organizationField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string version - { - get - { - return this.versionField; - } - set - { - this.versionField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string author - { - get - { - return this.authorField; - } - set - { - this.authorField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] - public System.DateTime date - { - get - { - return this.dateField; - } - set - { - this.dateField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class interfaceList - { - - private varDeclaration[] inputVarsField; - - private varDeclaration[] outputVarsField; - - private varDeclaration[] configVarsField; - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("varDeclaration", IsNullable = false)] - public varDeclaration[] inputVars - { - get - { - return this.inputVarsField; - } - set - { - this.inputVarsField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("varDeclaration", IsNullable = false)] - public varDeclaration[] outputVars - { - get - { - return this.outputVarsField; - } - set - { - this.outputVarsField = value; - } - } - - /// - [System.Xml.Serialization.XmlArrayItemAttribute("varDeclaration", IsNullable = false)] - public varDeclaration[] configVars - { - get - { - return this.configVarsField; - } - set - { - this.configVarsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class functionInstanceList - { - - private functionInstance[] functionInstanceField; - - private connection[] connectionField; - - /// - [System.Xml.Serialization.XmlElementAttribute("functionInstance")] - public functionInstance[] functionInstance - { - get - { - return this.functionInstanceField; - } - set - { - this.functionInstanceField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("connection")] - public connection[] connection - { - get - { - return this.connectionField; - } - set - { - this.connectionField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class functionInstance - { - - private object[] itemsField; - - private string nameField; - - private string uniqueIDField; - - private string typeIDRefField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string typeIDRef - { - get - { - return this.typeIDRefField; - } - set - { - this.typeIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class connection - { - - private string sourceField; - - private string destinationField; - - private string descriptionField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string source - { - get - { - return this.sourceField; - } - set - { - this.sourceField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string destination - { - get - { - return this.destinationField; - } - set - { - this.destinationField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string description - { - get - { - return this.descriptionField; - } - set - { - this.descriptionField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class templateList - { - - private parameterTemplate[] parameterTemplateField; - - private allowedValuesTemplate[] allowedValuesTemplateField; - - /// - [System.Xml.Serialization.XmlElementAttribute("parameterTemplate")] - public parameterTemplate[] parameterTemplate - { - get - { - return this.parameterTemplateField; - } - set - { - this.parameterTemplateField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("allowedValuesTemplate")] - public allowedValuesTemplate[] allowedValuesTemplate - { - get - { - return this.allowedValuesTemplateField; - } - set - { - this.allowedValuesTemplateField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class parameterTemplate - { - - private object itemField; - - private ItemChoiceType3 itemElementNameField; - - private conditionalSupport[] conditionalSupportField; - - private actualValue actualValueField; - - private defaultValue defaultValueField; - - private substituteValue substituteValueField; - - private allowedValues allowedValuesField; - - private unit unitField; - - private property[] propertyField; - - private string uniqueIDField; - - private parameterTemplateAccess accessField; - - private string accessListField; - - private parameterTemplateSupport supportField; - - private bool supportFieldSpecified; - - private bool persistentField; - - private string offsetField; - - private string multiplierField; - - private string templateIDRefField; - - public parameterTemplate() - { - this.accessField = parameterTemplateAccess.read; - this.persistentField = false; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] - [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] - public object Item - { - get - { - return this.itemField; - } - set - { - this.itemField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public ItemChoiceType3 ItemElementName - { - get - { - return this.itemElementNameField; - } - set - { - this.itemElementNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("conditionalSupport")] - public conditionalSupport[] conditionalSupport - { - get - { - return this.conditionalSupportField; - } - set - { - this.conditionalSupportField = value; - } - } - - /// - public actualValue actualValue - { - get - { - return this.actualValueField; - } - set - { - this.actualValueField = value; - } - } - - /// - public defaultValue defaultValue - { - get - { - return this.defaultValueField; - } - set - { - this.defaultValueField = value; - } - } - - /// - public substituteValue substituteValue - { - get - { - return this.substituteValueField; - } - set - { - this.substituteValueField = value; - } - } - - /// - public allowedValues allowedValues - { - get - { - return this.allowedValuesField; - } - set - { - this.allowedValuesField = value; - } - } - - /// - public unit unit - { - get - { - return this.unitField; - } - set - { - this.unitField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("property")] - public property[] property - { - get - { - return this.propertyField; - } - set - { - this.propertyField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(parameterTemplateAccess.read)] - public parameterTemplateAccess access - { - get - { - return this.accessField; - } - set - { - this.accessField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] - public string accessList - { - get - { - return this.accessListField; - } - set - { - this.accessListField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public parameterTemplateSupport support - { - get - { - return this.supportField; - } - set - { - this.supportField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool supportSpecified - { - get - { - return this.supportFieldSpecified; - } - set - { - this.supportFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool persistent - { - get - { - return this.persistentField; - } - set - { - this.persistentField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string templateIDRef - { - get - { - return this.templateIDRefField; - } - set - { - this.templateIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] - public enum ItemChoiceType3 - { - - /// - BITSTRING, - - /// - BOOL, - - /// - BYTE, - - /// - CHAR, - - /// - DINT, - - /// - DWORD, - - /// - INT, - - /// - LINT, - - /// - LREAL, - - /// - LWORD, - - /// - REAL, - - /// - SINT, - - /// - STRING, - - /// - UDINT, - - /// - UINT, - - /// - ULINT, - - /// - USINT, - - /// - WORD, - - /// - WSTRING, - - /// - dataTypeIDRef, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class conditionalSupport - { - - private string paramIDRefField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string paramIDRef - { - get - { - return this.paramIDRefField; - } - set - { - this.paramIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class actualValue - { - - private object[] itemsField; - - private string valueField; - - private string offsetField; - - private string multiplierField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class substituteValue - { - - private object[] itemsField; - - private string valueField; - - private string offsetField; - - private string multiplierField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class unit - { - - private object[] itemsField; - - private string multiplierField; - - private string unitURIField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] - public string unitURI - { - get - { - return this.unitURIField; - } - set - { - this.unitURIField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class property - { - - private string nameField; - - private string valueField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string name - { - get - { - return this.nameField; - } - set - { - this.nameField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum parameterTemplateAccess - { - - /// - @const, - - /// - read, - - /// - write, - - /// - readWrite, - - /// - readWriteInput, - - /// - readWriteOutput, - - /// - noAccess, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum parameterTemplateSupport - { - - /// - mandatory, - - /// - optional, - - /// - conditional, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class allowedValuesTemplate - { - - private value[] valueField; - - private range[] rangeField; - - private string uniqueIDField; - - /// - [System.Xml.Serialization.XmlElementAttribute("value")] - public value[] value - { - get - { - return this.valueField; - } - set - { - this.valueField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("range")] - public range[] range - { - get - { - return this.rangeField; - } - set - { - this.rangeField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class parameter - { - - private object[] itemsField; - - private object[] items1Field; - - private Items1ChoiceType[] items1ElementNameField; - - private conditionalSupport[] conditionalSupportField; - - private denotation denotationField; - - private actualValue actualValueField; - - private defaultValue defaultValueField; - - private substituteValue substituteValueField; - - private allowedValues allowedValuesField; - - private unit unitField; - - private property[] propertyField; - - private string uniqueIDField; - - private parameterTemplateAccess accessField; - - private string accessListField; - - private parameterTemplateSupport supportField; - - private bool supportFieldSpecified; - - private bool persistentField; - - private string offsetField; - - private string multiplierField; - - private string templateIDRefField; - - public parameter() - { - this.accessField = parameterTemplateAccess.read; - this.persistentField = false; - } - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] - [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] - [System.Xml.Serialization.XmlElementAttribute("variableRef", typeof(variableRef))] - [System.Xml.Serialization.XmlChoiceIdentifierAttribute("Items1ElementName")] - public object[] Items1 - { - get - { - return this.items1Field; - } - set - { - this.items1Field = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("Items1ElementName")] - [System.Xml.Serialization.XmlIgnoreAttribute()] - public Items1ChoiceType[] Items1ElementName - { - get - { - return this.items1ElementNameField; - } - set - { - this.items1ElementNameField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("conditionalSupport")] - public conditionalSupport[] conditionalSupport - { - get - { - return this.conditionalSupportField; - } - set - { - this.conditionalSupportField = value; - } - } - - /// - public denotation denotation - { - get - { - return this.denotationField; - } - set - { - this.denotationField = value; - } - } - - /// - public actualValue actualValue - { - get - { - return this.actualValueField; - } - set - { - this.actualValueField = value; - } - } - - /// - public defaultValue defaultValue - { - get - { - return this.defaultValueField; - } - set - { - this.defaultValueField = value; - } - } - - /// - public substituteValue substituteValue - { - get - { - return this.substituteValueField; - } - set - { - this.substituteValueField = value; - } - } - - /// - public allowedValues allowedValues - { - get - { - return this.allowedValuesField; - } - set - { - this.allowedValuesField = value; - } - } - - /// - public unit unit - { - get - { - return this.unitField; - } - set - { - this.unitField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("property")] - public property[] property - { - get - { - return this.propertyField; - } - set - { - this.propertyField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - //[System.ComponentModel.DefaultValueAttribute(parameterTemplateAccess.read)] - public parameterTemplateAccess access - { - get - { - return this.accessField; - } - set - { - this.accessField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] - public string accessList - { - get - { - return this.accessListField; - } - set - { - this.accessListField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public parameterTemplateSupport support - { - get - { - return this.supportField; - } - set - { - this.supportField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool supportSpecified - { - get - { - return this.supportFieldSpecified; - } - set - { - this.supportFieldSpecified = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(false)] - public bool persistent - { - get - { - return this.persistentField; - } - set - { - this.persistentField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string offset - { - get - { - return this.offsetField; - } - set - { - this.offsetField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string multiplier - { - get - { - return this.multiplierField; - } - set - { - this.multiplierField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string templateIDRef - { - get - { - return this.templateIDRefField; - } - set - { - this.templateIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class variableRef - { - - private instanceIDRef[] instanceIDRefField; - - private variableIDRef variableIDRefField; - - private memberRef[] memberRefField; - - private byte positionField; - - public variableRef() - { - this.positionField = ((byte)(1)); - } - - /// - [System.Xml.Serialization.XmlElementAttribute("instanceIDRef")] - public instanceIDRef[] instanceIDRef - { - get - { - return this.instanceIDRefField; - } - set - { - this.instanceIDRefField = value; - } - } - - /// - public variableIDRef variableIDRef - { - get - { - return this.variableIDRefField; - } - set - { - this.variableIDRefField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("memberRef")] - public memberRef[] memberRef - { - get - { - return this.memberRefField; - } - set - { - this.memberRefField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - [System.ComponentModel.DefaultValueAttribute(typeof(byte), "1")] - public byte position - { - get - { - return this.positionField; - } - set - { - this.positionField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class instanceIDRef - { - - private string uniqueIDRefField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string uniqueIDRef - { - get - { - return this.uniqueIDRefField; - } - set - { - this.uniqueIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class variableIDRef - { - - private string uniqueIDRefField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string uniqueIDRef - { - get - { - return this.uniqueIDRefField; - } - set - { - this.uniqueIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class memberRef - { - - private string uniqueIDRefField; - - private long indexField; - - private bool indexFieldSpecified; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string uniqueIDRef - { - get - { - return this.uniqueIDRefField; - } - set - { - this.uniqueIDRefField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public long index - { - get - { - return this.indexField; - } - set - { - this.indexField = value; - } - } - - /// - [System.Xml.Serialization.XmlIgnoreAttribute()] - public bool indexSpecified - { - get - { - return this.indexFieldSpecified; - } - set - { - this.indexFieldSpecified = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] - public enum Items1ChoiceType - { - - /// - BITSTRING, - - /// - BOOL, - - /// - BYTE, - - /// - CHAR, - - /// - DINT, - - /// - DWORD, - - /// - INT, - - /// - LINT, - - /// - LREAL, - - /// - LWORD, - - /// - REAL, - - /// - SINT, - - /// - STRING, - - /// - UDINT, - - /// - UINT, - - /// - ULINT, - - /// - USINT, - - /// - WORD, - - /// - WSTRING, - - /// - dataTypeIDRef, - - /// - variableRef, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class denotation - { - - private object[] itemsField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class parameterGroup - { - - private object[] itemsField; - - private parameterGroup[] parameterGroup1Field; - - private parameterRef[] parameterRefField; - - private string uniqueIDField; - - private string kindOfAccessField; - - /// - [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] - [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] - [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] - [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] - public object[] Items - { - get - { - return this.itemsField; - } - set - { - this.itemsField = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("parameterGroup")] - public parameterGroup[] parameterGroup1 - { - get - { - return this.parameterGroup1Field; - } - set - { - this.parameterGroup1Field = value; - } - } - - /// - [System.Xml.Serialization.XmlElementAttribute("parameterRef")] - public parameterRef[] parameterRef - { - get - { - return this.parameterRefField; - } - set - { - this.parameterRefField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] - public string uniqueID - { - get - { - return this.uniqueIDField; - } - set - { - this.uniqueIDField = value; - } - } - - /// - [System.Xml.Serialization.XmlAttributeAttribute()] - public string kindOfAccess - { - get - { - return this.kindOfAccessField; - } - set - { - this.kindOfAccessField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class parameterRef - { - - private string uniqueIDRefField; - - /// - [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] - public string uniqueIDRef - { - get - { - return this.uniqueIDRefField; - } - set - { - this.uniqueIDRefField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - public enum ProfileBody_Device_CANopenDeviceClass - { - - /// - compact, - - /// - modular, - - /// - configurable, - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class standardComplianceList - { - - private compliantWith[] compliantWithField; - - /// - [System.Xml.Serialization.XmlElementAttribute("compliantWith")] - public compliantWith[] compliantWith - { - get - { - return this.compliantWithField; - } - set - { - this.compliantWithField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class picturesList - { - - private picture[] pictureField; - - /// - [System.Xml.Serialization.XmlElementAttribute("picture")] - public picture[] picture - { - get - { - return this.pictureField; - } - set - { - this.pictureField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class dictionaryList - { - - private dictionary[] dictionaryField; - - /// - [System.Xml.Serialization.XmlElementAttribute("dictionary")] - public dictionary[] dictionary - { - get - { - return this.dictionaryField; - } - set - { - this.dictionaryField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class functionTypeList - { - - private functionType[] functionTypeField; - - /// - [System.Xml.Serialization.XmlElementAttribute("functionType")] - public functionType[] functionType - { - get - { - return this.functionTypeField; - } - set - { - this.functionTypeField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class inputVars - { - - private varDeclaration[] varDeclarationField; - - /// - [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] - public varDeclaration[] varDeclaration - { - get - { - return this.varDeclarationField; - } - set - { - this.varDeclarationField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class outputVars - { - - private varDeclaration[] varDeclarationField; - - /// - [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] - public varDeclaration[] varDeclaration - { - get - { - return this.varDeclarationField; - } - set - { - this.varDeclarationField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class configVars - { - - private varDeclaration[] varDeclarationField; - - /// - [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] - public varDeclaration[] varDeclaration - { - get - { - return this.varDeclarationField; - } - set - { - this.varDeclarationField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class parameterList - { - - private parameter[] parameterField; - - /// - [System.Xml.Serialization.XmlElementAttribute("parameter")] - public parameter[] parameter - { - get - { - return this.parameterField; - } - set - { - this.parameterField = value; - } - } - } - - /// - [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] - [System.SerializableAttribute()] - [System.Diagnostics.DebuggerStepThroughAttribute()] - [System.ComponentModel.DesignerCategoryAttribute("code")] - [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] - [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] - public partial class parameterGroupList - { - - private parameterGroup[] parameterGroupField; - - /// - [System.Xml.Serialization.XmlElementAttribute("parameterGroup")] - public parameterGroup[] parameterGroup - { - get - { - return this.parameterGroupField; - } - set - { - this.parameterGroupField = value; - } - } - } -} diff --git a/libEDSsharp/CanOpenXSD_1_0.cs b/libEDSsharp/CanOpenXSD_1_0.cs new file mode 100644 index 00000000..a981b552 --- /dev/null +++ b/libEDSsharp/CanOpenXSD_1_0.cs @@ -0,0 +1,9376 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +// +// This source code was auto-generated by xsd, Version=4.6.1055.0. +// +namespace CanOpenXSD_1_0 { + using System.Xml.Serialization; + + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class ISO15745ProfileContainer + { + + private ISO15745Profile[] iSO15745ProfileField; + + /// + [System.Xml.Serialization.XmlElementAttribute("ISO15745Profile")] + public ISO15745Profile[] ISO15745Profile + { + get + { + return this.iSO15745ProfileField; + } + set + { + this.iSO15745ProfileField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class ISO15745Profile + { + + private ProfileHeader_DataType profileHeaderField; + + private ProfileBody_DataType profileBodyField; + + /// + public ProfileHeader_DataType ProfileHeader + { + get + { + return this.profileHeaderField; + } + set + { + this.profileHeaderField = value; + } + } + + /// + public ProfileBody_DataType ProfileBody + { + get + { + return this.profileBodyField; + } + set + { + this.profileBodyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileHeader_DataType + { + + private string profileIdentificationField; + + private string profileRevisionField; + + private string profileNameField; + + private string profileSourceField; + + private ProfileClassID_DataType profileClassIDField; + + private System.DateTime profileDateField; + + private bool profileDateFieldSpecified; + + private string additionalInformationField; + + private ISO15745Reference_DataType iSO15745ReferenceField; + + private string[] iASInterfaceTypeField; + + /// + public string ProfileIdentification + { + get + { + return this.profileIdentificationField; + } + set + { + this.profileIdentificationField = value; + } + } + + /// + public string ProfileRevision + { + get + { + return this.profileRevisionField; + } + set + { + this.profileRevisionField = value; + } + } + + /// + public string ProfileName + { + get + { + return this.profileNameField; + } + set + { + this.profileNameField = value; + } + } + + /// + public string ProfileSource + { + get + { + return this.profileSourceField; + } + set + { + this.profileSourceField = value; + } + } + + /// + public ProfileClassID_DataType ProfileClassID + { + get + { + return this.profileClassIDField; + } + set + { + this.profileClassIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] + public System.DateTime ProfileDate + { + get + { + return this.profileDateField; + } + set + { + this.profileDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool ProfileDateSpecified + { + get + { + return this.profileDateFieldSpecified; + } + set + { + this.profileDateFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "anyURI")] + public string AdditionalInformation + { + get + { + return this.additionalInformationField; + } + set + { + this.additionalInformationField = value; + } + } + + /// + public ISO15745Reference_DataType ISO15745Reference + { + get + { + return this.iSO15745ReferenceField; + } + set + { + this.iSO15745ReferenceField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("IASInterfaceType")] + public string[] IASInterfaceType + { + get + { + return this.iASInterfaceTypeField; + } + set + { + this.iASInterfaceTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] + public enum ProfileClassID_DataType + { + + /// + AIP, + + /// + Process, + + /// + InformationExchange, + + /// + Resource, + + /// + Device, + + /// + CommunicationNetwork, + + /// + Equipment, + + /// + Human, + + /// + Material, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ISO15745Reference_DataType + { + + private string iSO15745PartField; + + private string iSO15745EditionField; + + private string profileTechnologyField; + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "positiveInteger")] + public string ISO15745Part + { + get + { + return this.iSO15745PartField; + } + set + { + this.iSO15745PartField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "positiveInteger")] + public string ISO15745Edition + { + get + { + return this.iSO15745EditionField; + } + set + { + this.iSO15745EditionField = value; + } + } + + /// + public string ProfileTechnology + { + get + { + return this.profileTechnologyField; + } + set + { + this.profileTechnologyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileHandle_DataType + { + + private string profileIdentificationField; + + private string profileRevisionField; + + private string profileLocationField; + + /// + public string ProfileIdentification + { + get + { + return this.profileIdentificationField; + } + set + { + this.profileIdentificationField = value; + } + } + + /// + public string ProfileRevision + { + get + { + return this.profileRevisionField; + } + set + { + this.profileRevisionField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "anyURI")] + public string ProfileLocation + { + get + { + return this.profileLocationField; + } + set + { + this.profileLocationField = value; + } + } + } + + /// + [System.Xml.Serialization.XmlIncludeAttribute(typeof(ProfileBody_CommunicationNetwork_CANopen))] + [System.Xml.Serialization.XmlIncludeAttribute(typeof(ProfileBody_Device_CANopen))] + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] + public abstract partial class ProfileBody_DataType + { + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopen : ProfileBody_DataType + { + + private object[] itemsField; + + private string formatNameField; + + private string formatVersionField; + + private string fileNameField; + + private string fileCreatorField; + + private System.DateTime fileCreationDateField; + + private System.DateTime fileCreationTimeField; + + private bool fileCreationTimeFieldSpecified; + + private System.DateTime fileModificationDateField; + + private bool fileModificationDateFieldSpecified; + + private System.DateTime fileModificationTimeField; + + private bool fileModificationTimeFieldSpecified; + + private string fileModifiedByField; + + private string fileVersionField; + + private string supportedLanguagesField; + + public ProfileBody_CommunicationNetwork_CANopen() + { + this.formatNameField = "CANopen"; + this.formatVersionField = "1.0"; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("ApplicationLayers", typeof(ProfileBody_CommunicationNetwork_CANopenApplicationLayers))] + [System.Xml.Serialization.XmlElementAttribute("ExternalProfileHandle", typeof(ProfileHandle_DataType))] + [System.Xml.Serialization.XmlElementAttribute("NetworkManagement", typeof(ProfileBody_CommunicationNetwork_CANopenNetworkManagement))] + [System.Xml.Serialization.XmlElementAttribute("TransportLayers", typeof(ProfileBody_CommunicationNetwork_CANopenTransportLayers))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string formatName + { + get + { + return this.formatNameField; + } + set + { + this.formatNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string formatVersion + { + get + { + return this.formatVersionField; + } + set + { + this.formatVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileName + { + get + { + return this.fileNameField; + } + set + { + this.fileNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileCreator + { + get + { + return this.fileCreatorField; + } + set + { + this.fileCreatorField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] + public System.DateTime fileCreationDate + { + get + { + return this.fileCreationDateField; + } + set + { + this.fileCreationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] + public System.DateTime fileCreationTime + { + get + { + return this.fileCreationTimeField; + } + set + { + this.fileCreationTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool fileCreationTimeSpecified + { + get + { + return this.fileCreationTimeFieldSpecified; + } + set + { + this.fileCreationTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] + public System.DateTime fileModificationDate + { + get + { + return this.fileModificationDateField; + } + set + { + this.fileModificationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool fileModificationDateSpecified + { + get + { + return this.fileModificationDateFieldSpecified; + } + set + { + this.fileModificationDateFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] + public System.DateTime fileModificationTime + { + get + { + return this.fileModificationTimeField; + } + set + { + this.fileModificationTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool fileModificationTimeSpecified + { + get + { + return this.fileModificationTimeFieldSpecified; + } + set + { + this.fileModificationTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileModifiedBy + { + get + { + return this.fileModifiedByField; + } + set + { + this.fileModifiedByField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileVersion + { + get + { + return this.fileVersionField; + } + set + { + this.fileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] + public string supportedLanguages + { + get + { + return this.supportedLanguagesField; + } + set + { + this.supportedLanguagesField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayers + { + + private ProfileBody_CommunicationNetwork_CANopenApplicationLayersIdentity identityField; + + private CANopenObjectList cANopenObjectListField; + + private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy[] dummyUsageField; + + private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannel[] dynamicChannelsField; + + private string conformanceClassField; + + private string communicationEntityTypeField; + + public ProfileBody_CommunicationNetwork_CANopenApplicationLayers() + { + this.communicationEntityTypeField = "slave"; + } + + /// + public ProfileBody_CommunicationNetwork_CANopenApplicationLayersIdentity identity + { + get + { + return this.identityField; + } + set + { + this.identityField = value; + } + } + + /// + public CANopenObjectList CANopenObjectList + { + get + { + return this.cANopenObjectListField; + } + set + { + this.cANopenObjectListField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("dummy", IsNullable = false)] + public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy[] dummyUsage + { + get + { + return this.dummyUsageField; + } + set + { + this.dummyUsageField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("dynamicChannel", IsNullable = false)] + public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannel[] dynamicChannels + { + get + { + return this.dynamicChannelsField; + } + set + { + this.dynamicChannelsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string conformanceClass + { + get + { + return this.conformanceClassField; + } + set + { + this.conformanceClassField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] + [System.ComponentModel.DefaultValueAttribute("slave")] + public string communicationEntityType + { + get + { + return this.communicationEntityTypeField; + } + set + { + this.communicationEntityTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayersIdentity + { + + private vendorID vendorIDField; + + private deviceFamily deviceFamilyField; + + private productID productIDField; + + private version[] versionField; + + private System.DateTime buildDateField; + + private bool buildDateFieldSpecified; + + private specificationRevision specificationRevisionField; + + /// + public vendorID vendorID + { + get + { + return this.vendorIDField; + } + set + { + this.vendorIDField = value; + } + } + + /// + public deviceFamily deviceFamily + { + get + { + return this.deviceFamilyField; + } + set + { + this.deviceFamilyField = value; + } + } + + /// + public productID productID + { + get + { + return this.productIDField; + } + set + { + this.productIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("version")] + public version[] version + { + get + { + return this.versionField; + } + set + { + this.versionField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] + public System.DateTime buildDate + { + get + { + return this.buildDateField; + } + set + { + this.buildDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool buildDateSpecified + { + get + { + return this.buildDateFieldSpecified; + } + set + { + this.buildDateFieldSpecified = value; + } + } + + /// + public specificationRevision specificationRevision + { + get + { + return this.specificationRevisionField; + } + set + { + this.specificationRevisionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class vendorID + { + + private bool readOnlyField; + + private string valueField; + + public vendorID() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class deviceFamily + { + + private object[] itemsField; + + private bool readOnlyField; + + public deviceFamily() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class vendorTextDescription + { + + private string langField; + + private string uRIField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "language")] + public string lang + { + get + { + return this.langField; + } + set + { + this.langField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] + public string URI + { + get + { + return this.uRIField; + } + set + { + this.uRIField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class vendorTextDescriptionRef + { + + private string dictIDField; + + private string textIDField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string dictID + { + get + { + return this.dictIDField; + } + set + { + this.dictIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string textID + { + get + { + return this.textIDField; + } + set + { + this.textIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute(DataType = "anyURI")] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class vendorTextLabel + { + + private string langField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "language")] + public string lang + { + get + { + return this.langField; + } + set + { + this.langField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class vendorTextLabelRef + { + + private string dictIDField; + + private string textIDField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string dictID + { + get + { + return this.dictIDField; + } + set + { + this.dictIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string textID + { + get + { + return this.textIDField; + } + set + { + this.textIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute(DataType = "anyURI")] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class productID + { + + private bool readOnlyField; + + private string valueField; + + public productID() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class version + { + + private versionVersionType versionTypeField; + + private bool readOnlyField; + + private string valueField; + + public version() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public versionVersionType versionType + { + get + { + return this.versionTypeField; + } + set + { + this.versionTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum versionVersionType + { + + /// + SW, + + /// + FW, + + /// + HW, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class specificationRevision + { + + private bool readOnlyField; + + private string valueField; + + public specificationRevision() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class CANopenObjectList + { + + private CANopenObjectListCANopenObject[] cANopenObjectField; + + private uint mandatoryObjectsField; + + private bool mandatoryObjectsFieldSpecified; + + private uint optionalObjectsField; + + private bool optionalObjectsFieldSpecified; + + private uint manufacturerObjectsField; + + private bool manufacturerObjectsFieldSpecified; + + /// + [System.Xml.Serialization.XmlElementAttribute("CANopenObject")] + public CANopenObjectListCANopenObject[] CANopenObject + { + get + { + return this.cANopenObjectField; + } + set + { + this.cANopenObjectField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint mandatoryObjects + { + get + { + return this.mandatoryObjectsField; + } + set + { + this.mandatoryObjectsField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool mandatoryObjectsSpecified + { + get + { + return this.mandatoryObjectsFieldSpecified; + } + set + { + this.mandatoryObjectsFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint optionalObjects + { + get + { + return this.optionalObjectsField; + } + set + { + this.optionalObjectsField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool optionalObjectsSpecified + { + get + { + return this.optionalObjectsFieldSpecified; + } + set + { + this.optionalObjectsFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint manufacturerObjects + { + get + { + return this.manufacturerObjectsField; + } + set + { + this.manufacturerObjectsField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool manufacturerObjectsSpecified + { + get + { + return this.manufacturerObjectsFieldSpecified; + } + set + { + this.manufacturerObjectsFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class CANopenObjectListCANopenObject + { + + private CANopenObjectListCANopenObjectCANopenSubObject[] cANopenSubObjectField; + + private byte[] indexField; + + private string nameField; + + private byte objectTypeField; + + private byte[] dataTypeField; + + private string lowLimitField; + + private string highLimitField; + + private CANopenObjectListCANopenObjectAccessType accessTypeField; + + private bool accessTypeFieldSpecified; + + private string defaultValueField; + + private string actualValueField; + + private string denotationField; + + private string edseditor_extension_storagelocationField; + + private bool edseditor_extension_notifyonchangeField; + + private CANopenObjectListCANopenObjectPDOmapping pDOmappingField; + + private bool pDOmappingFieldSpecified; + + private byte[] objFlagsField; + + private string uniqueIDRefField; + + private byte subNumberField; + + private bool subNumberFieldSpecified; + + /// + [System.Xml.Serialization.XmlElementAttribute("CANopenSubObject")] + public CANopenObjectListCANopenObjectCANopenSubObject[] CANopenSubObject + { + get + { + return this.cANopenSubObjectField; + } + set + { + this.cANopenSubObjectField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] index + { + get + { + return this.indexField; + } + set + { + this.indexField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte objectType + { + get + { + return this.objectTypeField; + } + set + { + this.objectTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] dataType + { + get + { + return this.dataTypeField; + } + set + { + this.dataTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string lowLimit + { + get + { + return this.lowLimitField; + } + set + { + this.lowLimitField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string highLimit + { + get + { + return this.highLimitField; + } + set + { + this.highLimitField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public CANopenObjectListCANopenObjectAccessType accessType + { + get + { + return this.accessTypeField; + } + set + { + this.accessTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool accessTypeSpecified + { + get + { + return this.accessTypeFieldSpecified; + } + set + { + this.accessTypeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string defaultValue + { + get + { + return this.defaultValueField; + } + set + { + this.defaultValueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string actualValue + { + get + { + return this.actualValueField; + } + set + { + this.actualValueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string denotation + { + get + { + return this.denotationField; + } + set + { + this.denotationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string edseditor_extenstion_storagelocation + { + get + { + return this.edseditor_extension_storagelocationField; + } + set + { + this.edseditor_extension_storagelocationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool edseditor_extension_notifyonchange + { + get + { + return this.edseditor_extension_notifyonchangeField; + } + set + { + this.edseditor_extension_notifyonchangeField = value; + } + } + + + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public CANopenObjectListCANopenObjectPDOmapping PDOmapping + { + get + { + return this.pDOmappingField; + } + set + { + this.pDOmappingField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool PDOmappingSpecified + { + get + { + return this.pDOmappingFieldSpecified; + } + set + { + this.pDOmappingFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] objFlags + { + get + { + return this.objFlagsField; + } + set + { + this.objFlagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string uniqueIDRef + { + get + { + return this.uniqueIDRefField; + } + set + { + this.uniqueIDRefField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte subNumber + { + get + { + return this.subNumberField; + } + set + { + this.subNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool subNumberSpecified + { + get + { + return this.subNumberFieldSpecified; + } + set + { + this.subNumberFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class CANopenObjectListCANopenObjectCANopenSubObject + { + + private byte[] subIndexField; + + private string nameField; + + private byte objectTypeField; + + private byte[] dataTypeField; + + private string lowLimitField; + + private string highLimitField; + + private CANopenObjectListCANopenObjectCANopenSubObjectAccessType accessTypeField; + + private bool accessTypeFieldSpecified; + + private string defaultValueField; + + private string actualValueField; + + private string denotationField; + + private CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping pDOmappingField; + + private bool pDOmappingFieldSpecified; + + private byte[] objFlagsField; + + private string uniqueIDRefField; + + private bool edseditor_extension_notifyonchangeField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool edseditor_extension_notifyonchange + { + get + { + return this.edseditor_extension_notifyonchangeField; + } + set + { + this.edseditor_extension_notifyonchangeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] subIndex + { + get + { + return this.subIndexField; + } + set + { + this.subIndexField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte objectType + { + get + { + return this.objectTypeField; + } + set + { + this.objectTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] dataType + { + get + { + return this.dataTypeField; + } + set + { + this.dataTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string lowLimit + { + get + { + return this.lowLimitField; + } + set + { + this.lowLimitField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string highLimit + { + get + { + return this.highLimitField; + } + set + { + this.highLimitField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public CANopenObjectListCANopenObjectCANopenSubObjectAccessType accessType + { + get + { + return this.accessTypeField; + } + set + { + this.accessTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool accessTypeSpecified + { + get + { + return this.accessTypeFieldSpecified; + } + set + { + this.accessTypeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string defaultValue + { + get + { + return this.defaultValueField; + } + set + { + this.defaultValueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string actualValue + { + get + { + return this.actualValueField; + } + set + { + this.actualValueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string denotation + { + get + { + return this.denotationField; + } + set + { + this.denotationField = value; + } + } + + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping PDOmapping + { + get + { + return this.pDOmappingField; + } + set + { + this.pDOmappingField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool PDOmappingSpecified + { + get + { + return this.pDOmappingFieldSpecified; + } + set + { + this.pDOmappingFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] objFlags + { + get + { + return this.objFlagsField; + } + set + { + this.objFlagsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string uniqueIDRef + { + get + { + return this.uniqueIDRefField; + } + set + { + this.uniqueIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum CANopenObjectListCANopenObjectCANopenSubObjectAccessType + { + + /// + ro, + + /// + wo, + + /// + rw, + + /// + @const, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping + { + + /// + no, + + /// + @default, + + /// + optional, + + /// + TPDO, + + /// + RPDO, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum CANopenObjectListCANopenObjectAccessType + { + + /// + ro, + + /// + wo, + + /// + rw, + + /// + @const, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum CANopenObjectListCANopenObjectPDOmapping + { + + /// + no, + + /// + @default, + + /// + optional, + + /// + TPDO, + + /// + RPDO, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy + { + + private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry entryField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry entry + { + get + { + return this.entryField; + } + set + { + this.entryField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry + { + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0001=0")] + Dummy00010, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0002=0")] + Dummy00020, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0003=0")] + Dummy00030, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0004=0")] + Dummy00040, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0005=0")] + Dummy00050, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0006=0")] + Dummy00060, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0007=0")] + Dummy00070, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0001=1")] + Dummy00011, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0002=1")] + Dummy00021, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0003=1")] + Dummy00031, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0004=1")] + Dummy00041, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0005=1")] + Dummy00051, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0006=1")] + Dummy00061, + + /// + [System.Xml.Serialization.XmlEnumAttribute("Dummy0007=1")] + Dummy00071, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannel + { + + private byte[] dataTypeField; + + private ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannelAccessType accessTypeField; + + private byte[] startIndexField; + + private byte[] endIndexField; + + private uint maxNumberField; + + private byte[] addressOffsetField; + + private byte bitAlignmentField; + + private bool bitAlignmentFieldSpecified; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] dataType + { + get + { + return this.dataTypeField; + } + set + { + this.dataTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannelAccessType accessType + { + get + { + return this.accessTypeField; + } + set + { + this.accessTypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] startIndex + { + get + { + return this.startIndexField; + } + set + { + this.startIndexField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] endIndex + { + get + { + return this.endIndexField; + } + set + { + this.endIndexField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint maxNumber + { + get + { + return this.maxNumberField; + } + set + { + this.maxNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "hexBinary")] + public byte[] addressOffset + { + get + { + return this.addressOffsetField; + } + set + { + this.addressOffsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte bitAlignment + { + get + { + return this.bitAlignmentField; + } + set + { + this.bitAlignmentField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool bitAlignmentSpecified + { + get + { + return this.bitAlignmentFieldSpecified; + } + set + { + this.bitAlignmentFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum ProfileBody_CommunicationNetwork_CANopenApplicationLayersDynamicChannelAccessType + { + + /// + readOnly, + + /// + writeOnly, + + /// + readWriteOutput, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagement + { + + private ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures cANopenGeneralFeaturesField; + + private ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures cANopenMasterFeaturesField; + + private ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning deviceCommissioningField; + + /// + public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures CANopenGeneralFeatures + { + get + { + return this.cANopenGeneralFeaturesField; + } + set + { + this.cANopenGeneralFeaturesField = value; + } + } + + /// + public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures CANopenMasterFeatures + { + get + { + return this.cANopenMasterFeaturesField; + } + set + { + this.cANopenMasterFeaturesField = value; + } + } + + /// + public ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning deviceCommissioning + { + get + { + return this.deviceCommissioningField; + } + set + { + this.deviceCommissioningField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures + { + + private bool groupMessagingField; + + private byte dynamicChannelsField; + + private bool selfStartingDeviceField; + + private bool sDORequestingDeviceField; + + private byte granularityField; + + private ushort nrOfRxPDOField; + + private ushort nrOfTxPDOField; + + private bool ngMasterField; + private bool ngSlaveField; + private ushort NrOfNG_MonitoredNodesField; + private bool bootUpSlaveField; + + private bool layerSettingServiceSlaveField; + + public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures() + { + this.groupMessagingField = false; + this.dynamicChannelsField = ((byte)(0)); + this.selfStartingDeviceField = false; + this.sDORequestingDeviceField = false; + this.nrOfRxPDOField = ((ushort)(0)); + this.nrOfTxPDOField = ((ushort)(0)); + this.ngMasterField = false; + this.ngSlaveField = false; + this.NrOfNG_MonitoredNodesField = ((ushort)(0)); + this.bootUpSlaveField = false; + this.layerSettingServiceSlaveField = false; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool groupMessaging + { + get + { + return this.groupMessagingField; + } + set + { + this.groupMessagingField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(typeof(byte), "0")] + public byte dynamicChannels + { + get + { + return this.dynamicChannelsField; + } + set + { + this.dynamicChannelsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool selfStartingDevice + { + get + { + return this.selfStartingDeviceField; + } + set + { + this.selfStartingDeviceField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool SDORequestingDevice + { + get + { + return this.sDORequestingDeviceField; + } + set + { + this.sDORequestingDeviceField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte granularity + { + get + { + return this.granularityField; + } + set + { + this.granularityField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] + public ushort nrOfRxPDO + { + get + { + return this.nrOfRxPDOField; + } + set + { + this.nrOfRxPDOField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] + public ushort nrOfTxPDO + { + get + { + return this.nrOfTxPDOField; + } + set + { + this.nrOfTxPDOField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool bootUpSlave + { + get + { + return this.bootUpSlaveField; + } + set + { + this.bootUpSlaveField = value; + } + } + + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ngSlave + { + get + { + return this.ngSlaveField; + } + set + { + this.ngSlaveField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool ngMaster + { + get + { + return this.ngMasterField; + } + set + { + this.ngMasterField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(typeof(ushort), "0")] + public ushort NrOfNG_MonitoredNodes + { + get + { + return this.NrOfNG_MonitoredNodesField; + } + set + { + this.NrOfNG_MonitoredNodesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool layerSettingServiceSlave + { + get + { + return this.layerSettingServiceSlaveField; + } + set + { + this.layerSettingServiceSlaveField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures + { + + private bool bootUpMasterField; + + private bool flyingMasterField; + + private bool sDOManagerField; + + private bool configurationManagerField; + + private bool layerSettingServiceMasterField; + + public ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures() + { + this.bootUpMasterField = false; + this.flyingMasterField = false; + this.sDOManagerField = false; + this.configurationManagerField = false; + this.layerSettingServiceMasterField = false; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool bootUpMaster + { + get + { + return this.bootUpMasterField; + } + set + { + this.bootUpMasterField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool flyingMaster + { + get + { + return this.flyingMasterField; + } + set + { + this.flyingMasterField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool SDOManager + { + get + { + return this.sDOManagerField; + } + set + { + this.sDOManagerField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool configurationManager + { + get + { + return this.configurationManagerField; + } + set + { + this.configurationManagerField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool layerSettingServiceMaster + { + get + { + return this.layerSettingServiceMasterField; + } + set + { + this.layerSettingServiceMasterField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning + { + + private byte nodeIDField; + + private string nodeNameField; + + private string actualBaudRateField; + + private ulong networkNumberField; + + private string networkNameField; + + private bool cANopenManagerField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public byte NodeID + { + get + { + return this.nodeIDField; + } + set + { + this.nodeIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string nodeName + { + get + { + return this.nodeNameField; + } + set + { + this.nodeNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string actualBaudRate + { + get + { + return this.actualBaudRateField; + } + set + { + this.actualBaudRateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ulong networkNumber + { + get + { + return this.networkNumberField; + } + set + { + this.networkNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string networkName + { + get + { + return this.networkNameField; + } + set + { + this.networkNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public bool CANopenManager + { + get + { + return this.cANopenManagerField; + } + set + { + this.cANopenManagerField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayers + { + + private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayer physicalLayerField; + + /// + public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayer PhysicalLayer + { + get + { + return this.physicalLayerField; + } + set + { + this.physicalLayerField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayer + { + + private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate baudRateField; + + /// + public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate baudRate + { + get + { + return this.baudRateField; + } + set + { + this.baudRateField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate + { + + private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate[] supportedBaudRateField; + + private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue defaultValueField; + + public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate() + { + this.defaultValueField = ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue.Item250Kbps; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("supportedBaudRate")] + public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate[] supportedBaudRate + { + get + { + return this.supportedBaudRateField; + } + set + { + this.supportedBaudRateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue.Item250Kbps)] + public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue defaultValue + { + get + { + return this.defaultValueField; + } + set + { + this.defaultValueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate + { + + private ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue + { + + /// + [System.Xml.Serialization.XmlEnumAttribute("10 Kbps")] + Item10Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("20 Kbps")] + Item20Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("50 Kbps")] + Item50Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("100 Kbps")] + Item100Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("125 Kbps")] + Item125Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("250 Kbps")] + Item250Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("500 Kbps")] + Item500Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("800 Kbps")] + Item800Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("1000 Kbps")] + Item1000Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("auto-baudRate")] + autobaudRate, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateDefaultValue + { + + /// + [System.Xml.Serialization.XmlEnumAttribute("10 Kbps")] + Item10Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("20 Kbps")] + Item20Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("50 Kbps")] + Item50Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("100 Kbps")] + Item100Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("125 Kbps")] + Item125Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("250 Kbps")] + Item250Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("500 Kbps")] + Item500Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("800 Kbps")] + Item800Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("1000 Kbps")] + Item1000Kbps, + + /// + [System.Xml.Serialization.XmlEnumAttribute("auto-baudRate")] + autobaudRate, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0")] + public partial class ProfileBody_Device_CANopen : ProfileBody_DataType + { + + private DeviceIdentity deviceIdentityField; + + private DeviceManager deviceManagerField; + + private DeviceFunction[] deviceFunctionField; + + private ApplicationProcess[] applicationProcessField; + + private ProfileHandle_DataType[] externalProfileHandleField; + + private string formatNameField; + + private string formatVersionField; + + private string fileNameField; + + private string fileCreatorField; + + private System.DateTime fileCreationDateField; + + private System.DateTime fileCreationTimeField; + + private bool fileCreationTimeFieldSpecified; + + private System.DateTime fileModificationDateField; + + private bool fileModificationDateFieldSpecified; + + private System.DateTime fileModificationTimeField; + + private bool fileModificationTimeFieldSpecified; + + private string fileModifiedByField; + + private string fileVersionField; + + private string supportedLanguagesField; + + private ProfileBody_Device_CANopenDeviceClass deviceClassField; + + private bool deviceClassFieldSpecified; + + public ProfileBody_Device_CANopen() + { + this.formatNameField = "CANopen"; + this.formatVersionField = "1.0"; + } + + /// + public DeviceIdentity DeviceIdentity + { + get + { + return this.deviceIdentityField; + } + set + { + this.deviceIdentityField = value; + } + } + + /// + public DeviceManager DeviceManager + { + get + { + return this.deviceManagerField; + } + set + { + this.deviceManagerField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("DeviceFunction")] + public DeviceFunction[] DeviceFunction + { + get + { + return this.deviceFunctionField; + } + set + { + this.deviceFunctionField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("ApplicationProcess")] + public ApplicationProcess[] ApplicationProcess + { + get + { + return this.applicationProcessField; + } + set + { + this.applicationProcessField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("ExternalProfileHandle")] + public ProfileHandle_DataType[] ExternalProfileHandle + { + get + { + return this.externalProfileHandleField; + } + set + { + this.externalProfileHandleField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string formatName + { + get + { + return this.formatNameField; + } + set + { + this.formatNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string formatVersion + { + get + { + return this.formatVersionField; + } + set + { + this.formatVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileName + { + get + { + return this.fileNameField; + } + set + { + this.fileNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileCreator + { + get + { + return this.fileCreatorField; + } + set + { + this.fileCreatorField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] + public System.DateTime fileCreationDate + { + get + { + return this.fileCreationDateField; + } + set + { + this.fileCreationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] + public System.DateTime fileCreationTime + { + get + { + return this.fileCreationTimeField; + } + set + { + this.fileCreationTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool fileCreationTimeSpecified + { + get + { + return this.fileCreationTimeFieldSpecified; + } + set + { + this.fileCreationTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] + public System.DateTime fileModificationDate + { + get + { + return this.fileModificationDateField; + } + set + { + this.fileModificationDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool fileModificationDateSpecified + { + get + { + return this.fileModificationDateFieldSpecified; + } + set + { + this.fileModificationDateFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "time")] + public System.DateTime fileModificationTime + { + get + { + return this.fileModificationTimeField; + } + set + { + this.fileModificationTimeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool fileModificationTimeSpecified + { + get + { + return this.fileModificationTimeFieldSpecified; + } + set + { + this.fileModificationTimeFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileModifiedBy + { + get + { + return this.fileModifiedByField; + } + set + { + this.fileModifiedByField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string fileVersion + { + get + { + return this.fileVersionField; + } + set + { + this.fileVersionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] + public string supportedLanguages + { + get + { + return this.supportedLanguagesField; + } + set + { + this.supportedLanguagesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public ProfileBody_Device_CANopenDeviceClass deviceClass + { + get + { + return this.deviceClassField; + } + set + { + this.deviceClassField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool deviceClassSpecified + { + get + { + return this.deviceClassFieldSpecified; + } + set + { + this.deviceClassFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class DeviceIdentity + { + + private vendorName vendorNameField; + + private vendorID vendorIDField; + + private vendorText vendorTextField; + + private deviceFamily deviceFamilyField; + + private productFamily productFamilyField; + + private productName productNameField; + + private productID productIDField; + + private productText productTextField; + + private orderNumber[] orderNumberField; + + private version[] versionField; + + private System.DateTime buildDateField; + + private bool buildDateFieldSpecified; + + private specificationRevision specificationRevisionField; + + private instanceName instanceNameField; + + /// + public vendorName vendorName + { + get + { + return this.vendorNameField; + } + set + { + this.vendorNameField = value; + } + } + + /// + public vendorID vendorID + { + get + { + return this.vendorIDField; + } + set + { + this.vendorIDField = value; + } + } + + /// + public vendorText vendorText + { + get + { + return this.vendorTextField; + } + set + { + this.vendorTextField = value; + } + } + + /// + public deviceFamily deviceFamily + { + get + { + return this.deviceFamilyField; + } + set + { + this.deviceFamilyField = value; + } + } + + /// + public productFamily productFamily + { + get + { + return this.productFamilyField; + } + set + { + this.productFamilyField = value; + } + } + + /// + public productName productName + { + get + { + return this.productNameField; + } + set + { + this.productNameField = value; + } + } + + /// + public productID productID + { + get + { + return this.productIDField; + } + set + { + this.productIDField = value; + } + } + + /// + public productText productText + { + get + { + return this.productTextField; + } + set + { + this.productTextField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("orderNumber")] + public orderNumber[] orderNumber + { + get + { + return this.orderNumberField; + } + set + { + this.orderNumberField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("version")] + public version[] version + { + get + { + return this.versionField; + } + set + { + this.versionField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute(DataType = "date")] + public System.DateTime buildDate + { + get + { + return this.buildDateField; + } + set + { + this.buildDateField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool buildDateSpecified + { + get + { + return this.buildDateFieldSpecified; + } + set + { + this.buildDateFieldSpecified = value; + } + } + + /// + public specificationRevision specificationRevision + { + get + { + return this.specificationRevisionField; + } + set + { + this.specificationRevisionField = value; + } + } + + /// + public instanceName instanceName + { + get + { + return this.instanceNameField; + } + set + { + this.instanceNameField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class vendorName + { + + private bool readOnlyField; + + private string valueField; + + public vendorName() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class vendorText + { + + private object[] itemsField; + + private bool readOnlyField; + + public vendorText() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class productFamily + { + + private bool readOnlyField; + + private string valueField; + + public productFamily() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class productName + { + + private bool readOnlyField; + + private string valueField; + + public productName() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class productText + { + + private object[] itemsField; + + private bool readOnlyField; + + public productText() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class orderNumber + { + + private bool readOnlyField; + + private string valueField; + + public orderNumber() + { + this.readOnlyField = true; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(true)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class instanceName + { + + private bool readOnlyField; + + private string valueField; + + public instanceName() + { + this.readOnlyField = false; + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool readOnly + { + get + { + return this.readOnlyField; + } + set + { + this.readOnlyField = value; + } + } + + /// + [System.Xml.Serialization.XmlTextAttribute()] + public string Value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class DeviceManager + { + + private indicatorList indicatorListField; + + /// + public indicatorList indicatorList + { + get + { + return this.indicatorListField; + } + set + { + this.indicatorListField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class indicatorList + { + + private LEDList lEDListField; + + /// + public LEDList LEDList + { + get + { + return this.lEDListField; + } + set + { + this.lEDListField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class LEDList + { + + private LED[] lEDField; + + private combinedState[] combinedStateField; + + /// + [System.Xml.Serialization.XmlElementAttribute("LED")] + public LED[] LED + { + get + { + return this.lEDField; + } + set + { + this.lEDField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("combinedState")] + public combinedState[] combinedState + { + get + { + return this.combinedStateField; + } + set + { + this.combinedStateField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class LED + { + + private object[] itemsField; + + private LEDstate[] lEDstateField; + + private LEDLEDcolors lEDcolorsField; + + private LEDLEDtype lEDtypeField; + + private bool lEDtypeFieldSpecified; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("LEDstate")] + public LEDstate[] LEDstate + { + get + { + return this.lEDstateField; + } + set + { + this.lEDstateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public LEDLEDcolors LEDcolors + { + get + { + return this.lEDcolorsField; + } + set + { + this.lEDcolorsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public LEDLEDtype LEDtype + { + get + { + return this.lEDtypeField; + } + set + { + this.lEDtypeField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool LEDtypeSpecified + { + get + { + return this.lEDtypeFieldSpecified; + } + set + { + this.lEDtypeFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class LEDstate + { + + private object[] itemsField; + + private string uniqueIDField; + + private LEDstateState stateField; + + private LEDstateLEDcolor lEDcolorField; + + private uint flashingPeriodField; + + private bool flashingPeriodFieldSpecified; + + private byte impulsWidthField; + + private byte numberOfImpulsesField; + + public LEDstate() + { + this.impulsWidthField = ((byte)(50)); + this.numberOfImpulsesField = ((byte)(1)); + } + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public LEDstateState state + { + get + { + return this.stateField; + } + set + { + this.stateField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public LEDstateLEDcolor LEDcolor + { + get + { + return this.lEDcolorField; + } + set + { + this.lEDcolorField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint flashingPeriod + { + get + { + return this.flashingPeriodField; + } + set + { + this.flashingPeriodField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool flashingPeriodSpecified + { + get + { + return this.flashingPeriodFieldSpecified; + } + set + { + this.flashingPeriodFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(typeof(byte), "50")] + public byte impulsWidth + { + get + { + return this.impulsWidthField; + } + set + { + this.impulsWidthField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(typeof(byte), "1")] + public byte numberOfImpulses + { + get + { + return this.numberOfImpulsesField; + } + set + { + this.numberOfImpulsesField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum LEDstateState + { + + /// + on, + + /// + off, + + /// + flashing, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum LEDstateLEDcolor + { + + /// + green, + + /// + amber, + + /// + red, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum LEDLEDcolors + { + + /// + monocolor, + + /// + bicolor, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum LEDLEDtype + { + + /// + IO, + + /// + device, + + /// + communication, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class combinedState + { + + private object[] itemsField; + + private combinedStateLEDstateRef[] lEDstateRefField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("LEDstateRef")] + public combinedStateLEDstateRef[] LEDstateRef + { + get + { + return this.lEDstateRefField; + } + set + { + this.lEDstateRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class combinedStateLEDstateRef + { + + private string stateIDRefField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string stateIDRef + { + get + { + return this.stateIDRefField; + } + set + { + this.stateIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class DeviceFunction + { + + private capabilities capabilitiesField; + + private picture[] picturesListField; + + private dictionary[] dictionaryListField; + + /// + public capabilities capabilities + { + get + { + return this.capabilitiesField; + } + set + { + this.capabilitiesField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("picture", IsNullable = false)] + public picture[] picturesList + { + get + { + return this.picturesListField; + } + set + { + this.picturesListField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("dictionary", IsNullable = false)] + public dictionary[] dictionaryList + { + get + { + return this.dictionaryListField; + } + set + { + this.dictionaryListField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class capabilities + { + + private characteristicsList[] characteristicsListField; + + private compliantWith[] standardComplianceListField; + + /// + [System.Xml.Serialization.XmlElementAttribute("characteristicsList")] + public characteristicsList[] characteristicsList + { + get + { + return this.characteristicsListField; + } + set + { + this.characteristicsListField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("compliantWith", IsNullable = false)] + public compliantWith[] standardComplianceList + { + get + { + return this.standardComplianceListField; + } + set + { + this.standardComplianceListField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class characteristicsList + { + + private characteristicsListCategory categoryField; + + private characteristic[] characteristicField; + + /// + public characteristicsListCategory category + { + get + { + return this.categoryField; + } + set + { + this.categoryField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("characteristic")] + public characteristic[] characteristic + { + get + { + return this.characteristicField; + } + set + { + this.characteristicField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class characteristicsListCategory + { + + private object[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class characteristic + { + + private characteristicName characteristicNameField; + + private characteristicContent[] characteristicContentField; + + /// + public characteristicName characteristicName + { + get + { + return this.characteristicNameField; + } + set + { + this.characteristicNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("characteristicContent")] + public characteristicContent[] characteristicContent + { + get + { + return this.characteristicContentField; + } + set + { + this.characteristicContentField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class characteristicName + { + + private object[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class characteristicContent + { + + private object[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class compliantWith + { + + private object[] itemsField; + + private string nameField; + + private compliantWithRange rangeField; + + public compliantWith() + { + this.rangeField = compliantWithRange.international; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(compliantWithRange.international)] + public compliantWithRange range + { + get + { + return this.rangeField; + } + set + { + this.rangeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum compliantWithRange + { + + /// + international, + + /// + @internal, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class picture + { + + private object[] itemsField; + + private string uRIField; + + private uint numberField; + + private bool numberFieldSpecified; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] + public string URI + { + get + { + return this.uRIField; + } + set + { + this.uRIField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public uint number + { + get + { + return this.numberField; + } + set + { + this.numberField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool numberSpecified + { + get + { + return this.numberFieldSpecified; + } + set + { + this.numberFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class dictionary + { + + private file fileField; + + private string langField; + + private string dictIDField; + + /// + public file file + { + get + { + return this.fileField; + } + set + { + this.fileField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "language")] + public string lang + { + get + { + return this.langField; + } + set + { + this.langField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string dictID + { + get + { + return this.dictIDField; + } + set + { + this.dictIDField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class file + { + + private string uRIField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] + public string URI + { + get + { + return this.uRIField; + } + set + { + this.uRIField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class ApplicationProcess + { + + private dataTypeList dataTypeListField; + + private functionType[] functionTypeListField; + + private functionInstanceList functionInstanceListField; + + private templateList templateListField; + + private parameter[] parameterListField; + + private parameterGroup[] parameterGroupListField; + + /// + public dataTypeList dataTypeList + { + get + { + return this.dataTypeListField; + } + set + { + this.dataTypeListField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("functionType", IsNullable = false)] + public functionType[] functionTypeList + { + get + { + return this.functionTypeListField; + } + set + { + this.functionTypeListField = value; + } + } + + /// + public functionInstanceList functionInstanceList + { + get + { + return this.functionInstanceListField; + } + set + { + this.functionInstanceListField = value; + } + } + + /// + public templateList templateList + { + get + { + return this.templateListField; + } + set + { + this.templateListField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("parameter", IsNullable = false)] + public parameter[] parameterList + { + get + { + return this.parameterListField; + } + set + { + this.parameterListField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("parameterGroup", IsNullable = false)] + public parameterGroup[] parameterGroupList + { + get + { + return this.parameterGroupListField; + } + set + { + this.parameterGroupListField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class dataTypeList + { + + private array[] arrayField; + + private @struct[] structField; + + private @enum[] enumField; + + private derived[] derivedField; + + /// + [System.Xml.Serialization.XmlElementAttribute("array")] + public array[] array + { + get + { + return this.arrayField; + } + set + { + this.arrayField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("struct")] + public @struct[] @struct + { + get + { + return this.structField; + } + set + { + this.structField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("enum")] + public @enum[] @enum + { + get + { + return this.enumField; + } + set + { + this.enumField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("derived")] + public derived[] derived + { + get + { + return this.derivedField; + } + set + { + this.derivedField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class array + { + + private object[] itemsField; + + private subrange[] subrangeField; + + private object itemField; + + private ItemChoiceType itemElementNameField; + + private string nameField; + + private string uniqueIDField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("subrange")] + public subrange[] subrange + { + get + { + return this.subrangeField; + } + set + { + this.subrangeField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] + [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] + public object Item + { + get + { + return this.itemField; + } + set + { + this.itemField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public ItemChoiceType ItemElementName + { + get + { + return this.itemElementNameField; + } + set + { + this.itemElementNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class subrange + { + + private long lowerLimitField; + + private long upperLimitField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public long lowerLimit + { + get + { + return this.lowerLimitField; + } + set + { + this.lowerLimitField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public long upperLimit + { + get + { + return this.upperLimitField; + } + set + { + this.upperLimitField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class dataTypeIDRef + { + + private string uniqueIDRefField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string uniqueIDRef + { + get + { + return this.uniqueIDRefField; + } + set + { + this.uniqueIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] + public enum ItemChoiceType + { + + /// + BITSTRING, + + /// + BOOL, + + /// + BYTE, + + /// + CHAR, + + /// + DINT, + + /// + DWORD, + + /// + INT, + + /// + LINT, + + /// + LREAL, + + /// + LWORD, + + /// + REAL, + + /// + SINT, + + /// + STRING, + + /// + UDINT, + + /// + UINT, + + /// + ULINT, + + /// + USINT, + + /// + WORD, + + /// + WSTRING, + + /// + dataTypeIDRef, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class @struct + { + + private object[] itemsField; + + private varDeclaration[] varDeclarationField; + + private string nameField; + + private string uniqueIDField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] + public varDeclaration[] varDeclaration + { + get + { + return this.varDeclarationField; + } + set + { + this.varDeclarationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class varDeclaration + { + + private object[] itemsField; + + private object itemField; + + private ItemChoiceType1 itemElementNameField; + + private string nameField; + + private string uniqueIDField; + + private string sizeField; + + private string initialValueField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] + [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] + public object Item + { + get + { + return this.itemField; + } + set + { + this.itemField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public ItemChoiceType1 ItemElementName + { + get + { + return this.itemElementNameField; + } + set + { + this.itemElementNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string size + { + get + { + return this.sizeField; + } + set + { + this.sizeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string initialValue + { + get + { + return this.initialValueField; + } + set + { + this.initialValueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] + public enum ItemChoiceType1 + { + + /// + BITSTRING, + + /// + BOOL, + + /// + BYTE, + + /// + CHAR, + + /// + DINT, + + /// + DWORD, + + /// + INT, + + /// + LINT, + + /// + LREAL, + + /// + LWORD, + + /// + REAL, + + /// + SINT, + + /// + STRING, + + /// + UDINT, + + /// + UINT, + + /// + ULINT, + + /// + USINT, + + /// + WORD, + + /// + WSTRING, + + /// + dataTypeIDRef, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class @enum + { + + private object[] itemsField; + + private enumValue[] enumValueField; + + private object bOOLField; + + private object bITSTRINGField; + + private object bYTEField; + + private object cHARField; + + private object wORDField; + + private object dWORDField; + + private object lWORDField; + + private object sINTField; + + private object iNTField; + + private object dINTField; + + private object lINTField; + + private object uSINTField; + + private object uINTField; + + private object uDINTField; + + private object uLINTField; + + private object rEALField; + + private object lREALField; + + private object sTRINGField; + + private object wSTRINGField; + + private string nameField; + + private string uniqueIDField; + + private string sizeField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("enumValue")] + public enumValue[] enumValue + { + get + { + return this.enumValueField; + } + set + { + this.enumValueField = value; + } + } + + /// + public object BOOL + { + get + { + return this.bOOLField; + } + set + { + this.bOOLField = value; + } + } + + /// + public object BITSTRING + { + get + { + return this.bITSTRINGField; + } + set + { + this.bITSTRINGField = value; + } + } + + /// + public object BYTE + { + get + { + return this.bYTEField; + } + set + { + this.bYTEField = value; + } + } + + /// + public object CHAR + { + get + { + return this.cHARField; + } + set + { + this.cHARField = value; + } + } + + /// + public object WORD + { + get + { + return this.wORDField; + } + set + { + this.wORDField = value; + } + } + + /// + public object DWORD + { + get + { + return this.dWORDField; + } + set + { + this.dWORDField = value; + } + } + + /// + public object LWORD + { + get + { + return this.lWORDField; + } + set + { + this.lWORDField = value; + } + } + + /// + public object SINT + { + get + { + return this.sINTField; + } + set + { + this.sINTField = value; + } + } + + /// + public object INT + { + get + { + return this.iNTField; + } + set + { + this.iNTField = value; + } + } + + /// + public object DINT + { + get + { + return this.dINTField; + } + set + { + this.dINTField = value; + } + } + + /// + public object LINT + { + get + { + return this.lINTField; + } + set + { + this.lINTField = value; + } + } + + /// + public object USINT + { + get + { + return this.uSINTField; + } + set + { + this.uSINTField = value; + } + } + + /// + public object UINT + { + get + { + return this.uINTField; + } + set + { + this.uINTField = value; + } + } + + /// + public object UDINT + { + get + { + return this.uDINTField; + } + set + { + this.uDINTField = value; + } + } + + /// + public object ULINT + { + get + { + return this.uLINTField; + } + set + { + this.uLINTField = value; + } + } + + /// + public object REAL + { + get + { + return this.rEALField; + } + set + { + this.rEALField = value; + } + } + + /// + public object LREAL + { + get + { + return this.lREALField; + } + set + { + this.lREALField = value; + } + } + + /// + public object STRING + { + get + { + return this.sTRINGField; + } + set + { + this.sTRINGField = value; + } + } + + /// + public object WSTRING + { + get + { + return this.wSTRINGField; + } + set + { + this.wSTRINGField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string size + { + get + { + return this.sizeField; + } + set + { + this.sizeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class enumValue + { + + private object[] itemsField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class derived + { + + private object[] itemsField; + + private count countField; + + private object itemField; + + private ItemChoiceType2 itemElementNameField; + + private string nameField; + + private string uniqueIDField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + public count count + { + get + { + return this.countField; + } + set + { + this.countField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] + [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] + public object Item + { + get + { + return this.itemField; + } + set + { + this.itemField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public ItemChoiceType2 ItemElementName + { + get + { + return this.itemElementNameField; + } + set + { + this.itemElementNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class count + { + + private object[] itemsField; + + private defaultValue defaultValueField; + + private allowedValues allowedValuesField; + + private string uniqueIDField; + + private countAccess accessField; + + public count() + { + this.accessField = countAccess.read; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + public defaultValue defaultValue + { + get + { + return this.defaultValueField; + } + set + { + this.defaultValueField = value; + } + } + + /// + public allowedValues allowedValues + { + get + { + return this.allowedValuesField; + } + set + { + this.allowedValuesField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(countAccess.read)] + public countAccess access + { + get + { + return this.accessField; + } + set + { + this.accessField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class defaultValue + { + + private object[] itemsField; + + private string valueField; + + private string offsetField; + + private string multiplierField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class allowedValues + { + + private value[] valueField; + + private range[] rangeField; + + private string templateIDRefField; + + /// + [System.Xml.Serialization.XmlElementAttribute("value")] + public value[] value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("range")] + public range[] range + { + get + { + return this.rangeField; + } + set + { + this.rangeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string templateIDRef + { + get + { + return this.templateIDRefField; + } + set + { + this.templateIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class value + { + + private object[] itemsField; + + private string value1Field; + + private string offsetField; + + private string multiplierField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute("value")] + public string value1 + { + get + { + return this.value1Field; + } + set + { + this.value1Field = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class range + { + + private rangeMinValue minValueField; + + private rangeMaxValue maxValueField; + + private rangeStep stepField; + + /// + public rangeMinValue minValue + { + get + { + return this.minValueField; + } + set + { + this.minValueField = value; + } + } + + /// + public rangeMaxValue maxValue + { + get + { + return this.maxValueField; + } + set + { + this.maxValueField = value; + } + } + + /// + public rangeStep step + { + get + { + return this.stepField; + } + set + { + this.stepField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class rangeMinValue + { + + private object[] itemsField; + + private string valueField; + + private string offsetField; + + private string multiplierField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class rangeMaxValue + { + + private object[] itemsField; + + private string valueField; + + private string offsetField; + + private string multiplierField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public partial class rangeStep + { + + private object[] itemsField; + + private string valueField; + + private string offsetField; + + private string multiplierField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum countAccess + { + + /// + @const, + + /// + read, + + /// + write, + + /// + readWrite, + + /// + noAccess, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] + public enum ItemChoiceType2 + { + + /// + BITSTRING, + + /// + BOOL, + + /// + BYTE, + + /// + CHAR, + + /// + DINT, + + /// + DWORD, + + /// + INT, + + /// + LINT, + + /// + LREAL, + + /// + LWORD, + + /// + REAL, + + /// + SINT, + + /// + STRING, + + /// + UDINT, + + /// + UINT, + + /// + ULINT, + + /// + USINT, + + /// + WORD, + + /// + WSTRING, + + /// + dataTypeIDRef, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class functionType + { + + private object[] itemsField; + + private versionInfo[] versionInfoField; + + private interfaceList interfaceListField; + + private functionInstanceList functionInstanceListField; + + private string nameField; + + private string uniqueIDField; + + private string packageField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("versionInfo")] + public versionInfo[] versionInfo + { + get + { + return this.versionInfoField; + } + set + { + this.versionInfoField = value; + } + } + + /// + public interfaceList interfaceList + { + get + { + return this.interfaceListField; + } + set + { + this.interfaceListField = value; + } + } + + /// + public functionInstanceList functionInstanceList + { + get + { + return this.functionInstanceListField; + } + set + { + this.functionInstanceListField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string package + { + get + { + return this.packageField; + } + set + { + this.packageField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class versionInfo + { + + private object[] itemsField; + + private string organizationField; + + private string versionField; + + private string authorField; + + private System.DateTime dateField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string organization + { + get + { + return this.organizationField; + } + set + { + this.organizationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string version + { + get + { + return this.versionField; + } + set + { + this.versionField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string author + { + get + { + return this.authorField; + } + set + { + this.authorField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "date")] + public System.DateTime date + { + get + { + return this.dateField; + } + set + { + this.dateField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class interfaceList + { + + private varDeclaration[] inputVarsField; + + private varDeclaration[] outputVarsField; + + private varDeclaration[] configVarsField; + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("varDeclaration", IsNullable = false)] + public varDeclaration[] inputVars + { + get + { + return this.inputVarsField; + } + set + { + this.inputVarsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("varDeclaration", IsNullable = false)] + public varDeclaration[] outputVars + { + get + { + return this.outputVarsField; + } + set + { + this.outputVarsField = value; + } + } + + /// + [System.Xml.Serialization.XmlArrayItemAttribute("varDeclaration", IsNullable = false)] + public varDeclaration[] configVars + { + get + { + return this.configVarsField; + } + set + { + this.configVarsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class functionInstanceList + { + + private functionInstance[] functionInstanceField; + + private connection[] connectionField; + + /// + [System.Xml.Serialization.XmlElementAttribute("functionInstance")] + public functionInstance[] functionInstance + { + get + { + return this.functionInstanceField; + } + set + { + this.functionInstanceField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("connection")] + public connection[] connection + { + get + { + return this.connectionField; + } + set + { + this.connectionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class functionInstance + { + + private object[] itemsField; + + private string nameField; + + private string uniqueIDField; + + private string typeIDRefField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string typeIDRef + { + get + { + return this.typeIDRefField; + } + set + { + this.typeIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class connection + { + + private string sourceField; + + private string destinationField; + + private string descriptionField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string source + { + get + { + return this.sourceField; + } + set + { + this.sourceField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string destination + { + get + { + return this.destinationField; + } + set + { + this.destinationField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string description + { + get + { + return this.descriptionField; + } + set + { + this.descriptionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class templateList + { + + private parameterTemplate[] parameterTemplateField; + + private allowedValuesTemplate[] allowedValuesTemplateField; + + /// + [System.Xml.Serialization.XmlElementAttribute("parameterTemplate")] + public parameterTemplate[] parameterTemplate + { + get + { + return this.parameterTemplateField; + } + set + { + this.parameterTemplateField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("allowedValuesTemplate")] + public allowedValuesTemplate[] allowedValuesTemplate + { + get + { + return this.allowedValuesTemplateField; + } + set + { + this.allowedValuesTemplateField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class parameterTemplate + { + + private object itemField; + + private ItemChoiceType3 itemElementNameField; + + private conditionalSupport[] conditionalSupportField; + + private actualValue actualValueField; + + private defaultValue defaultValueField; + + private substituteValue substituteValueField; + + private allowedValues allowedValuesField; + + private unit unitField; + + private property[] propertyField; + + private string uniqueIDField; + + private parameterTemplateAccess accessField; + + private string accessListField; + + private parameterTemplateSupport supportField; + + private bool supportFieldSpecified; + + private bool persistentField; + + private string offsetField; + + private string multiplierField; + + private string templateIDRefField; + + public parameterTemplate() + { + this.accessField = parameterTemplateAccess.read; + this.persistentField = false; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] + [System.Xml.Serialization.XmlChoiceIdentifierAttribute("ItemElementName")] + public object Item + { + get + { + return this.itemField; + } + set + { + this.itemField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public ItemChoiceType3 ItemElementName + { + get + { + return this.itemElementNameField; + } + set + { + this.itemElementNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("conditionalSupport")] + public conditionalSupport[] conditionalSupport + { + get + { + return this.conditionalSupportField; + } + set + { + this.conditionalSupportField = value; + } + } + + /// + public actualValue actualValue + { + get + { + return this.actualValueField; + } + set + { + this.actualValueField = value; + } + } + + /// + public defaultValue defaultValue + { + get + { + return this.defaultValueField; + } + set + { + this.defaultValueField = value; + } + } + + /// + public substituteValue substituteValue + { + get + { + return this.substituteValueField; + } + set + { + this.substituteValueField = value; + } + } + + /// + public allowedValues allowedValues + { + get + { + return this.allowedValuesField; + } + set + { + this.allowedValuesField = value; + } + } + + /// + public unit unit + { + get + { + return this.unitField; + } + set + { + this.unitField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("property")] + public property[] property + { + get + { + return this.propertyField; + } + set + { + this.propertyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(parameterTemplateAccess.read)] + public parameterTemplateAccess access + { + get + { + return this.accessField; + } + set + { + this.accessField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] + public string accessList + { + get + { + return this.accessListField; + } + set + { + this.accessListField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public parameterTemplateSupport support + { + get + { + return this.supportField; + } + set + { + this.supportField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool supportSpecified + { + get + { + return this.supportFieldSpecified; + } + set + { + this.supportFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool persistent + { + get + { + return this.persistentField; + } + set + { + this.persistentField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string templateIDRef + { + get + { + return this.templateIDRefField; + } + set + { + this.templateIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] + public enum ItemChoiceType3 + { + + /// + BITSTRING, + + /// + BOOL, + + /// + BYTE, + + /// + CHAR, + + /// + DINT, + + /// + DWORD, + + /// + INT, + + /// + LINT, + + /// + LREAL, + + /// + LWORD, + + /// + REAL, + + /// + SINT, + + /// + STRING, + + /// + UDINT, + + /// + UINT, + + /// + ULINT, + + /// + USINT, + + /// + WORD, + + /// + WSTRING, + + /// + dataTypeIDRef, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class conditionalSupport + { + + private string paramIDRefField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string paramIDRef + { + get + { + return this.paramIDRefField; + } + set + { + this.paramIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class actualValue + { + + private object[] itemsField; + + private string valueField; + + private string offsetField; + + private string multiplierField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class substituteValue + { + + private object[] itemsField; + + private string valueField; + + private string offsetField; + + private string multiplierField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class unit + { + + private object[] itemsField; + + private string multiplierField; + + private string unitURIField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "anyURI")] + public string unitURI + { + get + { + return this.unitURIField; + } + set + { + this.unitURIField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class property + { + + private string nameField; + + private string valueField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string name + { + get + { + return this.nameField; + } + set + { + this.nameField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum parameterTemplateAccess + { + + /// + @const, + + /// + read, + + /// + write, + + /// + readWrite, + + /// + readWriteInput, + + /// + readWriteOutput, + + /// + noAccess, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum parameterTemplateSupport + { + + /// + mandatory, + + /// + optional, + + /// + conditional, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class allowedValuesTemplate + { + + private value[] valueField; + + private range[] rangeField; + + private string uniqueIDField; + + /// + [System.Xml.Serialization.XmlElementAttribute("value")] + public value[] value + { + get + { + return this.valueField; + } + set + { + this.valueField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("range")] + public range[] range + { + get + { + return this.rangeField; + } + set + { + this.rangeField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class parameter + { + + private object[] itemsField; + + private object[] items1Field; + + private Items1ChoiceType[] items1ElementNameField; + + private conditionalSupport[] conditionalSupportField; + + private denotation denotationField; + + private actualValue actualValueField; + + private defaultValue defaultValueField; + + private substituteValue substituteValueField; + + private allowedValues allowedValuesField; + + private unit unitField; + + private property[] propertyField; + + private string uniqueIDField; + + private parameterTemplateAccess accessField; + + private string accessListField; + + private parameterTemplateSupport supportField; + + private bool supportFieldSpecified; + + private bool persistentField; + + private string offsetField; + + private string multiplierField; + + private string templateIDRefField; + + public parameter() + { + this.accessField = parameterTemplateAccess.read; + this.persistentField = false; + } + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("BITSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BOOL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("BYTE", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("CHAR", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("DWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("INT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LREAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("LWORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("REAL", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("SINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("STRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UDINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("UINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("ULINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("USINT", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WORD", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("WSTRING", typeof(object))] + [System.Xml.Serialization.XmlElementAttribute("dataTypeIDRef", typeof(dataTypeIDRef))] + [System.Xml.Serialization.XmlElementAttribute("variableRef", typeof(variableRef))] + [System.Xml.Serialization.XmlChoiceIdentifierAttribute("Items1ElementName")] + public object[] Items1 + { + get + { + return this.items1Field; + } + set + { + this.items1Field = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("Items1ElementName")] + [System.Xml.Serialization.XmlIgnoreAttribute()] + public Items1ChoiceType[] Items1ElementName + { + get + { + return this.items1ElementNameField; + } + set + { + this.items1ElementNameField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("conditionalSupport")] + public conditionalSupport[] conditionalSupport + { + get + { + return this.conditionalSupportField; + } + set + { + this.conditionalSupportField = value; + } + } + + /// + public denotation denotation + { + get + { + return this.denotationField; + } + set + { + this.denotationField = value; + } + } + + /// + public actualValue actualValue + { + get + { + return this.actualValueField; + } + set + { + this.actualValueField = value; + } + } + + /// + public defaultValue defaultValue + { + get + { + return this.defaultValueField; + } + set + { + this.defaultValueField = value; + } + } + + /// + public substituteValue substituteValue + { + get + { + return this.substituteValueField; + } + set + { + this.substituteValueField = value; + } + } + + /// + public allowedValues allowedValues + { + get + { + return this.allowedValuesField; + } + set + { + this.allowedValuesField = value; + } + } + + /// + public unit unit + { + get + { + return this.unitField; + } + set + { + this.unitField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("property")] + public property[] property + { + get + { + return this.propertyField; + } + set + { + this.propertyField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + //[System.ComponentModel.DefaultValueAttribute(parameterTemplateAccess.read)] + public parameterTemplateAccess access + { + get + { + return this.accessField; + } + set + { + this.accessField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "NMTOKENS")] + public string accessList + { + get + { + return this.accessListField; + } + set + { + this.accessListField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public parameterTemplateSupport support + { + get + { + return this.supportField; + } + set + { + this.supportField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool supportSpecified + { + get + { + return this.supportFieldSpecified; + } + set + { + this.supportFieldSpecified = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(false)] + public bool persistent + { + get + { + return this.persistentField; + } + set + { + this.persistentField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string offset + { + get + { + return this.offsetField; + } + set + { + this.offsetField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string multiplier + { + get + { + return this.multiplierField; + } + set + { + this.multiplierField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string templateIDRef + { + get + { + return this.templateIDRefField; + } + set + { + this.templateIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class variableRef + { + + private instanceIDRef[] instanceIDRefField; + + private variableIDRef variableIDRefField; + + private memberRef[] memberRefField; + + private byte positionField; + + public variableRef() + { + this.positionField = ((byte)(1)); + } + + /// + [System.Xml.Serialization.XmlElementAttribute("instanceIDRef")] + public instanceIDRef[] instanceIDRef + { + get + { + return this.instanceIDRefField; + } + set + { + this.instanceIDRefField = value; + } + } + + /// + public variableIDRef variableIDRef + { + get + { + return this.variableIDRefField; + } + set + { + this.variableIDRefField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("memberRef")] + public memberRef[] memberRef + { + get + { + return this.memberRefField; + } + set + { + this.memberRefField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + [System.ComponentModel.DefaultValueAttribute(typeof(byte), "1")] + public byte position + { + get + { + return this.positionField; + } + set + { + this.positionField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class instanceIDRef + { + + private string uniqueIDRefField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string uniqueIDRef + { + get + { + return this.uniqueIDRefField; + } + set + { + this.uniqueIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class variableIDRef + { + + private string uniqueIDRefField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string uniqueIDRef + { + get + { + return this.uniqueIDRefField; + } + set + { + this.uniqueIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class memberRef + { + + private string uniqueIDRefField; + + private long indexField; + + private bool indexFieldSpecified; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string uniqueIDRef + { + get + { + return this.uniqueIDRefField; + } + set + { + this.uniqueIDRefField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public long index + { + get + { + return this.indexField; + } + set + { + this.indexField = value; + } + } + + /// + [System.Xml.Serialization.XmlIgnoreAttribute()] + public bool indexSpecified + { + get + { + return this.indexFieldSpecified; + } + set + { + this.indexFieldSpecified = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(Namespace = "http://www.canopen.org/xml/1.0", IncludeInSchema = false)] + public enum Items1ChoiceType + { + + /// + BITSTRING, + + /// + BOOL, + + /// + BYTE, + + /// + CHAR, + + /// + DINT, + + /// + DWORD, + + /// + INT, + + /// + LINT, + + /// + LREAL, + + /// + LWORD, + + /// + REAL, + + /// + SINT, + + /// + STRING, + + /// + UDINT, + + /// + UINT, + + /// + ULINT, + + /// + USINT, + + /// + WORD, + + /// + WSTRING, + + /// + dataTypeIDRef, + + /// + variableRef, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class denotation + { + + private object[] itemsField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class parameterGroup + { + + private object[] itemsField; + + private parameterGroup[] parameterGroup1Field; + + private parameterRef[] parameterRefField; + + private string uniqueIDField; + + private string kindOfAccessField; + + /// + [System.Xml.Serialization.XmlElementAttribute("description", typeof(vendorTextDescription))] + [System.Xml.Serialization.XmlElementAttribute("descriptionRef", typeof(vendorTextDescriptionRef))] + [System.Xml.Serialization.XmlElementAttribute("label", typeof(vendorTextLabel))] + [System.Xml.Serialization.XmlElementAttribute("labelRef", typeof(vendorTextLabelRef))] + public object[] Items + { + get + { + return this.itemsField; + } + set + { + this.itemsField = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("parameterGroup")] + public parameterGroup[] parameterGroup1 + { + get + { + return this.parameterGroup1Field; + } + set + { + this.parameterGroup1Field = value; + } + } + + /// + [System.Xml.Serialization.XmlElementAttribute("parameterRef")] + public parameterRef[] parameterRef + { + get + { + return this.parameterRefField; + } + set + { + this.parameterRefField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "ID")] + public string uniqueID + { + get + { + return this.uniqueIDField; + } + set + { + this.uniqueIDField = value; + } + } + + /// + [System.Xml.Serialization.XmlAttributeAttribute()] + public string kindOfAccess + { + get + { + return this.kindOfAccessField; + } + set + { + this.kindOfAccessField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class parameterRef + { + + private string uniqueIDRefField; + + /// + [System.Xml.Serialization.XmlAttributeAttribute(DataType = "IDREF")] + public string uniqueIDRef + { + get + { + return this.uniqueIDRefField; + } + set + { + this.uniqueIDRefField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + public enum ProfileBody_Device_CANopenDeviceClass + { + + /// + compact, + + /// + modular, + + /// + configurable, + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class standardComplianceList + { + + private compliantWith[] compliantWithField; + + /// + [System.Xml.Serialization.XmlElementAttribute("compliantWith")] + public compliantWith[] compliantWith + { + get + { + return this.compliantWithField; + } + set + { + this.compliantWithField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class picturesList + { + + private picture[] pictureField; + + /// + [System.Xml.Serialization.XmlElementAttribute("picture")] + public picture[] picture + { + get + { + return this.pictureField; + } + set + { + this.pictureField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class dictionaryList + { + + private dictionary[] dictionaryField; + + /// + [System.Xml.Serialization.XmlElementAttribute("dictionary")] + public dictionary[] dictionary + { + get + { + return this.dictionaryField; + } + set + { + this.dictionaryField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class functionTypeList + { + + private functionType[] functionTypeField; + + /// + [System.Xml.Serialization.XmlElementAttribute("functionType")] + public functionType[] functionType + { + get + { + return this.functionTypeField; + } + set + { + this.functionTypeField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class inputVars + { + + private varDeclaration[] varDeclarationField; + + /// + [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] + public varDeclaration[] varDeclaration + { + get + { + return this.varDeclarationField; + } + set + { + this.varDeclarationField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class outputVars + { + + private varDeclaration[] varDeclarationField; + + /// + [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] + public varDeclaration[] varDeclaration + { + get + { + return this.varDeclarationField; + } + set + { + this.varDeclarationField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class configVars + { + + private varDeclaration[] varDeclarationField; + + /// + [System.Xml.Serialization.XmlElementAttribute("varDeclaration")] + public varDeclaration[] varDeclaration + { + get + { + return this.varDeclarationField; + } + set + { + this.varDeclarationField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class parameterList + { + + private parameter[] parameterField; + + /// + [System.Xml.Serialization.XmlElementAttribute("parameter")] + public parameter[] parameter + { + get + { + return this.parameterField; + } + set + { + this.parameterField = value; + } + } + } + + /// + [System.CodeDom.Compiler.GeneratedCodeAttribute("xsd", "4.6.1055.0")] + [System.SerializableAttribute()] + [System.Diagnostics.DebuggerStepThroughAttribute()] + [System.ComponentModel.DesignerCategoryAttribute("code")] + [System.Xml.Serialization.XmlTypeAttribute(AnonymousType = true, Namespace = "http://www.canopen.org/xml/1.0")] + [System.Xml.Serialization.XmlRootAttribute(Namespace = "http://www.canopen.org/xml/1.0", IsNullable = false)] + public partial class parameterGroupList + { + + private parameterGroup[] parameterGroupField; + + /// + [System.Xml.Serialization.XmlElementAttribute("parameterGroup")] + public parameterGroup[] parameterGroup + { + get + { + return this.parameterGroupField; + } + set + { + this.parameterGroupField = value; + } + } + } +} From 5ca7d71649ba69d7fccec85178a172be418f17f8 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 13 Apr 2024 11:39:19 +0200 Subject: [PATCH 143/226] Adding the contex menu on od column click back (#108) --- EDSEditorGUI/DeviceODView.cs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index fcc18215..cdbe6f43 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -633,6 +633,11 @@ private void ListView_objects_SelectedIndexChanged(object sender, EventArgs e) private void ListView_objects_ColumnClick(object sender, ColumnClickEventArgs e) { ((ListView)sender).SelectedItems.Clear(); + + contextMenu_object.Show(Cursor.Position); + PopulateObject(); + PopulateSubList(); + ListView_objects_MouseClick(sender, new MouseEventArgs(MouseButtons.Right, 0, 0, 0, 0)); } From bbb9ad2ce53a586998dfb229e1ecd9cc620b34fc Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Mon, 15 Apr 2024 23:47:08 +0000 Subject: [PATCH 144/226] Bump microsoft/setup-msbuild from 1.3 to 2 Bumps [microsoft/setup-msbuild](https://github.com/microsoft/setup-msbuild) from 1.3 to 2. - [Release notes](https://github.com/microsoft/setup-msbuild/releases) - [Changelog](https://github.com/microsoft/setup-msbuild/blob/main/building-release.md) - [Commits](https://github.com/microsoft/setup-msbuild/compare/v1.3...v2) --- updated-dependencies: - dependency-name: microsoft/setup-msbuild dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dotnet.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 66158f1f..b35e7f73 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -19,7 +19,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET - uses: microsoft/setup-msbuild@v1.3 + uses: microsoft/setup-msbuild@v2 - name: C# problem matcher run: | Invoke-WebRequest "https://raw.githubusercontent.com/actions/setup-dotnet/main/.github/csc.json" -OutFile "csc.json" diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 5ad0e674..c42bf3fa 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -14,7 +14,7 @@ jobs: - name: Checkout uses: actions/checkout@v4 - name: Setup .NET - uses: microsoft/setup-msbuild@v1.3 + uses: microsoft/setup-msbuild@v2 - name: Add Packages run: | dotnet restore From 652f67108ca91071e409b86981cd49990d2ad239 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 27 Apr 2024 15:42:39 +0200 Subject: [PATCH 145/226] 110 xdd v1.0: exporting sets wrong type on highest sub index supported (#111) * created test to catch & reproduce the bug * bugfix --- Tests/XDDImportExportTest.cs | 1 + libEDSsharp/CanOpenXDD.cs | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/Tests/XDDImportExportTest.cs b/Tests/XDDImportExportTest.cs index b6b211cf..36f40238 100644 --- a/Tests/XDDImportExportTest.cs +++ b/Tests/XDDImportExportTest.cs @@ -179,6 +179,7 @@ public void TestImportExportArray() if (od.subobjects[1].PDOtype != PDOMappingType.optional) throw new Exception("TPDOMappingType.optional not set in EDS for ARRAY"); + Assert.True(od.subobjects[0].datatype == DataType.UNSIGNED8, "array subindex 0 datatype is changed"); } diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 22e85d9e..9dde28e2 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -496,7 +496,7 @@ public ISO15745ProfileContainer convert(EDSsharp eds) AppLayer.CANopenObjectList.CANopenObject[count].CANopenSubObject[subcount].edseditor_extension_notifyonchange = subod.prop.CO_flagsPDO; - if (od.objecttype == ObjectType.ARRAY) + if (od.objecttype == ObjectType.ARRAY && count != 0) bytes = BitConverter.GetBytes((UInt16)od.datatype); else bytes = BitConverter.GetBytes((UInt16)subod.datatype); From 2cca6bced031f85d6d0a9e978333d95330e206fa Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 2 Jul 2024 12:28:37 +0200 Subject: [PATCH 146/226] Bugfix file filter when opening Network XML --- EDSEditorGUI/Form1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 1d051a94..6775ba03 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -816,7 +816,7 @@ private void loadNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) OpenFileDialog odf = new OpenFileDialog(); odf.Filter = "All supported files (*.nxdd;*.nxdc)|*.nxdd;*.nxdc|" + "CANopen Network XDD (*.nxdd)|*.nxdd|" - + "CANopen Network XDC (*.nxdc)|*.nxdc|"; + + "CANopen Network XDC (*.nxdc)|*.nxdc"; if (odf.ShowDialog() == DialogResult.OK) { From 591a57a5e5acebed292f3c268ed44281547e8d91 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Tue, 16 Jul 2024 16:03:03 +0200 Subject: [PATCH 147/226] experimental protobuffer support (#115) * Added protobuffer exporter/importer. --------- Co-authored-by: Janez --- EDSEditorGUI/.gitignore | 3 +- EDSEditorGUI/Form1.cs | 86 ++- libEDSsharp/CanOpenXDD_1_1.cs | 1151 ++++++++++++++++++++++++++++++- libEDSsharp/libEDSsharp.csproj | 17 +- libEDSsharp/proto/.gitignore | 1 + libEDSsharp/proto/CanOpen.proto | 168 +++++ 6 files changed, 1416 insertions(+), 10 deletions(-) create mode 100644 libEDSsharp/proto/.gitignore create mode 100644 libEDSsharp/proto/CanOpen.proto diff --git a/EDSEditorGUI/.gitignore b/EDSEditorGUI/.gitignore index a16e7a5a..a0ac84af 100644 --- a/EDSEditorGUI/.gitignore +++ b/EDSEditorGUI/.gitignore @@ -1 +1,2 @@ -version.txt \ No newline at end of file +version.txt +EDSEditorGUI.csproj.user diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 6775ba03..3a5f3278 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -278,12 +278,13 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) Warnings.warning_list.Clear(); OpenFileDialog odf = new OpenFileDialog(); - odf.Filter = "All supported files (*.xdd;*.xdc;*.xpd;*.eds;*.dcf)|*.xdd;*.xdc;*.xpd;*.eds;*.dcf|" + odf.Filter = "All supported files (*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.binpb;*.json)|*.xdd;*.xdc;*.xpd;*.eds;*.dcf;*.binpb;*.json|" + "CANopen XDD (*.xdd)|*.xdd|" + "CANopen XDC (*.xdc)|*.xdc|" + "CANopen XPD (*.xpd)|*.xpd|" + "Electronic Data Sheet (*.eds)|*.eds|" - + "Device Configuration File (*.dcf)|*.dcf"; + + "Device Configuration File (*.dcf)|*.dcf|" + + "CANopen Protobuffer (*.binpb;*.json)|*.binpb;*.json"; if (odf.ShowDialog() == DialogResult.OK) { @@ -304,6 +305,14 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) openEDSfile(odf.FileName, InfoSection.Filetype.File_DCF); break; + case ".binpb": + OpenProtobufferfile(odf.FileName, false); + break; + + case ".json": + OpenProtobufferfile(odf.FileName, true); + break; + default: return; @@ -369,6 +378,49 @@ private void openXDDfile(string path) } + private void OpenProtobufferfile(string path, bool json) + { + Warnings.warning_list.Clear(); + + try + { + EDSsharp eds; + + CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); + eds = coxml_1_1.ReadProtobuf(path, json); + + if (eds == null) + { + return; + } + + eds.projectFilename = path; + + DeviceView device = new DeviceView(eds, network); + + device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + eds.OnDataDirty += Eds_onDataDirty; + + tabControl1.TabPages.Add(eds.di.ProductName); + tabControl1.TabPages[tabControl1.TabPages.Count - 1].Controls.Add(device); + + device.Dock = DockStyle.Fill; + device.dispatch_updateOD(); + + network.Add(eds); + } + catch (Exception ex) + { + Warnings.warning_list.Add(ex.ToString()); + } + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + } + private void Device_UpdateODViewForEDS(object sender, UpdateODViewEventArgs e) { foreach (TabPage page in tabControl1.TabPages) @@ -484,6 +536,8 @@ private void exportDeviceFileToolStripMenuItem_Click(object sender, EventArgs e) sfd.Filter = "CANopen XDD v1.1 stripped (*.xdd)|*.xdd|" //must be first or change condition below + "Electronic Data Sheet (*.eds)|*.eds|" + "Device Configuration File (*.dcf)|*.dcf|" + + "Protobuffer binary, experimental (*.binpb)|*.binpb|" + + "Protobuffer JSON, experimental (*.json)|*.json|" + "Documentation (*.md)|*.md|" + "CANopen XDD v1.0, old (*.xdd)|*.xdd"; @@ -605,6 +659,20 @@ void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripp dv.eds.xddfilename_1_0 = FileName; } break; + + case ".binpb": + case ".json": + Warnings.warning_list.Clear(); + + CanOpenXDD_1_1 copb = new CanOpenXDD_1_1(); + copb.WriteProtobuf(FileName, dv.eds, Path.GetExtension(FileName) == ".json"); + + if (Warnings.warning_list.Count != 0) + { + WarningsFrm frm = new WarningsFrm(); + frm.Show(); + } + break; } dv.dispatch_updateOD(); @@ -683,6 +751,12 @@ void OpenRecentFile(object sender, EventArgs e) if (ext == ".xdd" || ext == ".xdc" || ext == ".xpd") openXDDfile(filepath); + + else if (ext == ".binpb") + OpenProtobufferfile(filepath, false); + else if (ext == ".json") + OpenProtobufferfile(filepath, true); + if ( ext == ".eds" ) openEDSfile(filepath, InfoSection.Filetype.File_EDS); if (ext == ".dcf") @@ -1203,6 +1277,14 @@ private void ODEditor_MainForm_DragDrop(object sender, DragEventArgs e) openXDDNetworkfile(fileName); break; + case ".binpb": + OpenProtobufferfile(fileName, false); + break; + + case ".json": + OpenProtobufferfile(fileName, true); + break; + default: break; diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 31f20d9f..1e83122e 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -26,6 +26,10 @@ You should have received a copy of the GNU General Public License using System.Xml; using System.Xml.Serialization; using CanOpenXSD_1_1; +using LibCanOpen; +using Google.Protobuf; +using Google.Protobuf.WellKnownTypes; +using System.Linq; namespace libEDSsharp { @@ -153,6 +157,66 @@ public void WriteXML(string file, EDSsharp eds, string gitVersion, bool deviceCo stream.Close(); } + /// + /// Read protobuffer file into EDSsharp object + /// + /// Name of the protobuffer file + /// read as JSON string or binary wireformat + /// EDSsharp object + public EDSsharp ReadProtobuf(string file, bool json) + { + CanOpenDevice devCanOpen; + + // read the protobuffer message in json format or binary wireformat + if (json) + { + var parserConfig = new JsonParser.Settings(100); + var parser = new JsonParser(parserConfig); + devCanOpen = parser.Parse(File.ReadAllText(file)); + } + else + { + using (var input = File.OpenRead(file)) + { + devCanOpen = CanOpenDevice.Parser.ParseFrom(input); + } + } + + /* first convert to XDD, then to EDSsharp (for now) */ + ISO15745ProfileContainer devXdd = ConvertFromProtobuf(devCanOpen, file, true, false); + + return Convert(devXdd); + } + + /// + /// Write protobuffer file from EDSsharp object + /// + /// Name of the protobuffer file + /// EDSsharp object + /// write as JSON string or binary wireformat + public void WriteProtobuf(string file, EDSsharp eds, bool json) + { + /* first convert to XDD, then to protobuffer (for now) */ + ISO15745ProfileContainer devXdd = Convert(eds, Path.GetFileName(file), true, false); + CanOpenDevice dev = ConvertToProtobuf(devXdd); + + // write the protobuffer message in json format or binary wireformat + if (json) + { + var formatterConfig = new JsonFormatter.Settings(true).WithIndentation().WithFormatDefaultValues(true); + var formatter = new JsonFormatter(formatterConfig); + var rawJsonString = formatter.Format(dev); + File.WriteAllText(file, rawJsonString); + } + else + { + using (var output = File.Create(file)) + { + dev.WriteTo(output); + } + } + } + private parameterTemplateAccess ConvertAccessType(EDSsharp.AccessType edsAccessType) { switch (edsAccessType) @@ -167,6 +231,23 @@ private parameterTemplateAccess ConvertAccessType(EDSsharp.AccessType edsAccessT } } + private parameterTemplateAccess ConvertAccessType(OdSubObject subEntry) + { + switch (subEntry.Sdo) + { + case LibCanOpen.OdSubObject.Types.AccessSDO.Ro: return parameterTemplateAccess.read; + case LibCanOpen.OdSubObject.Types.AccessSDO.Wo: return parameterTemplateAccess.write; + case LibCanOpen.OdSubObject.Types.AccessSDO.Rw: + switch (subEntry.Pdo) + { + case LibCanOpen.OdSubObject.Types.AccessPDO.R: return parameterTemplateAccess.readWriteInput; + case LibCanOpen.OdSubObject.Types.AccessPDO.T: return parameterTemplateAccess.readWriteOutput; + default: return parameterTemplateAccess.readWrite; + } + default: return parameterTemplateAccess.noAccess; + } + } + private EDSsharp.AccessType ConvertAccessType(parameterTemplateAccess xddAccessType) { switch (xddAccessType) @@ -181,6 +262,34 @@ private EDSsharp.AccessType ConvertAccessType(parameterTemplateAccess xddAccessT } } + private void ConvertAccessType(parameterTemplateAccess xddAccessType, OdSubObject subEntry) + { + switch (xddAccessType) + { + case parameterTemplateAccess.@const: + case parameterTemplateAccess.read: + subEntry.Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro; + break; + case parameterTemplateAccess.readWrite: + subEntry.Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw; + break; + case parameterTemplateAccess.readWriteInput: + subEntry.Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw; + subEntry.Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.T; + break; + case parameterTemplateAccess.readWriteOutput: + subEntry.Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw; + subEntry.Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.R; + break; + case parameterTemplateAccess.write: + subEntry.Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Wo; + break; + default: + subEntry.Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.No; + break; + } + } + private Items1ChoiceType ConvertDataType (ODentry od) { UInt32 byteLength; @@ -280,6 +389,131 @@ private DataType ConvertDataType(Items1ChoiceType choiceType, string defaultValu } } + private Items1ChoiceType ConvertDataType(OdSubObject subEntry) + { + UInt32 byteLength; + bool signed = false; + var dt = subEntry.Type; + + switch (dt) + { + case LibCanOpen.OdSubObject.Types.DataType.Boolean: return Items1ChoiceType.BOOL; + case LibCanOpen.OdSubObject.Types.DataType.Integer8: return Items1ChoiceType.SINT; + case LibCanOpen.OdSubObject.Types.DataType.Integer16: return Items1ChoiceType.INT; + case LibCanOpen.OdSubObject.Types.DataType.Integer32: return Items1ChoiceType.DINT; + case LibCanOpen.OdSubObject.Types.DataType.Integer64: return Items1ChoiceType.LINT; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned8: return Items1ChoiceType.USINT; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned16: return Items1ChoiceType.UINT; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned32: return Items1ChoiceType.UDINT; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned64: return Items1ChoiceType.ULINT; + case LibCanOpen.OdSubObject.Types.DataType.Real32: return Items1ChoiceType.REAL; + case LibCanOpen.OdSubObject.Types.DataType.Real64: return Items1ChoiceType.LREAL; + case LibCanOpen.OdSubObject.Types.DataType.VisibleString: return Items1ChoiceType.STRING; + case LibCanOpen.OdSubObject.Types.DataType.OctetString: return Items1ChoiceType.BITSTRING; + case LibCanOpen.OdSubObject.Types.DataType.UnicodeString: return Items1ChoiceType.WSTRING; + + case LibCanOpen.OdSubObject.Types.DataType.Domain: + subEntry.DefaultValue = ""; + return Items1ChoiceType.BITSTRING; + + default: + subEntry.Type = LibCanOpen.OdSubObject.Types.DataType.Integer32; + return Items1ChoiceType.DINT; + + // transform other non standard values to OCTET_STRING + case LibCanOpen.OdSubObject.Types.DataType.Integer24: byteLength = 3; signed = true; break; + case LibCanOpen.OdSubObject.Types.DataType.Integer40: byteLength = 5; signed = true; break; + case LibCanOpen.OdSubObject.Types.DataType.Integer48: byteLength = 6; signed = true; break; + case LibCanOpen.OdSubObject.Types.DataType.Integer56: byteLength = 7; signed = true; break; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned24: byteLength = 3; break; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned40: byteLength = 5; break; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned48: + case LibCanOpen.OdSubObject.Types.DataType.TimeOfDay: + case LibCanOpen.OdSubObject.Types.DataType.TimeDifference: byteLength = 6; break; + case LibCanOpen.OdSubObject.Types.DataType.Unsigned56: byteLength = 7; break; + } + + // set datatype OCTET_STRING and write default value as a sequence of bytes, little endian, like "56 34 12" + UInt64 value; + try + { + value = signed ? (UInt64)((Int64)new System.ComponentModel.Int64Converter().ConvertFromString(subEntry.DefaultValue)) + : (UInt64)new System.ComponentModel.UInt64Converter().ConvertFromString(subEntry.DefaultValue); + } + catch (Exception) + { + value = 0; + } + + List bytes = new List(); + for (UInt32 i = 0; i < byteLength; i++) + { + bytes.Add(String.Format("{0:X2}", value & 0xFF)); + value >>= 8; + } + subEntry.Type = LibCanOpen.OdSubObject.Types.DataType.OctetString; + subEntry.DefaultValue = string.Join(" ", bytes); + + return Items1ChoiceType.BITSTRING; + } + + private void ConvertDataType(Items1ChoiceType choiceType, OdSubObject OdSubObject) + { + switch (choiceType) + { + case Items1ChoiceType.BOOL: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Boolean; + break; + case Items1ChoiceType.CHAR: + case Items1ChoiceType.SINT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Integer8; + break; + case Items1ChoiceType.INT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Integer16; + break; + case Items1ChoiceType.DINT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Integer32; + break; + case Items1ChoiceType.LINT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Integer64; + break; + case Items1ChoiceType.BYTE: + case Items1ChoiceType.USINT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned8; + break; + case Items1ChoiceType.WORD: + case Items1ChoiceType.UINT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned16; + break; + case Items1ChoiceType.DWORD: + case Items1ChoiceType.UDINT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32; + break; + case Items1ChoiceType.LWORD: + case Items1ChoiceType.ULINT: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned64; + break; + case Items1ChoiceType.REAL: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Real32; + break; + case Items1ChoiceType.LREAL: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Real64; + break; + case Items1ChoiceType.STRING: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.VisibleString; + break; + case Items1ChoiceType.WSTRING: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.UnicodeString; + break; + case Items1ChoiceType.BITSTRING: + OdSubObject.Type = OdSubObject.DefaultValue == "" ? LibCanOpen.OdSubObject.Types.DataType.Domain : LibCanOpen.OdSubObject.Types.DataType.OctetString; + break; + default: + OdSubObject.Type = LibCanOpen.OdSubObject.Types.DataType.Integer32; + break; + } + } + private void WriteVar(parameter devPar, ODentry od) { if (od.accesstype == EDSsharp.AccessType.UNKNOWN && od.parent != null && od.parent.objecttype == ObjectType.ARRAY) @@ -309,6 +543,99 @@ private void WriteVar(parameter devPar, ODentry od) } } + private void WriteVar(parameter devPar, OdSubObject subEntry) + { + devPar.access = ConvertAccessType(subEntry); + + devPar.Items1 = new object[] { new object() }; + devPar.Items1ElementName = new Items1ChoiceType[] { ConvertDataType(subEntry) }; + + if (subEntry.DefaultValue != null && subEntry.DefaultValue != "") + devPar.defaultValue = new defaultValue { value = subEntry.DefaultValue }; + + if (subEntry.LowLimit != null && subEntry.LowLimit != "" && subEntry.HighLimit != null && subEntry.HighLimit != "") + { + devPar.allowedValues = new allowedValues + { + range = new range[] + { + new range + { + minValue = new rangeMinValue { value = subEntry.LowLimit }, + maxValue = new rangeMaxValue { value = subEntry.HighLimit } + } + } + }; + } + } + + private void ConvertXddProperties(property[] properties, OdObject entry, OdSubObject subEntry) + { + if (properties != null) + { + foreach (property prop in properties) + { + switch (prop.name) + { + case "CO_disabled": entry.Disabled = prop.value == "true"; break; + case "CO_countLabel": entry.CountLabel = prop.value ?? ""; break; + case "CO_storageGroup": entry.StorageGroup = prop.value ?? ""; break; + case "CO_flagsPDO": entry.FlagsPDO = prop.value == "true"; break; + case "CO_accessSRDO": + if (prop.value != null) + switch (prop.value) + { + case "rx": subEntry.Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.Rx; break; + case "tx": subEntry.Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.Tx; break; + case "trx": subEntry.Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.Trx; break; + case "no": subEntry.Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No; break; + } + break; + case "CO_stringLengthMin": + try { subEntry.StringLengthMin = System.Convert.ToUInt16(prop.value); } + catch (Exception) { subEntry.StringLengthMin = 0; } + break; + } + } + } + } + + private property[] ConvertXddProperties(OdObject entry) + { + var props = new List(); + + if (entry.Disabled) + props.Add(new property { name = "CO_disabled", value = "true" }); + if (entry.CountLabel != "") + props.Add(new property { name = "CO_countLabel", value = entry.CountLabel }); + if (entry.StorageGroup != "RAM" && entry.StorageGroup != "") + props.Add(new property { name = "CO_storageGroup", value = entry.StorageGroup }); + if (entry.FlagsPDO) + props.Add(new property { name = "CO_flagsPDO", value = "true" }); + + return props.ToArray(); + } + + private property[] ConvertXddProperties(OdSubObject subEntry) + { + var props = new List(); + string val; + + switch (subEntry.Srdo) + { + case LibCanOpen.OdSubObject.Types.AccessSRDO.Rx: val = "rx"; break; + case LibCanOpen.OdSubObject.Types.AccessSRDO.Tx: val = "tx"; break; + case LibCanOpen.OdSubObject.Types.AccessSRDO.Trx: val = "trx"; break; + default: val = "no"; break; + } + props.Add(new property { name = "CO_accessSRDO", value = val }); + + if (subEntry.StringLengthMin != 0) + props.Add(new property { name = "CO_stringLengthMin", value = subEntry.StringLengthMin.ToString() }); + + return props.ToArray(); + } + private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool deviceCommissioning, bool stripped) { // Get xdd template from eds (if memorized on xdd file open) @@ -434,7 +761,7 @@ private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool dev if (od.objecttype == ObjectType.VAR) { - try { netObj.PDOmapping = (CANopenObjectListCANopenObjectPDOmapping)Enum.Parse(typeof(CANopenObjectListCANopenObjectPDOmapping), od.PDOtype.ToString()); } + try { netObj.PDOmapping = (CANopenObjectListCANopenObjectPDOmapping)System.Enum.Parse(typeof(CANopenObjectListCANopenObjectPDOmapping), od.PDOtype.ToString()); } catch (Exception) { netObj.PDOmapping = CANopenObjectListCANopenObjectPDOmapping.no; } netObj.PDOmappingSpecified = true; @@ -477,7 +804,7 @@ private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool dev PDOmappingSpecified = true, uniqueIDRef = "UID_SUB_" + subUid }; - try { netSubObj.PDOmapping = (CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping)Enum.Parse(typeof(CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping), subod.PDOtype.ToString()); } + try { netSubObj.PDOmapping = (CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping)System.Enum.Parse(typeof(CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping), subod.PDOtype.ToString()); } catch (Exception) { netSubObj.PDOmapping = CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.no; } var devSubPar = new parameter { @@ -1007,7 +1334,7 @@ private EDSsharp Convert(ISO15745ProfileContainer container) EDSsharp.AccessType accessType; if (netObj.accessTypeSpecified) { - try { accessType = (EDSsharp.AccessType)Enum.Parse(typeof(EDSsharp.AccessType), netObj.accessType.ToString()); } + try { accessType = (EDSsharp.AccessType)System.Enum.Parse(typeof(EDSsharp.AccessType), netObj.accessType.ToString()); } catch (Exception) { accessType = EDSsharp.AccessType.ro; } } else { @@ -1017,7 +1344,7 @@ private EDSsharp Convert(ISO15745ProfileContainer container) PDOMappingType PDOtype; if (netObj.PDOmappingSpecified) { - try { PDOtype = (PDOMappingType)Enum.Parse(typeof(PDOMappingType), netObj.PDOmapping.ToString()); } + try { PDOtype = (PDOMappingType)System.Enum.Parse(typeof(PDOMappingType), netObj.PDOmapping.ToString()); } catch (Exception) { PDOtype = PDOMappingType.no; } } else @@ -1093,7 +1420,7 @@ private EDSsharp Convert(ISO15745ProfileContainer container) EDSsharp.AccessType subAccessType; if (netSubObj.accessTypeSpecified) { - try { subAccessType = (EDSsharp.AccessType)Enum.Parse(typeof(EDSsharp.AccessType), netSubObj.accessType.ToString()); } + try { subAccessType = (EDSsharp.AccessType)System.Enum.Parse(typeof(EDSsharp.AccessType), netSubObj.accessType.ToString()); } catch (Exception) { subAccessType = EDSsharp.AccessType.ro; } } else @@ -1104,7 +1431,7 @@ private EDSsharp Convert(ISO15745ProfileContainer container) PDOMappingType subPDOtype; if (netSubObj.PDOmappingSpecified) { - try { subPDOtype = (PDOMappingType)Enum.Parse(typeof(PDOMappingType), netSubObj.PDOmapping.ToString()); } + try { subPDOtype = (PDOMappingType)System.Enum.Parse(typeof(PDOMappingType), netSubObj.PDOmapping.ToString()); } catch (Exception) { subPDOtype = PDOMappingType.no; } } else @@ -1199,6 +1526,818 @@ private EDSsharp Convert(ISO15745ProfileContainer container) return eds; } + + private CanOpenDevice ConvertToProtobuf(ISO15745ProfileContainer container) + { + CanOpenDevice dev = new CanOpenDevice(); + + dev.FileInfo = new CanOpen_FileInfo(); + dev.DeviceInfo = new CanOpen_DeviceInfo(); + dev.DeviceCommissioning = new CanOpen_DeviceCommissioning(); + + ProfileBody_Device_CANopen body_device = null; + ProfileBody_CommunicationNetwork_CANopen body_network = null; + ProfileBody_CommunicationNetwork_CANopenApplicationLayers ApplicationLayers = null; + var parameters = new Dictionary(); + + foreach (ISO15745Profile item in container.ISO15745Profile) + { + if (item.ProfileBody.GetType() == typeof(ProfileBody_Device_CANopen)) + body_device = (ProfileBody_Device_CANopen)item.ProfileBody; + else if (item.ProfileBody.GetType() == typeof(ProfileBody_CommunicationNetwork_CANopen)) + body_network = (ProfileBody_CommunicationNetwork_CANopen)item.ProfileBody; + } + + if (body_device != null) + { + //eds.fi.FileName = body_device.fileName ?? ""; + dev.FileInfo.FileVersion = body_device.fileVersion ?? ""; + dev.FileInfo.CreatedBy = body_device.fileCreator ?? ""; + dev.FileInfo.ModifiedBy = body_device.fileModifiedBy ?? ""; + + if (body_device.fileCreationTimeSpecified) + { + dev.FileInfo.CreationTime = Timestamp.FromDateTime(body_device.fileCreationDate.Add(body_device.fileCreationTime.TimeOfDay).ToUniversalTime()); + + } + if (body_device.fileModificationDateSpecified) + { + dev.FileInfo.ModificationTime = Timestamp.FromDateTime(body_device.fileModificationDate.Add(body_device.fileModificationTime.TimeOfDay).ToUniversalTime()); + } + + if (body_device.DeviceIdentity != null) + { + if (body_device.DeviceIdentity.productText != null) + dev.FileInfo.Description = G_label_getDescription(body_device.DeviceIdentity.productText.Items); + if (body_device.DeviceIdentity.vendorName != null) + dev.DeviceInfo.VendorName = body_device.DeviceIdentity.vendorName.Value ?? ""; + if (body_device.DeviceIdentity.productName != null) + dev.DeviceInfo.ProductName = body_device.DeviceIdentity.productName.Value ?? ""; + } + + if (body_device.ApplicationProcess != null + && body_device.ApplicationProcess[0] != null + && body_device.ApplicationProcess[0].parameterList != null) + { + foreach (parameter param in body_device.ApplicationProcess[0].parameterList) + { + if (!parameters.ContainsKey(param.uniqueID)) + parameters.Add(param.uniqueID, param); + } + } + } + + if (body_network != null) + { + ProfileBody_CommunicationNetwork_CANopenTransportLayers TransportLayers = null; + ProfileBody_CommunicationNetwork_CANopenNetworkManagement NetworkManagement = null; + + foreach (object item in body_network.Items) + { + if (item.GetType() == typeof(ProfileBody_CommunicationNetwork_CANopenApplicationLayers)) + ApplicationLayers = (ProfileBody_CommunicationNetwork_CANopenApplicationLayers)item; + else if (item.GetType() == typeof(ProfileBody_CommunicationNetwork_CANopenTransportLayers)) + TransportLayers = (ProfileBody_CommunicationNetwork_CANopenTransportLayers)item; + else if (item.GetType() == typeof(ProfileBody_CommunicationNetwork_CANopenNetworkManagement)) + NetworkManagement = (ProfileBody_CommunicationNetwork_CANopenNetworkManagement)item; + } + + if (TransportLayers != null && TransportLayers.PhysicalLayer != null + && TransportLayers.PhysicalLayer.baudRate != null && TransportLayers.PhysicalLayer.baudRate.supportedBaudRate != null) + { + foreach (ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate baud in TransportLayers.PhysicalLayer.baudRate.supportedBaudRate) + { + switch (baud.value.ToString()) + { + case "Item10Kbps": dev.DeviceInfo.BaudRate10 = true; break; + case "Item20Kbps": dev.DeviceInfo.BaudRate20 = true; break; + case "Item50Kbps": dev.DeviceInfo.BaudRate50 = true; break; + case "Item125Kbps": dev.DeviceInfo.BaudRate125 = true; break; + case "Item250Kbps": dev.DeviceInfo.BaudRate250 = true; break; + case "Item500Kbps": dev.DeviceInfo.BaudRate500 = true; break; + case "Item800Kbps": dev.DeviceInfo.BaudRate800 = true; break; + case "Item1000Kbps": dev.DeviceInfo.BaudRate1000 = true; break; + case "autobaudRate": dev.DeviceInfo.BaudRateAuto = true; break; + } + } + } + + if (NetworkManagement != null) + { + if (NetworkManagement.CANopenGeneralFeatures != null) + { + dev.DeviceInfo.LssSlave = NetworkManagement.CANopenGeneralFeatures.layerSettingServiceSlave; + } + + if (NetworkManagement.CANopenMasterFeatures != null) + { + dev.DeviceInfo.LssMaster = NetworkManagement.CANopenMasterFeatures.layerSettingServiceMaster; + } + + if (NetworkManagement.deviceCommissioning != null) + { + dev.DeviceCommissioning.NodeId = NetworkManagement.deviceCommissioning.NodeID; + dev.DeviceCommissioning.NodeName = NetworkManagement.deviceCommissioning.nodeName; + try { dev.DeviceCommissioning.Baudrate = System.Convert.ToUInt32(NetworkManagement.deviceCommissioning.actualBaudRate); } + catch (Exception) { dev.DeviceCommissioning.Baudrate = 0; } + } + } + + if (ApplicationLayers != null) + { + if (ApplicationLayers.CANopenObjectList != null && ApplicationLayers.CANopenObjectList.CANopenObject != null) + { + foreach (CANopenObjectListCANopenObject netObj in ApplicationLayers.CANopenObjectList.CANopenObject) + { + if (netObj.index == null || netObj.index.Length != 2) + continue; + + string index = netObj.index[0].ToString("X2") + netObj.index[1].ToString("X2"); + + // some properties for object, set to default, changed by netObj + LibCanOpen.OdObject.Types.ObjectType objectType = LibCanOpen.OdObject.Types.ObjectType.Unspecified; + + // some properties for sub objects, set to default, changed by netObj or netSubObj + LibCanOpen.OdSubObject.Types.DataType dataType = LibCanOpen.OdSubObject.Types.DataType.Unspecified; + LibCanOpen.OdSubObject.Types.AccessSDO accessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.No; + LibCanOpen.OdSubObject.Types.AccessPDO accessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.No; + + if (System.Enum.IsDefined(typeof(LibCanOpen.OdObject.Types.ObjectType), (Int32)netObj.objectType)) + { + objectType = (LibCanOpen.OdObject.Types.ObjectType)netObj.objectType; + } + + if (netObj.dataType != null && netObj.dataType.Length == 1) + { + if (System.Enum.IsDefined(typeof(LibCanOpen.OdSubObject.Types.DataType), netObj.dataType[0])) + { + dataType = (LibCanOpen.OdSubObject.Types.DataType)netObj.dataType[0]; + } + } + + // accessType in xdd may be specified by netObj.accessType or inside netObj.uniqueIDRef ?? + if (netObj.accessTypeSpecified) + { + switch (netObj.accessType) + { + case CANopenObjectListCANopenObjectAccessType.@const: + case CANopenObjectListCANopenObjectAccessType.ro: accessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.Ro; break; + case CANopenObjectListCANopenObjectAccessType.wo: accessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.Wo; break; + case CANopenObjectListCANopenObjectAccessType.rw: accessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.Rw; break; + } + } + + if (netObj.PDOmappingSpecified) + { + switch (netObj.PDOmapping) + { + case CANopenObjectListCANopenObjectPDOmapping.RPDO: accessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.R; break; + case CANopenObjectListCANopenObjectPDOmapping.TPDO: accessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.T; break; + case CANopenObjectListCANopenObjectPDOmapping.optional: accessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.Tr; break; + } + } + + OdObject entry = new OdObject() + { + Name = netObj.name ?? "", + Alias = netObj.denotation ?? "", + Type = objectType + }; + + OdSubObject subEntry0 = new OdSubObject() + { + Type = dataType, + Sdo = accessSDO, + Pdo = accessPDO, + DefaultValue = netObj.defaultValue ?? "", + ActualValue = netObj.actualValue ?? "", + LowLimit = netObj.lowLimit ?? "", + HighLimit = netObj.highLimit ?? "" + }; + + if (netObj.uniqueIDRef != null && netObj.uniqueIDRef != "" && parameters.ContainsKey(netObj.uniqueIDRef)) + { + parameter devPar = parameters[netObj.uniqueIDRef]; + + entry.Description = G_label_getDescription(devPar.Items); + + ConvertAccessType(devPar.access, subEntry0); + + if (devPar.defaultValue != null && devPar.defaultValue.value != null) + subEntry0.DefaultValue = devPar.defaultValue.value; + + if (devPar.Items1 != null && devPar.Items1ElementName != null) + ConvertDataType(devPar.Items1ElementName[0], subEntry0); + + if (devPar.actualValue != null && devPar.actualValue.value != null) + subEntry0.ActualValue = devPar.actualValue.value; + + if (devPar.denotation != null) + subEntry0.Alias = G_label_getDescription(devPar.denotation.Items); + + if (devPar.allowedValues != null && devPar.allowedValues.range != null && devPar.allowedValues.range[0] != null) + { + range r = devPar.allowedValues.range[0]; + if (r.minValue != null) subEntry0.LowLimit = r.minValue.value ?? ""; + if (r.maxValue != null) subEntry0.HighLimit = r.maxValue.value ?? ""; + } + + ConvertXddProperties(devPar.property, entry, subEntry0); + } + + if (netObj.CANopenSubObject == null) + { + entry.SubObjects.Add("00", subEntry0); + } + else + { + foreach (CANopenObjectListCANopenObjectCANopenSubObject netSubObj in netObj.CANopenSubObject) + { + if (netSubObj.subIndex == null || netSubObj.subIndex.Length != 1) + continue; + + string subIndex = netSubObj.subIndex[0].ToString("X2"); + LibCanOpen.OdSubObject.Types.DataType subDataType = LibCanOpen.OdSubObject.Types.DataType.Unspecified; + LibCanOpen.OdSubObject.Types.AccessSDO subAccessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.No; + LibCanOpen.OdSubObject.Types.AccessPDO subAccessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.No; + + if (netSubObj.dataType != null && netSubObj.dataType.Length == 1) + { + if (System.Enum.IsDefined(typeof(LibCanOpen.OdSubObject.Types.DataType), netSubObj.dataType[0])) + { + subDataType = (LibCanOpen.OdSubObject.Types.DataType)netSubObj.dataType[0]; + } + } + + if (netSubObj.accessTypeSpecified) + { + switch (netSubObj.accessType) + { + case CANopenObjectListCANopenObjectCANopenSubObjectAccessType.@const: + case CANopenObjectListCANopenObjectCANopenSubObjectAccessType.ro: subAccessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.Ro; break; + case CANopenObjectListCANopenObjectCANopenSubObjectAccessType.wo: subAccessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.Wo; break; + case CANopenObjectListCANopenObjectCANopenSubObjectAccessType.rw: subAccessSDO = LibCanOpen.OdSubObject.Types.AccessSDO.Rw; break; + } + } + + if (netSubObj.PDOmappingSpecified) + { + switch (netSubObj.PDOmapping) + { + case CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.RPDO: subAccessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.R; break; + case CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.TPDO: subAccessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.T; break; + case CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.optional: subAccessPDO = LibCanOpen.OdSubObject.Types.AccessPDO.Tr; break; + } + } + + OdSubObject subEntry = new OdSubObject() + { + Name = netSubObj.name ?? "", + Alias = netSubObj.denotation ?? "", + Type = subDataType, + Sdo = subAccessSDO, + Pdo = subAccessPDO, + DefaultValue = netSubObj.defaultValue ?? "", + ActualValue = netSubObj.actualValue ?? "", + LowLimit = netSubObj.lowLimit ?? "", + HighLimit = netSubObj.highLimit ?? "" + }; + + if (netSubObj.uniqueIDRef != null && netSubObj.uniqueIDRef != "" && parameters.ContainsKey(netSubObj.uniqueIDRef)) + { + parameter devSubPar = parameters[netSubObj.uniqueIDRef]; + + entry.Description += G_label_getDescription(devSubPar.Items); + + ConvertAccessType(devSubPar.access, subEntry); + + if (devSubPar.defaultValue != null && devSubPar.defaultValue.value != null) + subEntry.DefaultValue = devSubPar.defaultValue.value; + + if (devSubPar.Items1 != null && devSubPar.Items1ElementName != null) + ConvertDataType(devSubPar.Items1ElementName[0], subEntry); + + if (devSubPar.actualValue != null && devSubPar.actualValue.value != null) + subEntry.ActualValue = devSubPar.actualValue.value; + + if (devSubPar.denotation != null) + subEntry.Alias = G_label_getDescription(devSubPar.denotation.Items); + + if (devSubPar.allowedValues != null && devSubPar.allowedValues.range != null && devSubPar.allowedValues.range[0] != null) + { + range r = devSubPar.allowedValues.range[0]; + if (r.minValue != null) subEntry.LowLimit = r.minValue.value ?? ""; + if (r.maxValue != null) subEntry.HighLimit = r.maxValue.value ?? ""; + } + + ConvertXddProperties(devSubPar.property, entry, subEntry); + } + + if (!entry.SubObjects.ContainsKey(subIndex)) + entry.SubObjects.Add(subIndex, subEntry); + } + } + + if (!dev.Objects.ContainsKey(index)) + dev.Objects.Add(index, entry); + } + } + } + } + + return dev; + } + + private ISO15745ProfileContainer ConvertFromProtobuf(CanOpenDevice dev, string fileName, bool deviceCommissioning, bool stripped) + { + #region base_elements + ISO15745ProfileContainer container = new ISO15745ProfileContainer(); + + container.ISO15745Profile = new ISO15745Profile[] + { + new ISO15745Profile(), + new ISO15745Profile(), + }; + + container.ISO15745Profile[0].ProfileHeader = new ProfileHeader_DataType + { + ProfileIdentification = "CANopen device profile", + ProfileRevision = "1.1", + ProfileName = "", + ProfileSource = "", + ProfileClassID = ProfileClassID_DataType.Device, + ISO15745Reference = new ISO15745Reference_DataType + { + ISO15745Part = "1", + ISO15745Edition = "1", + ProfileTechnology = "CANopen" + } + }; + container.ISO15745Profile[0].ProfileBody = new ProfileBody_Device_CANopen(); + var body_device = (ProfileBody_Device_CANopen)container.ISO15745Profile[0].ProfileBody; + + container.ISO15745Profile[1].ProfileHeader = new ProfileHeader_DataType + { + ProfileIdentification = "CANopen communication network profile", + ProfileRevision = "1.1", + ProfileName = "", + ProfileSource = "", + ProfileClassID = ProfileClassID_DataType.CommunicationNetwork, + ISO15745Reference = new ISO15745Reference_DataType + { + ISO15745Part = "1", + ISO15745Edition = "1", + ProfileTechnology = "CANopen" + } + }; + container.ISO15745Profile[1].ProfileBody = new ProfileBody_CommunicationNetwork_CANopen(); + var body_network = (ProfileBody_CommunicationNetwork_CANopen)container.ISO15745Profile[1].ProfileBody; + + #endregion + + #region ObjectDictionary + var body_network_objectList = new List(); + var body_device_parameterList = new List(); + var body_device_arrayList = new List(); + var body_device_structList = new List<@struct>(); + + foreach (var kvp in dev.Objects) + { + string index = kvp.Key; + Int16 indexInt; + OdObject entry = kvp.Value; + + + try + { + indexInt = System.Convert.ToInt16(index, 16); + } + catch (Exception) + { + Warnings.AddWarning($"Error in Object ({index}), wrong index", Warnings.warning_class.WARNING_GENERIC); + continue; + } + + if (stripped && entry.Disabled) + continue; + + var netObj = new CANopenObjectListCANopenObject + { + index = new byte[] { (byte)(indexInt >> 8), (byte)(indexInt & 0xFF) }, + name = entry.Name, + objectType = (byte)entry.Type, + uniqueIDRef = "UID_OBJ_" + index + }; + body_network_objectList.Add(netObj); + + var devPar = new parameter { uniqueID = "UID_OBJ_" + index }; + if (entry.Description != null && entry.Description != "") + { + devPar.Items = new object[] { new vendorTextDescription { lang = "en", Value = entry.Description } }; + } + else + { + // Add at least label made from parameter name, because g_labels is required by schema + devPar.Items = new object[] { new vendorTextLabel { lang = "en", Value = entry.Name } }; + } + if (deviceCommissioning && entry.Alias != null && entry.Alias != "") + { + devPar.denotation = new denotation + { + Items = new object[] { new vendorTextLabel { lang = "en", Value = entry.Alias } } + }; + } + body_device_parameterList.Add(devPar); + + if (entry.Type == LibCanOpen.OdObject.Types.ObjectType.Var) + { + if (entry.SubObjects.Count != 1) + { + Warnings.AddWarning($"Error in Object ({index}), VAR must have one subobject", Warnings.warning_class.WARNING_GENERIC); + continue; + } + var subEntry0 = entry.SubObjects[entry.SubObjects.Keys.First()]; + switch (subEntry0.Pdo) + { + case LibCanOpen.OdSubObject.Types.AccessPDO.R: netObj.PDOmapping = CANopenObjectListCANopenObjectPDOmapping.RPDO; break; + case LibCanOpen.OdSubObject.Types.AccessPDO.T: netObj.PDOmapping = CANopenObjectListCANopenObjectPDOmapping.TPDO; break; + case LibCanOpen.OdSubObject.Types.AccessPDO.Tr: netObj.PDOmapping = CANopenObjectListCANopenObjectPDOmapping.optional; break; + default: netObj.PDOmapping = CANopenObjectListCANopenObjectPDOmapping.no; break; + } + + netObj.PDOmappingSpecified = true; + + if (!stripped) + { + var propOd = ConvertXddProperties(entry); + var propSub = ConvertXddProperties(subEntry0); + devPar.property = new property[propOd.Length + propSub.Length]; + propOd.CopyTo(devPar.property, 0); + propSub.CopyTo(devPar.property, propOd.Length); + } + + WriteVar(devPar, subEntry0); + if (deviceCommissioning && subEntry0.ActualValue != null && subEntry0.ActualValue != "") + devPar.actualValue = new actualValue { value = subEntry0.ActualValue }; + } + else if ((entry.Type == LibCanOpen.OdObject.Types.ObjectType.Array || entry.Type == LibCanOpen.OdObject.Types.ObjectType.Record) && entry.SubObjects != null && entry.SubObjects.Count > 0) + { + netObj.subNumber = (byte)entry.SubObjects.Count; + netObj.subNumberSpecified = true; + + if (!stripped) + devPar.property = ConvertXddProperties(entry); + + var netSubObjList = new List(); + var devStructSubList = new List(); + ItemChoiceType ArrayItemElementName = ItemChoiceType.SINT; + + foreach (var subKvp in entry.SubObjects) + { + string subIndex = subKvp.Key; + byte subIndexInt; + OdSubObject subEntry = subKvp.Value; + + try + { + subIndexInt = System.Convert.ToByte(subIndex, 16); + } + catch (Exception) + { + Warnings.AddWarning($"Error in Object ({index}), wrong SubIndex", Warnings.warning_class.WARNING_GENERIC); + continue; + } + + var netSubObj = new CANopenObjectListCANopenObjectCANopenSubObject + { + subIndex = new byte[] { subIndexInt }, + name = subEntry.Name, + objectType = (byte)LibCanOpen.OdObject.Types.ObjectType.Var, + PDOmappingSpecified = true, + uniqueIDRef = "UID_SUB_" + index + subIndex + }; + switch (subEntry.Pdo) + { + case LibCanOpen.OdSubObject.Types.AccessPDO.R: netSubObj.PDOmapping = CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.RPDO; break; + case LibCanOpen.OdSubObject.Types.AccessPDO.T: netSubObj.PDOmapping = CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.TPDO; break; + case LibCanOpen.OdSubObject.Types.AccessPDO.Tr: netSubObj.PDOmapping = CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.optional; break; + default: netSubObj.PDOmapping = CANopenObjectListCANopenObjectCANopenSubObjectPDOmapping.no; break; + } + + var devSubPar = new parameter + { + uniqueID = "UID_SUB_" + index + subIndex + }; + // Add at least label made from parameter name, because g_labels is required by schema + devSubPar.Items = new object[] { new vendorTextLabel { lang = "en", Value = subEntry.Name } }; + + if (!stripped) + devSubPar.property = ConvertXddProperties(subEntry); + + if (deviceCommissioning && subEntry.Alias != null && subEntry.Alias != "") + { + devPar.denotation = new denotation + { + Items = new object[] { new vendorTextLabel { lang = "en", Value = subEntry.Alias } } + }; + } + WriteVar(devSubPar, subEntry); + + if (deviceCommissioning && subEntry.ActualValue != null && subEntry.ActualValue != "") + devPar.actualValue = new actualValue { value = subEntry.ActualValue }; + + if (entry.Type == LibCanOpen.OdObject.Types.ObjectType.Record) + { + devStructSubList.Add(new varDeclaration + { + name = subEntry.Name, + uniqueID = "UID_RECSUB_" + index + subIndex, + Item = new object(), + ItemElementName = (ItemChoiceType1)ConvertDataType(subEntry) + }); + } + else + { + ArrayItemElementName = (ItemChoiceType)ConvertDataType(subEntry); + } + + body_device_parameterList.Add(devSubPar); + netSubObjList.Add(netSubObj); + } + + // add refference to data type definition and definition of array or struct data type (schema requirement) + if (entry.Type == LibCanOpen.OdObject.Types.ObjectType.Array) + { + devPar.Items1 = new object[] { new dataTypeIDRef { uniqueIDRef = "UID_ARR_" + index } }; + devPar.Items1ElementName = new Items1ChoiceType[] { Items1ChoiceType.dataTypeIDRef }; + body_device_arrayList.Add(new array + { + uniqueID = "UID_ARR_" + index, + name = entry.Name, + Item = new object(), + ItemElementName = ArrayItemElementName, + subrange = new subrange[] { new subrange { lowerLimit = 0, upperLimit = entry.SubObjects.Count - 1 } } + }); + } + else + { + devPar.Items1 = new object[] { new dataTypeIDRef { uniqueIDRef = "UID_REC_" + index } }; + devPar.Items1ElementName = new Items1ChoiceType[] { Items1ChoiceType.dataTypeIDRef }; + body_device_structList.Add(new @struct + { + uniqueID = "UID_REC_" + index, + name = entry.Name, + varDeclaration = devStructSubList.ToArray() + }); + } + + netObj.CANopenSubObject = netSubObjList.ToArray(); + } + } + #endregion + + #region body_device + body_device.fileName = fileName; + body_device.fileCreator = dev.FileInfo.CreatedBy; + body_device.fileCreationDate = dev.FileInfo.CreationTime.ToDateTime(); + body_device.fileCreationTime = dev.FileInfo.CreationTime.ToDateTime(); + body_device.fileCreationTimeSpecified = true; + body_device.fileVersion = dev.FileInfo.FileVersion; + body_device.fileModifiedBy = dev.FileInfo.ModifiedBy; + body_device.fileModificationDate = dev.FileInfo.ModificationTime.ToDateTime(); + body_device.fileModificationTime = dev.FileInfo.ModificationTime.ToDateTime(); + body_device.fileModificationDateSpecified = true; + body_device.fileModificationTimeSpecified = true; + body_device.supportedLanguages = "en"; + + // Device identity + if (body_device.DeviceIdentity == null) + body_device.DeviceIdentity = new DeviceIdentity(); + body_device.DeviceIdentity.vendorName = new vendorName { Value = dev.DeviceInfo.VendorName }; + body_device.DeviceIdentity.vendorID = new vendorID { Value = "0" }; + body_device.DeviceIdentity.productName = new productName { Value = dev.DeviceInfo.ProductName }; + body_device.DeviceIdentity.productID = new productID { Value = "0" }; + if (dev.FileInfo.Description != null && dev.FileInfo.Description != "") + { + body_device.DeviceIdentity.productText = new productText + { + Items = new object[] + { + new vendorTextDescription { lang = "en", Value = dev.FileInfo.Description } + } + }; + } + + // version is optional element, make a template if empty + if (body_device.DeviceIdentity.version == null) + { + body_device.DeviceIdentity.version = new version[] + { + new version { versionType = versionVersionType.SW, Value = "0" }, + new version { versionType = versionVersionType.FW, Value = "0" }, + new version { versionType = versionVersionType.HW, Value = "0" } + }; + } + + // DeviceFunction is required by schema, make a template if empty. + if (body_device.DeviceFunction == null) + { + // This is just a template for somehow complex xml structure. Users can edit the + // xdd file directly to write characteristics of own devices or use generic xml + // editing tool. External editing will be preserved anyway, if xdd file will be + // later opened and saved back in EDSEditor. + // EDSEditor curerently does not have interface for editing the characteristics. + body_device.DeviceFunction = new DeviceFunction[] + { + new DeviceFunction + { + capabilities = new capabilities + { + characteristicsList = new characteristicsList[] + { + new characteristicsList + { + characteristic = new characteristic[] + { + new characteristic + { + characteristicName = new characteristicName + { + Items = new object[] + { + new vendorTextLabel { lang = "en", Value = "SW library" } + } + }, + characteristicContent = new characteristicContent[] + { + new characteristicContent { + Items = new object[] + { + new vendorTextLabel { lang = "en", Value = "libedssharp" } + } + }, + new characteristicContent { + Items = new object[] + { + new vendorTextLabel { lang = "en", Value = "CANopenNode" } + } + } + } + } + } + } + } + } + } + }; + } + + // ApplicationProcess (insert object dictionary) + if (body_device.ApplicationProcess == null) + body_device.ApplicationProcess = new ApplicationProcess[1]; + if (body_device.ApplicationProcess[0] == null) + body_device.ApplicationProcess[0] = new ApplicationProcess(); + body_device.ApplicationProcess[0].dataTypeList = new dataTypeList + { + array = body_device_arrayList.ToArray(), + @struct = body_device_structList.ToArray() + }; + body_device.ApplicationProcess[0].parameterList = body_device_parameterList.ToArray(); + #endregion + + #region body_network + body_network.fileName = fileName; + body_network.fileCreator = dev.FileInfo.CreatedBy; + body_network.fileCreationDate = dev.FileInfo.CreationTime.ToDateTime(); + body_network.fileCreationTime = dev.FileInfo.CreationTime.ToDateTime(); + body_network.fileCreationTimeSpecified = true; + body_network.fileVersion = dev.FileInfo.FileVersion; + body_network.fileModificationDate = dev.FileInfo.ModificationTime.ToDateTime(); + body_network.fileModificationTime = dev.FileInfo.ModificationTime.ToDateTime(); + body_network.fileModificationDateSpecified = true; + body_network.fileModificationTimeSpecified = true; + body_network.supportedLanguages = "en"; + + // base elements + ProfileBody_CommunicationNetwork_CANopenApplicationLayers ApplicationLayers = null; + ProfileBody_CommunicationNetwork_CANopenTransportLayers TransportLayers = null; + ProfileBody_CommunicationNetwork_CANopenNetworkManagement NetworkManagement = null; + if (body_network.Items != null && body_network.Items.Length >= 3) + { + foreach (object item in body_network.Items) + { + if (item.GetType() == typeof(ProfileBody_CommunicationNetwork_CANopenApplicationLayers)) + ApplicationLayers = (ProfileBody_CommunicationNetwork_CANopenApplicationLayers)item; + else if (item.GetType() == typeof(ProfileBody_CommunicationNetwork_CANopenApplicationLayers)) + TransportLayers = (ProfileBody_CommunicationNetwork_CANopenTransportLayers)item; + else if (item.GetType() == typeof(ProfileBody_CommunicationNetwork_CANopenApplicationLayers)) + NetworkManagement = (ProfileBody_CommunicationNetwork_CANopenNetworkManagement)item; + } + } + if (ApplicationLayers == null || TransportLayers == null || NetworkManagement == null) + { + body_network.Items = new object[3]; + body_network.Items[0] = new ProfileBody_CommunicationNetwork_CANopenApplicationLayers(); + ApplicationLayers = (ProfileBody_CommunicationNetwork_CANopenApplicationLayers)body_network.Items[0]; + body_network.Items[1] = new ProfileBody_CommunicationNetwork_CANopenTransportLayers(); + TransportLayers = (ProfileBody_CommunicationNetwork_CANopenTransportLayers)body_network.Items[1]; + body_network.Items[2] = new ProfileBody_CommunicationNetwork_CANopenNetworkManagement(); + NetworkManagement = (ProfileBody_CommunicationNetwork_CANopenNetworkManagement)body_network.Items[2]; + } + + // ApplicationLayers -> dummyUsage + ApplicationLayers.dummyUsage = new ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy[7]; + for (int x = 0; x < 7; x++) + ApplicationLayers.dummyUsage[x] = new ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummy(); + + ApplicationLayers.dummyUsage[0].entry = ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry.Dummy00010; + ApplicationLayers.dummyUsage[1].entry = ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry.Dummy00021; + ApplicationLayers.dummyUsage[2].entry = ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry.Dummy00031; + ApplicationLayers.dummyUsage[3].entry = ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry.Dummy00041; + ApplicationLayers.dummyUsage[4].entry = ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry.Dummy00051; + ApplicationLayers.dummyUsage[5].entry = ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry.Dummy00061; + ApplicationLayers.dummyUsage[6].entry = ProfileBody_CommunicationNetwork_CANopenApplicationLayersDummyEntry.Dummy00071; + + // ApplicationLayers -> CANopenObjectList (insert object dictionary) + ApplicationLayers.CANopenObjectList = new CANopenObjectList + { + CANopenObject = body_network_objectList.ToArray() + }; + + // TransportLayers -> supportedBaudRate + List bauds; + bauds = new List(); + if (dev.DeviceInfo.BaudRate10) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item10Kbps); + if (dev.DeviceInfo.BaudRate20) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item20Kbps); + if (dev.DeviceInfo.BaudRate50) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item50Kbps); + if (dev.DeviceInfo.BaudRate125) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item125Kbps); + if (dev.DeviceInfo.BaudRate250) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item250Kbps); + if (dev.DeviceInfo.BaudRate500) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item500Kbps); + if (dev.DeviceInfo.BaudRate800) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item800Kbps); + if (dev.DeviceInfo.BaudRate1000) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.Item1000Kbps); + if (dev.DeviceInfo.BaudRateAuto) + bauds.Add(ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRateValue.autobaudRate); + TransportLayers.PhysicalLayer = new ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayer + { + baudRate = new ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRate + { + supportedBaudRate = new ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate[bauds.Count] + } + }; + for (int i = 0; i < bauds.Count; i++) + { + TransportLayers.PhysicalLayer.baudRate.supportedBaudRate[i] = new ProfileBody_CommunicationNetwork_CANopenTransportLayersPhysicalLayerBaudRateSupportedBaudRate + { + value = bauds[i] + }; + } + + // NetworkManagement + if (NetworkManagement.CANopenGeneralFeatures == null) + NetworkManagement.CANopenGeneralFeatures = new ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenGeneralFeatures(); + NetworkManagement.CANopenGeneralFeatures.granularity = 8; // required parameter + NetworkManagement.CANopenGeneralFeatures.nrOfRxPDO = 4; //extract from OD + NetworkManagement.CANopenGeneralFeatures.nrOfTxPDO = 4; //extract from OD + + NetworkManagement.CANopenGeneralFeatures.ngSlave = false; + NetworkManagement.CANopenGeneralFeatures.ngMaster = false; + NetworkManagement.CANopenGeneralFeatures.NrOfNG_MonitoredNodes = 0; + + NetworkManagement.CANopenGeneralFeatures.layerSettingServiceSlave = dev.DeviceInfo.LssSlave; + NetworkManagement.CANopenGeneralFeatures.groupMessaging = false; + NetworkManagement.CANopenGeneralFeatures.dynamicChannels = 0; + + if (NetworkManagement.CANopenMasterFeatures == null) + NetworkManagement.CANopenMasterFeatures = new ProfileBody_CommunicationNetwork_CANopenNetworkManagementCANopenMasterFeatures(); + NetworkManagement.CANopenMasterFeatures.layerSettingServiceMaster = dev.DeviceInfo.LssMaster; + NetworkManagement.CANopenMasterFeatures.bootUpMaster = false; + + if (deviceCommissioning) + { + NetworkManagement.deviceCommissioning = new ProfileBody_CommunicationNetwork_CANopenNetworkManagementDeviceCommissioning + { + NodeID = (byte)dev.DeviceCommissioning.NodeId, + nodeName = dev.DeviceCommissioning.NodeName, + actualBaudRate = dev.DeviceCommissioning.Baudrate.ToString() + }; + } + else + { + NetworkManagement.deviceCommissioning = null; + } + #endregion + + return container; + } + } } diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 3bd702cb..a5c42523 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -23,6 +23,21 @@ - + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libEDSsharp/proto/.gitignore b/libEDSsharp/proto/.gitignore new file mode 100644 index 00000000..8143e15f --- /dev/null +++ b/libEDSsharp/proto/.gitignore @@ -0,0 +1 @@ +*.cs diff --git a/libEDSsharp/proto/CanOpen.proto b/libEDSsharp/proto/CanOpen.proto new file mode 100644 index 00000000..bff4c332 --- /dev/null +++ b/libEDSsharp/proto/CanOpen.proto @@ -0,0 +1,168 @@ +syntax = "proto3"; + +package LibCanOpen; + +import "google/protobuf/timestamp.proto"; + +/* File information related properties. */ +message CanOpen_FileInfo +{ + string fileVersion = 1; // Actual file version (as string). + string description = 2; // File description. + google.protobuf.Timestamp creationTime = 3; // File creation time. + string createdBy = 4; // Name or a description of the file creator. + google.protobuf.Timestamp modificationTime = 5; // Time of the last modification. + string modifiedBy = 6; // Name or a description of the creator. +} + +/* CANopen device information related properties. */ +message CanOpen_DeviceInfo +{ + string vendorName = 1; // Vendor name. + string productName = 3; // Product name. + bool baudRate10 = 100; // Support of the baud rate 10 kbit/s. + bool baudRate20 = 101; // Support of the baud rate 20 kbit/s. + bool baudRate50 = 102; // Support of the baud rate 50 kbit/s. + bool baudRate125 = 103; // Support of the baud rate 125 kbit/s. + bool baudRate250 = 104; // Support of the baud rate 250 kbit/s. + bool baudRate500 = 105; // Support of the baud rate 500 kbit/s. + bool baudRate800 = 106; // Support of the baud rate 800 kbit/s. + bool baudRate1000 = 107; // Support of the baud rate 1000 kbit/s. + bool baudRateAuto = 108; // Support of the auto baud rate. + bool lssSlave = 150; // Support of the LSS slave functionality. + bool lssMaster = 151; // Support of the LSS master functionality. +} + +/* Actual CANopen device properties. */ +message CanOpen_DeviceCommissioning +{ + uint32 nodeId = 1; // CANopen device’s address. + string nodeName = 2; // Node name. + uint32 baudrate = 3; // CANopen device’s baudrate. +} + +/* Object Dictionary SubEntry on specific Subindex. Sorted dictionary of them is part of the OdEntry. If OdEntry + * ObjectType is "record", then each SubEntry in the dictionary may be unique. If OdEntry ObjectType is "array", + * then some properties of all SubEntries must be equal. If OdEntry ObjectType is "var", then one SubEntry exists. */ +message OdSubObject +{ + /* Object dictionary basic data types from CiA 301. */ + enum DataType + { + UNSPECIFIED = 0x00; // Unspecified, should not be used. + BOOLEAN = 0x01; // Boolean. + INTEGER8 = 0x02; // 8-bit signed integer. + INTEGER16 = 0x03; // 16-bit signed integer. + INTEGER32 = 0x04; // 32-bit signed integer. + UNSIGNED8 = 0x05; // 8-bit unsigned integer. + UNSIGNED16 = 0x06; // 16-bit unsigned integer. + UNSIGNED32 = 0x07; // 32-bit unsigned integer. + REAL32 = 0x08; // 32-bit floating point number. + VISIBLE_STRING = 0x09; /* Null terminated string (8-bit chars). It may contain control characters and UTF-8 + * characters. StringLengthMin specifies minimum buffer length for the string. */ + OCTET_STRING = 0x0A; // Fixed length array of bytes. + UNICODE_STRING = 0x0B; /* Null terminated string (16-bit chars). Not recommended to use. + * StringLengthMin specifies minimum buffer length for the string. */ + TIME_OF_DAY = 0x0C; // 48 bit long structure. + TIME_DIFFERENCE = 0x0D; // 48 bit long structure. + DOMAIN = 0x0F; // Data block of any length, don't have default value. + INTEGER24 = 0x10; // 24-bit signed integer, should not be used. + REAL64 = 0x11; // 64-bit floating point number. + INTEGER40 = 0x12; // 40-bit signed integer, should not be used. + INTEGER48 = 0x13; // 48-bit signed integer, should not be used. + INTEGER56 = 0x14; // 56-bit signed integer, should not be used. + INTEGER64 = 0x15; // 64-bit signed integer. + UNSIGNED24 = 0x16; // 24-bit unsigned integer, should not be used. + UNSIGNED40 = 0x18; // 40-bit unsigned integer, should not be used. + UNSIGNED48 = 0x19; // 48-bit unsigned integer, should not be used. + UNSIGNED56 = 0x1A; // 56-bit unsigned integer, should not be used. + UNSIGNED64 = 0x1B; // 64-bit unsigned integer. + } + + /* CANopen SDO access permissions. */ + enum AccessSDO + { + ACCESS_SDO_NO = 0; // No access. + ACCESS_SDO_RO = 1; // Read only access. + ACCESS_SDO_WO = 2; // Write only access. + ACCESS_SDO_RW = 3; // Read and write access. + } + + /* CANopen PDO access permissions. */ + enum AccessPDO + { + ACCESS_PDO_NO = 0; // No access. + ACCESS_PDO_T = 1; // TPDO access. + ACCESS_PDO_R = 2; // RPDO access. + ACCESS_PDO_TR = 3; // TPDO and RPDO access. + } + + /* CANopen SRDO access permissions. */ + enum AccessSRDO + { + ACCESS_SRDO_NO = 0; // no access. + ACCESS_SRDO_TX = 1; // SRDO TX access. + ACCESS_SRDO_RX = 2; // SRDO RX access. + ACCESS_SRDO_TRX = 3; // SRDO TX or RX access. + } + + string name = 1; // Name of the sub entry. If OdEntry is "VAR", this property is not relevant. + string alias = 2; // Additonal sub parameter name, for the actual device. If OdEntry is "VAR", this property is not relevant. + DataType type = 3; // CANopen data type + AccessSDO sdo = 4; // CANopen SDO access permissions + AccessPDO pdo = 5; // CANopen PDO access permissions + AccessSRDO srdo = 6; // CANopen SRDO access permissions. + string defaultValue = 7; // Default value of the sub object. + string actualValue = 8; // Actual value of the sub object, for the actual device. + string lowLimit = 9; // Low limit for the value. + string highLimit = 10; // High limit for the value. + uint32 stringLengthMin = 101; // CanOpenNode OD exporter V4: Minimum length of a string that can be stored. +} + +/* Object Dictionary Entry on specific Index. Sorted dictionary of them is part of CanOpenDevice - CANopen Object Dictionary. */ +message OdObject +{ + /* Type of Object Dictionary entry, similar as Object Code from CiA 301. */ + enum ObjectType + { + // Not defined, default + OBJECT_TYPE_UNSPECIFIED = 0; + // A single value such as an UNSIGNED8, BOOLEAN, FLOAT, INTEGER16, VISIBLE STRING etc. + OBJECT_TYPE_VAR = 7; + // A multiple data field object where each data field is a simple variable of the SAME basic data type e.g. array + // of UNSIGNED16 etc. Sub-index 0 is of UNSIGNED8. + OBJECT_TYPE_ARRAY = 8; + // A multiple data field object where the data fields may be any combination of + // simple variables. Sub-index 0 is of UNSIGNED8 and sub-index 255 is of UNSIGNED32. + OBJECT_TYPE_RECORD = 9; + } + + // If true, object is completelly skipped by CANopenNode exporters, etc. + bool disabled = 1; + // Name of the entry. + string name = 2; + // Additonal parameter name, for the actual device. + string alias = 3; + // Description of the Entry. + string description = 4; + // CANopen Object Type. + ObjectType type = 5; + // CanOpenNode OD exporter V4: it will generate a macro for each different CO_countLabel. For example, if four + // OD objects have "CO_countLabel" set to "TPDO", then macro "#define ODxyz_CNT_TPDO 4" will be generated by the OD exporter. + string countLabel = 101; + // CanOpenNode OD exporter V4: storage group into which the C variable will belong. If not defined, it will default to "RAM". + string storageGroup = 102; + // CanOpenNode OD exporter V1.3: Flags for the PDO. + bool flagsPDO = 103; + // Sorted dictionary of sub entries + map subObjects = 200; +} + +/* CANopen Device description object. */ +message CanOpenDevice +{ + CanOpen_FileInfo fileInfo = 1; // File information related properties. + CanOpen_DeviceInfo deviceInfo = 2; //CANopen device information related properties. + CanOpen_DeviceCommissioning deviceCommissioning = 3; // Parameters of the actual CANopen device. + map objects = 200; // CANopen Object Dictionary as sorted dictionary. +} From b0f439a5b1d5f4ad3bfcd8eb72c96ba749bf2f3e Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Thu, 18 Jul 2024 09:40:05 +0200 Subject: [PATCH 148/226] Divided the DocumentationGen into DocumentationGenHtml & DocumentationMarkup (#120) --- EDSEditorGUI/Form1.cs | 11 +- libEDSsharp/DocumentationGenHtml.cs | 193 ++++++++++++++++++ ...tationGen.cs => DocumentationGenMarkup.cs} | 144 +------------ 3 files changed, 200 insertions(+), 148 deletions(-) create mode 100644 libEDSsharp/DocumentationGenHtml.cs rename libEDSsharp/{DocumentationGen.cs => DocumentationGenMarkup.cs} (71%) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 3a5f3278..63c45481 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -621,7 +621,7 @@ void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripp break; case ".md": - DocumentationGen docgen = new DocumentationGen(); + DocumentationGenMarkup docgen = new DocumentationGenMarkup(); docgen.genmddoc(FileName, dv.eds, this.gitVersion); dv.eds.mdfilename = FileName; break; @@ -1028,9 +1028,10 @@ private void documentationToolStripMenuItem_Click(object sender, EventArgs e) this.UseWaitCursor = true; - DocumentationGen docgen = new DocumentationGen(); - docgen.genhtmldoc(temp, dv.eds); - docgen.genmddoc(temp2, dv.eds, this.gitVersion); + DocumentationGenHtml docgenHtml = new DocumentationGenHtml(); + docgenHtml.genhtmldoc(temp, dv.eds); + DocumentationGenMarkup docgenMarkup = new DocumentationGenMarkup(); + docgenMarkup.genmddoc(temp2, dv.eds, this.gitVersion); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("cmd", $"/c start {temp2}")); @@ -1092,7 +1093,7 @@ private void saveExportAllToolStripMenuItem_Click(object sender, EventArgs e) if (dv.eds.mdfilename != null && dv.eds.mdfilename != "") { - DocumentationGen docgen = new DocumentationGen(); + DocumentationGenMarkup docgen = new DocumentationGenMarkup(); docgen.genmddoc(dv.eds.mdfilename, dv.eds, this.gitVersion); cnt++; } diff --git a/libEDSsharp/DocumentationGenHtml.cs b/libEDSsharp/DocumentationGenHtml.cs new file mode 100644 index 00000000..a2717025 --- /dev/null +++ b/libEDSsharp/DocumentationGenHtml.cs @@ -0,0 +1,193 @@ +/* + This file is part of libEDSsharp. + + libEDSsharp is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + libEDSsharp is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with libEDSsharp. If not, see . + + Copyright(c) 2016 - 2019 Robin Cornelius + Copyright(c) 2020 Janez Paternoster +*/ + +using System; +using System.Collections.Generic; +using System.IO; + +namespace libEDSsharp +{ + /// + /// Documentation generator + /// + public class DocumentationGenHtml + { + StreamWriter file = null; + + /// + /// Generate html documentation + /// + /// where the documentation should be saved + /// data to generate the documentation from + public void genhtmldoc(string filepath, EDSsharp eds) + { + + file = new StreamWriter(filepath, false); + file.NewLine = "\n"; + + file.Write(""); + + file.Write(string.Format("

{0} Documentation

",eds.di.ProductName)); + + file.Write("

Device Information

"); + + file.Write(""); + write2linetableheader("Product name", eds.di.ProductName); + write2linetableheader("Product number", eds.di.ProductNumber); + write2linetableheader("Revision number", eds.di.RevisionNumber); + write2linetableheader("Vendor name", eds.di.VendorName); + file.Write("
"); + + file.Write("

Mandatory objects

"); + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + if (od.prop.CO_disabled == true) + continue; + + if (od.Index == 0x1000 || od.Index == 0x1001 || od.Index == 0x1018) + { + writeODentryhtml(od); + } + } + + file.Write("

Optional objects

"); + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + if (od.prop.CO_disabled == true) + continue; + + if ((od.Index > 0x1001 && od.Index != 0x1018 && od.Index<0x2000) || od.Index>=0x6000) + { + writeODentryhtml(od); + } + } + + file.Write("

Manufacturer specific objects

"); + + foreach (KeyValuePair kvp in eds.ods) + { + ODentry od = kvp.Value; + if (od.prop.CO_disabled == true) + continue; + + if (od.Index >= 0x2000 && od.Index<0x6000) + { + writeODentryhtml(od); + } + } + + + file.Write(""); + + file.Close(); + + + } + /// + /// Write a object dictionary html entry to file + /// + /// Object dictionary entry + void writeODentryhtml(ODentry od) + { + if (od.parent == null) + { + file.Write("
"); + file.Write(String.Format("

0x{0:x4} - {1}

", od.Index, od.parameter_name)); + } + else + { + file.Write(String.Format("

0x{0:x4} sub 0x{2:x2} - {1}

", od.Index, od.parameter_name,od.Subindex)); + } + + file.Write(""); + write2linetableheader("Parameter", "Value"); + + ObjectType ot = od.objecttype; + if (ot == ObjectType.UNKNOWN && od.parent != null) + ot = od.parent.objecttype; + + write2linetablerow("Object Type", ot.ToString()); + + DataType dt = od.datatype; + if (dt == DataType.UNKNOWN && od.parent != null) + dt = od.parent.datatype; + + write2linetablerow("Data Type", dt.ToString()); + write2linetablerow("Default Value", od.defaultvalue); + + write2linetablerow("Location", od.prop.CO_storageGroup); + write2linetablerow("Access type", od.accesstype.ToString()); + write2linetablerow("PDO mapping", od.PDOMapping); + write2linetablerow("No Sub index", od.Nosubindexes); + + file.Write("
"); + + string description = od.Description; + file.Write(string.Format("
{0}
", description)); + + foreach (KeyValuePair sub in od.subobjects) + { + ODentry subod = sub.Value; + writeODentryhtml(subod); + } + + } + /// + /// Write a html table row with 2 elements to file + /// + /// element a + /// element b + void write2linetablerow(string a,object b) + { + if (b == null) + b = ""; + file.Write("{0}{1}", a, b.ToString()); + } + /// + /// Write a html table header with 2 elements to file + /// + /// + /// + void write2linetableheader(string a, object b) + { + file.Write("{0}{1}",a,b.ToString()); + } + /// + /// Returns the datatype of a object dictionary + /// + /// the object dictionary entry + /// datatype of the OD entry + string PrintDataType(ODentry od) + { + string dt = od.datatype.ToString(); + if ((od.datatype == DataType.VISIBLE_STRING || od.datatype == DataType.UNICODE_STRING) + && od.prop.CO_stringLengthMin > od.defaultvalue.Length) + { + dt += $" (len={od.prop.CO_stringLengthMin})"; + } + + return dt; + } + } +} diff --git a/libEDSsharp/DocumentationGen.cs b/libEDSsharp/DocumentationGenMarkup.cs similarity index 71% rename from libEDSsharp/DocumentationGen.cs rename to libEDSsharp/DocumentationGenMarkup.cs index b5aef6a1..798dbf39 100644 --- a/libEDSsharp/DocumentationGen.cs +++ b/libEDSsharp/DocumentationGenMarkup.cs @@ -27,152 +27,10 @@ namespace libEDSsharp /// /// Documentation generator /// - public class DocumentationGen + public class DocumentationGenMarkup { StreamWriter file = null; - /// - /// Generate html documentation - /// - /// where the documentation should be saved - /// data to generate the documentation from - public void genhtmldoc(string filepath, EDSsharp eds) - { - - file = new StreamWriter(filepath, false); - file.NewLine = "\n"; - - file.Write(""); - - file.Write(string.Format("

{0} Documentation

",eds.di.ProductName)); - - file.Write("

Device Information

"); - - file.Write(""); - write2linetableheader("Product name", eds.di.ProductName); - write2linetableheader("Product number", eds.di.ProductNumber); - write2linetableheader("Revision number", eds.di.RevisionNumber); - write2linetableheader("Vendor name", eds.di.VendorName); - file.Write("
"); - - file.Write("

Mandatory objects

"); - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - if (od.prop.CO_disabled == true) - continue; - - if (od.Index == 0x1000 || od.Index == 0x1001 || od.Index == 0x1018) - { - writeODentryhtml(od); - } - } - - file.Write("

Optional objects

"); - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - if (od.prop.CO_disabled == true) - continue; - - if ((od.Index > 0x1001 && od.Index != 0x1018 && od.Index<0x2000) || od.Index>=0x6000) - { - writeODentryhtml(od); - } - } - - file.Write("

Manufacturer specific objects

"); - - foreach (KeyValuePair kvp in eds.ods) - { - ODentry od = kvp.Value; - if (od.prop.CO_disabled == true) - continue; - - if (od.Index >= 0x2000 && od.Index<0x6000) - { - writeODentryhtml(od); - } - } - - - file.Write(""); - - file.Close(); - - - } - /// - /// Write a object dictionary html entry to file - /// - /// Object dictionary entry - void writeODentryhtml(ODentry od) - { - if (od.parent == null) - { - file.Write("
"); - file.Write(String.Format("

0x{0:x4} - {1}

", od.Index, od.parameter_name)); - } - else - { - file.Write(String.Format("

0x{0:x4} sub 0x{2:x2} - {1}

", od.Index, od.parameter_name,od.Subindex)); - } - - file.Write(""); - write2linetableheader("Parameter", "Value"); - - ObjectType ot = od.objecttype; - if (ot == ObjectType.UNKNOWN && od.parent != null) - ot = od.parent.objecttype; - - write2linetablerow("Object Type", ot.ToString()); - - DataType dt = od.datatype; - if (dt == DataType.UNKNOWN && od.parent != null) - dt = od.parent.datatype; - - write2linetablerow("Data Type", dt.ToString()); - write2linetablerow("Default Value", od.defaultvalue); - - write2linetablerow("Location", od.prop.CO_storageGroup); - write2linetablerow("Access type", od.accesstype.ToString()); - write2linetablerow("PDO mapping", od.PDOMapping); - write2linetablerow("No Sub index", od.Nosubindexes); - - file.Write("
"); - - string description = od.Description; - file.Write(string.Format("
{0}
", description)); - - foreach (KeyValuePair sub in od.subobjects) - { - ODentry subod = sub.Value; - writeODentryhtml(subod); - } - - } - /// - /// Write a html table row with 2 elements to file - /// - /// element a - /// element b - void write2linetablerow(string a,object b) - { - if (b == null) - b = ""; - file.Write("{0}{1}", a, b.ToString()); - } - /// - /// Write a html table header with 2 elements to file - /// - /// - /// - void write2linetableheader(string a, object b) - { - file.Write("{0}{1}",a,b.ToString()); - } /// /// Generate markup documentation /// From e2c5b9ea31d3ba84f6036cb98eb4440f727dbb0b Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Thu, 18 Jul 2024 09:40:28 +0200 Subject: [PATCH 149/226] 116 convert default profiles to xpd files (#118) * converted .xml profiles to .xpd profiles * Changed to project to copy all .xpd files to output directory * Removed traces of .xml support --- EDSEditorGUI/EDSEditorGUI.csproj | 8 +- EDSEditorGUI/Form1.cs | 7 +- EDSEditorGUI/Profiles/DS301_profile_old.xml | 392 ------ EDSEditorGUI/Profiles/DS301_profile_old.xpd | 969 +++++++++++++ EDSEditorGUI/Profiles/DSP302-NMTMaster.xml | 295 ---- EDSEditorGUI/Profiles/DSP302-NMTMaster.xpd | 1404 +++++++++++++++++++ 6 files changed, 2377 insertions(+), 698 deletions(-) delete mode 100644 EDSEditorGUI/Profiles/DS301_profile_old.xml create mode 100644 EDSEditorGUI/Profiles/DS301_profile_old.xpd delete mode 100644 EDSEditorGUI/Profiles/DSP302-NMTMaster.xml create mode 100644 EDSEditorGUI/Profiles/DSP302-NMTMaster.xpd diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 6a83635b..aa39e082 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -64,7 +64,7 @@ Component - + PreserveNewest @@ -85,12 +85,6 @@ - - PreserveNewest - - - PreserveNewest - Always diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 63c45481..f94216a0 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -84,7 +84,7 @@ private void loadprofiles() foreach (string file in profilelist) { string ext = Path.GetExtension(file).ToLower(); - if (ext == ".xml" || ext == ".xpd" || ext == ".xdd") + if (ext == ".xpd" || ext == ".xdd") { item = new ToolStripMenuItem(); item.Name = Path.GetFileName(file); @@ -116,11 +116,10 @@ void ProfileAddClick(object sender, EventArgs e) if (item.Name == "///openFile") { OpenFileDialog odf = new OpenFileDialog(); - odf.Filter = "All supported files (*.xpd;*.xdd;*.xdc;*.xml)|*.xpd;*.xdd;*.xdc;*.xml|" + odf.Filter = "All supported files (*.xpd;*.xdd;*.xdc)|*.xpd;*.xdd;*.xdc|" + "CANopen XPD 1.1 (*.xpd)|*.xpd|" + "CANopen XDD 1.1 (*.xdd)|*.xdd|" - + "CANopen XDC 1.1 (*.xdc)|*.xdc|" - + "CANopenNode XML, old (*.xml)|*.xml"; + + "CANopen XDC 1.1 (*.xdc)|*.xdc"; if (odf.ShowDialog() != DialogResult.OK) return; diff --git a/EDSEditorGUI/Profiles/DS301_profile_old.xml b/EDSEditorGUI/Profiles/DS301_profile_old.xml deleted file mode 100644 index e3d2ff57..00000000 --- a/EDSEditorGUI/Profiles/DS301_profile_old.xml +++ /dev/null @@ -1,392 +0,0 @@ - - - - - bit 0-15: Device profile number -bit 16-31: Additional information - - - bit 0: generic error -bit 1: current -bit 2: voltage -bit 3: temperature -bit 4: communication error (overrun, error state) -bit 5: device profile specific -bit 6: Reserved (always 0) -bit 7: manufacturer specific - - - bit 0-31: Not used by stack (available for user) - - - Number of Errors -bit 0-7: Zero can be written to erase error history - -Standard Error Field -bit 0-15: Error code as transmited in the Emergency object -bit 16-31: Manufacturer specific additional information - - - - - - - - - - - - - bit 0-10: COB-ID for SYNC object -bit 11-29: set to 0 -bit 30: 1(0) - node generates (does NOT generate) SYNC object -bit 31: set to 0 - - - bit 0-31: period of SYNC transmission in µs (0 = no transmission, no checking) - - - bit 0-31: window leghth after SYNC when PDOS must be transmited in µs, (0 = not used) - - - Name of the manufacturer as string - - - Name of the hardware version as string - - - Name of the software version as string. - - - The objects at index 100Ch and 100Dh include the guard time in milliseconds and the life time factor. - -The life time factor multiplied with the guard time gives the life time for the Life Guarding Protocol. It is - -0 if not used. - - - - The life time factor multiplied with the guard time gives the life time for the node guarding protocol. It is - -0 if not used. - - - - Writing value 0x65766173 ('s','a','v','e' from LSB to MSB) into this location stores all ROM variables into EEPROM. - - - - - Writing value 0x64616F6C ('l','o','a','d' from LSB to MSB) into this location restores all ROM and EEPROM variables after reset. (After reset read form EEPROM is not performed, so default values are used.) - - - - - Index 1012h defines the COB-ID of the Time-Stamp Object (TIME). Further, it defines whether the - -device consumes the TIME or whether the device generates the TIME. - - - - This object contains a time stamp with a resolution of 1 µs (see 9.3.2). It can be mapped into a PDO in - -order to define a high resolution time stamp message. (Note that the data type of the standard time - -stamp message (TIME) is fixed). Further application specific use is encouraged. - - - - bit 0-10: COB-ID -bit 11-30: set to 0 for 11 bit COB-ID -bit 31: 0(1) - node uses (does NOT use) Emergency object - - - bit 0-15: Inhibit time of emergency message in 100µs - - - max sub-index - -Consumer Heartbeat Time -bit 0-15: Heartbeat consumer time in ms (0 = node is not monitored) -bit 16-23: Node ID -bit 24-31: set to 0 - - - - - - - - bit 0-15: Heartbeat producer time in ms (0 = disable transmission) - - - max sub-index - -Vendor-ID -bit 0-31: Assigned by CiA - -Product code -bit 0-31: Manufacturer specific - -Revision number -bit 0-15: Minor revision num. (CANopen behavior has not changed) -bit 16-31: Major revision number (CANopen behavior has changed) - -Serial number -bit 0-31: Manufacturer specific - - - - - - - - If value is zero, then SYNC message is transmitted with data length 0. - -If Value is from 2 to 240, then SYNC message has one data byte, which contains the counter. - -Other values are reserved. - - - If error is detected and operating NMT state is NMT operational, this object defines behavior of the device. - -Value definition for all subindexes: - 0x00 - if operational, switch to NMT pre-operational - 0x01 - do nothing - 0x02 - switch to NMT stopped - -01 - Communication error - bus off or Heartbeat consumer error. -02 - Communication other error (critical errors - see 'Error status bits') except CAN bus passive but including bus off or Heartbeat consumer. -03 - Communication passive - any communication error including CAN bus passive. -04 - Generic error (critical errors - see 'Error status bits'). -05 - Device profile error - bit 5 in error register is set. -06 - Manufacturer specific error - bit 7 in error register is set. - - - - - - - - - - 0x1200 SDO server parameter -max sub-index - -COB-ID client to server (Receive SDO) -bit 0-31: 0x00000600 + Node ID - -COB-ID server to client (Transmit SDO) -bit 0-31: 0x00000580 + Node ID - - - -0x1201 - 0x127F SDO server parameter -max sub-index - -COB-ID client to server (Receive SDO) -bit 0-10: COB_ID -bit 11-30: Set to 0 -bit 31*: 0(1) - node uses (does NOT use) SDO - -COB-ID server to client (Transmit SDO) -bit 0-31: same as previous - -Node-ID of the SDO client -bit 0-7: Node ID (optional) - - - - - - 0x1280 - 0x12FF SDO client parameter -max sub-index - -COB-ID client to server (Transmit SDO) -bit 0-10: COB_ID -bit 11-30: Set to 0 -bit 31: 0(1) - node uses (does NOT use) SDO - -COB-ID server to client (Receive SDO) -bit 0-31: same as previous - -Node-ID of the SDO server -0-7: Node ID - - - - - - - 0x1400 - 0x15FF RPDO communication parameter -max sub-index - -COB-ID -bit 0-10: COB-ID for PDO, to change it bit 31 must be set -bit 11-29: set to 0 for 11 bit COB-ID -bit 30: 0(1) - rtr are allowed (are NOT allowed) for PDO -bit 31: 0(1) - node uses (does NOT use) PDO - -Transmission type -value = 0-240: reciving is synchronous, process after next reception of SYNC object -value = 241-253: not used -value = 254: manufacturer specific -value = 255: asynchronous - - - - - - 0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) -Number of mapped objects - -mapped object (subindex 1...8) -bit 0-7: data length in bits -bit 8-15: subindex from OD -bit 16-31: index from OD - - - - - - - - - - - - 0x1800 - 0x19FF TPDO communication parameter -max sub-index - -COB-ID -bit 0-10: COB-ID for PDO, to change it bit 31 must be set -bit 11-29: set to 0 for 11 bit COB-ID -bit 30: 0(1) - rtr are allowed (are NOT allowed) for PDO -bit 31: 0(1) - node uses (does NOT use) PDO - -Transmission type -value = 0: transmiting is synchronous, specification in device profile -value = 1-240: transmiting is synchronous after every N-th SYNC object -value = 241-251: not used -value = 252-253: Transmited only on reception of Remote Transmission Request -value = 254: manufacturer specific -value = 255: asinchronous, specification in device profile - -inhibit time -bit 0-15: Minimum time between transmissions of the PDO in 100µs. Zero disables functionality. - -event timer -bit 0-15: Time between periodic transmissions of the PDO in ms. Zero disables functionality. - -SYNC start value -value = 0: Counter of the SYNC message shall not be processed. -value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message. - - - - - - - - - 0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). -Number of mapped objects - -mapped object (subindex 1...8) -bit 0-7: data length in bits -bit 8-15: subindex from OD -bit 16-31: index from OD - - - - - - - - - - - - - - - VENDORNAME - 2 - New Product - 1 - - sdfsdsdf - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/EDSEditorGUI/Profiles/DS301_profile_old.xpd b/EDSEditorGUI/Profiles/DS301_profile_old.xpd new file mode 100644 index 00000000..c73b4dba --- /dev/null +++ b/EDSEditorGUI/Profiles/DS301_profile_old.xpd @@ -0,0 +1,969 @@ + + + + + + + CANopen device profile + 1.1 + + + Device + + 1 + 1 + CANopen + + + + + VENDORNAME + 2 + New Product + 1 + + sdfsdsdf + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bit 0-15: Device profile number +bit 16-31: Additional information + + + + + + bit 0: generic error +bit 1: current +bit 2: voltage +bit 3: temperature +bit 4: communication error (overrun, error state) +bit 5: device profile specific +bit 6: Reserved (always 0) +bit 7: manufacturer specific + + + + + bit 0-31: Not used by stack (available for user) + + + + + Number of Errors +bit 0-7: Zero can be written to erase error history + +Standard Error Field +bit 0-15: Error code as transmited in the Emergency object +bit 16-31: Manufacturer specific additional information + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bit 0-10: COB-ID for SYNC object +bit 11-29: set to 0 +bit 30: 1(0) - node generates (does NOT generate) SYNC object +bit 31: set to 0 + + + + + + bit 0-31: period of SYNC transmission in µs (0 = no transmission, no checking) + + + + + + bit 0-31: window leghth after SYNC when PDOS must be transmited in µs, (0 = not used) + + + + + + Name of the manufacturer as string + + + + + + Name of the hardware version as string + + + + + + Name of the software version as string. + + + + + + The objects at index 100Ch and 100Dh include the guard time in milliseconds and the life time factor. + +The life time factor multiplied with the guard time gives the life time for the Life Guarding Protocol. It is + +0 if not used. + + + + + The life time factor multiplied with the guard time gives the life time for the node guarding protocol. It is + +0 if not used. + + + + Writing value 0x65766173 ('s','a','v','e' from LSB to MSB) into this location stores all ROM variables into EEPROM. + + + + + + + + + + + + + + Writing value 0x64616F6C ('l','o','a','d' from LSB to MSB) into this location restores all ROM and EEPROM variables after reset. (After reset read form EEPROM is not performed, so default values are used.) + + + + + + + + + + + + + + Index 1012h defines the COB-ID of the Time-Stamp Object (TIME). Further, it defines whether the + +device consumes the TIME or whether the device generates the TIME. + + + + + This object contains a time stamp with a resolution of 1 µs (see 9.3.2). It can be mapped into a PDO in + +order to define a high resolution time stamp message. (Note that the data type of the standard time + +stamp message (TIME) is fixed). Further application specific use is encouraged. + + + + bit 0-10: COB-ID +bit 11-30: set to 0 for 11 bit COB-ID +bit 31: 0(1) - node uses (does NOT use) Emergency object + + + + + + bit 0-15: Inhibit time of emergency message in 100µs + + + + + + max sub-index + +Consumer Heartbeat Time +bit 0-15: Heartbeat consumer time in ms (0 = node is not monitored) +bit 16-23: Node ID +bit 24-31: set to 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + bit 0-15: Heartbeat producer time in ms (0 = disable transmission) + + + + + + max sub-index + +Vendor-ID +bit 0-31: Assigned by CiA + +Product code +bit 0-31: Manufacturer specific + +Revision number +bit 0-15: Minor revision num. (CANopen behavior has not changed) +bit 16-31: Major revision number (CANopen behavior has changed) + +Serial number +bit 0-31: Manufacturer specific + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + If value is zero, then SYNC message is transmitted with data length 0. + +If Value is from 2 to 240, then SYNC message has one data byte, which contains the counter. + +Other values are reserved. + + + + + + If error is detected and operating NMT state is NMT operational, this object defines behavior of the device. + +Value definition for all subindexes: + 0x00 - if operational, switch to NMT pre-operational + 0x01 - do nothing + 0x02 - switch to NMT stopped + +01 - Communication error - bus off or Heartbeat consumer error. +02 - Communication other error (critical errors - see 'Error status bits') except CAN bus passive but including bus off or Heartbeat consumer. +03 - Communication passive - any communication error including CAN bus passive. +04 - Generic error (critical errors - see 'Error status bits'). +05 - Device profile error - bit 5 in error register is set. +06 - Manufacturer specific error - bit 7 in error register is set. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0x1200 SDO server parameter +max sub-index + +COB-ID client to server (Receive SDO) +bit 0-31: 0x00000600 + Node ID + +COB-ID server to client (Transmit SDO) +bit 0-31: 0x00000580 + Node ID + + + +0x1201 - 0x127F SDO server parameter +max sub-index + +COB-ID client to server (Receive SDO) +bit 0-10: COB_ID +bit 11-30: Set to 0 +bit 31*: 0(1) - node uses (does NOT use) SDO + +COB-ID server to client (Transmit SDO) +bit 0-31: same as previous + +Node-ID of the SDO client +bit 0-7: Node ID (optional) + + + + + + + + + + + + + + + + + + + + 0x1280 - 0x12FF SDO client parameter +max sub-index + +COB-ID client to server (Transmit SDO) +bit 0-10: COB_ID +bit 11-30: Set to 0 +bit 31: 0(1) - node uses (does NOT use) SDO + +COB-ID server to client (Receive SDO) +bit 0-31: same as previous + +Node-ID of the SDO server +0-7: Node ID + + + + + + + + + + + + + + + + + + + + + + + + 0x1400 - 0x15FF RPDO communication parameter +max sub-index + +COB-ID +bit 0-10: COB-ID for PDO, to change it bit 31 must be set +bit 11-29: set to 0 for 11 bit COB-ID +bit 30: 0(1) - rtr are allowed (are NOT allowed) for PDO +bit 31: 0(1) - node uses (does NOT use) PDO + +Transmission type +value = 0-240: reciving is synchronous, process after next reception of SYNC object +value = 241-253: not used +value = 254: manufacturer specific +value = 255: asynchronous + + + + + + + + + + + + + + + + + + + + 0x1600 - 0x17FF RPDO mapping parameter (To change mapping, 'Number of mapped objects' must be set to 0) +Number of mapped objects + +mapped object (subindex 1...8) +bit 0-7: data length in bits +bit 8-15: subindex from OD +bit 16-31: index from OD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0x1800 - 0x19FF TPDO communication parameter +max sub-index + +COB-ID +bit 0-10: COB-ID for PDO, to change it bit 31 must be set +bit 11-29: set to 0 for 11 bit COB-ID +bit 30: 0(1) - rtr are allowed (are NOT allowed) for PDO +bit 31: 0(1) - node uses (does NOT use) PDO + +Transmission type +value = 0: transmiting is synchronous, specification in device profile +value = 1-240: transmiting is synchronous after every N-th SYNC object +value = 241-251: not used +value = 252-253: Transmited only on reception of Remote Transmission Request +value = 254: manufacturer specific +value = 255: asinchronous, specification in device profile + +inhibit time +bit 0-15: Minimum time between transmissions of the PDO in 100µs. Zero disables functionality. + +event timer +bit 0-15: Time between periodic transmissions of the PDO in ms. Zero disables functionality. + +SYNC start value +value = 0: Counter of the SYNC message shall not be processed. +value = 1-240: The SYNC message with the counter value equal to this value shall be regarded as the first received SYNC message. + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 0x1A00 - 0x1BFF TPDO mapping parameter. (To change mapping, 'Number of mapped objects' must be set to 0). +Number of mapped objects + +mapped object (subindex 1...8) +bit 0-7: data length in bits +bit 8-15: subindex from OD +bit 16-31: index from OD + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CANopen communication network profile + 1.1 + + + CommunicationNetwork + + 1 + 1 + CANopen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/EDSEditorGUI/Profiles/DSP302-NMTMaster.xml b/EDSEditorGUI/Profiles/DSP302-NMTMaster.xml deleted file mode 100644 index 8ac064d2..00000000 --- a/EDSEditorGUI/Profiles/DSP302-NMTMaster.xml +++ /dev/null @@ -1,295 +0,0 @@ - - - - - This object configures the start-up behavior of a device that is able to perform the NMT. The -value has the following interpretation: - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - New Product - - - - - - - - - - - - - \ No newline at end of file diff --git a/EDSEditorGUI/Profiles/DSP302-NMTMaster.xpd b/EDSEditorGUI/Profiles/DSP302-NMTMaster.xpd new file mode 100644 index 00000000..650eb1fb --- /dev/null +++ b/EDSEditorGUI/Profiles/DSP302-NMTMaster.xpd @@ -0,0 +1,1404 @@ + + + + + + + CANopen device profile + 1.1 + + + Device + + 1 + 1 + CANopen + + + + + + + New Product + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + This object configures the start-up behavior of a device that is able to perform the NMT. The +value has the following interpretation: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + CANopen communication network profile + 1.1 + + + CommunicationNetwork + + 1 + 1 + CANopen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 94182239d743124256f5092a4d204fe95cd1250c Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Tue, 23 Jul 2024 08:11:28 +0200 Subject: [PATCH 150/226] Replaced folderpath + filename with filepath in CanOpenNodeExporters (#125) * Replaced folderpath + filename with filepath in CanOpenNodeExporters * Remove odname parameter from canopennode exporters * Created basic tests for EDSSharp to make sure i did not mess up the directory or filenames --- EDSEditor.sln | 3 + EDSEditorGUI/Form1.cs | 3 +- EDSSharp/Program.cs | 5 +- Tests/CLITest.cs | 37 ++++ Tests/ExporterTestsV4.cs | 63 +++--- Tests/Tests.csproj | 11 + Tests/minimal_project.xdd | 297 ++++++++++++++++++++++++++ libEDSsharp/CanOpenNodeExporter.cs | 9 +- libEDSsharp/CanOpenNodeExporter_V4.cs | 10 +- libEDSsharp/IExporter.cs | 6 +- 10 files changed, 395 insertions(+), 49 deletions(-) create mode 100644 Tests/CLITest.cs create mode 100644 Tests/minimal_project.xdd diff --git a/EDSEditor.sln b/EDSEditor.sln index 3bc6d4f2..5b28768c 100644 --- a/EDSEditor.sln +++ b/EDSEditor.sln @@ -8,6 +8,9 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "libEDSsharp", "libEDSsharp\libEDSsharp.csproj", "{CC0FA4B1-2BFC-43B3-8C56-B428DF2D24E7}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Tests", "Tests\Tests.csproj", "{2A479BF3-7628-409B-8A29-9314C308445E}" + ProjectSection(ProjectDependencies) = postProject + {8B7A7545-6257-44BF-8868-F429E1B72C77} = {8B7A7545-6257-44BF-8868-F429E1B72C77} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "EDSSharp", "EDSSharp\EDSSharp.csproj", "{8B7A7545-6257-44BF-8868-F429E1B72C77}" EndProject diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index f94216a0..9c07d69c 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -226,7 +226,8 @@ private void exportCanOpenNode(DeviceView dv, string FileName, ExporterFactory.E { string savePath = Path.GetDirectoryName(FileName); string baseFileName = Path.GetFileNameWithoutExtension(FileName); - exporter.export(savePath, baseFileName, this.gitVersion, dv.eds, baseFileName); + var filepath = $"{savePath}/{baseFileName}"; + exporter.export(filepath, this.gitVersion, dv.eds); } catch (Exception ex) { diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index e149a96e..d1d96f79 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -92,8 +92,6 @@ private static void openEDSfile(string infile, string outfile, InfoSection.Filet private static void exportCOOD(string outpath,ExporterFactory.Exporter type) { - string odname = outpath; - outpath = Path.GetFullPath(outpath); string savePath = Path.GetDirectoryName(outpath); @@ -103,8 +101,9 @@ private static void exportCOOD(string outpath,ExporterFactory.Exporter type) Warnings.warning_list.Clear(); IExporter exporter = ExporterFactory.getExporter(type); + var filepath = Path.Combine(savePath, Path.GetFileNameWithoutExtension(outpath)); - exporter.export(savePath, Path.GetFileNameWithoutExtension(outpath), gitversion, eds, odname); + exporter.export(filepath, gitversion, eds); foreach(string warning in Warnings.warning_list) { diff --git a/Tests/CLITest.cs b/Tests/CLITest.cs new file mode 100644 index 00000000..8bbdbae8 --- /dev/null +++ b/Tests/CLITest.cs @@ -0,0 +1,37 @@ +using System.Diagnostics; +using System.IO; +using Xunit; + +namespace Tests +{ + public class CliTest : libEDSsharp.EDSsharp + { + string RunEDSSharp(string arguments) + { + Process p = new Process(); + p.StartInfo.UseShellExecute = false; + p.StartInfo.RedirectStandardOutput = true; + p.StartInfo.FileName = "EDSSharp.exe"; + p.StartInfo.Arguments = arguments; + p.Start(); + string output = p.StandardOutput.ReadToEnd(); + p.WaitForExit(); + return output; + } + + [Fact] + public void XddToCanOpenNodeLegacy() + { + RunEDSSharp("--type CanOpenNode --infile minimal_project.xdd --outfile Legacy"); + string[] files = Directory.GetFiles(".", "Legacy.*"); + Assert.Equal(2, files.Length); + } + [Fact] + public void XddToCanOpenNodeV4() + { + RunEDSSharp("--type CanOpenNodeV4 --infile minimal_project.xdd --outfile V4"); + string[] files = Directory.GetFiles(".", "V4.*"); + Assert.Equal(2, files.Length); + } + } +} diff --git a/Tests/ExporterTestsV4.cs b/Tests/ExporterTestsV4.cs index 1d040355..becda204 100644 --- a/Tests/ExporterTestsV4.cs +++ b/Tests/ExporterTestsV4.cs @@ -14,7 +14,7 @@ public ExporterTestsV4() _eds = new EDSsharp(); } - void GetExportResult(EDSsharp eds, out IEnumerable cfile, out IEnumerable hfile) + void GetExportResult(EDSsharp eds, out IEnumerable cfile, out IEnumerable hfile, out string odname) { var fullPath = Path.GetTempFileName(); var tempfile = Path.GetFileName(fullPath); @@ -22,9 +22,10 @@ void GetExportResult(EDSsharp eds, out IEnumerable cfile, out IEnumerabl var cfilePath = fullPath + ".c"; var hfilePath = fullPath + ".h"; - export(path, tempfile, ".", eds, "OD_Test"); + export(cfilePath, ".", eds); cfile = File.ReadLines(cfilePath); hfile = File.ReadLines(hfilePath); + odname = tempfile; } bool FindExpectedLines(IEnumerable lines, List expectedLines) @@ -85,12 +86,12 @@ public void TestVariableStringZeroData() _eds.ods.Add(0x2000, od); - GetExportResult(_eds, out var cfile, out var hfile); - Assert.True(FindExpectedLines(hfile, new List { "#define OD_Test_ENTRY_H2000 &OD_Test->list[0]" })); - Assert.True(FindExpectedLines(hfile, new List { "#define OD_Test_ENTRY_H2000_testString &OD_Test->list[0]" })); + GetExportResult(_eds, out var cfile, out var hfile, out var odname); + Assert.True(FindExpectedLines(hfile, new List { $"#define {odname}_ENTRY_H2000 &{odname}->list[0]" })); + Assert.True(FindExpectedLines(hfile, new List { $"#define {odname}_ENTRY_H2000_testString &{odname}->list[0]" })); Assert.True(FindExpectedLines(cfile, new List { - "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + $"static CO_PROGMEM {odname}Objs_t {odname}Objs = {{", " .o_2000_testString = {", " .dataOrig = NULL,", " .attribute = ODA_SDO_R | ODA_STR,", @@ -99,8 +100,8 @@ public void TestVariableStringZeroData() "};"})); Assert.True(FindExpectedLines(cfile, new List { - "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", - " {0x2000, 0x01, ODT_VAR, &OD_TestObjs.o_2000_testString, NULL},", + $"static {odname}_ATTR_OD OD_entry_t {odname}List[] = {{", + $" {{0x2000, 0x01, ODT_VAR, &{odname}Objs.o_2000_testString, NULL}},", " {0x0000, 0x00, 0, NULL, NULL}", "};"})); } @@ -123,25 +124,25 @@ public void TestVariableString(string defaultValue, uint stringLengthMin, int ex _eds.ods.Add(0x2000, od); - GetExportResult(_eds, out var cfile, out var _); + GetExportResult(_eds, out var cfile, out var _, out var odname); Assert.True(FindExpectedLines(cfile, new List { - "OD_Test_ATTR_RAM OD_Test_RAM_t OD_Test_RAM = {", + $"{odname}_ATTR_RAM {odname}_RAM_t {odname}_RAM = {{", $" .x2000_testString = {{{expectedInitialValues}}}", "};"})); Assert.True(FindExpectedLines(cfile, new List { - "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + $"static CO_PROGMEM {odname}Objs_t {odname}Objs = {{", " .o_2000_testString = {", - " .dataOrig = &OD_Test_RAM.x2000_testString[0],", + $" .dataOrig = &{odname}_RAM.x2000_testString[0],", " .attribute = ODA_SDO_R | ODA_STR,", $" .dataLength = {expectedLength}", " }", "};"})); Assert.True(FindExpectedLines(cfile, new List { - "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", - " {0x2000, 0x01, ODT_VAR, &OD_TestObjs.o_2000_testString, NULL},", + $"static {odname}_ATTR_OD OD_entry_t {odname}List[] = {{", + $" {{0x2000, 0x01, ODT_VAR, &{odname}Objs.o_2000_testString, NULL}},", " {0x0000, 0x00, 0, NULL, NULL}", "};"})); } @@ -165,18 +166,18 @@ public void TestRecordWithString(string defaultValue, uint stringLengthMin, int od.subobjects[1].prop.CO_stringLengthMin = stringLengthMin; _eds.ods.Add(0x2000, od); - GetExportResult(_eds, out var cfile, out var hfile); + GetExportResult(_eds, out var cfile, out var hfile, out var odname); Assert.True(FindExpectedLines(hfile, new List { "typedef struct {", " struct {", " uint8_t numElements;", $" char str[{expectedLength+1}];", " } x2000_testRec;", - "} OD_Test_RAM_t;"})); + $"}} {odname}_RAM_t;"})); Assert.True(FindExpectedLines(cfile, new List { - "OD_Test_ATTR_RAM OD_Test_RAM_t OD_Test_RAM = {", + $"{odname}_ATTR_RAM {odname}_RAM_t {odname}_RAM = {{", " .x2000_testRec = {", " .numElements = 0x00,", $" .str = {{{expectedInitialValues}}}", @@ -187,20 +188,20 @@ public void TestRecordWithString(string defaultValue, uint stringLengthMin, int { "typedef struct {", " OD_obj_record_t o_2000_testRec[2];", - "} OD_TestObjs_t;"})); + $"}} {odname}Objs_t;"})); Assert.True(FindExpectedLines(cfile, new List { - "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + $"static CO_PROGMEM {odname}Objs_t {odname}Objs = {{", " .o_2000_testRec = {", " {", - " .dataOrig = &OD_Test_RAM.x2000_testRec.numElements,", + $" .dataOrig = &{odname}_RAM.x2000_testRec.numElements,", " .subIndex = 0,", " .attribute = ODA_SDO_RW | ODA_TRPDO,", " .dataLength = 1", " },", " {", - " .dataOrig = &OD_Test_RAM.x2000_testRec.str[0],", + $" .dataOrig = &{odname}_RAM.x2000_testRec.str[0],", " .subIndex = 1,", " .attribute = ODA_SDO_RW | ODA_TRPDO | ODA_STR,", $" .dataLength = {expectedLength}", @@ -210,8 +211,8 @@ public void TestRecordWithString(string defaultValue, uint stringLengthMin, int Assert.True(FindExpectedLines(cfile, new List { - "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", - " {0x2000, 0x02, ODT_REC, &OD_TestObjs.o_2000_testRec, NULL},", + $"static {odname}_ATTR_OD OD_entry_t {odname}List[] = {{", + $" {{0x2000, 0x02, ODT_REC, &{odname}Objs.o_2000_testRec, NULL}},", " {0x0000, 0x00, 0, NULL, NULL}", "};"})); } @@ -231,17 +232,17 @@ public void TestRecordWithZeroLengthString() od.addsubobject(1, new ODentry("str", 0x2000, DataType.VISIBLE_STRING, "", EDSsharp.AccessType.rw, PDOMappingType.optional)); _eds.ods.Add(0x2000, od); - GetExportResult(_eds, out var cfile, out var hfile); + GetExportResult(_eds, out var cfile, out var hfile, out var odname); Assert.True(FindExpectedLines(hfile, new List { "typedef struct {", " struct {", " uint8_t numElements;", " } x2000_testRec;", - "} OD_Test_RAM_t;"})); + $"}} {odname}_RAM_t;"})); Assert.True(FindExpectedLines(cfile, new List { - "OD_Test_ATTR_RAM OD_Test_RAM_t OD_Test_RAM = {", + $"{odname}_ATTR_RAM {odname}_RAM_t {odname}_RAM = {{", " .x2000_testRec = {", " .numElements = 0x00", " }", @@ -251,14 +252,14 @@ public void TestRecordWithZeroLengthString() { "typedef struct {", " OD_obj_record_t o_2000_testRec[2];", - "} OD_TestObjs_t;"})); + $"}} {odname}Objs_t;"})); Assert.True(FindExpectedLines(cfile, new List { - "static CO_PROGMEM OD_TestObjs_t OD_TestObjs = {", + $"static CO_PROGMEM {odname}Objs_t {odname}Objs = {{", " .o_2000_testRec = {", " {", - " .dataOrig = &OD_Test_RAM.x2000_testRec.numElements,", + $" .dataOrig = &{odname}_RAM.x2000_testRec.numElements,", " .subIndex = 0,", " .attribute = ODA_SDO_RW | ODA_TRPDO,", " .dataLength = 1", @@ -274,8 +275,8 @@ public void TestRecordWithZeroLengthString() Assert.True(FindExpectedLines(cfile, new List { - "static OD_Test_ATTR_OD OD_entry_t OD_TestList[] = {", - " {0x2000, 0x02, ODT_REC, &OD_TestObjs.o_2000_testRec, NULL},", + $"static {odname}_ATTR_OD OD_entry_t {odname}List[] = {{", + $" {{0x2000, 0x02, ODT_REC, &{odname}Objs.o_2000_testRec, NULL}},", " {0x0000, 0x00, 0, NULL, NULL}", "};"})); } diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 5deedc04..02f77340 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -9,6 +9,17 @@ + + + + + + + + + Always + + diff --git a/Tests/minimal_project.xdd b/Tests/minimal_project.xdd new file mode 100644 index 00000000..2a043d8a --- /dev/null +++ b/Tests/minimal_project.xdd @@ -0,0 +1,297 @@ + + + + + + + CANopen device profile + 1.1 + + + Device + + 1 + 1 + CANopen + + + + + + + minimal_test + + 0 + 0 + 0 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * bit 7: manufacturer specific +* bit 6: Reserved (always 0) +* bit 5: device profile specific +* bit 4: communication error (overrun, error state) +* bit 3: temperature +* bit 2: voltage +* bit 1: current +* bit 0: generic error + + + + + + * Sub Index 0: Contains number of actual errors. 0 can be written to clear error history. +* sub-index 1 and above: + * bit 16-31: Manufacturer specific additional information + * bit 0-15: Error code as transmited in the Emergency object + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + * bit 31: set to 0 +* bit 30: If set, CANopen device generates SYNC object +* bit 11-29: set to 0 +* bit 0-10: 11-bit CAN-ID + + + + + + + Period of SYNC transmission in µs (0 = transmission disabled). + + + + + + + Synchronous window leghth in µs (0 = not used). All synchronous PDOs must be transmitted within this time window. + + + + + + * bit 31: If set, EMCY does NOT exist / is NOT valid +* bit 11-30: set to 0 +* bit 0-10: 11-bit CAN-ID + + + + + + + Inhibit time of emergency message in multiples of 100µs. The value 0 disables the inhibit time. + + + + + + Heartbeat producer time in ms (0 = disable transmission). + + + + + + + * Value 0: SYNC message is transmitted with data length 0. +* Value 1: reserved. +* Value 2-240: SYNC message has one data byte, which contains the counter. +* Value 241-255: reserved. + + + + + + Sub-indexes 1 and above: +* Value 0x00: on error change to NMT state Pre-operational (only if currently in NMT state Operational) +* Value 0x01: on error do nothing +* Value 0x02: on error change to NMT state Stopped + + + + + + + + + + + + + + + + + + + + + + + + + + CANopen communication network profile + 1.1 + + + CommunicationNetwork + + 1 + 1 + CANopen + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 92c8eedb..3e9f1b95 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -94,14 +94,13 @@ public void prepareCanOpenNames() /// /// Export eds into CanOpenNode v1-3 source files (.h and .c) /// - /// folder path to save the files into - /// base filename, .c and .h will be added to this + /// filepath, .c and .h will be added to this to make the mulitiple files /// git version of this software /// the eds data to be exported - /// object dictionary name - public void export(string folderpath, string filename, string gitVersion, EDSsharp eds,string odname) + public void export(string filepath, string gitVersion, EDSsharp eds) { - this.folderpath = folderpath; + this.folderpath = Path.GetDirectoryName(filepath); + string filename = Path.GetFileNameWithoutExtension(filepath); this.gitVersion = gitVersion; this.eds = eds; diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index c5e86043..05a66a43 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -49,14 +49,14 @@ public class CanOpenNodeExporter_V4 : IExporter /// /// export the current data set in the CanOpen Node format V4 /// - /// - /// + /// filepath, .c and .h will be added to this to make the mulitiple files /// /// - /// - public void export(string folderpath, string filename, string gitVersion, EDSsharp eds, string odname) + public void export(string filepath, string gitVersion, EDSsharp eds) { - this.odname = odname; + string filename = Path.GetFileNameWithoutExtension(filepath); + string folderpath = Path.GetDirectoryName(filepath); + this.odname = filename; Prepare(eds); diff --git a/libEDSsharp/IExporter.cs b/libEDSsharp/IExporter.cs index 53b94b10..683cfe32 100644 --- a/libEDSsharp/IExporter.cs +++ b/libEDSsharp/IExporter.cs @@ -14,11 +14,9 @@ public interface IExporter /// /// Export file(s) /// - /// Path to the folder that will contain the new files - /// base filename for the new files + /// filepath, .c and .h will be added to this to make the mulitiple files /// version that will be saved to the file /// The eds that will be exported - /// The object dictionary name - void export(string folderpath, string filename, string gitVersion, EDSsharp eds , string odname="OD"); + void export(string filepath, string gitVersion, EDSsharp eds); } } From 40c02b38c8f4320bd3da0fdf1959c4c7f4376ff5 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Tue, 23 Jul 2024 11:06:29 +0200 Subject: [PATCH 151/226] 126 move gitversion from gui to libeds (#127) * Moved assemby info from sourcefile to .csproj and included git info * Removed gitVersion parameter from exporters, fetch it from assembly info instead * Fetch all history for all tags as its now needed when building --- .github/workflows/dotnet.yml | 2 ++ .github/workflows/release.yml | 2 ++ EDSEditorGUI/Form1.cs | 12 ++++----- EDSSharp/Program.cs | 3 +-- Tests/ExporterTestsV4.cs | 2 +- libEDSsharp/CanOpenNodeExporter.cs | 11 +++++--- libEDSsharp/CanOpenNodeExporter_V4.cs | 10 +++++-- libEDSsharp/CanOpenXDD_1_1.cs | 10 +++++-- libEDSsharp/DocumentationGenMarkup.cs | 10 +++++-- libEDSsharp/IExporter.cs | 3 +-- libEDSsharp/Properties/AssemblyInfo.cs | 36 -------------------------- libEDSsharp/libEDSsharp.csproj | 25 ++++++++++++++++-- 12 files changed, 68 insertions(+), 58 deletions(-) delete mode 100644 libEDSsharp/Properties/AssemblyInfo.cs diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index b35e7f73..f491a634 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -18,6 +18,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup .NET uses: microsoft/setup-msbuild@v2 - name: C# problem matcher diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index c42bf3fa..98b3fae5 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -13,6 +13,8 @@ jobs: steps: - name: Checkout uses: actions/checkout@v4 + with: + fetch-depth: 0 - name: Setup .NET uses: microsoft/setup-msbuild@v2 - name: Add Packages diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 9c07d69c..9bdec100 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -227,7 +227,7 @@ private void exportCanOpenNode(DeviceView dv, string FileName, ExporterFactory.E string savePath = Path.GetDirectoryName(FileName); string baseFileName = Path.GetFileNameWithoutExtension(FileName); var filepath = $"{savePath}/{baseFileName}"; - exporter.export(filepath, this.gitVersion, dv.eds); + exporter.export(filepath, dv.eds); } catch (Exception ex) { @@ -622,7 +622,7 @@ void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripp case ".md": DocumentationGenMarkup docgen = new DocumentationGenMarkup(); - docgen.genmddoc(FileName, dv.eds, this.gitVersion); + docgen.genmddoc(FileName, dv.eds); dv.eds.mdfilename = FileName; break; @@ -873,12 +873,12 @@ private void saveNetworkXmlToolStripMenuItem_Click(object sender, EventArgs e) case 2: // .nxdc V1.1 with actual value, denotation and deviceCommissioning info CanOpenXDD_1_1 xdc_1_1 = new CanOpenXDD_1_1(); - xdc_1_1.WriteMultiXML(sfd.FileName, network, this.gitVersion, true); + xdc_1_1.WriteMultiXML(sfd.FileName, network, true); break; case 1: // .nxdd V1.1 CanOpenXDD_1_1 xdd_1_1 = new CanOpenXDD_1_1(); - xdd_1_1.WriteMultiXML(sfd.FileName, network, this.gitVersion, false); + xdd_1_1.WriteMultiXML(sfd.FileName, network, false); break; } } @@ -1031,7 +1031,7 @@ private void documentationToolStripMenuItem_Click(object sender, EventArgs e) DocumentationGenHtml docgenHtml = new DocumentationGenHtml(); docgenHtml.genhtmldoc(temp, dv.eds); DocumentationGenMarkup docgenMarkup = new DocumentationGenMarkup(); - docgenMarkup.genmddoc(temp2, dv.eds, this.gitVersion); + docgenMarkup.genmddoc(temp2, dv.eds); if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows)) { System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("cmd", $"/c start {temp2}")); @@ -1094,7 +1094,7 @@ private void saveExportAllToolStripMenuItem_Click(object sender, EventArgs e) if (dv.eds.mdfilename != null && dv.eds.mdfilename != "") { DocumentationGenMarkup docgen = new DocumentationGenMarkup(); - docgen.genmddoc(dv.eds.mdfilename, dv.eds, this.gitVersion); + docgen.genmddoc(dv.eds.mdfilename, dv.eds); cnt++; } diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index d1d96f79..674b5ab1 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -12,7 +12,6 @@ class Program { static libEDSsharp.EDSsharp eds = new EDSsharp(); - static string gitversion = ""; static void Main(string[] args) { @@ -103,7 +102,7 @@ private static void exportCOOD(string outpath,ExporterFactory.Exporter type) IExporter exporter = ExporterFactory.getExporter(type); var filepath = Path.Combine(savePath, Path.GetFileNameWithoutExtension(outpath)); - exporter.export(filepath, gitversion, eds); + exporter.export(filepath, eds); foreach(string warning in Warnings.warning_list) { diff --git a/Tests/ExporterTestsV4.cs b/Tests/ExporterTestsV4.cs index becda204..a1a45a7c 100644 --- a/Tests/ExporterTestsV4.cs +++ b/Tests/ExporterTestsV4.cs @@ -22,7 +22,7 @@ void GetExportResult(EDSsharp eds, out IEnumerable cfile, out IEnumerabl var cfilePath = fullPath + ".c"; var hfilePath = fullPath + ".h"; - export(cfilePath, ".", eds); + export(cfilePath, eds); cfile = File.ReadLines(cfilePath); hfile = File.ReadLines(hfilePath); odname = tempfile; diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 3e9f1b95..5068277b 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -26,6 +26,7 @@ based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are using System.Text.RegularExpressions; using System.Threading.Tasks; using System.IO; +using System.Reflection; @@ -95,13 +96,17 @@ public void prepareCanOpenNames() /// Export eds into CanOpenNode v1-3 source files (.h and .c) ///
/// filepath, .c and .h will be added to this to make the mulitiple files - /// git version of this software /// the eds data to be exported - public void export(string filepath, string gitVersion, EDSsharp eds) + public void export(string filepath, EDSsharp eds) { this.folderpath = Path.GetDirectoryName(filepath); string filename = Path.GetFileNameWithoutExtension(filepath); - this.gitVersion = gitVersion; + var versionAttributes = Assembly + .GetExecutingAssembly() + .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) + as AssemblyInformationalVersionAttribute[]; + + this.gitVersion = versionAttributes[0].InformationalVersion; this.eds = eds; diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 05a66a43..93c0e225 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -24,6 +24,7 @@ You should have received a copy of the GNU General Public License using System.Text.RegularExpressions; using System.IO; using System.Linq; +using System.Reflection; namespace libEDSsharp { @@ -50,9 +51,8 @@ public class CanOpenNodeExporter_V4 : IExporter /// export the current data set in the CanOpen Node format V4 ///
/// filepath, .c and .h will be added to this to make the mulitiple files - /// /// - public void export(string filepath, string gitVersion, EDSsharp eds) + public void export(string filepath, EDSsharp eds) { string filename = Path.GetFileNameWithoutExtension(filepath); string folderpath = Path.GetDirectoryName(filepath); @@ -60,6 +60,12 @@ public void export(string filepath, string gitVersion, EDSsharp eds) Prepare(eds); + var versionAttributes = Assembly + .GetExecutingAssembly() + .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) + as AssemblyInformationalVersionAttribute[]; + + string gitVersion = versionAttributes[0].InformationalVersion; Export_h(folderpath, filename, gitVersion, eds); Export_c(folderpath, filename, gitVersion, eds); } diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 1e83122e..29af2a6a 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -30,6 +30,7 @@ You should have received a copy of the GNU General Public License using Google.Protobuf; using Google.Protobuf.WellKnownTypes; using System.Linq; +using System.Reflection; namespace libEDSsharp { @@ -98,10 +99,15 @@ public List ReadMultiXML(string file ) ///
/// Name of the multi xdd file /// List of EDSsharp objects - /// Git version string for documentation field /// If true, device commisioning, denotations and actual values will be included - public void WriteMultiXML(string file, List edss, string gitVersion, bool deviceCommissioning) + public void WriteMultiXML(string file, List edss, bool deviceCommissioning) { + var versionAttributes = Assembly + .GetExecutingAssembly() + .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) + as AssemblyInformationalVersionAttribute[]; + + string gitVersion = versionAttributes[0].InformationalVersion; List devs = new List(); foreach (EDSsharp eds in edss) diff --git a/libEDSsharp/DocumentationGenMarkup.cs b/libEDSsharp/DocumentationGenMarkup.cs index 798dbf39..1ef6084f 100644 --- a/libEDSsharp/DocumentationGenMarkup.cs +++ b/libEDSsharp/DocumentationGenMarkup.cs @@ -21,6 +21,7 @@ You should have received a copy of the GNU General Public License using System; using System.Collections.Generic; using System.IO; +using System.Reflection; namespace libEDSsharp { @@ -36,9 +37,14 @@ public class DocumentationGenMarkup /// /// where the documentation should be created /// data to generate the documentation from - /// git version of this software - public void genmddoc(string filepath, EDSsharp eds, string gitVersion) + public void genmddoc(string filepath, EDSsharp eds) { + var versionAttributes = Assembly + .GetExecutingAssembly() + .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) + as AssemblyInformationalVersionAttribute[]; + + string gitVersion = versionAttributes[0].InformationalVersion; file = new StreamWriter(filepath, false); file.NewLine = "\n"; diff --git a/libEDSsharp/IExporter.cs b/libEDSsharp/IExporter.cs index 683cfe32..f67c585a 100644 --- a/libEDSsharp/IExporter.cs +++ b/libEDSsharp/IExporter.cs @@ -15,8 +15,7 @@ public interface IExporter /// Export file(s) /// /// filepath, .c and .h will be added to this to make the mulitiple files - /// version that will be saved to the file /// The eds that will be exported - void export(string filepath, string gitVersion, EDSsharp eds); + void export(string filepath, EDSsharp eds); } } diff --git a/libEDSsharp/Properties/AssemblyInfo.cs b/libEDSsharp/Properties/AssemblyInfo.cs deleted file mode 100644 index 05056129..00000000 --- a/libEDSsharp/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("libEDSsharp")] -[assembly: AssemblyDescription("")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("")] -[assembly: AssemblyProduct("libEDSsharp")] -[assembly: AssemblyCopyright("Copyright © 2016")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("01bcd5d8-58a1-419d-8fd4-5f0bfbac9105")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.0.0")] -[assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index a5c42523..767f8e79 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -1,11 +1,32 @@ - + net481 net6.0 net481;net6.0 Library - false + true + + + + + + libEDSsharp + Copyright © 2016 + libEDSsharp + 1.0.0.0 + 1.0.0.0 + + + + + + + + $(gitInfo) + + + docs\libEDSsharp.xml From 18610b31a2f6eb6b7d403cb41099aabf6b151e77 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 3 Aug 2024 14:17:50 +0200 Subject: [PATCH 152/226] added module tab back to deviceview (#123) --- EDSEditorGUI/DeviceView.Designer.cs | 27 +++++++++++++++++++++++++++ EDSEditorGUI/DeviceView.cs | 4 ++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/EDSEditorGUI/DeviceView.Designer.cs b/EDSEditorGUI/DeviceView.Designer.cs index 80cde950..5f3f3fe8 100644 --- a/EDSEditorGUI/DeviceView.Designer.cs +++ b/EDSEditorGUI/DeviceView.Designer.cs @@ -40,11 +40,14 @@ private void InitializeComponent() this.tabPage1 = new System.Windows.Forms.TabPage(); this.deviceInfoView = new ODEditor.DeviceInfoView(); this.tabControl1 = new System.Windows.Forms.TabControl(); + this.tabPage5 = new System.Windows.Forms.TabPage(); + this.moduleInfo1 = new ODEditor.ModuleInfo(); this.tabPage4.SuspendLayout(); this.tabPage3.SuspendLayout(); this.tabPage2.SuspendLayout(); this.tabPage1.SuspendLayout(); this.tabControl1.SuspendLayout(); + this.tabPage5.SuspendLayout(); this.SuspendLayout(); // // imageList1 @@ -152,6 +155,7 @@ private void InitializeComponent() this.tabControl1.Controls.Add(this.tabPage2); this.tabControl1.Controls.Add(this.tabPage3); this.tabControl1.Controls.Add(this.tabPage4); + this.tabControl1.Controls.Add(this.tabPage5); this.tabControl1.Dock = System.Windows.Forms.DockStyle.Fill; this.tabControl1.ImageList = this.imageList1; this.tabControl1.Location = new System.Drawing.Point(0, 0); @@ -161,6 +165,26 @@ private void InitializeComponent() this.tabControl1.Size = new System.Drawing.Size(1038, 773); this.tabControl1.TabIndex = 1; // + // tabPage5 + // + this.tabPage5.Controls.Add(this.moduleInfo1); + this.tabPage5.Location = new System.Drawing.Point(4, 23); + this.tabPage5.Name = "tabPage5"; + this.tabPage5.Padding = new System.Windows.Forms.Padding(3); + this.tabPage5.Size = new System.Drawing.Size(1030, 746); + this.tabPage5.TabIndex = 4; + this.tabPage5.Text = "Modules"; + this.tabPage5.UseVisualStyleBackColor = true; + // + // moduleInfo1 + // + this.moduleInfo1.Dock = System.Windows.Forms.DockStyle.Fill; + this.moduleInfo1.Location = new System.Drawing.Point(3, 3); + this.moduleInfo1.Margin = new System.Windows.Forms.Padding(4); + this.moduleInfo1.Name = "moduleInfo1"; + this.moduleInfo1.Size = new System.Drawing.Size(1024, 740); + this.moduleInfo1.TabIndex = 0; + // // DeviceView // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); @@ -176,6 +200,7 @@ private void InitializeComponent() this.tabPage2.ResumeLayout(false); this.tabPage1.ResumeLayout(false); this.tabControl1.ResumeLayout(false); + this.tabPage5.ResumeLayout(false); this.ResumeLayout(false); } @@ -191,5 +216,7 @@ private void InitializeComponent() private System.Windows.Forms.TabPage tabPage1; private DeviceInfoView deviceInfoView; private System.Windows.Forms.TabControl tabControl1; + private System.Windows.Forms.TabPage tabPage5; + private ModuleInfo moduleInfo1; } } diff --git a/EDSEditorGUI/DeviceView.cs b/EDSEditorGUI/DeviceView.cs index 536af994..8b49c28d 100644 --- a/EDSEditorGUI/DeviceView.cs +++ b/EDSEditorGUI/DeviceView.cs @@ -84,8 +84,8 @@ public void dispatch_updatedevice() deviceInfoView.populatedeviceinfo(); - //moduleInfo.eds = eds; - //moduleInfo.populatemoduleinfo(); + moduleInfo1.eds = eds; + moduleInfo1.populatemoduleinfo(); } public void dispatch_updatePDOinfo() From 86294fb003700e842bb72ecd678ee246d315baa3 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Wed, 25 Sep 2024 18:38:52 +0200 Subject: [PATCH 153/226] Unified file exporter interface for cli (#131) * unified exporter & cli changes --- EDSEditorGUI/Form1.cs | 2 +- EDSSharp/Program.cs | 119 ++++++++++++++++++++------ Tests/CLITest.cs | 32 ++++++- libEDSsharp/CanOpenNodeExporter.cs | 18 +++- libEDSsharp/CanOpenNodeExporter_V4.cs | 18 +++- libEDSsharp/CanOpenXDD.cs | 23 ++++- libEDSsharp/CanOpenXDD_1_1.cs | 57 +++++++++++- libEDSsharp/DocumentationGenHtml.cs | 17 +++- libEDSsharp/DocumentationGenMarkup.cs | 17 +++- libEDSsharp/Filetypes.cs | 38 ++++++++ libEDSsharp/IFileExporter.cs | 75 ++++++++++++++++ libEDSsharp/NetworkPDOreport.cs | 13 ++- libEDSsharp/eds.cs | 20 ++++- 13 files changed, 413 insertions(+), 36 deletions(-) create mode 100644 libEDSsharp/Filetypes.cs create mode 100644 libEDSsharp/IFileExporter.cs diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 9bdec100..201d9145 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -643,7 +643,7 @@ void dosave(DeviceView dv, string FileName, bool xddfileVersion_1_1, bool stripp Warnings.warning_list.Clear(); CanOpenXDD_1_1 coxdd = new CanOpenXDD_1_1(); - coxdd.WriteXML(FileName, dv.eds, this.gitVersion, Path.GetExtension(FileName) == ".xdc", stripped); + coxdd.WriteXML(FileName, dv.eds, Path.GetExtension(FileName) == ".xdc", stripped); dv.eds.Dirty = false; if (Warnings.warning_list.Count != 0) diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index 674b5ab1..c1686d42 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -43,24 +43,25 @@ static void Main(string[] args) } - if (argskvp.ContainsKey("--type") && argskvp.ContainsKey("--infile") && argskvp.ContainsKey("--outfile")) + if (argskvp.ContainsKey("--infile") && argskvp.ContainsKey("--outfile")) { string infile = argskvp["--infile"]; string outfile = argskvp["--outfile"]; + string outtype = ""; + if (argskvp.ContainsKey("--type")) + { + outtype = argskvp["--type"]; + } - ExporterFactory.Exporter type = ExporterFactory.Exporter.CANOPENNODE_LEGACY; //sensible default - - if (argskvp["--type"].IndexOf("4") > 0) - type = ExporterFactory.Exporter.CANOPENNODE_V4; switch (Path.GetExtension(infile).ToLower()) { case ".xdd": - openXDDfile(infile, outfile,type); + openXDDfile(infile); break; case ".eds": - openEDSfile(infile, outfile,InfoSection.Filetype.File_EDS,type); + openEDSfile(infile); break; @@ -68,28 +69,47 @@ static void Main(string[] args) return; } + if(eds != null) + { + Export(outfile, outtype); + } } else { - Console.WriteLine("Usage EDSEditor --type [CanOpenNode|CanOpenNodeV4] --infile file.[xdd|eds] --outfile [CO_OD.c|OD]"); + PrintHelpText(); } } catch(Exception e) { Console.WriteLine(e.ToString()); + PrintHelpText(); } } - private static void openEDSfile(string infile, string outfile, InfoSection.Filetype ft, ExporterFactory.Exporter exporttype) + private static void openEDSfile(string infile) { eds.Loadfile(infile); + } - exportCOOD(outfile,exporttype); + private static void openXDDfile(string path) + { + CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); + eds = coxml_1_1.ReadXML(path); + if (eds == null) + { + CanOpenXDD coxml = new CanOpenXDD(); + eds = coxml.readXML(path); + + if (eds == null) + return; + } + + eds.projectFilename = path; } - private static void exportCOOD(string outpath,ExporterFactory.Exporter type) + private static void Export(string outpath, string outType) { outpath = Path.GetFullPath(outpath); @@ -99,10 +119,15 @@ private static void exportCOOD(string outpath,ExporterFactory.Exporter type) Warnings.warning_list.Clear(); - IExporter exporter = ExporterFactory.getExporter(type); - var filepath = Path.Combine(savePath, Path.GetFileNameWithoutExtension(outpath)); + var exporterDef = FindMatchingExporter(outpath, outType); - exporter.export(filepath, eds); + if(exporterDef == null) + { + throw new Exception("Unable to find matching exporter)"); + } + + var edss = new List { eds }; + exporterDef.Func(outpath, edss); foreach(string warning in Warnings.warning_list) { @@ -111,22 +136,68 @@ private static void exportCOOD(string outpath,ExporterFactory.Exporter type) } - private static void openXDDfile(string path, string outpath,ExporterFactory.Exporter exportertype) + static ExporterDescriptor FindMatchingExporter(string outpath, string outType) { - CanOpenXDD_1_1 coxml_1_1 = new CanOpenXDD_1_1(); - eds = coxml_1_1.ReadXML(path); + //Find exporter(s) matching the file extension + var exporters = Filetypes.GetExporters(); - if (eds == null) + var outFiletype = Path.GetExtension(outpath); + var exporterMatchingFiletype = new List(); + foreach (var exporter in exporters) { - CanOpenXDD coxml = new CanOpenXDD(); - eds = coxml.readXML(path); + foreach (var type in exporter.Filetypes) + { + if (type == outFiletype) + { + exporterMatchingFiletype.Add(exporter); + break; + } + } + } - if (eds == null) - return; + if (exporterMatchingFiletype.Count == 1) + { + //If only one match we use that one. + return exporterMatchingFiletype[0]; } - eds.projectFilename = path; - exportCOOD(outpath,exportertype); + //If multiple or zero matches use type + foreach (var exporter in exporters) + { + if (exporter.Description.Replace(" ", null) == outType) + { + return exporter; + } + } + return null; + } + + static void PrintHelpText() + { + Console.WriteLine("Usage: EDSEditor --infile file.[xdd|eds] --outfile [valid output file] [OPTIONAL] --type [exporter type]"); + Console.WriteLine("The output file format depends on --outfile extension and --type"); + Console.WriteLine("If --outfile extension matcher one exporter then --type IS NOT needed"); + Console.WriteLine("If --outfile extension matcher multiple exporter then --type IS needed"); + Console.WriteLine("If --outfile has no extension --type IS needed"); + Console.WriteLine("Exporter types:"); + + var exporters = Filetypes.GetExporters(); + foreach (var exporter in exporters) + { + string filetypes = ""; + for (int i = 0; i < exporter.Filetypes.Length; i++) + { + filetypes += exporter.Filetypes[i]; + //add seperator char if multiple filetypes + if(i +1 != exporter.Filetypes.Length) + { + filetypes += ','; + } + } + + string description = $" {exporter.Description.Replace(" ",null)} [{filetypes}]"; + Console.WriteLine(description); + } } } } diff --git a/Tests/CLITest.cs b/Tests/CLITest.cs index 8bbdbae8..92b7c110 100644 --- a/Tests/CLITest.cs +++ b/Tests/CLITest.cs @@ -1,4 +1,5 @@ -using System.Diagnostics; +using System.Collections.Generic; +using System.Diagnostics; using System.IO; using Xunit; @@ -8,6 +9,13 @@ public class CliTest : libEDSsharp.EDSsharp { string RunEDSSharp(string arguments) { + File.Delete("Legacy.c"); + File.Delete("Legacy.h"); + File.Delete("V4.c"); + File.Delete("V4.h"); + File.Delete("file.eds"); + File.Delete("file.xpd"); + Process p = new Process(); p.StartInfo.UseShellExecute = false; p.StartInfo.RedirectStandardOutput = true; @@ -33,5 +41,27 @@ public void XddToCanOpenNodeV4() string[] files = Directory.GetFiles(".", "V4.*"); Assert.Equal(2, files.Length); } + [Fact] + public void OnlySingleExporterByExtensionPossible() + { + RunEDSSharp("--infile minimal_project.xdd --outfile file.eds"); + string[] files = Directory.GetFiles(".", "file.eds"); + Assert.Single(files); + } + [Fact] + public void MultipleExporterByExtensionPossibleWithoutType() + { + //this should fail + RunEDSSharp("--infile minimal_project.xdd --outfile file.xdd"); + string[] files = Directory.GetFiles(".", "file.xdd"); + Assert.Empty(files); + } + [Fact] + public void MultipleExporterByExtensionPossibleWithType() + { + RunEDSSharp("--type CanOpenXDDv1.1 --infile minimal_project.xdd --outfile file.nxdd"); + string[] files = Directory.GetFiles(".", "file.nxdd"); + Assert.Single(files); + } } } diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 5068277b..df728b8d 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -35,7 +35,7 @@ namespace libEDSsharp /// /// Export .c and .h files for CanOpenNode v1-3 /// - public class CanOpenNodeExporter : IExporter + public class CanOpenNodeExporter : IExporter, IFileExporter { private string folderpath; @@ -59,6 +59,22 @@ public class CanOpenNodeExporter : IExporter ODentry maxRXmappingsOD=null; ODentry maxTXmappingsOD=null; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] + { + new ExporterDescriptor("CanOpenNode", new string[] { ".h", ".c" }, ExporterDescriptor.ExporterFlags.CanOpenNode, delegate (string filepath, List edss) + { + var e = new CanOpenNodeExporter(); + e.export(filepath, edss[0]); + }) + }; + } + /// /// Register names of index and subindex that need to have standard names to be able to work with CanOpenNode /// diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 93c0e225..786bb9c1 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -31,7 +31,7 @@ namespace libEDSsharp /// /// Exporter for CanOpenNode_V4 /// - public class CanOpenNodeExporter_V4 : IExporter + public class CanOpenNodeExporter_V4 : IExporter, IFileExporter { private string odname; @@ -47,6 +47,22 @@ public class CanOpenNodeExporter_V4 : IExporter private Dictionary ODCnt; private Dictionary ODArrSize; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] + { + new ExporterDescriptor("CanOpenNodeV4", new string[] { ".h", ".c" }, ExporterDescriptor.ExporterFlags.CanOpenNode, delegate (string filepath, List edss) + { + var e = new CanOpenNodeExporter_V4(); + e.export(filepath, edss[0]); + }) + }; + } + /// /// export the current data set in the CanOpen Node format V4 /// diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 9dde28e2..acd57b11 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -29,9 +29,30 @@ based heavily on the files CO_OD.h and CO_OD.c from CANopenNode which are namespace libEDSsharp { - public class CanOpenXDD + public class CanOpenXDD : IFileExporter { public ISO15745ProfileContainer dev; + + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] { + new ExporterDescriptor("CanOpen XDD v1.0", new string[] { ".xdd" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD(); + e.writeXML(filepath,edss[0]); + }), + new ExporterDescriptor("CanOpen Network v1.0", new string[] { ".nxdd" }, ExporterDescriptor.ExporterFlags.MultipleNodeSupport, delegate (string filepath, List edss) + { + var e = new CanOpenXDD(); + e.writeMultiXML(filepath,edss); + }) + }; + } + public EDSsharp readXML(string file) { diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 29af2a6a..d05840b2 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -38,8 +38,52 @@ namespace libEDSsharp /// Convert to/from EDSsharp and CanOpenXDD v1.1, it uses the generated source file CanOpenXSD_1_1 /// /// - public class CanOpenXDD_1_1 + public class CanOpenXDD_1_1 : IFileExporter { + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] { + new ExporterDescriptor("CanOpen XDD v1.1", new string[] { ".xdd" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteXML(filepath,edss[0],false,false); + }), + new ExporterDescriptor("CanOpen XDD v1.1 stripped", new string[] { ".xdd" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteXML(filepath,edss[0],false,true); + }), + new ExporterDescriptor("CanOpen XDC v1.1", new string[] { ".xdc" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteXML(filepath,edss[0],true,true); + }), + new ExporterDescriptor("CanOpen Network XDD v1.1", new string[] { ".nxdd" }, ExporterDescriptor.ExporterFlags.MultipleNodeSupport, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteMultiXML(filepath,edss,false); + }), + new ExporterDescriptor("CanOpen Network XDC v1.1", new string[] { ".nxdc" }, ExporterDescriptor.ExporterFlags.MultipleNodeSupport, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteMultiXML(filepath,edss,true); + }), + new ExporterDescriptor("CanOpenNode Protobuf (json)", new string[] { ".json" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteProtobuf(filepath,edss[0],true); + }), + new ExporterDescriptor("CanOpenNode Protobuf (binary)", new string[] { ".binpb" }, 0, delegate (string filepath, List edss) + { + var e = new CanOpenXDD_1_1(); + e.WriteProtobuf(filepath,edss[0],false); + }) + }; + } /// /// Read XDD file into EDSsharp object /// @@ -142,10 +186,9 @@ public void WriteMultiXML(string file, List edss, bool deviceCommissio /// /// Name of the xdd file /// EDSsharp object - /// Git version string for documentation field /// If true, device commisioning, denotations and actual values will be included /// If true, then all CANopenNode specific parameters and all disabled objects will be stripped - public void WriteXML(string file, EDSsharp eds, string gitVersion, bool deviceCommissioning, bool stripped) + public void WriteXML(string file, EDSsharp eds, bool deviceCommissioning, bool stripped) { ISO15745ProfileContainer dev = Convert(eds, Path.GetFileName(file), deviceCommissioning, stripped); XmlSerializer serializer = new XmlSerializer(typeof(ISO15745ProfileContainer)); @@ -154,6 +197,14 @@ public void WriteXML(string file, EDSsharp eds, string gitVersion, bool deviceCo stream.NewLine = "\n"; XmlWriter writer = XmlWriter.Create(stream, new XmlWriterSettings { Indent = true, NewLineChars = "\n" }); writer.WriteStartDocument(); + + var versionAttributes = Assembly + .GetExecutingAssembly() + .GetCustomAttributes(typeof(AssemblyInformationalVersionAttribute), false) + as AssemblyInformationalVersionAttribute[]; + + string gitVersion = versionAttributes[0].InformationalVersion; + writer.WriteComment(string.Format("File is generated by CANopenEditor {0}, URL: https://github.com/CANopenNode/CANopenEditor", gitVersion)); if (!stripped) writer.WriteComment("File includes additional custom properties for CANopenNode, CANopen protocol stack, URL: https://github.com/CANopenNode/CANopenNode"); diff --git a/libEDSsharp/DocumentationGenHtml.cs b/libEDSsharp/DocumentationGenHtml.cs index a2717025..49656243 100644 --- a/libEDSsharp/DocumentationGenHtml.cs +++ b/libEDSsharp/DocumentationGenHtml.cs @@ -27,10 +27,25 @@ namespace libEDSsharp /// /// Documentation generator /// - public class DocumentationGenHtml + public class DocumentationGenHtml : IFileExporter { StreamWriter file = null; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] + { + new ExporterDescriptor("Documentation HTML", new string[] { ".html" }, ExporterDescriptor.ExporterFlags.Documentation, delegate (string filepath, List edss) + { + var e = new DocumentationGenMarkup(); + e.genmddoc(filepath, edss[0]); + }) + }; + } /// /// Generate html documentation /// diff --git a/libEDSsharp/DocumentationGenMarkup.cs b/libEDSsharp/DocumentationGenMarkup.cs index 1ef6084f..2e035178 100644 --- a/libEDSsharp/DocumentationGenMarkup.cs +++ b/libEDSsharp/DocumentationGenMarkup.cs @@ -28,10 +28,25 @@ namespace libEDSsharp /// /// Documentation generator /// - public class DocumentationGenMarkup + public class DocumentationGenMarkup : IFileExporter { StreamWriter file = null; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] + { + new ExporterDescriptor("Documentation Markup", new string[] { ".md" }, ExporterDescriptor.ExporterFlags.Documentation, delegate (string filepath, List edss) + { + var e = new DocumentationGenMarkup(); + e.genmddoc(filepath, edss[0]); + }) + }; + } /// /// Generate markup documentation /// diff --git a/libEDSsharp/Filetypes.cs b/libEDSsharp/Filetypes.cs new file mode 100644 index 00000000..64581a78 --- /dev/null +++ b/libEDSsharp/Filetypes.cs @@ -0,0 +1,38 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using static libEDSsharp.ExporterDescriptor; + +namespace libEDSsharp +{ + /// + /// Unified interface to all filetypes supported by the library + /// + public class Filetypes + { + /// + /// Returns description of all the different filetypes that can be exported to + /// + /// optional filter to filter out different types of exporters + /// list of file exporter that matches the filter + public static ExporterDescriptor[] GetExporters(ExporterFlags flags = 0) + { + var exporters = new List(); + foreach (Type mytype in System.Reflection.Assembly.GetExecutingAssembly().GetTypes() + .Where(mytype => mytype.GetInterfaces().Contains(typeof(IFileExporter)))) + { + var exporterClass = (IFileExporter)Activator.CreateInstance(mytype); + var classExporters = exporterClass.GetExporters(); + foreach (var exporter in classExporters) + { + if (((exporter.Flags & flags) > 0) || flags == 0) + { + exporters.Add(exporter); + } + + } + } + return exporters.ToArray(); + } + } +} diff --git a/libEDSsharp/IFileExporter.cs b/libEDSsharp/IFileExporter.cs new file mode 100644 index 00000000..eaf6ac7c --- /dev/null +++ b/libEDSsharp/IFileExporter.cs @@ -0,0 +1,75 @@ +using System; +using System.Collections.Generic; + +namespace libEDSsharp +{ + /// + /// Includes all info about a exporter that is needed to show user and call it + /// + public class ExporterDescriptor + { + /// + /// Export eds(s) to file(s) + /// + /// path path that should indicate where and what name the outputed file(s) should have + /// list of eds(s) not all support multiple edss, in that case use the first + public delegate void ExportFunc(string filepath, List edss); + [Flags] + public enum ExporterFlags + { + /// + /// True if exporter will expect multiple edss + /// + MultipleNodeSupport = 1, + /// + /// Documentation related + /// + Documentation = 2, + /// + /// CanOpenNode related + /// + CanOpenNode = 3, + } + /// + /// short human readable description + /// + public string Description { get; } + /// + /// What file extension the exported file(s) will have + /// + public string[] Filetypes { get; } + /// + /// Used to indicated different types of exporters + /// + public ExporterFlags Flags { get; } + /// + /// The function that is exporting to file + /// + public ExportFunc Func { get; } + /// + /// constructor that sets all the values + /// + /// short human readable description + /// What file extension the exported file(s) will have + /// Used to indicated different types of exporters + /// The function that is exporting to file + public ExporterDescriptor(string description, string[] filetypes, ExporterFlags flags, ExportFunc func) + { + Description = description; + Filetypes = filetypes; + Flags = flags; + Func = func; + } + } + /// + /// Interface for exporters + /// + public interface IFileExporter + { + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + ExporterDescriptor[] GetExporters(); + } +} diff --git a/libEDSsharp/NetworkPDOreport.cs b/libEDSsharp/NetworkPDOreport.cs index a7318011..d6108347 100644 --- a/libEDSsharp/NetworkPDOreport.cs +++ b/libEDSsharp/NetworkPDOreport.cs @@ -26,9 +26,20 @@ namespace libEDSsharp /// /// Generate a PDO network report /// - public class NetworkPDOreport + public class NetworkPDOreport : IFileExporter { + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] + { + new ExporterDescriptor("Network PDO Report", new string[] { ".md" }, ExporterDescriptor.ExporterFlags.Documentation | ExporterDescriptor.ExporterFlags.MultipleNodeSupport, delegate (string filepath, List edss) + { + var e = new NetworkPDOreport(); + e.gennetpdodoc(filepath, edss); + }) + }; + } StreamWriter file = null; /// /// Generate a PDO network report diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 5df21990..e12fa21b 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1666,7 +1666,7 @@ public Module(UInt16 moduleindex) } - public partial class EDSsharp + public partial class EDSsharp : IFileExporter { public enum AccessType @@ -1758,6 +1758,24 @@ public bool Dirty public delegate void DataDirty(bool dirty, EDSsharp sender); public event DataDirty OnDataDirty; + /// + /// Fetches all the different fileexporter types the class supports + /// + /// List of the different exporters the class supports + public ExporterDescriptor[] GetExporters() + { + return new ExporterDescriptor[] { + new ExporterDescriptor("Electronic Data Sheet", new string[] { ".eds" }, 0, delegate (string filepath, List eds) + { + eds[0].Savefile(filepath, InfoSection.Filetype.File_EDS); + }), + new ExporterDescriptor("Device Configuration File", new string[] { ".dcf" }, 0, delegate (string filepath, List eds) + { + eds[0].Savefile(filepath, InfoSection.Filetype.File_DCF); + }) + }; + } + public EDSsharp() { From 6d02e11a8966a75dc2322e95a64d164ed6c2cf41 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sun, 6 Oct 2024 20:36:50 +0200 Subject: [PATCH 154/226] Warning fixes (#121) * disabled CA1416 as it should only run on windows * Fixed buildDate cannot be null warning * Fixed WFAC010 warning about the HighDPImode in manifest --- EDSEditorGUI/EDSEditorGUI.csproj | 4 ++++ EDSEditorGUI/app.manifest | 12 ------------ libEDSsharp/CanOpenXDD.cs | 2 +- 3 files changed, 5 insertions(+), 13 deletions(-) diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index aa39e082..603a3e01 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -25,6 +25,7 @@ true true true + SystemAware Index_8287_16x.ico @@ -32,6 +33,9 @@ app.manifest + + $(NoWarn);CA1416 + False diff --git a/EDSEditorGUI/app.manifest b/EDSEditorGUI/app.manifest index 3c672767..f317ad56 100644 --- a/EDSEditorGUI/app.manifest +++ b/EDSEditorGUI/app.manifest @@ -45,18 +45,6 @@ - - - - - true - - - - + + + + + + + + + + + + \ No newline at end of file diff --git a/EDSEditorGUI2/App.axaml.cs b/EDSEditorGUI2/App.axaml.cs new file mode 100644 index 00000000..07140117 --- /dev/null +++ b/EDSEditorGUI2/App.axaml.cs @@ -0,0 +1,32 @@ +using Avalonia; +using Avalonia.Controls.ApplicationLifetimes; +using Avalonia.Data.Core.Plugins; +using Avalonia.Markup.Xaml; +using EDSEditorGUI2.ViewModels; +using EDSEditorGUI2.Views; + +namespace EDSEditorGUI2; + +public partial class App : Application +{ + public override void Initialize() + { + AvaloniaXamlLoader.Load(this); + } + + public override void OnFrameworkInitializationCompleted() + { + if (ApplicationLifetime is IClassicDesktopStyleApplicationLifetime desktop) + { + // Line below is needed to remove Avalonia data validation. + // Without this line you will get duplicate validations from both Avalonia and CT + BindingPlugins.DataValidators.RemoveAt(0); + desktop.MainWindow = new MainWindow + { + DataContext = new MainWindowViewModel(), + }; + } + + base.OnFrameworkInitializationCompleted(); + } +} \ No newline at end of file diff --git a/EDSEditorGUI2/Assets/avalonia-logo.ico b/EDSEditorGUI2/Assets/avalonia-logo.ico new file mode 100644 index 0000000000000000000000000000000000000000..da8d49ff9b94e52778f5324a1b87dd443a698b57 GIT binary patch literal 176111 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 zds⪻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

r@R8DskCg$QY%d=x6zD zS7xPZcT!SYuTEDHH==$j{oi%tH1uNt18`7s86HDF4!ZI235u(usyz~^-r(5>KU(d7 z)a7ngv1_-XG%RViwqV*k_ml3iUGtuJ5c2RwH;@=B(7% zUIHUb*azeIr0`R;S`mYr)%2}i+cA&*L|d`>V#ZKIl!GrxsGR!BgE{WX zikccGd2s0p#jEWTh=&EuV+qUM^#~>9eKCd3zORO>t0jqd+kxzl7y30*WYckjFsi}@ zdW7Z-3F;7%bVH>G@CTK-+y-C<7FFqR1ym24xsuezPkJ9-PO8rY;{R#PxcwjUYX=bo z#DLedtyomk;j2Z;>FT^09F~$h_^qQwKs+q8nT=$-vM%K^AwS;#>K*_!zjDy8{EJwe zkbWF+0fMP?A0K@5^p6ImaGGZCloL4E3LbrEKAJe(!U{Ic#~XMHjCmQ!JuUD5$)wy;NV}4N3gCcye(-{fFZ$Y=dT|JX15@@6ru1z1OCt^60t zw4Ve4g##Eb<0@Pc`TfQ?B6Pf6xv_Q=53-veSLQPJ5W*Qc%bXarrzz5ca!wS`=~n#< zLUP7yKzY_xf3 zlzw3`I#6;16WNqvCQ($3TwPCPso-ozcEMn&Uk9$$3=C+n&zqkDLwA~~0dNCF!?Jh? z45xtUg*6>C=$E3&%>3U;zq;w2AF2qTl#}ORej6JkW}yvJvXBJ`Yk zV+`ih|265EX7F`ol|x901({tr$zt$oKiH2dHAS(^7E&(p4COZ<){(V4YoJJ1OZNNK~zrXR&ID*fMF5ECciW9q5w-RhK)J*7V`8yvzm z)HiQ4-41XsP1A?Qac`;5A9II_Zs(*1!FPzZ_iJ2TWCU0QeItJ5#&Y?|Kg81%>)2g zXOVu(>(iM-K~oP~6Q`!6=t`rigOh2R2ul=Sc&M(+&}~Uqyq@GXh!cK#wvHl|siF#@{t(J`3#jPn z_MRgvnrg!^CGe(=56{s^|Ad8ZzgKoUu8InX6yxSoE^WNmK_%R2Lb#Ai#Hf46H(f`^ zYl}47_Bixq1TAW4y1oC%YCjEY^~KY%zeDH>)+>q{~n>G_wQCLnp&oVqhoCFU_X^6P$P0z~F3|<^%e8 zyA%8@oYrw{DHF<1_{S!F@5`0(>1B(f7x#L9f1L1*<@(X&z>>APke>VT`~3jv)-nT^ z!v9A39U8DB#{+VJC>MtZ88=2-Z`xY_FJ%Tx`8+)~PxU9wrC@fxEc}rt;G5Wb!EBuc zzR)8}%Q_ROKMF>9-v$jRo)7;>nWH=c0P@+HY8wQYYW+nr$yl1eZw+t5RMlkh^=cP) zK4q-8)#3^29$wd*Vv4PYw{+qKx<9}<4eQVl|L=@Ip6S7Og#l12A`z7>Gb#TO$F{}) zB@)3mOT}a_N|;Q#EbP+Kz^r#D)sRuWO@1tps@J^ zaK9f3JjS2;*De#TBY>&Gzd)3(XaQKQMe>POOkLT_L#oudq_E@>)g>eg)qAwF2>Dq3 z(qEl=;ljDCgKe*#@U^brk^HGBm}`LvR_SYa?mhy2>{Zz+Bq(aQEQGn<;{)0s_7m;g7Ta6$pHPzX!K*ER-yQvYT+C9LH?1j}3Q9Bdd;WoH=K0Gg9 z5)Nu$;U#{}31Wm_H!@?uUI1D&_@fgcKRPlxas3!^d~C$JDSBmH&_2DH+`9r_e&@_C zg8qBdVmGDX{lMV!mf-Ew_;<|8xoW(%vHz1o&hi{^g0S}S8McKwO0d2WBWeB|+ejY0 zrAl5emzq5bV`}%l--dQ7?}6maIi#rkyd(=hZr;;s-WC(-ouieFA{1y|Zd zKe+QrZhh1ZP<>N&heUl_|I`BPqB~Xb(L@9_YgA7)eyS_3%!LAiqS7Jn2UuWY%o^w; z3uUymR1=x`tpA$Xdz^I-tw=54+N@Y{d4jOo(9iP`6mkaNO5UW6}ySjXU$ET!J#4hrxX3u zZOPCWwBD`mhkH5KzwMh_jXERBbGIbdN=|u@*B;8^LPlmM>@T zAGftuKe@7yc1)2)1Vw>aiO8?N)ZgxBakpL`PDt0yPg}8~QiK%=@$~L7IKCG#gFC~& zr&gfs!jcOoarE@u$b~mOqvPO7sMg65(CBDcI9*sfs@sb1vfbnlzUgvjYs_WfRu4wJ zT;T|G+T#X1ZaCXmVBW_)4FftP4%d&900l<%%nlC1}dxMVXa*#$xa2TFyY zZxB&ZLc6-WY$cBHh^!3pI9!$sOB+J+f4feF*;`n2sx}FqMKCY?_@p*=pnLeR`d7Cl zOJmJjD>v$*MgSAe19g43~wD7Qo_Po-D&( zT1^}7r@p)aH^(dkP-}t6H-V=r$R~sw=*rUMWHZ@)VJyN(bKmYTz?BL12jJ=XWoJ1s zjx2NP0ze!dT0+M<;?z5JjA2gipXMntMHm5M12WJxdS6>K(?B?>+j-%Lye|{Xp}@1O+q!jjaMC2%4Na3>Kd&@7BNWyM^XDQ&^|w zRcxFfg;35V@S0NOo_-6yz-yfdNk=Je+Xf`)YClmyzfBSvYddfQM_k}} zDJD#`vzh+Nt(k6j<+(8QB1Wx`xF;R4;8aWNvY%Qo3PaL!*O-lwa)vRQZ>AlMNeS1m zb}V4N%^!*$TN?nG)f2#Q$Hske4u04}r7 z-9qbS>TZF%u?uz=9%Pp+HV-#>2h?H#kRmY+g)y?J))Ih@AKEdkQ+Z$LqK z`7ANpeSgupv|mCgLx6Lgh;Iqz84)S)2kR3h>=g{=fKVK z^oD~7j%X#;&fD_I(M7eNq3MyCe&gu@$SjH15}WI*J*T-I*X=U_y~5?MqmCcA6SwXt zrf+0&>%-#H3tXHz9C@923p@;wfW`stQuOo3RW-B;#-iZn1iRMo5%22z^J!M=IbS~G z*+N5W?;06@sa%HXhRClHATg3h<8xU2b3fPHJTSVL8bjMQREWBpZ1>k+_}F&*mLy8z zC3oYir@i)t(ArJfO#8Xrxm-(;(?rwmW`XTE3;Gi*ds&USQaU z$>EKED&D=56^5lMlZe^~p@oIkeuBpU%HI>k5HFcX1!`i&|>nXa2 zqi_(e2kPc}4LR}=emDna>C?0py!OOGcuj1Mc8fF0`xQ5KE^rFRm0m6=rfPI~kNS6y zjzDomiz6x^jYo*}xd*2E8J^}VeUz$=%)4TKfwg`E9>89p$E=8G#yEQ%x zv(3g+D2J8-gi9tbB;FcES-_9@_ zw*7b^sN^LfYnZSb|BdzjP@TT6y}0x4K$kmrhGiU6dqG2}E!TbDda8?=v5$6J9J&o& zR7gTSDM6)eO&Jz(mXAk1;Y;>qmjpXoz@&qNyf{3B@J3-9Q!H5Qko;AREokJVSWft+UWDgh`@n0hXO1L&kM6*5wHjg(mpJJ4kpr}$+o%u0^*7jZquq00B za-H4ZAU|2H3?ys4YbqMAbl=i3wbhwbKd}&Qnq@MM(SYKm$)4)frEHuikRt}xv5!ln z1^2#moe1?hc^7xv5!q_d%VD<4NIU17>LpC>G``cR9vS+w60$ZaM_T6o1K%`e=FRSK z13<3@60S(_ST*$z2qRcQLBUYljoPO1pA&-3R?&R8F!fl_DhUkGQp3Sf`kJ=M6O+hS zr^H<=x>{jl_yc&R$WCL5dpzGc^@j#ntn%g-9j{ON2W4d5Y8weG(l2>6w zVvljr%~JS~#DaW8dSB5{qkK5PF@UGH7%2k?RWb@8Y3)5z6w036yr%ZQ? z6VEh;6AuC{_q2ys>ja`!_f|Jb8MXk=d}o@ly8(zJMSvH@EP*STWfm9Wqg9>6T}7k{ zonsEg7K3L3&t;gexOT-a&1Em%y(fqM8qkYpdK8MDO|~0~{vKXQfo~%ZHQy8UVTU9L zQ~W=<{$8$Kgj$5h;uk+T1`(UWLKAdoV?1p4x2{s{F|!u$@|Xk#AH{Z1DJGj7z{S-S z4?u;YkEPCS{1u=~(cBU>@@n;+?F3?*GNn`P`ZbrA=VGr2XSc%C9-LfUc*}z!qp%QY zM1(#H#QS~y=8>7!{)Z^Gv60&oiJZrcZ2*s-Sq1%c6lFV)doeBBtynu#Mv7w0vSBd} z+Ja^M`nVHKuP*hy+nOJHX3h^=XuGgOhHi_kDz3Y4F(%jps;Na>VLV*C_!Zzxi&&Ea zP25;-h$%87eEGnxE7c$&d!g0^7yywh7c`MB4&hQZfC#XNr>=RUY(Ps}skoY4VMdvX z0EI0DQ>r*io0>QoV{z{qZxM0fS>WOb2jb~SJF?90FRmCoL#Sn_l>_7?J=IS8G7Vf% zTLu;+AAKc^g`6b5Jn;aGKBBl@q&&N23gL`yd<@aZGc`xb3-b*$>i}L>6gniT7`zA> z1l}5=x!*_g?cJ|AKe~7UF!zJsTUy-ZL&r~5DmzEd4_2jP4dY4U#ov#a^?5s$=S$0x z(h&kLz?#4|FwX`L4?#YJun{U#;N!XQM>J@LyxCzT+V=!mlfmMv$L)UY6PLF4do~BJ9%**9~)K)>Hpc zsG~+C_-FB9DGCl^c5Gt?l0hD})O-vJ4aZ%zoM+@`Egm!#{%5~Cmmq?f$(TRkf4>v^ zkYD8ep{==sGm2qrzV#9lN%;y5&rpRviz$Mc_T_0PJ@+g~1QnP8D&iS%i>05oEvYae?M=0O)SixB@F`Cxk(}5g^n(kG6yM!aTbf?tTy5a z^}&ofBB&HK0w`7|+I7dn4NgKV6eEIbV~ydE%S;qw_G=GZ`>mC|MF{^2sgaAP#vt_f zB5xm|1sFnQZy|xSpPIR_twS+u+(wV6!R(gd)X2yqxNdaJl0ubr;oL4XgSuG3K2Kk2}zg$3pBm0nbrA>kQa9Rtp25 z1?plVbR)pQzxBhj4dYt9b$ndl;XnKZB70|UgAHPf0al8d@N||sFa1u8F1m=Zzc?RV z(wP}meSn^yD14#^*8?Sh7x7PW(=!mmHefS&;RkVh2Egw^CjpZhi=OTtKjMs|(Urkx z5P9;_#fDj<&FSLQ4d|0&O;ZySNhVZLNS0?_s!eJx<<(2@*$41!dA2Va1N&Uq>_zb4 z1mK+z%0h#F-k|Q`g$}2X6=uh&i^A38VVU7=D=_{dC)4}^1t%4dN%(UOp?msX95fF- zZIdG`VYE+!7l>|1c6R;Uik&&rT6-bRzsjTJuv*~d%Ans2@ow;s>75?sCrD zbG#aGpj<{`;`4|{wOx-y#oH!inSHBPS`92|A|S1xTCb&`<167IcU8m{6ICWQRWCGt zdXa=~`)7RrIHY!El0z6G^-Urv+MZCKi<XQyxy;~L4HY`fKKf`{%0JIWGKJc1me+av z%_fHkr&&-UvG)Jtt?db$zdSYKCgbgix67!@y`l1#l}+?mq}+`Pbsyt_A4f#vq7C;I zT>CUNT8<(HPcrfo&(xh3b^CclqMnXlztCF_d^lz3fu@O-fCB`2CIc9!F9oDS)*$;tk%3)kM4D?{1NTI0<{B&=6 zs1LsE{Eau<)`%Mi7G~pd_xbd>`aE=FI$EU~K;=Xb|w7Y+5 zN2J>P$XOHV`FBuQ<}$4EE}5MlNDKX{Vdzkb~V4Bkbu4IBikP{WO@k(K^Tq=uu+ zsa5=Gfppw)y_4E_b@of?wj&R!dy~D(NZHVn)V`N`iNGut*WAszZzxG!g=jmNmgQ5i zNlH5VaM|w|E9(e1JJ<&_eTOEm`abc66RL2TcK-@;d9_C9W!In^8U+f)&N>o{tEBWm=2QawvC)baxT7rE4K; zo#{waCXei`9T(TV4dknZ;XvUpAbfH*G;TbLNu+k<+};{WF~JY}qR#%dbkwOM_H;p! zd&>e9xGE9gIa}Haf$C7z#~M<>*!M^$8`rVcr%0`Rn@z>Q7+Q;JmgCV+MtWV6nN

!LxQh!NmF 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 values, Type targetType, object? parameter, CultureInfo culture) + { + // Ensure all bindings are provided and attached to correct target type + if (values?.Count != 3 || !targetType.IsAssignableFrom(typeof(ImmutableSolidColorBrush))) + throw new NotSupportedException(); + + if (values[0] is not string rawindex || + values[1] is not string name || + values[2] is not int typeIndex) + return BindingOperations.DoNothing; + + int index = int.Parse(rawindex, NumberStyles.HexNumber); + + var typeValues = Enum.GetNames(typeof(LibCanOpen.OdObject.Types.ObjectType)).Skip(1).ToArray(); + bool parseOk = Enum.TryParse(typeValues[typeIndex], out LibCanOpen.OdObject.Types.ObjectType type); + + if (parseOk) + { + var indexRequest = new NewIndexRequest(index, name, type); + return indexRequest; + } + else + { + return BindingOperations.DoNothing; + } + } +} diff --git a/EDSEditorGUI2/EDSEditorGUI2.csproj b/EDSEditorGUI2/EDSEditorGUI2.csproj new file mode 100644 index 00000000..ab887d37 --- /dev/null +++ b/EDSEditorGUI2/EDSEditorGUI2.csproj @@ -0,0 +1,30 @@ + + + WinExe + net8.0 + enable + true + app.manifest + true + + + + + + + + + + + + + + + + + + + + + + diff --git a/EDSEditorGUI2/Extensions.cs b/EDSEditorGUI2/Extensions.cs new file mode 100644 index 00000000..2ccc548a --- /dev/null +++ b/EDSEditorGUI2/Extensions.cs @@ -0,0 +1,15 @@ +using System; + +namespace EDSEditorGUI2 +{ + public static class StringExtensions + { + /// + /// Convert different types of hex/dec string to integer + /// + public static UInt16 ToInteger(this String val) + { + return (UInt16)Convert.ToInt32(val, 16); + } + } +} diff --git a/EDSEditorGUI2/Icons.axaml b/EDSEditorGUI2/Icons.axaml new file mode 100644 index 00000000..ef341445 --- /dev/null +++ b/EDSEditorGUI2/Icons.axaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + M3.7547787,12.4995322 L20.2466903,12.4995322 C20.6609039,12.4995322 20.9966903,12.1637458 20.9966903,11.7495322 C20.9966903,11.3353187 20.6609039,10.9995322 20.2466903,10.9995322 L3.7547787,10.9995322 C3.34056514,10.9995322 3.0047787,11.3353187 3.0047787,11.7495322 C3.0047787,12.1637458 3.34056514,12.4995322 3.7547787,12.4995322 Z + M14.5,13 L14.5,3.75378577 C14.5,3.33978577 14.164,3.00378577 13.75,3.00378577 C13.336,3.00378577 13,3.33978577 13,3.75378577 L13,13 L3.75387573,13 C3.33987573,13 3.00387573,13.336 3.00387573,13.75 C3.00387573,14.164 3.33987573,14.5 3.75387573,14.5 L13,14.5 L13,23.7523651 C13,24.1663651 13.336,24.5023651 13.75,24.5023651 C14.164,24.5023651 14.5,24.1663651 14.5,23.7523651 L14.5,14.5 L23.7498262,14.5030754 C24.1638262,14.5030754 24.4998262,14.1670754 24.4998262,13.7530754 C24.4998262,13.3390754 24.1638262,13.0030754 23.7498262,13.0030754 L14.5,13 Z + M3 5.75C3 4.23122 4.23122 3 5.75 3H15.7145C16.5764 3 17.4031 3.34241 18.0126 3.9519L20.0481 5.98744C20.6576 6.59693 21 7.42358 21 8.28553V18.25C21 19.7688 19.7688 21 18.25 21H5.75C4.23122 21 3 19.7688 3 18.25V5.75ZM5.75 4.5C5.05964 4.5 4.5 5.05964 4.5 5.75V18.25C4.5 18.9404 5.05964 19.5 5.75 19.5H6V14.25C6 13.0074 7.00736 12 8.25 12H15.75C16.9926 12 18 13.0074 18 14.25V19.5H18.25C18.9404 19.5 19.5 18.9404 19.5 18.25V8.28553C19.5 7.8214 19.3156 7.37629 18.9874 7.0481L16.9519 5.01256C16.6918 4.75246 16.3582 4.58269 16 4.52344V7.25C16 8.49264 14.9926 9.5 13.75 9.5H9.25C8.00736 9.5 7 8.49264 7 7.25V4.5H5.75ZM16.5 19.5V14.25C16.5 13.8358 16.1642 13.5 15.75 13.5H8.25C7.83579 13.5 7.5 13.8358 7.5 14.25V19.5H16.5ZM8.5 4.5V7.25C8.5 7.66421 8.83579 8 9.25 8H13.75C14.1642 8 14.5 7.66421 14.5 7.25V4.5H8.5Z + + + diff --git a/EDSEditorGUI2/Mapper/ProtobufferViewModelMapper.cs b/EDSEditorGUI2/Mapper/ProtobufferViewModelMapper.cs new file mode 100644 index 00000000..9fff16ce --- /dev/null +++ b/EDSEditorGUI2/Mapper/ProtobufferViewModelMapper.cs @@ -0,0 +1,51 @@ +using AutoMapper; +using Google.Protobuf.WellKnownTypes; +using LibCanOpen; +using System; + +namespace EDSEditorGUI2.Mapper +{ + public partial class ProtobufferViewModelMapper + { + public static ViewModels.Device MapFromProtobuffer(CanOpenDevice source) + { + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap().ConvertUsing(ts => ts.ToDateTime()); + cfg.CreateMap() + .ForMember(dest => dest.FileVersion, opt => opt.MapFrom(src => src.FileVersion)) + .ForMember(dest => dest.Description, opt => opt.MapFrom(src => src.Description)) + .ForMember(dest => dest.CreationTime, opt => opt.MapFrom(src => src.CreationTime)) + .ForMember(dest => dest.CreatedBy, opt => opt.MapFrom(src => src.CreatedBy)) + .ForMember(dest => dest.ModificationTime, opt => opt.MapFrom(src => src.ModificationTime)) + .ForMember(dest => dest.ModifiedBy, opt => opt.MapFrom(src => src.ModifiedBy)); + cfg.CreateMap() + .ForMember(dest => dest.FileInfo, opt => opt.MapFrom(src => src.FileInfo)) + .ForMember(dest => dest.DeviceInfo, opt => opt.MapFrom(src => src.DeviceInfo)) + .ForMember(dest => dest.DeviceCommissioning, opt => opt.MapFrom(src => src.DeviceCommissioning)) + .ForPath(dest => dest.Objects.Data, opt => opt.MapFrom(src => src.Objects)); + + cfg.CreateMap(); + cfg.CreateMap(); + cfg.CreateMap(); + + }); + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + var result = mapper.Map(source); + return result; + } + + public static CanOpenDevice MapToProtobuffer(ViewModels.Device source) + { + var config = new MapperConfiguration(cfg => + { + //TODO + }); + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + var result = mapper.Map(source); + return result; + } + } +} diff --git a/EDSEditorGUI2/Program.cs b/EDSEditorGUI2/Program.cs new file mode 100644 index 00000000..c22186a5 --- /dev/null +++ b/EDSEditorGUI2/Program.cs @@ -0,0 +1,21 @@ +using Avalonia; +using System; + +namespace EDSEditorGUI2; + +sealed class Program +{ + // Initialization code. Don't use any Avalonia, third-party APIs or any + // SynchronizationContext-reliant code before AppMain is called: things aren't initialized + // yet and stuff might break. + [STAThread] + public static void Main(string[] args) => BuildAvaloniaApp() + .StartWithClassicDesktopLifetime(args); + + // Avalonia configuration, don't remove; also used by visual designer. + public static AppBuilder BuildAvaloniaApp() + => AppBuilder.Configure() + .UsePlatformDetect() + .WithInterFont() + .LogToTrace(); +} diff --git a/EDSEditorGUI2/ViewLocator.cs b/EDSEditorGUI2/ViewLocator.cs new file mode 100644 index 00000000..c52fcee4 --- /dev/null +++ b/EDSEditorGUI2/ViewLocator.cs @@ -0,0 +1,33 @@ +using Avalonia.Controls; +using Avalonia.Controls.Templates; +using EDSEditorGUI2.ViewModels; +using System; + +namespace EDSEditorGUI2; + +public class ViewLocator : IDataTemplate +{ + + public Control? Build(object? data) + { + if (data is null) + return null; + + var name = data.GetType().FullName!.Replace("ViewModel", "View", StringComparison.Ordinal); + var type = Type.GetType(name); + + if (type != null) + { + var control = (Control)Activator.CreateInstance(type)!; + control.DataContext = data; + return control; + } + + return new TextBlock { Text = "Not Found: " + name }; + } + + public bool Match(object? data) + { + return data is ViewModelBase; + } +} diff --git a/EDSEditorGUI2/ViewModels/Device.cs b/EDSEditorGUI2/ViewModels/Device.cs new file mode 100644 index 00000000..82868a44 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/Device.cs @@ -0,0 +1,29 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace EDSEditorGUI2.ViewModels +{ + public partial class Device : ObservableObject + { + public Device() + { + } + + [ObservableProperty] + private FileInfo _fileInfo = new(); + + [ObservableProperty] + private DeviceInfo _deviceInfo = new(); + + [ObservableProperty] + private DeviceCommissioning _deviceCommissioning = new(); + + [ObservableProperty] + private DeviceOD _objects = new(); + + public void OnClickCommand() + { + // do something + } + } +} + diff --git a/EDSEditorGUI2/ViewModels/DeviceCommissioning.cs b/EDSEditorGUI2/ViewModels/DeviceCommissioning.cs new file mode 100644 index 00000000..aee74b5d --- /dev/null +++ b/EDSEditorGUI2/ViewModels/DeviceCommissioning.cs @@ -0,0 +1,16 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; + +namespace EDSEditorGUI2.ViewModels; + +public partial class DeviceCommissioning : ObservableObject +{ + [ObservableProperty] + private UInt32 _nodeId; + + [ObservableProperty] + private string _nodeName = string.Empty; + + [ObservableProperty] + private UInt32 _baudrate; +} diff --git a/EDSEditorGUI2/ViewModels/DeviceInfo.cs b/EDSEditorGUI2/ViewModels/DeviceInfo.cs new file mode 100644 index 00000000..c9111e83 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/DeviceInfo.cs @@ -0,0 +1,45 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace EDSEditorGUI2.ViewModels; + +public partial class DeviceInfo : ObservableObject +{ + [ObservableProperty] + string _vendorName = string.Empty; + + [ObservableProperty] + string _productName = string.Empty; + + [ObservableProperty] + bool _baudRate10; + + [ObservableProperty] + bool _baudRate20; + + [ObservableProperty] + bool _baudRate50; + + [ObservableProperty] + bool _baudRate125; + + [ObservableProperty] + bool _baudRate250; + + [ObservableProperty] + bool _baudRate500; + + [ObservableProperty] + bool _baudRate800; + + [ObservableProperty] + bool _baudRate1000; + + [ObservableProperty] + bool _baudRateAuto; + + [ObservableProperty] + bool _lssSlave; + + [ObservableProperty] + bool _lssMaster; +} diff --git a/EDSEditorGUI2/ViewModels/DeviceOD.cs b/EDSEditorGUI2/ViewModels/DeviceOD.cs new file mode 100644 index 00000000..03b2128b --- /dev/null +++ b/EDSEditorGUI2/ViewModels/DeviceOD.cs @@ -0,0 +1,91 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; + +namespace EDSEditorGUI2.ViewModels; +public partial class DeviceOD : ObservableObject +{ + public ObservableCollection> Data { get; } = []; + + [ObservableProperty] + KeyValuePair _selectedObject; + + [ObservableProperty] + KeyValuePair _selectedSubObject; + + [ObservableProperty] + ObservableCollection> _selectedSubObjects = []; + + public DeviceOD() + { + } + + private static int IndexStringToInt(string str) + { + if (str.StartsWith("0x")) + { + var hex = str[2..]; + return Convert.ToUInt16(hex, 16); + } + else + { + return Convert.ToUInt16(str); + } + } + + public void AddIndex(int index, string name, LibCanOpen.OdObject.Types.ObjectType type) + { + var strIndex = index.ToString("X4"); + var newObj = new OdObject + { + Name = name, + Type = type + }; + + // create OD entry + if (type == LibCanOpen.OdObject.Types.ObjectType.Var) + { + var newSub = new OdSubObject() + { + Name = name, + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + }; + newObj.SubObjects.Add(new KeyValuePair("0x0", newSub)); + } + else + { + var CountSub = new OdSubObject() + { + Name = "Highest sub-index supported", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0x01" + }; + var Sub1 = new OdSubObject() + { + Name = "Sub Object 1", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + }; + + newObj.SubObjects.Add(new KeyValuePair("0x0", CountSub)); + newObj.SubObjects.Add(new KeyValuePair("0x1", Sub1)); + } + Data.Add(new KeyValuePair(strIndex, newObj)); + } + + public void RemoveIndex(object sender) + { + + } +} diff --git a/EDSEditorGUI2/ViewModels/FileInfo.cs b/EDSEditorGUI2/ViewModels/FileInfo.cs new file mode 100644 index 00000000..7d2f5596 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/FileInfo.cs @@ -0,0 +1,25 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using System; + +namespace EDSEditorGUI2.ViewModels; + +public partial class FileInfo : ObservableObject +{ + [ObservableProperty] + private string _fileVersion = string.Empty; + + [ObservableProperty] + private string _description = string.Empty; + + [ObservableProperty] + private DateTime _creationTime; + + [ObservableProperty] + private string _createdBy = string.Empty; + + [ObservableProperty] + private DateTime _modificationTime; + + [ObservableProperty] + private string _modifiedBy = string.Empty; +} diff --git a/EDSEditorGUI2/ViewModels/MainWindowViewModel.cs b/EDSEditorGUI2/ViewModels/MainWindowViewModel.cs new file mode 100644 index 00000000..9d0dfdf9 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,45 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using EDSEditorGUI2.Mapper; +using System.Collections.ObjectModel; + +namespace EDSEditorGUI2.ViewModels; + +public partial class MainWindowViewModel : ViewModelBase +{ + int Counter = 0; + public void AddNewDevice(object sender) + { + var device = new LibCanOpen.CanOpenDevice + { + DeviceInfo = new() + { + ProductName = "New Product" + Counter.ToString() + }, + }; + + Counter++; + + //string dir = Environment.OSVersion.Platform == PlatformID.Win32NT ? "\\" : "/"; + //eds.projectFilename = Environment.GetFolderPath(Environment.SpecialFolder.Personal) + dir + "project"; + + //DeviceView device = new DeviceView(eds, network); + //device.UpdateODViewForEDS += Device_UpdateODViewForEDS; + + //eds.OnDataDirty += Eds_onDataDirty; + + //device.Dock = DockStyle.Fill; + //device.dispatch_updateOD(); + + var DeviceView = ProtobufferViewModelMapper.MapFromProtobuffer(device); + Network.Add(DeviceView); + } +#pragma warning disable CA1822 // Mark members as static + public string Greeting => "Welcome to Avalonia!"; +#pragma warning restore CA1822 // Mark members as static + public ObservableCollection Network { get; set; } = []; + + [ObservableProperty] + public Device? selectedDevice; + + +} diff --git a/EDSEditorGUI2/ViewModels/OdObject.cs b/EDSEditorGUI2/ViewModels/OdObject.cs new file mode 100644 index 00000000..02e90e64 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/OdObject.cs @@ -0,0 +1,155 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using libEDSsharp; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace EDSEditorGUI2.ViewModels +{ + public partial class OdObject : ObservableObject + { + [ObservableProperty] + private bool _disabled; + + [ObservableProperty] + string _name = string.Empty; + + [ObservableProperty] + string _alias = string.Empty; + + [ObservableProperty] + string _description = string.Empty; + + [ObservableProperty] + LibCanOpen.OdObject.Types.ObjectType _type; + + [ObservableProperty] + string _countLabel = string.Empty; + + [ObservableProperty] + string _storageGroup = string.Empty; + + [ObservableProperty] + bool flagsPDO; + + [ObservableProperty] + ObservableCollection> _subObjects = []; + + /// + /// very based on ODentry.AddSubEntry + /// + public OdSubObject? AddSubEntry(KeyValuePair selected) + { + if (Type == LibCanOpen.OdObject.Types.ObjectType.Var) + return null; + + OdSubObject newOd; + + //Do we need the type check?? + if ((SubObjects.Count == 0) && ((Type == LibCanOpen.OdObject.Types.ObjectType.Array) || (Type == LibCanOpen.OdObject.Types.ObjectType.Record))) + { + SubObjects.Add(new KeyValuePair("0", new OdSubObject + { + Name = "Highest sub-index supported", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0x01" + })); + } + + var lastSubOd = SubObjects.Last(); + UInt16 maxSubIndex = 1; + UInt16 lastSubIndex = 1; + + // create new or clone existing sub od + if (lastSubOd.Value == null || lastSubOd.Key.ToInteger() < 1) + { + newOd = new OdSubObject + { + Name = "item", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32 + }; + } + else + { + newOd = new OdSubObject + { + //TODO: make a clone function with reflection to keep it up-to-date + Name = selected.Value.Name, + Alias = selected.Value.Alias, + Type = selected.Value.Type, + Sdo = selected.Value.Sdo, + Pdo = selected.Value.Pdo, + Srdo = selected.Value.Srdo, + DefaultValue = selected.Value.DefaultValue, + ActualValue = selected.Value.ActualValue, + LowLimit = selected.Value.LowLimit, + HighLimit = selected.Value.HighLimit, + StringLengthMin = selected.Value.StringLengthMin, + }; + } + + // insert new sub od + ObservableCollection> newSubObjects = []; + UInt16 newSubIndex = 0; + foreach (var sub in SubObjects) + { + var subOd = sub.Value; + if (sub.Key.ToInteger() > newSubIndex) + newSubIndex = sub.Key.ToInteger(); + + newSubObjects.Add(new KeyValuePair((newSubIndex++).ToHexString(), subOd)); + + if (selected.Value == subOd) + newSubObjects.Add(new KeyValuePair((newSubIndex++).ToHexString(), newOd)); + } + + SubObjects = newSubObjects; + + // Write maxSubIndex to first sub index + if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && SubObjects.Count > 0) + { + SubObjects[0].Value.DefaultValue = string.Format("0x{0:X2}", newSubIndex - 1); + } + + return newOd; + } + /// + /// Remove current sub entry + /// + /// Keyvalue pair of the subindex to be removed + /// Renumber subentries + /// true on successfull removal + public bool RemoveSubEntry(KeyValuePair subObjectToRemove, bool renumber) + { + if (Type == LibCanOpen.OdObject.Types.ObjectType.Array || Type == LibCanOpen.OdObject.Types.ObjectType.Record) + { + UInt16 maxSubIndex = SubObjects[0].Value.DefaultValue.ToInteger(); + UInt16 lastSubIndex = SubObjects.Last().Key.ToInteger(); + + SubObjects.Remove(subObjectToRemove); + + if (renumber) + { + ObservableCollection> newSubObjects = []; + UInt16 subIndex = 0; + foreach (var subOd in SubObjects) + newSubObjects.Add(new KeyValuePair((subIndex++).ToHexString(), subOd.Value)); + + SubObjects = newSubObjects; + } + + // Write maxSubIndex to first sub index + if (maxSubIndex > 0 && maxSubIndex == lastSubIndex && SubObjects.Count > 0) + { + SubObjects[0].Value.DefaultValue = string.Format("0x{0:X2}", SubObjects.Last().Key.ToInteger()); + } + return true; + } + return false; + } + } +} diff --git a/EDSEditorGUI2/ViewModels/OdSubObject.cs b/EDSEditorGUI2/ViewModels/OdSubObject.cs new file mode 100644 index 00000000..99d0b946 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/OdSubObject.cs @@ -0,0 +1,40 @@ +using CommunityToolkit.Mvvm.ComponentModel; +using static LibCanOpen.OdSubObject.Types; + +namespace EDSEditorGUI2.ViewModels; + +public partial class OdSubObject : ObservableObject +{ + [ObservableProperty] + private string _name = string.Empty; + + [ObservableProperty] + private string _alias = string.Empty; + + [ObservableProperty] + private DataType _type; + + [ObservableProperty] + private AccessSDO _sdo; + + [ObservableProperty] + private AccessPDO _pdo; + + [ObservableProperty] + private AccessSRDO _srdo; + + [ObservableProperty] + private string _defaultValue = string.Empty; + + [ObservableProperty] + private string _actualValue = string.Empty; + + [ObservableProperty] + private string _lowLimit = string.Empty; + + [ObservableProperty] + string _highLimit = string.Empty; + + [ObservableProperty] + private uint _stringLengthMin; +} diff --git a/EDSEditorGUI2/ViewModels/ViewModelBase.cs b/EDSEditorGUI2/ViewModels/ViewModelBase.cs new file mode 100644 index 00000000..a4565d46 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/ViewModelBase.cs @@ -0,0 +1,7 @@ +using CommunityToolkit.Mvvm.ComponentModel; + +namespace EDSEditorGUI2.ViewModels; + +public class ViewModelBase : ObservableObject +{ +} diff --git a/EDSEditorGUI2/Views/DeviceInfoView.axaml b/EDSEditorGUI2/Views/DeviceInfoView.axaml new file mode 100644 index 00000000..a624698e --- /dev/null +++ b/EDSEditorGUI2/Views/DeviceInfoView.axaml @@ -0,0 +1,40 @@ + + + + + + + + + + + + + + LSS Slave + Master + + + Baudrates + 10 kbit/s. + 20 kbit/s. + 50 kbit/s. + 125 kbit/s. + 250 kbit/s. + 500 kbit/s. + 800 kbit/s. + 1000 kbit/s. + auto + + + + + diff --git a/EDSEditorGUI2/Views/DeviceInfoView.axaml.cs b/EDSEditorGUI2/Views/DeviceInfoView.axaml.cs new file mode 100644 index 00000000..fbf6126a --- /dev/null +++ b/EDSEditorGUI2/Views/DeviceInfoView.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace EDSEditorGUI2.Views; + +public partial class DeviceInfoView : UserControl +{ + public DeviceInfoView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/EDSEditorGUI2/Views/DeviceODView.axaml b/EDSEditorGUI2/Views/DeviceODView.axaml new file mode 100644 index 00000000..0b5453f1 --- /dev/null +++ b/EDSEditorGUI2/Views/DeviceODView.axaml @@ -0,0 +1,132 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Autosave + + + + + + diff --git a/EDSEditorGUI2/Views/DeviceODView.axaml.cs b/EDSEditorGUI2/Views/DeviceODView.axaml.cs new file mode 100644 index 00000000..74cc6e93 --- /dev/null +++ b/EDSEditorGUI2/Views/DeviceODView.axaml.cs @@ -0,0 +1,113 @@ +using Avalonia.Controls; +using Avalonia.Interactivity; +using LibCanOpen; +using System; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Linq; + +namespace EDSEditorGUI2.Views; + +public partial class DeviceODView : UserControl +{ + private List _odViews = []; + public DeviceODView() + { + InitializeComponent(); + ODView_Com.grid.SelectionChanged += IndexGridSelectionChanged; + ODView_Manufacture.grid.SelectionChanged += IndexGridSelectionChanged; + ODView_Device.grid.SelectionChanged += IndexGridSelectionChanged; + + subindexGrid.SelectionChanged += subindexGridSelectionChanged; + + _odViews.Add(ODView_Com.grid); + _odViews.Add(ODView_Manufacture.grid); + _odViews.Add(ODView_Device.grid); + + foreach (var v in Enum.GetNames(typeof(OdSubObject.Types.DataType))) + { + combo_datatype.Items.Add(v); + } + + foreach (var v in Enum.GetNames(typeof(OdSubObject.Types.AccessSDO))) + { + combo_sdo.Items.Add(v); + } + + foreach (var v in Enum.GetNames(typeof(OdSubObject.Types.AccessPDO))) + { + combo_pdo.Items.Add(v); + } + + foreach (var v in Enum.GetNames(typeof(OdSubObject.Types.AccessSRDO))) + { + combo_srdo.Items.Add(v); + } + } + + private void IndexGridSelectionChanged(object? sender, SelectionChangedEventArgs e) + { + if (sender is DataGrid s && DataContext is ViewModels.DeviceOD dc) + { + if (s.SelectedItem is KeyValuePair selected) + { + dc.SelectedObject = selected; + foreach (var dg in _odViews) + { + if (dg != s) + { + dg.SelectedItem = null; + subindexGrid.SelectedItem = null; + } + } + } + } + } + private void subindexGridSelectionChanged(object? sender, SelectionChangedEventArgs e) + { + if (sender is DataGrid s && DataContext is ViewModels.DeviceOD dc) + { + if (s.SelectedItem is KeyValuePair selected) + { + dc.SelectedSubObject = selected; + dc.SelectedSubObjects.Clear(); + foreach (var row in s.SelectedItems) + { + if (row is KeyValuePair subObj) + { + dc.SelectedSubObjects.Add(subObj); + } + } + } + } + } + private void ContextMenuSubObjectAddClick(object? sender, RoutedEventArgs e) + { + if (DataContext is ViewModels.DeviceOD dc) + { + var selectedObj = dc.SelectedObject.Value; + ObservableCollection> selection = []; + + foreach (var row in dc.SelectedSubObjects) + { + selectedObj.AddSubEntry(row); + } + } + } + private void ContextMenuSubObjectRemoveClick(object? sender, RoutedEventArgs e) + { + bool renumber = sender == contextMenu_subObject_removeSubItemToolStripMenuItem; + + if (DataContext is ViewModels.DeviceOD dc) + { + var selectedObject = dc.SelectedObject.Value; + + //Clone the list because we cant modify the list we iterate on + var selectedObj = dc.SelectedSubObjects.ToList(); + foreach (var item in selectedObj) + { + selectedObject.RemoveSubEntry(item, renumber); + } + } + } +} diff --git a/EDSEditorGUI2/Views/DevicePDOView.axaml b/EDSEditorGUI2/Views/DevicePDOView.axaml new file mode 100644 index 00000000..0fe71fc2 --- /dev/null +++ b/EDSEditorGUI2/Views/DevicePDOView.axaml @@ -0,0 +1,78 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Invalid + + + + + + + + Zoom: + + + diff --git a/EDSEditorGUI2/Views/DevicePDOView.axaml.cs b/EDSEditorGUI2/Views/DevicePDOView.axaml.cs new file mode 100644 index 00000000..b7917baf --- /dev/null +++ b/EDSEditorGUI2/Views/DevicePDOView.axaml.cs @@ -0,0 +1,81 @@ +using Avalonia.Controls; +using Avalonia.Media; +using System.Collections.Generic; + +namespace EDSEditorGUI2.Views; + +public partial class DevicePDOView : UserControl +{ + private List _bitColumns = []; + public DevicePDOView() + { + InitializeComponent(); + + CreateMappingBitsAndBytesIndication(); + Zoom.Value = 100; + } + + void CreateMappingBitsAndBytesIndication() + { + //Bits + for (int i = 0; i < 64; i++) + { + var indication = new TextBlock + { + Text = i.ToString(), + VerticalAlignment = Avalonia.Layout.VerticalAlignment.Center, + TextWrapping = TextWrapping.Wrap, + }; + if ((i % 8) == 0) + { + indication.Foreground = Brushes.Red; + } + AddToMappingGrid(indication, 0, 3 + i); + + var newColumn = new ColumnDefinition(new GridLength(10 * 1.0)); + _bitColumns.Add(newColumn); + + MappingGrid.ColumnDefinitions.Add(newColumn); + } + //Bytes + for (int i = 0; i < 8; i++) + { + var indication = new TextBlock + { + Text = $"Byte {i}", + HorizontalAlignment = Avalonia.Layout.HorizontalAlignment.Center, + + TextWrapping = TextWrapping.Wrap, + }; + AddToMappingGrid(indication, 1, 3 + (i*8), 8); + } + } + void AddToMappingGrid(Control element, int row,int column, int columnspam = 1) + { + Grid.SetRow(element, row); + Grid.SetColumn(element, column); + Grid.SetColumnSpan(element, columnspam); + MappingGrid.Children.Add(element); + } + + private void Zoom_PropertyChanged(object? sender, Avalonia.AvaloniaPropertyChangedEventArgs e) + { + if (e.Property.Name == "Value") + { + decimal newValue = Zoom.Value ?? 0; + ChangeMappingZoom((double)newValue); + } + } + /// + /// Changes the zoom level on pdo mapping + /// + /// zoom level in percent + private void ChangeMappingZoom(double zoomPercent) + { + var zoom = zoomPercent / 100; + foreach (var column in _bitColumns) + { + column.Width = new GridLength(10 * zoom); + } + } +} diff --git a/EDSEditorGUI2/Views/DeviceView.axaml b/EDSEditorGUI2/Views/DeviceView.axaml new file mode 100644 index 00000000..707f1da9 --- /dev/null +++ b/EDSEditorGUI2/Views/DeviceView.axaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + This is tab 3 content + + + + diff --git a/EDSEditorGUI2/Views/DeviceView.axaml.cs b/EDSEditorGUI2/Views/DeviceView.axaml.cs new file mode 100644 index 00000000..13758624 --- /dev/null +++ b/EDSEditorGUI2/Views/DeviceView.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace EDSEditorGUI2.Views; + +public partial class DeviceView : UserControl +{ + public DeviceView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/EDSEditorGUI2/Views/MainWindow.axaml b/EDSEditorGUI2/Views/MainWindow.axaml new file mode 100644 index 00000000..d2469cd4 --- /dev/null +++ b/EDSEditorGUI2/Views/MainWindow.axaml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EDSEditorGUI2/Views/MainWindow.axaml.cs b/EDSEditorGUI2/Views/MainWindow.axaml.cs new file mode 100644 index 00000000..8fc2bd17 --- /dev/null +++ b/EDSEditorGUI2/Views/MainWindow.axaml.cs @@ -0,0 +1,11 @@ +using Avalonia.Controls; + +namespace EDSEditorGUI2.Views; + +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/EDSEditorGUI2/Views/ODIndexRangeView.axaml b/EDSEditorGUI2/Views/ODIndexRangeView.axaml new file mode 100644 index 00000000..08b0d548 --- /dev/null +++ b/EDSEditorGUI2/Views/ODIndexRangeView.axaml @@ -0,0 +1,69 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EDSEditorGUI2/Views/ODIndexRangeView.axaml.cs b/EDSEditorGUI2/Views/ODIndexRangeView.axaml.cs new file mode 100644 index 00000000..f395a39a --- /dev/null +++ b/EDSEditorGUI2/Views/ODIndexRangeView.axaml.cs @@ -0,0 +1,88 @@ +using Avalonia; +using Avalonia.Controls; +using Avalonia.Interactivity; +using DialogHostAvalonia; +using EDSEditorGUI2.Converter; +using LibCanOpen; +using System; +using System.Linq; + +namespace EDSEditorGUI2.Views; + +public partial class ODIndexRangeView : UserControl +{ + public ODIndexRangeView() + { + InitializeComponent(); + var values = Enum.GetNames(typeof(OdObject.Types.ObjectType)).Skip(1).ToArray(); + type.ItemsSource = values; + + grid.LoadingRow += GridLoadingRow; + } + + /// + /// Hides rows with indexes that is not in min&max range + /// + /// sender object + /// event param + private void GridLoadingRow(object? sender, DataGridRowEventArgs e) + { + if(e.Row.DataContext != null) + { + var dc = (System.Collections.Generic.KeyValuePair)e.Row.DataContext; + int index = int.Parse(dc.Key, System.Globalization.NumberStyles.HexNumber); + int min = Convert.ToInt32(MinIndex, 16); + int max = Convert.ToInt32(MaxIndex, 16); + e.Row.IsVisible = (min <= index && index <= max); + } + } + + public static readonly StyledProperty HeadingProperty = + AvaloniaProperty.Register(nameof(HeadingProperty)); + public string Heading + { + get { return GetValue(HeadingProperty); } + set { SetValue(HeadingProperty, value); HeadingText.Text = value; } + } + + public static readonly StyledProperty MinIndexProperty = + AvaloniaProperty.Register(nameof(MinIndexProperty)); + public string MinIndex + { + get { return GetValue(MinIndexProperty); } + set { SetValue(MinIndexProperty, value); } + } + + public static readonly StyledProperty MaxIndexProperty = + AvaloniaProperty.Register(nameof(MaxIndexProperty)); + public string MaxIndex + { + get { return GetValue(MaxIndexProperty); } + set { SetValue(MaxIndexProperty, value); } + } + + private async void AddIndex(object? sender, RoutedEventArgs e) + { + await DialogHost.Show(Resources["NewIndexDialog"]!, "NoAnimationDialogHost", OnDialogClosing); + } + + private void OnDialogClosing(object? sender, DialogClosingEventArgs e) + { + if (e.Parameter != null) + { + if (DataContext is ViewModels.DeviceOD dc && e.Parameter is NewIndexRequest param) + { + dc.AddIndex(param.Index, param.Name, param.Type); + } + } + } + + private async void RemoveIndex(object? sender, RoutedEventArgs e) + { + await DialogHost.Show(Resources["NewIndexDialog"]!, "NoAnimationDialogHost"); + } + + private void DataGrid_SelectionChanged(object? sender, Avalonia.Controls.SelectionChangedEventArgs e) + { + } +} \ No newline at end of file diff --git a/EDSEditorGUI2/app.manifest b/EDSEditorGUI2/app.manifest new file mode 100644 index 00000000..d88e268e --- /dev/null +++ b/EDSEditorGUI2/app.manifest @@ -0,0 +1,18 @@ + + + + + + + + + + + + + + diff --git a/GUITests/.gitignore b/GUITests/.gitignore new file mode 100644 index 00000000..aaddf9f7 --- /dev/null +++ b/GUITests/.gitignore @@ -0,0 +1,3 @@ +/obj +/bin + diff --git a/GUITests/GUITests.csproj b/GUITests/GUITests.csproj new file mode 100644 index 00000000..499faeae --- /dev/null +++ b/GUITests/GUITests.csproj @@ -0,0 +1,25 @@ + + + net8.0 + enable + enable + + false + true + + + + + + + + + + + + + + + + + diff --git a/GUITests/ViewModels_OdObjects.cs b/GUITests/ViewModels_OdObjects.cs new file mode 100644 index 00000000..25f779ff --- /dev/null +++ b/GUITests/ViewModels_OdObjects.cs @@ -0,0 +1,124 @@ +using EDSEditorGUI2.ViewModels; + +namespace GUITests +{ + public class ViewModels_OdObjects + { + private OdObject sut; + public ViewModels_OdObjects() + { + sut = new OdObject(); + sut.SubObjects.Add(new KeyValuePair("0", new OdSubObject + { + Name = "Highest sub-index supported", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0x01" + })); + sut.SubObjects.Add(new KeyValuePair("1", new OdSubObject() + { + Name = "Sub Object 1", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + })); + sut.SubObjects.Add(new KeyValuePair("2", new OdSubObject() + { + Name = "Sub Object 2", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + })); + } + + [Fact] + public void AddSubEntry_VarType() + { + sut = new OdObject(); + sut.Type = LibCanOpen.OdObject.Types.ObjectType.Var; + sut.SubObjects.Add(new KeyValuePair("0", new OdSubObject + { + Name = "variableTest", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + })); + sut.AddSubEntry(sut.SubObjects[0]); + Assert.Single(sut.SubObjects); + } + + [Fact] + public void AddSubEntry_RecordType() + { + sut.Type = LibCanOpen.OdObject.Types.ObjectType.Record; + sut.AddSubEntry(sut.SubObjects[1]); + Assert.Equal(4, sut.SubObjects.Count); + Assert.Equal("0x03", sut.SubObjects[0].Value.DefaultValue); + } + + [Theory] + [InlineData(false)] + [InlineData(true)] + public void RemoveSubEntry_VarType(bool renumber) + { + sut = new OdObject(); + sut.Type = LibCanOpen.OdObject.Types.ObjectType.Var; + sut.SubObjects.Add(new KeyValuePair("0x01", new OdSubObject + { + Name = "variableTest", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + })); + + var result = sut.RemoveSubEntry(sut.SubObjects[0], renumber); + Assert.False(result); + } + [Fact] + public void RemoveSubEntry_RecordType() + { + sut = new OdObject(); + sut.Type = LibCanOpen.OdObject.Types.ObjectType.Record; + sut.SubObjects.Add(new KeyValuePair("0x00", new OdSubObject + { + Name = "variableTest0", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0x01" + })); + sut.SubObjects.Add(new KeyValuePair("0x01", new OdSubObject + { + Name = "variableTest1", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + })); + sut.SubObjects.Add(new KeyValuePair("0x02", new OdSubObject + { + Name = "variableTest2", + Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + })); + + var result = sut.RemoveSubEntry(sut.SubObjects[1], false); + Assert.False(result); + } + } +} \ No newline at end of file From 6511c031ba66d0699ff2ff028567d72287f36536 Mon Sep 17 00:00:00 2001 From: Peter <31046837+pettaa123@users.noreply.github.com> Date: Sun, 16 Feb 2025 20:02:55 +0100 Subject: [PATCH 179/226] corrected logic to filter communication profile area objects (#170) Co-authored-by: Tuppatsch --- EDSEditorGUI/DeviceODView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index 6d2c2a82..acb113da 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -225,7 +225,7 @@ public void PopulateObjectLists(EDSsharp eds_target) if (od.prop.CO_disabled == true) lvi.ForeColor = Color.LightGray; - if (index <= 0x1000 || index < 0x2000) + if (index >= 0x1000 && index < 0x2000) listView_communication_objects.Items.Add(lvi); else if (index >= 0x2000 && index < 0x6000) listView_manufacturer_objects.Items.Add(lvi); From e601b40863343d7607a422833a2c7331d921dbd5 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 17 Feb 2025 17:57:25 +0100 Subject: [PATCH 180/226] Use single automapper version (#171) * upgrade version for .net8 * fix automapper v13 assert errors --- libEDSsharp/CanOpenEDSMapping.cs | 15 ++++++++++++++- libEDSsharp/libEDSsharp.csproj | 3 ++- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/CanOpenEDSMapping.cs b/libEDSsharp/CanOpenEDSMapping.cs index 599486a5..ce980ef3 100644 --- a/libEDSsharp/CanOpenEDSMapping.cs +++ b/libEDSsharp/CanOpenEDSMapping.cs @@ -90,6 +90,15 @@ public static EDSsharp MapFromProtobuffer(CanOpenDevice source) .ForMember(dest => dest.ModificationDate, opt => opt.MapFrom(src => src.ModificationTime.ToDateTime().ToString("MM-dd-yyyy"))) .ForMember(dest => dest.ModificationTime, opt => opt.MapFrom(src => src.ModificationTime.ToDateTime().ToString("h:mmtt"))); cfg.CreateMap() + .ForMember(dest => dest.BaudRate_10, opt => opt.MapFrom(src => src.BaudRate10)) + .ForMember(dest => dest.BaudRate_20, opt => opt.MapFrom(src => src.BaudRate20)) + .ForMember(dest => dest.BaudRate_50, opt => opt.MapFrom(src => src.BaudRate50)) + .ForMember(dest => dest.BaudRate_125, opt => opt.MapFrom(src => src.BaudRate125)) + .ForMember(dest => dest.BaudRate_250, opt => opt.MapFrom(src => src.BaudRate250)) + .ForMember(dest => dest.BaudRate_500, opt => opt.MapFrom(src => src.BaudRate500)) + .ForMember(dest => dest.BaudRate_800, opt => opt.MapFrom(src => src.BaudRate800)) + .ForMember(dest => dest.BaudRate_1000, opt => opt.MapFrom(src => src.BaudRate1000)) + .ForMember(dest => dest.BaudRate_auto, opt => opt.MapFrom(src => src.BaudRateAuto)) .ForMember(dest => dest.VendorNumber, opt => opt.Ignore()) .ForMember(dest => dest.ProductNumber, opt => opt.Ignore()) .ForMember(dest => dest.RevisionNumber, opt => opt.Ignore()) @@ -113,7 +122,11 @@ public static EDSsharp MapFromProtobuffer(CanOpenDevice source) .ForMember(dest => dest.LSS_SerialNumber, opt => opt.Ignore()); cfg.CreateMap() .ForMember(dest => dest.CO_accessSRDO, opt => opt.Ignore()) - .ForMember(dest => dest.CO_stringLengthMin, opt => opt.Ignore()); + .ForMember(dest => dest.CO_stringLengthMin, opt => opt.Ignore()) + .ForMember(dest => dest.CO_disabled, opt => opt.MapFrom(src => src.Disabled)) + .ForMember(dest => dest.CO_countLabel, opt => opt.MapFrom(src => src.CountLabel)) + .ForMember(dest => dest.CO_storageGroup, opt => opt.MapFrom(src => src.StorageGroup)) + .ForMember(dest => dest.CO_flagsPDO, opt => opt.MapFrom(src => src.FlagsPDO)); cfg.CreateMap().ConvertUsing(); cfg.CreateMap() .ForMember(dest => dest.Index, opt => opt.Ignore()) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 2c71b47d..96f77a65 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -47,7 +47,8 @@ - + + From d9ca4aa216ff553aaee5ac570825c16bc125457f Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 17 Feb 2025 21:14:50 +0100 Subject: [PATCH 181/226] Gui2: add missing tests (#167) * gui2: add missing tests * fixing the detected error * fixed bug in test --- .github/workflows/dotnet.yml | 4 ++++ EDSEditorGUI2/ViewModels/DeviceOD.cs | 2 +- EDSEditorGUI2/ViewModels/OdObject.cs | 8 ++++---- GUITests/MappingTests.cs | 16 ++++++++++++++++ GUITests/ViewModels_OdObjects.cs | 10 +++++----- 5 files changed, 30 insertions(+), 10 deletions(-) create mode 100644 GUITests/MappingTests.cs diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index afcc9464..15e6a5b9 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -42,6 +42,10 @@ jobs: - name: Test run: | dotnet test --no-build --verbosity normal Tests\bin\${{ matrix.configuration }}\${{ matrix.dotnet }}*\tests.dll + - name: GUITest + if: matrix.dotnet == 'net8' + run: | + dotnet test --no-build --verbosity normal GUITests\bin\${{ matrix.configuration }}\${{ matrix.dotnet }}*\GUITests.dll - name: Upload Artifact uses: actions/upload-artifact@v4 with: diff --git a/EDSEditorGUI2/ViewModels/DeviceOD.cs b/EDSEditorGUI2/ViewModels/DeviceOD.cs index 03b2128b..78684cad 100644 --- a/EDSEditorGUI2/ViewModels/DeviceOD.cs +++ b/EDSEditorGUI2/ViewModels/DeviceOD.cs @@ -40,7 +40,7 @@ public void AddIndex(int index, string name, LibCanOpen.OdObject.Types.ObjectTyp var newObj = new OdObject { Name = name, - Type = type + ObjectType = type }; // create OD entry diff --git a/EDSEditorGUI2/ViewModels/OdObject.cs b/EDSEditorGUI2/ViewModels/OdObject.cs index 02e90e64..e27277bf 100644 --- a/EDSEditorGUI2/ViewModels/OdObject.cs +++ b/EDSEditorGUI2/ViewModels/OdObject.cs @@ -22,7 +22,7 @@ public partial class OdObject : ObservableObject string _description = string.Empty; [ObservableProperty] - LibCanOpen.OdObject.Types.ObjectType _type; + LibCanOpen.OdObject.Types.ObjectType _objectType; [ObservableProperty] string _countLabel = string.Empty; @@ -41,13 +41,13 @@ public partial class OdObject : ObservableObject ///
public OdSubObject? AddSubEntry(KeyValuePair selected) { - if (Type == LibCanOpen.OdObject.Types.ObjectType.Var) + if (ObjectType == LibCanOpen.OdObject.Types.ObjectType.Var) return null; OdSubObject newOd; //Do we need the type check?? - if ((SubObjects.Count == 0) && ((Type == LibCanOpen.OdObject.Types.ObjectType.Array) || (Type == LibCanOpen.OdObject.Types.ObjectType.Record))) + if ((SubObjects.Count == 0) && ((ObjectType == LibCanOpen.OdObject.Types.ObjectType.Array) || (ObjectType == LibCanOpen.OdObject.Types.ObjectType.Record))) { SubObjects.Add(new KeyValuePair("0", new OdSubObject { @@ -125,7 +125,7 @@ public partial class OdObject : ObservableObject /// true on successfull removal public bool RemoveSubEntry(KeyValuePair subObjectToRemove, bool renumber) { - if (Type == LibCanOpen.OdObject.Types.ObjectType.Array || Type == LibCanOpen.OdObject.Types.ObjectType.Record) + if (ObjectType == LibCanOpen.OdObject.Types.ObjectType.Array || ObjectType == LibCanOpen.OdObject.Types.ObjectType.Record) { UInt16 maxSubIndex = SubObjects[0].Value.DefaultValue.ToInteger(); UInt16 lastSubIndex = SubObjects.Last().Key.ToInteger(); diff --git a/GUITests/MappingTests.cs b/GUITests/MappingTests.cs new file mode 100644 index 00000000..a810f678 --- /dev/null +++ b/GUITests/MappingTests.cs @@ -0,0 +1,16 @@ +using EDSEditorGUI2.Mapper; +using LibCanOpen; + +namespace GUITests +{ + public class MappingTests + { + [Fact] + public void MappingFromProtobuffer() + { + // testing for exception in the mapping assert. + var sut = new CanOpenDevice(); + ProtobufferViewModelMapper.MapFromProtobuffer(sut); + } + } +} diff --git a/GUITests/ViewModels_OdObjects.cs b/GUITests/ViewModels_OdObjects.cs index 25f779ff..b9a1045d 100644 --- a/GUITests/ViewModels_OdObjects.cs +++ b/GUITests/ViewModels_OdObjects.cs @@ -41,7 +41,7 @@ public ViewModels_OdObjects() public void AddSubEntry_VarType() { sut = new OdObject(); - sut.Type = LibCanOpen.OdObject.Types.ObjectType.Var; + sut.ObjectType = LibCanOpen.OdObject.Types.ObjectType.Var; sut.SubObjects.Add(new KeyValuePair("0", new OdSubObject { Name = "variableTest", @@ -58,7 +58,7 @@ public void AddSubEntry_VarType() [Fact] public void AddSubEntry_RecordType() { - sut.Type = LibCanOpen.OdObject.Types.ObjectType.Record; + sut.ObjectType = LibCanOpen.OdObject.Types.ObjectType.Record; sut.AddSubEntry(sut.SubObjects[1]); Assert.Equal(4, sut.SubObjects.Count); Assert.Equal("0x03", sut.SubObjects[0].Value.DefaultValue); @@ -70,7 +70,7 @@ public void AddSubEntry_RecordType() public void RemoveSubEntry_VarType(bool renumber) { sut = new OdObject(); - sut.Type = LibCanOpen.OdObject.Types.ObjectType.Var; + sut.ObjectType = LibCanOpen.OdObject.Types.ObjectType.Var; sut.SubObjects.Add(new KeyValuePair("0x01", new OdSubObject { Name = "variableTest", @@ -88,7 +88,7 @@ public void RemoveSubEntry_VarType(bool renumber) public void RemoveSubEntry_RecordType() { sut = new OdObject(); - sut.Type = LibCanOpen.OdObject.Types.ObjectType.Record; + sut.ObjectType = LibCanOpen.OdObject.Types.ObjectType.Record; sut.SubObjects.Add(new KeyValuePair("0x00", new OdSubObject { Name = "variableTest0", @@ -118,7 +118,7 @@ public void RemoveSubEntry_RecordType() })); var result = sut.RemoveSubEntry(sut.SubObjects[1], false); - Assert.False(result); + Assert.True(result); } } } \ No newline at end of file From f4694cd0f14aba5e1af4a9803c02f8729c3d5699 Mon Sep 17 00:00:00 2001 From: Peter <31046837+pettaa123@users.noreply.github.com> Date: Thu, 6 Mar 2025 15:13:57 +0100 Subject: [PATCH 182/226] changed incorrect argument naming from cob to idx for build_PDOlist (#173) Co-authored-by: Tuppatsch --- libEDSsharp/PDOHelper.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index a476e8be..332b0bf3 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -242,11 +242,11 @@ public void build_PDOlists() /// /// Look through the OD and register PDO /// - /// OD index to to start looking from, it will stop after 0x1ff indexes + /// OD index to to start looking from, it will stop after 0x1ff indexes /// list to add found pdo into - void build_PDOlist(UInt16 startcob, List slots) + void build_PDOlist(UInt16 startIdx, List slots) { - for (UInt16 idx = startcob; idx < startcob + 0x01ff; idx++) + for (UInt16 idx = startIdx; idx < startIdx + 0x01ff; idx++) { if (eds.ods.ContainsKey(idx)) { From 1332dc0e1c0c53efe8f9d06e99d9d16c7c87a202 Mon Sep 17 00:00:00 2001 From: Charles Hardin Date: Mon, 17 Mar 2025 23:07:53 -0700 Subject: [PATCH 183/226] extend the protobuffer compile to support macosx (#175) The protoc tools are available for OSX and adding this support allows EDSSharp and libEDSsharp to compile for macosx using dotnet 8.0 Signed-off-by: Charles Hardin --- libEDSsharp/libEDSsharp.csproj | 1 + 1 file changed, 1 insertion(+) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 96f77a65..3e443832 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -57,6 +57,7 @@ + From ee517a245ce7e6c1f4a7bb918f62d03dfa7d4d2f Mon Sep 17 00:00:00 2001 From: Charles Hardin Date: Wed, 19 Mar 2025 10:39:57 -0700 Subject: [PATCH 184/226] msbuild: allow the dotnet for macosx installs to target windows (#176) This makes the build complete on a dotnet install for a mac so that it is easier to verify the build and setup. Signed-off-by: Charles Hardin --- EDSEditorGUI/EDSEditorGUI.csproj | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 9dde5d88..42bc8815 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -3,6 +3,7 @@ net481 net8.0-windows net481;net8.0-windows + true WinExe ODEditor EDSEditor @@ -104,6 +105,6 @@ - git describe --tags --long --dirty > "$(MSBuildProjectDirectory)\version.txt" || exit 0 + git describe --tags --long --dirty > "$(MSBuildProjectDirectory)$([System.IO.Path]::DirectorySeparatorChar)version.txt" || exit 0
\ No newline at end of file From ada7c1bc3a9ac1571fdd70922cdb9336116951b8 Mon Sep 17 00:00:00 2001 From: Charles Hardin Date: Fri, 21 Mar 2025 12:40:52 -0700 Subject: [PATCH 185/226] edssharp: use the basename of the argv0 for the usage output (#178) The code was hardcoded to EDSEditor but the compiled code was EDSSharp and so just cleanup the code to handle that case Before: Usage: EDSEditor --infile file.[xdd|eds] --outfile [valid output file] \ [OPTIONAL] --type [exporter type] After: Usage: EDSSharp --infile file.[xdd|eds] --outfile [valid output file] \ [OPTIONAL] --type [exporter type] Signed-off-by: Charles Hardin --- EDSSharp/Program.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index c1686d42..a8b783a8 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -174,7 +174,8 @@ static ExporterDescriptor FindMatchingExporter(string outpath, string outType) static void PrintHelpText() { - Console.WriteLine("Usage: EDSEditor --infile file.[xdd|eds] --outfile [valid output file] [OPTIONAL] --type [exporter type]"); + string name = Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]); + Console.WriteLine($"Usage: {name} --infile file.[xdd|eds] --outfile [valid output file] [OPTIONAL] --type [exporter type]"); Console.WriteLine("The output file format depends on --outfile extension and --type"); Console.WriteLine("If --outfile extension matcher one exporter then --type IS NOT needed"); Console.WriteLine("If --outfile extension matcher multiple exporter then --type IS needed"); From 4c80424e8947fabee5d6c16d55fdc1ff77e45fcc Mon Sep 17 00:00:00 2001 From: Peter <31046837+pettaa123@users.noreply.github.com> Date: Thu, 17 Apr 2025 17:04:28 +0200 Subject: [PATCH 186/226] gui: exit loop early once row and col found in pdoview (#177) Co-authored-by: Tuppatsch --- EDSEditorGUI/DevicePDOView2.cs | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 085e021f..025c0b20 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -162,36 +162,38 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) SourceGrid.Cells.ICellVirtual getItemAtGridPoint(Point P, out int foundrow, out int foundcol) { - int y = 0; - int y2 = 0; foundrow = 0; + foundcol = 0; + + // Calculate the row index based on the Y position + int y = 0; foreach (GridRow row in grid1.Rows) { - y2 = y + row.Height; + int y2 = y + row.Height; if (P.Y > y && P.Y < y2) { foundrow = row.Index + grid1.VScrollBar.Value; + break; } y = y2; } + // Calculate the column based on the X position int x2 = 0; - foundcol = 0; int outofview = 0; for (int i = 0; i < grid1.HScrollBar.Value; i++) { - outofview += grid1.Columns.GetWidth(i); + x2 += grid1.Columns.GetWidth(i); } - x2 = -outofview; + foreach (GridColumn col in grid1.Columns) { - - - if (P.X > x2) + if (P.X > x2 && P.X <= x2 + col.Width) { foundcol = col.Index; + break; } x2 += col.Width; } From 9bdecb90573aaa6160dd4d220ce6cabe024edced Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 5 May 2025 19:47:59 +0200 Subject: [PATCH 187/226] gui2: object dictionary rewrite (#182) * gui2 object dictionary rewrite --- .../Mapper/ProtobufferViewModelMapper.cs | 44 ++- EDSEditorGUI2/ViewModels/Device.cs | 2 +- EDSEditorGUI2/ViewModels/DeviceOD.cs | 91 ----- EDSEditorGUI2/ViewModels/ObjectDictionary.cs | 334 ++++++++++++++++++ EDSEditorGUI2/ViewModels/OdObject.cs | 6 +- EDSEditorGUI2/ViewModels/OdSubObject.cs | 2 +- EDSEditorGUI2/Views/DeviceODView.axaml | 6 +- EDSEditorGUI2/Views/DeviceODView.axaml.cs | 8 +- EDSEditorGUI2/Views/DevicePDOView.axaml | 2 +- EDSEditorGUI2/Views/ODIndexRangeView.axaml | 4 +- EDSEditorGUI2/Views/ODIndexRangeView.axaml.cs | 2 +- GUITests/ViewModels_OdObjects.cs | 16 +- 12 files changed, 398 insertions(+), 119 deletions(-) delete mode 100644 EDSEditorGUI2/ViewModels/DeviceOD.cs create mode 100644 EDSEditorGUI2/ViewModels/ObjectDictionary.cs diff --git a/EDSEditorGUI2/Mapper/ProtobufferViewModelMapper.cs b/EDSEditorGUI2/Mapper/ProtobufferViewModelMapper.cs index 9fff16ce..33e56929 100644 --- a/EDSEditorGUI2/Mapper/ProtobufferViewModelMapper.cs +++ b/EDSEditorGUI2/Mapper/ProtobufferViewModelMapper.cs @@ -19,22 +19,58 @@ public static ViewModels.Device MapFromProtobuffer(CanOpenDevice source) .ForMember(dest => dest.CreatedBy, opt => opt.MapFrom(src => src.CreatedBy)) .ForMember(dest => dest.ModificationTime, opt => opt.MapFrom(src => src.ModificationTime)) .ForMember(dest => dest.ModifiedBy, opt => opt.MapFrom(src => src.ModifiedBy)); + cfg.CreateMap, ViewModels.ObjectDictionary>().ConvertUsing(); cfg.CreateMap() .ForMember(dest => dest.FileInfo, opt => opt.MapFrom(src => src.FileInfo)) .ForMember(dest => dest.DeviceInfo, opt => opt.MapFrom(src => src.DeviceInfo)) .ForMember(dest => dest.DeviceCommissioning, opt => opt.MapFrom(src => src.DeviceCommissioning)) - .ForPath(dest => dest.Objects.Data, opt => opt.MapFrom(src => src.Objects)); - + .ForMember(dest => dest.Objects, opt => opt.MapFrom(src => src.Objects)); cfg.CreateMap(); cfg.CreateMap(); - cfg.CreateMap(); - }); config.AssertConfigurationIsValid(); var mapper = config.CreateMapper(); var result = mapper.Map(source); return result; } + public class ODConverter : ITypeConverter, ViewModels.ObjectDictionary>, + ITypeConverter< ViewModels.ObjectDictionary, Google.Protobuf.Collections.MapField> + { + public ViewModels.ObjectDictionary Convert(Google.Protobuf.Collections.MapField source, ViewModels.ObjectDictionary destination, ResolutionContext context) + { + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }); + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + + destination = []; + foreach (var item in source) + { + destination.Add(item.Key, mapper.Map(item.Value)); + } + return destination; + } + public Google.Protobuf.Collections.MapField Convert(ViewModels.ObjectDictionary source, Google.Protobuf.Collections.MapField destination, ResolutionContext context) + { + var config = new MapperConfiguration(cfg => + { + cfg.CreateMap(); + cfg.CreateMap(); + }); + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + + destination = []; + foreach (var item in source) + { + destination.Add(item.Key, mapper.Map(item.Value)); + } + return destination; + } + } public static CanOpenDevice MapToProtobuffer(ViewModels.Device source) { diff --git a/EDSEditorGUI2/ViewModels/Device.cs b/EDSEditorGUI2/ViewModels/Device.cs index 82868a44..c5f1ca85 100644 --- a/EDSEditorGUI2/ViewModels/Device.cs +++ b/EDSEditorGUI2/ViewModels/Device.cs @@ -18,7 +18,7 @@ public Device() private DeviceCommissioning _deviceCommissioning = new(); [ObservableProperty] - private DeviceOD _objects = new(); + private ObjectDictionary _objects = new(); public void OnClickCommand() { diff --git a/EDSEditorGUI2/ViewModels/DeviceOD.cs b/EDSEditorGUI2/ViewModels/DeviceOD.cs deleted file mode 100644 index 78684cad..00000000 --- a/EDSEditorGUI2/ViewModels/DeviceOD.cs +++ /dev/null @@ -1,91 +0,0 @@ -using CommunityToolkit.Mvvm.ComponentModel; -using System; -using System.Collections.Generic; -using System.Collections.ObjectModel; - -namespace EDSEditorGUI2.ViewModels; -public partial class DeviceOD : ObservableObject -{ - public ObservableCollection> Data { get; } = []; - - [ObservableProperty] - KeyValuePair _selectedObject; - - [ObservableProperty] - KeyValuePair _selectedSubObject; - - [ObservableProperty] - ObservableCollection> _selectedSubObjects = []; - - public DeviceOD() - { - } - - private static int IndexStringToInt(string str) - { - if (str.StartsWith("0x")) - { - var hex = str[2..]; - return Convert.ToUInt16(hex, 16); - } - else - { - return Convert.ToUInt16(str); - } - } - - public void AddIndex(int index, string name, LibCanOpen.OdObject.Types.ObjectType type) - { - var strIndex = index.ToString("X4"); - var newObj = new OdObject - { - Name = name, - ObjectType = type - }; - - // create OD entry - if (type == LibCanOpen.OdObject.Types.ObjectType.Var) - { - var newSub = new OdSubObject() - { - Name = name, - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, - Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, - Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, - Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, - DefaultValue = "0" - }; - newObj.SubObjects.Add(new KeyValuePair("0x0", newSub)); - } - else - { - var CountSub = new OdSubObject() - { - Name = "Highest sub-index supported", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, - Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro, - Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, - Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, - DefaultValue = "0x01" - }; - var Sub1 = new OdSubObject() - { - Name = "Sub Object 1", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, - Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, - Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, - Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, - DefaultValue = "0" - }; - - newObj.SubObjects.Add(new KeyValuePair("0x0", CountSub)); - newObj.SubObjects.Add(new KeyValuePair("0x1", Sub1)); - } - Data.Add(new KeyValuePair(strIndex, newObj)); - } - - public void RemoveIndex(object sender) - { - - } -} diff --git a/EDSEditorGUI2/ViewModels/ObjectDictionary.cs b/EDSEditorGUI2/ViewModels/ObjectDictionary.cs new file mode 100644 index 00000000..560af730 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/ObjectDictionary.cs @@ -0,0 +1,334 @@ +using System; +using System.Collections; +using System.Collections.Generic; +using System.Collections.ObjectModel; +using System.Collections.Specialized; +using System.ComponentModel; +using System.Linq; +using System.Runtime.CompilerServices; + + +//based on https://raw.githubusercontent.com/Cysharp/ObservableCollections/refs/heads/master/src/ObservableCollections/ObservableDictionary.cs + +namespace EDSEditorGUI2.ViewModels; +public class ObjectDictionary : IDictionary, INotifyCollectionChanged, INotifyPropertyChanged +{ + #region ObservableDictionary + private IDictionary _Dictionary; + protected IDictionary Dictionary + { + get + { + return _Dictionary; + } + } + + public ObjectDictionary() + { + _Dictionary = new Dictionary(); + } + + public void Add(string key, OdObject value) + { + Insert(key, value, true); + } + + public bool ContainsKey(string key) + { + return Dictionary.ContainsKey(key); + } + + public ICollection Keys + { + get { return Dictionary.Keys; } + } + + public bool Remove(string key) + { + if (key == null) throw new ArgumentNullException(nameof(key)); + + var removed = Dictionary.Remove(key); + if (removed) + { OnCollectionChanged(); } + return removed; + } + + public bool TryGetValue(string key, out OdObject value) + { + return Dictionary.TryGetValue(key, out value); + } + + public ICollection Values + { + get { return Dictionary.Values; } + } + + public OdObject this[string key] + { + get + { + return Dictionary[key]; + } + set + { + Insert(key, value, false); + } + } + + public void Add(KeyValuePair item) + { + Insert(item.Key, item.Value, true); + } + + public void Clear() + { + if (Dictionary.Count > 0) + { + Dictionary.Clear(); + OnCollectionChanged(); + } + } + + public bool Contains(KeyValuePair item) + { + return Dictionary.Contains(item); + } + + public void CopyTo(KeyValuePair[] array, int arrayIndex) + { + Dictionary.CopyTo(array, arrayIndex); + } + + public int Count + { + get { return Dictionary.Count; } + } + + public bool IsReadOnly + { + get { return Dictionary.IsReadOnly; } + } + + public bool Remove(KeyValuePair item) + { + return Remove(item.Key); + } + + public IEnumerator> GetEnumerator() + { + return Dictionary.GetEnumerator(); + } + + IEnumerator IEnumerable.GetEnumerator() + { + return ((IEnumerable)Dictionary).GetEnumerator(); + } + + public event NotifyCollectionChangedEventHandler? CollectionChanged; + + public event PropertyChangedEventHandler? PropertyChanged; + + public void AddRange(IDictionary items) + { + ArgumentNullException.ThrowIfNull(items); + + if (items.Count > 0) + { + if (Dictionary.Count > 0) + { + if (items.Keys.Any((k) => Dictionary.ContainsKey(k))) + { + throw new ArgumentException("An item with the same key has already been added."); + } + else + { + foreach (var item in items) + { + Dictionary.Add(item); + } + } + } + else + { + _Dictionary = new Dictionary(items); + } + OnCollectionChanged(NotifyCollectionChangedAction.Add, items.ToArray()); + } + } + + private void Insert(string key, OdObject value, bool add) + { + ArgumentNullException.ThrowIfNull(key); + + if (Dictionary.TryGetValue(key, out var item)) + { + if (add) + { + throw new ArgumentException("An item with the same key has already been added."); + } + if (Equals(item, value)) + { + return; + } + Dictionary[key] = value; + + OnCollectionChanged(NotifyCollectionChangedAction.Replace, new KeyValuePair(key, value), new KeyValuePair(key, item)); + } + else + { + Dictionary[key] = value; + OnCollectionChanged(NotifyCollectionChangedAction.Add, new KeyValuePair(key, value)); + } + } + + private void OnPropertyChanged() + { + OnPropertyChanged(nameof(Count)); + OnPropertyChanged("Item[]"); + OnPropertyChanged(nameof(Keys)); + OnPropertyChanged(nameof(Values)); + } + + protected virtual void OnPropertyChanged(string propertyName) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private void OnCollectionChanged() + { + OnPropertyChanged(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(NotifyCollectionChangedAction.Reset)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair changedItem) + { + OnPropertyChanged(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, changedItem)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, KeyValuePair newItem, KeyValuePair oldItem) + { + OnPropertyChanged(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, newItem, oldItem)); + } + + private void OnCollectionChanged(NotifyCollectionChangedAction action, IList newItems) + { + OnPropertyChanged(); + CollectionChanged?.Invoke(this, new NotifyCollectionChangedEventArgs(action, newItems)); + } + #endregion ObservableDictionary + + KeyValuePair _selectedObject; + KeyValuePair _selectedSubObject; + ObservableCollection> _selectedSubObjects = []; + + public void AddIndex(int index, string name, LibCanOpen.OdObject.Types.ObjectType type) + { + var strIndex = index.ToString("X4"); + var newObj = new OdObject + { + Name = name, + ObjectType = type + }; + + // create OD entry + if (type == LibCanOpen.OdObject.Types.ObjectType.Var) + { + var newSub = new OdSubObject() + { + Name = name, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + }; + newObj.SubObjects.Add(new KeyValuePair("0x0", newSub)); + } + else + { + var CountSub = new OdSubObject() + { + Name = "Highest sub-index supported", + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0x01" + }; + var Sub1 = new OdSubObject() + { + Name = "Sub Object 1", + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, + Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, + Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, + DefaultValue = "0" + }; + + newObj.SubObjects.Add(new KeyValuePair("0x0", CountSub)); + newObj.SubObjects.Add(new KeyValuePair("0x1", Sub1)); + } + Add(new KeyValuePair(strIndex, newObj)); + } + + // This method is called by the Set accessor of each property. + // The CallerMemberName attribute that is applied to the optional propertyName + // parameter causes the property name of the caller to be substituted as an argument. + private void NotifyPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + public KeyValuePair SelectedObject + { + get + { + return _selectedObject; + } + + set + { + if (value.Key != _selectedObject.Key || value.Value != _selectedObject.Value) + { + this._selectedObject = value; + NotifyPropertyChanged(); + } + } + } + + public KeyValuePair SelectedSubObject + { + get + { + return _selectedSubObject; + } + + set + { + if (value.Key != _selectedSubObject.Key || value.Value != _selectedSubObject.Value) + { + _selectedSubObject = value; + NotifyPropertyChanged(); + } + } + } + + public ObservableCollection> SelectedSubObjects + { + get + { + return _selectedSubObjects; + } + + set + { + if (value != _selectedSubObjects) + { + _selectedSubObjects = value; + NotifyPropertyChanged(); + } + } + } +} diff --git a/EDSEditorGUI2/ViewModels/OdObject.cs b/EDSEditorGUI2/ViewModels/OdObject.cs index e27277bf..01c83e8a 100644 --- a/EDSEditorGUI2/ViewModels/OdObject.cs +++ b/EDSEditorGUI2/ViewModels/OdObject.cs @@ -52,7 +52,7 @@ public partial class OdObject : ObservableObject SubObjects.Add(new KeyValuePair("0", new OdSubObject { Name = "Highest sub-index supported", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -70,7 +70,7 @@ public partial class OdObject : ObservableObject newOd = new OdSubObject { Name = "item", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32 + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32 }; } else @@ -80,7 +80,7 @@ public partial class OdObject : ObservableObject //TODO: make a clone function with reflection to keep it up-to-date Name = selected.Value.Name, Alias = selected.Value.Alias, - Type = selected.Value.Type, + DataType = selected.Value.DataType, Sdo = selected.Value.Sdo, Pdo = selected.Value.Pdo, Srdo = selected.Value.Srdo, diff --git a/EDSEditorGUI2/ViewModels/OdSubObject.cs b/EDSEditorGUI2/ViewModels/OdSubObject.cs index 99d0b946..1256593c 100644 --- a/EDSEditorGUI2/ViewModels/OdSubObject.cs +++ b/EDSEditorGUI2/ViewModels/OdSubObject.cs @@ -12,7 +12,7 @@ public partial class OdSubObject : ObservableObject private string _alias = string.Empty; [ObservableProperty] - private DataType _type; + private DataType _dataType; [ObservableProperty] private AccessSDO _sdo; diff --git a/EDSEditorGUI2/Views/DeviceODView.axaml b/EDSEditorGUI2/Views/DeviceODView.axaml index 0b5453f1..e8a8ac54 100644 --- a/EDSEditorGUI2/Views/DeviceODView.axaml +++ b/EDSEditorGUI2/Views/DeviceODView.axaml @@ -8,7 +8,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="800" x:Class="EDSEditorGUI2.Views.DeviceODView" - x:DataType="vm:DeviceOD"> + x:DataType="vm:ObjectDictionary"> @@ -41,7 +41,7 @@ - + @@ -97,7 +97,7 @@ - + diff --git a/EDSEditorGUI2/Views/DeviceODView.axaml.cs b/EDSEditorGUI2/Views/DeviceODView.axaml.cs index 74cc6e93..491110cc 100644 --- a/EDSEditorGUI2/Views/DeviceODView.axaml.cs +++ b/EDSEditorGUI2/Views/DeviceODView.axaml.cs @@ -47,7 +47,7 @@ public DeviceODView() private void IndexGridSelectionChanged(object? sender, SelectionChangedEventArgs e) { - if (sender is DataGrid s && DataContext is ViewModels.DeviceOD dc) + if (sender is DataGrid s && DataContext is ViewModels.ObjectDictionary dc) { if (s.SelectedItem is KeyValuePair selected) { @@ -65,7 +65,7 @@ private void IndexGridSelectionChanged(object? sender, SelectionChangedEventArgs } private void subindexGridSelectionChanged(object? sender, SelectionChangedEventArgs e) { - if (sender is DataGrid s && DataContext is ViewModels.DeviceOD dc) + if (sender is DataGrid s && DataContext is ViewModels.ObjectDictionary dc) { if (s.SelectedItem is KeyValuePair selected) { @@ -83,7 +83,7 @@ private void subindexGridSelectionChanged(object? sender, SelectionChangedEventA } private void ContextMenuSubObjectAddClick(object? sender, RoutedEventArgs e) { - if (DataContext is ViewModels.DeviceOD dc) + if (DataContext is ViewModels.ObjectDictionary dc) { var selectedObj = dc.SelectedObject.Value; ObservableCollection> selection = []; @@ -98,7 +98,7 @@ private void ContextMenuSubObjectRemoveClick(object? sender, RoutedEventArgs e) { bool renumber = sender == contextMenu_subObject_removeSubItemToolStripMenuItem; - if (DataContext is ViewModels.DeviceOD dc) + if (DataContext is ViewModels.ObjectDictionary dc) { var selectedObject = dc.SelectedObject.Value; diff --git a/EDSEditorGUI2/Views/DevicePDOView.axaml b/EDSEditorGUI2/Views/DevicePDOView.axaml index 0fe71fc2..6a45cafe 100644 --- a/EDSEditorGUI2/Views/DevicePDOView.axaml +++ b/EDSEditorGUI2/Views/DevicePDOView.axaml @@ -7,7 +7,7 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="1000" d:DesignHeight="450" x:Class="EDSEditorGUI2.Views.DevicePDOView" - x:DataType="vm:DeviceOD"> + x:DataType="vm:ObjectDictionary"> diff --git a/EDSEditorGUI2/Views/ODIndexRangeView.axaml b/EDSEditorGUI2/Views/ODIndexRangeView.axaml index 08b0d548..fa1d4714 100644 --- a/EDSEditorGUI2/Views/ODIndexRangeView.axaml +++ b/EDSEditorGUI2/Views/ODIndexRangeView.axaml @@ -8,11 +8,11 @@ xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d" d:DesignWidth="800" d:DesignHeight="450" x:Class="EDSEditorGUI2.Views.ODIndexRangeView" - x:DataType="vm:DeviceOD"> + x:DataType="vm:ObjectDictionary"> - ("0", new OdSubObject { Name = "Highest sub-index supported", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned8, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Ro, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -20,7 +20,7 @@ public ViewModels_OdObjects() sut.SubObjects.Add(new KeyValuePair("1", new OdSubObject() { Name = "Sub Object 1", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -29,7 +29,7 @@ public ViewModels_OdObjects() sut.SubObjects.Add(new KeyValuePair("2", new OdSubObject() { Name = "Sub Object 2", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -45,7 +45,7 @@ public void AddSubEntry_VarType() sut.SubObjects.Add(new KeyValuePair("0", new OdSubObject { Name = "variableTest", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -74,7 +74,7 @@ public void RemoveSubEntry_VarType(bool renumber) sut.SubObjects.Add(new KeyValuePair("0x01", new OdSubObject { Name = "variableTest", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -92,7 +92,7 @@ public void RemoveSubEntry_RecordType() sut.SubObjects.Add(new KeyValuePair("0x00", new OdSubObject { Name = "variableTest0", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -101,7 +101,7 @@ public void RemoveSubEntry_RecordType() sut.SubObjects.Add(new KeyValuePair("0x01", new OdSubObject { Name = "variableTest1", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, @@ -110,7 +110,7 @@ public void RemoveSubEntry_RecordType() sut.SubObjects.Add(new KeyValuePair("0x02", new OdSubObject { Name = "variableTest2", - Type = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, + DataType = LibCanOpen.OdSubObject.Types.DataType.Unsigned32, Sdo = LibCanOpen.OdSubObject.Types.AccessSDO.Rw, Pdo = LibCanOpen.OdSubObject.Types.AccessPDO.No, Srdo = LibCanOpen.OdSubObject.Types.AccessSRDO.No, From 34e007c96caeeafc7badc35be376a2635c4df144 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 12 Aug 2025 07:41:37 +0000 Subject: [PATCH 188/226] Bump actions/checkout from 4 to 5 Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] --- .github/workflows/dotnet.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 15e6a5b9..293ee11b 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -17,7 +17,7 @@ jobs: # runs-on: ubuntu-latest # Error: setup-msbuild can only be run on Windows runners steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Setup .NET diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index e80a22dc..9c7628e3 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: contents: write steps: - name: Checkout - uses: actions/checkout@v4 + uses: actions/checkout@v5 with: fetch-depth: 0 - name: Setup .NET From ac80ef0dafb372605473186c2787f371457a7836 Mon Sep 17 00:00:00 2001 From: reza0310 Date: Mon, 20 Oct 2025 15:19:32 +0200 Subject: [PATCH 189/226] [README] Typos Patched some typos from the README --- README.md | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 40faf5e7..9b4a9863 100644 --- a/README.md +++ b/README.md @@ -41,7 +41,7 @@ Please consider this code experimental and beta quality. It is a work in progress and is rapidly changing. Every attempt has been made to comply with the revelant DSP306 and other -standards and esd files from multile sources have been tested for loading and +standards and EDS files from multiple sources have been tested for loading and saving as been (at times) validated for errors using EDS conformance tools. With many thanks to the following contributors for spotting my mistakes and @@ -59,12 +59,12 @@ Library * Save EDS/DCF classes back to EDS file * Export C and H files in CanOpenNode format CO_OD.c and CO_OD.h * EDS/DCF supports modules -* EDS/DCF supports compactPDO (read only) 1* -* EDS/DCF supports implict PDO (read only) 1* -* EDS/DCF supports CompactSubOb (read only) 1* +* EDS/DCF supports compactPDO (read only) *¹ +* EDS/DCF supports implict PDO (read only) *¹ +* EDS/DCF supports CompactSubOb (read only) *¹ * Supports loading/saving of all EDS/DCF module information -1* read only in this context means the EDS/DCF is fully expanded but the compact +*¹ Read only, in this context, means the EDS/DCF is fully expanded but the compact forms is not written back, only the expanded form will be saved. GUI @@ -80,15 +80,15 @@ GUI * Create profiles that can be added to any project (just save the device xml file to the profiles/ directory, only include the minimum number of objects that you want to auto insert) This will auto add to insert menu * Edit Device and File Info sections -* Set RX/TX PDO mappings easily from dropdown lists of avaiable objects +* Set RX/TX PDO mappings easily from dropdown lists of available objects * Add and remove new PDO entries (communication paramaters and mapping) in a single button push -* Save groups of EDS/XML files as a network objects with abality to set concrete node IDs -* View report of all configured PDO across the network +* Save groups of EDS/XML files as a network object with ability to set concrete node IDs +* View report of all configured PDOs across the network * View modules and module details present within EDS files * View/edit actual object values for device configuring/DCF files * Support for loading XDD files (CanOpen offical XML) * Support for saving XDD files (CanOpen offical XML) -* Some module info is displayed in GUI showing avaiable modules (eds) and +* Some module info is displayed in GUI showing available modules (eds) and configured modules (dcf) and what OD entries they reference. Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be. From c455e609c3c0fb0e064d666e3c4e85869365b167 Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Tue, 21 Oct 2025 15:53:37 +0200 Subject: [PATCH 190/226] [DOCS] README rephrasing Starting my redocumentation by correcting some typos I missed, rephrasing some hard-to-understand phrases and aligning lines of the README with how we want them to appear for easier reading (and as such editing) of the raw version. --- README.md | 72 +++++++++++++++++++++++++------------------------------ 1 file changed, 32 insertions(+), 40 deletions(-) diff --git a/README.md b/README.md index 9b4a9863..39345dbd 100644 --- a/README.md +++ b/README.md @@ -1,63 +1,54 @@ CANopenEditor ============= -CANopenEditor is a fork from https://github.com/robincornelius/libedssharp, author Robin Cornelius. -Its homepage is https://github.com/CANopenNode/CANopenEditor +CANopenEditor is a fork from [libedssharp, authored by Robin Cornelius](https://github.com/robincornelius/libedssharp). +CANopenEditor's homepage is https://github.com/CANopenNode/CANopenEditor. CANopen Object Dictionary Editor: - Imports: CANopen electronic data sheets in EDS or XDD format. - - Exports: CANopen electronic data sheets in EDS or XDD format, documentation, CANopenNode C source files. - - GUI editor for CANopen Object Dictionary, Device information, etc. + - Exports: CANopen electronic data sheets in EDS or XDD format, documentation, CANopenNode C source files and more. + - Interfaces: GUI editor for CANopen Object Dictionary, Device information, etc. CLI client for simple conversions. -CANopen is the internationally standardized (EN 50325-4) ([CiA301](http://can-cia.org/standardization/technical-documents)) higher-layer protocol for embedded control system built on top of CAN. For more information on CANopen see http://www.can-cia.org/ +CANopen is the internationally standardized (EN 50325-4) ([CiA301](http://can-cia.org/standardization/technical-documents)) higher-layer protocol for embedded control system built on top of CAN. For more information on CANopen see http://www.can-cia.org/ . -[CANopenNode](https://github.com/CANopenNode/CANopenNode) is free and open source CANopen Stack +[CANopenNode](https://github.com/CANopenNode/CANopenNode) is a free and open source CANopen Stack. EDSSharp -------- -A C# CanOpen EDS (Electronic Data Sheet) library and GUI editor +A C# CanOpen EDS (Electronic Data Sheet) library, CLI convertor and GUI editor. -This application is designed to load/save/edit and create EDS/DCF/XDC file for -CanOpen and also to generate the object dictionary for CanOpenNode -CO_OD.c and CO_OD.h) to aid development of CanOpenNode devices. +This application is designed to load/save/edit and create EDS/DCF/XDC file for CANopen and also to generate the object dictionary for CANopenNode (CO_OD.c and CO_OD.h) to aid development of CANopenNode devices. -EDS (Electronic Data Sheet) files are text files that define CanOpen Devices. -DCF (Device Configuration File) files are text files that define configured -CanOpenDevices XDD files are an XML version of EDS files +EDS (Electronic Data Sheet) files are text files that define CANopen devices. +DCF (Device Configuration File) files are text files that define configured CANopen devices. +XDD files are an XML version of EDS files. -EDS/DCF are fully defined in the DSP306 standard by the can open standards -body CiA. +EDS/DCF are fully defined in the DSP306 standard by the CANopen standards body: CiA. -The EDS editor on its own is useful without the CanOpenNode specific export and -as of the 0.6-XDD-alpha version the editor can also load/save XDD files. -The GUI also shows PDO mappings and can generate reports -of multiple devices that are loaded into the software. +The EDS editor on its own is useful without the CANopenNode specific export and, as of the 0.6-XDD-alpha version, the editor can also load/save XDD files. +The GUI also shows PDO mappings and can generate reports of multiple devices that are loaded into the software. -The core library can be used without the GUI to implement eds/xdd loading/saving -and parsing etc in other projects. +The core library can be used without the GUI to implement eds/xdd loading/saving and parsing etc in other projects. Please consider this code experimental and beta quality. It is a work in progress and is rapidly changing. -Every attempt has been made to comply with the revelant DSP306 and other -standards and EDS files from multiple sources have been tested for loading and -saving as been (at times) validated for errors using EDS conformance tools. +Every attempt has been made to comply with the relevant DSP306 and other standards and EDS files from multiple sources have been tested for loading/saving and as been (at times) validated for errors using EDS conformance tools. -With many thanks to the following contributors for spotting my mistakes and -improving the code - * s-fuchs - * martinwag - * trojanobelix - * many others... +With many thanks to the following contributors for spotting my mistakes and improving the code: + * s-fuchs + * martinwag + * trojanobelix + * many others... Library ------- -* Read EDS/DCF/XDC file and parse contents to approprate classes +* Read EDS/DCF/XDC file and parse contents to appropriate classes * Dump EDS/DCF classes via ToString() * Save EDS/DCF classes back to EDS file -* Export C and H files in CanOpenNode format CO_OD.c and CO_OD.h +* Export C and H files in CANopenNode format CO_OD.c and CO_OD.h * EDS/DCF supports modules * EDS/DCF supports compactPDO (read only) *¹ * EDS/DCF supports implict PDO (read only) *¹ @@ -67,6 +58,10 @@ Library *¹ Read only, in this context, means the EDS/DCF is fully expanded but the compact forms is not written back, only the expanded form will be saved. +CLI +--- +TODO + GUI --- * Open multiple devices @@ -77,27 +72,24 @@ GUI * Delete exisiting OD entries * Create new Devices * Add default profiles -* Create profiles that can be added to any project (just save the device xml file to the profiles/ - directory, only include the minimum number of objects that you want to auto insert) This will auto add to insert menu +* Create profiles that can be added to any project (just save the device xml file to the profiles/ directory, only include the minimum number of objects that you want to auto insert); This will auto add to insert menu * Edit Device and File Info sections * Set RX/TX PDO mappings easily from dropdown lists of available objects -* Add and remove new PDO entries (communication paramaters and mapping) in a single button push +* Add and remove new PDO entries (communication paramaters and mapping) with a single button's push * Save groups of EDS/XML files as a network object with ability to set concrete node IDs * View report of all configured PDOs across the network * View modules and module details present within EDS files * View/edit actual object values for device configuring/DCF files * Support for loading XDD files (CanOpen offical XML) * Support for saving XDD files (CanOpen offical XML) -* Some module info is displayed in GUI showing available modules (eds) and - configured modules (dcf) and what OD entries they reference. Full details such - as subobj extension and fixed subobj are not currently displayed and unless - there is demand probably will not ever be. +* Some module info is displayed in GUI showing available modules (eds) and configured modules (dcf) and what OD entries they reference. + Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be. TODO ---- * Ensure and validate all XDD is loading/save correctly (Looking good so far) -* Add extra Gui fields for accessing extra XDD paramaters not in EDS +* Add extra GUI fields for accessing extra XDD paramaters not in EDS (all common ones are done, a few special/edge cases remain) * Look at XDC files and see if we can save config changes and allow editing and network setup here in the app, partial support is implemented by supporting From 4bab8ac343ec6ac6d689843939b84ac55557f547 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Mon, 27 Oct 2025 12:33:02 +0100 Subject: [PATCH 191/226] Add Link to free EDSchecker Fortunately, Vector is once again offering its EDS Checker as a single download without requiring users to install the gigabyte-sized ToolChain. --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index 9b4a9863..bf2fce65 100644 --- a/README.md +++ b/README.md @@ -110,6 +110,8 @@ BUGS If you find any, please open a bug report on github and attach any files you have created/opened etc. +You might want to check your EDS/XDD file with this free [EDSchecker](https://www.vector.com/de/de/support-downloads/download-center/#product=%5B%2274771%22%5D&tab=1&pageSize=15&sort=date&order=desc) + Pictures -------- From c86a0923e65c60714fa2da53f9530717965efe1f Mon Sep 17 00:00:00 2001 From: reza0310 Date: Tue, 28 Oct 2025 08:40:00 +0100 Subject: [PATCH 192/226] [FEAT] EDSSharp: Suggested better error management (#193) * [README] Typos Patched some typos from the README * [FEAT] Suggested better error management PLEASE NOTE: All of this have been tested but only with CLI. I don't really know neither can test the GUI but I hope it doesn't rely on bad error management. * [FIX] We want to print the error --- EDSSharp/Program.cs | 20 +++++++++++++++++++- 1 file changed, 19 insertions(+), 1 deletion(-) diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index a8b783a8..d96a48d1 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -66,29 +66,47 @@ static void Main(string[] args) default: + Program.WriteError("Invalid INFILE extension."); + PrintHelpText(); return; } if(eds != null) { Export(outfile, outtype); + Console.WriteLine("Successful conversion"); + } + else + { + Program.WriteError("Invalid XDD INFILE."); + PrintHelpText(); } } else { + Program.WriteError("INFILE or OUTFILE missing."); PrintHelpText(); } } catch(Exception e) { Console.WriteLine(e.ToString()); + Console.WriteLine(""); + Program.WriteError("Invalid EDS INFILE."); PrintHelpText(); } } + private static void WriteError(string message) + { + Console.ForegroundColor = ConsoleColor.Red; + Console.Error.WriteLine(message); + Console.ResetColor(); + Console.WriteLine(""); + } + private static void openEDSfile(string infile) { - eds.Loadfile(infile); } From b805697c123c82f5af67c2e8d49fab5632590c55 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 28 Oct 2025 08:40:26 +0100 Subject: [PATCH 193/226] Bump actions/upload-artifact from 4 to 5 (#195) Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 4 to 5. - [Release notes](https://github.com/actions/upload-artifact/releases) - [Commits](https://github.com/actions/upload-artifact/compare/v4...v5) --- updated-dependencies: - dependency-name: actions/upload-artifact dependency-version: '5' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dotnet.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 293ee11b..666513e0 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -47,7 +47,7 @@ jobs: run: | dotnet test --no-build --verbosity normal GUITests\bin\${{ matrix.configuration }}\${{ matrix.dotnet }}*\GUITests.dll - name: Upload Artifact - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v5 with: name: EDSEditor_${{ matrix.dotnet }} path: | From 8f5b3eca4cf5be9f474984ac1026b00162a3a179 Mon Sep 17 00:00:00 2001 From: reza0310 Date: Sat, 1 Nov 2025 09:23:26 +0100 Subject: [PATCH 194/226] [STDOUT] Suggesting a more posix friendly help message (#192) --- EDSSharp/Program.cs | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index d96a48d1..555b8f26 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -10,7 +10,6 @@ namespace EDSSharp { class Program { - static libEDSsharp.EDSsharp eds = new EDSsharp(); static void Main(string[] args) @@ -193,11 +192,14 @@ static ExporterDescriptor FindMatchingExporter(string outpath, string outType) static void PrintHelpText() { string name = Path.GetFileNameWithoutExtension(Environment.GetCommandLineArgs()[0]); - Console.WriteLine($"Usage: {name} --infile file.[xdd|eds] --outfile [valid output file] [OPTIONAL] --type [exporter type]"); - Console.WriteLine("The output file format depends on --outfile extension and --type"); - Console.WriteLine("If --outfile extension matcher one exporter then --type IS NOT needed"); - Console.WriteLine("If --outfile extension matcher multiple exporter then --type IS needed"); - Console.WriteLine("If --outfile has no extension --type IS needed"); + Console.WriteLine($"Usage: {name} --infile FILE1 --outfile FILE2 [--type EXPORTER]"); + Console.WriteLine("Converts a given XDD or EDS file to many other available types."); + Console.WriteLine($"Example: {name} --infile project.xdd --outfile map.md --type NetworkPDOReport"); + Console.WriteLine(""); + Console.WriteLine("FILE1 shall be a .xdd or .eds file."); + Console.WriteLine("FILE2 shall have the extension of one of the supported exporters below."); + Console.WriteLine("EXPORTER shall be one of the listed exporters below IF AND ONLY IF multiple of them support your output file extension."); + Console.WriteLine(""); Console.WriteLine("Exporter types:"); var exporters = Filetypes.GetExporters(); From 6abb5a67f2529b9e4dc0be8791b09785f43d3a71 Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Tue, 4 Nov 2025 15:07:51 +0100 Subject: [PATCH 195/226] [DOCS] Contributing guidelines first draft --- CONTRIBUTING.md | 61 +++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 61 insertions(+) create mode 100644 CONTRIBUTING.md diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 00000000..46691304 --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,61 @@ +# CANopenEditor Contributing Guidelines + +Thank you for your interest in contributing to this project ! +Being a well referenced EDS/DCF editor and the only one supporting CANopenNode, CANopenEditor let everyone manage CANopen files, completely free of charge ! +CANopenEditor is maintained by a small team of volunteers from around the world. As such, those rules are meant for a better communication between everyone but, any help being very welcome, reviewers might approve PRs not respecting all of these rules as long as you tried. +Also, those rules do not apply to code owners (as they might have specific needs) and might change. +Please note that by contributing to this project, you agree to have read this file and to the [Developer's Certificate of Origin 1.1](https://developercertificate.org/) + +## Discussions +Discussions shall be done in respect to everyone and everyone's work. +Any major change shall be first discussed in an issue. Do not worry: maintainers are quite active and will answer. + +## Code convention +This project doesn't really follow any real code convention and doesn't have any linter for now BUT following [common C# code conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions) is very welcome and might be asked of you if some parts of your code is too hard to read. +If linting is ever needed, `dotnet format` will be our solution of choice. +Even tho there is no hard defined conventions, non-explicit names or lack of spacing might result in non-approval of a PR. + +## What might or might not be a PR +A simple refactor of code without any real change won't ever be approved. This project relies quite a bit on git blame and as such you are only allowed to refactor code you change. Moreover, trying to enforce a code convention with approval of the main maintainers first might be seen as disrespectful. + +## Testing +Any code change shall be tested. You can: +- Add unit tests in the right directories +- Describe any tests you did with the files you might have used +Code that you didn't even try to compile won't be accepted. + +## Code comments +Complex algorithms MUST be explained with code comments. +Hardcoded values (e.g. specific numbers in the middle of nowhere) MUST be justified with code comments. +Non explicit data structures (e.g. an array of set size with every index having a meaning) MUST be explained with code comments. +Commented lines of code MUST be preceded by a comment line starting with either `//// DEBUG code:` or `//// TODO:`. +Comments SHALL have a space between the comment string (e.g. `//`) and the text. +Functions and methods MIGHT have comments describing what they are doing, what are their inputs and/or outputs (if it's not explicit enough). +Loops and switches MIGHT have comments justifying why every case is taken into account (if it's not explicit enough). +Any more useful comment is welcome. + +## Names and descriptions +### PR names +They shall be composed of three sections: +1) Which project is affected (MIX if multiple) +2) What types of changes are made (e.g. FEAT, FIX, DOCUMENTATION/DOC, CORRECTION/CORR, SUGGESTION/SUGG, BUILD, ...) +3) An explicit but less than 100 chars long summary of the changes +Sections shall be clearly separated (e.g. with colons, parenthesis, ...). +Example of valid and explicit PR name: `[MIX][DOC] Explaining explicit PR title rules`. +If you have multiple unrelated changes (e.g. adding a feature and fixing another) to do, please do multiple PRs. + +### PR descriptions +They shall: +- Describe any change made +- Explain why such changes are made +- Explain any decision taken +- Link any related issue / any related other PR +- Describe any test made +- The sentence "I have read the contributing guidelines, I agree to following them and I agree to the Developer's Certificate of Origin 1.1" + +### Commits +Names shall be composed of: +2) What types of changes are made +3) An explicit but less than 100 chars long summary of the changes + +Descriptions are entirely up to you. From f86ca9d5025592e104a465145c20c1c0b0153337 Mon Sep 17 00:00:00 2001 From: reza0310 Date: Tue, 4 Nov 2025 15:23:34 +0100 Subject: [PATCH 196/226] [DOCS] Prettyfication of the contributing guidelines Using the online github editor to check in real time how it renders. --- CONTRIBUTING.md | 41 +++++++++++++++++++++-------------------- 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 46691304..2e470d1d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,38 +1,38 @@ # CANopenEditor Contributing Guidelines -Thank you for your interest in contributing to this project ! -Being a well referenced EDS/DCF editor and the only one supporting CANopenNode, CANopenEditor let everyone manage CANopen files, completely free of charge ! -CANopenEditor is maintained by a small team of volunteers from around the world. As such, those rules are meant for a better communication between everyone but, any help being very welcome, reviewers might approve PRs not respecting all of these rules as long as you tried. -Also, those rules do not apply to code owners (as they might have specific needs) and might change. -Please note that by contributing to this project, you agree to have read this file and to the [Developer's Certificate of Origin 1.1](https://developercertificate.org/) +Thank you for your interest in contributing to this project!
+Being a well referenced EDS/DCF editor and the only one supporting CANopenNode, CANopenEditor let everyone manage CANopen files, completely free of charge!
+CANopenEditor is maintained by a small team of volunteers from around the world. As such, those rules are meant for a better communication between everyone but, any help being very welcome, reviewers might approve PRs not respecting all of these rules as long as you tried. Project owners are above those rules as they might have specific needs.
+Please note that by contributing to this project, you agree to have read this file and to the [Developer's Certificate of Origin 1.1](https://developercertificate.org/). ## Discussions Discussions shall be done in respect to everyone and everyone's work. Any major change shall be first discussed in an issue. Do not worry: maintainers are quite active and will answer. ## Code convention -This project doesn't really follow any real code convention and doesn't have any linter for now BUT following [common C# code conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions) is very welcome and might be asked of you if some parts of your code is too hard to read. +This project doesn't really follow any real code convention and doesn't have any linter for now BUT following [common C# code conventions](https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/coding-style/coding-conventions) is very welcome and might be asked of you if some parts of your code are too hard to read. If linting is ever needed, `dotnet format` will be our solution of choice. -Even tho there is no hard defined conventions, non-explicit names or lack of spacing might result in non-approval of a PR. +Even tho there is no hard-defined conventions, non-explicit names or lack of spacing might result in non-approval of a PR. ## What might or might not be a PR -A simple refactor of code without any real change won't ever be approved. This project relies quite a bit on git blame and as such you are only allowed to refactor code you change. Moreover, trying to enforce a code convention with approval of the main maintainers first might be seen as disrespectful. +A simple refactor of code without any real change won't ever be approved. This project relies quite a bit on git blame and as such you are only allowed to refactor code you change. Moreover, trying to enforce a code convention without approval of the main maintainers first might be seen as disrespectful. ## Testing Any code change shall be tested. You can: - Add unit tests in the right directories - Describe any tests you did with the files you might have used + Code that you didn't even try to compile won't be accepted. ## Code comments -Complex algorithms MUST be explained with code comments. -Hardcoded values (e.g. specific numbers in the middle of nowhere) MUST be justified with code comments. -Non explicit data structures (e.g. an array of set size with every index having a meaning) MUST be explained with code comments. -Commented lines of code MUST be preceded by a comment line starting with either `//// DEBUG code:` or `//// TODO:`. -Comments SHALL have a space between the comment string (e.g. `//`) and the text. -Functions and methods MIGHT have comments describing what they are doing, what are their inputs and/or outputs (if it's not explicit enough). -Loops and switches MIGHT have comments justifying why every case is taken into account (if it's not explicit enough). -Any more useful comment is welcome. +- Complex algorithms MUST be explained with code comments. +- Hardcoded values (e.g. specific numbers in the middle of nowhere) MUST be justified with code comments. +- Non explicit data structures (e.g. an array of set size with every index having a meaning) MUST be explained with code comments. +- Commented lines of code MUST be preceded by a comment line starting with either `//// DEBUG code:` or `//// TODO:`. +- Comments SHALL have a space between the comment string (e.g. `//`) and the text content. +- Functions and methods MIGHT have comments describing what they are doing, what are their inputs and/or outputs (if it's not explicit enough). +- Loops and switches MIGHT have comments justifying why every case is taken into account (if it's not explicit enough). +- Any more useful comment is welcome. ## Names and descriptions ### PR names @@ -40,8 +40,9 @@ They shall be composed of three sections: 1) Which project is affected (MIX if multiple) 2) What types of changes are made (e.g. FEAT, FIX, DOCUMENTATION/DOC, CORRECTION/CORR, SUGGESTION/SUGG, BUILD, ...) 3) An explicit but less than 100 chars long summary of the changes -Sections shall be clearly separated (e.g. with colons, parenthesis, ...). -Example of valid and explicit PR name: `[MIX][DOC] Explaining explicit PR title rules`. + +Sections shall be clearly separated (e.g. with colons, parenthesis, ...).
+Examples of valid and explicit PR names: `[MIX][DOC] Explaining explicit PR title rules`, `gui2: fix: Fixed bug where 1 = 2`.
If you have multiple unrelated changes (e.g. adding a feature and fixing another) to do, please do multiple PRs. ### PR descriptions @@ -55,7 +56,7 @@ They shall: ### Commits Names shall be composed of: -2) What types of changes are made -3) An explicit but less than 100 chars long summary of the changes +1) What types of changes are made (e.g. PR names sections 2) +2) An explicit but less than 100 chars long summary of the changes Descriptions are entirely up to you. From d095b9d7e27a36e93c80e8668c38b33020631439 Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Tue, 4 Nov 2025 15:46:27 +0100 Subject: [PATCH 197/226] [DOCS] Cleaning the root a little --- pic1.jpg => Images/pic1.jpg | Bin pic2.jpg => Images/pic2.jpg | Bin pic3.jpg => Images/pic3.jpg | Bin pic4.jpg => Images/pic4.jpg | Bin README.md | 8 ++++---- 5 files changed, 4 insertions(+), 4 deletions(-) rename pic1.jpg => Images/pic1.jpg (100%) rename pic2.jpg => Images/pic2.jpg (100%) rename pic3.jpg => Images/pic3.jpg (100%) rename pic4.jpg => Images/pic4.jpg (100%) diff --git a/pic1.jpg b/Images/pic1.jpg similarity index 100% rename from pic1.jpg rename to Images/pic1.jpg diff --git a/pic2.jpg b/Images/pic2.jpg similarity index 100% rename from pic2.jpg rename to Images/pic2.jpg diff --git a/pic3.jpg b/Images/pic3.jpg similarity index 100% rename from pic3.jpg rename to Images/pic3.jpg diff --git a/pic4.jpg b/Images/pic4.jpg similarity index 100% rename from pic4.jpg rename to Images/pic4.jpg diff --git a/README.md b/README.md index 39345dbd..ef2fc62a 100644 --- a/README.md +++ b/README.md @@ -105,7 +105,7 @@ have created/opened etc. Pictures -------- -![alt tag](pic1.jpg) -![alt tag](pic2.jpg) -![alt tag](pic3.jpg) -![alt tag](pic4.jpg) +![Device info section of the GUI](Images/pic2.jpg) +![OD section of the GUI](Images/pic1.jpg) +![TX PDO Mapping section of the GUI](Images/pic3.jpg) +![A specific PDO view in the GUI](Images/pic4.jpg) From 4848452c34a13a03af8c8132975e3793c16fdcaa Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Wed, 5 Nov 2025 15:40:32 +0100 Subject: [PATCH 198/226] [DOCS] README splitting and cleaning Also put in it trojanobelix's suggestion --- EDSEditorGUI/README.md | 22 +++++++++ EDSEditorGUI2/README.md | 3 ++ EDSSharp/README.md | 54 ++++++++++++++++++++ GUITests/README.md | 3 ++ Images/README.md | 9 ++++ README.md | 107 ++++++---------------------------------- Tests/README.md | 3 ++ libEDSsharp/README.md | 15 ++++++ 8 files changed, 124 insertions(+), 92 deletions(-) create mode 100644 EDSEditorGUI/README.md create mode 100644 EDSEditorGUI2/README.md create mode 100644 EDSSharp/README.md create mode 100644 GUITests/README.md create mode 100644 Images/README.md create mode 100644 Tests/README.md create mode 100644 libEDSsharp/README.md diff --git a/EDSEditorGUI/README.md b/EDSEditorGUI/README.md new file mode 100644 index 00000000..d88a0409 --- /dev/null +++ b/EDSEditorGUI/README.md @@ -0,0 +1,22 @@ +GUI +============= +* Open multiple devices +* Open EDS/DCF/XDC files +* Save EDS/DCF/XDC files +* View OD Entries and explore the Object Dictionary +* Add new OD entries +* Delete exisiting OD entries +* Create new Devices +* Add default profiles +* Create profiles that can be added to any project (just save the device xml file to the profiles/ directory, only include the minimum number of objects that you want to auto insert); This will auto add to insert menu +* Edit Device and File Info sections +* Set RX/TX PDO mappings easily from dropdown lists of available objects +* Add and remove new PDO entries (communication paramaters and mapping) with a single button's push +* Save groups of EDS/XML files as a network object with ability to set concrete node IDs +* View report of all configured PDOs across the network +* View modules and module details present within EDS files +* View/edit actual object values for device configuring/DCF files +* Support for loading XDD files (CanOpen offical XML) +* Support for saving XDD files (CanOpen offical XML) +* Some module info is displayed in GUI showing available modules (eds) and configured modules (dcf) and what OD entries they reference. + Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be. diff --git a/EDSEditorGUI2/README.md b/EDSEditorGUI2/README.md new file mode 100644 index 00000000..550a5fb7 --- /dev/null +++ b/EDSEditorGUI2/README.md @@ -0,0 +1,3 @@ +GUI2 +============= +This GUI is meant to be cross-platform, meant to replace the old GUI and is made using Avalonia. It is not yet ready. diff --git a/EDSSharp/README.md b/EDSSharp/README.md new file mode 100644 index 00000000..67449a85 --- /dev/null +++ b/EDSSharp/README.md @@ -0,0 +1,54 @@ +EDSSharp +============= + +A C# CanOpen EDS (Electronic Data Sheet) library, CLI convertor and GUI editor. + +This application is designed to load/save/edit and create EDS/DCF/XDC file for CANopen and also to generate the object dictionary for CANopenNode (V1.3 and newer) to aid development of CANopenNode devices. + +EDS (Electronic Data Sheet) files are text files that define CANopen devices. +DCF (Device Configuration File) files are text files that define configured CANopen devices. +XDD files are an XML version of EDS files. + +EDS/DCF are fully defined in the DSP306 standard by the CANopen standards body: CiA. + +The EDS editor on its own is useful without the CANopenNode specific export and, as of the 0.6-XDD-alpha version, the editor can also load/save XDD files. +The GUI also shows PDO mappings and can generate reports of multiple devices that are loaded into the software. + +The core library can be used without the GUI to implement eds/xdd loading/saving and parsing etc in other projects. + +Please consider this code experimental and beta quality. +It is a work in progress and is rapidly changing. + +Every attempt has been made to comply with the relevant DSP306 and other standards and EDS files from multiple sources have been tested for loading/saving and as been (at times) validated for errors using EDS conformance tools. + +Usage +----- +- Using `dotnet run`, your {name} is `dotnet run EDSSharp/Program.cs --project EDSSharp --framework [net481/net8.0]`. +- Using compiled version, your {name} is the name of your executable. +- Depending on your environment, you may or may not need to use ./ at the beginning of your command + +`{name} --infile FILE1 --outfile FILE2 [--type EXPORTER]`
+Converts a given XDD or EDS file to many other available types.
+Example: {name} --infile project.xdd --outfile map.md --type NetworkPDOReport
+
+FILE1 shall be a .xdd or .eds file.
+FILE2 shall have the extension of one of the supported exporters below.
+EXPORTER shall be one of the listed exporters below IF AND ONLY IF multiple of them support your output file extension.
+
+Available exporters for now:
+- ElectronicDataSheet [.eds] +- DeviceConfigurationFile [.dcf] +- CanOpenNode [.h,.c] +- CanOpenNodeV4 [.h,.c] +- CanOpenXDDv1.0 [.xdd] +- CanOpenNetworkv1.0 [.nxdd] +- CanOpenXDDv1.1 [.xdd] +- CanOpenXDDv1.1stripped [.xdd] +- CanOpenXDCv1.1 [.xdc] +- CanOpenNetworkXDDv1.1 [.nxdd] +- CanOpenNetworkXDCv1.1 [.nxdc] +- CanOpenNodeProtobuf(json) [.json] +- CanOpenNodeProtobuf(binary) [.binpb] +- DocumentationHTML [.html] +- DocumentationMarkup [.md] +- NetworkPDOReport [.md] diff --git a/GUITests/README.md b/GUITests/README.md new file mode 100644 index 00000000..79239caf --- /dev/null +++ b/GUITests/README.md @@ -0,0 +1,3 @@ +GUITests +============= +This directory only contains unit tests for the old GUI for now. More tests, functional tests or tests for the new GUI might be added later. All tests shall be written is C# and executable on Windows. diff --git a/Images/README.md b/Images/README.md new file mode 100644 index 00000000..14e2d3bb --- /dev/null +++ b/Images/README.md @@ -0,0 +1,9 @@ +Images +============= +Contains any and all images used in the documentation. Not all images in here are used but no image used in the documentation shall be anywhere but here. + +Here are some: +![Device info section of the GUI](Images/pic2.jpg) +![OD section of the GUI](Images/pic1.jpg) +![TX PDO Mapping section of the GUI](Images/pic3.jpg) +![A specific PDO view in the GUI](Images/pic4.jpg) diff --git a/README.md b/README.md index ef2fc62a..0a69e949 100644 --- a/README.md +++ b/README.md @@ -12,100 +12,23 @@ CANopen is the internationally standardized (EN 50325-4) ([CiA301](http://can-ci [CANopenNode](https://github.com/CANopenNode/CANopenNode) is a free and open source CANopen Stack. - -EDSSharp +File structure -------- - -A C# CanOpen EDS (Electronic Data Sheet) library, CLI convertor and GUI editor. - -This application is designed to load/save/edit and create EDS/DCF/XDC file for CANopen and also to generate the object dictionary for CANopenNode (CO_OD.c and CO_OD.h) to aid development of CANopenNode devices. - -EDS (Electronic Data Sheet) files are text files that define CANopen devices. -DCF (Device Configuration File) files are text files that define configured CANopen devices. -XDD files are an XML version of EDS files. - -EDS/DCF are fully defined in the DSP306 standard by the CANopen standards body: CiA. - -The EDS editor on its own is useful without the CANopenNode specific export and, as of the 0.6-XDD-alpha version, the editor can also load/save XDD files. -The GUI also shows PDO mappings and can generate reports of multiple devices that are loaded into the software. - -The core library can be used without the GUI to implement eds/xdd loading/saving and parsing etc in other projects. - -Please consider this code experimental and beta quality. -It is a work in progress and is rapidly changing. - -Every attempt has been made to comply with the relevant DSP306 and other standards and EDS files from multiple sources have been tested for loading/saving and as been (at times) validated for errors using EDS conformance tools. - -With many thanks to the following contributors for spotting my mistakes and improving the code: - * s-fuchs - * martinwag - * trojanobelix - * many others... - -Library -------- - -* Read EDS/DCF/XDC file and parse contents to appropriate classes -* Dump EDS/DCF classes via ToString() -* Save EDS/DCF classes back to EDS file -* Export C and H files in CANopenNode format CO_OD.c and CO_OD.h -* EDS/DCF supports modules -* EDS/DCF supports compactPDO (read only) *¹ -* EDS/DCF supports implict PDO (read only) *¹ -* EDS/DCF supports CompactSubOb (read only) *¹ -* Supports loading/saving of all EDS/DCF module information - -*¹ Read only, in this context, means the EDS/DCF is fully expanded but the compact - forms is not written back, only the expanded form will be saved. - -CLI ---- -TODO - -GUI ---- -* Open multiple devices -* Open EDS/DCF/XDC files -* Save EDS/DCF/XDC files -* View OD Entries and explore the Object Dictionary -* Add new OD entries -* Delete exisiting OD entries -* Create new Devices -* Add default profiles -* Create profiles that can be added to any project (just save the device xml file to the profiles/ directory, only include the minimum number of objects that you want to auto insert); This will auto add to insert menu -* Edit Device and File Info sections -* Set RX/TX PDO mappings easily from dropdown lists of available objects -* Add and remove new PDO entries (communication paramaters and mapping) with a single button's push -* Save groups of EDS/XML files as a network object with ability to set concrete node IDs -* View report of all configured PDOs across the network -* View modules and module details present within EDS files -* View/edit actual object values for device configuring/DCF files -* Support for loading XDD files (CanOpen offical XML) -* Support for saving XDD files (CanOpen offical XML) -* Some module info is displayed in GUI showing available modules (eds) and configured modules (dcf) and what OD entries they reference. - Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be. - -TODO ----- - -* Ensure and validate all XDD is loading/save correctly (Looking good so far) -* Add extra GUI fields for accessing extra XDD paramaters not in EDS - (all common ones are done, a few special/edge cases remain) -* Look at XDC files and see if we can save config changes and allow editing and - network setup here in the app, partial support is implemented by supporting - DCF files - +The main files and directories you'll need to understand are: +- [setup.nsi](https://github.com/CANopenNode/CANopenEditor/blob/main/setup.nsi) is the Windows installer. +- [Makefile](https://github.com/CANopenNode/CANopenEditor/blob/main/Makefile) is the Linux installation and manipulation script. +- [EDSEditorGUI](https://github.com/CANopenNode/CANopenEditor/tree/main/EDSEditorGUI) directory is the old GUI. Fully functional but only works on Windows. +- [EDSEditorGUI2](https://github.com/CANopenNode/CANopenEditor/tree/main/EDSEditorGUI2) directory is the new GUI. It is not fully finished yet but is meant to work on any Windows, Mac or Linux OS. +- [EDSSharp](https://github.com/CANopenNode/CANopenEditor/tree/main/EDSSharp) directory is the CLI. It is only meant for simple conversions for now. +- [GUITests](https://github.com/CANopenNode/CANopenEditor/tree/main/GUITests) directory is the directory for all GUI unit tests. More tests, functional tests and tests for GUI2 may come here. +- [Images](https://github.com/CANopenNode/CANopenEditor/tree/main/Images) directory is the directory containing any and all of the documentation's images. +- [Tests](https://github.com/CANopenNode/CANopenEditor/tree/main/Tests) directory is the directory for all Lib unit tests. More tests, functional tests and tests for CLI may come here. +- [libEDSsharp](https://github.com/CANopenNode/CANopenEditor/tree/main/libEDSsharp) directory contains the libe from Robin Cornelius making all of this work. BUGS ----- - -If you find any, please open a bug report on github and attach any files you -have created/opened etc. - -Pictures -------- +If you find any, please open a bug report on github and attach any files you have created/opened etc... We need any help we can have and the main maintainers are quite active and will answer you fast. -![Device info section of the GUI](Images/pic2.jpg) -![OD section of the GUI](Images/pic1.jpg) -![TX PDO Mapping section of the GUI](Images/pic3.jpg) -![A specific PDO view in the GUI](Images/pic4.jpg) +Contributing +-------- +If you want to help us out by contributing to this project, first of all thank you ! And please read our [Contributing Guidelines](https://github.com/CANopenNode/CANopenEditor/blob/docs/CONTRIBUTING.md). We are very beginner friendly so, even if you are not extremely experienced with contributing to open source projects, fear not and try ! diff --git a/Tests/README.md b/Tests/README.md new file mode 100644 index 00000000..75e12979 --- /dev/null +++ b/Tests/README.md @@ -0,0 +1,3 @@ +Tests +============= +This directory only contains unit tests for the lib for now. More tests, functional tests or tests for the CLI might be added later. All tests shall be written is C# and executable on Windows. diff --git a/libEDSsharp/README.md b/libEDSsharp/README.md new file mode 100644 index 00000000..86dd98e5 --- /dev/null +++ b/libEDSsharp/README.md @@ -0,0 +1,15 @@ +libEDSsharp +============= +The library making it all work. + +* Read EDS/DCF/XDC file and parse contents to appropriate classes +* Dump EDS/DCF classes via ToString() +* Save EDS/DCF classes back to EDS file +* Export C and H files in CANopenNode format (V1.3 and newer) +* EDS/DCF supports modules +* EDS/DCF supports compactPDO (read only) \*¹ +* EDS/DCF supports implict PDO (read only) \*¹ +* EDS/DCF supports CompactSubOb (read only) \*¹ +* Supports loading/saving of all EDS/DCF module information + +\*¹ Read only, in this context, means the EDS/DCF is fully expanded but the compact forms is not written back, only the expanded form will be saved. From 4e9f8b73dc14180185e68a630e2171df27884b38 Mon Sep 17 00:00:00 2001 From: reza0310 Date: Wed, 5 Nov 2025 15:50:07 +0100 Subject: [PATCH 199/226] [DOCS] Images PATH correction --- Images/README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Images/README.md b/Images/README.md index 14e2d3bb..2e1acb23 100644 --- a/Images/README.md +++ b/Images/README.md @@ -3,7 +3,7 @@ Images Contains any and all images used in the documentation. Not all images in here are used but no image used in the documentation shall be anywhere but here. Here are some: -![Device info section of the GUI](Images/pic2.jpg) -![OD section of the GUI](Images/pic1.jpg) -![TX PDO Mapping section of the GUI](Images/pic3.jpg) -![A specific PDO view in the GUI](Images/pic4.jpg) +![Device info section of the GUI](pic2.jpg) +![OD section of the GUI](pic1.jpg) +![TX PDO Mapping section of the GUI](pic3.jpg) +![A specific PDO view in the GUI](pic4.jpg) From c532ad5de1e72e0f6762e9ea98502c7c1112cf88 Mon Sep 17 00:00:00 2001 From: reza0310 Date: Wed, 5 Nov 2025 20:55:55 +0100 Subject: [PATCH 200/226] [CLI][FIX] Fixed a bug where parity of arguments mattered too much (#191) * [FIX] Fixed a bug where parity of arguments mattered too much * [OPTI] Mini optimization --- EDSSharp/Program.cs | 18 ++++++------------ 1 file changed, 6 insertions(+), 12 deletions(-) diff --git a/EDSSharp/Program.cs b/EDSSharp/Program.cs index 555b8f26..d44aaf98 100644 --- a/EDSSharp/Program.cs +++ b/EDSSharp/Program.cs @@ -19,26 +19,20 @@ static void Main(string[] args) Dictionary argskvp = new Dictionary(); - int argv = 0; - - for (argv = 0; argv < (args.Length - 1); argv++) + for (int argv = 0; argv < (args.Length - 1); argv++) { if (args[argv] == "--infile") { - argskvp.Add("--infile", args[argv + 1]); + argskvp.Add("--infile", args[++argv]); } - - if (args[argv] == "--outfile") + else if (args[argv] == "--outfile") { - argskvp.Add("--outfile", args[argv + 1]); + argskvp.Add("--outfile", args[++argv]); } - - if (args[argv] == "--type") + else if (args[argv] == "--type") { - argskvp.Add("--type", args[argv + 1]); + argskvp.Add("--type", args[++argv]); } - - argv++; } From 1ae0cb718df91318ea09b9be61c6e728039e2b9a Mon Sep 17 00:00:00 2001 From: reza0310 Date: Mon, 10 Nov 2025 14:12:51 +0100 Subject: [PATCH 201/226] [DOCS] Corrections Applying nimrof's corrections Co-authored-by: Lars Elgtvedt Susaas --- GUITests/README.md | 2 +- README.md | 2 +- Tests/README.md | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/GUITests/README.md b/GUITests/README.md index 79239caf..5f3cdbcf 100644 --- a/GUITests/README.md +++ b/GUITests/README.md @@ -1,3 +1,3 @@ GUITests ============= -This directory only contains unit tests for the old GUI for now. More tests, functional tests or tests for the new GUI might be added later. All tests shall be written is C# and executable on Windows. +This directory contains unit tests for the avalonia GUI. All tests shall be written in C# and run on all supported OS diff --git a/README.md b/README.md index ea589550..701d6d46 100644 --- a/README.md +++ b/README.md @@ -23,7 +23,7 @@ The main files and directories you'll need to understand are: - [GUITests](https://github.com/CANopenNode/CANopenEditor/tree/main/GUITests) directory is the directory for all GUI unit tests. More tests, functional tests and tests for GUI2 may come here. - [Images](https://github.com/CANopenNode/CANopenEditor/tree/main/Images) directory is the directory containing any and all of the documentation's images. - [Tests](https://github.com/CANopenNode/CANopenEditor/tree/main/Tests) directory is the directory for all Lib unit tests. More tests, functional tests and tests for CLI may come here. -- [libEDSsharp](https://github.com/CANopenNode/CANopenEditor/tree/main/libEDSsharp) directory contains the libe from Robin Cornelius making all of this work. +- [libEDSsharp](https://github.com/CANopenNode/CANopenEditor/tree/main/libEDSsharp) directory contains the library from Robin Cornelius making all of this work. BUGS -------- diff --git a/Tests/README.md b/Tests/README.md index 75e12979..30327a90 100644 --- a/Tests/README.md +++ b/Tests/README.md @@ -1,3 +1,3 @@ Tests ============= -This directory only contains unit tests for the lib for now. More tests, functional tests or tests for the CLI might be added later. All tests shall be written is C# and executable on Windows. +This directory contains unit tests for the library and CLI. All tests shall be written in C# and run on all supported OS From d98cb8243dbfbac1e7b3c31c7622922b34506579 Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Mon, 10 Nov 2025 14:36:58 +0100 Subject: [PATCH 202/226] [DOCS] Explanation of the projects of the repository --- GUITests/README.md | 2 +- README.md | 8 +++++++- Tests/README.md | 2 +- 3 files changed, 9 insertions(+), 3 deletions(-) diff --git a/GUITests/README.md b/GUITests/README.md index 5f3cdbcf..0c72b618 100644 --- a/GUITests/README.md +++ b/GUITests/README.md @@ -1,3 +1,3 @@ GUITests ============= -This directory contains unit tests for the avalonia GUI. All tests shall be written in C# and run on all supported OS +This directory contains unit tests for the avalonia (new) GUI. All tests shall be written in C# and run on all supported OS. diff --git a/README.md b/README.md index 701d6d46..8fad532c 100644 --- a/README.md +++ b/README.md @@ -12,6 +12,13 @@ CANopen is the internationally standardized (EN 50325-4) ([CiA301](http://can-ci [CANopenNode](https://github.com/CANopenNode/CANopenNode) is a free and open source CANopen Stack. +Repository structure +-------- +This repository is home to three projects: +- [LibEDSsharp](https://github.com/reza0310/CANopenEditor/blob/docs/libEDSsharp/README.md), a C# library for EDS files manipulation which went upstream and is now maintained in this repository. +- [A CLI](https://github.com/reza0310/CANopenEditor/blob/docs/EDSSharp/README.md), used for simple conversions across all supported formats. +- [A GUI](https://github.com/reza0310/CANopenEditor/blob/docs/EDSEditorGUI/README.md) for full manipulation of your CANopen files [which is being rewritten to be more multi platform](https://github.com/reza0310/CANopenEditor/blob/docs/EDSEditorGUI2/README.md). + File structure -------- The main files and directories you'll need to understand are: @@ -27,7 +34,6 @@ The main files and directories you'll need to understand are: BUGS -------- - If you find any, please open a bug report on github and attach any files you have created/opened etc... We need any help we can have and the main maintainers are quite active and will answer you fast. You might want to check your EDS/XDD file with this free [EDSchecker](https://www.vector.com/de/de/support-downloads/download-center/#product=%5B%2274771%22%5D&tab=1&pageSize=15&sort=date&order=desc) diff --git a/Tests/README.md b/Tests/README.md index 30327a90..62ba29c0 100644 --- a/Tests/README.md +++ b/Tests/README.md @@ -1,3 +1,3 @@ Tests ============= -This directory contains unit tests for the library and CLI. All tests shall be written in C# and run on all supported OS +This directory contains unit tests for the library and CLI. All tests shall be written in C# and run on all supported OS. From 1e92795691ea1661a12651c606cbce3dce5815f9 Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Mon, 10 Nov 2025 14:45:24 +0100 Subject: [PATCH 203/226] [DOCS] Global list of available formats --- EDSEditorGUI/README.md | 2 ++ EDSEditorGUI2/README.md | 2 ++ EDSSharp/README.md | 18 +----------------- README.md | 27 ++++++++++++++++++++++++--- libEDSsharp/README.md | 2 ++ 5 files changed, 31 insertions(+), 20 deletions(-) diff --git a/EDSEditorGUI/README.md b/EDSEditorGUI/README.md index d88a0409..ed8d6ca3 100644 --- a/EDSEditorGUI/README.md +++ b/EDSEditorGUI/README.md @@ -20,3 +20,5 @@ GUI * Support for saving XDD files (CanOpen offical XML) * Some module info is displayed in GUI showing available modules (eds) and configured modules (dcf) and what OD entries they reference. Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be. +
+[Available formats' list can be found here](https://github.com/CANopenNode/CANopenEditor?tab=readme-ov-file#available-formats). diff --git a/EDSEditorGUI2/README.md b/EDSEditorGUI2/README.md index 550a5fb7..edb55896 100644 --- a/EDSEditorGUI2/README.md +++ b/EDSEditorGUI2/README.md @@ -1,3 +1,5 @@ GUI2 ============= This GUI is meant to be cross-platform, meant to replace the old GUI and is made using Avalonia. It is not yet ready. +
+[Available formats' list can be found here](https://github.com/CANopenNode/CANopenEditor?tab=readme-ov-file#available-formats). diff --git a/EDSSharp/README.md b/EDSSharp/README.md index 67449a85..a569bd26 100644 --- a/EDSSharp/README.md +++ b/EDSSharp/README.md @@ -35,20 +35,4 @@ FILE1 shall be a .xdd or .eds file.
FILE2 shall have the extension of one of the supported exporters below.
EXPORTER shall be one of the listed exporters below IF AND ONLY IF multiple of them support your output file extension.

-Available exporters for now:
-- ElectronicDataSheet [.eds] -- DeviceConfigurationFile [.dcf] -- CanOpenNode [.h,.c] -- CanOpenNodeV4 [.h,.c] -- CanOpenXDDv1.0 [.xdd] -- CanOpenNetworkv1.0 [.nxdd] -- CanOpenXDDv1.1 [.xdd] -- CanOpenXDDv1.1stripped [.xdd] -- CanOpenXDCv1.1 [.xdc] -- CanOpenNetworkXDDv1.1 [.nxdd] -- CanOpenNetworkXDCv1.1 [.nxdc] -- CanOpenNodeProtobuf(json) [.json] -- CanOpenNodeProtobuf(binary) [.binpb] -- DocumentationHTML [.html] -- DocumentationMarkup [.md] -- NetworkPDOReport [.md] +[Available exporters' list can be found here](https://github.com/CANopenNode/CANopenEditor?tab=readme-ov-file#available-formats). diff --git a/README.md b/README.md index 8fad532c..4cd12de6 100644 --- a/README.md +++ b/README.md @@ -15,9 +15,30 @@ CANopen is the internationally standardized (EN 50325-4) ([CiA301](http://can-ci Repository structure -------- This repository is home to three projects: -- [LibEDSsharp](https://github.com/reza0310/CANopenEditor/blob/docs/libEDSsharp/README.md), a C# library for EDS files manipulation which went upstream and is now maintained in this repository. -- [A CLI](https://github.com/reza0310/CANopenEditor/blob/docs/EDSSharp/README.md), used for simple conversions across all supported formats. -- [A GUI](https://github.com/reza0310/CANopenEditor/blob/docs/EDSEditorGUI/README.md) for full manipulation of your CANopen files [which is being rewritten to be more multi platform](https://github.com/reza0310/CANopenEditor/blob/docs/EDSEditorGUI2/README.md). +- [LibEDSsharp](https://github.com/CANopenNode/CANopenEditor/blob/docs/libEDSsharp/README.md), a C# library for EDS files manipulation which went upstream and is now maintained in this repository. +- [A CLI](https://github.com/CANopenNode/CANopenEditor/blob/docs/EDSSharp/README.md), used for simple conversions across all supported formats. +- [A GUI](https://github.com/CANopenNode/CANopenEditor/blob/docs/EDSEditorGUI/README.md) for full manipulation of your CANopen files [which is being rewritten to be more multi platform](https://github.com/CANopenNode/CANopenEditor/blob/docs/EDSEditorGUI2/README.md). + +Available formats +-------- +Exhaustive list of the library's supported formats:
+- ElectronicDataSheet [.eds] +- DeviceConfigurationFile [.dcf] +- CanOpenNode [.h,.c] +- CanOpenNodeV4 [.h,.c] +- CanOpenXDDv1.0 [.xdd] +- CanOpenNetworkv1.0 [.nxdd] +- CanOpenXDDv1.1 [.xdd] +- CanOpenXDDv1.1stripped [.xdd] +- CanOpenXDCv1.1 [.xdc] +- CanOpenNetworkXDDv1.1 [.nxdd] +- CanOpenNetworkXDCv1.1 [.nxdc] +- CanOpenNodeProtobuf(json) [.json] +- CanOpenNodeProtobuf(binary) [.binpb] +- DocumentationHTML [.html] +- DocumentationMarkup [.md] +- NetworkPDOReport [.md] + File structure -------- diff --git a/libEDSsharp/README.md b/libEDSsharp/README.md index 86dd98e5..e8057e25 100644 --- a/libEDSsharp/README.md +++ b/libEDSsharp/README.md @@ -13,3 +13,5 @@ The library making it all work. * Supports loading/saving of all EDS/DCF module information \*¹ Read only, in this context, means the EDS/DCF is fully expanded but the compact forms is not written back, only the expanded form will be saved. +
+[Available exporters' list can be found here](https://github.com/CANopenNode/CANopenEditor?tab=readme-ov-file#available-formats). From f1b8548bbe40ba18f5f7d5061374651e7846383b Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Mon, 10 Nov 2025 14:54:20 +0100 Subject: [PATCH 204/226] [DOCS][ACTION] YAML action for automatic contributor's list --- .github/workflows/main.yml | 20 ++++++++++++++++++++ README.md | 11 ++++++++++- 2 files changed, 30 insertions(+), 1 deletion(-) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 00000000..64e7f5a5 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,20 @@ +on: push + +jobs: + contrib-readme-job: + runs-on: ubuntu-latest + name: A job to automate contrib in readme + permissions: + contents: write + pull-requests: write + steps: + - name: Contribute List + uses: akhilmhdh/contributors-readme-action@v2.3.11 + with: + image_size: 50 + use_username: true + columns_per_row: 12 + commit_message: "[ROOT][DOCS] contrib-readme-action has updated readme" + pr_title_on_protected: "[ROOT][DOCS] contributors readme action update" + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} diff --git a/README.md b/README.md index 4cd12de6..c11776fc 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,6 @@ Exhaustive list of the library's supported formats:
- DocumentationMarkup [.md] - NetworkPDOReport [.md] - File structure -------- The main files and directories you'll need to understand are: @@ -62,3 +61,13 @@ You might want to check your EDS/XDD file with this free [EDSchecker](https://ww Contributing -------- If you want to help us out by contributing to this project, first of all thank you ! And please read our [Contributing Guidelines](https://github.com/CANopenNode/CANopenEditor/blob/docs/CONTRIBUTING.md). We are very beginner friendly so, even if you are not extremely experienced with contributing to open source projects, fear not and try ! + +Collaborators +-------- + + + +Contributors +-------- + + From 303af02eba33f81a371483dd1cfc36383ab65416 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 10 Nov 2025 15:48:41 +0000 Subject: [PATCH 205/226] [ROOT][DOCS] contrib-readme-action has updated readme --- README.md | 212 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) diff --git a/README.md b/README.md index c11776fc..815155a5 100644 --- a/README.md +++ b/README.md @@ -65,9 +65,221 @@ If you want to help us out by contributing to this project, first of all thank y Collaborators -------- + + + + + + +
+ + reza0310 +
+ reza0310 +
+
Contributors -------- + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
+ + robincornelius +
+ robincornelius +
+
+ + trojanobelix +
+ trojanobelix +
+
+ + nimrof +
+ nimrof +
+
+ + CANopenNode +
+ CANopenNode +
+
+ + martinwag +
+ martinwag +
+
+ + simon-fuchs-inmach +
+ simon-fuchs-inmach +
+
+ + heliochronix +
+ heliochronix +
+
+ + Bartimaeus- +
+ Bartimaeus- +
+
+ + cfr-mir +
+ cfr-mir +
+
+ + JuPrgn +
+ JuPrgn +
+
+ + gotocoffee1 +
+ gotocoffee1 +
+
+ + wilkinsw +
+ wilkinsw +
+
+ + pettaa123 +
+ pettaa123 +
+
+ + henrikbrixandersen +
+ henrikbrixandersen +
+
+ + ckhardin +
+ ckhardin +
+
+ + Regelink +
+ Regelink +
+
+ + DylanRobertBennett +
+ DylanRobertBennett +
+
+ + rgruening +
+ rgruening +
+
+ + Barzello +
+ Barzello +
+
+ + rcolatobe +
+ rcolatobe +
+
+ + kekiefer +
+ kekiefer +
+
+ + zhanglongqi +
+ zhanglongqi +
+
+ + DaMutz +
+ DaMutz +
+
+ + StormOli +
+ StormOli +
+
+ + possibly-not +
+ possibly-not +
+
+ + reza0310 +
+ reza0310 +
+
+ + KwonTae-young +
+ KwonTae-young +
+
From a02b3f2b69c905c7b7fbade5544ba7cd832865ab Mon Sep 17 00:00:00 2001 From: Oleksii Slabchenko Date: Thu, 13 Nov 2025 10:57:11 +0100 Subject: [PATCH 206/226] Add a small dialog for PDO mapping width adjustments --- EDSEditorGUI/ChangeMappingWidth.Designer.cs | 115 ++++++++++++++++ EDSEditorGUI/ChangeMappingWidth.cs | 57 ++++++++ EDSEditorGUI/ChangeMappingWidth.resx | 145 ++++++++++++++++++++ 3 files changed, 317 insertions(+) create mode 100644 EDSEditorGUI/ChangeMappingWidth.Designer.cs create mode 100644 EDSEditorGUI/ChangeMappingWidth.cs create mode 100644 EDSEditorGUI/ChangeMappingWidth.resx diff --git a/EDSEditorGUI/ChangeMappingWidth.Designer.cs b/EDSEditorGUI/ChangeMappingWidth.Designer.cs new file mode 100644 index 00000000..4f62f9d7 --- /dev/null +++ b/EDSEditorGUI/ChangeMappingWidth.Designer.cs @@ -0,0 +1,115 @@ +namespace ODEditor +{ + partial class ChangeMappingWidth + { + /// + /// Required designer variable. + /// + private System.ComponentModel.IContainer components = null; + + /// + /// Clean up any resources being used. + /// + /// true if managed resources should be disposed; otherwise, false. + protected override void Dispose(bool disposing) + { + if (disposing && (components != null)) + { + components.Dispose(); + } + base.Dispose(disposing); + } + + #region Windows Form Designer generated code + + /// + /// Required method for Designer support - do not modify + /// the contents of this method with the code editor. + /// + private void InitializeComponent() + { + System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ChangeMappingWidth)); + this.label_enterwidth = new System.Windows.Forms.Label(); + this.updown_newwidth = new System.Windows.Forms.NumericUpDown(); + this.button_ok = new System.Windows.Forms.Button(); + this.button_cancel = new System.Windows.Forms.Button(); + ((System.ComponentModel.ISupportInitialize)(this.updown_newwidth)).BeginInit(); + this.SuspendLayout(); + // + // label_enterwidth + // + this.label_enterwidth.AutoSize = true; + this.label_enterwidth.Location = new System.Drawing.Point(33, 24); + this.label_enterwidth.Name = "label_enterwidth"; + this.label_enterwidth.Size = new System.Drawing.Size(126, 13); + this.label_enterwidth.TabIndex = 0; + this.label_enterwidth.Text = "Enter the new width (bits)"; + // + // updown_newwidth + // + this.updown_newwidth.Location = new System.Drawing.Point(165, 22); + this.updown_newwidth.Maximum = new decimal(new int[] { + 64, + 0, + 0, + 0}); + this.updown_newwidth.Minimum = new decimal(new int[] { + 1, + 0, + 0, + 0}); + this.updown_newwidth.Name = "updown_newwidth"; + this.updown_newwidth.Size = new System.Drawing.Size(61, 20); + this.updown_newwidth.TabIndex = 1; + this.updown_newwidth.Value = new decimal(new int[] { + 1, + 0, + 0, + 0}); + // + // button_ok + // + this.button_ok.Location = new System.Drawing.Point(12, 57); + this.button_ok.Name = "button_ok"; + this.button_ok.Size = new System.Drawing.Size(130, 37); + this.button_ok.TabIndex = 2; + this.button_ok.Text = "OK"; + this.button_ok.UseVisualStyleBackColor = true; + this.button_ok.Click += new System.EventHandler(this.button_ok_Click); + // + // button_cancel + // + this.button_cancel.Location = new System.Drawing.Point(183, 57); + this.button_cancel.Name = "button_cancel"; + this.button_cancel.Size = new System.Drawing.Size(130, 37); + this.button_cancel.TabIndex = 3; + this.button_cancel.Text = "Cancel"; + this.button_cancel.UseVisualStyleBackColor = true; + this.button_cancel.Click += new System.EventHandler(this.button_cancel_Click); + // + // ChangeMappingWidth + // + this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 13F); + this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; + this.ClientSize = new System.Drawing.Size(325, 111); + this.Controls.Add(this.button_cancel); + this.Controls.Add(this.button_ok); + this.Controls.Add(this.updown_newwidth); + this.Controls.Add(this.label_enterwidth); + this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.Name = "ChangeMappingWidth"; + this.Text = "Change mapping width"; + ((System.ComponentModel.ISupportInitialize)(this.updown_newwidth)).EndInit(); + this.ResumeLayout(false); + this.PerformLayout(); + + } + + #endregion + + private System.Windows.Forms.Label label_enterwidth; + private System.Windows.Forms.NumericUpDown updown_newwidth; + private System.Windows.Forms.Button button_ok; + private System.Windows.Forms.Button button_cancel; + } +} \ No newline at end of file diff --git a/EDSEditorGUI/ChangeMappingWidth.cs b/EDSEditorGUI/ChangeMappingWidth.cs new file mode 100644 index 00000000..98d5e993 --- /dev/null +++ b/EDSEditorGUI/ChangeMappingWidth.cs @@ -0,0 +1,57 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using System.Data; +using System.Drawing; +using System.Linq; +using System.Text; +using System.Threading.Tasks; +using System.Windows.Forms; + +namespace ODEditor +{ + /// + /// A small dialog for PDO mapping width adjustments + /// + public partial class ChangeMappingWidth : Form + { + public int selected_width = 1; + private int default_width = 1; + + public ChangeMappingWidth(int current_width, int max_width) + { + InitializeComponent(); + // Validate params + if (current_width < 1) + current_width = 1; + if (max_width < 1) + max_width = 1; + if (current_width > max_width) + current_width = max_width; + updown_newwidth.Maximum = max_width; + updown_newwidth.Value = current_width; + selected_width = current_width; + default_width = current_width; + } + + private void button_ok_Click(object sender, EventArgs e) + { + selected_width = (int)updown_newwidth.Value; + if (selected_width != default_width) + { + this.DialogResult = DialogResult.OK; + } + else + { + this.DialogResult = DialogResult.Cancel; + } + this.Close(); + } + + private void button_cancel_Click(object sender, EventArgs e) + { + this.DialogResult = DialogResult.Cancel; + this.Close(); + } + } +} diff --git a/EDSEditorGUI/ChangeMappingWidth.resx b/EDSEditorGUI/ChangeMappingWidth.resx new file mode 100644 index 00000000..a903c780 --- /dev/null +++ b/EDSEditorGUI/ChangeMappingWidth.resx @@ -0,0 +1,145 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + + + AAABAAEAEBAAAAAAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAA + AAD///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH///8B////Afb29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/9vb2/////wH29vb/QkJC/0JCQv9CQkL/9vb2//b29v9CQkL/QkJC/0JCQv/29vb/9vb2/0JC + Qv9CQkL/QkJC//b29v////8B9vb2/0JCQv/x7/D/QkJC//b29v/29vb/QkJC//Hv8P9CQkL/9vb2//b2 + 9v9CQkL/8e/w/0JCQv/29vb/////Afb29v9CQkL/QkJC/0JCQv/29vb/9vb2/0JCQv9CQkL/QkJC//b2 + 9v/29vb/QkJC/0JCQv9CQkL/9vb2/////wH29vb/9vb2/0JCQv/29vb/9vb2//b29v/29vb/QkJC//b2 + 9v/29vb/9vb2//b29v9CQkL/9vb2//b29v////8B////Afb29v9CQkL/9vb2//b29v/29vb/9vb2/0JC + Qv/29vb/9vb2//b29v/29vb/QkJC//b29v////8B////Af///wH29vb/QkJC/0JCQv9CQkL/QkJC/0JC + Qv9CQkL/QkJC/0JCQv9CQkL/QkJC/0JCQv/29vb/////Af///wH///8B9vb2//b29v/29vb/9vb2//b2 + 9v/29vb/QkJC//b29v/29vb/9vb2//b29v/29vb/9vb2/////wH///8B////Af///wH///8B////Af// + /wH///8B9vb2/0JCQv/29vb/////Af///wH///8B////Af///wH///8B////Af///wH///8B////Af// + /wH29vb/9vb2//b29v9CQkL/9vb2//b29v/29vb/////Af///wH///8B////Af///wH///8B////Af// + /wH///8B9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2/////wH///8B////Af///wH///8B////Af// + /wH///8B////Afb29v9CQkL/8e/w//Hv8P/x7/D/QkJC//b29v////8B////Af///wH///8B////Af// + /wH///8B////Af///wH29vb/QkJC//Hv8P/x7/D/8e/w/0JCQv/29vb/////Af///wH///8B////Af// + /wH///8B////Af///wH///8B9vb2/0JCQv9CQkL/QkJC/0JCQv9CQkL/9vb2/////wH///8B////Af// + /wH///8B////Af///wH///8B////Afb29v/29vb/9vb2//b29v/29vb/9vb2//b29v////8B////Af// + /wH///8BAAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA//8AAP//AAD//wAA + //8AAP//AAD//w== + + + \ No newline at end of file From 19081985290d96bfee953ae0707454d7e8cd19e7 Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Thu, 13 Nov 2025 13:55:34 +0100 Subject: [PATCH 207/226] [DOCS] Better explanation and sorting of exporters --- .github/workflows/main.yml | 2 -- README.md | 46 ++++++++++++++++++++++++-------------- 2 files changed, 29 insertions(+), 19 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 64e7f5a5..382ef33f 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -11,9 +11,7 @@ jobs: - name: Contribute List uses: akhilmhdh/contributors-readme-action@v2.3.11 with: - image_size: 50 use_username: true - columns_per_row: 12 commit_message: "[ROOT][DOCS] contrib-readme-action has updated readme" pr_title_on_protected: "[ROOT][DOCS] contributors readme action update" env: diff --git a/README.md b/README.md index 815155a5..e0824f3f 100644 --- a/README.md +++ b/README.md @@ -21,23 +21,35 @@ This repository is home to three projects: Available formats -------- -Exhaustive list of the library's supported formats:
-- ElectronicDataSheet [.eds] -- DeviceConfigurationFile [.dcf] -- CanOpenNode [.h,.c] -- CanOpenNodeV4 [.h,.c] -- CanOpenXDDv1.0 [.xdd] -- CanOpenNetworkv1.0 [.nxdd] -- CanOpenXDDv1.1 [.xdd] -- CanOpenXDDv1.1stripped [.xdd] -- CanOpenXDCv1.1 [.xdc] -- CanOpenNetworkXDDv1.1 [.nxdd] -- CanOpenNetworkXDCv1.1 [.nxdc] -- CanOpenNodeProtobuf(json) [.json] -- CanOpenNodeProtobuf(binary) [.binpb] -- DocumentationHTML [.html] -- DocumentationMarkup [.md] -- NetworkPDOReport [.md] +Exhaustive list of the library's supported formats sorted by category:
+ +### CAN in Automation official formats: +| Description | Exporter | Format | +|---------------------------------------|------------------------------------------------------------|--------| +| Electronic Data Sheet (CiA 306-1) | ElectronicDataSheet | .eds | +| Device Configuration File (CiA 306-1) | DeviceConfigurationFile | .dcf | +| XML Device Description (CiA 311) | CanOpenXDDv1.0
CanOpenXDDv1.1
CanOpenXDDv1.1stripped | .xdd | +| XML Device Configuration (CiA 311) | CanOpenXDCv1.1 | .xdc | + +### Extended formats: +| Description | Exporter | Format | +|----------------------------------|---------------------------------------------|--------| +| Network XML Device Description | CanOpenNetworkv1.0
CanOpenNetworkXDDv1.1 | .nxdd | +| Network XML Device Configuration | CanOpenNetworkXDCv1.1 | .nxdc | +| XML Profile Description | None | .xpd | + +### CANopenNode specific formats: +| Description | Exporter | Format | +|------------------------------------------|----------------------------------------------------------|-----------------| +| CanOpenNode Object Dictionary file pairs | CanOpenNode
CanOpenNodeV4 | .h,.c | +| PCanOpenNode Project file | CanOpenNodeProtobuf(json)
CanOpenNodeProtobuf(binary) | .json
.binpb | + +### Documentation formats: +| Exporter | Format | +|---------------------|--------| +| DocumentationHTML | .html | +| DocumentationMarkup | .md | +| NetworkPDOReport | .md | File structure -------- From 9fe43115cf8b6d253aa6168ab5ce1cd60e30ac03 Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Thu, 13 Nov 2025 12:56:30 +0000 Subject: [PATCH 208/226] [ROOT][DOCS] contrib-readme-action has updated readme --- README.md | 60 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index e0824f3f..73fa838c 100644 --- a/README.md +++ b/README.md @@ -82,7 +82,7 @@ Collaborators - reza0310 + reza0310
reza0310
@@ -100,84 +100,86 @@ Contributors - robincornelius + robincornelius
robincornelius
- trojanobelix + trojanobelix
trojanobelix
- nimrof + nimrof
nimrof
- CANopenNode + CANopenNode
CANopenNode
- martinwag + martinwag
martinwag
- simon-fuchs-inmach + simon-fuchs-inmach
simon-fuchs-inmach
+ + - heliochronix + heliochronix
heliochronix
- Bartimaeus- + Bartimaeus-
Bartimaeus-
- cfr-mir + cfr-mir
cfr-mir
- JuPrgn + JuPrgn
JuPrgn
- gotocoffee1 + gotocoffee1
gotocoffee1
- wilkinsw + wilkinsw
wilkinsw
@@ -186,84 +188,86 @@ Contributors - pettaa123 + pettaa123
pettaa123
- henrikbrixandersen + henrikbrixandersen
henrikbrixandersen
- ckhardin + ckhardin
ckhardin
- Regelink + Regelink
Regelink
- DylanRobertBennett + DylanRobertBennett
DylanRobertBennett
- rgruening + rgruening
rgruening
+ + - Barzello + Barzello
Barzello
- rcolatobe + rcolatobe
rcolatobe
- kekiefer + kekiefer
kekiefer
- zhanglongqi + zhanglongqi
zhanglongqi
- DaMutz + DaMutz
DaMutz
- StormOli + StormOli
StormOli
@@ -272,21 +276,21 @@ Contributors - possibly-not + possibly-not
possibly-not
- reza0310 + reza0310
reza0310
- KwonTae-young + KwonTae-young
KwonTae-young
From 792b2092cd191fdd50885b1ccd82eedd221a9eef Mon Sep 17 00:00:00 2001 From: Oleksii Slabchenko Date: Thu, 13 Nov 2025 16:49:47 +0100 Subject: [PATCH 209/226] Implement PDO bitwise mapping --- EDSEditorGUI/ChangeMappingWidth.Designer.cs | 4 + EDSEditorGUI/ChangeMappingWidth.cs | 12 ++ EDSEditorGUI/DevicePDOView2.Designer.cs | 20 ++- EDSEditorGUI/DevicePDOView2.cs | 133 ++++++++++++-------- Tests/PDOHelperTests.cs | 16 +-- libEDSsharp/PDOHelper.cs | 49 ++++++-- 6 files changed, 155 insertions(+), 79 deletions(-) diff --git a/EDSEditorGUI/ChangeMappingWidth.Designer.cs b/EDSEditorGUI/ChangeMappingWidth.Designer.cs index 4f62f9d7..101033b6 100644 --- a/EDSEditorGUI/ChangeMappingWidth.Designer.cs +++ b/EDSEditorGUI/ChangeMappingWidth.Designer.cs @@ -69,6 +69,7 @@ private void InitializeComponent() // // button_ok // + this.button_ok.DialogResult = System.Windows.Forms.DialogResult.OK; this.button_ok.Location = new System.Drawing.Point(12, 57); this.button_ok.Name = "button_ok"; this.button_ok.Size = new System.Drawing.Size(130, 37); @@ -79,6 +80,7 @@ private void InitializeComponent() // // button_cancel // + this.button_cancel.DialogResult = System.Windows.Forms.DialogResult.Cancel; this.button_cancel.Location = new System.Drawing.Point(183, 57); this.button_cancel.Name = "button_cancel"; this.button_cancel.Size = new System.Drawing.Size(130, 37); @@ -97,8 +99,10 @@ private void InitializeComponent() this.Controls.Add(this.updown_newwidth); this.Controls.Add(this.label_enterwidth); this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); + this.KeyPreview = true; this.Name = "ChangeMappingWidth"; this.Text = "Change mapping width"; + this.KeyDown += new System.Windows.Forms.KeyEventHandler(this.ChangeMappingWidth_KeyDown); ((System.ComponentModel.ISupportInitialize)(this.updown_newwidth)).EndInit(); this.ResumeLayout(false); this.PerformLayout(); diff --git a/EDSEditorGUI/ChangeMappingWidth.cs b/EDSEditorGUI/ChangeMappingWidth.cs index 98d5e993..f5256566 100644 --- a/EDSEditorGUI/ChangeMappingWidth.cs +++ b/EDSEditorGUI/ChangeMappingWidth.cs @@ -53,5 +53,17 @@ private void button_cancel_Click(object sender, EventArgs e) this.DialogResult = DialogResult.Cancel; this.Close(); } + + private void ChangeMappingWidth_KeyDown(object sender, KeyEventArgs e) + { + if (e.KeyCode == Keys.Enter) + { + this.button_ok_Click(null, null); + } + else if (e.KeyCode == Keys.Escape) + { + this.button_cancel_Click(null, null); + } + } } } diff --git a/EDSEditorGUI/DevicePDOView2.Designer.cs b/EDSEditorGUI/DevicePDOView2.Designer.cs index b94639a0..847b9aa7 100644 --- a/EDSEditorGUI/DevicePDOView2.Designer.cs +++ b/EDSEditorGUI/DevicePDOView2.Designer.cs @@ -58,6 +58,7 @@ private void InitializeComponent() this.contextMenuStrip_removeitem = new System.Windows.Forms.ContextMenuStrip(this.components); this.toolStripMenuItem_removeitem = new System.Windows.Forms.ToolStripMenuItem(); this.toolStripMenuItem_insert = new System.Windows.Forms.ToolStripMenuItem(); + this.toolStripMenuItem_changewidth = new System.Windows.Forms.ToolStripMenuItem(); this.grid1 = new SourceGrid.Grid(); this.button_down = new System.Windows.Forms.Button(); this.groupBox2 = new System.Windows.Forms.GroupBox(); @@ -313,25 +314,33 @@ private void InitializeComponent() this.contextMenuStrip_removeitem.ImageScalingSize = new System.Drawing.Size(20, 20); this.contextMenuStrip_removeitem.Items.AddRange(new System.Windows.Forms.ToolStripItem[] { this.toolStripMenuItem_removeitem, - this.toolStripMenuItem_insert}); + this.toolStripMenuItem_insert, + this.toolStripMenuItem_changewidth}); this.contextMenuStrip_removeitem.Name = "contextMenuStrip_removeitem"; - this.contextMenuStrip_removeitem.Size = new System.Drawing.Size(145, 48); + this.contextMenuStrip_removeitem.Size = new System.Drawing.Size(200, 70); this.contextMenuStrip_removeitem.Text = "Remove Item"; // // toolStripMenuItem_removeitem // this.toolStripMenuItem_removeitem.Name = "toolStripMenuItem_removeitem"; - this.toolStripMenuItem_removeitem.Size = new System.Drawing.Size(144, 22); + this.toolStripMenuItem_removeitem.Size = new System.Drawing.Size(199, 22); this.toolStripMenuItem_removeitem.Tag = "remove"; this.toolStripMenuItem_removeitem.Text = "Remove Item"; // // toolStripMenuItem_insert // this.toolStripMenuItem_insert.Name = "toolStripMenuItem_insert"; - this.toolStripMenuItem_insert.Size = new System.Drawing.Size(144, 22); + this.toolStripMenuItem_insert.Size = new System.Drawing.Size(199, 22); this.toolStripMenuItem_insert.Tag = "insert"; this.toolStripMenuItem_insert.Text = "Insert Item"; // + // toolStripMenuItem_changewidth + // + this.toolStripMenuItem_changewidth.Name = "toolStripMenuItem_changewidth"; + this.toolStripMenuItem_changewidth.Size = new System.Drawing.Size(199, 22); + this.toolStripMenuItem_changewidth.Tag = "changewidth"; + this.toolStripMenuItem_changewidth.Text = "Change mapping width"; + // // grid1 // this.grid1.AllowDrop = true; @@ -395,7 +404,7 @@ private void InitializeComponent() this.AutoSize = true; this.Controls.Add(this.groupBox3); this.Controls.Add(this.groupBox1); - this.Controls.Add(this.button_addPDO); + this.Controls.Add(this.button_addPDO); this.Controls.Add(this.button_savepdochanges); this.Controls.Add(this.button_deletePDO); this.Controls.Add(this.groupBox2); @@ -449,5 +458,6 @@ private void InitializeComponent() private System.Windows.Forms.Button button_down; private System.Windows.Forms.GroupBox groupBox2; private System.Windows.Forms.GroupBox groupBox3; + private System.Windows.Forms.ToolStripMenuItem toolStripMenuItem_changewidth; } } diff --git a/EDSEditorGUI/DevicePDOView2.cs b/EDSEditorGUI/DevicePDOView2.cs index 025c0b20..d3c21a4a 100644 --- a/EDSEditorGUI/DevicePDOView2.cs +++ b/EDSEditorGUI/DevicePDOView2.cs @@ -30,6 +30,9 @@ public partial class DevicePDOView2 : MyTabUserControl Point RightClickPoint = new Point(0, 0); + // Info columns: ID, COB, Index + const int INFO_COLS_COUNT = 3; + public DevicePDOView2() { InitializeComponent(); @@ -54,15 +57,15 @@ public DevicePDOView2() for (int x = 0; x < 64; x++) { - grid1[0, 3 + x] = new MyHeader(string.Format("{0}", x)); + grid1[0, INFO_COLS_COUNT + x] = new MyHeader(string.Format("{0}", x)); } for (int x = 0; x < 8; x++) { - grid1[1, 3 + x * 8] = new MyHeader(string.Format("Byte {0}", x)); - grid1[1, 3 + x * 8].ColumnSpan = 8; + grid1[1, INFO_COLS_COUNT + x * 8] = new MyHeader(string.Format("Byte {0}", x)); + grid1[1, INFO_COLS_COUNT + x * 8].ColumnSpan = 8; - grid1[1, 3 + x * 8].View.BackColor = Color.Tomato; + grid1[1, INFO_COLS_COUNT + x * 8].View.BackColor = Color.Tomato; } @@ -85,6 +88,7 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte int foundrow, foundcol; SourceGrid.Cells.ICellVirtual v = getItemAtGridPoint(RightClickPoint, out foundrow, out foundcol); SourceGrid.Cells.Cell c = (SourceGrid.Cells.Cell)v; + var width_limit = 64 + INFO_COLS_COUNT - foundcol; if (c == null) return; @@ -98,15 +102,29 @@ private void ContextMenuStrip_removeitem_ItemClicked(object sender, ToolStripIte switch (e.ClickedItem.Tag) { case "remove": - location.slot.Mapping.Remove(location.entry); + location.slot.Mapping.Remove(location.mappingentry); break; case "insert": - ODentry od = new ODentry(); - location.slot.Mapping.Insert(location.ordinal, eds.dummy_ods[0x002]); + PDOMappingEntry od = new PDOMappingEntry(); + od.entry = eds.dummy_ods[0x002]; + od.width = Math.Min(od.entry.Sizeofdatatype(), width_limit); + location.slot.Mapping.Insert(location.ordinal, od); break; + case "changewidth": + var mapping = location.slot.Mapping[location.ordinal]; + width_limit = Math.Min(mapping.entry.Sizeofdatatype(), width_limit); + if (mapping.width > width_limit) + mapping.width = width_limit; + var temp = new ChangeMappingWidth(mapping.width, width_limit); + if (temp.ShowDialog() == DialogResult.OK) + { + mapping.width = temp.selected_width; + location.slot.Mapping[location.ordinal] = mapping; + } + break; } helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); @@ -133,25 +151,39 @@ private void Vcc_ValueChangedEvent(object sender, EventArgs e) PDOlocator location = (PDOlocator)((SourceGrid.Cells.Cell)cell.Cell).Tag; PDOSlot slot = location.slot; - ODentry newentry = null; + var newmapping = new PDOMappingEntry(); - if (eds.tryGetODEntry(newindex, out newentry)) + if (eds.tryGetODEntry(newindex, out newmapping.entry)) { if (newsubindex != 0) - newentry = newentry.subobjects[newsubindex]; + { + newmapping.entry = newmapping.entry.subobjects[newsubindex]; + newmapping.width = newmapping.entry.Sizeofdatatype(); + } } else { return; } - if (location.entry == null) + int current_width = newmapping.entry.Sizeofdatatype(); + int width_limit = 64 + INFO_COLS_COUNT - cell.Position.Column; + width_limit = Math.Min(width_limit, newmapping.entry.Sizeofdatatype()); + current_width = Math.Min(width_limit, current_width); + newmapping.width = current_width; + var change_pdo_entry_width = new ChangeMappingWidth(current_width, width_limit); + if (change_pdo_entry_width.ShowDialog() == DialogResult.OK) { - slot.Mapping.Add(newentry); + newmapping.width = change_pdo_entry_width.selected_width; + } + + if (location.mappingentry.entry == null) + { + slot.Mapping.Add(newmapping); } else { - slot.Mapping[location.ordinal] = newentry; + slot.Mapping[location.ordinal] = newmapping; } helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); @@ -427,7 +459,6 @@ public void UpdatePDOinfo(bool updatechoices = true) #if !NETCOREAPP comboStandard.Control.DropDownWidth = 0x100; #endif - comboStandard.Changed += ComboStandard_Changed; //tableLayoutPanel1.SuspendLayout(); @@ -444,8 +475,8 @@ public void UpdatePDOinfo(bool updatechoices = true) { if (isTXPDO != slot.isTXPDO()) continue; - if (grid1.ColumnsCount > 64+3) - grid1.ColumnsCount = 64+3; + if (grid1.ColumnsCount > 64+INFO_COLS_COUNT) + grid1.ColumnsCount = 64+INFO_COLS_COUNT; grid1.Redim(grid1.RowsCount + 1, grid1.ColumnsCount); grid1.Rows[grid1.RowsCount - 1].Tag = slot; grid1.Rows[row + 2].Height = 30; @@ -460,33 +491,34 @@ public void UpdatePDOinfo(bool updatechoices = true) int bitoff = 0; int ordinal = 0; - foreach (ODentry entry in slot.Mapping) + foreach (PDOMappingEntry mappingentry in slot.Mapping) { - if ((bitoff + entry.Sizeofdatatype()) > 64) + if ((bitoff + mappingentry.width) > 64) { string toDisplay = string.Join(Environment.NewLine, slot.Mapping); MessageBox.Show(string.Format("Invalid TXPDO mapping parameters in 0x{0:X}!\r\nTrying to map more than the maximum lenght of a CAN message (8 bytes).\r\n\r\nMembers are:\r\n{1}", slot.ConfigurationIndex,toDisplay)); break; } - string target = slot.getTargetName(entry); - grid1[row + 2, bitoff + 3] = new SourceGrid.Cells.Cell(target, comboStandard); - grid1[row + 2, bitoff + 3].ColumnSpan = entry.Sizeofdatatype(); - grid1[row + 2, bitoff + 3].View = viewNormal; + string target = slot.getTargetName(mappingentry.entry); + grid1[row + 2, bitoff + INFO_COLS_COUNT] = new SourceGrid.Cells.Cell(target, comboStandard); + grid1[row + 2, bitoff + INFO_COLS_COUNT].ColumnSpan = mappingentry.width; + grid1[row + 2, bitoff + INFO_COLS_COUNT].View = viewNormal; + grid1[row + 2, bitoff + INFO_COLS_COUNT].ToolTipText = grid1[row + 2, bitoff + INFO_COLS_COUNT].DisplayText; - PDOlocator location = new PDOlocator(); - location.slot = slot; - location.ordinal = ordinal; - location.entry = entry; + PDOlocator location = new PDOlocator(); + location.slot = slot; + location.ordinal = ordinal; + location.mappingentry = mappingentry; - Console.WriteLine(string.Format("New location at Row {0} Col {1} Loc {2}", row, bitoff, location.ToString())); - grid1[row + 2, bitoff + 3].Tag = location; + Console.WriteLine(string.Format("New location at Row {0} Col {1} Loc {2}", row, bitoff, location.ToString())); + grid1[row + 2, bitoff + INFO_COLS_COUNT].Tag = location; - ValueChangedController vcc = new ValueChangedController(); - vcc.ValueChangedEvent += Vcc_ValueChangedEvent; + ValueChangedController vcc = new ValueChangedController(); + vcc.ValueChangedEvent += Vcc_ValueChangedEvent; - grid1[row + 2, bitoff + 3].AddController(vcc); - bitoff += entry.Sizeofdatatype(); + grid1[row + 2, bitoff + INFO_COLS_COUNT].AddController(vcc); + bitoff += mappingentry.width; ordinal++; @@ -496,23 +528,24 @@ public void UpdatePDOinfo(bool updatechoices = true) //Pad out with an empty combo if (bitoff < 64) { - grid1[row + 2, bitoff + 3] = new SourceGrid.Cells.Cell("Empty", comboStandard); - int colspan = 64 - bitoff; - if (colspan > 8) + grid1[row + 2, bitoff + INFO_COLS_COUNT] = new SourceGrid.Cells.Cell("Empty", comboStandard); + // Align "Empty" cell to byte end + int colspan = (64 - bitoff) % 8; + if ((colspan == 0) && ((64 - bitoff) > 8)) colspan = 8; - grid1[row + 2, bitoff + 3].ColumnSpan = colspan; - grid1[row + 2, bitoff + 3].View = viewEmpty; + grid1[row + 2, bitoff + INFO_COLS_COUNT].ColumnSpan = colspan; + grid1[row + 2, bitoff + INFO_COLS_COUNT].View = viewEmpty; ValueChangedController vcc = new ValueChangedController(); vcc.ValueChangedEvent += Vcc_ValueChangedEvent; - grid1[row + 2, bitoff + 3].AddController(vcc); + grid1[row + 2, bitoff + INFO_COLS_COUNT].AddController(vcc); PDOlocator location = new PDOlocator(); location.slot = slot; location.ordinal = ordinal; - location.entry = null; + location.mappingentry.entry = null; Console.WriteLine(string.Format("New location at Row {0} Col {1} Loc {2}", row, bitoff, location.ToString())); - grid1[row + 2, bitoff + 3].Tag = location; + grid1[row + 2, bitoff + INFO_COLS_COUNT].Tag = location; } @@ -523,12 +556,6 @@ public void UpdatePDOinfo(bool updatechoices = true) grid1.VScrollBar.Value = savVScrollValue; } - private void ComboStandard_Changed(object sender, EventArgs e) - { - - - } - public void redrawtable() { @@ -561,12 +588,12 @@ private class PDOlocator { public PDOSlot slot; public int ordinal; - public ODentry entry; + public PDOMappingEntry mappingentry; public override string ToString() { string msg; - msg = String.Format("Ordinal {0} , slot {1} entry {2}", ordinal, slot.ToString(), entry == null ? "NULL" : entry.ToString()); + msg = String.Format("Ordinal {0} , slot {1} entry {2}", ordinal, slot.ToString(), mappingentry.entry == null ? "NULL" : mappingentry.ToString()); return msg; } @@ -581,7 +608,7 @@ private void clickEvent_Click(object sender, EventArgs e) private void button_down_Click(object sender, EventArgs e) { - int newwidth = grid1.Columns[3].Width - 10; + int newwidth = grid1.Columns[INFO_COLS_COUNT].Width - 10; if (newwidth < 18) newwidth = 18; @@ -589,19 +616,19 @@ private void button_down_Click(object sender, EventArgs e) for (int x = 0; x < 64; x++) { - grid1.Columns[x + 3].Width = newwidth; + grid1.Columns[x + INFO_COLS_COUNT].Width = newwidth; } } private void button_up_Click(object sender, EventArgs e) { - int newwidth = grid1.Columns[3].Width + 10; + int newwidth = grid1.Columns[INFO_COLS_COUNT].Width + 10; Console.WriteLine("New Width " + newwidth.ToString()); for (int x = 0; x < 64; x++) { - grid1.Columns[x + 3].Width = newwidth; + grid1.Columns[x + INFO_COLS_COUNT].Width = newwidth; } } @@ -696,7 +723,7 @@ private void grid1_DragDrop(object sender, DragEventArgs e) foreach (ODentry entry in entries) { - location.slot.insertMapping(location.ordinal, entry); + location.slot.insertMapping(location.ordinal, new PDOMappingEntry(entry, entry.Sizeofdatatype())); } helper.buildmappingsfromlists((ExporterFactory.Exporter)Properties.Settings.Default.ExporterType == ExporterFactory.Exporter.CANOPENNODE_V4); diff --git a/Tests/PDOHelperTests.cs b/Tests/PDOHelperTests.cs index df940964..01e869ba 100644 --- a/Tests/PDOHelperTests.cs +++ b/Tests/PDOHelperTests.cs @@ -26,14 +26,14 @@ public void Test_TPDO() //fill it with some dummy entries - ODentry od; - tryGetODEntry(0x0002, out od); + var od = new PDOMappingEntry(); + tryGetODEntry(0x0002, out od.entry); slot.Mapping.Add(od); - tryGetODEntry(0x0003, out od); + tryGetODEntry(0x0003, out od.entry); slot.Mapping.Add(od); - tryGetODEntry(0x0004, out od); + tryGetODEntry(0x0004, out od.entry); slot.Mapping.Add(od); pdo.buildmappingsfromlists(true); @@ -103,14 +103,14 @@ public void Test_RPDO() //fill it with some dummy entries - ODentry od; - tryGetODEntry(0x0002, out od); + var od = new PDOMappingEntry(); + tryGetODEntry(0x0002, out od.entry); slot.Mapping.Add(od); - tryGetODEntry(0x0003, out od); + tryGetODEntry(0x0003, out od.entry); slot.Mapping.Add(od); - tryGetODEntry(0x0004, out od); + tryGetODEntry(0x0004, out od.entry); slot.Mapping.Add(od); pdo.buildmappingsfromlists(true); diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 332b0bf3..1b71d0db 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -6,6 +6,27 @@ namespace libEDSsharp { + + /// + /// Represents a single PDO mapping entry + /// Holds a reference to ODentry and a mapped width + /// + public struct PDOMappingEntry + { + public ODentry entry; + public int width; + + public PDOMappingEntry(ODentry entry = null, int width = 0) + { + if ((entry != null) && (width == 0)) + this.width = entry.Sizeofdatatype(); + else + this.width = width; + + this.entry = entry; + } + } + /// /// Represent a PDO slot (mapping + communication index) /// @@ -109,7 +130,7 @@ public bool invalid /// /// PDO mapping /// - public List Mapping = new List(); + public List Mapping = new List(); /// /// PDO inhibit time,multiple of 100us /// @@ -142,7 +163,7 @@ public PDOSlot() configloc = "PERSIST_COMM"; mappingloc = "PERSIST_COMM"; transmissiontype = 254; - Mapping = new List(); + Mapping = new List(); DescriptionComm = ""; DescriptionMap = ""; } @@ -194,15 +215,15 @@ public string getTargetName(ODentry od) /// /// The zero-based index at which item should be inserted /// OD entry to be mapped - public void insertMapping(int ordinal, ODentry entry) + public void insertMapping(int ordinal, PDOMappingEntry entry) { int size = 0; - foreach(ODentry e in Mapping) + foreach(PDOMappingEntry e in Mapping) { - size += e.Sizeofdatatype(); + size += e.width; } - if (size + entry.Sizeofdatatype() > 64) + if (size + entry.width > 64) return; Mapping.Insert(ordinal,entry); @@ -333,10 +354,10 @@ void build_PDOlist(UInt16 startIdx, List slots) //validate this against what is in the actual object mapped try { - ODentry maptarget; + var maptarget = new PDOMappingEntry(null, datasize); if (pdosub == 0) { - if (eds.tryGetODEntry(pdoindex, out maptarget) == false) + if (eds.tryGetODEntry(pdoindex, out maptarget.entry) == false) { Console.WriteLine("MAPPING FAILED"); //Critical PDO error @@ -344,15 +365,17 @@ void build_PDOlist(UInt16 startIdx, List slots) } } else - maptarget = eds.ods[pdoindex].Getsubobject(pdosub); + maptarget.entry = eds.ods[pdoindex].Getsubobject(pdosub); - if (maptarget.prop.CO_disabled == false && datasize == (maptarget.Sizeofdatatype())) + if ((maptarget.entry.prop.CO_disabled == false) && + (datasize <= maptarget.entry.Sizeofdatatype()) && + (datasize > 0)) { //mappingfail = false; } else { - Console.WriteLine(String.Format("MAPPING FAILED {0} != {1}", datasize, maptarget.Sizeofdatatype())); + Console.WriteLine(String.Format("MAPPING FAILED {0} != {1}", datasize, maptarget.entry.Sizeofdatatype())); } slot.Mapping.Add(maptarget); @@ -504,11 +527,11 @@ public void buildmappingsfromlists(bool isCANopenNode_V4) mapping.addsubobject(0x00, sub); byte mappingcount = 1; - foreach (ODentry mapslot in slot.Mapping) + foreach (PDOMappingEntry mapslot in slot.Mapping) { sub = new ODentry(String.Format("Application object {0:X}", mappingcount), (ushort)slot.MappingIndex, mappingcount); sub.datatype = DataType.UNSIGNED32; - sub.defaultvalue = string.Format("0x{0:X4}{1:X2}{2:X2}", mapslot.Index, mapslot.Subindex, mapslot.Sizeofdatatype()); + sub.defaultvalue = string.Format("0x{0:X4}{1:X2}{2:X2}", mapslot.entry.Index, mapslot.entry.Subindex, mapslot.width); sub.accesstype = EDSsharp.AccessType.rw; mapping.addsubobject(mappingcount, sub); From 108ca55d98a28765aba98b54c85e063cc9482c1b Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Thu, 13 Nov 2025 17:11:32 +0100 Subject: [PATCH 210/226] [DOCS] Usage --- EDSSharp/README.md | 14 -------------- README.md | 9 ++++++++- 2 files changed, 8 insertions(+), 15 deletions(-) diff --git a/EDSSharp/README.md b/EDSSharp/README.md index a569bd26..66e6dbfc 100644 --- a/EDSSharp/README.md +++ b/EDSSharp/README.md @@ -21,18 +21,4 @@ It is a work in progress and is rapidly changing. Every attempt has been made to comply with the relevant DSP306 and other standards and EDS files from multiple sources have been tested for loading/saving and as been (at times) validated for errors using EDS conformance tools. -Usage ------ -- Using `dotnet run`, your {name} is `dotnet run EDSSharp/Program.cs --project EDSSharp --framework [net481/net8.0]`. -- Using compiled version, your {name} is the name of your executable. -- Depending on your environment, you may or may not need to use ./ at the beginning of your command - -`{name} --infile FILE1 --outfile FILE2 [--type EXPORTER]`
-Converts a given XDD or EDS file to many other available types.
-Example: {name} --infile project.xdd --outfile map.md --type NetworkPDOReport
-
-FILE1 shall be a .xdd or .eds file.
-FILE2 shall have the extension of one of the supported exporters below.
-EXPORTER shall be one of the listed exporters below IF AND ONLY IF multiple of them support your output file extension.
-
[Available exporters' list can be found here](https://github.com/CANopenNode/CANopenEditor?tab=readme-ov-file#available-formats). diff --git a/README.md b/README.md index 73fa838c..e4209fa8 100644 --- a/README.md +++ b/README.md @@ -19,9 +19,16 @@ This repository is home to three projects: - [A CLI](https://github.com/CANopenNode/CANopenEditor/blob/docs/EDSSharp/README.md), used for simple conversions across all supported formats. - [A GUI](https://github.com/CANopenNode/CANopenEditor/blob/docs/EDSEditorGUI/README.md) for full manipulation of your CANopen files [which is being rewritten to be more multi platform](https://github.com/CANopenNode/CANopenEditor/blob/docs/EDSEditorGUI2/README.md). +How to use +-------- +1. [Download the latest release's binary zip file](https://github.com/CANopenNode/CANopenEditor/releases). DO NOT DOWNLOAD SOURCE CODE. +2. Unzip it. +3. Go to net8.0-windows directory. +4. Execute the .exe . + Available formats -------- -Exhaustive list of the library's supported formats sorted by category:
+Exhaustive list of the library's supported formats to date, sorted by category:
### CAN in Automation official formats: | Description | Exporter | Format | From 0750ecd1edd8028ab69181d4adb18c6412467c3e Mon Sep 17 00:00:00 2001 From: Geoffroy Du Prey Date: Fri, 14 Nov 2025 13:57:05 +0100 Subject: [PATCH 211/226] [DOCS] Added pictures --- EDSEditorGUI/README.md | 28 ++++++++++++++++++++++++++++ Images/Applying profile.png | Bin 0 -> 115906 bytes Images/Edit PDO.png | Bin 0 -> 335923 bytes Images/General infos.png | Bin 0 -> 223552 bytes Images/Modules.png | Bin 0 -> 70766 bytes Images/OD comm specific param.png | Bin 0 -> 293856 bytes Images/OD selected object.png | Bin 0 -> 321633 bytes Images/Profiles.png | Bin 0 -> 82165 bytes Images/README.md | 6 +++++- Images/RPDO.png | Bin 0 -> 214005 bytes Images/TPDO.png | Bin 0 -> 266893 bytes 11 files changed, 33 insertions(+), 1 deletion(-) create mode 100644 Images/Applying profile.png create mode 100644 Images/Edit PDO.png create mode 100644 Images/General infos.png create mode 100644 Images/Modules.png create mode 100644 Images/OD comm specific param.png create mode 100644 Images/OD selected object.png create mode 100644 Images/Profiles.png create mode 100644 Images/RPDO.png create mode 100644 Images/TPDO.png diff --git a/EDSEditorGUI/README.md b/EDSEditorGUI/README.md index ed8d6ca3..5911d8ab 100644 --- a/EDSEditorGUI/README.md +++ b/EDSEditorGUI/README.md @@ -22,3 +22,31 @@ GUI Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be.
[Available formats' list can be found here](https://github.com/CANopenNode/CANopenEditor?tab=readme-ov-file#available-formats). + +Pictures +------------- +For those pictures, the file shown is: https://www.hbm.com/fileadmin/mediapool/support/download/weighing/pad/PAD4000_P80_113_01_COS.EDS + +### General informations +![General informations tab](Images/General infos.png) + +### OD manipulation +![OD when you select an object](Images/OD selected object.png) +![OD's communication specific parameters](Images/OD comm specific param.png) + +### PDO manipulation +TPDO:
+![TPDO tab](Images/TPDO.png)
+RPDO:
+![RPDO tab](Images/RPDO.png)
+PDO editing:
+![PDO edition](Images/Edit PDO.png) + +### Modules +![Modules tab](Images/Modules.png) + +### Profiles +Available profiles:
+![Profiles option](Images/Profiles.png)
+Applying a profile:
+![Profiles application](Images/Applying profile.png) diff --git a/Images/Applying profile.png b/Images/Applying profile.png new file mode 100644 index 0000000000000000000000000000000000000000..d8d7d6b2ab4c13ba705c26fc7e15234f8c3c7b5c GIT binary patch literal 115906 zcmb@tRd8KB&@FfZW@d(%nHght%*+@wGc&UtbIi;XGaOUQ%*@P8$Lu-z?%bN1e;%f$ zY94l}q}}Q*skK`zt)&PBISB+fJIp(QAvnrK_pqDVq=4?v*r1k?85^Cm7tjtvMDK7iZJxIKoD^ZF6S);R<~!2 zo38O7DGGBzb-#$)3#~fo%`o+HmmO|S!5y64E^=yvN1?}n#o=rK1%J?iPm%&Uzq(ou z1$V;WUzJe?2lO)_*CnPw_#rI7Um9}I7XPo6rKLR^<*73dPa-)&u-73##}W%Z=1XI; z1d+l^%$tba<`=*K;>UOH#BmEdJ4#M=_Sv+vQC&iS_urwwo$tetUELd;9|6_*AbJc@ zD}XnA(6FtIYCPy{)B!maNC(h)5=Wze>e3gGG$*2xM5+bpY+3;T{I|@JXw0!}5*N-%Sh&@or`!#7$7s`A4&X8@C zUr=DzxsQ2?f#hEi&g+iki{Yaod00oF=H>?I#)up?-ZqybSbh=3!^J&0JuQ*XxFDqC zaVc+Tn5*djvNgi=oa=tgU?tQIxpfjy!0pn=9jliI zez=~maQC%ld!C`Za_)r0Zb)2qQ68|geUw*B=xcE~GYvYSzV}8zO(N7pnR!nB=z6>9 zYA9^+J?z=F)2Ow+J9TuqskQgD$fgRiNA&JpVH8Myf)Ujb@A7j;m9uXhT@n#?eykDv zu*)rTS5neR!ouS0;dmZPV4;OK_R60wq=>lGaX0**Z%lF&=dOsLtAB2?$W#A!>jf96^+;Ii(-f6p? zr?GjQY=z)c^}_Y+=P)}xkj4pe*De1QW8siz0bKDj3VfUy$@B5MJV*PM92lEze+9ii zeK0tbL0+$9`1$QIBJCh8Zn`Vi{NT#m{XyjOs?W$^ONO!@AoLKWkLq0v@sJm!o^18a|QmJb;?@x{~%=iQR}V@#cWN9-ESaxFQ`V zv0c+cWF;?1ejzB~bEgQ{?(p03p?txNJot1DN&O!$dOH_{#~#~loAK^b>s+pJe)~mO z4`&-8f}oD3IPFzGpQm{}QU?WfnqCLQFBp#V=WZ8oM(Uf_`qfWoWo9{-?5I%p<>gXq zcb9~_9^_pIYZ&i(&4l)~>oA_Wk(Y#*oxJ`ZyQ;mkM|vi6x9K0>_n`m)dz|gxF{GTa zo9n5Yj7nUCLn7XuF@d{{gxJ-VxPO~d*9}vOCb&JF6$f@0U8Yhw8#eDey z_pU}pddhS&JXiDD7br-YZ`lx&M;<@|mwt;m7mg`Te!b^-k+8L#>*x>fLmRhc`@c#F zKVOOm4e@FUcw@ZQfrGn&E|Yl0DmzGAPOmtA-6e>RUrXEC>UjTx`?E0*^5t$+!mr%)MN8U2;Q)Ic3Q;n~vk+#vE|_?vErdR=3zvd2G}_`?~2kHz(i5 z5%lN5L6zgMngP*TE^&6DwNw?SeIj1AC5Yr@Bl{IGDF=eAI^S)>E4Jh=FG%S1%I%w@-Mn7$zYOPcZI*>VNPE zoi|C3*o`g%zN}+WLhcAuJvok>J%yOHyBB|6d*%R!-SqAObR3AaUJ|~EIY*v$w!qm& zl@u0+_x}XB$B6G<;BXrD1Yh*6Hrow;{2*I^OP60v5m+I0fcR^JSb z*O(`L5ONm_JN(X0y!<-wvWx7T`2L&@njsO49eZsPNE~&77J<}(L0&PfX7_JCz;%R> z7al&_@!ghKY3TLqcIcn1fNmh4R}<3Qi_cvsx&!sl@|=dgmR98I5d;K;RuyJk-^aBX zA7q@Jxp}uyrCNm-4Iv#ZJ;6@ZT>#(BV`9sF#1}He%odDT!DtH3v*g81&)fM_ub4g* zl;$R=lhfEX+Zj*{h%3E~3ZBigtvt+*szCyE;d*p0ss@853onKJy#(5<>>nQ z+HK9@5YH~tZzXQ>uP};Sk*?giCn}vgDZPd+SpNVaw)tNoFfUb%~w(YIX4P3mhIL;}HgFuU>rpqKiFP zzx5UDk1D+)vUjhkKcBSiZV3>yZXaZ%j^zZQ0eQc;GU6iXT{Uv3r(EP90?(e`y>Y&} z02r_+64Mg1*r!zZU?^L_zB4z#vkB=g^O-8X$!=4?aOLbT+VqdUXBR>1^)_}kwuY9L z$EU-b945ohw&7iG535{byN?~l!wIStY8GtigM?l(Bq`3gycn?ko9_>ttU}jnLOw9< z&*y;*>Y|s;qddX(fPwHveedU;+sSmOM{*SWiB0#HEav-(mco`&bv-Yq+}|;~Z=3JW zYh^QVpnAf{UZ@8|_WT?g9!(96Bf?B>CsPFl1rZSukbEJf3v-$b7pI$qTPA=qD11ZR zMOD>OiOyMp$jUS1Txeq!vC9Y&fK5^|`-4O`-!3Xo-1%f`S}KPx4C>|4Eyq zfTTX3y(auki&j^Se@HlZ!YSK}63zHH1JRzJJU_+mAP;%rkb*{Es@6!|$p`=d22yj8 zAn8wXFrNThKk>F}%06#l7`4u?f?Z%{5&$s35`MImkEa}9A0C1;T7nAzOfiNZVJ&W5 z_fqx_5LfWk<*?#Vi7=Y7OHTOYNI(JnYhf-5^hL3vzjk8L7{mYoTaE!7&-;6cHg`hq z4n7^(7;B7B0G(sve0_A0Co!8%)*)#vNGVpyk@zAa^OOJ`RbFVo)+%wnR}NCxZ64I9 zVHK|h^rbnTr9X!H}H^Xo-{R~nK;h;+TBPpV^U3LF5Sjv0QW2aX`OPuTjJ|J-M> z4cR5SeIQuntv|o>(1P9o9A60xuwa2L21S|sB%D)vBHIwcMEI8YB7mvz&*y5x-RxSzdr|Ah23F>!_OfB$mdJ0Hb z@f5CecjZHx-ctDluEsS8hr-WvK43L7#V$EN?cM!Ukqvx|)m)StL5>mF?X(x&^de3T z&*tMzh%(1Af&o|QP9BCs>Cg{e|H*E7Zz{@#l3$BWm+~tl)r8ezoTEqR*AEWfWXgl7 z`1u(N7F>Enmb4L5`j8k{TA+BDuthm>FNa zKhS5UeR66(ZeGrK2pJD9fFjMQU*$97oj32D`Y7hw?`N^P)*VYLafUWT{gB39h8o2>Mk}hT3x;l zQKL$i6t^sppcU(aR_N>8efR%@d}*xFOZZ+lg1%8`&sGzu#Ng_BHi(#=QLR1h=xN`v zH#4NrLMOLY8()5V&oq(7(r9UC6`lIxCL0ka|Lc}PX&Y<>f7%IfZ=GR(d?z1~8i7Ap zNw0$>jnFd_b!E=(*@6=9m(67HbGnM0AOTOGqkWEQ&>8)(1VBpU!FnB zLqIR<4&N(}Be6dXb1O#809I<>59C78Rd;+InvU~LsNT3gK=;#q;uIv}p5CBDfl;JF z4_h{D)Us|NmJ3@pci=j!rY1uT5fj2$e9K420xN6T(ar4K;i=jv zXN*&PoTjR5VpYX(32F41QJ|8ffHPm8Rj?-mqHo)8wC|@@7C$TTMGWVEjTE8sLOevz zp<2*SLjAXI@7&*Mn0_POH#Dh-*Y5yLA(pd+FRxu3PM#-*hf?ig)kwa09{!cj=57;_ zN-n0tM)V=h7Dlb>N4xYk={LjUsPYnUD)<$Ot&`+%s5~mXFU4~^#Hi0V+io(DHOWAf zirdpg^)I3YRI}+tA6Zjyx*h~^G7r%1p~6raj+AHcA~usmG4U}4;o=gfKvOv@nV;NC z!v`X_(sm}IBm~Q83xuHv(^?i!4ZX*=qgnIE4IeljvzgkTB8$_!OhXpK4HHBMC2Zfj_xLH`8RZS}d0(h1|DK4`p~fMd)+6@24SFkG1x^l-V+> z4R*hPtq~!LL?=f_hJ{%x5%9lvM-erD@?EWi#&0(ib|V2s=%>3CJXnrNCzUy$7uj;+ z?XKTN8;QtVT#jvD z6UDvf4qyp`76v0x%5QzJ;aS+oUQdzWBETc;<2egB{eL*e=qrJ?zXs+O7G)I`^{eL_ z^vGZ-`^Inak}?#mbaZ2rlW~6yqUjP*#P6D#IPj+-K7Wc4@7>4Nr1+<{8#?fhR#kFx zGFP?!NqF_V<+$l>gT-u%4#R)0*nsWK6{uCUQD+jRREFPJD4o7RRtc@ym!(6ivFh;4^ZFuygIF=r>nhC%ELR997-+HgYkaIbBd!qil?pW z(r`qLLIOGOgJ{^OJ%`a+k};;HyvUR`vPG@Dv*(Qh9JE@uS$RIdRMjkDBUc4(6&I98`Xs zWHTbp{GxY%!uxO=ba9hI%GF-stzUe9DX6GFUj^J(VNV>#@$>BCAqyvTk%PBTVV@OR{#Cd7Pfeq^pD#;GfKul2jl?C<#g zW3r#_%YAlxd%G^s*MsD(nezSlp*hEF(Zks5x$kd*7pICFlBrzrPC6H0=kAdNqo&#Bi?6BPff>>y{Ntn`XX*)_%p1kS%*nrh-YB}6gePQRFJkX6 zteAaIg2ypQ=;rn7tD3P(?n8oiV76+m7e$x;*5PvrP=g|}$HuawEvnuk*wyq?v2Jj-mFQP&{F zS5eU-$dXuTDIKP+a|MU`6AeAV2-L;lwzVsl z$F6BHMG?*Fjnv!;qOu?>vpJnu&rMO{=aVcOlah2~5^G5>Z@>829%Z>Se3~T^C(K0+3L_K{u} z>c#sewPQ?Y(B5=lK4-GQ(MdyocvQ%_O&IFq|TOxEkvV5I_&$|#IN_mHTXrGzK*C=+JHoWWLZYT~c|hpwfuz-@<%3*OzGjnUNuuCq1>t%iy|5u@+99L7h1E zg)FaLNj2@mOWRshDx6NE&oPE%>d}6ih#cKzxvcmRhu`#)%`Ii`)y;?0Psv%w@@Hw9 z&-jTKvg5ivC;J>T9`1enmBNqj=Fpe^fAzE#V}7ESzCQ{zW?f0Al|dK&JDhT5z!{1Ntw`VOaF?NGH!R9NxD18E`66M# zZLZnVKTCNM%n~-)n0;>gRJf&ld?uEo*}@zj@YQ?yw9E=0 z34zwi;*`wq+mdX+g|6FGPre^Rw;6X^oK|*{$YFI}2eSFoM|1)HKgbg$cOu}_oQVfl zRxh8w%BQ{Efk4$7Op39;jIT!-lh@t{26H-9Yb165>=a#MNqiG9`f0G)XFma_$D~R+TT@e zatYsi^0sqrIn#LV%Mn?#d(b64@G;?X61iZEr^|SvDWbAQ3~C{i1ir*O2)t21{u@6i zP>>}VYT0HPWYG2?kzXdCM;-4K5}bh8(8R=pRCsTUIZwqQ6>LmDCPeKES<#>1e5W5F zLipPdw-l_{)}al&q%=|F1|iU%#oyvll&MS}hATJwz>2%~nH1ohi4e(PkmM6&x=dBMJ7DEG}6$$(2-8R`wAwxVm}&)7ZRx?%JU@ zd3by5{2b1TV<-v&fd&!of}oIAtU1h!|3w%D0osQxA^1c@aY6q}WH2f^Dk>^EI@tbS zfE7)Mc*2Hj!*=OKw4Lex_l|*7j|p51Xor3VLj&M&7C^!SPPX8P^Z&nR{o!jIAi%Y~ z0S(jtMHc`R@LT{~K_LI%vq|9NjF8aK*lIr=RiT6Jpw)`3#NH6D!EfXFtd?;f4`Xo{ zGSuVxB!uH}btfkcgA4q(4<)C*&*ZGEPKWUcES56)(fzpzo-*S~ct@`a4kgP@OfqBm z{Ru!9wX@0Lji+}Q%ng8y)+9pi_~yrLlkBRLOttVgx4h7TqH1Ed-i$6zadOyJ_=zDu z4lH-L>T}?O4W0FAtqA`Kt9FGz+i4WYwNZjRG7LDX1qnF9YpqyIad370}w_wO}=-TM+YIff&-J@Ka; z5t4XIE31wf@k?{+GAeGJq5+9F1+&_vv6y~dq~ry2wgp8xO>IpNV^E18zNP6@1V0uDY+T_@{HH@wmDPoK+FMmQTm*v9bZdta=|_}mRX7?(qMj8B1~ zSs48x`yOJDwZUQ(pok@OM12~BB^0VE!`duw2LQJgg#6u zrKP&qzf6m3x&M*rGkf3!6-{*nA_D6#9tQ}xy`pG%uH8}dw=v-QBoNL1keYF^r|>;C z;T93Tqzad?w$RBgG|j5Y_AajjbbeGHIjKff?^J#9B4NY=qR6 z^`&WO*_kDKcUj3;iFH&ICeEiY46$-ocgDSLm!Sqp-}lY4LB@mU_XVdMY+-Ug;-sUursA1g z-m}U!bb26~=Be(Nx^O-u~ z=4~oV0Sy#0`&O^v%rjqrAyXO!C$HAPmBRn>S|$TAE7WpCxNo%8=gt#Pfx3Hu$g@H4V$+ zrn~c(jREJbvn2+4=_LpJ-I*yXwVI9pl^A_Sq3(FoDjUXG zvR=rl3B$XsWyq4%Z?>(qbJWv$D1~qr<@r)?*yS~++*!L?^B^za?bQemW^lBC1b#6 zYs+%ro1(_&;sx{lx-xW{;q6)=f4TXhqA4Z**Nqy)k!4|5o5|`J!*9$~U$_5&W1K~v zsVvis`AANxjV^SG)bVbFpFIV?$l6=^ASW+yOJ*$xDHIR?Hy5C1bc(9bM*Lf<9=}4RdEI>o4dcL?{r1A zfA0tM+J8;n{W@eQKCUh3^AvV2F%lC$65e|Il>%y$Kc`huyY6X!uycG7+nGwh;-E*c zD`n>H#>itNtYkc^OKEz>_3luc1p{eK(9Jhec&ekJiFJPe%yT_>pE`VFeZesD=jPtId>eK?wbfJ_h{+ zNNcE0oxjE?68Tj* zBFOk`?P{k?WKy52;;8XGU%L!nc=i`9i%f0H>r~WmH6L4tHtky3KG_4y{|qu1sJCxf&$$?hb!pXCLHg)YeX?WJdQoL@(w1cy}c=q}&(!`>F@TP|Yb>{K4sUZS#f zyF4S4C?A&2B2QDHQm~7{Ij~((b49 z)#!Z;Oov*(90s}Q&PV%P#`}Q0uh!~*qwA#&UI?g*?M@P!6qTn_pp=xd9aw+Um7c;~ ziLGuWPjnKIQMR#oPsu!}CTJUb)_tfx7d&8_ZP_X16?DfutW@woS1L5{NLlW{)C%(a zC~@m*t17IGZ3Fq0)Cp=ocR$Y`#bGs71kNN}WTl0A(v`k@Pw;aNKv-5DI%d#xZg@B^ z;#_>5Zr;3L#+C^%v&w4eqM?Z?z8mMJZn3(*pU&z(r|<7a2=2{S#*x(Ia(dOp^ z?wo>f%I;RuSzYk@DhNF(U^%ygBbSg{Czcc&j*~ku_j{6^E)sZG=n(e3ketlub(jXb z4U&;>UM_wo{X$1u@^K&t>n$#}M2y6Qd{(x9fk-}IGmYMx%((KD0fbB>QC@%MMo1>m zvZ0-}a6|1~;(A$Js3^vvqyG9cM}PZdmlyHif_+f%`5ED-Xa#+xacMnV!!>n}6UMfqQ6nT|yjo32J6@>bB3;>cfRhV#q<8_Dp7P z>VDAG`j3bHz+m_$DkiG6fx?t?y+qw2gpBvSe6JQYl@zyjO;r^XbW{i1FKR@?%8E2- z7d~&FIJy}ZUsH!Oy>=@YmDt0Y&IFu)b}`WzZ@42edT+CW zDAQMC=v~Mgp*U^${xF$piC*4ghIP?jApmCUhls(SgDhZ z3Y^PjR0!#tZH26t3xm zJL*8Nb-W_dzs*jKJv~?MutC1vVTO-=tEtV-s;vEQZVbPXQE6Q)nkt*vr-8l~DaJ0gS?qg1Pb3$CsE1|u9XL|z^zdaXcVFqUSb9~-KrAG=I z%8=RxiiFe?-Zm!v_9$WYVF#atdAw4d&LE%>6I1_OrD@+?Uf3iI1aCT@?|mhY(=1kR zv{;5r>=h!8gXs8eYRmI}Yj=tWu{nCD37ElSWlahG^(T zowpJh27H`xSLJb%IZjtByj9G2ek&VPRn;ugd`&O^Lhil)A)C`oMH;K3*vlk77FF?%fxoZ!_!q}$mppTw4?j-GKKGwx6pMzzrFC4=uMo&p ztZx7TWWm@fks5?VJ7zVizBMpeo#sjjWYOch&TMW-p_Uc2E|#*1z1Y8)dBrHOrhZk` zcHG$M_?LB|7db~ztJu*`iZMzBYJn%FO4x&ppE=~!OGl8NV$oy69#@*yR^P|WEJd5m9W-nJ|!@4n79!_U2g z8WC{}I!qJtKdKprS5_R2-^vD7QNP5WmecDq{K#r_XVLHG@>?|UXHh=3?&?0eJC;Tb z%DN7mumfQb@^5&nmm|Y0!&gizXlfcQa9UQJo~$C^>PEFzvRRb~z0T}tq6r&`>SD=2 zqp_%D4$*QIAKq{~!;VJd!Xdd){4m)r^`hqJD3hJfQ_sCxhWpt{hl`UYk8!7rlU`MZ zxLAw^5f+=n0>UNN$FiXEtPcSg9VPYe) zvZx|h$uqdD4-6Mq&8kYg)p420LW~0`%i&|yH_xb!o6@I8R;0DM>pN&SN~OHdG>!(M z45E*^orj$5j?*gX@@5VogoDoqZ5%9XDj=#yCgH-RezRG8loEvwVGkp(7qXjr6`flsb!i9R1o`slRC^z-wNfgsaV0} zJPITisj2NyJYEBM^vv~32li`~7jJiO+^}L0uqLGls5X3L2HD29N|7rS7mojKCYza> z9^;?w@DrbTM&v_SH)B4f}#Sb*F~XBzmWv?DjAuCTMCT~K~GGZDwpUPk>82C zbVs*t&lq^i#q`b0MGQA6G054nXx+780++QMmlR}O`mHUJlthbuCF8Ji`@NRf`|!>9L-(F^#7S73>W zi;j?yr8McvE@fEBH{w~9w_)am6FVK7OZpfMvyn+>Qk5~NU=apZAs$+_fX@yx(@toihD^3GG3&i!t zsKJ(Hzj$}E+`fHjosLraq7g0*lSunJj~;^^7s}9@dU9eTBde=KuD4c;4ZbJTiM8=q zHEaH4k9R=2Ki>%?nEBPx?(&ajy6VZoZm8NK6~$~E&2`IxKc{$fLuGOK&Q_ka78)y+ zr8jcH=7@jWGyS7j-$03cBuYY-BsLL_sVc8CfmUKw$HCnJ0q;#Y&8iDo)%Xw^_hfdp zdu5H-x--dT_k^IY;5yBB)0ng^=I1kkjN~J?OKoQtHg0Y{f$5fS2=^ix>KtC{@~!-d>)#S6-9LD_!4i7e9sl&rWTtjgMs z>o>8rBWLn2cIIiq6sDn>$L5Q(;r;@ua~uj2)k+~Pi&!|%dvUw`iGQ2ohd81zNO-Q; zgMp&S#S!}_g-FCK>aSA&PV_e?lm- zFD6zS`R$-VJA;G&_U=W~h8d*ew<^oYq=C-%)K+q#`^Q*k>`B5Q&W?x)izQ9?mt^p% zbV`rt`|YKtOJ~!TpY~#x*XC+Dj^FCjQRX+kBf+78<65frqMm#uRyALcAM25^>1Nor zjy9?vP}7=2ollI6*U(L)5*~j>^2_~a+&^RPF=uML+b5CYrK{{&<(RlJ))efQk0&o` zD@oe#_kZW0Rj=E^-VL`~E}VZ+8`JdvtmT64iI}($LXGV;R+?!zEn)C-J^rfYM~-YV zrk%y?VyJg*SF-^cstp&c>hP*onUOc?uIlZr)>Azcm9{!qW*D-%FY<6A|4Rf4!`}RIN%Q zmSwrB>x+B0Y*qcNU$qhOW>0LHgw-R$;3?!@2WAj++cZ`0lawGZ&fAtun^z~q;x0F~ zp#v*6cy!fIVSwu^_h5M2m3Mg<=)i0CJua`T^E+!Z|O z8Ia?n0pZ09;-9t|lOn}cumJ;2(({{%!}-rJ!XsUyylT30{$nxs^BI2Ywk(ZXKfDFB zcdl4%Cf9UyH<#A2o4%?1dXnXpV7{#8EneMtrPDW?dYDi_6%^nXrdYl?FoT+uvni!o zx;}O~MW8+C4~C%jEV+aVA&1s^KG0WZ%pw@IK4w!g*+Cx3?rrU-jB*i4!{a1>72%PT zscJia)$n~ycxvXq|C<&6jMzBM7kuzWj8`&vA{Fv#s;#`hsGTlz@J@JtzLF5Ip!)=2 z8nZA@UDnz13VORm+fCaEU~odzFjdv|vbd-PgsrYy1fCB|y&xH_S<)f*vTDc93Q57u>C0*Sb zk?Ik98ql4LpU3y`Lq)g0xV)99UTTVnZe-lN_@!mF{W*u-816|$pA2N$jBT7hY5#J4 z;osfluY0&$-VBATf2<3aJfv37{WdCsR1v6wVJL$V@vULpluVW+|B)4fyN>lQKg(Dz-*H(QU}X|dr5 zAuiH+12Ic(yj+^? zaWlgA^HHoh-r~*oxtYEs0}zCdx@eqK?!5DnT&fio^l_>6?290gfZnp{B^fvU2u#i6 z(~Bm1!7^7i6^aF%+36T>*V|ET*Xv0BmbmfK-rjK(VGfonhtOh5`+jXYyS~87bDSJa zL?3GCAiu-pS855iDOw@xflniJxi}RzgM#kfKwKA&gjZ8?9UxuIVD8}9Z<^HWNK9{egW_rSn zjorq53~UJnt@>mR%Qtc1Z~ew}`<2UYh7)pv+`YokLH4utla`Q_gQFwTO|LJl^J#Ql z-=)mV7D>^(art>Hqq5DPpaa z*s20q>%FRTS!A|Kqh;uZyg}PaZAusCY4ETP|OAREQa zK;lU|z+>-j8Aaaj$$2==xHHgVc4e?Y?^3H<z9n2gWiaLm)zWCw0hfmD9pKs)E zDXbspFo`Ad>FN0Wl!;3ugmr(G=pu=^zH{4Jma|Z}=!C1#Z99dq;7D5)LO;>9f5FJh zo8A?Mur8AcUJMs1W)jsEHrnmkGfZ%bqx-$0)i{7it4arRr7oAn%}Fh{O}Teh4iEb= zb#gbjGo{xQ+8wOQxVSl} zIk*8EOkccVBSg!~%D&lbw0jIh<9ub_12qTgt;AWsyghE?n%>xqVuiwL6!>NoHJ+=; zKBUHVj%i$PWJMkHhw8W^)_|FAmv}mtLobhwr(SpGT{=3T>8=)&tkZpyxXoJkqpZ>H z{`?bjfvXzLO@|yW(}l)Fmg-=y88s1+*<)S(cV2mqRUhTz=%|bJOLTu)yfm4Kk&!?U zMNGPR&z?gM_VjSqhqsp5*<1NVo&yhqx3>7fyH{~cFlOvUi8Na}o- z5jqI#f*OZIgb4)Sz?sK*(*xB85_K7SJgyyo9gO3x)6O(?k{E94;(zxEC>9RGSNj&! z`pUSeC&LZi&N% z3Jf23{ovRBw79Y596$mby52VgQF+p?lUVJ;3wzr?s2mc4V#JA(e2^Z6SpPVq{uLp# zg$dMhGo=^CUfT$)adx)r%F~lb@h?tgc$d&U9}->vcq0J#3ApX1euJ91yITRL`gMyi z(89ms)USLU|KRV(&y2dLCCYD)bH;h6O>O-KWf%5yXyEfB`j9U+-To=GFP_^ZZhC=xyx%<<0-_Q&0`;Ja>M^0fbdY(a2GMDIf7 z!XUn(yquXl5OahC{8~7|_L%_7fO+YRqRt%~hPescsGgrmrjdODGf8q$RW02K|AEpi z&h68rx_0y~JO!WAn#GWzkey@g>!iQX9g zM}GwLLde(rd(+tsXLIKe0AG-N#H-g+%v4%9efXbs;ckRQ{fq*f@6!H>8}wz$QT`9^ zcl1^HOFZswJP%q>-o32_SjxX5G11=D8MlUrF*1ooBBd9a)KgCN5a`FIeOB;hz7F<`cA?37Lf>e*cPPbZ7w%De%89bK3=B+i2?q; z-6$)g5onZGsWk89U271nKewjPP*4H{!Tbx9L#CagxRV_~jJULnOdnMDQY%GJvzV{1 zuap$5Ku!Ca$+3ixP=IjWZzjW@eFkViE|Gok!_2}$DCzS)0|Yh=;~F&B6Br$a@(2tQ z$4kOP1`XqH*G%iGBrzD(TZ4)5!d`#1cO9`l!S`xdX#cZ`0o(s@HvebVpz_Wfs8Z=F zEiuka&nr%mWUrYDWP7W}r8{>S98tl{_<}UeMG`>5!Qn4d@XNEL;h0CIyqubsXo4(|1K3<-;CSx52zys&a>weojpnSX{7&bR&S1-RF*feiAk2lh) zRkl1VK;^uw4n&$}%?sTP&nY;19&$3S-yhVNIn$>Eu&@=R=<0XfO>}iFxrnl^%`73) zEL|&xH&-2^m-Jd#&mO*m`UfvGH&iE1?KAVvQ9LQC8!Kc7KA>$V|tyYDk zZN9!u??2`OP3C*8ZsHd42<#>O8Pv7$-ty~6l0I(H(yAh(9YC8*>OA>;Cw29#eje5_ zhWlL{^f8!U>v?da>K=T(K(|NrgQ@*R5TN$TZh71;rKe$MT5X0sX2_vmW5PEWao#LB zxlUX=C>Uk>>5lUOHPwE#R43JoU9XER#sR}~icP0P@-;8_n&S!moMcFRy9y&~U98JF zc7mCQ(0;dRCMD`oXHWwX*g{d>&YL4Id>-lQq z`2KyU@u$U8E4XSdbth3fbybzDHLVeOtSp)`#R?ahu3x!xAyGT-bm?VfSN4W_@59y7 z<0I6xiMu2uEd&&**AFos2w9k{ut{QMa{6iL!ML!j@?|`$E_BkWs&K;Wtr#WF=L5w= zX)!pnb~)I6Ch#Tn%bKd5Qp!bYV_x3k?dT4=ykQgfNO5Vc#0RsoxZ~EznxYn^Je^PQ zk;1C?pT&L}NCL`C%n&|S#HN)}x~Jz9v|8K_e_#mrIP8jgk~uT=!Iku1ZiOI>{ckRSY?rHRJDcQp)^ZxlSknt?5ehuvfNPWp z3);kxx769S870+>WXjCf>9Hhp{E7I}qHg%E@a0h>-}QXu#W~mPsH4!x9)9|gii(Cq zEMt3{hxd`Q?<0@Y!xqXUpLIZBMC-*3Ur<@QNP-QM)^Y-0>-{3ARU&qt$Exc&j>c$W z98H9@(CAvMt24t;|~N+Fb5BzyZ( zEv&v-E&_u*{a2M>dS15Q>jSjtG6!Y0psI#vIZ9WFY^kZx!+LDE7a6!lAo$i^61%nS zj5AYqqu}w~?D&|z%k*7q$+~`-{-vB?U(^o=u<7iJ~9L*WcLF<${_-&gnK@ZuPr3tE8;0VloF5 za93AAoi|~Qug($OwlzciNl!1FcqjOu(Q~Wq2`>$n(UmD=BDazbz3-KcmhK`PKA|37 z)7SWw=HM-gH&;w#x@z#O!hQMbm-bEWrv5}5FV=27ImQ{YBb|f6mc`=dS*E`)V>F&B zflYDUgasT4cF#o(3JXR=L2{%Ed0`VKe$H`=NuC{@prX3TOcvk9S%YR2_Xyv2EM7 zZQIGjwrxyoV`4jBKhJyK@2qwH?_FJ8t9sYIue$EvCeUU^L|a+awt(aBV<8XA^aix= z7d3*inO|9zj!nm<3yDIeZ-B?mhb=B{WEGFFtvsh~ZC@J5Nod!cd>UwV!x7DV*Y&*> zP7>9VI5n$I#>&bcajbqeczT~S96nv4Q-n*!*URZi&hoF@+fqOk>26b-EQI2&5@rgc z%YZbCr6Gu%nr@OC&~{{zaGNorv}kLw^nPqQ%V~{BoJEgC79nX(SA5g zi6m#JFh_UM|lHl6YiveR<}|WMFE!i@xxspOr1U`Nm<>aRJ{Yg?UUPLu4~;_X&yRxN=dtVI z*C3ZEMY&iGfz3waTZxs-LH37!#xHV1#c|Rjn+5hGzx#B)OY?kRuaOcsZ^g|9SHx>r zkNy3RA@Bi(%>f79W46#a)7ZYBunA-srh^dh(NG2lTs00Z*`R=cQG%B6hrERF?iN{c zBjp6S&B|KJMHAaj^BpaSP&1AUQpdkys5S_Y!iM{WiWAU&wNs?9>@xDTc^7@7VoxisH^IMh1QoXBSI z@`FXHPCr6Np9?7e&DFyDR-#ruuI~7r(XH8V6Twku^0OQyJpPM=H)0FVF2O0BgO55G z;_**vj?QAa5xgn+GXqWgwNZ8I+c~Fd$<0I5Mdu`L5mcgSMZf7vgqm2p8E;`#PW!?f zx@v|#E89t3$qL2)RU0WF`g~C0tRGCcSC{PLD%3pHI$s~_=HkqXohz&A51tsf{r1O< z1Z~+rBi;_r=g06<;TcF0$5aUy=FI6NC@vT5ktZAmIPN)1*R`AwkHt^bq=J&AndKj! z17O!_HhJ0zXCycLRDsj7)7scy4Z0FI5`!?2=#4VE0;(d$^%*LF+QqP4xOcbjZmmI? zk_($@E8bC?yZU$e!&I>GI_{@$Afg9K%`Wr|)bSXb~gX#==0JMsS4tB9NzcVaIR#ehJuphvpV`NzMr){u|Vn&5!cgYs?}S!P^Ub?Otx{q1SyQPB1hdy_&14ZHFmpuHkjb9Tt%SAV zf{UzToW9AdyMtj3qTtvK)zr6jefvtdJpL(tY{52G1XhOdsa7`Br?A78RWL9jnWxOG z(RVA-c)Wum*QclDU)fnE_H^1@k=lvc%568p{a;V#N}3f;&uI4&{~A$8SV|5{iA|a@ zr4jw_9xRE;**SG429fddWm#7_+FDw&k>%}|Qt%ieP3BHzczFg6nVTqu5%d%4O~i2H zCH`?sG_+dK93eO2!NdQ4`n{mY{Q8TQ(JbZ!YUB*XGQ`BsA*i)~!R6h+ZyC$ZMYvOz zkUX19XyVX(Cdaq8we1OKK?)6qf->dJyNSP`53{01C{?a!zZkdmu~oB0%eQ(*WE}fwXT$+ zUoR^?FI|XyIl@0Y{?Ga038|K_X?y?8?!G3qew3oHu%e)9k(Ke~rh_4er8c|%8`xfA zSrfXy`0wYdzRjYdwR1GpmWo7g3h9?62^pkGePt(-^pRSr`ipBOxAFLlY}&YJ0+x4; zbvtX$jGH!gh%mxh%3~9Fn_8OD_R^CPDuhj~|9qW)A5+{rYvwevi_GjRz2E;bj8YId z`0TQB$Sht1rigO$Z=*A-6^NG-?*@`8&@bV2+)?s2Ti6E;NkyA0p2ze{v>Y(P&z31m zs*;I6F~K2b85~BTx9tZ3aZrpofEtmtwWWg(UB(VcF&u#A?o600TL2xRC_i^QIleCJ zvf?S4PtZ3}Vl4jIh%1MP%@*a>&~|e<>@C}iJMcYDWSaW5zed4gZ|jYwI_rAf?mx!`rolpc@3A6hmp{QG=n&_jxDy6Ix7WhHbcB>y^x zk|rX>1}-g8>M~Rh51m5%g5D2{%9f4qb$l`BKJGRlGTz{Xs2S_#o1%(InEve3&$!wC zoYcZXNCZRwEn9d9=v z)j9cRFNk)yAaT?6!LkZ_p>Y2@+TQ=Q{No_4_swc(rq1VQOW?;5kgibgk;iEMZ_}Ua zb^YGm-^*q8U^ua77&1T+^9?yl;V_Zp=i}g{&HYEf`xKZ!HI?t1rROEdGV^gqL|7OW z?|gA2sPjTg!42c%V$OB7_oJ;E=9!*dK@lA+F$<`Wv_xUid+u?^{M$YWh$u5e6cpN_ z@8mH26>kCj`ZV7^kKea*b<@A!l~K?0IJK_t+iN81*T2=e zbV*Xt1C2_ol#~>kjpp<7^86Dg(Av^xk8O6_;#Az>LZ(~2=#hClvWcJ!G!W<;ryTj9 z2@6K6&;7{;barLJ(*`WGq}5|bOdc&)_V_lMESA)96v{UPJC2S>R_gqv7S3PRIjtA5 zX2p;nsuf2|5wFp_`(f}nDbmLWBhipu5b;B{3v5->cJXa8h{}hGNQfjte|5S=*cFZoBlcXU3v@Qf-K%L2Arv{{szL93`u>w}2 z+>jnpaMZxg=e5cPkd*D8L^_JSpVX#^1!)@9k%M@RT$*?s?PShQ|>OO0-_ ziT8*blK?4`o-$z$X<7Z}|nZkAlkXIBG~voLy3@5sBJK=}d9 zFyc2qg1VoJy6AvLWw+Pc{a1kZTe_DOELYB;Q4jPHK6U)=ivq}=$<4}oKT4KI_(#i& z-{=4H-Ea_DhX!~(z4>ex+)%8XNKLU1C3reH>ps~KvVTgk zU{Jb1BXtOslGB^+zR-aYJOrvssSE?EHzbziy|hzyZ8L+2*qbO`@Fqd}NpzHwQ{eZ; z*fZIi${Z#b@CDuq5!kL2GmPUE=&XqM@yw|R;kQw_wpzIh3FFAN=fW+Y%N_cqU#I{E z2^ru1`ERCJe@J6PjzGZm;Ha{;hcGK%r3!2U3pUwg?Zv#A?%~iiu#(sPW#T?rj1ArB z_MU5ibrN&?10hh5kRH*lt*f(h!>VP`g7s(tIoM#8EsvhB-dDodo!NP%XoLoXJZA5N z)*mV#$0pYN0r8Tik#W&%%hfq82!W)&h7=@FP>1i;hd+BJ%+sYh(~s+jB;Id^Fe1MX z;ltad`3g$*B_?kbV@qHoj1UQGxMlLGRe&2Xh!AO&e7u+h2?`9vk?uC!Ya7r(>gUHF zJu-MWCOuP7Q!}&gaCCB_RB6n#k|AB{)U^%hcf+?8L4pzmn#b7)-`Ln#U|QjMrgiuQyoBA-JKv-5VW7yWzjx=B^&R>sqBEMv9n<8ZZ#Fx3Fi$o+)J^ z8in&8FJ3x-X|Jl^L!BoM-WH0`attyo*Ez zmMsmEh-vj>+J8?w@RfuxJ`V5!z_04pIHx0kRq%1k(;m6Ah}7di@cCjf2=C?$%Isf3 z4lx5coz#x_??(j*<99$utkZ+2Q*|)r7#AJwcO0q}!Th%dC^~lWh~X4Sl4vlfv8md3igv0xo4WmL|Mj%6dCLyqrV?iHU56v-=#m~T!UhwdruZmw z0m<2`ecy-Qi!7%I@DnHB9yas6hco35F^XJEH@Zxqwk~m)T`q#hifhe16sg^q312wY+`CW9E&ma+ zfrDIoMYQ)~dB$HqyhTMt{k3`mBm`KnVxNGI&00MP5qj#(tV zMXj=`@V<|6ja zq4m4m->>F(R`25uj;_L{+r?1)3&p3cQ%D(Ez|p0KeE+l!lPTqjQ4P$W-jNaL8O?eN zEACZz1#c(|~ei{L1)b((pUn;vr{NQN(sLwys(A!vXq8Cv<`rFOk49eOf zJwOmHnw>Kfwxcv4J`9UUp&4Tq9Y_%-YFcRS-iU!5cO5(wvTzp6gYWUt%CfKl%5NPW zf+o|EY6CNVhpQvy zUzyo%H(7PpYC9z_Y!U@K-pElSnPU_K$A}p|u4-&+kpT|sbvo43xva?s{B;q&-gAQv z>Pc;E!F#OCBy`HA2y*nqFdJ40?A+9r%aswO>EhLJtDScf`QwId^DMJ)c;izwT;z;I zOBRywYF0vWU+1?-0)((_H;EivPnTiSeg(*1Wb-ybM`8(B(5+VEb%7hn1ruO9{W76C zZWZg`%f|(c0kC_Y$(EMk?j&Ytt(bMW-ajCaNa7et#FJz!&SIfuJ>_+?yEd;^p+aWQh=Aqd?Gj6i3O?PX zi^bQdI9!Smtuq96WR3!2;#mn$-yVH5Rct(3WT`dLThIOlP3?un$~Mjb>7oeY#Z({W zJNFdugN>46=tt@TSRz`O2;Kzg0DXi}vx>H$a=dDGAasY2exl$)Xt;Ex?!cqvJs*UnZ`^%MgS{X1ZTh1>~gu# zE;JtfUV+3fN91&Cvz%?ay2{G8y4V8oHd z)mN{94D3JchpW)p-;U1Gtsl3A`u8h%zt=vmCryBhf4023W{R#Y;u4}VS^aUnsblHk zlvL6yFSegl%mzo2a#P`Bt?UD)$#I_d4S!~>k%q&>ZB(1{`20}J$d#$ zxpPQh$EUIY;gt6}isAI*7aT+(lqxUE0qC!q7EF7?qgMNE@(?f!)`Gf$BlJXuTM4AY zE!&PwWhJslIIIR{j+-)~k?(@O}CYWf!#|0Z3WC^#G%m*3-e!E!(g zNj-7P zzxVc_Ma>c<`zfckJ@)qeRvK-=n@9y|e%?5O4PS&@)#i9R+o@i5Bn~Dt=8mRz{Tyf8 z>oK3~$D#m8uaq~Vp_Z@XjHhb{KIw?A=t8)TfAEG$dzmtS2kjA?vNlg`l4d0K~= zJ@!}DvDs3olorM6F%f@&nej$z!k*>#T*y?ef-_V&|AJkcWMqJ@6BXOy9=spl*XliZ z@KUEzGcX{=k1^E<995zkvuwkw}jl$&)?{xVQYIsb1oUXKN7<5*~daSAWZGL|r zP1hSI%#Gxlx*SxQ$g%|7$;X{ag%Sm)l6;RmEziLKn`j95{^2MrKrGD=(G zLd%cJmGPK!sRbcW8N$Q~IClAE6DJosW7m!xvtqqrLue0>mOphSO!}CNEKh?0PzX@0 zjTOve-73)LvTE4bYJIKo)8#yksHygqZc2?HUr2gOrcVC za&od@-B?>MvW@9SmvUgQX|2^nM7CjENps)BBT^jDX`7l?+5bhEYKJ|rJYPjXVT?F0 zPO*f^+pyJME@vIn2s~1yte#eNco>}0SU+iGO)vqyK*XyRFs-xFArG1d_jxIXXu^P< z^!820T@xDq2OE!E&MO2+;&GnR!*VMm$5VcrRo!8LVI%u@vRyM@$4~RP?=-Pgfw}m- zcQjGL9cybq4LfEGL^00VDLx8wrYH)yM97@qW#ln2%-5ojO^8wHXHHSDmmvz#Q#bLS zWizIX9714+zpU&@bi8Ja;QBETrJU;^5*K z3LS)oz&qgFbQ!pUroiFARJAqXVs&k}>wQZm%6Ce|zFw-|qyFCI+jpm)M6zF}yQiDm z&w-B%n52cY$MX|qWh>M&s=trdb+s`MQB8_6>iv@5EDuuxSsudK#BZM3@!bB57%gbi zO89#iJE!KRxvVa_fCSRQBb=nPrQq%Mv`s9=ZXe%!RQeRMk_GG3f9(M?wKSeY-a$K)r zmuMqSWHse&arhVrzCveUpu6raDtj-ROj4#pPX@rgk`i)=v%5$tmm(G1iE$pkiV}&s z5i7@bzMaI5wg_urOU?)r0~QfeDh-^%LilE#y3BX z|Cfw|Y$j&Lm(ciNI0n+m*qnTum9OZy|7EUQr`4*J+30x?8qQH;KpD}VZdDspqPcLg z!%;@xKho{PpShpsH;EH76BF5)agRSn zle_2wZa0&hmz*n;IiP~KH0!mt9YwYzNd?T#{f z{#3=^r#C;Wpgfk7F`jdmDyo);Wz~8uRxQF$g9o0mB*E zxvq!C+fhew$6MOOFKwda$RbPSdKpl-ldHKk@891scgoD@eF~}U^rky0oO?~LOW*Gk zo#Q9=yElu`RI?st=60!W8Y6-2Wzd1sxEWX=t^)nm3`36a!}4KoOJB9_tNw*WD58}K zzAVGP!*h@b(}WH2acwa*w2(r~2C{JLPX;mU2N*{BWdeEBKyuj&i2XUNXs7eR?|{ZQ z2CVHx@KDWWgQrty)FC4NgikHnnK5Dl0%Kv(X(a(FPu98m2%0-dpuTM@#;;!^!^3cB zt9Z`O|0N-vRYOH&F~gn6#L1`}OsD7r(UCP8(rG!UsN^SWEM;47vL!A$ML}c8a``jS z$T+40F83V`cI>(74ewV5Zd&!2pNi&CvXw?FbT6#)}d(D{F@&iF;ra&TuL zd1FV}DWiG+*9DN*d%UGl9JVmcNb(Z;+oM*dF+PI5AzN#-5{n3pn*Eg&iRR@%EHhoe zteL4f36&MK&$m!~x4mwTBAa)3qWC)(LWOIz%_I zcmEpNG=emF^$rJE_E7x9)@HAg}xf8Zh0bP{R%=sI2!D?&6Cp|^j` z#KoaWis`unrOUv}>0o;u0t6wXHkvyu)6;k*Ply7Sok$m!P7u(2lFA~c`@i4u$(2MC zm((6%kXPxXov0>+6;mAaRGtMlDtN`#N;c_3@?EiV-Y1D&#hu(#jG+Fw%gOpbhKNOf zxTv^=*2?7n%H$vaMO5n?p?kO`%9U1cP#xO+mTwvx)-(uYt@+Z!{j& zNoX9W?~}+4MvO#qv%vI&hjDtNafNWfe{j!$Dh|>%7~IsR6@_g@$xkth;lK!YI*80I z8D-{Fkw)6PNKOm^(4XwB>ga1L`CXG-ma^*SDbc(^0YJ_?rdtA#;Co+rK{Pj)?VbOGELv^*sfv{-wp{<~KH^A3Kb$%5&NqFyEq&7gkqRuGgE)o8g5Bk$@E{ zRqWbudJ0bmdew_Ft=C>4WV_C_#U@GsJPtc$>f}f?Mtmy~ z6c{nk8T{1{fEptZ@bhk{5r$2wHg&@Nhe<*W6aGI;Pork#ONa3Zkca_Bcst)4V6U6Iz+=5cv_@wAn=hN|LV%LNq8 z{M!YzaX(IXh$IvEoTh~?m4$xh$@IlkAbx-D2X0Y6A7S9@5(2+#>`q}YrJV;<8P{8S z%Trr2$?AYb73OO7qQ;#Ba^vA^z|nfG5}{_u4|Qb^9PM5q9#Jv=Bloh&I?RL1Ovd*(&h35Q`vF8FY@3%Q%m&OIIlLoc*Oakr>RCfe>$ zc{@u6jr7mOt+hlT^t1vgWcmRV*=(CrFwn$d;~)-^+j|TkQ`QS?JQ@S2r}Q~lE2bs1 zWXwrFV^fADhT`SZWw0z0%m@jf)8ExJ8(u}#gEU>T*qr()*t z=B|1*un7D_rl14w=q{v%QV}^HXvzbGhh>1HqPWCVK^dTi#~G#$DWPLe7|)-@`G-ck zvfy`Q-2HAuMNH*jk(06EekD1G+*~XyGSeD=uv&TD;?iM}C>#n8tGA}b^AU~~V&A8Z zL>pMVka;byYFVZHm;xIfBBc=zk7)eGQIdTmyYN;)lId&XCsbolDqmWI35ggVy%Nq#6 z;jv2=6;T=;5pxA^;P2U-w&px^2-&%!jM|v{mIJ(u7FiowTCQq8W*0#TV4(s{W7pgi znf-?gRB%}<;*rrP%(yG)EjxR~5}{F)2)@3m+0u2+K!KttA>pW6e{gWJv>)}1_7_N2 zZXJnu`A6(j+E!Isw7)t%50El-CW^S>e~Vq=hm9Q(?^AZqdr;xfy>#!KS%CDwV1hu! zLJ%XCpzNgwS3+OZ?41K;;{`z55IIO1*gyo=P)Iq8D0AJCeEOcuS~=t=hecjkfDuCv z5(grK=^;x}&1-?isu{3?sr@|zLx<+Z2^bHVS8@1+d0wDJ9L5ApoC~7GcI5}6LC-N4E>%E3?~v{5Ru7%lY}qd#LOUdx69p}5xjv^xv-_UtNNxnM zxsT%9Vcy5k+lUh^A;UWmgpdzdKw6NT%x<*_PXMI9z}Kn*>Q8{^gl2D zJi2qB<8o=8fp7J6*zdkxydcW=3F+u|KRt{Q?5Ko+rn|pKm0$axo!>271mDnoD5Tpk zEXz>cXU_Th>$}yRpdWPhSAa)Dk1HWTeYSA1Bc91B@D%nSbN2;&O81wGJfmb#haTPt z*|8-w87#&!vS6EifeOMyvWwV0fm>!!79-qx?7;>ILm;AZ`rKv-{sFf3HV|8r*JCo- zIldXK8xM|Jpn(})2D(2phOgx%^BieDD(iCNFmqkWwY2A>_dbs$YuKWX=OeF}`*FKb z_ul!YKyI>F*@$&#$O#+b=dcrYHonzn_@uIQDylp_d)|VT3V$DtbH{&EZ2$g1Yy?9N zNmBNd=<~4pdLihoCqzhIu`E=cKL6SHRyQ?CIXmDAeA2S>Ig0w&$)HS&m~7)~uM1_i z-md-Oh%^o?vgco|lF#FgUAp|Z&oQaIUJc%K>jr=H_L_3gD%|_XuXsq#^LbsClI9KU zPm;XVoYt-T%F*6~_P&b*S4^^S6xo4n$6$-Enb-S#6}ag8rEP z>t#ltUydAq6is-z1tAmR{7>PbGN&%M>IWhDF9fzg9xQU%z{~jsb_B<-Al`S4V8ODf zV#gp&vVO&4~9z458h=TB-X_q;HYqLW05M&KyHua_%jx!@(e| z){!sxo8@3zHz7d@ho<~4b`wzSNkRyp3Ts0eBtsEa7YI(ELmLaRLRjnh7IH0Es!$0{ zk%Ch&+;`C6Z3uwSgVm5l=SUtViwf#8dWtM{HX=z1p;zZwCzg&&O4L*-P#6&wlf+cf zf0RX~B+RZii275lteo9tc?fNF^f!C#N%PgXX#RPE3WeGq zBv?)zcBj)-8WrvYDucU#5fFavwVFMb*Yx0}%z*M>*}!G*!V;KSgSr3^6J{j1P9ZdM z7}T?+x6%$SKSg$$y?SX1(6ee_G^Y7Q=izxFd|y_>=n~FsHSJZK00;Dp3u^A$xCBb@ z)hlLJbuaJ%X^hxCD;t)WWQ4x}0*9s3Fj(KF_rC-#S7~fa>c0d|TVSF{1~Y^L)PL}x z1y$VXl!`b~@>#Jv7b18y@_a1QhFm6FYuF5VyhJAd3i9Jf(E_cT*3W3RyWBo&N?;X& z86E$sx&RYr)AgDWLE%z7S*-@7eOy1ktH{#4_2%pQ%imuQSvr&KM5kLWP?kJVbO0II zInToOta271M)U%9%E-*w#;99@!N+J?ZMX0{+%J)49JqH<{%oX96GJ6-!r`XY>naCWWk2 zZS@@;J)>&M>Z+{|JX&T!vY2=)`c77#5yM3S0xYxf+XO;(^OrXC$}!3Z&$*mt7S>Jc z+|gDte_Br&B!3scc!(%V5(cnp4A5KC^L%gaq~VXqwPg>ODcLqg&G~VcRN6LGO2fz? zUhTpvyqjSS_wy%60$vb?LZu%^cs|4h!dPtY&^}$3JQ1 zjxcQPyL3YKQ4c=_(&C0N*Jl-0f!X|?pNG*xs5d5@hHZBn7XbT}ODG={$`WW8U@Wn3 z!{!0`U35=I7=K$Q@P`||Q|rtk)Qmu3i6{q75tK@JhJILKpqtA}!;A3UI1>dI0Wwn- zf2&KI7CnB9B_;J=x;UrngcZ%(7~P9`w*;j1U{SgneKy*<&)x_84}aH1s^>mcVaiq4 z-|#%GpQUhy>G;D1%P%s8%XKr=A9c@&-JaLMgARLCUk}`2hMZQL>u68e-a*77>uZdp6t^(z;39QUkoX$K^Dv=3}KwuM=63rRA`I=lR=S& zppvK}7U5OawsnL5Lo`Y~`w`s3?L*DRJVPz&{F1n z64z(`HV=r_{4<{*8k+#8qSQ913O{9)Ab22_Er8(I_z5_t)yVqRiD4-&w1k>Og?}ZnR4L}We^^wPfJum~|!SXRGa9?GS z>Q4~)1Zn32*Rkt!kV6W&>(mKV!$*)zn6l+;%9Zs+rcRA>`XY!f~4qGYpi(wE;HEX>lFo(<&Gndmva zysv}6AXud5OQ)s!TKC{!Q6>XOBFZm=0xvvf@7)Io7OIz33^E_swW?v<*~|53_x8A0%SN=iiQR(~A1NQ7l%qKEc5UCxkV+0n<8 z0Ey{ihwA{J4Dj88gdhPs^ZbBj{n%FM2*dvj>+J08?fs6Q!a}A+kDfZFrlW&z|Frqb zgbDXdFTRNc27(Oq81^jmXF2ZwjPQNCKL%)@=RFKmROHXa3s-9~{r z6@Z;gQd9xVN~wUO8F91KmdEGy)V^s5+8Us=L(^6VmT3kGI z?t;)92taB8QI0uNmJl;hSN=cFTp%VE;JyQPK8=ly9T^$fZaM}XjTzc^$dJH*3H@L0 z^fdQB+^He}KyTRC*u=!dJb3+Z9=n^!(R7nBw&(Oha4`@pTizgD~$W@AcC^qxo7-5Emb6*m)5`=?FA_>_=I?k7(8( z#tRxLP!PW-9KZpC2N=y~ajTE{<|jF(ca8hX%F7A(yqb%OjQ%5&*WV715 zHTi3?n`^?D*MD|WFDKgDd10ybdOQqTE_?&L2UIlQ*IR#ge9q<3xM}IWtBz9)Ne@H%1t_&!Xuo!}@%f&57rk?rh&>jK%eeeKpIM!c{GyWXJBg^Pd?&XPStQrO!2 zD){@{@q2J=MM6mRF77b(qeG0SX$hpRdujE^Zf<6~ZBCRp2c&M|`j&uI>$iDp-vX_) zmcxe*MQ!iHv_w9>-4dtpW{tiRGPe~zjxwzsjQSLUw= zO#`TvOJuvw3t1~;W{IADJZ&(!xSNF(@sCnLLWY_RDEWcRVFM^ZN7{wv2Dj>w7ZK=BBelLYmlTgnaR_}gt!7+XLor6CkR+0YM)18%^rL2Y;t z`mP`e5JuzYpW`E}p;%XY!mk6JnKNU$RLV(KlwRI^@Z-&IZA6M5rYF#ixmXUbc^I$t zkPO|dsN*=t$~_x`Y3PM3uGcOJ_BF^iuf#pThcwX35? zAnX_rFL4rSRHxGl#OwClALjI&y5kOZ&Opc@8P1G2snVarzN&R@g16DqUW&}0u_+2? zUexB;%#B+as2WKG8Tw%x=`G8HWs7z!gt7LUznvXMy18iH3G#lw?GfE)9vqzDEB6FU)Fvk!*_ zbU|CeHkh%1?c_GVw&79x1y453TL$eQ=Cy!gOBYnYke(;-qb3~$8U{{&&09h)3r5}U znF^bf{p<~|C$RlGqPO6J|NYycl)!RW709YMo_sbd3Z2?Qskr!)gP7X6s=j1PL&Kvp zGh)g4Fhv*w=TR%SK}$Y58jV@T9HeB*(G9_7)nG1gPv)z%x)QD#UdnWWxL$D zjSnMFokA)6Ci)|8WtuAolU)jRklb^cWWqaCz^%A_VxqjfOhRRorIl7tY%oIzvI6hYs%u{bDs)^K67ok?8!?9-BsQ0 z4-QMzNHR=8YmwOIx^SggdYUwzA4zUi)QViqB;2>7f}clD4%9~3dt;|tI=Z@7cS4dV zjPd=zj$%#uuow&`DfN!s!o@6^FTJX>gp9U?`d2`COmf7l&&8X!(I|}Cs^M+DqZZw7 ze7au^J#xP#bX~)jZ@fH+OGVMA&EI+VR94kns^HZSbLB9iENZ-@D;huUAr(qW*4{Cx zU`~RpF+-i%mUf`He=&j~p~H*fj|T}VAe50?)CabK+PDFc*Ms+y2R4AmwC0g6!^fHj zVj#c}JSPpkSs{^E^*~36LdAlGfpr@tC>GR=GQ=tpXebs#YQQMCsT=hKAO;Zz^+D{p zy+IDt)_tQ4m;R^JU8vZov&Sd$8b$tJR?0^Ce*U#z>BC~byr{70p#NTg{FC?A zdnH;tSB^=ccVG8eUOw*mD_mf`(O(AHy7VYF_J;*aHVF%{y8R{chxXS&;q4ejuLXQ= z($h;9hK%lfa>`=z`7$E^Px6$pcaO!~dbnNZ&7Hs89e9%Lou|uhG3`FD&$^qO5iH$= zUN2WIlaQykJZFKa9@7Q9KLUC-KJF7^)#mw`Ek;i4`sQi`oat~y1mC8I7xunWQXlss z6uXW~oqeO@@^CLJf(Vipb$@)C^!?aWYg`(fQ zNWY8wFMRv%?MV2J_S z!_UK^G4bb5@7La2oqI=5dmruBZJ2qUC!uje`N5a>bC~UyiDndI&Vq{bYkHnZW3lf? zc7FHWPMOuunD6t?*KPj=_yft@E~@{4-4E+(lE`KQ-+dwjfezcwR`1i&*!TOfCT_bA ziyGfkf2TRRnHSx4SPjl<-;0P{2OB@T--PrrjyK8o!`5Z(6oKHv57nPP*uB@bN5AFe z2Q0(%IMvwzlA^3&T9Dx0&AiD&;D04W?1Dq*@j5Uc2w4pfWip2YT}}=7qyI{ZQDN(I z@7`00HenlCu#1d}8G^h646*;0g+ly?g=)p_-nq}=+^r8RBUmA}hX|U3YFP!JLH-XA zWwRXldvxOMXFaX7oNH;#NA7?ARO;A`yyIC$Wp6Gdr1#HPzMR>z+c3WdP1>`t$qhZv zi#0B+1q*wc_K)xXx&W#dv&FADkfvxX@SS6D@)x)_p%3fN588>+KYMy_c^zKJWqk7sXC`>t`d;{$k49F2Bg46YJ|?@V+QS zOll-~CFKU})F6D(H)8E?lNc}Kwb#mpEJRG6*>&-RVfOP+F?*$i|82jAhgx1BqvyT1 z@7A>1A2+q{?X%i(;T%TwBQUCeCG~2GW2*U2FRjK2gJ>D2=)Aj4?~ri0#^{&zhkmN! z!o|TH!qJU6!>(GrBFNvUs}I@HZAcnpRBHb258J7bC;8gB*@Apq&euERy-S|Hsybq( zbxmLHrnbbes-SLrz+JLRx~81bi@hNb%#y0mf?=dYR0q8^!Dt9$60U=vYGy$hk}nVn z!7^MTq%nNF5Y*lYn2xH22$z0Et)=j&0bZ!5&GAHPYBr_MK<_t*+e`*y2x>oWk9GXA z(!Kp{T`nebRsxF{xC*>cyzATjp`jU#4hCnpQuCveF+P$7>Pz@=JQ>n~>c8&VtjQi} zMPpG*vp=hgF>6ON`r_e|vpO-KYP0E7-QFs<8uB$3g(8x=*0m=h+L4@J`Sky$+<)A&s0U`jjeLxs}ZX!KABz#Qrvm;{kB8bmZ z;5ePD=0cgyt@W2YVB(gB&L2+-855@oH3}>ACHzMzs$^bTtJ7qD5!2Q5Ml1a@7C3Se zCSg)WPR`8PDy@2W-u~KrSnoaaD zmyiWKxxYGuyb3%HSirzROaVO6N^|O*5gSsF%rUeCswBr`=pV2DkEwqOlcWo`aM3Q? zwr$(Cx@@z{HoI)ww!3WGwry+Yzt&l2?|G3ok&(}wIWwM&81MMLQBlOk>|-TeWnutD zik#lJU!g4vp9&+>t|K2Q#bCnn#@oHVq|dx&dQrCdadBo=sF0q`Zu=Zn#(zbLyF2z9 zJaK5x-CxXH2_l11@@V3)yirX5xMg`avmU)&E6&Nh$-m;}na zxI`&@*Z!XkK8g@+g5#Skv~KU-t?)3JlO-w6uh4;GFerv+4OSo$@9}JwExefd&#R^8 z`M9!hC+4CqW_MkK8s5$;cf;cGKBU`GQ3pj7Qw@DzrTtguuB{Cl+VxMVa0*syLq}PS zRk0B9(z!Bdtc9NYHM3@(Fxw1C;u8bSu+FNe-N9hQiWM`C+k|4}nzZPyHyioiI;3}! zJ1Ne;#4yY;ZTEDR6wd@p{D(l$VO~!SS_2pM2p~&YfD|CwfGb~wrO?z)07g|E@Gnn! zdSH|gsK>KjDviad(mYaT(euc*M9BMGA^mQ?&FP*8q{o<+LYhlqxI2K_bn~jVp3q0Ma!44{1bxy z>ITndT8IA~si)#1jYmMDG~Qn!edR+YL%H0tf78uL+3}UX#&v-F&ep}`2LB1g!Oyxk zER!LBth{>1f|eO6|LwhwNQN}kO;WMKil<%L_U8vj+g^s9zs`bvrQ7dig~5hQzaTL{ zI-kpb*O~JR2BEiT#ke`~yX`XjI72XDOqP2UvFIE6K zX5xtLR8^0m%}<;-Uh?=ZO{$T=(^X0*E@AyoJBT2gpd}=xq0`UjzK-1XutN9i`NEFL z*kqQwVJ$2^MAP+$YiUkO<7qiXgNQctcC{}YFeN!snERw~$HIxemtiXxt(k1G!1*s8 zDlZS^^Wgb$eLbJUD}5~SqpQnZ#_L~fj{o^*X-G)y+|R>{g_*lLSTEr+#ur$vv-=EK z)&e4>ZY(Yy-QTs41eKgkZeR!KvMRBC5$pcVngucE66k^**_1u)^onzZhE!*PZ4$ z3Hd+H6HKWiOp0BR(iBidQVI>oY~(RPCWz8)Y15z?k>OQazMb?uA-XUEpN&gTr*|1G||Y&=OKT)=z2Y^ktFY8 z+U%jYR_Gv?3@fc`Y2(2+jydd~GF7)U_zee;!t9e6T?$KY9~0m_f>-|ZZ{o)ybdz_s#8OO~(K_-RS&EZjKnsl&C5w1Pa?!^XQ1fV5Hnb?KUT-l?-CBRS2ccxvHz7@A z>FjT-hz|*p1Xn}(of6oEg{>_#0Hnqm>;bd`BmplZMlp(FxF>6Xxog3nRsB~;T9^>b zxX{={2pl-wxCiS2sVOnB=l)HA`4!i?zbX@Ee9yHO0;0!xE_MW z06_OL&@Yvtmul6j#;-CJfuHTiX72}t3b!P*`2GkEe>m3-Gr0Q>%}d2kLA2O>x~<7E zOhrmU6<@EGb3HB&2>9G?e)c9FSUBo!Camato{Ry=#D}beqJ`(OOf5tB!Pwas*$lx9 zrCk~I^XE-!s9Sta@w**g_*iWF*AxZDP|;Tmr=bb9NsUgzbtZ0n20xm0+_P5Rj5;IB z$@a^e@lMUp;U8Pp-08^ZAR%>TLwsFsm+7cL2DcwCxnT(%W?4x!3&L(c@om9`kZ{1X zQG6|4KMF!{B^ZqhZJN4;r{}#CW)L-_ya80};ltZ5C`sonh0m-bbR3>22#(B~)Q9ve~aZxZ)Zklk+c2Bgm;hHttt`jP6ko4xnJFI(M+yGZ5-~Pr(Ivd7d)py;kbc zn`=mv-d7w0Y52z*GZCE~K*?^92CZ7<56*RmYLVV*d9_eeEbU?p|-p!F6 zrjeC|7gDMc)*-OXzjzNNAi~s?My=yZ?QNc%&VXs3Ro6`@ zJp&C({N^j{nMwm&hKt{e>&9{o*2hg%#$UHPOVCv6c=IK0*6$6qJu+;;mVA6o2Rjjo zRKV{I2z7200}D&^Nan8+r#c5J;$WXUJ7i;f0&Cn~|13Cnh(S7_dJu~~LMSkF_y)Tm zMUq`mLVf}BXs~*gfMig9rpGG8Aw4WG(n$y-xg7ji#JR`33PzW{`#R_XWX5yu`=V zm^y;L>6l+z(*z6^m7q4Ks;}q~2>jUItoAjVV|&hcUD%b*|G)Va;YAeG$fUj*J!|Xk z=h{!s<7C5)E(Z^Tcl|jE>A#}-KN~H0{N9}W{DOX1#Dvb=K7D~;ySZft=RbhzkF^F< znCG9#$;rEe5s0KZ&!_Xn#YKu-Z$}MJrrc(?n{7Z}1qr;W=$PcNF_VgliiR~C5LE|8 za{_>G6axbT*)d%$n;0=Qyr$Qc?dXqgz?Cx_m>5r_kBS)>m;?A0HYC6|%tjdN3zVDWb& zeEq+x?|c{LfWdgE+Ottx$UztI`%}OxFup?3gUCLx#EA$YqPhUd?wpK_%#-IAK`IMz zQ&STsZp=U^!h$#_{QGF0S|uO;Ot;U+|I2yuYiewp>DRUVlpT3%XLR-6>Y`5^tVF1Tfwoq;Bzk!i7{3?! z&Hwq}C{_Sfj?=I9GuJG=)|;*6*#4ZS0F{a zeeG*?d2+ehJOig?NNJ`3SmmDWBF+ayccDOyTElu1eDpY6VJD!!@tC2~k_^+m^i(*~ z3}pKuuSG8&w6E@f=KPRABCcA17h(pGAa@-;?1S}+@4QrldQ7?)feUGW1#UDDsFm)v@7vD!sh$>{%iipg(MJ2$&NWJPtL{zbd~h^H7dWlUeY z7fQw14^%hm%;r&loHhnQU66-ZY6DBk$C6=%F}X3w*?Vm^|A8Amu(QGHF%(Mh=WiO_ z)@bajvaC}KVlH7wOOS20iv7cv<&`#JN@Fe-HESdkx>aUN_wjR?4Po$G?7g?=s>{Sn z?k4*;GU4NPJh>|u+Eeeq!}afJ-}jS8QG|NJKzwTIJji*#t(re6sIvcKj?K7jLs#q1 zhMYeldz?YivoH1i^OX0)R42zx=KYi`$k<`i8$S)i*i9QBfz8tFNOUHjr*wlXrNg8y z`9ox4m|vxF(17JiOY#a!dsK&z@aNW4@zDOraDj!%h)G0lE4 zZcz^C*6PZ*h+p$c*waW{%WtefJf&^{3;5ADaLK}FM%bOL#cXVvTJb*oiL|&=X&jC< zOm{^1N$5G!SoVw;C*))m4vPag(kU0!LY+oE?OOl+UH~3&pJ|O4kw#H zr^bTfW+n4jlG6+so~+-cb3(s>CjRi~Dnp~~q)Cl*&H}g2LBEufyQzrHqD=KJE zJv&fF*qh3{;Cwk@->0A7*Wpo+p;vjiGR0J=p{+M;WF5_`g_U*$F#uipNp-VihmVo# zJYBq0F{Fgmh|4po+^Hjp;GvF??>Hyf3Ph3938t<ARQ*SOo?(o{*13<9x!ijc076pp}yQ@2E+Qt@59hkJI zlO9M4f^9>k3m4j`h=6p6cQ4Q3#WD+2jlps6`Nv7fczb-4Nud_;JR!JCpEueHttrR( zAg$(nX0N6k*FIoEhoWK*0bY596|29lkc}#9;={Kf!JXGK`1&SP)_h+V!*+hFK8zQk zD;N|eobrd4Jm1c)kIyq0Lk|`!&oGl_g%#CQvcx8eyg}0@(9sMDs>yDPYZs%BX_aIf z*xbK=0oh{AlRLDXTcc$>qbx}DND#g0lDHbU^EJl(cy0PEdM?!~nEg>4$&73l6+L_P z`{Tn{?JzPjM2}bAL3Z+)`Jo9>4L&>YDfEN#OeDut`}WlapT<8O8l9 zMMhV->0kmw&8FKQsKe{CKow<#^sMp5%Q|$x)bnSv@4-*6^D^F#RMnf=n&hBaoqQ5Q z+3BUm?^fdHWT5quQ_Z(N0F8_LEBy(F0Cso5;kvsZNAG()>UZkc+Ur6)TCVL3J%^aY z(4;P+frFk3_DV&-pd5?}-c9n(E5@=Ies*)8x9YPODGj4-MXvpOkCT2HtpXyOYVPXC z-Tuwi%U*02EbiOrK3c7;0x(Z+Tdw~1Zl$hAh%F&KpYJ1s_KsigcALjdy^Z?euv_Y= z&f)Vx$FleLo_UX&VcBlR-Mj(=ZMsmG*4VyNSi(e4cUVZC1OfaXdk7#;@(H^m_}YBR z7u+(j7on`E{8rBMB))6$m(s{$TxHwjcMFfyrEf2V`i3H?`Ui;-Ha>?krs~3LBW;=P z$164`;x!Sc`>2H~%Z-ooi=CW_&|pK9n~hf95DALyDoT}&Z8{04EdRP)i^Gm0QSOkV z>VAQlpM^z_F;p$}YjYXD;wg8_r%ENIX-^-I=l8;hvU<||Dh2+G3g~C=kJemwzqJFur?<2>4@P3noaz1O?KNskU_eq`V_qZuWV%IWOS7oXpoUjj-wzE+Ey;hKHF z{zmA{JA<1~y$?g^y{{acDZ1~kG*$}i_*z}F6rRcz`-q*vo2iS7tNYeFXES}ZVf-ZI z$kJJlzTJz}Dd!{nw?nESAurPm0l+7Y`JK2`-6`@ z)Xf>AN0(Z&D;kS0Pb-r)+wBz8&r87w$OAh*{dQQhc)+sCGQFB8R}Nyz0b4@|*qQ)> z)ztx*jyg2xB=V( zqTjRulM$IdI|BnOsulE0V=k346m)*PD)J|ZovpfRr`%mn6Cxg_&}{aWmrZ1~^09_5 z=>yh$eyz>8^=nDh?w{&xwuHw*QXU_oa!zuzNPhf8kF`f zn$CYHh==(x*HaR8n{IC3*kj>ja=MJhZ|mfv*FBMP+02#uZy^N)x~6C6G21GaStiR= zn^?1ExKxe$D`pn_XI0h4@X=W5MHBXCNEk8a<9_*tr>*5PJuXMf5|6Qn!z##!hm|73 zRn)BB%y6`BL}Tg~;CgrD9aYh>k*@nxG*;H5cm!Uk!mAZQZ~If6cZ9Cx~P*Q-C3)I7t|@;$yhyORR8 zhhm=2Jy%Xe7{UpfPu12EQBtgd;a)fnVy_;NU?U4_cK=7IEL(Zah_-y8#kNeO5GHNR z`Kyv0vx6ZToDW~e*O@+^RC=tR4IN|Y{PJ*+l1b1HVhjmV6g#MT{;b-S$I-HNBg&I5 zR_dgVtDAIz(Vdyk`!k7420xR}HfeEL?NwK=tG@DOodPyMvP97m5|uhRY(%Gn87Gn? zZZz!NriRk;eKOn{A zp{pNB5|kI+x_LcIw2+WVSlT2mU=ZW}NQh{QPA+lGW@t?cHy}*heAWVpYQV@?9DJcx zyFe6JkC9e+T-=07)0v)Uw3rP?$2FTl>6Ei{QUSKRo0 zPFNx~93krLYBM$oEhiK$L?Qwx7No*2PLwbSUXptpP^)iE2`&AT=i^N9y9rCzHVrc< z7jxk2O!ngpTQ2n4O%r7tIjpzftjc;0$cPyBN%e{oP=z0L<$S7TrQ@rd9v#)l(Rz^( z^5~1LFA5z^mt+;gUgolgPKd*nt$LC?w@2(JrKlQSTx)`~QM`b4>I{u8vl}W+a$pAT z>(;mLsDtm>o8X_xW$tmDbzw;th0RC(Rb1Ry)7S%WBN5F}rtKbvOqfs0$P~PIP8Be- z9KS%9TUQTrOT8b%N0WqskydW!T|Z8edEWm`Gtc+aSWQy@<`0!9dcM4v%U4>2&9nGG zO=M6?`8yq<98oS*$#Oy0JFGE@_eZ+4@dlB?@Yc$`K_Sn8drG_(ib5;fOf_>Jfk38U za}b$_RERh|EO{tqJfp>GkF;k3S}j?Jza4ulZ{l>>rRhRY7$UPprEZy4 zNf9;aBJg>R!AVuWsbcHjp8JA|zV7Fp?8lACG~cagfh!(O59^FA^V&nqcL7sNJxZbA zMsm-!+{o%kPTIM`g3V^iiStt>P>A$ygmEl7E6w`Fr3>7WsaH2y@o?B1QUE_`WPMA2 zpm(B_r9_#vIx7ZlG@29CB2oIUOStsF)Y~8_33=00RCJg14u|)3+T5{{#Ha!o96$c@ zKc{tW$*3vEpPq>IEu(Zb{ue9PRy^Nd3ej5GLnM6%jLs_E;rwDqWA6ME|DG!YJ1d-A zTz!mnpQfunXiJ{?9Xx{650sxT#!;JHTsvxn)LnK%K@L`N9rC zZ*F+s?#Juuf2nr*&DBhT?=9VDptP}Dqz{NszI0jw=S zea&O{|GWV3ICyBZ2AQF7`k!uoQqoaT1IK_MQ;gvy>0*=qVzzQwY97lzY$zHfdeNFX zQC<~vPLI2T&c|?RkZcA7Y4{|jfUpiV=1?gzjeZK=I@wLz7EPcUQ2bL#xce5-XzlvN zNyK{%A6p`=Vmgfha?-z2yvAMbxKf1p-KX&<`{K-^ZDDYSmgpW(c<0^A)ZO3}Seh4ch0bW{uS=nxtL5glM?2 zaQiAHLl4KLVax;IT@PpNE*GC)U*=O8Y^!0El$3tIECA)`HM$*+PELh|g?6~8LomtG z+5A4-?wy2JE8A??(E!h|$hWMVoSclz1C`<3{!n;$I79dAe%?GF(XCsur5_W_F#p77X5P87Dok)qz%Z$0)3)1g}0H%JikpVHpTxLw!qH5 z;9&oaBimoir+^6oh8u_o0_7Uq=>EesS@TRdWunM*=fz2Q2~kHHk!IKkCZl_ z$#~N)qSdI|eP+tts$5B7(Es*ITCs!B#R&>@t>sZp-{&(Suws>J|J-Xr(b`Y}UiNg7(r>AvmHrKw- zenSU$fS4cT@ZbSJw|alT3IhWjWds42Wf+&8l@+(!wT_chek*5+3FRc^Ch#I)x z;!y9)>qoA-{Id%r8;SjFT!Gh3^{FgJ&x7a9mi)*lL01eDIihiSm`+W;1eh-?W*jyk zJ`E(e?R9ft$l>5!$9@_uh|CQq6X1=~|1ter1n0H;#8CphhMJ`?Cf``%vtwQB2fzj5 z5QJuT6hA%_^RWEJaVn7ODFp*w+g=wJ)Qqb@!ReMN=-u6pQHa0XTw;2i9=@qy2=uxB z-gE&TpFT5h1U9_x6Y|O|Cysgl*~H%%6UOzLGw6_#)@Elyit(uVK03Ktt`&QIrKr}< z|H~3uj#mwlE~j~Jz}6$1(S23d-ApOAH(7emO?Ldwf>_a;D=eq}7<}fqFS6doBN*I*C9ek(rzL2+!$t!c;vna*|22cd4^*}uf>`magA^?fo_Lgh(k#&! z{`eLsK;~l1oO12ZB}CNmBf~ekT(e=HM*?)+5Q(=Dad1_Y!Z+T(FBQpeKQzz-%Tz^W zB${iLTUkE7oEqbD{2l6o7NBch@9Ddk`H1oCyE+=4Q)dwcw@^m?vtM~I=QjHiE9qBoJWS+}8L35*~RZA>9mhN_Q2_spx3H8&S zbPtY{8u7g(7*wrg2?Z|aI$TJ#mg4SjbOt+f{L!y6elPnIg^K0lHkQ;_n19Fv6|9T7 z-;Q#8Waw0IExl%a8nk$Dgm;M@&`D@dZ%4)@UMTa+DQb&Ze_(O=!4%4bNGrz?tc!!M zpzLH}fGQ*qD#c1|+7u;Nxojj;$27E6-JLI5M;;sA3U4UnNQi-OHH^$%s%0?2QHS#) z5RRq`;3DJ&<(W7S8MWYtM)tgcb_WUN+HGkMi|0hPi70u&*|2*@`_{G|)I?O6a5+J# z$w|cmN}#c&_imZo2|-TJeUYUf!>s-UxP zdOem`IY_t56objl;xmMuNb+)5|4uPBjTG4|<|mT?^VbW7!s2((7%qak@2j|AvVAIb z&E-<5CPc{PbvsKk$Ro6itCufcR!`HxjH>^B%wbX0a+-ZalQ}7Ir}NyJt9`i{-}#z4 ztNM4hmxI!0X(Q!**k3GTBFOUHesrbZ`0z0CbO3B2_^&Tz(8ls{^zkEg8kq#Wi~aY* zUP&QF0|Mv_4hG>lK8|3WGZqeXOOi6axA%ILl#*lScts88f>=@{xdghM9Tiu@kJ0ix zBesy!w`^g}B-W!~MzD012DS> z@?h|bS>Wo!0jf- z+x$%ldl^GuKXjNktn$8~6zCCA87DB_K<~W1FjOylzz~!u6DUGxJe8l~u+p`xVx%uk zy?Sb^qF_2E(zOTTUb%4_*-?9cBL=EyRtg&V!91pIws>LXQv5)m2P-cPrIV22@#$H_ z=8sp0`LF3>RUB&R8HC&?(%dPC98L5zw#Zv!Q|rq7vXK6NS`BC3svR4-25e4M2UB=UnBsiBG=P_WQ zHE0HEM3H4OX*QsQppmK^^vFSW1w*YNSQ!JO?7kaw*)nFn<-GzvN{c zK|RR41178n_WnY@f`FYBKtCwai zz^%G&g0cVf)&&fJNq#lB3jG1QzXwu)WTk%1!4YjM6{35u7A>|RF@6mY)_Wm~WoSui z&f#v_yP)eph~9dC-yf8fkbmAjn23@1`e*3C8!O%+9=K-myO}LSDj4?0n?6MNAo5W4 z2+!r2o0;#}YOLk&GkIxZo<+s#^H(FrlCA4v+NAl4ojc*LdL|I&GkKh*V~kXZ-G&11 zOPR$T-4X!?N?((iq-Z;R6N|4#+Ix8GZscy zP{sB?bp)viX^ho|M|XTkyxpV*oETnXTXOihNX7l1pHE{c685U0F+6vgSSW~e)u~BQ zPY9^P;X9v~so|X;$R0#p$jZq}Y6}@I`LRX6plX8fb|;@PzE}DQ*9REa?EE~oudtiX zOT~z!Kf)1mzZ!tYTuuvfKV8l~i?MW~7EZ0cJ+|&$v}047{j*3iesUKW6cRA4-Ky7` zjt^?7`LGo{O-EQ>%tf1jIz5h92y}Z-FXNgHlO=M!p6=qN`xVT8oUE;V3peN#(6(M` zJ5@fJw^3b_ zR0omc*K_VV28iB=89DS8hsvX2Zg^8Ht^vuDo#M^fBVkAE zLc;49x$kO9hC_hALn^%oYCUeirI0eYewVEtn}%YmBtMx})4k2Nu1tpGVk6K(hv4y< zPX!=>hYqd%&eU)EN&LB#_cC`Z%5~nI2MM7i$`tt5!Cl%|C1%J0M&xH#OSRhZ=eaf) z@s~Bcf~Wl+3Ig0-O$aWx-Tb{z=8N6u=WgVMFElQP<&a-0`7e+&jYgv{kc<<^pEkGF zt^zU|LzCgv%ETi;7&iZRYt{%m>Ugg4T}=)SMgx^?J}CG+RfT{{idZ7UtK0R!J3$t0H}JDqo$KkE~f`q5F&tfw@N?6^vz5%M|A z(%cxnx{N%~NQ0e*gU?{U(OqV_P*Hh=M?+50h0U0^gAy{BCd(m<>!xU**{wi zKi`Hb1?N`2s{pmw{D0J9|4O5W6uU@yAPQ)kUqc()Tot{s`rS9#d$K5~c0b)JE-k-t zTzwz_A><-O{dHoq-va+Mz*Hp&iGdt5dyxHZ9iR8k6Awos!`D>!rQRP3O+VFsR zy?A)b43oiI3IiU2UcXzEh1$e+rC8H>x%c+Ca5#ScwSi=2u-jfI5z;$Zz;^?l0a$Gn ztK90iR%eRrQoiF<))OcTq&s-p=xLmf{(PL<`?d+g;bPNVeXExY)s?HSaWromF}`@k zh1_(Qz^e6{?T6)9nsckO+ia3-{<#|KY7S*h3PVE~;v=nHt8v01JcohEUJ_j{#ujCTtY!=sol}JPwTiWTO;C=uc zG3DdsW~}mJ?zJtw7>B?&qy3dycD{c`@51H3 z0F>Q~#x^vPF|+^M)LfF?f?*s1@dfCyB)(E`}4#U9T0Z6f=z!k_&DLZnhkBA@8_C@!A*BIwmL9mnMH66TY_sjt_m- zWbvSHsN^Bc#NpgRM`W%IJ3E_~R(jL#CQguW9`jN@yU*%HcA4vvy-;t$c%I8fKtI6? zVS|Or`7i0e1rrAz+^)YjjGTayR#Feb1pC!(YrT3-gHf?T@XVHSd5>u7udQY)St}JM z^)!v(mlzgz-UD%3o%c~=nN)f_yaC0gL)=Mq|EVRvc77%oXBXrqwKg4Kbq01(V&>0< z5_!GP(zk=ZA!P`*fUfAXXXzQ_PN4fmwEJMi8p9}H&^2$E3E@q>ix3U&>nzbj=F|Gq zz^c7O7nUgvk#q(<^&F(y*odeo7c;$kOh)BV#PFt$qTbZIx4Ui5bJb>v(*TW|jh;P3 z%$QM%v?UFV-AbHSA2%y4A&rv>a>3(zq?WyAM^{n*1|Bj@){9X$tXiPyBUEk!0V7NO zl=cdczv$K=Ysi?G#>x$I*6fwSohfU^i$D`0xQ)gOU-sRH95C8=4P{w-;Q|hUCSu(1 zB}qyhgvx65TUIa$GFzMgP+f*7wd+hwc1a~$iDkoXhqUlZ1|)sc*t+?Tq9gt#Y229q zi5s6~7$x!$2}Jy{y{D+AY>w$s7%O&RZg83X+7y@sScbsutsryImaE4&B-j!2Y1v10 z@DN6TSYd_ToDd`4|5w9CYo-?nUz8qR(_VKO6ZRDFaV8EKMweb1!Cri4go%^Qs5yrj zFH_9#Vf|Mz=ooFXoty?AG?b@qiRlOxE8cdv7fS}@Hn@2rKKWEmpYm(-HEECm-X$q( zvL-4MlRn?;V+1~E$!vuyO{eF&gAJ^7U1Iutd9AFRu9~)@{WK1^?^q4%Gsdr({ zkTHDE!SdA`JW{%6nG6U>;qNWf0@p{Z`qGse1mT!F`f$DQ0I`(Il$gW|D%o@t)BzIj z#D;!Gi=EL=PEId<3QS2ti zpX*VG?+o6quiYNKkH=J>Vg&iNSaMQ)j~}nJhp|Q$^7pkEyw7WW0itY=B2x)_tSwK| z4*0lGqZQXPSWmiH-YJ~_wDgha>5T9D{&3$iyKllhX#c*yYAj97f>o0XEX&#flfXnM zb?~!Ry%r$IQ;o}=6YyGem{Wo`e&8@jLui4GFzcuWhW>hR+1$NMLZjgAsOR2fqz3*n z5T3+{l7gbxK#~#kGZRrd1q60U)`B0We4808{%^#FnJGT)tUH$VoDZ>=iWbyv=e5h6th?(mq$5HiigVWi&_t)C|$vG>_pk?Kh$Mdi%q=0wvrFWaiF z*AmXI++7?DWNdjS7 zs=s%{_=t|f->C3+c4W%5C*K5qbgV6y-5tx$%cyu&@yJmbAu>elz*9FFnk^&Qed`H& zFI=W0<)jf(x%}QwqF&%z)hjwPa57|ae>&(@G#+@#z& z1|Mt&Bv6OM>Gc{7-|VTjN|vqS_5DW?r(a*JC(Pu+h+8?>Hj=B+_K1n2MOPNx7Ih}6 zASyxTlt$}QIwD+cXWX!9r(-UIJc`9Ua$xs_XcHA>u%}P(c(;A2=rFjK*cD0pdQpOe z5R!`xtOJJCW|SR0IYB#qtpHIt&Zi z!v`<4-4e%wz0n{V9KVKd8_XD(k^H{T&XVAMGm6Q3{@Kn#%BLG?@w?w160?(smxm<0 z;+l1FTmo=}E~cecCtLtW$oS~v$*o%d=lErPCHymZ=*FLhGnArSo6O4=xl*j2v;ErJ z0g=3}26)m_2=hA$0+ZYo;@T3U_rA9aoaOUk=gnr0ho&!*8Y(3|t7!RPEE}4RL*3nYw-8eMDsml~MrZ4+ zt*_o~AF1RYX=)-cxk1?d7)*Uq>@=^(ON*q|8=G}CK-->o;==>}kB3T*ep-(|o?>f0 z(*C|U4-J2P^;p7TJUA`i&^dM7y1J}xA^<0>4sqrFyl#5VzV?*x%V*5{{?A@BymMI3V*E%duBV!BeUt2bqAN69%Gg4jNe! zZ5k8MzVN#g@KFwU^C=&|%vh|fsiT97k3Vg|=xqxc>0F2lFX7_Syk!eWU=xX>4j76a z8zpYkhqV*0F_F?#A`%vGGFtCHF-9*9oGYIGK}d{4B|pP*k@zi6Dqw3A_L_<}1W7A(Klv7A|MPaZ zir7Aa2RCCf9$GAC!W$&_hhu|xA(d1hf|2~MLV<3%ppU5T334n66zKp4UlXxwu<+HL zb8jLMBe5c_Q5{*ZK{AKEfwGk(<3^rT?vuIj%d<(tY*85|eWoG}lJ#nZgAP z$AoO8C`u_a(HQ)vyxnXIg}DZ?t$zaY8h$h&iW0a z2n=NVLc(aE&FgAiNEwu;7+IZz5%=r)3nN5eSR` zbdt&I(J)guTr+UKRM~2?#_ad~3Fy8XAzE;8ll3kUn09E_{bmMei(>P<+pT$Zbp^2b zHa9oZqQji|y_nA-IdkJBj={pg!NI`bRCxkIMIK&Wa@nkx4M+;|U~x^adjz&LwD(87 z9Ue&Ty3ENGZ9%m}KI*JjYBo1FPc3#N81i)fkLRcruiDA?1ETs+P*C)}?}mhi`i<%# z;Bo)y(%#WYP@)o(6|7t!b=Weezw^i?3lfToiW1(q2@3W$11T!nBDn@B=i6ATdzybw zxaE{JIi3y#fw%m{2ap?jpypHc-G{e@&P^*ZMMdz)^L_>b8&AKj;fU)ADH%Q8IwOx| z#YxzF0GnXSL&pQ0;g7-d5u%C}OWWwI&&*|{*YolI-_hd#-%-JX@i;%F9~aaluXLii zQ$RNwt?K922`pqSEv+iGi*l7xN|6SHcf~^G@=e+Kg6lZyU{~7?-L+xgWH0cs zU2RS#e9}5rPwt{S83z^+a0RYzmY-@&Ig>jkb8uXIGxrD{;2f#Th-e?xd+-3P{z7~T zXx)?iXE<;@pr(T1&oV*nDRxFMj*}z*k5feI+s}G^D8iMR_Nz7J@weegu?8b-pgo&1#&l8cHU1Rd_W;E?Hh8@{VtrihII$V}(>v&=uw8t0ubadv|sTHLK))?Q@`iRPV=B0aiizpE)3VEuVQ698<&C z(fJe{`?Z}l$wWQ*aBhU}OB8Z334glMpg!Vjgrd$He0e!%)eR5{YOED?K)c#xHdCLI z$8o`M{Z$8W8a{U`smZFCA7NxR7UqooFQOo_s(9({>WG(@_kBHM!X*|%r66X3VDrkO zQfjg%|vOwNh0LZBHrF!4-s#Qta$B* z=78_PA|Yy;1V(HQs}Vms0lwwb7b7kvOHXy9%pPpi?!K(FPY^B&JEV97(G->twuxug zetjw8fekjf&%J}=z2*r1zeO{)K0v%844pahWbq$QGl)>^1=A`AjbGZg*qeQ68cK9*7VP{TzFHq{d4rbjM zrYmFu8kPAuZ3i%4+?tC=f$hM2{GS&9kB>f#UD73<7Ux{yhMuy_ zhP+52=VNdY@&DxhWSl)$0-QmX(f&ax1af%(l9tLn?`w`8@U2$P-=ZgTpaqhBkE8kO zxA6Yhi1A2>4wcQX2mc2C$6mdCg%3U9+aS!d(~Rz*FZDV~>NPZY1LT8R5h{~IG;*cX-G_%$e` zqphnFDrD}uOC{UR$QULwXe@^vqE+jb2y&!DY``=uld4QVmsfG!)RFC4AXEMrWs>j~ zV3b1;dws1WLTvaxcjlftVR&9uY0I%X1y4A)hHIIY29K_)+9ADQ3EI2gHzOb$3=v&W zUQs@f-Hy zA0>L}g4N5BmFI_3=#pZR7tUbDf!+J>XDG^ZyzY&hkrU8d_nQ9H`BQ`j+NP1!zMyvZTnnOpc{6Hm}5=F{#V6uqCBxkCwiK=N~mI{Em(`|0;M(pYYrKM;fm{ps3$#8MNHFe-Ejn z_Pgo^zha}BxBEdLx9jIl=%zg9TB`Qa`#1oLrGL@$s6MvDN63%3zP^OjZK97n#^O1n z6M~N5>fPYC)|U;j%u{WUoM;J<%j{_%6rf5 z!YNko(nul}ul_SK8e#OU={^f?BgV9Yn4`Nx6rA<*XreV`blT?Q;s=#oH*~YXazRM6 z{I)pv>*?;zZ`|H}X?4{7DjDiQ0{$dT_PiihU!#t_^`HRzbHR+()BHpxU9syc1fgfW zs~GVt)^W2@VD-(7-fSc#cIWl^mr+7aR)g(*Wi5Xq`-*Pcw?Ys2)ha7P0EP(_-Mi(& zcqvErh(Fw>)JxC%slJ{U`A|&2_u{UOu7%GcCeIfjfsB1xMRtqPY<)7_Fidr>W2Wls z!pv;842pq1+VpYBgQmc#*4)Ig_49MC(b|vGvmWb{Yd?hGu!~hHVl}}wZv1*FLaHg$ zD5k5q9(6My*6+Fh;Ds-zZ|F5fJF(SpvSt}smC2lu_-jU+7uZHjN`y5!w=6SKAq z&pP+b;-Wrs`1Ex3O(t+kz9*p5xE0Gy1K@aS6{_OO5hdQTVzcGhH*xM7(yTpqkZ2Ro zr9Fsqs$3iyUqbJw4LKKqlF2}1@%t_Nz!HkRkOYT;HuaY9pHgmwFgM164smIX%=^52 zpgET{9k~CMYrC4=Zlr9I;M}_p0wxQzu_Bet?!W)%#@nM0vDN-zqp^Q#w)(NLGAvacz-ppKk6sv_j*vY>T{de$ywn$%3G7SrF75JO!;0&%6R@8w+jYJtc%#y zr_${^v1;n4*^ua6_ww@PrU&rS+P^AW>G`fWzx|zay7uY*T)Z$Pwz~%P0w7Qw=5mreEKB`ds??(mSfP z7N>^m$*Jn!%tZZb1{5<}?kb3!ze!rpUfD9aCJM*UD)~Mk8+^V)<>gZGcFn?KWF23l zqZR>^fKyClJTFttKZx^D+rmYA`VOY09J4kX0rv9OnQx7RbeXDOJZ&DR8g?TENw%RI z-J$uL6##?I^<7))c-PM`F^LEBP{`7fa#m*KS0S{r{3#8E5>@PP|65p|2)gGuNpJV% zVY`3)-Nl8`Y0RX-BRJ)zQ0_> zc?!fsy;8cJmRc+s{U@}7#*J9C!&amnIJ2tSdZJ-}N*~4~C3PS$T9-!jd9KT=mCeX% z5guO^$4&u1ZWV=Pv=Fx71lQm*|!Zge4BX)sLVvfl&HWy&Xbz)*_)c0e|c#- z8%v9;3QtoiZjuu#Cz=>WQxos0C>vYYUeSA?su_zbCe6)+Ii`jA_Exp2=z}^}p@>TJ)z_c3HB=GIUlu>2qZ-={6+F zI4|YaO~7m6F!>`0|H*Up`!9!(Q=W&0 zlGgZYounZ~D1tiL{cS|Wc0Tu?f4$&u5OqfyCHK=#{GVMGD{HkHGFl8)fJuW|QZ>ry z(C04DO^?Hj5Kt*%Za>s)PU_;w3h?0R*s`Qaq85gC&!VQ)&M%S+e?k4I#)kq0P8c_E zIs2)`Jr4yQwq>?x)dt&+zcG_)LbVHpfQ3z903{)iH;X7;#FpN1@Z{fT;Gm%cuU^wN zwC_)dyoYVQUd%=MFmwnWG`)*}q{#zhG|Av@AQB4N{(&J@0M(hp?Q5c=A(87ZmA6a! zWyqmOk#jk6cM^~)(Qgl4Ic9d7%$Oj7LT)Z5-3E)4BzinXWFLq?870*hbexELG5_bG zdYkG!kQP~r2*d;L*egOt%we9^EU9e8r((I3t;MpxpntV;;%L(b!e{MttK@!$&23Kt z6nG;pj!?%BcEW^7`$R5Mh75>j`hbHhasES8D+{g@d4#~0vnDvBg&-d9%)pM9AdRJ|ha_|tmKnsJ)8q1Nj58)!~ z65$;{A}@**4QV;=WR@J}*XP5JaFp^Kg=LpY!7BI$;I-1r^0wS)I8<o5>IMpw!uYpxiP)(0#D$zEK}YkK12R~2;WAGShL`@_QJiOS^V2jsz# z7TZf!a0LJwzX6E@91+f{K}!|~RnpqKyi`QCHl_jyy!7=T0tf8&BTuPSjNt!#B}%73 z!$q*esDj{0ljvg}r7|rU>URMe({7ierttlAZ3$(voUWiZ1Eqvs;lIm%e?!Ba1GXDj zb>ZS|jSu^~h~Z4v6)|Q4>`GAm&9`*onvyP3PGQ6ORuB?3u}m&sbg#j(6W|pvWEjrE zM8;w|7MXUh6gKx(u?1*yu4G^51v9U(vh2s!P+Iq<|iG5#*(ycUppIt)FWB`n8b5rn{;)`^25*1n-?! zt2)7@sg=@@{0Isr*?MFk<$0AIM1=;N`onyRd3~ww*U|X&;zhCMeMYsllUM zQbb7q-YHuKa@`Ri_|;aQuwv>C3|Em-%I8wwYt!U`12S{OIiqG`QvAb$0By1aYb($g zDGg5eK99KP@18OeDG%HsSAf?|wChdaO_-cnD%$T~TYN&!%K94$n$Ci!t{PjBo%wf= z=#*5pt3M9(fWsgh_~Wn<;fT$>9Q56Y_{}~ zd~Wf|RgLetP&d7g)}jS@v2ZV^1ADdATt0L~m>h3GgnGA`VN*)vU%O)K!J98Hbx!JE zX%ZyGG&+y1PWJ)$cv5R3eSt9&f$0G0mA5< zlN2HoDVfJPX3I1R*9<1v{V= z`dA#^0FwOs@s4&k-=Yc9K1D&;85Jsi+q=IIpFb>5V@Lavt)q2* zzLSFpx4dw_B(~}FnM&Dv#87$7w;JIXF5J=z|AJTgGDsoLV@o%{(T9YvW<#qmG!nLl*x zQ{{13N(6)KyzcQVm0vC@HQ*1nNZQ;(KlKv2xr_j*PW9N<&W2VzPHk|jKk zC@tU~+~mCNHGmxXvzs&#IsQ#IU5)D9U&H+W zxbMk{cGV~@2w<$R43)cj*iL3JVEP<685zK|9~BfCGGz38vF6mFv9B%H8qP(p`OB%* ziE0TeX=|?{A_xdJB^VpIFO4%g2WRx-AVs7N;>MbAMOA-6FDGM1LfuJ>2LmW*BlsWi zs|N-EzmRAOdfAwu2+jbQ+Lp?g!Ai>i?XvABZ*Kzs^>~WjKq5@Da{v^HHxm))s2-^0 z42S|i1FS{-=2Lw#AhErOcOJsjo9ENbWTSHV%3&Hz0MuCp@lO<>1yzG4dm1L<+Xt3z zp56RL`1<$O2EaXEZ3ap61~}0GGy6YemxY~OyJ~r%L|(b9XQG*`Ct-S8u4N-DE6eA9 z=CZp5olvY%{Upj_@Hmq4Utliz+*|+9t(DN-4?7#%|kpDno~ zV8gWW!&Sh_F}Vq=oO{wNqala)fB_UoY?x3y(!vq0{Sx9|#B1}9sd_dIH{@q~jiVM^ zrn(E}1)M&4qXB~e@&1Ca27FBXq|9HZU!S-}0srpgPCQ8K0Z&fNijQ}`@my!brJvx_ zHE8Mfd`PYkMt;!vS|0t=@a#XBS_dESG*VbI8?V7VNlckH`@FrY&Z|3-<>Y(^z}Zcw zMz`I}RQz;aL)T3gx9IC~r6U`k7k-B4#}H-lkg)`PYjBF~#=CxZ-Y7W$BZyKrQKT z#;DEfKt4xE|Ao4TSNsn9ql~l~GybZ^&F%o(`A_ucsw(qf)2Xpq!}Ja+cHb=APZ=|X z)P1b6dd|7}!Z!GQKr|wtrOZ+*3jPzgkA})eAauYK%%v|*Kb2KWh>V|ce&-Ol3CYgI z#noSj0VM>8Ox8-;sVK@8BxhuP$3p>xh>3BLB0m%8C4eiB3&+((S`t;*wDnH)yXpfE zEQ&(i>Eb|HOHX4r84-#`q*_l?xyF9nl-*;0@p24T6;Qw60mwH5EgaT!*E}~BB-jg) zmDMc(5N;M-%RzepMC6%~VNi2)X8V3wn?x0##(iJf(_Lri9@K3&d#6*!mO$}tStmng z{;|8OQ%T+JB)dyLnDlWB{s2oBM#k=mRzME&;!MDxRU zQq;~N<`e6qpt#H$`{G4GdKF9TCu4m;I8@oFJdO@GqYlidZQm_gYqWg;7c;e#G?O`B zpD~QT`EQ7rY}r-Cx%Fat%i`IZ-_~6EWr6PB*^O1QHnfo!^T8e!LrQoS0%t_})D=U6 zjR(DEORE90z*nW9)mx>OmQ^k7t$9RTyA0tbRqEzO_CLlnYFyj@A*e-n7sxV4V2~cx z*~gW3g}f#!EGyJYo>@O@-GR07NYAc9TPxv&tz0CzTeCEZd*kR6>k@9jOiKiZg5(ZJZ%YC3ZvgNx@v1|8y1Wd%PN_Ug4IJ3_kZO5>A4q1Y7()|>vKUPuD@^`Lhu zH7LWD723o_vmQ#97!M;CvzJIAY%W`}Wp2@`YjAB@eXVdlMHjiYSF7hRc_D6IQLc5J zZ-{Bcx3s0pkv*U;!o#*rEfqtYRK}ymAGcJk_=tjw=Fvo&M+66RK5v=gVwo7fS+<-u z#l{mNhz<&F59v+=jw2Q%wzQbb1QPGgQ~y)KmR(S&d3m|nifbeJ=hERJDV<*OXhp-q zF9o(_%61Ta-%U5Fe;M0xTM+dI{@5Rh=~4ThPOYigNL81{M8*#R!k+g;as=&h)HVpd z_q%i5F!Bp`W5s?6bJwSBW4||6$B|-EC?2d!EGV-i#kF+|Iz*;Yl$*>A(SxYN6x7S6 zC$0Zjl;2$cQahb`&1sl7mTPBgaYW1Q!7AtyK`AjaIn(2FS#Kfn(K!5Wz-r>$v zuJLnUktXI*!^7%ufm^Sm+#S5M#rs4$`_43|>40Nf+%&AE#H%m~SLTXx8v%SfA73i0+m?r2d}X_Y$=+6&E3;%feiq zu}bY~C^?CbJ?dO>{k#lFLvecAeuV!-X=M6aVIxkb^Xn!Gll`tOCIhg$Ck=J2hlSxD zo<~tift#E!lsQmB*N&H}2p6aCx{`tlAlHGiphVFc)Xu-C)uOI(-93t5yr?a%@=l5 z6RF)@X0{|5LTwJ40R>dN>iTM>V^Ziz;UI3wL_Z4YH14+xkOiLS78Q|;zxch5f$&vR zSZ|oSp81l}WIW}`vXF#QwoycSn+(KtQC&VaMYnV(wA4R!bT`b!)e*r4#gHW-15hN0 zyILffx}MXnWg{CU3DQY{cD_gA^shSKr+J^ZpSRl%H@$LR1Q!aAOHBR_n+<*{=o~qN z;Uczkoy8nYA7ZPEDB4V+;OaE(wgmw+ z?+}O{KgT)(vX?EaUzgV3GroPg`aa)VbZ9I% zFC!2ola%Ltl(f8R3hiE24`X&P&DV6Z{ktEwTh(7T$u2X=SMM|Iag%etw>FYiZs^Xe zDL&8F5N>xZ-mg#H^YcOYJWWcP9glrAXVJW|iuLEN0&B6lg`|{mzCO)~L8gL4=JNXU zxopdB&H;MI6%@8nj;Jmc+T2rcUCk|>qvZP_kC{?1npmC{d&eubK3nO&^oi4M^xv;| z6g0r8To`^TS!r_%RRYx2)gUb}};Hfa+&4pQe%9iDOMT=9|n!8paD(DfG+ejke< zFkdgi78Y~xMRs>to|j{m%>F}1HXa?+@7pE(RG)8$Ju|85-394@~vAATOcflAXBo#$2lo$uXuelsYHK?894hZRn9UVZ1%8)xtu zhT=Qy$U85H%Yra}Y2rf4KM6wPb!H2WDFTy3tWRrF8#3SxF}n zm&oMgrA~z&kBzQ@#<6s{_LrU- zaqC@pcFtJhxR9oE4!Sd~OH4|b7d2$)5mi0Rn;c%!$epRftpEvvX& zl&-eEa@GD{(%`c3_M)=D@@LqQflOp4bhU&h>>alnGIAtVvdt8dVs;Db6B|>!p->LC z{4i88S74QMmiW-?HfTIAYbZX?q0*^>7Sv#HX(+H6eQijjtbf5Dj~LX*eADP`>T z!duX^U@sDXL^B>OOICKC7wOpXUoQZ3v)|2aNm%;jn?BbA2k1{KcuaAndK&7~5##hLMi|Y{xScDOJ0=q*xO}GUvHii4K}5(twPY*jtTjYK z(4I*JL>z`r~?F@nUf07Zi#XnZtTg%l)g zkD?>i~eSZJ|qcXx`N_@ z5#R*pT343mgU!fNhUOWoORMLGAtZ9Bb5$!Ef?W6~|LHK1JVz13_CUEH(qS-@49OKo zO9Dcr%6L(hrPk>r8VpCt^C}C-7bH@LV;8wPLGu|)JzpfnM~`IuE|+V&yK?z|-oeV9H( z%STxCXvw+sfBGcu5-Bog;YNdYZ#jhgPgb-Ms8K%}*LB#!mPd;gYC(Ad1R!^zW5KA((=*u_<5M@7#x zc}lNmA5~EjSM~Cf^eMOpWp(4qq38A!b1OZ8l$fJjI69=?@Vo?Grq94*Q;l(jW()9t z-T*&bh1-)@|ulzc-cq_8ZHDKnxe@ zB2#m4!ED`9cv_$fYDz7W>erMls^Q(s_By|m{_Fh7y&+DPC@h$V@){@oZ^OSdjU1w9yoA$MnhR@Xe3F*7S)d` zu~6?Y@{F^-WAg|{%EE<0N6ACW|GGPtv_uYW8WU##!7d|I#^AQ3y3&`cy;kkRPx;Us zoE$uNZB+luJ7@9UM>0*h1cE``O^yAEqn3m=ZSnwmm55w;aeE0yuh1Q#O!sogd^^3~ zbF6q|r;T>mdUo}qg!}ZzJPGR1hC}`@eNFQ(XF|!eA|~+4DppoN$5CvuNM~t;Dl{0m z0X6pbwY#LWDLRKIm$sYFQ`JCqxBv9V4MlPM{Of`h_t`=cW#DQuMa`cbrOuL_tgJC~ zdtrKgJj(W`vx9dyEBf-rSE1^LWjDu_Sf;{pK`-~6+cV@L^zKWky*p1~Mc?OKp9jNm zcbbrJr_4I0sdIP@-Mlz!%t#)fvb%frss?1&>vrmQpTaCWX1DV*RgbwX{%iO5qIIhr z4UD33V&5Kl{f|@#x31U0{MPttb`(r*-^U60p2wAEeDCKmUqy}bv(r@dkp|Pods2Gb z%`xiM=+>SrTmyTsgRRvl{~#L8?;O1M8+T>&?dt*L2Sn|!W|QeV6f%WhDnt7*iYr|f zI#>mht+T%kQJ}fM&Qf!hKTTI+W$n5}N0Kx@+TeY>g|CLr5S?e=C&+fl-&=O#KM7G` zY;BK*z0_)^r6GNB#Dx))x-PC#UF5qRFSF>|yD-ujJl8*-uO<$dS_KMB|2j9bZ2PG{ z`Eu>5C{{l8I?wN_>6>2jzbt?CEBpAOXGut`-PGw2a#tX|NLoySbOAGasL>hqIaC(1 zT+d+1H!yySor-d^IAB(4KJ&KSebMV})*nb}CM%?8^CQPb(dRNdGA7ciCp5bq@)4ol zP{=rvgkUdpR9U@Q36XHP&T;a;>`jFIHsNPo70>Z~zg!WM$5!nM){H_=m-&8OFxVRf zxRF5;7Q{u0WWLp3w@dKXRbGzfH~6{_dzNpqMCfYRQ4ZYz3;3`IB&CG`Oz{l48hK%v zHoN4IAA3BG`7D2Hk2nZxU&j{AlhR^K=}1Us(z8%#k2rL$mYyR`)+7yi;OPDExC0I2 zrAJ>95S74Fs@jh{5V=*+bVNf)_cS9+nANyFPC@#Hnn9T;%qL}Wb#_7BaU!S-F$xMJq)h)x2;Dke zb&pNQLuwp@)@krW0cMsD(RQxJ=28Hs6-O64P)05us^2q%;B3$0e9#N>Ai5Qo3PN-( zio&pui9~Jr~N7>Wrcnq2{bdE?c7w0uvpH(B`}vd zS_%`hjDQf!z#j3vX7K1fWQ2(2Rln*->nWNDN*Wp~aUd~47Hg$w z{B&lQ9-alkI0WyX_}%Cx$5#pa2bxSxEQvYE{@*{fNNr*LuKna^^^vX?qf7AicZ)jhnYJ6=*4C-DUsZZ83uq1is`d{X+Q)#RzWxx_5wBL3 zh=MLbG)#t#y=Tl&($TY{7{A7wG|%yA_I`Ej@$-(V&-S|F{5#xawPL$gFG_=UaI0Ko zs-UUa2B>SU(r&3=yKvZAT{YkEQM&gPlrNdydw3D<qPfx8{he=SXq0X?9nmG4DL< z0`$Z{hZr4>ryO)Slpi!{cv0{8ond|_Rx#h-)svekYa~;KHNS+gf7cYv^M20B+sc6v z$TjmJPoutvera{T9%ba`=MN4Jj;Z~v50EMXlo`Rk4ltL`T!Lxz_;yJZc|OdEkGPW-)bGcNt zkv$au#I{us8_YZUh%~D8eTQfa%D7*;q_eiKEo(zGc6Tet&6Pnb73G&rj=xJqO{o14 zx@E}A((aXJ#xVm|!B%8EG) z*6~!vhyeqF6W%;4_$w~s6DB4mDJdzyhmUML*8vUV_i>l!7Dwn8TJv^~uQsKh!gIt| z9%?pKM{oB=uJgHKg+3Gcdtf&&M-`vvLF{H$Ud-gT<)?8RJyIQI>ujQUl(%9lPU#N#P|TQGLe@t78IRZT#Jpff6B@3-$6jA9YC!Axz{;kvG;P93=MSFnz1IdbGMjuH zL#eRDbnNZY$BR~7SPthg7wo`|v{v?vDC|ygH4pgSI#lgdtPfZ46v866V@SS=y?&9EYp6wpaPL0H~2 zXeUd!q2RsVuNORfpxh%MPk*lQwcPHjffsOnPNWFuz7XngMR-u)?mhK~mONh7ZQF8k z^PRTW>JGM@HXTFf#})kZ+Bh`c-RIYE5rnWI1Bd9m92`$=^|fX-L!mELH=FMB&>>CC z>VDzJ_3q_yghcJPthZ2nc_pLbnoZ{w-Sgv;;ZxVF6W0@*1Eur<_&-obZ}{i5ax>xI zxx&{clxtO_##_M=U!xp4)78chtbwhsD>@z4ht8zNIPz5krdFI!w=IWFXTB?-6_5G> zBuM0P`W_33u#9ODY|SOWzu8K;foMI$vq2hu3mI{=a_5!7GEOlJ11;*IH{t}gL!ZnA z+(+-=e$MIvk-89!2XBhzN`Xg$S;F`GBRdz66g~%bft+FWi3JV5GFTB7QuS?vc3m>4 zvYm;f3FYR*j14a6?1(}=RP65qohA$&PamwX{F#tnepZG;6DtfB&I6+%YiL>!idC_v za919d>PIIEy4q3@CHMFidbWX zUT2BZ&HD>gYRxn;V=!Sn`KZ_9ml=ax9eic5d+uw=P*^xGA;R;rxgHQOuUw@*6@gKT zzy5<~_g>>2dl5Wt>Zd>B`1TIU16XXC7YL%^D6Ffrp6=ctE(|K=0S7H8gMiux8MXaK-~<-4Jl!rk8;# z&@DO?Eoiby62l5Bt(LfX=-Bbh-4sk5h{%B0KcK-rb{QX>;V@|B@YnVp+q=FJj$(H% zd8JXb3v)ZTwYOlwvc`-O0z*Pf%2eY>=Obh~XErSe#i&+Mco4nhVo7)c{>XD?#bbxN z10U0{8Wf(yLlb~Hx9_UwOeVp2;NbmaS1bCX>&~Y%4B}c7H<(hZ3ESS#;nKVJ2qt#+ z%YL@kc>d7}g2l|dR&(gL2s9@R^l3{Mm~wiz+${W$7zjiM|KmUv;7;&bSD_B%{>NRR z^$3;R27fsLON2^d!9Z**X@A6@^*`LT_EH_NL{#)4c5e|7L0A}Xf(b~4^pTx8{FnKp zglywEfes)l;XmkZxO%03@c)DqX-%BKJp>5O4`U+Sxn#zmQV9kWqv%qZk7os5J8!#5 zybx&KkI(1xW^d3iJ>RcSLAUx{Erc=h+zgOh+aE<9u0|swo znKkfQ&*87^Jo3-fh_Fy>bRQbK3|3xzx0x0V@**Y2CrSKt`~0-xU(KO>ZRWvv9a{@f zNKBZ?C@V2KCfC05EW(q8R74pJxzZxz z`zo_&B2^ro3p%;0`OsKwu=0jf=rel*Ud;P(o7Lh2a-EaYbN>k9%hPTBG`L-`FGbJo zHx`4EGoG^FpZl)oz@+-ymhQ({S}WVMVcZHOU+evy49DF7b*hJ>(HME14$HntEs?`B zpa!qPSdyT)i@h!SuE!a_%PMghbe+$^tFRjVY%JdHk>mRQLXZxyaHQS)AR7!c^k1;E zZGpNbj}Qu*z%SN+>affr^8UKKv^j9NtK!i3f(t-|wFtjsa+?t6%Xs$g2hN8V=2D=+ zf2hq`^cBNp#rJ_mKoJ-Stw~Zm3u>TUP=PpsnvBu8(%~OI1EhTNoQAMh&H2Sat2?Cj z>y4eXqSMOjOR5CE*Zp#LHd7S#vfkaES!S?fSpo%$=3aygrblG@-_xfs`74A*5`rNpdg%yedgS+KO{3lF=Xjk7aLy0VX_ zsqc#}xh4j@xu%*SOItVVH}4fQxsmC(o|ep2pHl0?^u=9D5TI}R&-J}r8Y;V|J6@3s z*^aT6opiUy{DBlUp#m*7YwHGI~ff|dU_;myVO5l zKzgj%5CoJk;fVawc~`5iYLCCa#O@{={hKOpvZ`Flk6ky>`VcJSnt#!JuWeOmoxp&u zJ5RQbR@iyG;YZp7`3#;;8L;Af-ZZb!0&bB;PUfubRiBFn@?KFmJ;1S0Z~FeGSeX9& zE3QWC**T)Hvfad^b>+%g9@!HoyHl<-bn68Np$bh^SoM08i8Jh9!9})DIR80dReMBp6#W4yBC&sHZam%NzJXsYP_Dg%1BjIVDtUe zrronjeExMb;S+-2y)oZ;mNxUmU{R$XvpBb|Qu=nZCd|w5e8uZGVYZ%U`Mkn)8G+^W zz~TK(CoFU&BUmV~&UNz6!GX8!4r!#kCxPysMCe8K7dBQYB(sxS8RaPYdqjfb*LGWc zBCHk&OSXR;cCT4bva^ET*d;}>{!h!f5-fKl;XE0|Ps1^<@7K2^AQ`cv$`om1uu3Qg z5Bu{=%gUMk)u#bq*RlO9qo16G&zUN6Wf~NsUG6Qvavzx?9`(w%?vuIq(t=?EmB`RMzcmfgwK zG?Xh6L7(7+UJWSTvzdkO(agC2rs3hU7>>@gPzgU7U)9__xx8c)LKHcq`IEs- zt7XQ_uJ*vzvoxei*3q z4>KAQv!Fwa#+2R`+}W^@Q_lEANSZqlvcFD2?HHCBy`=tyn}#zSPOL0<0ir?nZz9DZ zj;}$U!?I*5R9i3_1umq|4TsVo^hDYYisn-MLb{H3Vj0j**K zIkWQKlgG6pZ6en}R){?s_(74=c<$+DA_W zE^y`GKF)EOE`<8$gvMYs{fP}7W$A?-X6`Yq+}|W|xrkB3a5?a{3`;AN| zjh7&>`XEP%#dJcH2~+}b@17u8srd-Y_DQ)b2h})7%hBfpTq1)W!t$n-Q{z=ONp7&Q$Z#nz5es}yaU*q+? zc{h=6?{p$03A+KW?M!ZJ+LFh(3O}Cl;>ji-98fKxG)z<FoPQZkr8U5$|0`-2d<9_^E_3q>^iCPX=AbD43Z5p`@m{p8a z<&wEqpF%}ZurXZ`>(VQ})`6)3T(>EWex!N}172EYli2v+e?04S@1gwFtz6=w*faGX z`pT5%{)O@ch;>p+A0MXLHM+fTK9$u6&;fnmO~`MaKo(l(jRvkj5l}>AyPXDXL0dmX zEbXh>3@J`P-%fm-MNo)lOTzeAIWP^_0=Gdqz{5ENQU$e3gM(!hHhPbLrhB7d+xzZD z1c-p6&tuugrX!4Bqc+Czl|hQ+>mlE3$o?Y}xc*A*TOUv&-LEXJU&*$g>3V!3b!`92 zx-<>?lFQ3efYLGS?@r9-(?xf7X<5E}MMzB{K^+Xuq4)4qYZV}{;qlCujq;Wds5!5o zSVJfM3+J&EgA5%)rQbzZ?tJ~VKa5vTrRaGi5IAr(_pm%9B?(J4v6yF5L0bv3qCwq| zpj|{{${+v!&dN}FH)jm4yY-4Fo-`>R9bM-H6~?!*WaSop)FI!840;zV7PVo`0&#y$ z!}}IAQpLwl6eW7_9vo}ea&38e(H7q1g90trtH#!?t~9T;1{Rw=y{wz#b6#69f-)qp zQrEeB^+~#uDq5vSq@LN3Co_se2qozuwfU7Fn2yYPaFHL=p)?JCdL=zTk{tPu3;@%3 zApLeHiU!34r6D`30;0$2{1_Mt^q>*`0HOyY4wEPMb6!M)5uXB_!xQ#QYdA49TnN;Y zcUA*tnQpc;Zvny`RRod1H96SGo&XIb0XE(Dbh1Nu`Lt8RmSg8pB`v9@K?65M~`vFuC@hr2_IJW6$`W*JVI?G^CefscPi4ri%bA zVJxml5!9`7CoBHxoQ<4ViE+(Jt?Xlgc%k7A%)DymFnEp` zee3J?K%eL1bR&}jEdUV_{-rLvDOYqxpW}JZ&)4_1crz}6&O(hw9pd&_97naDz;ua= z{ObIwM6Jd%>14=oAAP6UXkcn0*kS>#rSo$S_nXuEa=&7wtChv^F|_E}+Uqp$Ionri zcu;JdS(gAVFOG-H>J(ppj^}9{1l|V~l7Ls!0qMJ3o4?(ovC4@9R&5*qyL&%?Uf=uV zyu?HiSW;_Sh5|8;>g+1cR_+icktmHnsx$^-;M<)&+c}$9@B~Mrm6`+q>aDsEZpbiRrKrB%KcEB;f=r$ZZZpojvD7{XV-v(AKme{Fwsvl)qyc7iUOcCxVF6l z31lI6IGvg>JLugcB70;1EO6-+;27XPib(y+1dcyxh=e3raojOuk$cx+_NWQ1*huQ> z4LNgl@N&_7F!B^imn^BNsf~?|Pn|tSeYQXX{8!FxY-}Fgd5|JZfR#w?LH|)EFq*^V zND4=@vv7z3%0xA)8%%$F(qC^lzhxdXj)78yq+8;GObK{tm&XPn*K(Rx11RbKhJNGJ z>aOe(%j*^fk@1twReOLkaV(8yU%E>^IHh$9Vb|I&ehnNNj+T{yH=U12?^p`%p|x*j z*F6W&AA+hq-3`d5dv4)v*}{TW4Q{f!$IX>$*H*T=NCjUsJP1og4_K^cW>Ajvj)g0bmkRsjJ65fP!J!38i$jT$L{q^a{ulbVQz&BY@bD-{xw zBA+z=UGyl_&YH9N5x$2ySUhqMDdMRyeJKx`Zu9w9!?Y7Y+6e0IdR4?yY#bT`Hc$jD zkEy|&Ad&KA(c@e{+*E`ppWq~cJX~I*{#4I8bo~m>Rt}klnll8lq`}WsbbnOoHIdu) z0Gu?bRYy++mf4!jiHj&r#x$E=N{DdZpFnm}zd@4CijQAhj2LdYM!{7pW|p%bQS?sp zyyltg=;wmof_M0h=atP9cOrjQ1soNB(MQ&K3O3H;L z6E)T?988c%gsE_ugsGy?qxk~UK$*xy=s%p$6jBHxfYH#3s~|!U8H5nN@9bv@UD@If z0+n|MqMjmp6$I9iddUMfU<81hL5)I!atw7&g5#&bL?IoV0JSY3zYY8H|Lz95V7)zx zaiUL_*a4+?Li|(Umn@dZ>n&~Z2;W{jKW;IxMekX ze|rNoimY#JAfAhmCDpCYiosD*1oibAFyt2$Aa3yMJ?i;=x`YVTIUbJRZifTP+M)j8 z?Jt04{>aEkBxGcA?Su(%s+4v>_X}iu-Pib5?MjV)jZzt&&%>O*24uh)|dsx;3j z!6j0m2%z}IXeDfTX(leH&mdgH$lIIe&YL=AT)LY0AB#Bjcxf)$CyP)Xf`vA%ZoBiv zuRnrxF;W1^57^KFTEPr()AGL`QYlZ)SpQ4bp-u``mY3yb4fl`*)YVfrF6k&K^OVZa zV|~Wv&L1&gk46)Sld2%0p`{>a*&lG?>Ca3m{F&g$dh^v)Rhycd^*FXk`}XWxb*ceK zKYn6{47W-xs?pcEU9lMtK;_d^{{7bcpY$E2QT-O%twqhQP!@W?nRNaBe2#N_ zTrb*-Vc%AuK>0s)f&%e4xn?v9^a)T6qYHu_-RWS4zw2y8DqKnWiy8kTDfoLr>+9vh z)BWc}r1Yv_(&j(|CTMnd^TmiAxORX9AdG|)O{wC*jhF!%@)^UN@@yIbItE~)BPJpvBJ_)ErlrG+15`Hs-!y}%sj2^qW)QvvXy6y(y5;2LOx2VB&&iDk zJdyr&V2UDf5(Pe(;$u8q>TWS@bmzxZT*vvCy5wjxQmdCmfAvQ2{ zt-D_d^w8`AOR-@)A8Odc`rUg)P3E|+XHFOpPrRR#=w#l@k*w_1nM2eh?@ss(&W26XH2XKfZSR1oc`=Yk z2ClUP8J$S;cnbZ7=I}%r$A;j|39fz7k_ZpfcL8S_PXVlN!yGtp{uL2o%%;Nx-mY-q zAR-Ky(#VL`rq76DQig&zvDrj~taSV8xX7d_b22=y46}s)tjAta({VYko;2V>bo5=p ze*JRLIDh)8NI^>I;1~$GWNqqfxs>?OT_A!zyC;oOB8nm1_-esKc9Hv6K=6Y9@#h`8 ziT5XOF@xsZ<_is6e5emKt(^AK7rY-0MX&Vh0&LISWL`W0X65F44gH(_!ot0|ZVD!k z(qn#?9W9*l!ZvzrVk%vPbX?>My*YFnCGzn(AnqZeCT*v(+X{poQb5K5QBT} zkcpnCqr<=eo!!6!{F11G29PV?WU}BCVksR^C5Br0aOVVm7pLKXL;3RR7?b75h%ZYbdGaX>6eIV|#b=_&q85Qlo_xyzfeh z3ay5pn#p}@B|;cJ1M;Mc7k1^pB7!nNMA+gL=x>EW-okfk&D0%&01v)}scy3!D#t{e zbl_=%ORZ{q8Q?W7S^S)aQiCz2sRaf6F={lqUsVP}uA5NbYu7dkUqbzw6JEp_)d!D| zvUdUXnhzDM;Kc%n2w$*GTRG$FaPH6rP@vi;a?7A-3X0?II>0Uqv4?EdC=RnA7yA_96o9Afj;| zTYd!n?2@J>=casUAl;Z4Pj7&7={CjgFA_qWwVuD}H0>r|ZyZJex*548u_tBW##Mh; z?qcLj5hL2~J6?u`Oz@K;Xk5-@RW2PhS*^+X4s)NUMn$gfae3>F+UW1t25C zRxD&WGx7#EoZflC5rwu3&6u4cSgNC@NWjE`JfYT$%dS?uJdvtZE03j`LX1EEt0Vk6 zxm@PxMgKt+CQP^{(}b%PH?+L<|1kEBL6UaSw`Z4a+v>7y+h&(-SC?(uU9Re~ZQHhO zYqH;a{}Xp6=EHo<$b2I6Ihk?tto_?-uepVC#8*z}6uUghShR3VYizXRM-M_CFpU1F?_EpYzaalZzhLKK_C7}4GgEo=Di zwMFH1U5kTzgaFl{g1N}wWs4@*hR2Ma$Q8ibjv|TNj0$7%NTaSyfUE)0I#$OL*Q{>z zk{2xhVtaJfK4s*=_K$KSN^sUi|D!bZXD1w}eew#o2Ki7ZV|b>DF%3>a88H$fg+*w@ zAi-PW0Ol}^pJ@k)hD+JEI}@kBfCP#NiknwWH!+72xpu|4dcO4fa)~pb00K59jUG`k zJW%wQUBs@@};uTU<{I$TMj9&1hfC+amstm0-7BVlw;UJU4x!7AKw z>AVDL+=E!f{OM5qDT}|(6!}iAvJsZEJ_IJX-%#)fN6)>$PjEdD4etC+uw764_Bd=X zY?u@GgM83)iMXAR5F>$DAd4S7l{eCXSV)V@Q0_b;L%?uIWS~??Z`k?$KnqPXP>oyy z+rX~WlpKUfAXA{wd<`sq`3P?vJp%kYlxF^Xh>78@0bJ0Ml+KceV8!p?NC3>^l_Ba zK6+wOzvH-=1B&f_a@@=b<9O)b3^gO@HVGjWU0GDQ>F0L)Lap83tWbVMsyd6P%SeS6?Rr0nnxb$1xDMU+ zb_Hgn)Y14Hn+nCCk!K`{r%x)FWd0!`*cm9=e4kFSZp-N-&X<7b*CnZaGqv|jlC$FZ z$O;AG!oBTlfB(+fi}e+ZL(u*HMNwA(9yyg}$eE9}M>hZc;mgcTp!4oJD^LkkmS}RG z^R+jNWu{Wv1Jud=?RIaak6V5Te@3bKId&V05p{4RCRV&Q) zFLYoKC>KFQNdYwy#)sOxQ9vzJ4zd+AKLo^v4N~somQGVLPX}Eldim&ia&`ZMMpCNp z49g)~`^nAJqV3F+OM1Z9+g6k&lWEM^nDFIV1_~1rln_yfDQ;ASPkZ5E>}n3x)V&b1 z!G=uyY;(2Suv~2l#R=8Phm!wM05_Oyz{RowWSG&Td3*#O+SGi?PvF?ZcI)wpt9fy8 zQ%CFZb3ON3w?r!q@djdH5?wj-v)G3FYRCEF?Lge>^(uEqy{b1d8vfXp{0u$dKKA%+k;eC6%z4@=};S;?c;+!N0cCI`Hw+vSQvnhQp zJ2f`OO)~iW4Z<}WBIJvBfWJV`LCBQtsZ(rsN>(a((_Noi^HMR-{UAA+ZfT|Y;tJn3 z0CI$h*e)^|lBn6ey(>eL#rlNwgUlgSe4F|jPi4q{xBm*P|H$;>`>rwumq$XPj>%}f zx$V2Y5_~&(6z8k9e7E?%T9kwd_GcCePwsdF@qNo1O0s`!kEM^U(<;6WW5v=@ z{A2mFf5B9)3du*30JNu;&a@_qMDt~qrx zMi(Kd(!9T6wS#Xy8`Ie3bN1QpcI{b+D0Q-{(%@HjB!1g{V-PG^sL1gRssP1@Qa*S^ z{!0P39(&2g>kb~)>W7}Rc5k=-=Q+ZF7XwULSOU8G{Cc+4_4j!Q?02{k*kX0p{bTK6 z^K>C&@mL5#|MlD|KQdKZ6Zk@|fHw#WUcd?q#~f6S$VdhdXGHHy%Z_$96dCjsBF9Gv zxR@+tBv=fl#HPeOL0hH(rr(fW4VS-n3>?`t|N^Z^j+70a{cvm`Y_s(#J=?JgcX4% z>NJ3(B#Ru49zaE^zCWk9NEa(+QFwBdm)&258C(8zU@)Go1tOSV^*9jlkQL8t(w#3S zBIEu&WndOKv?pdfJ(0;KJ0Z!osCLD^z}9?1Nc8ZWDRUT>gvDq`oQV{ViBhRzA3!oo zM2eG`xe@XkvC0BCaf-j9bO4 z9a6r zwy-LARgVG-$L*$)aj|(x=E+ZD)B_esn~J1Jg~^a*⋘t$QhX`J8q)=x8tnvGL%-L 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

U>3WF9F-G@fvN6~RknH$}+xuH>++;7L4D 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℘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

FF$d@4!M6+}WgEhwx&^aUf+6*uAyEJfOTa4)S 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 literal 0 HcmV?d00001 diff --git a/Images/General infos.png b/Images/General infos.png new file mode 100644 index 0000000000000000000000000000000000000000..f1dc3422ec119985943d9c278e8f8a995dd9d4fc GIT binary patch literal 223552 zcmb@tWmH_-wl!LKf`;H8AV_eR;10nZf_rdxhd|-3!QI^pmtchicXxNUul7D?-*fJJ zKi>D_t=4L-wr16=R;$lBr1vo@R6$Mx1rZ++005v!Ns1}~00@2n04&!#c*w~9RJRD^ z0_CVAAq=P-BRqiIz?uok3IPB$(MZn*aFF}=c9NQo003(5UoWTu+hSt?;H^MPR7k~5 z_jm(=dH2*z4ClNN56i=MkQPr z_BVeI>6MimU%6j`hj3wuXJ%&|acPzkr$eJJJL#4Q$||}@WdAyHk@WMQmK3yXzp^#) zqoeEiR5a{7a+vpP0#@5C5nN7}OVS*ZIy(hyI=4{a{X#?jJ}T`;S0v1j zUIHw)`H|5lR7)Bfwbz21>X#qtuiExxMCbBpUwZB>Y}2b^8Hug&p}%r-<4H+Lo!?yW zv0~vQe_~-#YJ&aO&-&-AV`J?DU!9i5W7GK(#i~3`%;$9W;h#7E^#F<4qfqO^!-(74 z+v%y_z{CH~4`g5wVTD4qL+ckQa{hw9LFo(I@jXat^SHS_`q`P>kcrwNQ)S}=QpeFt zgXyA@&+H3lY_~IAY;%u4&A8%p9b=6|Y|DA`zV%IUzd`}2%N~);x6ha?#xLvjZY5pe z#|=zRKR1R%hfmq47rt3cs-!lmaX6%|dwbTu%~tsq#G3#3LR6cMJhiNpM=@p5TrT6N zHFSbsNqaO@@cAmcq@G=-leG6CSXucXX^A`eIcA$#$9nJmf1XiMqDU=m^Qx-zcj-;q zku2?;O<&*8+*T~YY5QSdm#yzPy6Lz_>F-a~Uh)iAyRBzOyV_pXh=6EfKK!fQ(cYK4 zwdmpDZ!+mz=!|XW(5KB?s4E}$tqpPZ1TE}^x+HA&VwsIthtCBhQlsK*g z-m+YX_`IvH9pY{bmXbyxP)T!nKgxJS6QbGHOnm)7=w+(OZM_C+k%f{;#c^nLcyefO zT73b$K(`*Owl`lxtrlJi6<$@$>2b#sYrX~xc>NjYOwZS>%bIyjyxyT}68XBJg#vvP z*y(`Ra$GQJ0cge-w{y7?eDe>SXtLESR-w6ndNT5JTN$dNEwzjsZ$TXvEVA7ji-Znj zHC-)4Dd&HgCkJt>qv16t4Dj!O>_ObqifwPVX^Z-n(#8)*L+kCx0jDU4lcOb71`2Pl zK;rJoj3wu)Uz~4SXbl6TO^ib)_m3{1{mv+6llWw0@7k_Q-=?acTNbd+-@pY7Iv5 zRO_~OdYlL6a-QPFgXPbR-P$Er+G5oR2KSKfk!K*s48ek(4maN9nf#iTvK-3Y8WRah z6XP5GU5Vb?1(4*=t91$*3ySQHxfXkquaqxx+;TL3Hbe5vcrt!rUdbh=cHxG?5KCn6 z(o{Sczfj#q9sUO&FQ2m`11d>YzyD0I@!67)NbtVyOf27c{6`E3v}PJq+r}y59w=8T zmE=Pn6=w}gF(c~kW7kIl3Yc^eCH zGqrG(1pfA1`RT=E zQqAaI;KTbfnw_g#B-A11;b+$(i?wLp6b39?ZSU^p78b$>1qBV_R1q*J>!=|YD1xE% zz3nOr^rMl9hYTEUjMt@a3#ZXYmh3_ng10?ceiZ5HvLJsLzB5^udFwb<{SqzlsO zjdr#?$;?r-Q9}?n@Co=dbEbalmayGv@@xC^+sbtH_@fy#0V*GTbgKcAjDTpB58lIf z_}lB(`;$4=v!NHTev^Tn3jEb|FP`t+)cE2xogPT#&L$%X`o1D|fHqpo7x~id7rAE~ z{%))fmo;8W!a&7ZaJq2^2QuVqlgrPnOI^1{S?kT&Wm-q5G+!SblB;%H#?5eTT2`yk z$(^cxQ9)Mt(<0`JJ*c_a{O!=)-P00WM!`blK=Ro32TjphlEElN&%q+Rz8>>rE%<>J zW>FTd&}3og>x|t)(jbS?^nQ(5lyoK)3QQY|H%sRYxbJr#TPfPV_WcF>&6YhGnT2ny zw+Vr?sMF1atD(h_6FV!5#jBYJB_(BXW$9%5As2FBS2F88Ej!+K0sBqZ-I3I(A0Ahu zoQetxek8unHA8otR`c0Q!r)){;*Asz?!BZgTKI-)1bs)#ExLc?;Au_%D8-#g2QTqt z0oGdLpm^PpeXG6~r77dU+FHgulri#8!FOD@M-&tW1CpvxrpV`*3B%^?=B-<7TiW%reZoy*;-B=T{iWLWy_d-iZ33m)kmttEdaXw-ynG7(gYI~wvJ_k@>jTIMQH6s)Je z=9?nmUjvaYq-kae)Dj|lmT?fC&NFqb#qG|<@66eSnD(~CnkR$nF{^FRtPft+2wN)o zbuPVZ=7R@4Y$Vr|7pwXIP97!_{qHIuNM*r^itdG?{CKk1duAiNU9jWY2j}PlG;+Ly zZHW@U1$B5o8UD!@GNXL>K6ZC^R|Ua^gM(x7CZdlc!2$QcbRULQ_GWb^-oH6`{Ht|X zT5Id6-VFqt!y;)RVo%2b=az%OA5|R>x2e45xaZbkBl0iRv$g64{E{9GQwU8aF@Kl@ z8DWYXI*y^r(Y_A*9{FngQBhDFo7%Is>|P7rt_HK{-7F;@5zK12r#}ih^{y_m6j!48 za5Sv`p4HA)ecjJC0Cdm`5dR26jsj;_@#~;?`ZjHQ`PvEnZAaEczLfbs|4I}s%EmHU z_g|fzE$>Ixg2!PyrVkPP6vL+zK8uQrTX+J1KYxB=WR!o(e5Ta{KU}^T>r_pIg@v(# zhujr6+mkY3=wMh_vbiAP%-QiUz8990(6D*Ku8L*;GmH~T7LaBrJANbPH_DLy!ry^! zF&SB9=#!x`AEAkY2KOz!Q<<1e%@gE*7n zEhTNX2S9-A#98Zx$K%|dhZT#!Hq#%6d$R>{jkpIRT*<`vV-&h628aXX-&Po7VRB~< ztaNxo$zr4jcQ%kn4_-;ZH>2Rq7VKWu({F=ht@UPag4?5(9Li;5kMQ8V(+(fj&bbFK z-4-vm;QxjN#Dv3wO#OGVrL)x5?p-%L@y!>ea3AJBO$G-Lct%cC`EC8xxPC_Mh_=uY$@J7f^2TGIKy)F08+KrfDYl1!x!y!tr= zsd3;jH{I1L6NBRns5<1Bom zaIX}a{k5*u9pwbGPf3S$q^Wn8&wt`~7>_I+pJw9QZA{Qi`P>O*`50RaGVwEU=wp|X z$3M)*yH7FkJ(5`0yOfVIBYP1PipdvBWOc@Ai{JKB{)KC9II!J2G=zb~n_#3dC1fA} zv#)GPR;7Z4vNGW^NyJvp0KTjQDv_wMDC{v2;l{yE5QEPvsDU9KX=HpipwlCn_TBO} zs~-$B^!cJ?RWBre?vkEAX;pFLAKW_p$2=Zw(= zUL4|($v7o!MBsm3gTbq*!M)hvJCjecZyg3zD&8@&W1Ps;?8aQY)#=-H);o?mTDfSb zM{}`IoZf;mB!r1qX^3q@ys;v11gGk|>XuJz`M%gyKHhlGR+fxXc-xkiG1E+EH}RjR zK6yIe7v>mLcapY5(fMiyKl+u)0FgEDZS;t<_`Uap3ndDr;pxWJmB%w?dXylg`wbUzVv&1U&ZQ3_KX}B~Bqx zL*vZL+Tz_0_v1?mz@y3bk>mS)jDNEO9c$cY3bI^U_IJ7gX2wlz6}fORhj(no_A>(|Dp)u++sUsaYlwJfda|TQO-xR-AhXZ zf6<>d_pAEx`^0unf#-7(>+`$ogQ*l26U0-{5d(x`>5rvzS2xv3*h?|<^75Yd6WC^# zi{~sI{-*L&83r6bzyeCFuiJx`J{ITGW_p<-NueU(UQ~lRibS9?4JHCY zX--d17x$hHf!;~bFfa|u=H_2GAR+#RcF1JsYcdUh4w#hKE@E;vAIt|V@!r4ExNYNI zBlS8MCiQFtukO*w|I6w>jIM0{IC{yZJ;R1Dtp?TJM%}f-ENPi+$d8F4)`R5OoXL+p zpghh$MBCxt+5y#*#n}BPDh^l;vQZ2xHrtNsH{;NWy$cS_bKxSWMYPP(Rl2oJRU37I z6tDUL|BAsXj(1{<9_l%P%j%>M63=dRbYuP4vaD%y;+XAys)T{AW5n=V?6zTAQ17?i z_d~dUSair@X~`3*b<2<))|vzO2#EA_EDZL$`bD z6g&(8nEt~$(a{wpdOz7cfx<51q4fVo4U&(szBqb4@amC~O&WPYQjPs#!+OiP%I{QE zR4ZUhVC=-s!>`hbANuCzC7v_2i{Ev>>V$w*`$eaH+=yMh=(a3jz^VI(16R#kMtH7P zbb7f_{(BAs11zWa8vRZ!SlHOP#l@0$VP8wHubps%fWSFOZn7?e~mC9qM=ne+uKjH^XgGhk4OqF$NtCsiO;rQlhVKH7bzM613QikADPvV%=pr2q#M z6lhM}C3}!$86G*&pBjRZvsm#+){abZh_&PTD3$s^U7S|3^QVBMZ8?2?TC_WZe$P@w z%mBW26LrfNU!g?cJ<1PW&z`wnIO09;9<1;yUW`zK1tyG}@dx1}5=8=S%e{++5ECzJ zeQpe$mwzp7ROF8IH1oOk-)lkwPAN8Oo*dsvNJzLv1PrYA1@GKnR=ydgRj^wm_A7+c zYdxU|b++pLMtDKn8o0a5>9YOY&(DGXQWki=#vGpG{va07V*U<(@sPtYG@U+0X1fS( z>rEV?`z_p)*~vlPX|~<*VkWHQBSlL=v08EVWJ+(nqOX;^*V6Bc_OP3RnL!R!Ax$HA zY>pyup?L(4wHJrN5(0JZtlQ}Uc(E49i{597F89>lGsDTohK~9*S zu|Y>k<*7BFLTgaY1}vyRDW@|TmtEPM<6VGhhNftFpr)f1a>o$4osI1zQ|KNUMs<;6 zI6p-9>-vJh#B}+AWvebmTcv5brA%0}1TG?Cd7`BZLz{?=iIp7~RDfk=Mc>f9MtgRL zgqV^NzUAoT9}eWv7DtsJnIh9LHTguY-ZV&|9{B5!1=D0Vx40fU(V_kj+^10zT+)D) zo-X#`f0zhXtwZB&hGyF`l6q>E-Yw%F`2^J2H6pukcYoS*+KacI?gBrv4!V`OU z4x%wKqR@Bf?smt5OsEpa1BWwdeIU;oo_#Ju2bLHOm53><#{G>#|4^kYLw7Hhs;F+` z?RWQKZI{*Mq80Z1JsoJlhUXuepELy%F@trGn#jIB;c{4qN_=mDp0z>54d>kpHOC4(8UB5QI>bzDkJ(jP{Phho)EFEP2V;yBF~pZA~uq0 zIrug>%bh~Oj&Mn>ynm5Bt(u)06Bvcvt&|iWT08M!;ipZEUs?r6>yYX>*N8-XlFJ2reuOqH60 z1K24`8datJbB3VFVC#0}T_n1@?UcwipIxCFV=0>`LJ&D=4fd__0BIK@(--qE)`p4r zvAz#vZ?8!YP3T&EPu)P_80!U?Mr=wlG{;zUqQJbPO#?@;ihbr>_Wd*}>`N;qn1j8B zFW05Z!2Tp-OcDAz#n#w^&f3XvZ*8msL7^o`8C0DK!n8?$Mp7txO z{@!Uj30jrUqiaq0J;v7U=wKb(6ca!@=s9qy<~mUi-J(F)ScNT4o>1<^BeV;SFw%41D30fL{7MO_SrC!mZ2 zyUY8T$?52OV6M?-%HB(W!qxY_-!N)6YSm3c!jp#-_eMr^n|(f$%49L=asGYKoNlfq zg3n1ATn_7)xkzD(<`&S7RsQ=2si7&pP5OI}8Y+e|(@k44xXu`c)eqkZ$gA;a`s$gmm zlGRDYgcgxM2~MTp4=Y3^mOf9WKY_m?5uz^`#XKDTELx!z z(K$yl5IcxzY}`+JQ(sKJKy2q!2W+nxe9{O6RBQ6e9WVY&B)HvlG9{jzn##HTxEBCS z9a>CxmTZv#bQ*D8u)- zzJ-$LWd)h-c0@dJfDA{r?VHWYNvsG6*V;)!Jg#3wQi}LGF!S@1!)~r(k`g0zsFv;S zaMm`KNOT8QR%Zs+Y7x_vXcX1#k&im{!slxNGHHyLRzp=9Abr&5EtmEE-O>3his+n5 z3C|8Ntc<%=2X!w=_5Kof^F$?%jqkN}+ufn>`KE$&g81pcH?Wrd6q26dgst@X%@d<$tg4!7FPs_94!pu2x~&0iV%ew^h1pqhft3b@r>rDiY`oH5_xNR`BJ{~`Jg zhK(Ms9q~#rjwoEY#q(mTJk4%zdji+{j`!KDn?dw*L2m7%5`v%D*AeK8_0hofEgK{^ zx88y>#(q_*PdpWf1^8541;nDS!?w(}vNV^{&I3iV5`=O)p-#Ns7^g7@&6dQb^z$XM z5{Vo{y5~2?5nVR7&PVm35t$PDqtBXd4vRlzI<|C1v?j3R+dWvtZyhisXf=EKJ_CB; z-MYHRR9xx$C0ScgU!F=0sN$f&#OKKSK?hspG4bS+q+2^0PmW78(@x8_U%1h%JIZ z=RHZXjPVbcu5ZlFVpTT$=Qq`HtoW?#fs?a{uUY~33|N{)6Q4_+@2s0%DYXLJbfxHi;$^9Wm<7&K^^f{Z}LRY)ZG+KF_Sh4h~q9i*PJ zP;Ug7#})6l_;F0Qv3`tf#>~CA&^0OQ5;RLcneYpLdUjsen(sZD*Eu@>{iW~y+T5B! zH?V38%md<_Aip)lIABr|GO7$#BCVCk@vHgvURfol5Wl#AAmaTUU$pwGBVT|1$Ut56 zS|C~yQU3;JDk?#2R45q{$yV>1w?CutSAGu|y$mU!u$A2Vct?C1%_yAXpd8ncZbuRy z(#u_#=QT4l{je&Sbd}Bddhj$+-JRU$SIOSWPx`XFs zCPxYVBE?0lI=z3t`uJ@+uL^s;tg54blPdTyN*<~}2}PQgm0GNTjfFwT-TX_~RjHzm zPWWP}MJyvF6ShhIq#93bG9qiruP_0`i_AgJ6W-#!r(w|J1STtvhI1!MRVc4V?vwe? zH)b69_Dg0TB$#hB&R}gN7TfPqX_5k^mZGnz!e0)Hl+<|0;UW?WnK;X^rRVl1ZM%G! zDqC$CbYI3XBfh<2Iuc{-_2_MCOU|^*|MwauFSm%2F`}|Mru>l6H`5M5Ok3S&bt9yd z{q<8S52zo}Ni;nS_6@ly&RC!D1_VbEgl~9*a_j8r4C9p0^{hTm<^*RbqSIJ==H10y zr0}}4P=-52oOqBP#2jgM=MCs1<1sdJy0i619w2fye57m=olz7pqZ2-p=kK}*Q|TE| z6Itn7$A#3Uv*izdGL@x>amA$SJyB5FfaX*`S=FM79&bc?j7;;3?FD8xmCd^dvEBA> z=d_g?VBUO;=>$}pQ&?w`y;;$%>wA6FG>01;LkFwu=8#>%q6RXmez$7~C4Zy%A0{Cl&zKa=x>W8%kjZPoF*|T||HTps_ zmHuqp^Hj*!Mg*-}qJbK1DmU)O?jbdlh6WVEHf`o=c_?A^ih0uNsIfh_p^fy7>Jx?B$;F;?ciEje$g6yCH@u;adcy0v$VL zH8v|>%a@wrj-n`zqU5)og%CG|8;!2|Z#3@C@Cl_@#3Bc9kmXx zxbs}aZ%|^HeOopUTV?x1`;ghvFTtGZpg=8B7Q=v=yLCmvuy4Zdm&{g6wdk$6-xN)c z;YiHXHNLA&-}HA(Mz{6bjpQ^^|2(v0VaOhisO=XRY} zPH<2LN_qK6jv8+7{5*1!p{BGWMhb3gSJ|G%^3@}<8{rdNxWF&qUZyANc>5FgsxDFF zv(f|da<~|AcnKFaZAzIc3zh<2zDSO&M47Od3 zHt2!PRZd&(c+{4Wx-%bt&V~b~;Fb{>OUIPq4QJAUjT3*r9LnMm-JrG31h5#pq-}58 z*)+U#(UVtyT3hv$O%05+8_qXG<>B*03w`3>7Af>ng zCzs6Flp+o;Q|57xPp3X_2G`|ZBUaYhbdx)hb$jbNN%}(*gio*;qCj7#RbEjtHlZ-; zWC-UoLLBV9T=5CB8j0JlX)>Q=eZ6j(a271%?+I4Dw$&~7OIdLoVjY8zu4ZJ zzxZsEyrS5))7+9qZA8M6zLPr$JJ?FsFYHi3*Vjx^%cY|?s8r}4EH+pa?Ur?)K=yCrPByx6c5!4-x9VHbHxpy6NB(6 ziv<;3zC^I&rxdFy;Hl;nmSV!WQxq4M%v6$QX*$z#f7N3Xn z+lrB~$nb_K_ssj+z9nRS;dCFlUAao zC%3r`TUFdbLo6*3zqyH-er{KR1JlL_j-mIM)g@Ni}a$gD`Cob~X&r z7$+&``%|@vqKyTs#^Nu_-r2{=_GTv&O;RQO3feX7DayHtMB5JPHAKyhON4hcDNEmb zN6xhe8G*thmKWMFY2+3NW=ocb#Txx{@JXx_Gtqm0>0+nz8XclUFylLaQ4RS>>{eqP4u+epD=5_zS6lqbS-b5b; zFyQ?6VXf4E`)N_pWL%gor^xEyIz4qKf@PFU(=IWBivOil?Xzrt_%m%#^FO-X{{u_m);x z5di_vD}?_xsefH8QODnuQJOng}VK-s_ zEy)*Wh>3}9bos+9ezJoUU69AVBz}WGC|((al(qp@1_s?AvHxC&=`o1u*4VCfJVIJ* z&eh?MjjJm`pzlpw6AyK@wO^HsMn*^R0H<9VjsHC>SprhfcqpG;T>QShw`ch_s*l=$ zpscKXqK5}ax+yIz3>IM6_cQh+g?Vupv~48%Uvt&!p!7pUZj?MH=gP{<>8#Nl@jfK^ zmKeqQztq;USbvzGpV#0_{_kgEfP?oth+{?ufV;8_3U*T6>0{e}nnYhCkseha$9}`f zqGROt@S`(oByy_RKT6`QTFQ(3WD!~JSgRB7Ec^N=Xx}j2Sx)b4ek{Wzh0)<3jC1>O z0fo|q1^^9yjQPGkQJyLaEG#TZ85vOrhgzGl7JFA$U{R4-+N~H4q}T8A@^WlBn*yYP ze1ro-?o?CLF;UR}b&k!uW3bcVGhVOP|9tIN$g)#7l0vN~(yALiT<%aaFa$R=IH!4f zVPaz&K3*R*A62&E0y;#mq4ZHNWO35UEh#7{$}OFw1_9}WtGYg~^(NPdxwi_MnxU7M z4!Y5t+2c41udI6iV1jQ1NMT4tdJh19lDD&C@_BtQYkSyDt8QqRXk?6`;4X>~CH z+<&zA0-%GTK3NEtYLvCgs?@2i93lxyNlj%Z0PwGU9RP{R#%75*%wHrych%}<(#~>P z$f>F(-U1QYh^ypxr6Dz_#uu}Wf0{+v`yrc^1?MARwZ;fRtxC6|BK~S`9GH=jak`S^ zecp|*KV5%C7B_E~Y=MwI*duKA$yvbpWPvm~7FI#pRIOs3xWV=QM7izsXYXv~you^4-2YUY zicS7Od21lrXsS?lvGWmNr=gK@>nw7a+Iblaar}*;OVkTRCI!-Hl(t>B-f^cYxba9L3`LU{K7?+d)xQ&+2OC$rO8e z1;j!$Z+nm!v(3gc7jJXe$;Bi7FhDRzXYB>&AQb%&XjA;$(=|nJhs+jPBoe^g(SStjBZlNFRCIrjed!xgo$vW zTpfEKYAxsutW2RC6Kx)D4XfAA&n2yGiBB*+@fA&Wt2sFRgF=Oy&L2v}olT%7qt1l1 zV-ZymV>za-&{))xAu>20VG-?djv9?!H*hZM`sUlJV6yXHC(cPNWgVRg6lidly_FRm zrCfS(`$m)X636q+oF13`rf9nqgMh=f8K!WN2~3gyF<(rT`_|neY#p_Ph59XaQv|W!x0u_TYk>sp*i~QD8LnCOh7H*xxIy8 zY_$wW9I9bjPJW9kp3;83v=%UYUsegbtgxjnK;eY$Q>6C~Ph;@_F)1M%s0`>+- zE!U!(PY%#NB<#WSsFOG~F$ybQ(|DbCf#1~;0tm7g&KqXw*L3TjUZjp)`ID*^LMoOT z4UhVr=c`RveWdS%eFfB=TBfTg=j+{z&g1le z^uUN>Si&_W{|zLczAJe?zkxG6|JB)tcW-BADOvme9elihev1WOp-!aD_vSd-LMn`~ zAf9^lbM;beWinLyiX*7wl|q0WG+7|$#$HoX&(VyD+s;N!%JNkYq>)w&rVG;i<#y6A z$KI^ zq|4aE_#z^B4Y>k#M0>Aq#r0IxUgB18VRcA~YMSBS6A_1lfx220ay5qA#@M;TlJCh2 zHlfE~W>s>_s{s$1+=DYjb?M*wE>sE1^h*W04p|Z~v2&`63E3@_i~Eipzn1?(R7t=j z=PY_RLs_VROCa=oR%*`xwGIUX-__eIqGfg+pSc`$+`^EY7+-G0LZyXx&0bK;MF98E zGC0JeW%?+^U)5Y*PWV7E!=&~lTLsq=T-sQOj}?SRUCtz2QLN?ctW;Iv@hPfmR>MkU zR@r-HRLsYQ_!9Y6y)%lSm_|g?o`15=VVrKMSa-&#I(ic^q>f-$_61bj2tPx?O?L8| zy5i$aamiJ2yUym-r8ace<9KGUvuqqVAvxL7vl{G?Q|0Qw-QxXni85zdj+kijn_6;w zayA;;dm&jpSKORoSl24=TfOgZNJ?84w5U=Keq;xWw%~;Cl+7?1i0yorgpT^J-ku zA`fn3Ne_JziwAP85@j)MWW_>%z+A;-sGHh(fjAkHkgQ$Dg_fYZl3A)2&)pY7cso8~ znucDf9M3fq4Tt4;__|QhjAq()kK&_I2g9TG z60pOlhwwynWPdKoLKc3M1R}$fAlv<8>eaMP9TrC8#L5GYcN{Gll-tjGPaEh>s&R4obiWbK{%*K3 zO-o*r=CaqP7tA@<&sip7Z#olB3GIo~5#9nnKv$%->*H^WjK;+C&a&ekw`%kOzD(I) z=|RiSQPB-Lr>wL4m_V=J*1%noermK+e6Y(uT`rT?y^whLp!Lj0@W+o7jzK#HGPSk{ zSCSGv(?|2+gfDLQp$oWoeYP4zzrt7>s;CJ_kqWn7^pKD8b(L?{iAVU9sn>re_$9#=PZm3D?9Z$G~mU9=e$V zn&a2qIuC(??VfjA@$$P_C5}~{uU`WK0%EeVd<%6O8St1ru{U%SgE3Hs9e1}FjfCDQ zd=8gu^j&-P<6eUmVnbidLXsNt#4&uBb3Cv8!F74aPS`>{wi*F9W!p8vx|AL;lpCqx zR2ccgqf`0R(!x{NB(_)>>HKnwb)1gJ<}%XFO%Yc(&DzQ7Da8$jvZM9Ar=f%M)e$Xk z4Sbn^Pj2^xjxo;SX=AH&s=D=ko0TZ>nu8bRZRbnT;0JX>M6g_CbxDNC zc@v|7Y#hb#2wU~wSHFt2_P}TtTKyA4G}&$g!udvQ600u~f@o$xWD@?|T2G$drOewx zdB_n*3wgi%Sty5PKQOpAv8Dt?5Qk+pYD%s?FzUM5qV)9mbe(x##Uc@K(HPnvR&l#s zU76f_53$fK5dqJIrLT`S-YM7gU3BhlC7*Tl|9#ZcQwJ2zLftHg3lA z)>(RRW=%^%G;VnywQQK%6og!09lm+1K=&Ea8&JMeCwPXSk!;C?E4`dH*82wq$MXY1 z5{ayY*R-Mv&wcOM5Xu<#qITOcLq5WJCZA`u=_tN+#`GN^X(?U=hBMtbV}|FBxNCx| zmXesGNlwHS=fO+Y2sivu-|Bm0eTD!zq^;db$9p61n}pCb{z%pnRL7eMv(L-br>H*6 zUJ#m{)2lY@j%W7pFwyCy0VwfzS15(s+qk4Crb!R=6PH?hEn(=&W7n9{Ei{AZV+oPQ z)rGd#`Ae3@^FS6?3eDunJciG#iQq2B^W_E3{h{xg!A6!=jf*nFvG`;6?1<zlmTw0D4AJxahi%TCMg*UK?c966o@vD60+owy$v`7e z*o|ZR`9qd5jRG|{lE@Aj65Zpd6{xhUv&3Ds$R?T|9v&9J0Aepn`tZl~>8$%7-3;kWs9nuZB)vwgR7Qu>-PNHhQO)_< zpVM5#ZCxKkqG6BUPChw|Xm9Y=qdl`br*ZYp!+t|DbGtc?)b(!d>YYU{tWaMw&EL4r z$7(JdY`SBJR(hf1^2&#a0; z2}_MuXYo59zKPKRC=RkOqj%*NhMknAOm%lZeLGj*A)ouzwFobzomkjc^7-xj*_55Z z(=0Mx!o zbtmhH=nCJt7B$T>f>Gbp8@jVsZt+%z0#-f2Q*^(K;uUjSX5K$TOi#h)xB(Q8$EKXH8i{Q1XG8sUi` zyqF15;!#8W%VTXUHhNItTYlHxgSy=u5v$$PC$srvob@bc_kE5DG#3{+g?u6*F*WLs zCsaAD#fX$}2sNJaWKm|1`j_;*>s0utJE_5WxH~}?^B1Fv^UGcWg<&AiCnl160;1ka z1*Cfyho7y=cn-_tzC1Y@HQNq$~13m4rni-3t6YY3BNS^DIM3X zjspxPA2%H803UIUP#FE40J&Qfk`TS*M!s-)GWA5bR=-R;J8bi^CJj1awW^PEl0sbH ze?)dn*$SdjIa>3$DSlz!`*W(B(s%>tNN_K(Mf?7@gVck)WfXuzs?mFMp(elmr>~LB zVnKBpMq_p2rr!@L!$27?h&*jpUmjYa^2k{+(*?083Vv(cj+M*xEOK=8Ofj2F9K5}wnlv(0Y(f)}BjXHk#jh5SU)N?Vkw2%1|Gr9Sq$E9pqR*WB)T>Hq{+Yl3} zh1Fzm~9OU_5KAAS6g^kw#B14dv<=K1N0;b-4Y&g3HTt(;u7TIu?93(hiO zg~80Z&!Ot@>Z&fm&lWmNmM(o5sx&9-PbJM<2nWm(H3zLLgAV)fYy2?G)pdx!hBd5s zm0-b(GRJ&a(MCm%^=0a+31p{TET8vqa+c@cncx-K8!n;u?WkqvgFZ-+YE@glz#lVQ zi8QUk)c1b6+uuf|3O7u^3NixErF~GhLV3zG6o6vbw{ZEWCCc{=>xi?8FmXrf-C83e z`1Ui|%%E!dQDkMQvDLE?0%{h6P-H6)?@QZyeyzXRUB~&IOF&?uV7@g82c1UPyP)E6 zD8nqi6@7IN{3YLejHkG7e>QE#1CcMqA^%vQ!o$_=@ZwIQ)67M|1naLFh3*dAn>G`W3Fmro#%dENEVBSTD6%Jpp*MYKyAt$n`2;QmzvK5^NepHi3eMO%eO z9(mE;=sjwLqE1q9VKZ{)`>Pn<@Ge2X!MG$~r?p{c?z1%?$Z&n$XW!Tex-J}-xAo&7 zKwCLJFc79c0x!^@H`pA;u9nI}RJ7UU{$YJx|D>*X$DyL;@(`#iVxk%O`<~f*-O?hO zfe+s3yjf~-V-$!+6oQB0rGT3evadWOIsQ#>`PDb(j1y}GUT$Oe$S+CzP_p-Oo-dUQR`>-L!><_(S@@jTNQHmOaKf-j;liK0W9>O$ zM?gE?o^uID_nCWAaZ=tI7)QyO zzJDh#DWS3wHU5n+R9P&D%V0Aib90A+_SMnCl`)Z)t?C~YYrnR&2d1l*GlJ?dvIWWr zM6FNU0N-hgDq*NeVa!`f&5Rj45P+U=_TKdkaJ`=^EOc#u{M`|@sO)5eNB>iTIi93| z3oKQ9on8JQ9D|rd46Y+=Hv&d%Y++xQzfZOLmj=(T(yLzd;&KkihH^oqbd;)A<3w|7 z+;F|1mM%@5rUWJH(8{gMo)=b1{RBs17BZviFJ>QYJf1a2+%LF!S;nAr3!bWZHI9$w zIgaIB{dc-rFZ!nLHV&jR^mQtJD$=4Ce}7o+-yfYPK7m#B)3|$BNO68ccALS>Df|Yt zG{*PgPZi16G;^l)-6G~vSDgF$JI7c?j0K)=tGJzB+Xn_HtPO~ik|N*k4ay(4sKazX zU9Dz}*N3ISsbnZTsB_s*_sk0UW~8(nQ0~+cVq%o2#IzE3ehm9-D@3)*=XfR%m(YOo z6yRv!a)so!8|3bGGoya-N0ywqs{~M>NqT>m>@8VZ8=#CbPbzUE@QZ1)_c8S9}ldCTBiv4BfXq1=`>7g)dbdh4V)}kXajO zytz_(ow^~Sbzalxdb^{Z;%}i%!3gNvdNF@rIpL0L-`L#RB9LuqX;~!h;OFO$q{L$~ zZvbjLqYpdgRhv6vFC#>B6)U!H6rB{Ps3-Z5Q)QQBa3`Qk*q34!PY!6(IL4-Z2+MA; ztkIR>5ypr~p#`>;3#z))^faAHs0gFh*Of{uklxzcfyJ#pf-51a03UFZRHCmODKe3q z^8!}bb@1-65Jpjv%ZCkd13`Y>Neo`@1Z(elgIct($%NM(#|e)GajOzZ@NTNro=(K7 zlZ@mbc7qGc3-LV}(afS#I@pI*F@_jeO^<+H_M#Y|p|dR%B}6=U6Bs2<#;<3iRY*s0 z0gNKu>>~XcOw3gmUFS}bR7xY^a<6v0P{jf^!u`yb_2)aH~HM zCCi0bxdxQ;;U()O|KLTVGrbMMUm-SLS?u(EOFe*yA6!1q%^ZWYOZYF;(6thF34=|t zX&j+W!4`9^3WyEdZNN3S@lq9IlBI}9&uF8q62xngH6;E@4*2%Rw4w_nzvu$I^eK#n z2j{}mOvSsv5+6>zXvGzJ{VXSBU~Q>_CT8GEw|Q|R`rh-X(S(*4|Mbo6Y*)pAAS^t5 z*Xg{CD0V_#bt(zPyvKa+Vn6gyns98+({rLgBlXaTps*e6w*fR@QyKYng|n=QX4%d9 zbY^deT$J#6A?WJIkv|4kqAtT6c6?15`VJV^j_rC2il~y2Fo;; z&NLUet!yqKnnSr5ac3_e^_mDmAO9gFKa+rW*kL>|)`@QqG#S_91_c=#7~~MO3%}y- zo^SNt9GXf>hBPKWaWgB5n3zBj(88%~f_gNJ^D1lw+*}XfwCqpn1-Rb5!BXYTPZGZX zA46xWZ;%8NBZ&w-ZbkIR%rVWdNQ;KXp|l{0NOUNgUbKG;P}HL?CLuYp{wLS*yt+T6 zm!+#Zlh|%b%>hfrlwsd{3fYNfNOb4`H$6#g6*j1u;p%YieL-xAB!;pM1}Rc8<^d`C zpjv9Lp@zWq2ghrn(amc~QKCOH+}uQenrh&0C=M}&qlvpvH4!*$gcK5rF&5z!)PWpu z5H_t^Y6vaqU{DsBe>PtYaT9s<`ql-4gbEx#+gI zPs8}96k*Xy%L^#qV#PNa_&=<@Ral(M*0zg7u*O}21b2eF6WnRsA-DwB;BE;T9D=*M zySuwXkj7nh&$-rI-}?UlVDE$7C&krQ)7{nYTUDb*J zyPh!#TPZ6d9~;5{lr+g2(J@_Ty{vY-cmw!t#R|Q3F$*zuS*!BpMFw_wm9wjjTpk_U zBU(rECy`^#V|6#xaxg@LH39Qox+aJwk%)cf`#Ca#sx!R==BPMRMGV!1S6F_uSMN&bdc<}@bna9*aHo|?8#rE z5ON;r>lxQ`6qT1qY6T0Oo-rDk=!VU#nf8I53B8(?JMFj@CU;Vi)rP7JGIX-avnFUE z=B8Z?=bvM6&2sB#u;6R$rMMLBo$Z$xnYakTFU^N438IQI(+$nJT`jfnOJ-H$RDK3! zjJ}65>tjEA>~^}_TEeK*)=0d5J+rGuj&tpK=x(1bEM2OuN15|)XHiLn++9<_!kK4O zSB#fSV`WpLn5I`kA;ia@dgz_+{xvLu6)Xt2>gq3>C|v2Kk~SL z=y3NS(f7Uc;1_xp^M0C_JY}vBl_(!7eE|}!Ua9;W#fVk}XYBsryZ+jA# zRNXO3JH3fP?``O53g(u8Qgs5&rHH${WGOTS$%II@@ZR`+Kf_C}P9vR=B2JFnip*Kx z-Z%$SXdJ=24;oT9%IU=eENW!q5cp@l#IZs*4LTO*zoYH^K3oR6Njs}DN@&F{RKnahTEfATleGdTi2Qf-KDt|?JvjVFE#AdzIxA{un&)w4e802xq_9wv4D;Up*P(i zw+%m?^khYo^ApnT_C&`ahQHFrj>PXy!p$5C5?1%A8kZ0lxX=0(MmRXmCxVVLB zI@ILkqN@cQ>eQVtSF&el(~PC)i|}SNV{#InGHgE-C3c-9Srq^T!NP9SF{7jFa z(#QFqZ)oq{Pl6rMpiqKJ)|9y_lFxY!GP*w#u=2!*mne1}T!#duxOZpbR|BT^$YnD~SY`@)TfV&$? z+R+0)IWcg}%pa=h#}i}{E>To8J)aY5Fi1+Mv2&s*)TJ}|2G88_$SSChA6zFIkGs-R zYVRiDQ({>zk7cHo8XEAEzWU*(+r`M~;pHEA(01qOd*2}dyiS2%$oGKcaPBd$?ZsRv zHL6V12u+CdN~-@pdF{TP$aQfnl*3K?2dHPgenDhomr2&Vxy#*hAk{{HCEB|A?j1s^ zLDCbB@wnS)0({)Wy_}GB$ua`@Tw*SWM_$*==kWd$A{WtWN&fID`#KEF|jf=*1qIn6-uYR8-6pT{mWxkZ(cJ*o4MLWK^cqH9e2?C&+lc<(LM+ z!2iCWGsIvqL)4USjlWH0_^@5@W=gC@GZ|=!I)W*RhIN2Q0XFhj+Z(oat!$IDHJh_9 zz`|RHhM~M2N|j}DAjc&2vY2c0lyF=EuMg2F%iiIuUp>3lx>0STKzMO_`BdB6ihjLp zufDD};uotwCk1D(=^7ojMaMGuH2K=EC-_!!+-{+upjiCgUL({bx79Jx&BZaZ;W)qW)|E5DhLg3WSpwq$p>X&=#YU~pwn z-Xy%=&fs`!mGy9-yQdR=QiTG}s=VYB7sz=0!!#9tvkKo{Y5IZC!$*DhS2F&`Y4#L5 zK4e9oS~%HFFEjw^^_1j_?s%$tuNB3hEL$;hBu6_D-O4VXoVj2P9G$2iMD=nHu3T~<}+{o zYuJYi*FS+d^PKKS2OU)`_RrtTmPK?NStv-A-`ZJ~Oy#U6_bUcRKWHd$I!v{fRU)W! z#7oP7=MGJ-QgpylGcXUdG>*Wd6=JhY+rombwVcYGjpwglK~=?mG*C9fU8fD$!N9Dt zDTO9^eI>eeFSuo!i7qg7oug_mayG?Qmbp-6e{z2j?vix<7x& zHaF(ozDaVfnwx0KcKZ+cOj;{0Qr54KRqB|YqQ(Z}`W@b~CwBr*?X-+zb-O;Y5;$UY=a;*^P%JcYgymh0_03T zKNI3TnzZ^Jv2tTng?(=bFRDP3Une7?zZOr-XKq=w#^vudN%^{ZFv{DgE@!Z%rH)vF z8Zqf;>l3fsCtbFz4Kv#T*!D|H-pNw55AGEb`go*7semU7cewZ zcHsSHHCG>iFqFv`oWGyy8XLj63vOO|@{2VZPU_`ODi-)%nn}d@ZTuGp zc$!f`+!1Ruyj&eM@&#oa&ClbKENHOQvImGsu-p+bNk~LvgAeSt_6*_Sqd!DN%WbWc z5`N}*3|sX^(*f`rm(jSnX)61+lxG?p!ZUBGEYaK>-4-|}Bw6MWyU5AsI5z~gUXqE6 zo02mwme~o##5mNj1-C3S0dc!j3d-RW68Rh%)b5zDuMsKYFwjF$yauzqG&yW0UC*s? zxz-$@&BuS`XPCwrpoW%EhX%a;DXk=sXZyNl1u!g@*|QLZyOJIKNLsy~f+9CR;ZTz- zR25g5fj(u=LM2Za!^D*7a4tx^3zyI}&kIY70xd7mOd}U7DlN*A!X+7VrlRR;T!VgGTgMhUu!3PeKsB|*+qJO*h4bf|r4K{4 zl5;@mPZf=ywN`ZBqvDWO?d^DH*gw;JJ`V1tNZ&f3S^%*@LO(6#CRK-h;Qro$P_B_x(o@F0F8WudlC{U|LDmC)6TQ|xginyB}Dfcac@F4^#GE+@gnMM7+2_KtntGL4}2rsHa!sNRtlxv4+J2HU; zuwtO4jHh0*57>51s&7{p!ML=>t%<>R0I1wyka$wDH!icH%IH&;O}#{Np?`jz-a&qa71tCP6FgC|T^-XYc+KcxyKA1Tku=ErdU z`iou^H~F6L!hY_L$RhU}?JW6|tiR3GbBl&arR%1s3KFyF=rOl77AdOy+>lSVVce8A zTlBcld&Md23Rgv+xkKBm%G(tyMAfaJ6w+>jeeV77__{t!oSz@DU3wxrgJlEmnRU<6 zXtxd=zP@K)#(cHCeSMqogem|cHX4vo{q^nF9R^j7_6(xeV-k8bAx&)id zAM(tBTz9197O+`$>27x??L3<@cWcL58*1IfvgY*OnHL+|?!bA?`}!7-%P@|6VLIh*Nq3F2f(y#0pA|l)CnHuU3V*k+1zOT*ru=?;Lh5`# z-oIfduElUEp*Y1g5a>2UgG}s2Vb^ZL?fJOUGcpIsBrst76#30@5rtxUa1?IgNx7ub z>F(}s<*-BFJD-L*rYj~mYbO%0F|caS+%;*fnD@1dvB}Y#)Y+{zsCfkceBIM%h1gE| z{gChFX1djwr~33zXs0u6R|%*ATQ8;9l$Io%>V=^b^<)@U$U!uohA>+sFlFoPhkRra zF=sE>^WwHSZFlmF&FAoO9nn0d-SN6tz>ugK{rzS0+2#3h3$v}Aye@h&NWpcvIK!l#ETF(AlKjbMfGyZ zPztDaNZ#0mNLT+Akp3&WAft802Fo1#BUK(|dPV{Zmrb&jbsflH%6D{BN!c>O3KO1t zDI5To%4|iwv{JhLRkiF4Uz-cDW{94UuZd4m84b(uF5+?lZRo9*^3&5JnYB1h?6Vh{O}Wkd{(^vv98_-0chgddu^O`( zG5;(ZZ$%o`(R;d$cE@)onf$SISykJ+0odHtIQbD7Ez1^s%2-nlxBFgsI(Ye z&bVPqT8&177`!A`a<#ZL;N12LD^rTPlJr+(i*f@9qTT{S$g64@i6-kPYLsh(S{n&< z)B9TxKSfCpSF_QICO+sEd+pT>spd2Cy4?q~CrVe2z{sd#Gb9G*`V>t^<4r3e*&2W0 zuo|UTGF|?nJNebngh}w**jSF^y?>ghV?na3m*qG8`h|_;x!i`|F!=>cERC3Elt0WV zuSUmu2`6?QCR;5R&NZPipY4u>w7p$Xab|;bSYBJ=n~c5-ea;xzoo=m=@^j%9)$oaC z#%1bXa7Tp%;~@WjICt#XX3_sl75MzNd$CuBk4JihXu*+P=M;R>#dmSTKDm8Bma%P8 z9+GJN5pLrWD%0Z}w(X(^$=!K?8~L7f(H4f~9zVvBouog{ZL&)VfIY{#&ic{-&r;j% zWbwIrQ?krw%3}y`%+rbHh2sxaWggZlokWH_Bt)TbyfC>lo&A6x=WqUAJzFw)f2z znFGYo68gYl!r_G~5I@Xf_~W-ewPfb2uNA&*h7|T-fZXPEo>aX+z$)AR0q16CF)I>~ z$BWERmkW5%|B-fwJBD;pxT6OkmiY#tx}EC!vdS}$s*nM1GK1-6{96nX@y8#iE#KS0~wSxuh@aA54)`5sbNiF zm@Bpt)aD;s=b)@2A)>r?e4~yl{CTNc?1ZQlcHE6g5dW-yNGz;`_J(s2E3BBvr7Fr% zX(iigA-lM5n1!{SSNcUTF-scBEqGQvWcFvqb={juYLF?NZfzYvG6gz^6fx+d|FoG|@H3`j#?H3mdwa zA?z&UU*s=8-PP@dMkVxyk?A8cSDoB<*nPpYVpN^x+7Kf}t(m=6kK3|Tl3j-){N6F3 zgq1PSy?$vN-ty`8mhM!Ea>wSWTk10&BWgX}BqN`roy&yiOT5dHQw;%rQXb2itQu+W zW^%lHrKK)iW_scxcTMGb?za# z&`fX4yp}zcnZ5qn`oW# zFv4aPWFew$UuYXVzc%0W{$WWg55HBc(RfMyk{%EGdBu5d$DfVGQC@J&`_r+mh?>On zl4s2404M7B04kK-MZ2Iuc&?CKxstBml2))0X&0SjmqE~e41A0-q@LR%nU1T~pX;j; znY>IhHY{n{)>`z9@ixvrgeZJKEnO2c=K~gIS&=WUI5T~rUv2BTH-dn_!*?sa39X2;x-B+w_M|oWj-6PA0EDPZ6$T<8Bqyt+NE;9yP>*;$V;NR+UP~j7s@DW zG#?<2s1&|Ij*sf-4lwJ;!`fWXfI_+mE!RP6?2CGdyUR`G??cO}T zxU)`YH^hQoC;D;@P;w~HgjN9pCRu%Zt**2L5KHQ)!uhB$QPVZ-a}{b zJ5R~>gLSKL+3aOT;2hZf+Xb(={vyiT3gO8@RS}n>8v_zbti;!Z2J@>esNu}E8t;K< z!q7nyud)rwKwGwt)LsL_8!3cbc5`r@_n^(nj1@@~)o;vEX{;#N)G@nTF&Rr)=}~)o zv&Jjo>O%Gs?%@QPsv)_dz?O<2FqdN*0V!J4$r$QKEJzYqBb2ZJiEuH`gHY+plQ-@s;~?@U8$0)ZWx0-yIRtI9?Kn;F$IMq z!yHqLDhyQR*|p>MDrsT=EP=`k(~>+jxrMABRRG`{Tv7rKROCT+TlB z?2gCT+5i_Pw%crwv<9(@S;99%{KSc4FT z*=wJUs+ech_g;%30=rLB$&>XuALiPI9GsfV_$B`K2qxxiGrZGJ5GrfXJl9Q=xk(tB zIu;`87eCyW_p+|cIJ6+E6I~eNyoQ~{N1b@;tL)jX^RMkRwp+MINC0MR&eygNBfjff zM~1Tx@Z|mdG@O+Z9p&g&KQQ8Pd=ZSQJ*0@B`l#y&n}LG9_e67h9>Ls& zM0^9y(WbApU_XzJ>fl8@d)Kp8YFmS#6ImRuLlpa!O*7YG$De=3WBCzmr*Z8nNy1^& z6S4-X><20Mr_u~5ig-sYNjf8A#1i#(M?@6N7OYmbJg{g~a>qP0i7Qk0d8Rh+)Rw@^ z=Qm5s%8OK=0Fg<*3D}*3qS|_h&RqUo#{eBYgAZ)9i{JoTdd9MZ-rJ~}ne;pm5fLvY z_&|o|Yt7>dS6ZF(^YcSvV|_dQk$<_>Z9!w4s+Qk76nF9td3yyc$w=@y5Wz_d+*zB` zV^2~$cUR6#0weD8BHYs}1u$on9goA6Typ*HgR$4W#8#itQHjnD1Hk#53t!Qfm-v_8 z!Os3_|CQ4-JL%vJ>|mUpX)L;;Krp%jY*+?Y`?&z?xLzH+*G~b%!_$yV==+_$!5)H!ybc#O)J2Rc{8RM;2q+&VBV!; znp=~f$mrEII||@(K^0XxOxrr#4<{)Xc)Nib7EVhCA3Xf2CyW)iqk)3<>H+dmSv?O$ z^8~DK3dPzJQ}yU&ajJ5qJS+5_ErJG;+FPrNhdrlo!nvznOvcifM!kNdbcoDd6tbF4 z1g01PJz6Ka0s$z!K6>|t4Mn)S^|!m|4029Vm6}3>gR{DZwhJK!o<(E*%`WT(x4--c z2avmhJP+ezir{fxsTx!OL`KRgaO2gB4kyu=;(BSJiLf%xenV9i8DJqSPHv1MQLIrQ z{bgv;?qVeG+t`Na?_S(M7g=37HUt|hs|a+8ke&Qw{XW0*iU(p1wZg@1=_C(`7udwzd zC3a1Gx$kIrZx+&JTQJ@Sb4lj7gpTtkqvClf-dDXGuKD`$%oj;V57lCf=($$r|Qr}7}g${kLxyT+}3nb20C_)c&as zzW{fIBq7+6mHQXtpVTjOBMC_?3+{Q9B9O_Z10U5ZO6M9ipC+YK3!BLme@@J;OS(w6 zZmRW#_6dLfv?5qvW6?A)fvqn;uX=XvYl4oE7&7+KVqrtCX2tD72u13};an&REuUYG zk>C6{6gBCu6{}Fisoe8>+Nr)sI#NtU7wU(sggKBm+!F{%Z-EPJ{Uw}%8T6QkEAlvn z{D689EGzF3Xc8{6^d$dq93JiP)LA&)uMK&!LN{H<*VA9gEUqD9Y2&W%ihevUb~T-} zBF?I)E(AyzF`i4x80aZfFd8~k+~Ivpo#_LZnt~i2fiRB@F9#<>j|YjsivGI}yOWTt z9Le1B`kT8D4^OhO(>@CsOiN5^UaSUJhY=co3C&Kh&Q0Ktfbz-+svXCQm~NWS`xWL^3XkBhh9;=?w}Tki=M*9Zm;3SCfX?yLB=|LZQeNx2z)lJ4kV|Fd;$Ow7W#<#HH0MV**XZHFFWGChQD^q&YQN>aX{rgSGPjS+?VLbMKBSk%Yy z0Y4JF(0IMHH#sASCQD?9f5;B?Wy=s%ZPhkLs{by{w_{#qu}VqAr^f4vnw_)30)55|YTI0LigSWhgG)8V^|QC`wvU*2=cXU{ z&YYsbef#_$UUr!Ff++-WLwa~~AWpFYu)d%2ezLa8FLr|1+- ztH@i)LZnoff<=MF;*JWmQ4CY$a89HEY>UtAy5g7)#uM`8 z4*`%)KsdlJZbNlB_Zx#L4IJQrTE*o5zE#xp^rGkH)NJjyz|4zv-P~&muXnK5j1Bzr z97A`pN%!RJ9vlDot0e@pbSa`9G0D z-M#dl>4S8iIds<(VS3xL_?g5;TLRY!9>n>Q>8^^dZdp5z?7wrde>b?H9oOG|=R}vA zHLchn$^dU8wA9pxV?E-yqHx}3pG^P5BKTX6bku`|h4po}1zZ?wG}x3`@bw%2GE&M) zV3{n&|4}Rrw}26H%M+lKfHX>`yKkV7zGCvv;o9GAu56+H|9)>UNL~Mb2GhSfF%8}9-U_a1^6q8$2B+B)#QUd>c>!Te* z2)vrYT14|C&Z>I1pu9Y6oAOd64AqF8bUHPS`D~VBw1Cd6@X+(r@KpBx&nG5r*Nd#C zksQ{2301EY-mfL+?R=oYF)mFb9W~@0RJ;DWdHQO44q|ITA1ql;(w=I$=6_WT_~#bL zy&HsJDd}@2fY)U1iM`(J^#b`sD84lkokWN93~u7SnbU^xfn8sfB|#qd9Y-9LXo3;5 zL%cO`CoyI@40gC0mGXVzHq_1pGo-K3>)GMD5nFLzDHF7MHkM%oSafPc9|o%Toc0nAb3ZoXaXc0r9UjBE0St;TjpH%!V~f_D)HE%~ zIdb6iaa!t$#>3oU*@45lPx&rWO{x;F?BYzu3wmv9f-u&oOUBF5F!$6eUFPkKU09l)=8+)V9t3U%lDQG$-{gnoB3)C`OShE=HW57HW?mVeq-x+Kak1ag!Qc@=jaUdf!Z2nEn_^V z;U*-sm5cYDBt#@I)Y#dAkY>!r$ley&n$Kcs$)jg>kaS%VeB`^Ke^J8~C~EnE&Qwn{y=qs%|bGp_E|nHw2SzeyhdML-G4>Gfr5@h&}s_n3&%`BtML~S}u~trKcS9a_US;RY=BDim=a7zmg6fmAUkK z99AWf@yS1;umVq#e(zzK;%esA=vA^K55Fdby_)A{7ZIH~g^SNIyxxBMB_g0GYV0W( zF;eQVuiiQ8=sN_03?7o75H<2ZDfy!}M(92GWl~Z@Sz`S(#H!y@LTgA`R?589PqA4^ zzR@N83)sWREamYE^RGZO9u>S4YhRfU88Ku%vykAi!H6Lj@CoXMs~bJKMCyh8QTe!U z;LUM@?ftN+zLc1sw#kHnPFzRu-o8zLIz%U0VP{v`le}BlNYWJ-?q)QC^iKY{5^IMB zyoEW6NRG@cLwT@Tp_Jolvcu=IB-mJq3qImBKu)J`-YhrntgUu1qgmO-2rtsIsK^5K z$Uk`sT0w>IKVWKv6l{%@`X=wb#BD++?ab0LZ#7Qw|DJ12;d+R%34W!(_P;)opOHJok+^31i*@7fNOt}fkM}h6;U6# zNLJkiU_WdNWzNJ$5sD^ofrbO~uBH>q;p#c&cWO6rpzZu1nO_xkTNxhEviLcmjyD;) z<1gHQA0^osICWnAq9FZbmRQ7pIN{b}9p@(0y944f@lybYbdn=8N@&%HAi-Ar{`T{p zyqXwh?I4iQJJvV;Z`sN?Il_%ciMyhcvDajs@Ci9Ig%J6P97T3@lPw_bkq4Rtal63* z=lJ?t&xeDYx(Boc24u;HYRWy_L_OijeXKrGU@+``ME{HLl*r13KjM`2xsr=I zRQ9MsjowGh!d&n|HcY5@Lujv_yveELGs9NT@nVJD;FX_?Z5a$J>4HlbAa#13lr=2T zwizcxwAPHuI9vjQd!X!EmJbWTX^s!v^}94X-{@ByX^!D+Gm79b2co;`<7<_FX)M8~>cV*RG}!(W)+1x88P&{)S?bu`i;i9dlvq)B z_jsV1|I8`ycmDvH-Z7+3b$XAqO)d?JW%%V1u@;P1p%W!>l(?q?Y)P4|VR3>RzD&I5 z4n#~SQTKM0gLwZy-q0L0f$FC@4xS+e>A^ex>d;5op!w12DTNOr~$T zUhBfw6o#L1R0)qH@?nZ*FTuj_{jHbV;|fb5@->NG-l%j$_#tV0sfH73m;({771%wu z2B|>s2@Bg2&Jt-+@H4;EUf_rtbac3#+h0q4Dt2Dm(dPhPUc}oX<)gWEOp+3BM@9_) zc|OD~b|8x?9X$6eKDcK_z^2j7{G?bSS%(qW^* zI}?;kYrH7ydSf{P?e!DBgR~7S0VR>}HHyD--dWs$5g-B?wQO!4#AzKaE4`r+0U_F=x;X3ivd!_lJ0VFt$VQEhmRtKuE%O$I|I5HH58q zgV}xSaQjNVJ#xRt%WCG?c!`OFml8~ggp{*Ky@I&~i^Cf#L^5-8A3<_diSqfqa=-KN zKEO-xlx@bEeBhx$A5EGMGr``>i`c|;oHlve_#SH#MU;jpzYAV8(nvVoIoiCPV=_D)Yrb58%uiR`@IJlGZi8|I zB+ki*Uffs(y}v=eZPa`qT!@gqFW1SKp@DsenU&xH=n*NQ@m%sOM&=OD5O*xm>Rp9N>kxcN}hV?C;D{!G) z{4W-kIFqBT>CZ3)|>FFu~Da- zNuo9sT$)9Q<$SqwQA2h?DCa3JJv7eWSb{AjSR<}$<1-UO0|MC8=+%_MK+PPF)zXOC z0RV${0$Gj9{*_y5wA6~A(LRz3jo>ZN@}|*XgB}7H#02Vi`Z8B)wv>1VX{~90bHy5} zoL{y}f3Z%zxjkr*yuBF>UuB^Pc}jI38mi6^6|Q=PT|WwuUwup>2r7vneYVqX5c(Tej|ou{yKv z*o$Tlq*ZY^+6)Fh_+4MF3+YJka*~a1kbG$cY=euBn|O&3*J*}j1v+D>+N0I^zhnP_MsiE%(cSSCN4?0r(D;=Jr_AQH{L2&#emLF z;;DX4A`!o{o)|`rCJzY~PS|iCMgsr0^T(wcdfCS4B-4)-bqMsb_FY-@T;VQRgV77v z2wKHx?CHUgpVty0M9u@!?LF&5W=Ertr*ri@lhLXf3{@v~RP<{9 zq2~qp80j|5B(ctgeMA#Re02`aelCp#e23=?A=a%2A~OThK} zh?X1|p7`3?mv!Q1S()tX`;0zzTCghMBA0Za_dI|0xMP9)v%CliwlKNj(B zV#6|e3=b2;3IZKUWZ#GS?OJGUCJ6*A|CFs(Q@g^j{S+(Zkcsc~l8JU}6{nqjbd@|-}uu~KXAdgO;&+V9at$tY)LUIY z3<|U9{a3Vj#Ui7iP{F~<+Wl8L8v`RZO@6Ke%tL1Nd2()QY66FgvN^fAP>+v~Et>MR zRaH|Ygda(T8*!1$UqaMC=y(r1fhh+idg9XkZxWGJ_eul_ioQYcwr~A@q|Z2Md5Fr} zC#clw*m1a#Lw1V0@s@&ks%Zg}LbL-E?}8y63dh_}gQ!87MWUOBq+k`mmBqfmIkz0G4Otvh)5j}a#Dwzy;(k{lR5~FCg*rP zUQKLm%f067e*D0|!o@w&=a9F{JJ+Uzek|s@n4V%*X4%DYCMNlA=Y(*SAZ@dz{e1(l z89VKy@51jS`ZiE2bSkD`M8#%Ol5OURt@RE@4Km@1$PnJ$d0a3mZ`FKacuqFcNssX zN5T0J=@l~PI8(0>fT73n#Q%unS($%YmiEs)Z=2huB2I2i8JdyLMqkh1xYFajq|J&3;^O1=rCK&^nOu}9mp;)_H4cc0hcbpA5KcCL z&~!_-_PC=K)x+ed&lIq4U1|IhWrSy=ncTsyt*hy#AaqAwu*OQFD&Q1{S&uWR*NN{7 z>I^#>q*t!@gMR~!GORUkeTurM4{NTmWET(M0Z`j_RA|t9I*nSzmYBys45B2w=*3*!rbtR-ip@VjKrORrkIE$q z%>&iOZg1FGoyBL(i|bg>cHkDzIsD;-5tMALdaA|gU|-*z_2%`Y-rDnfADGA{aDF`( zo8}B}DdP{Q2Q_?F+zjz?yGwcPbE9f7TKrv`HT-uHDp>=Zl5c>o($>2tE@^2w*L=G| z7kIuqn;r04hECyS(AwTl{`wd!mkA>;Z%Yu@C7^#Scd|g?byRSWzMD;z+`F zodLd?pmln;D%JEut`Je=h`kJ_V5+mwja%MO*IZwLYjdmmjY_g}Qz@&twS~k9h}9*m%BW&$OqdbEVi|&E$3&lgb_5&TTdVPSqfx!-ltS(hx3@EFp`(upAS2uw> z`w0|NQbo2mQ8?{UoH@L5F$MtdC3qc67eTka$t%7ykU)?b220@P~yx+O`qN^=uX0pId3O<4EuXqjZ^G$vMQG_d* zeSH-*ZZ_so$TcVM~ym$)qoR!sFGrcWa(s4$e&cNEbPxsH<;+&K5tBQR`npR&L7gogWDC}`&JH8xfyR>MkqYKS$K zWykts3I4BpWMcQ3(6@^{ zdP-?fpEQbp%z2YldLAk9dA;EL1Aj*9;npQ{B4eZafpt#k*?!>@1?6ug<5T3ZoK2kF zA`JFPLt>G(?g6TgPhi4e`*r7$dF zUzvE*AN?NlH~ZfKVCoF{lAxY?!~+ZRY`w(r64vYfQ1>vd#!)8V7C~ub4`_~3(en6H z(_7%A6#ZTz#m400w}RBr)%DlR6?U%PBfybLpA{oBiFG-HTp zD?d7*QwwZ6R;(C-UB7u~YJ|#UqnAHDkvW|5=3Y-ST!_;(R&gONcm8O0=jv%?d9U?Z zNb^zynXW%l2z-X6NG`TLnC7-{kS(Z<9-c2WcG^^E^~bETDkIZycPm8yy+^*v1IfwS zGb5^*h2k~`dQbaN<*u8a!vlpokiP0%PVN};(^~TGSF#Z1qDf`x>ENO48%?!{+6-h< zVs1Z`;qhPB^#K71Op)8FyZ#m`=wE5Lw>d6fon`t&q*72^F603Rq}o#Xs93 zK>oRh+qrZTjfdb%ORh@E@tutRQ`ZnGlRa)wTTye*FxTgh+mTy)KgVvk_A49qU_l?W zvld4tkCX&bYA(Da%;Mbi5Xx5PWB)gT5?rQd-GaWaLBD3+{<^9T_SV;Zx%&|tHhbVm zo!?3-SXSC74@sJxcBLre+sU*hA(Vd@TmfJ3sxZhC^M&`$8mB~N{07|_>u(|wtPlln zThO>Q-SdarEHtnTUB!{Q3_c-Wt&6@+ta*1zC>5a*ypp#q##wtPNcv5BGJc{F`=O*d zJEL+==ewNg&{*er=hN6$N2~rp=;Ox^v1?Y6KS}%pZ`R`FYWW`~tg${IqZjmC11AX1 zc%3;_vQo|0AYX+MNCLSQ$1?@|*oO&iPYlQL+5Kr5vpWk-`k5cMWN^HP)O4ARzX6wm zJS_ETUiS&5g&iPnp)#2BRKrV zAFywuDF!tHv}31%WKoD68*9k8zU=wIPTxs{tFZEJk#c+fTgLgTp4`jeE;XRkPyk*e(wf{GwgMfEE6NJWza_7%$O1ISR_u~g zPB5j{@du`6bRrZ)b(SQsl@b$s;|yG=W=dvgL@ZF)u_zyNn7(`74Ak2QSj{G_%AVpd zR|kO#kcAGGZ+7yoSqGPrM*HV1&USZpu@#lhyFa6gsn&nZClAZ+P@o_sZFA@E`Es$ox3XrUvunmLiB?5uxVSckLZRJ&0)L`tfbDku}i z&S7mP17LqRB7-yV>i&MH)bxiQzo~|YI+>rE+S;Ht5=9+Abqbn-HBF|x2I;dz>-JQF%Pm(OTu$Sa6P*KqW%PfIE+VA<8=rU67I z2TkgeR?OU4qx>|;Sl(;-sn>8a7Y%{p+mfVkry15uLT@Ae;nwlJ_mv(FAG z-=e`03^Ok(RuS~TStm)u@U^1=+Mvt0< zqjhWR5&`5kq~uk8dS_o74LhEwxI++Ol!VEKJhr*SJGX2PX_pGX?Wn@N!?1=|i#4Zv z+RwcFyu%WZRQX!U$0ky~K{V^Rgt^5Fi<$T}BkkXJ!1}{Z3wjEhsV_bmMRex9KYkZ{YBX8M>zMk4>V{$1t-JYcuib6K`0Pvi(0d9sY@f!R7%sAe%jKLO3v7f(+i~Q1Ase?v; zHZkO^e1=5aOgyA&xkfrNn(s6t^0nn;-2AOX?l@D>_0*#SRO$5uD)pp+9gpkyo<-8k zaR+AX)+;1BQGJ@_w7}Ih$iO|yQS6wF?&DzMEl-$YLEnOP9?!~|j32u?4sh+Z@*k;J zdV9g^>3gP@4cr!)$E=Y#MeV26g57?0Q;ENrP}EKT4YMp8FQf3wZ&7UNx02DgF7j9< z=Jn5Y9I;p5YT1J~`GhkLoRH5keo5zZSXHd_x@Q+K=IWWm+|4TbXdj|u=h!}F@{_)A zIU(hEoHylSjbr%OgO~^Oc&DST;A3d8xEo{kM}Iv!g3;PWXMRi8H1bgHJbm2|Y9(~? zcx6=S`1&%y3Z1a4d-%JI%hZg?|9<;`%aAXA4Foq+9^!VNrZo06Be{ zO26oe-kP+Ca3-D;fr9NhJNoLbrGJ)X;M5{dk2^xy z;-8c%lqi5vvEf<)?Xe>QoFjb$ndo0JRQpW-5s6;v4OmshWC2HCgUhM5YjLMJS%m}U zvJo9Pi#ROz7m^OAwW;Uo`H1q7_vN{Oe@(#i&*3Uqn^f2W($Y-xC45qGg7U^pP&Dw- zQA`1ach6^FuiJwr0~FZnS`2x}KhS26F~F=FtQA9FujIvcwFzKlc$dwOl(^0ibjofd zdIL%+<4vx$n1XZB$qzf33$RC=qswefh-?0QbA%;Y&z?yhpImCu(NeU zRDg($zBhVmEQ!L||G)-v0DOmrDS4Zon>u8E!t?Y>%#i5DjMx@Y0gzhKxW4DlvD}XN z1CObC&5$Xoz3Dzbu2*Sn=Tqh#D=q~cT|)lmwvuJnXMUV@Px|qLZIjvN5WC7{x=rK# zUMx9aHWzkG3-IA)3Wy1ZtC!9gsK)kFXpIsGVt3?5&!dOs&^-%88nNtUrztCzG57pDx1ZzfHlDjoVxcQb&?cTEl-Ei9Dv>5Uz zj2m&MLId92_36I>#+LZ(AGLPO_mvHm=IxZDaqT9UF$v`n5{K=z{2E2zckj8ld<2%< z=eD17YAIM7!>#9w6OA34nW*-W1c8X_wT~~+LK8>Y?XQYfE85hndXX~<+*u}b+Xowm zc?h>xD-){Ar86H4neH(vosCX%%JXYdy1gdcdtO+iJ`g@Okn*e$SF}WipO_|$^?crG zflZO+3GayIaqy*ohJ#;^=R$R!m_Brn5#dI3tCdAPfY~{y{mwLCFJ^ls2+$;sRN6jwITj&h`>n1%l|t) zJ+0Yfo5{QGnMCfl9aaz?_gh%{)Y4}C0|xTPFK27=4$>eNiiGI=s@?YL@1GiruA+Fa02?dmU<~C`?RCHe;LRw$}A*h z2#0fLr1&H=kuan;$Y4k{h<;uzqfB;fsy-SCN@ygOgUC~KAI)esn__<*<}mOEeb#tH zbt#zNC8Z+^WvY^vW|s? z5}$c3_lKgQqRzBG2X}Jx2Hs;xlJnNl*mJF(V7vf zd1HWQWp!yg6T9)_z0V%sr}RiS>ercjoT=lR1GWui%)YfXH&5!_HT^SRrQun&8XkF@ zUovCEwD}2_Yi{i9EtsPWfZokLwSCNg>H5DOp*`Fq7@Z+|+hupV_;P=WLRV#cOz)Dj zFLvwCQ$bXT7-g|JgXr%9=6tl#u)?dDgAWG9!;xqaFRn@cstC3sXLq82vn3=92y<;F zigm!YPDsv*dR9eKJ2BZYXkBpcp&o=$4eYaQ9Lj1MF=ASI^Aj=O8101Ly}ztkuFOorVe2 zlSiZnZc`1q9=8U~(8m$nIY9!GM_~?AELd2FdBiuXYm|7u&Ty0CsvPxiL}OfHX5U%6 zgY_c5Bn>jD!(?G3!D7gGk+ut^ZSl%xr+S`jwuV${E^$v~OPam6R}J=w((tF!1_B>_ zsW<;0x<-p$PxwNwxue8I^!17Q`ueiASQX8gl1JEO1z`Qz9gvFHqI2#m8~rW0&}&sA)M<#jM$flm>S=rMdwJ_v+U#*wWXgxmNQsC9@PasTkh9{F8eDi_uG?zqs@ohGY{G`OI>GZF z7Ux==HJ7w>t%FtIy=X-#sqOCW!lp2`T?6%DRd#Ybnb8ea;JA#8ldK=1+j8E2xMA&_ zd3kw?kf!)9;~GUZH8E4u9Vr=}e~*_y*4tuo^A|c6)*iKmmQ^w4mQ&uE?q9?|ot-}v zq(-!PGtq@J&U6{DVKdA=z{9u2!$kTY*2%DLXlOY5P_19(>Z@*|s-~@tcRXL=xbIo0 zUGN`O_PzfB)j&|M}0uKIzYYmB{~kUpRxj9oC$h z=EOs21+FCL=3Z2x>%H7PJ|5`}!wd@#7hYYLhl}VFR#W>5EB5}$hNn=9o<}YxCkOvb z8;HKo$H)i~T+8x}5tEZcK@AD0u4el0hKu82<(V+*!Ju$%66(tvW)SV!W*5}9G%h9F zsljf}T-prD5wHx$?|=Yiyr?YY|A>-&7Hk@(D_t4*cr|+tM=dcasUH?XSb2akazy+; zo5}#qMg+_pI-y;?kwYL!V|RDo78S{CO`g?UG<%{s(dUL=I10t`7b3x zRVvgFH%3QCDe4wSgHiAYM@Hh|<+qwu>|m38OJS?rx+x%{JrY5?-3;R6!xRqP>lF@| z6Bm;s+!Uf<8@P8E9g=>N4CY?Q&>OjX_BgU;Acyiem7yLT>KES@i3G;JwRwN=g&M88 zkC+tE(4MAwVg?1}DbDo@BcBWJsE4_1PFhco(8tF|;wAEb_+U%bO6{HI!(@ScGhhS@ zhCp!vfw(G=^?{pCd;D2j^QMJsdfBX`oOu)hG5SI<5c;Nus011 zVunl|&NcpB+F6o7x%%udI_w1gWoz?1bxOav0$tdcbtx$+Q&ZEy<+`nACD$LfX3{W$ zvt8kGWl{f!#NTZ^ZXBIqMdcoxi>j@P9wV&VKAD;?90`2C}wV)t`B!NTvx zw1h?@hKim-_8cU(P0t@Gd!3cK$w$K#KS{eU=G^lW+s7^BV7#IV6CN(C|GW0qeCao3 zFMB0u8MF9~7I3NrjGnHbqa#aXxPT}B7&5;gE+C9&5J-H^Wo6!U)G@_?_x2T6H!c$D zvxai)!Ec}^jkZ~FJyZ&XrhUn}kH{-G**YyAvYbn0yN%ilHw;bf9O+_G4_wtO#b2Vf7FJ3k(Jy#xAhr1cA+AQgV_x=6j*F~(+%}Vo{Dq#UxH8u_nmcH+nl*< z|72glgV_&@HE9?6=M>jr*lI+dX=(OKo<3#s~N+pIe$3-Nmmj z#l*E#b0z(yA@_;cy4Ke%M zKSPhy#8*%ih06p_H*s8njR86C9j&zDr82{pFQBJG-lB5Gi-Z$3A^Rl^kjkE~?YcwO zR^h8pe?l(}-bqx}A*!joUgv}$bkH10xl~!8t(Zo0BJO<6b>ejtsp_I@TG!$4$q`No zW0A{W$6uU&op#p!`d_uKgvKHODP{8dka zXd)rLs_;Cw#N7|?d8XBi0S1}HkJ5ChQqPlL6xw`xT8u}(MiR~^UmGiHWvYu?RAjgY zp;P+L{0*!@O1av^uL$S;_eKZv^R0_g*(|0VE$gH#F(+vns1+L?@JlPGqeFmCY9b;% zprZrIGH$ctnM2!osnw1cpusVZWjLhTWXh7GxUfbAcY4}^s=RuO5X)ccAr1b{&XsN! z{>!dur9ytmv_C5o!s}kPQYfY{zxwR9vW!FrLdU(g61J}jMV^wT5G`u=@wkc`+`{pM6no?kNFiRN;RpIOM zcq~X)@ZPU61uajd@-3p%$yDr`k+bz9OLq0hBgQ&+TxYnobUgM&>D{|ZoQxka7w9)p zW|5U-AgY7@KY=jUlY>*LVE!VA55wF#pMffC!D!W@ivGJ?SWVoBE|)hQ8`f?d8)xP> zz{7ZkYHgz(K*Q)`;+l~tl~8hjTkuvrziF|lN(FO#s|WwGit=E&gW((;#%5K28dkWA zwV~&<8AelaY;0=OB2GxQ!|I~z;pc%My!~?vKdQnrqsk$3CI z7650dSZc!8q_|W-p5wa9hsVd9c<_2q$Wmal2byWqGUQZ5!o&`9#}dh745Iko`-kok zD;fKKBPV=ue+f;)Q{nToS9nB3AzU?jg^KLio|c!}jLiz9ll1v|YQSyBzu0Ya-GJFj zgV0O@bD%0nnEh>2K+r4H57&SJa2=byOXS}QP#-PaRn?fEnp{!ON0&gC>5zFHH_3)} zLS_WEXC#)5*J`ua%T%b;AtcFP&Bt}sv70n#pQb@>?2ZnZ1PhNPi0hp~&kwtd_l8Gk z&lf!s?H&W)mPUPp;9uJUZ#`*NJ==8RQOsBI=BviZNGpgSCJ7X6wa2zQ1KCH+^}w*# z=L>R!cHXdSPH5+Rg{LI-h}lHts%+-h5#YJkaI)ZYi0=(Yt`0|X%OZ;AF)FKFA_0PM zXkEJgF|aE5T>q^&eGe}@>t7uz6prGyz4J@M2JI3W#v(mYDxcsz(JFmAGBUbwYjS8w z6SNZLXN-8pys`Am{>7Ne1gwcSLNh_TGNJ9KQ(Eb`W_LLRIwljt*NMsaoDMcW&6_;w zTud0+J1@R?FsWkQ1!ucKQj6X1HlN&%#u)D{wHTaHDdm!6)nz?HnzEskFbE8sR}Uz_ zjBHL>7u;@UkM)aPQRB~O5qG@%Zg$LN;FYWT>pToKo*&9<@;>N@Y)mD~bbus@^IR1K zmM!vP$&N~tTfiqz68x?~?z|i3#irHc4lDMINoc;_T@IdcS=*;u&=WE0xop$JPJAKiPese=}~3EBF}g)!shyJh)UIYY$4;O;F^IcMH*PXNk|6VPmE~3`Tf8!w6V9 zp%%pT2``_KS!1=6%9Grujdii~M1-L&sym9drWaB$ks@#t*;MUdLc;O1nI+vnWwEi# zcLTLS*6+ytz4hse&qOx~?vw8$*2o4_G|N}ubXFKZXstca%D_D9YNf#Wn>h{6;dI@L zswpwH#RI=jEr^cDmxw>g17OYhm_aNtfs|;Yl^JAn`d4JUjk0MTs1H*kI=7Z4d3p;V z@w8Q20zA2WD#7^zjT)*#jPz|)&IoOpuEwvUK8N0P5Z@mBiIpM3o~;B2)?1WPFP@&R zKTqq1!&UL_+pU$F0v_qyxXxc%11gnSt{qZ9WRYzh=_4oEuVbh7!wnYwO{3#VTeVSj zDHX&LF%lgnFORo$PtFVz`WWH^hR*u->Qn}OD?^T{poQ$Py7{_aw;qu7$2N(o-J*kO zm6SIEsKShf-2n<0N1pM`Ed9|+q&3f<)zl1EYf=puh<^NXD#383d6hZn4}5j3u`nmu zO)NfNP5bZtJp%!D9m$((zr30^LPnsV;tIU)3OJZ4rhOl$UdulrK9@_=lz~N{Ipz#A z#`c3F=UYGB-8U;ZbMikk7Gs*{e{HKs87rgf6&Ibha})edYFtw(TQF$0KN<2HF3Ojz zYxT)dXrS;5_Luky7eZ_L{)~17?X9WiL)WeXBrsmpypcw2z(#V2aA9+SJ z-23)($_*@l%Ytf<8H|!TXFXcpb!N>MU6K6E%zbQDXMBjk0rB?7m#8mvE&rTf8?_NK zRfP{;alj4maLJQ<-Ek7OTh;;|d$?H|!R877j8Cl*sz|C%=8hV>?%4A^Vq@$Wml$yvDqULUvgKF5 zM#TbMex=259C8$F`&l{~4J3&fQ!&^FYNUa$=P9$9%#Ts`+Ia%z+8V2kU#yF00I&Kf zVGn+d9uS?ilk%5-eW1rv|Usidac7ebl&>auQex$CoOmMGLH zJM>L|a!q=yBYZm5U303Z0U83raZ(0`-%JYNWXq0^Nx>e-0@^oOpoUo=lt^*Ga#ZZS zM-RMAmv>%KPmlXIms6V+x4A`?S;0M{Rt@J?UfKvG4OqkEHruw?+^8`ckWu!g$M6Bz4bo^s|4QNAP^MQWZv4h}Z`i z83i^d-4T)t+}`yTI|@9ihS_zjVVj(-F(ncUT=mv5f`(aHn`%dZj;e~aR)m5b&$w1e zFTI}Uz}>99L6&p*slw%0Hc z*&Pyn4{JEv9W$0YL-q0Te$|BX>q9MYM+7`mKOVbK*JxbxBqUO8-U}CvYj-`5xu@{= z?SD#kFs|0Zzu?5XP#Q<1i4qTcj{-`eS0@;wME#EsAIN2%0YWrv!?l{?z+y<52tRGv z0dviA2-j$wlN^E#7Si;EwF1nSwke^*XuQsmIpkbV*Em8kMEY z%HoWroJdCxZ)E*7xvzXo2#5uO29YX|5AolGO}DscaB-~(i};ip7_vYXS`gS>cs~jlyaXd(c9y;ah}CG zHB$(_;&-uA1Px&LWG0t*p(S7OJ4j}62M~jvV~I6vN$A;w^sLO79p`01I@M|HI@1dk z38(7AMH8A`)AS#QA$6P8JFzV00#@pFX4j~ImgT0nRx?~A7~Z}%Bbuc=VO{MyS&i+Q ztQnLk{V?2bLS+qHoPMXnvFtYV{rBbjqIRh88D=%g$ zxib{!gxa&DgoBn@gmCU_;fZW{kwhES?`JgY@Yd8!zm&@Quybj*2V)L^x>C(~tKGny zrj(Kvp?bQq8DoB9Ufimdec%VHpJ!$Zd68vB&Gka5>R}e;4+&V@)C@6XEZy+u8v>E{ z*QYB?M(DtH*BXmW&QWQG{AzXM2-d8$HNiJc(rp;NX5}VOUgGPy zZn^UHqTVVgTCKVbbAimPa=MvZ(JIT)jtsy|a$N&lnvSwv=?SOYFb8LXd0cv7C2N@6 zanj{BSVoGzPU+kdCQTu#kSnZsT_p*lerSys2W}9#D#e7^S!*WQ9=ogc>QB2I>zOY} z){;g#xpOZbMgO(qp^o6g^f#5X1s*fWE3Olne9$gFtU^`826e?`?rb#5mngxK~kq7jDERp(Ge9GeaG&t|HftNo;&3!r5>{77v>236hxrT5SF~MrS*E|o&&)N;CT;+ZI zXyJ4Rdu7h{J{O+kr+Z+Wc>c0DnxKtfo2*?r0R(slB&NRu@70d`J_UTGUt{kX;(eYVR6rFRQ zVAZ2euS{rQToBP#rfJKZo7J%088KJiI$-e^6ol|p3BF(xwf;>iEc--76B`X$aVMm z#Y6bB9XR!Hzp-1kdS+) zpi$YS0Ig0pNa$?ItK6-t<5};zCisOP2=d?HU`K4HtTZ*BGz{YAYz+E}uQsyjWP zAfR{BY_dVueNOCo?1J84V!d-I(=u+PNR$kV;Lf^{{FKZaLgX+VC#9fLDU(Ed0A7`p z%;E7xnLCQeO?Qb)Ocfiyb1pD@P%eapq=<%{JJrN2?B9NE{Qygf1$XGJNVR-OwddNk z8LAT(MfdUd`9Sr$__M0mVLRFD>Mni-(j?*j*jEbQTa1#ccj)v$M&av5iv8hf+OBu~ zVMOGd>hffU?{zRSa-lVYA6KlP?Yxj~Ax&CKRq#(bu~*dLIrT{Ux9I2d{klc#T#r{* zDxIML9Lb3?gH4bxu(164Gf{gv{Hn%t_mLM;;Teb(wKW81GKmV3;eQ{Dyjz3@iP>G> ziQw&b9FxN=sVpbsrB(0-ylVp{_4e909j?X-0eS2zon0#$;qs>*4PAK>-Krm8afgCl z|6%jYCACmUO~%fDgI8Olj^cc8*I%|{=nR^p<;Lbn6yC8j&nK4=KmAeIr#F8%sY-e1 z#pzCBG*pomXj3RI+CFlvqqP4_?AsjF%Hy8nY@AwJr9D>cs@Kg<8p3iHtu;DC)QM!L zD+T^W3I}2P92n$ebiaXfV@d3?yQ@0iZ-_=T{Kr2>#kFD*>41~#_x01xpXB52L<32s z9nB?Vg5l809Og$1$KBh=$S{$I1)heM1aq|-?kAQ?yzC!d*4Og{gcU4K+rys&aF=LN ze~U096AW_ceO|iqu(V8^QuCxTxZs0z{+b?4F1xv13D39fua?n^Fyi&y`hxs$hzZmD zMR4#|vM=ok4`=vQx$B)a80s)pbfnxtA2pOvxho01o|aZum|dtu23~_?va$w_68L91 zB;Vc7S`0jZ1;>_=Fr;L4E07r-ARjYBNn@TzQM{h!Ejc=zSzUFRGyI2rSf0aq?>k<} zRBm5BDM!#Il%jSihta#T(l!lj6poPdlE*IEc~1-{R~p`Y6v1&D5^29*Z@PyTLz-V= zvrBIxzO@zk$Nk+C@SOAUM?$I%`*c(2*yeKZ{9AI2y7$mxzN)AQ!_%7`h_MwGbN=I! zWG@QY!5j@1lq=5#dzjo<*xot$%4=XcbAUnE0PQ@L{W-!O8-J3doJx(Wek5^>4!6ML zVEqA712SW;O_a(Lyxz_3xQ*!d+^^AK+=g9decv;}wbXRskIj zb=5h#Oh2@E;^G-zku`q5u&OqZ_E8S=7H4wm&L90dHTiO9h4Ztjhw{>!sO5!*TpxFM z&?;-!-;RgL#c72&GPc)(x-Bqm+H%(QH+%m#avz@nNYP6&rycRYj1HLLkTR8WuRIr1BJZdpNgtFlaX>uy|Nt z2;_am1HBqFr&A1HZ82yHI3tNRwUY&wA#~IeD3^BcNt<|&)89lZ{6N{AV28^m-c+(# zP*bcuC+eP_{Gnw}q-UJJq8I$%6jN`@PNd|Uw(`>Q#n{1^9olcG@mRmZ1BS>I@lbERQBZ@*<|U0~+0$13Mbp-$qicOQL| z??CG?+~`g%puf%QX40{}?(e(0ir5wMs*5wsu@T^9((;3w9=ZD-9t$Uf(PBonrk3*X z3fRv4s9Ur#;V;tHfo$S_KOf!eQTX=T!!MwRJ7;}w%kMqUw>Wd!oM#s8mv_^7*O#`? zm4fHf^mdCYbt_U2OR(GV`B|EKH{u1Ngc?oJ20a{G=W0V87wX+24GPcr& zc>Kf{l^CH{iS=I^`%^h!>gB(8>4kJXGK)Wf+N{l`Vf{;NE|q#cI>d+fGcvEctJLS0 zD|*{F&YkZmPy~1g;qoh66x18AikckgED{_l99kDO<^!7^mz&cP?D?*>jlAAl$Jw`wFnPR(PIr_b;jl;frP+`4jdttme<4L1^eMX-cO&eQD zok@kBvK4t>FuATev6_fOQ?ZHLQpWXoir4T+gLa<3GuI`^vX=`|F}h-E@OIzx-Sn5fye{7+MJ^9cH5)rvzJkmpVgcZIHx(s z*RKyHe_tSRXD=76^reuThABm~Co~V>{C=%|-408B9hjw7c~~D&xbW?HMr5Y3AA4&Q z_Q;`2%;396Vhi#l*bhoa2*v9Sq!iqX+CST1#Mb+ubVu%WZ& zeJgdwwVwP9Sjz`-Xupg)60gG7-wIFwDHf%UAHTMTm3iPNDE44ioq?}6>du(};TSry z-pLArEdlmZZv!RiJ6W?aG%!Ak1uC%Xv#TYj(E!fw7qk63-^fZ6co_0>NCc^Ju)%^pT9P+Y8l!pU`Ng|PyM-!*M)xx zuXEnmk`?QsdnD1R`Nl^-`|7iupd-BR5kkLr7gPv>F0oapf?DXW>r|6SA%cozW|#l# zP?yEyrtb@p^e^{PEM8Sv}+<1nKnFnTus+@h{z^9`hPbux~Rl z;^vUGw0im^|J#Nxt8glsQ4=W<Ta z8%@WlB;bKRACdKt4>Np5OiZ39NDS7&>GpBEKXQAz#sv46h(S%jp!+NKW2}a%q=$SE zi}U-&M^!A}8w@+XCo%_tjUkv)XO` z3x|GJ)NUNX-&Sbsb_@P7!9nO-vS7~fUiSChxC;z#d;_q?K4WAa@oK>l+dcL@IX1AY zFA!OZ&fxLXKO*qxO$MbfVLo}-Le#hJ{>a}D@~wE&6ALsmW+sUJ3dtAL&v)b8Rgm8|Vp;KoTa1hy? zs3oEcp=F25zMhtY-}0iz4a4&=zcbkZh4ap^6P@rb&xY>V=e=~wDopJ3P^nh>m!>Jo zm4MCn-Cf8UcixO;oN^UsY+&M!AMnAQEHpH8XOszfzxh7Vj!4;MZTv{WqkG^@F(CRO z3hC12E2jh|Zp&AE@tPgl@lK1$5A3pGa#O4JhT^GLF_7gM@ctH-gD3Bt_}u^N88g`N z9HH*Y(`z_F0W>J#7*B=o#cI+P@)^JbU$^z2+)k+D63MlCG5jq>1&TLgYh-MuHxmHb zU2mW=*ub;G?s9z9ROh+OGp{OvF<-=gx}8JgjbG*~MX~%#kkm^xHM+jW^asmqV||&hEJs9jagdwS5&K@-*UT3_h{|@ zyyu{>Hiokwzv8j%6j+`V(=yb{J+bP((-LH#4YxxSw$6Ql!O;R7?f4CWWKQ`y>!5nh z`zhaUJ>=uWA3C>P$z1#?TL+V@k%6JY9P*icC#iKQw=W9i6CBextZ7}R^#{T{Q&n>O zNf`}ZucvfAY1ga~9A_j=OIsFL8q<=*aN3P9e~cI@p93lM zMrin=m=rJX;lYk&qA}j#ieciJ61tGgz7Rtad^ZeQsnS3OtqHin-x=-9y+4?fQqc1t zc_{Q~UG<=U@7X{?!4=E_ge6!iRwtA9R8sUqKq`!Iy8LkhUBh=Dh&|RcOFw*vd7r&O zI5=R^gymof$JHDJS7k`G$SXo6E>0JHPhN}Jj}O4@J2l@gTWrN^q>Y7;<}RlQSEU9c z0hPpi`yxD%aqZzG8f<++-f8(TRv*Z_-^t23NEF{zWSzUj)yH7Dds>yjQfEW{Ztq3A z?l2o-VN+FZd>{3#C*s6g203FHTXK3>A8S8r@EhSgnL#Q2;W+mZ&7_3gvnTM3+UaMu z0kfxps}46~ca~E3G0nK;gZ+j1pOC_sv^oe`? zc&h-4k+I+0AqxME(?@fUVRjPPFq-y;3Pna#8Sma4THE~maT+~4owG9gm0YRglvlv# z_M`s28%erj1OlqM?FK#1?>3ZNbG^^wJ7gSKY)X7P$_#|cvT8@))hkL1ODZWvT0@$j z_<8?$xGp3zyYlrQ5&QIM7Hrk^+qsLBH<2Wu6tCyW;QD+SczUQ$R$nf~b_Q3b92>VD8_i7F z#J5>rtFqx=!MJJrw-MiRCIEcbJ3kptzDRcx`&j7`5YqGH3zFD$BTiarmyG32Z{mNE z{bkB@gtTWlh9{ZxdQaQzCJawg#5X>oAUM8VMNdgf<{ts&NFuVFmVJ1w;nWpxyZD~u zbH%05@rX5p|1?EX#QGxg%xrmc;JuB@eo3R7iu7#eY7W+evvwCJ8f){re(dWXL2i{nRc~KInSQS9P z^>Y4V;skk7dN1@p4l%YiJzW+XY+T|F6<~o&S;OL``Co5$;s(xlgJ1FcI`^WnAYnwm z2)FHgk_N;jHte`Aeki8vN8-HTOsw%`9mCz^pLQNMpFf>Hh~t7>(TFea>U_mg69dd% z)GSFK0D_)B;D#3U@&a9KIywMZl^N}Y=V$}TeLML&U7|@F!)8B?R6RD`Fsq~ z8z4u_vj5vN1}mL2Pvs!-IBRAKMuRQ|*`1wqHMv6gc9>4jh`fAsIH3Y8NoUMY@1|Kr zWtfw>z#mYW!*tGYCZfErQ}cRb6v~))wzI3N`$Y%mG?-{skbn@Onv$5e9=hECn-Tkp z>`|*K?{WMH!d?g>C5>>DzfSlA8Us?EN)?IIDb6qlImlNi>O6U0W%kQB0z|-FQI`NC z%HUjS1+Om1W@de_&lUS(n}N{-6@_v^Lr-7k=^6?UkY4n!c^>gJdB}O|6fref;muu| zNy);u1ir4l;vOE*Ks0&n-mdaFh<*|9y0wQ+V|tN4z&84iIpTtMFDxu%7ZVf91#_-b ztE;MR?C%$^m}YHJQYW@i>A#SZ5)JNzV-sx#8yV_x1nm<)hLZtq7R-wrrQ4t1RC2PgLGq#OT6_5mLwd5avx7~*m^_r1-}c0c2!dfqekUbeeeog0$7X1I zZv}iG)q$9~w*fs-l|RAal@F;EO!bBN$28t6UUbq4rTRU1tlrOKKwyK{|H1DefJ#VZL z0ooF5*l-h1H8j4UIKYtJto_L3Mg*h`n#gYYCiz!5=F%I4)=RTCCwD|;86u>j^5 z7k5fqGUW4jbETerUG~L1Vx)J$Jk~Ch(G-P0qLLG-^h^|uEr}W16HG2TQ#yj4-jKWS z8v=(R(^Nv`G07O%>8Q~WiBHM^+&dm}ELVcM9x%5SQD1^^DH|bkXi#;0~HH7ze*gNdsV#wm>haj%}62>K+3iVO5x~B*5 zltBKk7F`%vC^`W_q*4p^f9fN*Ov@@NoY&z`$GS?H|I*OYM>!wQ$7W=B1<$@wcY}Ay z-R@+5UZ>|zd;@&=s;?44azi+o9Cn+1l^t@vdG5N>)gh2I#OQf4ELY2^zZUCsv=|hc zV#qceHj6NZDmT1H`90|{Q>&H~F`2I21 z6M}&yajwlRHo*A;QjgmGKhOqsko&3~wetYa5!K?(`2)9;rFz8@)MB}V+h{C)MW7tk;r(3fit?0&zAWed`cjX!^CSj$D#AiL z{8YM>U@Objf1}|qT`2InKl^J`s?1{IxN(w8yPV1Q0t^1s8+OB(^WB)Fxh)9aB5i_enb#jRb2+K=!}GM6&%3Eb`QMK644>L|z6eOwXUTWCLo z0Aks^c3~6nlEHhn9zq={mzhrTp#tFi16!~@T@Z!qk>UG`GoMeN&@o06d`j=J_{yo( zZV_@+1bEDTdItm|5K)LE)Y;HGJM8u^wF_>|w_>K~5C^_Ke*canGQAv$#CH3aQ(TCa z6hunk-qz6d`Rg!4QPWH4#>;JCP`>7OiKyJxivtBjfQw!b;<%WpFIlzanzuMFyscBd zReU|nbguXvc3VSUKz-Lm1UL--fRq>fstBJy>mWTYH!QVZ-)54HOIj5E zx2_-%XS2x4r(F|(cmbY0khns}g5upZ2swe%1#uR428G*^Md!v(Q&vI_VqeQul}}5S zKS(!rFJk;GI4fh~ox-8l9)P90Z5i&Bc$H2(@Wvfv{0@)cZ9zA`?1jGzUBt|dnx8*y zWo2cw9@fxGp2H>46Jur1j*blqpl5~Oi+_M0=E?&M7HlFBlQ{iZ37b3UL1I4YmYh1J zc-@}w2DfZ{SfFUbe1RXoKYqa0Kn{KA&s*VZB5;Fv_(Cgl7QuBqJ6UVTYF)BRx5nSX zJ&G{dUs(9xFMbDa(J$yjD?X8A>AoEIyxi>m;tl6LR__m?VTr)%bPB`|&h&is8N?ax zkcrkb;7bSeN1&@Y-j0!_kGtoL^Qn%Ti;d-``x?^LTyFwS{FgS*Jv=-v8@3IBkNtgB z0Guw4J_N8#xxtz+8|MQYJSzbiRI$&E5FsM(Y<#`D6tu!Qa-O)Q z%^Vqc_z4@A8-u}{tu@Qa&+l?Oc#~OkF>!~_V)%pG%cXj-^`ELkq9#k?8Fz{V0AS9y zmnUY+pxX=J!PijIoqv4d$$`tXD&@k4T}rEqJ#DXajom9giLPGwf#fyE#*;Yf_t`~6 zdBZS2cR^LWCg-{;+=If4j9<)oJvE~M)s!__etcBZW@TTe4FyFg|7-Au=jM*F^o(Ca zHB#P$C*P3IA(U3)3m5N~HokAo0M?NUQQ3+9y!vT6fE$GVib+;vxeKAoxiWCtO4UFU zydPa%c>tsS18kqGETA#PSD@qipL+?gndtuVU+CTPtY%5f8ByT^dGmC(5s25ZHCy8P z?#CDwv?dR8$GPlRw}^2ztIyU`+vVYt9w7Z?ci_ym=g&b1I$bG;M+0Ci0i>>@nP@F^ zjk!B~(qqBx%Wzz5%-`rcHzu8ak05})ukfo*5c@c43{qGrKj|4(Q~_S$_E=$NiDS3@DKkL*4ZZPB&#E_?ui@OEtyd`t{!W zoZRy^^N`Z!t4c~6zXieBee%iwx{*S2U;XUyAq&e2!r;tmuG2|tQ-HVV-&HEklB-*8 zADa?!$U6`a=Jg3X5py*8nR>6Vf`{NY&@zJa85^BN%iH5F&D*AzVl6I|`z?$4ZeublGNc zRKzoPD{~C`{{9PBuBHzfw8un3BSAZs^@-@6apy=n6WPB=Ja?HWSZ+s_-U>qUH=vK| z96Ua$_h~jR+M)_lZ(8=k6KCd3nGdJMt)kBsyXw=? z>}h9(+&{p~*q1NQH6?aC&}Ppo3=R#;h1RxUD16|^z=vT-4@FI>Of&B88T2 zq)ovAy%5)hSwU+YVpb02r+u?OC8n>AO^PwJ69PUX_?q|Sg%^;+b4dKZqh0d#nF~nt z&-)6B0b+AFJ0A}HV4nVek>GPS@=$T%Mb+xUf?=;3D&L<$nnz*prVKL*o8oIxGp?`` zEr7O`#6%h2bmL-VJi6q4ajcYsDZZxlj^(AU=X3`vMJi|f!-IQ@FBjKhAOtJjn2Sq` z%%c=6+?H&571#chuE$rc2`9UfO^&xbvEO*`e|GGEs)WA}3OKbn`%S@m)kOXe1j_+Huvx>*8(UMm#$R0@IqmI{ zAuQFHYP{>hWwGDQs1r_CZWRgQdjKxBegD@i#k&3uuJpC7pEuEEb9=M~`RRt8T7~N! zQq|}#MRopZ?2m+`UuUFRbLaD_8+UiF9Kh2Q$&4wSoES8?28<9(SYE>Gh5L=&N{!8v zIZ`cK1o_S1ekxDODx_FUjkfHbNK`C6uDdnrYR6d?7W@@rAJW3_0sTuYJ_m)WG8 z8<+Furd2=4;o)aE{X#GM!X2o@SLGEty#&*ppR zr^qV7OJ6v4^|5HY@m7`-BQFzqsa8wqRULA+O*H*LCz&md#l&HOzDa7rh%(5aa1pNo zS(Di*X|hU3hABba9r~grC}N&C0P(E-TY17B>7k9xg@)t#%|plmnh!63L^0{1mB|8a zldBrPkR8$qje!MW+oM+Z1pe9?w&$gjB*U!*Z@`&?4j7?!P^E1R6gP5kD_JixU3%e; zae{78wdE0BwO?p=w|Mm4nm@I>XFSyQdQGl0{3U-$g4tqoPtdv18#O*}h;weG-n9M* zd~d!zXMUa0w)-@%>dib zar0V|eND9%!uiscIDW)HJ8};>J|T_g@3k$n_cAhP#8OULcY@HQ+2lsE)ZTo2pykD@ zLq{16t-mV$6iu%!qfh$w+(qM4<*IRUc78QdkvL^loEBY~u7f-eQ9Di|2)mYIwJ^pA zC)y}xH;y%J`NDPl&NtGT7rrur&fn>z7`tfaB zkrRbGqMe7V7Rwy{ja$B}mDR}~v+m%Y7cup4tC!g7yxrWEZ z%2f+mv##76@&UD)5}aPA6gbBs@G`?VBc6rSn~L?9AJo*Ka%R;K|H2kQ^-# zmnvwliS$1CZCsd=y_Q*fe5w=Ov(J4X_DLJd->0!ok5|NDw=)86EzC^GAmI zl;I(20%|mLktadl!J*X zULDgft~SnqZ`Q;_;HUy+W7!Yd%N%v9y-;+RTAQw3oaPqiEWam|r&;i=$w;MJC0v@} zCRji4Vygzy71}@PN}_56v`@%tw+7*AWW8pl`z)3f-e1*deM<`gKfsxJ6qT^O9#-D5 zQ^N<|`&|gRW(?l^6BOnp0{JQ>IgqnRcs%_s;6+Lx>{5eD@3o~8l&HPDvxst;O9-I{ zHckgWec)yEU1|x9ck*}b6DlNA3>88gVOdiZEcvV;VQ^TAVo`}P9JvuBcw z%?6koy4|f#3MTE&vHz1>CjifUCHg6w&f|Z|7rdxq;8b)nkq#e1GNuv!aW)9&r+?C<9z?GoH$4+7uL!lo z;$5!iI{{Z-$QEp3UAIw(erbBPkdhxrD4C$SjGyQm6jrpPx_|OyU~@*;&I%Py^!Ava zsN4bOua4KKbTa087wT}}ZgN)OE-j~U z+U%LfMfwbkMo{sV%Rae@6i@O9y=Dh4`S*4^U@QH5yCsae;7#K>Rd|Jn19l>YSe>q! znbMX!3K6s~Z1EeV_bgy-_=qxVCP z8M2#XCeuKvgk_i0=@*T2*g=YQ%=%3e0wIk@hlgt!qVb6h_#z-)M-@>2vS{`90K`_* zne7z7OC9vr04V5%ffDZ}j@`mw=CF2Q;p!<}IDXg?!{BRWXr zY}$I;qG>$qPoTip=G}vd#Nn=?n5+#m@ywozl(NrBlK^x^c1IVMAuf(%vq+J-nB}3f zHnm`TYLR+)Ip%h0dFq!bsXn-8Ag^@~G30u+7I81iMk;59eZQj?f*`52%r6OUY7XpD zYrCO8Sl&&a#F{6KzxW6R?FSjEuz2&ahwag|%ZzPBkV@tys3vy#hse*k_7MxJTWm|Y1_=z-uf27~ zrr5p)n(^!F`6ftTDx$Z1N=%@lI^dE_g^?$cARlzXNoPlDo}l5{=cS5 zz-q2ns_wl_=jTCd&w!*vaX@zqI_u6F!C!O>i-Ug9ubE`q3b#(!IFs8*rl?0A`tS%64H_+4gN37P#cjO7I0Cf;PHBR*Kj zYC68CL01ae${m|#K{|xhY(FqTVOl?~7bcH7ITceC{8^`yLB9{>)nzF0r|Xsl|N9nW zTFoc^f(xNBU^#2dsch-QDy!bOJ|dG7cREJnmE?$}_HqwPYcQ94S1=qTiC!lR{*pmFZ?HnD5={h5vs3dNM>m3Gz>^kD>`j^j< zV=M9)Cz_igi2ZFI+Bg*Np-vS@DmVv6wY!Z9Jgalyuh&mslE_m=JTCCj4p1!^x<=n; zY&s#}%q6Lt{d^6aKK$8l0&F6H1l^GJh4W$<0_a%%py?5npz%lIud4D)wq(Q&Id8C={7<(MSwAbQggfPL`nN;K=7*YZ})z z{hCu)8!|$~Ym{~Rty5^Y#e~IbzIp0Lvf%i{8ak7OxfQ2GUdl|65FGku#nt9vLY*=E zEL@53Rm)BjYpRC6NBbvRtgb0;y3M;8#5ZqaBZy(VpAIS_eTP~eImi~Wzy-+sZNyPz zC~Eadb0yr}_6nPFCWk^JE_0!CEZe9L*KPfC_I9{bm^4}nLX3I`aWpFEhcgBA^PhJz zxBCWyWnvweFL|>iZY2qtHZe+rM9A%~g(gTbrE=&_s%3wsvQjJZ>AajZZnu&r^K?66 z>>N4`0$uOs{K85^*`vh#H{emgfM0ow;e$phOceZdNh&~H5~2MsDg|iTg8j^n&(^SR~iDJX`7UtJDVPspgYL-%vX{3;m`~Ni7BVcWq;E5Dc;EieM zkWDI?nnN~KrZUOw*6UD>6#Xc1>U;tRPgz!!$CDSG=*LxP(o6ZR$C{e99_Ny-wI(y* zkTp^zwIQq>R41jV3bQ)-ITeM{*PjX>n zpOA^7D!yQbCylV>KH}2-YtGzy=GBi=ss# z_M6n&?=b^+=bd}`NZ2CzNr8O*FqE5yg+C2%{2W$QERUM`P8Fow1Qx#MTd0wfi3SCC zh+bN@^IkH#f5GHx6nw?&+-e`vbdRwDAARNFLbcsbYmT3tgVhX8iU+|DJ9HpS50mj< zDSU-9XJv14@B(iN*SMgIGBdX^`TKXCOD5~+rEKt?l=eIL8d5+B0DfjRbMImY@a;{;srfBRYaXvote3mG%YwwZeRAmA+f_gU#Ty+KQ|TDLo7t z*4c#9E=O~`*{0OMy2XKA_}G)1`n)UsbJv!;gSP|?tM+6~tqGNl{6n?XM9^xk7JiqC zB40l;ayq42TZO&On~d?;80m$epAO4L?#iDWlgq{1HrGG4zz2TI<=}PkLwZ*`_~{@y zvg^bykc3QP`B?oGPM-K`-uv~gh|M%$)`AoI&At0^6$w#<1tHLl_@c9|Fc1*s6V+X5 zHAs54tMiTp%$y>U<-PUsY}=R^EcI2XA@A-PZO0aJmd|SaujBiJ7h_gCM@wtt#rBZt zk_O~1Vx4n@g{G@RvHLwe^CqiI7i=AiJDBjk?u^b#uLR`Q?zL{2_*jk@1q(b#J|<>4 z*XmhG*sIJgT^U()-2ktKIzfj5oYqDF5-4H z{En;6(?>Y(csXt~{$jyRHNV?nl{~E?9qct;G4QBr?}#~ z?PVg4k+HRALBTI$hZWn_YY)qWgq7%=KKE-SjLt;}Exr3dwbAI+Vlch+?Ge%3!}h)E z!lOWG;~E`-`|@Yt02-#fh3_DT@GU)kQxofzAwCNm(AtDLDIDE@BUC=_!{h>Q{W0M1 zWdjK&f!JmDZ!Mp(-PF@lsQ06%>Ng!t>@Z%zpufQrvpjm%Xgi9IT9@)Ruw&}M5)lgk z=ZSd6($YOQ(11)a=A_6}OkJrmcNe&{hL*J5rcK z3LTCcA`4k{Ug*c*!}j*DI%H*W0(~3G9N47Wp=m@L+_gG`a^y#cux&M0!T?}bjQ;!P$UGV1PJ+X|VWx@E~??=_g&;Ti)LnxBSAvipXZXgFC0U^J}oMhv~W7 zIdq}`&1nkit92GPvo$@{`3?&}wioV;bOS2&_a;*<14a*$;iIFN72P z@GOH7O5{_iw8jw?$#I_K^;L|=@t&y0$#MA5WvtcNHi7t-)}k*D#e!XVlQFms91=Y$!eIkuj~*{Y#3qi;%_Hy55>s%E&zmwL72*of5Z8Ql08RiDdI=U?S8 zSsZwa`czbKZ^kMm7cZ_ZPv$#;^0P5y>5=S$Y-UUFl$pdstR=$M5OZoy(#Q?}eBwiL z%f1n2xOA@A%47tanK%hpURrMai;f&?4b=SWAPeD5iW)Spu(pL4TX6yRN1H6hR=N-I0&GsMRiJ#=;9pHP>R(iE2XJ;gKudRitv@R*F?nYli zsup6BbW#}<3s<@+j7i-63IV&rFx7-UE5$B{BllRGW6x9-TSRop^c$rlQID)-onWS^ zlT&4Tg{gc8=OEuJ{B^Dc4?OfkcTbqZ`Y@Bbiys=Y0?z9T<`Q!*oEs<4;i{Osi%h|& zynab#*q;WcJ|H=5^KmR7UP6{uKiBI~yNK+^o272ciuXLsNeMXFaj0{V61={QKGfqB z3t7nTQz@E*;h0HB4k8f(_6HMmYWC;0`+M(6K5)jW+^hRRHPgjvxy_Kh&YkP$&_n=acTA@9!F zz_{M;9nTL8DoS4!%a_lDVudcPXMNr+{-sqTRmLY}Yz#Ik%~>cQYmnX1Dr^_FaF`U6 zO?$g+J)BKbE}@iu+mK&(Gtml26~dIO@HY<$Y6*~$_E=v=n<@=X^hjWddqF4hWPzsz zvwWxM&gf`=HcE*)8Sd_Pz*cRQeiKr#5v<5~ob8rRY| znt1ugsnBSJ%X2NiXRoqJD)l8_%`z!exXZvQB`}8Iz42~Qt3zkDC?;?be4CSypi3>d z5$jYeSxQ<{&91f*vr7NKFpF1ou;!xi&_%?qlE4qBK22hocazL)>o>V>?9761`s9KA zA!pB;n)_szH!V!U+3H20(!s!I&ib}y~K#K4*MOm_Y?P+4q6Lu11kd&e3X?NV@Sb9d9c zzR0CyE$lFwAhi3wkmc<@5>@48xtk~@;(>9au>#^gwiCpL=P?im^cXI=(CW3^-r{eh zm*?xq&J-JPftozY8rW|lLP1djy3}@XUCPh3-W93cy#98G|55gb3)muhYU>AM<4kn5 ze4t=c2@BW0;{0tR(}GcM>4JYJ8LzV%^}&n35knvV132FbK&NC${^9xFR&IB?9NW~` z*XKmebb5)zXi~}#X(HVOSJbxq{Rw-SffG(W4dR>rg!Yr~s?p(a#L8)}R~mD5YR9G3 zvfjwaX@6B6d=5&{wu|(1{5cCV+Pcr z^aTu)D)uY&6BPb2ALeqo(?Wg`+VdFdtF1@6jh^M6yBCiGGNZ+3@s*x15Z_@+@O>{( z6{pm5VAH<#c1r|p+T|zY{30A#W=uyQ~E>a)2-#WN`5HjVl5_F-4{QQW7nPtL)QZfgFRjWN9O8gn|POaxE zlaoe?KvGXl!P(ZN!_D*G3E1%Svg+#U+pc!?i`P;pIF;b(}lo!aeodEeYdcM?$gc{FgXM_4OOYqtQgl#o8Y+ zRhy^NO#(RMx{;$_#L^fMK-$mIg~2Fa5Pg{+e?e>_uZ+T@YM1%I$%~;gM%&RZSq1HtKq-FnBGX}9c!ZA}Xjgr#hzFO!la^2$6VK(?j4 z^E3*UXn;T>Z`94))X?x91H%yhFTCKyL>xRM7%eTW-|m);u}vK8!Eqb6y=@osQ?K4syL;2?5$hE`zlT!|Y)i*l?gO0y^a9 z{M1J(L2jH}29!A}tT{?j4!V?Q{KxL={mjyuz|kejh0X}8!-4jE{D<(*)7*o;p${5# z9jZ@BU)IQXf{YQQD}%vl`bXVvWwIr$$7Q#Io#=BwlDDn zk-zZC5!N|ihW}R7BMh5--{5)Qa%wgX!$?S3Cd7rHAq$ZmS>KOHe+N#Qe zE9R|C+3pVW^Q!5Pw6w)<{QpJr_FDY^RDAvrdHlVLN!~L5vFjw}@eI7!iT&9S>gALiiREZ1wJ#e>-LhWT-tQVAzRLlno69CxnP2d8qs~ zm+g+&Wkwd(NCor#tMha>fj1ei@E+(a}W(CJAg0TnKbr?D8(l7pgf~rGh$6WrHiOC8-CV?^I+G#O(-9yTNL@ zJ!?npY02Fa-jBJb{F(hZZ&>>XnV5trkzyTd$k8R^9G+Bcx;0Dieoj0Cv}taoZs#MA zC1?_qZU(wIIIckLIUaTmHMSSnIRChbE9RqIiU8rV5CGV)Ou=J?mhuyHz|=*+nCT-g zdttYtcl*(7!!fcnI{FTio0}UiDXq!AEv-@mXoeT>Yq%mhU<kYsOz*<4Zrw3V&pCf?nf{ z`t6aPDzX{S_1f!3WtmClG4S#w3XH@S>x`D+Ql3%jbgxnNJ=ziNp3=mh58EOrlzkb` zri<@vQewV#e~^|hnf;{n!9qYh)hCt1e2haQlz2>M{mCybq5zVGQ9_qozn~VgYePaL zB34qHr~@axG9BQUnKe69lY)i`1E#2OktCHzYI}63D8gB+V_L9-yvqPXuDs|1jx1UA zx3a-AZk!%>a>*K}43noK66c<2J`|qu3E&j<)AYV1Zb%}c1!4D% zSbQt8$w<+3vf8fsgOc4EPTROHON_Eu!V9xZ54WLuoB1)rfzvj#ukI0Qi_gnPLE!FA> zWQ&Bb)fST@+JO$`Mt`QVcdEziM`!$y5!&}L>t*i02ALg}8?D~tMw`hd*iejK5@~hS z@HpOTuHa0ZEQ5eRNZp>noWcB(`D!DszR7{%*#F>}{2df|D{za#g+NJp`77doeLE2~ zjbOk2#U#W4FSEu^*Jy@gDw5A`JV{>G3Ux9-IW*v!=cmHN|uBe5j5 z&)DiKa4u9iyOZU)x{rwtB?cB0B-BQntzt@HhiVqbYuP3Zxve+ag)ft`0!VS)uX8T z0nHbj3rRe_^!!d~E`FjX3ja!LD4VbTITTyPGTs^)M&aCe5cbrti zvFVRH=H6tDB}%{8W~|1Dvv{TA5X+89m{YvISfP8YT^sV?!|nHS)JlV}4|7{{rgoz z(76iR!x8Uc$&Jn|`M)$4Fh>1nt`3MYXd7xwdkTrDqy|0AcSPj8z26$eWWOC>Jv+N~ zF|9UqOMDG?M#@IzH*|!>6x^F%RbRBJUBf2zP5z62m!%jjTX;fvuU1wi*^jYGuIdGG z!;5o)rO>!I4DWCL@>vgcFF_@-g=pjw{xfGqT%njap~ylS%}i;S>I?cfJ39p>rr?~5 z8*JWGkopbsV$`eS|1I(>V`6-WVA zMzOK#`+Nste2GVK!^R7inGC83GfJGoU4g(r;M9)ylXxTBTjJvX8ia5JgbmG_%yir? zSxDyuNAW zNS}G-ad2^sjE#RnAP^ZUzFZff4b+3!tz^%}L29bG3iEo})U6;%(fz>~$fVWG4G7b`3-3d&MTI~O($2E3e{+$SL+ zf^)x=UIAH(nHD%MOn}tO};-jOF93LC2AFTMFq!dJw<}o;! zG3I*4s`?^CnGAqGqf{D!5s&D#&a1D3p|eO#wq;Nxqk!;6e^t! z(KBGklk0y|RJ0j7iHyHo5yNmz3OGgcn4p~v?cYg^ujC##JXN3N&+JnBh z*kAtILtuWEC=8QzKmq-omzURHzj$RqxB85Q!~OZPyZd`y9Ul&+^M|~~#u>N6tOIW0 zB(NMh1Tb612p*dk+@m;w4ZA`E$a2~P zI=i__crTttV}SKPXpgc9TH8rJU|RkZa;#n%Nw%6i^odK(cXe5QeSrIu_W=KdCq@wW zpQ!l{P5J+4<^K@hAqVDN8Q{Qsz}d^l17sa1G5@_*M%m>=*26bl9^!(w~aGqbaOmXgY;8^V2?-PZgMH(76lt;uFzR{9 zK)ILWz5sbZR=MN?xfzNc7zNyOUo0SGJWMVwKE@A*0{`t#vw)8!=S8V`<5zOcliUO) z0K?}0&(*)Itn7Bq_Q}is_i#$EKJ^xm_`QOCDq!we1eH^-3ckJ+kOunjoUlXCIk625Wnd~Ib5eCm@!{@l>elEgv* zGVcZ79!h4-7*3m=o!!;-HU2p>-2dmAQv62PRftTVeF0n(%j7fp!BAuCWwEc%Fej$~ zZ~p$V^N!-){G84eu$>Qd`LM9yAe*}?J4IyCjV~&u_EE^&%=5qB{MVbG{A6q<`Dr~r zCFSw``v1O^SsIwM(&M6k9v|~u?w&HAic(io$y?b8Zlt6;IabOn+&wxr{fU$NTxpEM z;*${0=W+N7YCs2xby?OaE61QD95qEM8;Y)e5@zP8y}S28{l;jGPOe$~VrELIE~=+e zVn%W=S|z7B%Gt-HQf0(K$9+#d%QD={rBqaf02=01!O?${wBh%Euk5vzpD2CBk9acx zcjw}U+fl3m&75w(E@YxmIl@8jZ0=ke$6j*^+PBjqX<_%8B~OJoZKgn`aLJFm_TD?7 zDae6z=&CgCtAGnQdNwGoE}rPJ2Y4VU@_Mt=yZIE%noyKG2F;K0?V?{VM_^uE?Kc!t zSQZ??!$G{1guc^O_lh0Catk}Byh{nZxvo9MG=k7r*$eUzOkBRom-;O{rv zr6Gw{d2Ly5sc=+-v06Cw!M)Dm3L-k1z;{pkaGs}r<#xl@dQgxx1;-lmvflLt*6Eck z->q`W1}vG{Y#Q`s<>h2RuNFjFCA@#S>yVm>yJC`Evu4T?uO+hTKRFecQf~ON^ zJ$boek2cJqd3q>C#Pz%VMJdfDVLcY5E8_+X2FPXND;ybvc?FGM)_>!Q+LX|CXaAL&{Mak%8+5=E{s-Cm%<_7u!__lqyTcEY16o+SMO{ku7?bhGwy#e+ z8ps19jd34z9^1#gXGe1c-vB4+cMq}}UyYn!edRYmwVj7<6uLocDl-u}$B7YM2{9Xc z*@4boOqjCHwh=9}>I&=#;W59A_HCaQSD5^*x!mmw`CE{2HM>;Rx=Zfk6*K>UO5e$P zx9OB=XR89ugEOu0WN#5i(jRzo-rV6(Q1~`P+k$Y+__1||H~PPvUR#y$j=TRy_Fe&*afl0O+9)Ia?No0cl$j^KoN4@$HWqchbds z6N1=YI%1+G&uVP`qt(3NFB8B)XHmOqWmMC9L_2XS+uhahk4g)JgRY&IqV`efC<99m z^GGvkW>bAGQ%47z081qzoi0VP!NFaAtk{6>d#gZu<>jSX~rrNs^C@=niA ztgpI1fIc0Zj=V9P*L&(QqDSL#LzI2+qB~?GwK zC)HIt^-9=Nc|6|x@AZg?MB^?*vYJfgyDlu#4d$lL1zonpD~DFa+#6qWU9z4`HuE{9ra)W00vM-*Uru*B>gtGy3S~S!!GpZNss{ObA}@R_+TE z(mRx1-IKf;Oo?(lqSR}uMCQ5OTWz{(1=Be=QTbbYwS zZMwZk%r*ko22LkReoRt{}WwwRA!09E2YAY{iK_LwpsS{<^&G|bj7O)Hz zn3IksdFdIZ*Tnmi;I{RHcW469f}gUg%8hkU?Lm1`a!O%#!c46p1md?_6pcn|a2F7WWn(6p=w#dldu^g$jq?DNtDz`Wu*q3e>4p2)t zaLHi3I86DqrnK{LhOg0j{A>~$*u+22HrVBBL^Yu$x@4bf?}*$^CEw;ULCv1itrb~Q+83vkdES^x!7BZY$+@FeF0z*6 zEEgw}NxG$A2wm=ECb#3wZHg(isrt&c@I6vspX=IZKKISdUw9S<@HJ%mnC}JdVWUI- z67DN_Pr3r-c5Vuv4+vn|1u#-k%El`U_)m+*1FK%d>AO|wtc2!qKc8MEI!jdAb!M!}E ztFS=T;%M=vRjt%i4Y7Xrnwtu$GzYQeZId$HOs0NB$)-W_T`C@8VA1z!jhHml3sWc{ zhsXl*Fy5>c;4o3KE-x`Oq2?erE!-mI^SP?>&ztUWW*s@wj(LK$grXH#M&l#tfdQNp z)GQB_j~}&q7()176k1;Gk#Uw(I$d~A?G`CLF2A7BVp!f3U)yORdyb$ic?rb`*ocMn zlB<6Z_(DRI5`B7ejiD_VL_s41De5OAWibBP5z?4Xe~g+Eu;-4gpb;JBAcGhq!S9N{ z4o&L{Sbx&yv>CUpnS8iT04KEd;+7CSlksfizg|5w__Vq2J^aSART?ARm5t)IF-}_l zD7pg)=Sv#jJa)AnDffw)tkOKZK-Rd9Y$wdC!rq<1fFg3s`50cpd9WsBzh5;{S639+f2c_Pn?EKKXCrG`38c`vJT4L zJ+lqa326U<#+r418>>_}Prs7JX^n(lZ|7Df`Z}(>W!MEUgwhMH7dLtNrV}uBo=j8Y7ZiR+N#vP*8W(hDQ4L6?s$9&ogKf z11WuLhe?waBz3TQq$ED92P(p;B|fxC@>QBM4m66Oh)Pest&_M)`(c`v8*{#1g);J* z3fc&-7HI64)`sTDn>)Kc$48S58pW+A;+PMK$+z>KF@I&T_@8Ud(SFxz%|Bg)kh((Z-kdc=)_!#N;jrlv`??I#LlSzd;kFZHHbgKJ-FpdhUZIlq zS>Bm0xb`!{!v#?_{McwbC@{NY@#H{(pL(_?YR2=67*Wr0Y-P~2g)79`3=fs@n=M?; za{e4(G`c-@XQcFzKvaVYOxXsTXNW0CBRLS7Ze4Z&7D9L1K z4b1magPq)rV7WhP?G1Bl4F;5Z;DkNXtrv=B^PE$I{^pGC2qLe4N|tHaNYKun^vRAD zu<9b)uJL(Z7DD9XAc=$49=k8FxG!$BBlYjvN?-AImSQqlwxPVLJO6wNYWX%kC`2XG zBBvcM#bQN_Jz@Wdo;w3`WY5;8DArP&+BYAHZl9N1z^e5ZO(LJv-?C#PUCL%6Hec6acEIP-Uq{8K$?rb z^hM`%CufhsD4UVPi%r_(C_iP7&l9=2Zg9)=`$P5xc8R)&hX%&Z;s&LBm_i1a51rpoByj<{z9d%te?#6SiW`xnt5v>2@4}5qhZ#V)O^H*@yaRc zVU)`C)df+e8A3$sE*#LMMuKTKw`FkBCazp65Obs_#wMh(EMZS71xzo~YA}Ip6JG|N zqvmC_%Wox!8bGh}Xi6Tb#Xr6r*BZl9l@|(|2|rGjTVu^WJ)c~xuv~tRc8bHW`yyb} zfWqolp-(9hTs!idsi?5K+;>QLdiWfM71e``s~lOg#>ug!CgIt4?U>aTwRgEf)YnBK zuMZYeG^1{A8^}?Ax~awS{q;3S5W4~T4LUM@LYpBA@@j^gj?v2P+{>n8kE%RTH6?}_ z>68*5?s;3RQR~$YvhMEhAz`<|E|NZ(Qu`(_4X8I9FJ)Skqs62XndtO*apUfOu5EYg zvT~Gv`#gLRQ=G!=?;F^#*WE*E<3g42ne+{a{e#)7ifCSH5B>GBUZom2CE?o2atl)*)$3w{dpGqLk^`eId&2%XM-0MamVlOXXuyGP%XX?4sCcN;jk0 z6UDP`ZCow)=8U3fF=lhkp=UMxC*yVeN25U`k;XgZ6t6-|NbJPP{tsPm8P!(TMUB!@pei)t zwB$U{6$AfKKLu}VTy3}0E?xkG?aPacZa>7JZG<0y0FbgUqZat__N4u{j&INCugbI4(~n1|aO?CYZGEbjYjv6g3C0^nlY=zFBU3Ku%f3 z*xvsBluy;xWJ1o&pmXu6BbjOYamZ$^nQ}2jPiYOm> z$C@*G=T;);n^Vy<-TYd6%A|2I(Ni$PUR2S1;N%^ydg2@(h|Z^x#T0U8X$PS%`dQfr zmwkV|Lx+pbJkk5Slg-?V=MNgHpJ9{H1 zewwMd&oZ9sS92%Tm7Bf^@cV7qaSg>&XnB+UGp+Nhf$g`O$N5(5AM~YnpVy%l^0m9| zyyEDF>91NMa`TFdivZ1&b;}HZTf|(Y`CA5WcMX--PsBd7JbxyR{pu-I*4awJ$jlvp zC-N!kbLmhhT}*Y=@GuK!2JdOcWj0NM;*eHC{kJ4jR)y{Ss>0LZFqOQevR`Vv(9)H* zrAj+bwJsdN-=#`U;iv0 zW5}H(;&&TjIz(J-$9n7Gh4ISfxpbxFceS4t6}fM}?yP7#&E7(fr@?Y*%5)q*YLj}a zd4ah^2=BtTk~&qYc@q-hB^#UDlY8mt;YUu3j#+5q)=u{9-v%H>I=bJ+ zD>IV}S%2rXW^YD5Dp}=q@`^$7VAsH-{ec_@a%pJOtG1tSpTnkd(A^A)XXwZRj4hdB z>ghw~BTCAuP1SOIRiM%a0S-;);%3u+$A{A3?2fZtH3geymyNRHAZlM0>O|a7Uu*>L z|FpTZJq-(Hm!WNAvDK%Rot`idpOpl^K)76yXT}yJfNbqwoC|8PEw-b%+oH2r&RYNg z2?-g}ri$py1k@wbmWlK>^J%RED;x>ag7+od{W#?N1_Mvp#(d5!e=x_oC_`ObeNs+F zA`CZ@W|%tF^=i~*WmRcQ7;FY_F6j64Wq~$NZ$7P@!M@Kp+Lmot>|3Qw_zx&4(=b`$ zE!y_u;p2%Zm~bji(`*nVt5bq#QliPE9{C*g6fl97&RW%`U~W~zL}`Bq9zkscuK^VC zk&gQ2@txE^^xhI)nu+bOQx5?R_9OdMv%>070@^$s1ZQALJg$>nlSqql^X;xI@&QT( zH>C`1w*y>-$~lnE!?d1W=LRlKdy|Dz^y>5W@YWUeg$wnfqZPc_+?+?s8GG4&=NIEt zZi!6MiLWn@+s;?$6awxY`q1X)THi)198wvaK8QB^{*b983qZpbeiTx7*a`0JZyqye ze+~U%f{VKOwFVr26M}bigg8I{VzM*)-XXpJh}Mku3~&6<*MQfdsP^rbKoXC1*jgA? z-8W{|yn33f96-l#ehOVYAIuE*kw42(t58j=%pL8hYjP|_kPeeZgaawh{Dpkjx|u$O zCJj$iF#c52T zk{4AA-D;En-IjgaBTWg!=%(I}^gbZ)tL3_-7o*xP6DzdXcB=;+y3aHZMBP<_LeB!4-R`v_%4 zkLt6MtMxF^zv9A%x};6GtN4#H4gIP~abDamv1474n%Eva{**3qCyqBC74+ zrPTeynNllmrB~)S&KMh9gvG~#qQp%~FN`MFop&BYdk98&(~*mc+k7itSYR~WL{B^2 zVt!}jgsCljN1lDTJoqWwFzlfsYqBvXMKoQ}O5(kFY(3{1#>9t&iG#c0`2(_mezL7? z%#C1P+W6mq-$!3meDcT7-Uz5ghE6OMwh@>crJ2V-MH_XdKLDRnb%|V&FP&8`DJmtS zO((M(h_V~#&iZc`P5f?5(uf1JrZxq!ndK*OT|O5QFzh?WyI|b55RQ=#!+N2)aJJ20 ze=Fu$8eI}(^zP&JSXDt{o|$D1Id*kc>(n zESF!J^Ztv`h7B2kQYA&@kJz9CI4H=kM9%6swxoP%J|$q}E@qcgbmO?}cI**MAz;5a z*2=J`<^GWzV6?1l={OEwtfW@l(2t>SDbr4O^%Ytx zSf6BXi?arSWZVc)ysTW9^1_~L#w6bdOg0g*dG>J}r_=MW8va}mrrGhnq|)Ladn9U{ ziH$gs?ZGwDnev#vO?{t?4-R^F_UkqS#u%>&P^cq~9{qFACu;cas z%|BB(GL16{dOCOlPsurfH7v_Khj;zhJ6M{_ub%LM99{;#?Jo#Doh!{&kO+-=T_P}CeTNXt7 zkR+IMFT=nYxofPrS@UAm6?5u0iO5&60Php?z2G=_ z%8X^9>*h?xU|Hx`m=9?Q*lh(;)$0~G^KQ_t;WRABOpLkcTnKcp&q?AUEQpe7CKxL* zwW6u&&gUuvr8PFd$uq`^?R__6waypByp~tbGc8FjRNCmGgKb-0z0U3b&9V*t`_Nol zdi%tLNZXm)nJ)LEKR;48a%Up=$mdKkJ! zD;C*jFt*W__S9nP_Gn zI({mXIRIoB(d#YOrd%(fqgby2bkH?ZML1|1Z|^j0x__|H{?fM`8^&(F3mZ@CIv&T6 ziE=&b;lH!zNA6(vBXXG>xoa?fkpWO%z3xx67ruD<=ntaMmFS;nwtdD<0a<&*LuQHQ z=CXT;O3C(7^P)VgYcr7kojSx1HTI%(NqtGBWPYF5-t4aOeB0xst3Ou~^b4(Pp}33Q zBZ~>yti4&Pgtt=r6X&+fne}quu24Dp>Sv=t-lCI{gM&!Nr4J#oWcNO#GP+W+WRM?x zG|Ja2*in08(EF2{K9mW6yn#>JCa(=cFR2!^LtCX{m76BqiP%zC{oWo=qu@-^eRe=b z8v`F+hZ^SSI{{iQ6kRuBN!X((zBzc7yyFb$p<#b?d!M>Zxm9k!!CHO?Ae9-0!4@nuD8cqk-47}$^>;~HNjHS z^Nezwvvo(^IrRJdiN!~+eq#Bn3=2k#IpGLpn);4ITi0&lpsuZMWEiK5C zljYPlXI$)Ssc1hsI-}-Ou@Pn3t_|>{;&$U1M$Dnm#GfL-uU2HPtd!m_3QrD!zxO-U zT=Boq&GtKHF1#-_(1~u&Sar^RCX4oWF(jhyNXh|#K5i=D>K)*X5&2ypKPs8v`5}2| zY#D)ePURUT?2G=olK=gUp#RlsXrrYfNvqs~10H!YfXndhS&$x>6XdPGoHM&`;UOy= z(^OWAnTePgztWrTIK@$Swc6^nZ?_w5tPtQGA~55+?<(SXqi@3vH(B0q9@eeZ^}=@J zq8OqdIp})k5n(kqMlj)@*&ldl)#xW8T4mA|;}Vq&^0jN3jJUC-N@Sr983TL}iVJAc z-HJB;sEumG9e*I^;0e4B-gRwDcI0u^(LTUyJeyAA-sSz zqWJh=STcaTpq_i_=tsg)(8n9h9cj;1wXFxPj6-tx9r3VXZ8B!TDn^U{vv#wmf715o(-7K}F?at`CeW{VIQ$-b)y%;o(TXtI`#uAl>Nv;vm zw0%&t&Rmrn44~yKEckt9exhz>PpKgd7em>hPQOuuAHMj9)U?7<=5j-49&r1#S58I= z6N}nHKFVti9p@Lj5J|8>*C#gQ4vzSL62LXG_4w@U6%qo1EnkM7nVoS*O*GZ*ffirWZv} zb~kTae#kqirS5j#3(NODY1e1oc`H6~k$89E9Q&4|Rb|);Opi&%+W|wul(hV%ea1e_ zS#nehYZ7;n*q}6*bZ?ErPRw%_Dc(xIhZmK^yr29#G`SKT*AhfW`c78@zV66?%7LPA zyG!g_vjW(*a+)y08S^E^AZ;IqxVA)9&H65=mk1S1(H4EtxTuug@iqM{#}n4UIK9}c07ci z08xCR^PV6u5KFY*PI@T3dsoIshD;eKXlyTCygj(;TE8^DE3>Gj2qJh?B6L_XT|x$Ib#x3HdGuVrKF zR<^0xUbNg9RX*&sFQrx=wyfFuuY8qc5b;F8+R(Dhp*vXI{sLYsBgA=dj#^pX_jT;G z@T&=m&VY9svszDGx|`@B>Mo9^V>@eexAtv(z>SR)Q&T}HDJkYH#0di%!+(rEp?fgl zz>pABAz|Uz8;al&tNikE421P)Kli^{y1t)Z`?}FX2T|sNlx9IuQ9@>>0>Uix*{9xc zw;7aA(*QV}Krc#5k6X{x;daDu7T9aY!4w$`6&QjoInS1zUM!>=+o5fi4!x zXOJfoZ?q!Q3X>ZLdbtL-H%jdw4VnX-O-zKU&Kr8rp} z4y?&-Vl?4JS?~u_<3z9-yD1M-q@nKTGOR4MKFu<$f+EP7&k@hUqJyB#V55H0C}hs= zXDNic{2*q*M{heMCFA0U*LaUC4I)Md@qK;vY1D$;20MIxcMA2B;6$V5WM*%Gd3R}J ziT?1NNJUlOc;oCLv;$f+UC4Dl!bQS7mz4l4vp3JmK$GLVV4Kt_zBTJwnp&HS(NoX& z(5?(!8neAHM2N~J4Gc7fPO94{%K{6f-d~IlH+bC@wTad7O;kc$5@1H#c`s zNJ!qeb!Lfp*q4&+hye@nvgx(M!$SppLqW!cl~H<%QP}Ff+(_DT3$XrI&#{2?rZ^bR@c|x zYf}CVhr_QN1W0%?qHAk8`Wq4uo3!xn+Cb-%DMW&`wsxYAp=6(5Ix#sZtE5CrLnHb0 zPkkxk-WG|TqskZ=QJ|opNc){iATC=9n6GPJceX!2iKC-JI@K?Z_^2K26BB2~;wL5z zn602~rT%E_<`q2YZU?ZSKlpNQb`%FmWMN(U>A!|;2}sp^n}|o!v#Z?xBt9cUUP~)^ zT?#RJJaca$%v!@Rc;vI&@Qj%YGs}T^QEPmMn zapT+5t7em`xhfXY{?)<%tRmNcSJ4^BjLaxObx%RK zJ`Zy;?P9~TFV<22!1EG7P{hl3V#n;3$n2fmf6y|M_DERSdJNLi;9k`Mjib&e`_wMC zpfSGnxHl*?czj>yKCQa2rr=&pKg6>odP{5k;K4qCTlc^9Yn}4X1qJbSPxI(Als!VX zoU0t_RSaxhIs}43mNgo7*h5R6EJY?3pf8N<%{O=pwvzs^viWAcZ3aYi)scTsChkQs zZ^2nDlvKvq9q^g!m=Px|IFLk}7XBL7S1QgiTd1Z2=$hjRj7u=o1=7ncD>_)c(B!ah z|8Ki}Y(+fCzwToXF$4%UuPJ#lL47)A8;0d7y$)ORv~K{L)lhs}tR4xIoI4^>vgE3;9j2k4QhHKn#h- zWc|L)oc8nnLUt5o){D-X(Gt`G@l_U*z!+U$`uqIXAl)8 z7T`g;{7S3F$vBNq5fWYqL*}D`y@qQTcR(^n$zO3-zc~zP!Yy`jPuez8R7{L{&hGj(TygytaIghA4v*?|=7=3;`qtR1 zq$$a8z`|oD5x7{&6d3r^#%8)2T>dl7g}znycD_!?^Biu#Zi${04ROxd^Qc|#*KT5F zkBb|0>1G0@b=DaT6o0F6;a9J0$|=cFTunmQ0--hx&kZ%fBgySpwS35C)!Y17jF*ys z&BcYkW4s0n-xAk(2+sU#1cOK$`~KONe}ODWXlH zY8??C%C!)!6U@c^mk+#T!LQJ27vXbuJnso2*OhfG;v|zneyWSFU>WMYUDMXL=H z6)^ZPJf|o3%cwbwIhkcA&&OruNzE?OT8pdYj~|e$CZO|qI34ZJpcH*%OhsVFO|>b# zAL>P(Pl}U}TekJR`7VKaaIIPTa$Z=(URP2L52JgP+3rtD-43ega*~G1|Bld}v{4#i z;dbu#?}x9|!q(;C$7O0c0xCXZS65fLvwP$=bm`;P-wO*v#>U1HX7+T#IO7)7{f%SE zc9{{C?0kWpKtXZDeXvh4zjr7vD+85t($oJ+o9Kv1wjJ%<-ac8o6WT800kZxcxv<(_FTgUc?0awuu_w|^6059XovwJ}KclP-Aub8Al3l$XD%XL3knuI@=)L({bDt)Jxbw*KzZ4i^ z@Lx#5D4K0qs}y8ow5Om9j~*=2VxU{jj>q**5t zbs$?$+$;?6`&Bf+&!t)MyH3=2h#7dpo#5qV%HkZ`_N&LCBS;!^dx8m<2p^pMNXq;9 z#ri|+_qo+~2F@?20~a%lbuoKv$6H8uK+~ec1a^h64C(91y2v@rS#k8ZtEuk^+?S?( zh8%Iuyq#iNqYq~-)@FguRj@IZ9%?8mo>4F=h+A6_ zy*Lrp`0bIC`T^Oz<(89nb?k|XAc+w2Tf_uux!KB2)@7e_8Y+x;ap_z6t;dkf$(;Y-h9jg0NyD2Zx(HWSTllT!xmUCYIui`6Euqa7W@({2@NoSZM<$^l1G%Ym^_ z32FanN1uwmB$)tVb01VE1iRFY`e~GGb1JEPtD&dFQ}q5Fp^Rh^j;ta;B0@7z zMX{NmWVg7dd|(xhdvH+LA??Wt4dQ4k%K<3@1RBtej1W%<6Fi>3Gewz%{>@RRrK`s1=h7o~A)?(d9H`a?Bt;TZ2-o+62Gv_z}d{iSjPoHCHg9Q=>B}bhG zf~m=_@gA;G4=XC|hSal)TNpvecHXgQj(*`qqDI{gfD^})+3K71l%}KjOC62*4{rKz z)5=7*h%K|I6D1A7Ee1~a(Cg0T-YF7zj2hzT69~h0-##8POA9bIj?X5NIZ^+D)m-l5 z@@9zgV002skp0cfVl(Rh5VkYVSBf8NK?3^TNQ4zReGxgGtF0#;7-2lWE8Qxqcv4D7 zpw74Ac&cI|AFnA#DKLr4b9hp6I_Jf`pr7e8ETLA99+DfC%3H0{{=KeZ9=<{+b3AZ$ z5#J3IqYR#C8;Irc0cxqR0H?}wG2b5f9P(V=_kELtp~d3!-O)|u``}IkBFWAEvg-c+ zb#ihkr^RAiI2+Rt;;~!L)kLRNC5;^hhc?|;NrbVMee+hQn(28MWbgQbQk5OnlC8s; za=c!KeX7xc&b$XdgG~psn78147T}WN-xKjqW{}t7pp#Grzb9`$AQLMG3ubGmrf2tV zd1;>cA7ef^&sHoUOpsB7Qh(hX68dTqD$VYE$cx=;W)0$-hV)SUVC+xGAtCJFL31EC zm{P@sRK{VrS}*_H5wd%JkLp1q@PnM!YvVj99uaa7aP;gSE}|$M@oJ6lcuI$zXQqy? zA&fwNQ3qDq2NSR5xtGZwL2ey7&R%SaD{UjI1#hcNJZ+RvUiWw%#if-LpOh(4Fds2r z6OB8FuK$9>n}IO8Gf|!uF0ZqUHKTYRl|pE#4mER|!QXyXMqE2{8rh3yJA2v;3p_U9 zgQ>CXsmu85vJ>}?Kmy@>YRgm0uM;=wet=ocLu0M(P_&(oufO$NS=9*@BqlHKDJd+Q zp;J7tyON7!JLliVz1kT$^jn_F4gEYuA;A~0@m%UGhDJk{|A-x*oW$@|7HZTR=P48e zr>Thfv! z(s)f}nQ`rZBXyEK47p^2pi~f`E4F&5P~eC0@MNk8Ie}u$ulNE6GvsA-!SVL8oz()Z z1ML0Z1>T=R;DT3{`Z$V9Exd&1aP&tZmHK)psvqD1Xd#Dw^o5 zqejRN4mdhl{o{lEPsA=t{d2X?p&xu3yj$#z`Y#0VxPf#g@=r7^r|py|hrA4zUz}Oz zb>xM$BMix`teE5(G!<#z55|_1B%kby151bIT6vWRhTZ`jaeCbd?A!sfM*8S|EiNw; z+umEw>l;b?4T+sb>Rm#m7S%MSKPCtOS$XznP#Hmy^sJ0;L_325*94{>(xqp;n(*#f z(|&NzVhJ4GM}PuH9P;zZQ$MgGKUuM#L~a5ayub?2Ev?Cfmlf7I!EW1lnZCG~3u|T& z9d9&$a*sZu=}xYan;k4~?H_N{sX96g;4w3KX@2-{YfLvW6pESvAi{VwA}gFGEMka7kvUW*q_S%86pO9O%e zp)L%8@1K)FP{7OGOv(o0lm&&5nwb3GYo&MF5i`?)Bd8T(sOl*V3HYT&-iO^Ypg-EQenvqY9otsvFsm8^<XiOCR`@ zt7$h&cCCCH28#$VdEPKW3rnAR(v#FZYK7?ZClkfy^=%J4Iyt5-tVZY{pN=zB#H z=79#23JS_~yZl~V`!XZG66oO2voP_|&YG>O>l@wo%BtB1&;teCmehOv=KaCg-jPXk zQDZ>Mf57k0{&$W*kl_7-wZjU#aT1Ls(%a zkDQ&=iibxao7v*rN)DU0|G2hADDGJtzg1d3Tg1EEy72tSCbveGxme>};;-rtPw$te zgC3)sam?G(YHwJALT%WIGItU8rF49alsHme45dMGQ)4o4-r#34H-3=k%`1GEoV_M@ zD|naKQ}^v>?rE+AX0<``W`~qYXQKLSBJ~M|2A!lO;7iaT!%zcTu?L1&%`xKa)Yv&b z$X@(lZ%U%S&0Iv!6*uN30~B$6@V%=8yiE= zQL{3zvTU_c4ZV3|?=I0h9&Yv;H{)atmW`ulC_ZaN&a8-+)x<1VS=*!7sw0muGxObW zmafBKQ}#qP`U>@_iLtF-gD5)yoh#!TaKweDu%Oy##AEssh!hiL z_d6VcIHl;X!#A1Ci*4j`wFC8zJm(ZAhADM~0tlD0+f%4IjIIPhJ^UZcKZTVw9X>oi zL!ktn<~kdA-|K5EJ-*NH`}ng8TIad?R_?){`o3Mt8LmkiF{F*qDz((hry3}09YnpQ zFAJfmszN>iD2|2!4C|=N!~H1UZx1?S%knUZ@|0DU%@2?al+Dk9A~%aVv@t|IxnhsM zOC0rgxb1PUqtOd(Kh>rF-&=;nNmg0e5feS3Lw>Et31qt`pr@<5n@TzLN3eO=P@uQ{ zSFwE^Ek#apJ=dT|!dBqd(~Vt`n|HgZ;Csa404vmVfiW1}V{%%Rn|1ZMxPFFQ^6d~f zq!D#{X_ok2TqgC5+@+S?ppFl4MotAsUdn^I0k?Jp4{V`?GmWp-k>eyyQa{PKp)_;r_4&eT|gPnvY=i)CrX4I-Wck5BKboh2?K5e1xb5MN|5EbFNN9;`t8Dq_AM{Il>AdMi(sv z=K4#m{n0B4cc`?ce_NFsv{Z}ACBPfliuG;*isCbE#8{ePjV1F&jNe4h)@4rLvOtzp zMtu9t6z598atopcq$s!qswQi{8Z1Gf3sWnPPCN+R0H z*IR3vn~4!5j5O(%&eZg@X^qbFmoCHm0W##w9`wQ7v;^>Ci_L63U`DwPyaJLbs@8cR zd`5!W;|;RO`GDF>eicpsQMv@~+d%#;n<;b>A(B0JZmFBMOH4{yMF?$8A^+L#RaJQ` z4M7RNs4o_m{*TE)NK`eDMkF?Obgl!_kqIFMF=toAv;{~uq^;1--C?0CIZ@KWt@9B)o!RCuMLpY<_<(%1u=JdWH~zpV zm-7Ij%?qQ91NMo$-J;(twG*qWQ;~Kqhx_lSn34SvZKanTa0InA@Z8p~KYGrnwfHkF zCQRBamNI^7dO+T7ee}TtG`J)Gp_{M-@sNM`$Ytmz>h%sQS`I>!{CMZ9%Rq8ufj9P5 zvn{xIJCL3SF#}P)ME~)A0gDbk!mM&6Cxogt;)S`-=OX@^kc}%5d4sVj!OtoJh#P>-KUo zsOK#3+bSh{>2guc4}kLg42LfVJG8%jUagx8B(!yZtzs}8w8ESC+u;i_+4|=Ut?T6p z6@}xK_cPy<_<%P(*m*v_T*tRkir0$B4ZSoQ^oRYRtLu-~&8sC?jcd6^!y0i7wAlID zuRgyx{`kx9QvJZ<*{A8>hd;?RhnMxblG`!sb?nHtu2H!vS+1IF`B`To1*Ig}N;4>_ zR&bvYh?7zNOKKJAA!Nz)fdo3y?M)ix+ekc#GW%BZqLmNJ9&Fj=Cgt9zjRgfL=T{;# zq+s#PktvX*Fza+i?O*?1y$Fvvl;S4ZJ2>zkhDOsS4AdxLV`KkC8&(P(eDuDV`c;#yPXDS3yKW&%O8^2q1`YRy7biHM|T-Pv^`CTC7Oa2RBNiOhsyX|ED zQXz*o2eZV>BE6OKyEdDVgItE)C8O3oTT;Ks^=G#-!ny(>qQhKzTr=Ns$}t6|H=uLe z!UuCye8OltfnUgv&^31g%lW}!w4z$}PW)N1`(4@;_M*%Mi1s25tl5Q+oOw3eaVCY` z-Y|Uq37Rchj59ail37iH_I%*{f?Q&!V3q_H{&&?`!1v0g^g;r`iox^2&;8$jTK!zm z7+A^UU}P#Q)+*{|`wUqmKL_^r{-IC!5%h_iQAKTPmtm+n8EO;cN& zNgkbmuz=iZ>^IOp59mn4Tq&2KV3RVy^7m+D5$EUuj_&XXZSx-`c@v;nX^9s)fKU`>eaHj9HrW^~i{Nylx|7 z+Qx>5=R?fuI~7Iqdn*x7$nehMiiy>Ug2-LJjJT+GXs|BkYw$j;jqH=wNoh73FZ{Cj zA}9NEtca9yGsPs(rZ`!Mz!}IYZTuRxQ$A2^2~f>H)$|!2tPR$UZTr#h_&D{zuA3#f zxwhSGc1MJZhnKX;;}BqxtcDoG)e1PC2Z8xdr#MDWb=3$^fGb@u<7IC4#Q?f)USGFG zius=5!7Jc#*mWg4Vz;0v*BipTKeIT` znakVVhWz}9qAxh*%H(;amA-ca2rf>hmoNa^8Ncnc=9*_qkJXrs=$#83u;}tWY96c3 z$g-V1xd{+%-h_`{nL)_5e9w6)npR>1nVIKa5*+XLUvoV(=q>}UV5_H{n(~@0FBLN* z4El3m76ha71B3PcLKTVkO3aVDI(?U?--RUjL-i|CNupDkc^*RlKQEX+&*M8G;U$La zv(Mbp-1TnABhlO&-|e=xFDbU?1B4;^b-c9z3ZN_4RPE>*HheJbmZ~ zcQ|u_$tZ=wf)++r-jOZ9(227>Dg5r=@5rgotH1*p+UU%u+Q##V-3EFw4saEkia_MI8Wssgs>;b! zE2{4Gdj3n281UINh_op8e+GTdGJhREpXcq|htm+XR!{qvI$@V2$PL!@yT2FR z3S#+~r4*Y2ro=zT)R@)y2CBjPeSaI&o^2$eqi0y`VCPaurmzgAjqrGHe!B3E=exFw zUKJ#+e2ZHpJ!b@xXt;sDrJk79Q`K)~oFlxe8;ynLYa2e9-VoejkzM+Ad| z6G0;bn$xxWjNOu?oD#m2EneXuLX;X=m2Nn=9Mb8ajdW?S*2nxej|Q-(oSmJ`R9CZY z%Om`+czJpIb6`D_m6etMZ@Eo{izJ#;^SLt{_fc6k6R?{4&6^)-f7}KuLqbBJ9eC{s z<1B=ttE#QN{hSdE1%>~w(jNHr<(+|1X3n-RN_WeZX-z}C=8S@2WYPy^a$cH{{OP7@ zp1P2Yasj{q58e$bJHUl5;8Q^?)xX}5rvxECYM zUdKD<5t(ePbmc5mX1ldG17EObu9Sn|PA`n!JP zA;bKi#~3kvP>IMzN*1vRo%7X{;j9$-d71>TojkUm)cMD!$35!WN`?c#&AF_I%SmOI z)#>gXy=x}h&eY*Dro=-ub96;hbH2xT+v`!|K;6?TW0`}?m((mBiL%0O^^H>|2FDm+ z)`O4RtNB;`Iv(j-0i)Iw23BpohaQCA#XLG7<@ zx)nrZb%T9{3;||FUUcc*A)o~K&^ifHwo5n0396+T`OQ;aLuYO<#tX@!dBWn`^uS_M z4BsoB%82pbKydA9_nt0*Jgk35u$jsZzlz5H^R0O-Xq=mxh+sdkr19%CYpki?Ap^z% z&L?HqtkA<5hY;me$adA?$k#b&CQ0@6*JhFH~aWF00SxK5TH3o%C7sZ!A(#edXsjZ!FA@f zO;tJUowf)*GyRc^bGJ9)so+Lq=WF|#X>G;o$I-JjP|E4FXaLn&0&jCY0ExX|XueG_ zC6;;ir0cuPQ{l}UnXtzs1V!}+T_Q%lBkJJ>|Bx}0#4&5fy{fd9QYg~Y zqx_rXG{vA}{pCu_F2W26<2y|Na#|#G^>fRu=UY1zQd{4-O+TDT$31wle*2l12y|V- zwCCLeNU@x{BANv0;WNYRV`#Yu)yBnxU_htC)7TjGp?bn%b*Mawe9j{&sqDKQ#CS8% z)n_q85hOF0_Mz2*pLQ+iDuCF(OGfG{Ilh4@G-9~-u8D`xzRH$ZbeDkEUHwvwEINT4 ziD!q~ppdLe^~r(VKt+E2$}l&w1pE9xVuei}u>0FRF-gMAC_r>0alHg-*SQX0U2yer zo^%A90ye*1Or@2ujudg(qU-M3Ub*OD89tt1Xd7@Oev5->-u21J8=_dI3DOVi4_tC` zTEm^W387rs<11+7t(E*5_Sc_%L>2N%JK|yOzh`YQc>T^WW_?)KM6oSbMNHUIM8|TD zU~peosM(rhYuaZ&g+%7-WWd8Qb1%Y{f4iW2SwpcMfH6W%VLpG4{QQ)kf7U`gGy2~I zOocX+F96FOe2U1|bgSut~?S z_*@YyDY4smEr+RRwP+rqyy5cFHzo#;=%Sq>UxWj^B0Ga=Yg}Y;NMYVbOM)qQ(iEK{ zr<6QEZye7}<|V)EB2X_QH+d?Mx zavnEwklhA5-W@;OL)9omXXC&_%T&kaA`7?SwjcE3RJw(o^Wz+U4g>OVn z3Z{8=&I!+ZDU!?g<`CYTS|iTDxyXanaP+oCcL~?I0W7342_X-x3lj^EfS=kXL*RLi5=_DoZV_ucI!(h-enkQFWGVV#@Bc{Htt<9Ba$T1AAq z<#jAs8T+1gb3}Qr93EwAjon8=cr;P_?e3g)oAce<&gZ7G_=nZmI-9z5o?(s;P9!g8RLK2njBvC}hy*%OG74AW}M z7Md)crixOSCBf05LVdBa68O>hk{euzHal$QQ77@A63;QK5u+qNw{u12El8D4jTgIR z?>rTVdjX^SPJV;ql8HIV;SZzOT|2FO74*D|Eyp7x8vB@`I;c{ z3Jp;e9C~_jxkzs}vxYOC!}6fDzsq^CnDY6I(v8C2PiXoQS31>;w}eS#yLVP}tJ}*b ztaT3v*&|T2cB3UOOKgGps3u<$F0eOySWZ!TNM+Ja0Z6eZqWu7>)Hzj*8}ME)yI+;v zb`63ctnV{!@G+GGf^@_PN65fC&N})IJEft5>Yu@;$6`C^ zGj$9!NgL$A6_yFk##$F2^3{$9*Owy2V2~^$af$vFwc0BHXqn)VQNe%Uy<=73qhhE%h;5u^+c({zuDHUm#R)A z`L<6y0|l+@%e73e{n94a@d$7)D8`qM#3cOEO5HgP)Dj^q=!m5F(u&?lz;vM{Siw>; zD6kml-&s|a*%IIArO}@4nTnH=qZ~jf$ih-7M~r=@M`)mry+p`uQVyE@Hfc+K&)7T8 zPb~2Pda}#nzn~=+xfv^FbbcjZz^4v}-}D6OP&8XSHWyxk9iQ(2uB~?6)y`X>F+-K$ zwvqM#rQdCXmTf+#g6~y%tXyl%_xR%w!`w4$JhDPthXh2LuQjdS%bOOtC^WX*nvvgf z883@wzwqlGheKOe8q*}J0)~qm?|uQb-KvtzJ+J(PTyM{X+;x$d@ooJnpWc)@JcHlF zRZ#|{mdxv=uSrb~Ng$fLvv!Y+zcfAMW ziQo0S*ZbG|&s@aBIdk^ed+oLE`?C~l-Fc$+<0T}lvC%DF@>#&?s|xlXAq`UZWxOhjk>IM*?Muq&DhfjQV=?@!2oPpm>uU& zo%(V>8`u1ByU6LG&p>PL*bRicY>nF6A=nt2Bcs$O7Db!%(C#Gpn^Vkmu{&rqR zT8Pb$5{BVs$^trheH}N=d|I*DkeSN~EZ;K}@)z`x3s_Lh4Wx19K$oY`_eEwt|L|kL zViw& zvn*lZgwG7Ct{P-FvZaoELCkO9VSb@eGckkLP+6g8{+f~!@{K11ve%5xX?sGB6odVq z7+B8#-y8r1`4;8H3{4Sp5|sTWM1e%>%6n0{h#z^7h_(o}#iM;R6ZiV4;g_QJfIQ=Q zGzY7PBe!Fv(l_;m&~DI$e*d^TWIU~ZFywF};8>_SR}`+~9c(}gScf?Nm1hLXmp~8p z-|F(D9l+V3mJ2lpIF&c1s)p595+HP#h-pPsHkZDP2%K7s##C3)c10!*=deKu2{YWT z;SfuC83v#fOQmX<{fwD|`roI*I}X1Dg<5nIx)g)0hpqom;f`<^6E;Ocl3ey`1cCYN7Hy`;mx zk=K9z&-BTkbN%(4KMw%9`cGc^Z{Ft4J;y-99)ybE+t&59fe$7jOYv=yO4z8du?pU~kv%OhyX=&&33LrCicy{Je-tbg-k7RCYYAZLRa+HFC z0$;$hn)Mu$UYc!u5)g8%x#gXsw=Yhj>bjzr&orw^%Nrv|GvKm;FwpMO{6Ut()wRTp zFnId-?}T}D)*^UVfH@3t-quzK-Ha%YA-^-9b%}H-B(9P{G>Hdr)L5|*cK7ueb%v3I zA(4z7ui0U6<#sk+*$F8rMX!3w-A7wulD8c`c)x#LxBOq`tv{!;6>s z+qr5iSy@@oDO5O)Q9G#yxR0#A7Wb%+ z*)cuc2mm%#GJ|GI%}z!_U;HioszjB1F<S$Y18ZGJM5n12uM?9O|@N;TK zwaEFm;vpKYOm!mztJ5{C3EZytwFBe#9bxnNXaCqV8(6mA1e{I7}ybIbQ(c+~fQFhQRTK!$6`L&r~lA z&fIr;fQK_4?|NvA`iTXt_^gnQ3#~Fzr%~c@x8!tNIg=!^bp1!v!fIbS#xGf_O03)j zCRXc2>K9&w(=qQ(RF7Y2wc$|Gt0fjFDf3JoCW_>r#YQ%mAk}oEiZNQJU47hBkD&@- z036%xyFjzT2+6$Q`$PRe5e;b7@o`9MiGdL5W&eQDuVD{7Y(Dze=^LSL-N^c=zB7>bmr-A! z-Pj}NaF^Evr=O5dmjk?n^lxRM$6dW*n}OQ;T1Robmz}rgj`v=Z4trTo9uY`a<5C|V z1M;At;T!4xx_eSsD&Lno`8&7DI(4Rc4ecPC>7Fm4gc2m3nNiZ*0lgd%N^?@;ekpdQ zNB7x4`uLT2>TOp?a(gs!UR2YcK@?O5m}o!S$&rC=vny#*Z$i;n&NPpDpt+V7Eo!Ro z^j(<8MTl@cP^Fb)l%A`|nWiN#Kfw@%XbLIILrU8#8OY?p+S3gvUydBRf!^T7=~%{P zB;a4ozwHZdYDcJ~WRoO$b~s?K_`PUnS!**U&$1=mP}!A@+a4jUY%g$RmM13i-hE12 zQ&p1J((q3VNj~_vxOshgjL|X%l@ND^u&(P_&~-{EuD^=h^aMJRdUboy9h+I1qb_kM z?~*&WO9{Ad3+uSwG3#6zkxME_n3n^bojRaPc70d5IqSvI4%6jQ`=W=ud zrmUnSm9Tm5CG<4M?KCUS?Q%Wt(qO@&GMbBnzU`CLtMwquwAV_0(&!WU802m)ueh=W zGd#*yOe``NiegL}9QyJv3wyXR*}mV+`)zv$ap&_loPKEYD5K^MbTF-3V7{rT39fb4 z?1D`^9weRLS{1V$RnYuk-grz%MVA;l0{Sjx;jdo9!8{?KwPtKwxxN_}tDvGR>Mrx7 zV#4HgFA5FK>#W?$ti9S6g&eKUwTRW~g>EX|oJbH@TU~LMT}Iso9;l%j8OO+v8#%yI z|6WJd;9u9#Bh<=dg0jld(jeWivDm8@ooUecZl+>4p7(Qi9Dj={uLZ4zIQ4cJ#^oT; z)r<}?ql{IeGuPSlpqsKRnt^8%o%fleU#SP#LD!yYgxflTR7xqL^Q*FqnSzH8YP+Wo z(#aUi5RF6hPGb9FPkAS)^&uDzTr@}bw}Je-k=vu6-Zk; z6Sj1e^K8CxlZ9)O+_G=d%@E8bRZFrZAm9M7%kk(D;vCXKGZLLC>wPj2^7q>(mK?^# ztky`}kJtN1*go&$LMVVVEmLZppCu^Q`7@W86TN-}VnB{(pO2|&q&&c~(5MhS`azBc zkxf5|%jz@Zg$wV(#F3u62zE+ojQ35VKq1a!z)wWI+`hI#YZ{t#6f^CvP5Hj;_J-2ox z-a;RPzXv(jw+VY$+?;w|e1 zH3cahKU}{$(qy)R4<1?>+kCqqSn3s%NEUzVtWQ&thtB19_pntRjPLKXZd*pR1p6fV zMJMeqGk4sb-Ep`Bp>u_H_D_D!gE2P4uRce9S2)9^4Q61EmvAkv%@Ry&Zf?8cetNd( zRC6Lu>M7YEkkE62v9H&1)xIlEXXFYZ8%s{S5l337G_M}FO6 zC$;W;E4trmm_3cf--RW|cWwi71rG6svUbF=OH3rpN)yo;otpjyTC3IXv6h_KGZr{M|V`h8hg3_kl&3#b$?bqECET7ttF!x2nqVCd1)2zgS|6@h~wip%U2QGaa~cxtpp4hPC+_sEA%18_#Oj~rv^7*y6TcG;tsvbj&Ie``lr6|gsfJVGaSdUn z4IeXX=j~Q@V9i@1-(o-8A|#TDBj*nqy2hTYAiD)o57Bi!R#fL9sQ`JMfo7~Jg|gfNbGaD-^f9H_Qb!?@2HwwD1Z07Q!|xSM z8b_cdw1URF)ACQHHEP=txhH&nsIY+;A`ptQLJGgtwvbp`r!I~uPRdCN$CUApMZeQY z!4px0`vh;%$m8i$5veQc7j zaKN*4FCM1=JCLqDHRs}`E8|XKYh;Q4c4Chi3wY06wgvQcBR!GY@th%QOS>vQ6Ow1u zEqD_1QN;EI&*AGEFiPHhSu8_>hkDtxR1+!)i)2G`)@lZ&4irjfeU}AvPUeU?Inv0_ zw>G;FL;}zUpD`Y^s`nUSQCDGfgkPAfC;`bJ9$YyRKE3lRd6|X-O%4x*p9r zV}2l^Czizdi4;1$_c=!t`H)$_jNPH`Pw-DZpyVJ--3H&sHXbV<-4Mv{F%#R;BSP43 z{M<^jWAgkqP?!K+DL$#4Wb6>2%*>a4Umq3R*z;*>p<`<5pp*3(Nb0XyBf#JsDkBtM zXg_ilTmnxnY>wJCDM1@E$Gn0}@9W})d0Dy!XIe(iH%qga4_E7rZzAPG=Cy>| zC)E4g_DOU+bfz~XnGT@6gU5^Rb>eg!4paRP9Eg>Il@SgO76?R?o$0Yl9U;9kBZ?M= zkNOhc!eflY&(M>vR!TFXbuq@{XHo?mL|%2B85nzQK{rlEEG{M9gCGT$%n}z#G$9ZF zXLDI}hY~f#eS7rtWg*%gv85J5bdU)#M5j|n8-1UYExxOv`|SJG{o8!IUfqFE9NzBN z`N}h#kg2@%a+;{I=;Yn$h7f)t)o&UL2vt89PQEDafWQ7waA0*UQ=AUx=T#J2EDa_> zkHaJ(c~{UhQVFJi$yyYjUo1(G$Q6BT(7>!t1UUJKyR6zq=ERbPxpl`zdy6o<5Kppf zF*qx;P4)7?>BC0mmL7GF4T4C!$5#!_t@1L9SH5X~e3#+(!y64bzd6f}HYCzf&AL8# z_z9{1-XinD#6MKM@fLi@&D^T^x3JR$<^=9b?Z$#aAV=^emWbPK& z(z&ShxLBeqx!%?(xF#r^ze+D1oi1%e+zGODbGr-CB61RN<-cQQ;=jj?5;Zr=y^NuC z^$}ZjKR@Wg=;2TuFo6+Gj+`tw((6%ak#}JhrHK|vl@{d0O-t>}bt1TxU z(;o7dTD_@&gsyTKp-^Q;lrnm~G84Atq20R{a=j8~M`c^Dr*}LiTFrRKLz+-a(28nn zXY5NBAx~MeGNYq4#UI=qoPi(1m5>R;8`+tm!=KhcTDpCybb8Mj!E0lOPIN%7)`+J=KPS^1h*HJRAwNeLf z1*NV9OeT%@H^>%w9nnn@nQW{v*A?gNh=LS_o_?G60ud$rXwl_(o*ei?0Z5o&`9jW# z-IrO`Ie+O4NuRXqyS-NITZ)rX&IG7LBiu6cfe!eA+8x=F~ecD*HvBzVX|m>C-bS z6{_j&yXDcjC5|{w*cFqc%jC#25{VxZh^Lo8$(P!7(G4d&%+X2Iex|3z2Y|1CNs)KF z>v&@fG;W$b6-;f!m}^dMV3U{^uJ`Pvu83rXvQATU#$SCg0q6{)2!(z-g1j zTIDqnpzvA}wVU4gY0NH}kkkj{68L~heTyAbv0m_x+GhVmSGZ>T207m67UQBaU&oc= z@SS0kS)A3SW;mRY8t zI9kc{yQDB)pIx4Ka$g-`6RaKV!n~Y6jy+Z*D1QgygCM~|6cU%>k<$$jxb*V%hsgnQ zmDk55u})XO*1HLGWubie(m#Z;cB>16jw`RzO;Hhh(d(Q9xVBmj-BbffeihnCo^0DV z-V(HFO6I*tTuiD4j2_>1Iv!zbmc+{HXmycN&94|_H|G#(4>mcs6E ze|J&?(|EPuOq-#FqIR;y?isTxZXO3F;MAuW3_H%&+s>(HW&fN^^|dPjbYH#s;`h%_n;IpX`-r-t!ByXI*jnThudVbkmhqTk z*!Tw(YR{iPma*f1yoA+VI+qK*|FsBSn3w&=zCukKct z<_Oag--Y{;#eXOk-AV0&1(-o{+R405r2TE5n4M6L614sB>jAXugtTf^NhAc1cPlP_9EWGKR$QEuiG)@?FtS2{Tj7!ng)0WJDmCQgEj;3{H$;X5^MB;uI36Ggq21^4MJ20=08?PNV!09j z^E2hK(tg6AP#ja%j%2vwwz3d`o>^uISBx#Gm;ZOLj?u+qLwtgn$_J4QfTJft-z5d= z5y}9+3fT?k`ExE`T~W}5Bzi}CTiXyslXDG1RSL5Ba%G&=(s+QDNK`vNu%8K&;wpvfA>PDt3b*3i<`ga#DP{9tJScHV{3Vv0vgB-u`+#DY) zx7I8N5LKT}Xx8ji&OWW1^E~bkC1i)vquk|}S6ehZfe}mpD1vW|NP&ND`p6j>NW2zZ z$+cdc?x^*4mv>r zviY;INCK;6nJtwDoiTzscNqychk^$)cjUHOIaWKqnl&4T)-UTp)RagrmtOe4_Jcu= z0V5(PwLu=6O}*Btrx{h@tm;XJV=oRe#iK5o?ym(?+*X2H8N>O{@S~_@H(F4cUcPu+ z`|)4V$$1y%5a7{v4ER_{C&^D$*TY@ado|#u0Fw&*bh=F8`t9LEs8#4P1tAEm1nByP5Jc|5r+p*3%>9l3POAUE%)mrl7Pwmw7RTRTzN$xTe=wPL2adP>C0jN3A7OW2^ef8lr|5+gf zs(HPbLw`POnPZ*(Kv>~Ph$1-Gyp)*Z0&JmN`qhLe@fe!Wkd?Gvm!Hfns>iAiVWQ*( zhxUkIo0zgdT+9l8nAtw{INK$sEBcsTdwbS8CuV4zMk%Z9AZeM$TB)5xTmrKlo9rLM zjZsk75zVMzICV9V`pO<{j3W;zm`yME6}tX9h83-sf2vC419l0<{Z`$Uc8x$cPt-&; z0Ho&W{AgTViP1ZTuA`~PR9yWzPt-UZQ=;I~GH)RTGc&*uk=clFry3(nmY-^=cwcG`-gmX_-VtY$p{M?ACx51B z=lalNpf(JBw=-besKu&M?^=l3)Y!*LrB4JKm+JVxF<~12F2k7GTJx_I4_;rmZ*eho zASGw-DZGW4@UGZ(!!9~cmh0sWYn;?v4d%+r`&lx~3evef=*s3-g0^}6B}KGa;?r*N zhq*&4wsE3!tPMpQBKRXV?Z<txhy_3YGmxuKr_N)WnTjqtoSq1t2a4YR z2vHEc>4_TKRrun%o7n@wQ4E*)kRk7#zRgdA|1~@~dA4j8!fPj`IsYA$;Yhb<-fYlk zI6F7pcg-F%MzM)G-NSmty0d3;(Lpo)B~|DHZ(ok=fkpt>OAoxmS5Es@~f zWJ8`MHXo~z9h@Gmd*Qr*W@D&xW5*>e<1}aT#Jb=*X4ZCCtsDbXg@Z3(vRo!<472})AB91mH8U8K<4}7iv-oYes z9sxA1{|~t3yQd-T4`rilAZVzOzSU9McH%)pL||kT9aTIFheDymi)HWLz5By2yWD}`HR)`cor=QjCA4N` zXJ_XZGUy3;+qR4~^&i`!8TId#3FrzxImruC-3@8ptBZ?CNs)1IV4SRJa%`O0?pa9>z40=oc;#a62^TNVH=gqv^>wkV4KKlm{w+Op81h?nK%yCel zBu{+ayF9h(2D?5AJa^50{4olZ)r|OAi0nz~#bzo~wnsd?tTt{QD&D~%3F=Vep|}rNpJU04pTjUMb`wW{XX5K@X!U#IlxH}Lv0uzX71%*1xZ%B6 z^$K9P66ZX*3b3KtZ_#boqU>7Ao8^J8J$ksyi@ zS-+ftgwMENC*r0q>~8qxhb`Evq0Nwrh}c+_bzd=tjLz24)Tse|x7YUrgbldK69FA2 zZD#fv?4D?o3kRl!uu%!2k!!xo-KK<+ij+u^PQ>6uyo$AjWtm!Y3>qFThN28`|DZe_?GQT`SrmVJ9 z<(anfH-_nng9y#HCDkg@VpJ?&B3y}7Xu9sHm})njf#3qMxep{5Q@OtIHf*vw4r@&8 z()=hG2*RPnm4vUW+|!#J(9X=U(wi(~Dcx0N0jM%?WEI{Brxi83Q{~C?buLkj#^~nm zh){G&f=E44+q@rkwj7URG5-ODZDwO>4_C7pR#n|!{w;$6Q=iT6PzjjC2mo(m`;U9W z(FF_3ti1LB$KpVj8j^IIKmv+G>G&=pCj2S3Q>;SC`Y_RKo0fwXA}Of@Di({Es#=pF zsCCrL-1g5io>51Q-M$BDyFRAO0G94MThsYgDah8MF=p$&=U3D!{tnB*##UazEcwqE z8kWyX9`7ITHmF8&-N~dRH-!`qF7#rOG2M``3mv@qejs&;r>e^l(AG<4ER!6NQl;Db z))C>VU(s#t3@k1swdN~6c=YqctwZ~{@X4|ZU=jH<7FXC-{*zZ;VfzoXr$?fbI72`{ zVCxhlIumU2*ZMxj9G;4q?ggz$A8<8)gKvayM(!^MV0JrQ4ILd>ffzK5qpu_v3~n_j z!F>LF?KkVpbUEzxU0vxnWAkx9Ex3cT-OUiJ&&S2sk>J3ETd)B_shZT^BK{)#5$GzF zJCB0?d3OMuSv%~Xs0#Pao&U_> zS6WA0mWZ(+|L&reO+Fz;ri2P^QI71!Stb8W>HUkb2_oi%0wjnn9qK)QVoa}P@Xfh) z(&o%se8?0X*Y|Hh_$~ZT=kT)FLsZBS>$al|qBV8;@6O1b=6mh%N?a2EU4eSbNV3$u+^|%LzfEAP3>57llB_Tr6aP>x#!8 zRjGlzUN@Z<*^?9v)7XpD2W{SeD((QK`-D^q-z7H_Q%x3=3>u_zFYG%A!FjRSt<<*! z+CK|urp8vU)okbT8>B5lSj5yXP`i0uONG>3UQ3F+dmO_E?{AJGu3Z)4Yk_* zRcl8VqhUO&lj4?SbGWGjJ_?VNlo)CBdiqnewmhlquL;`vaPbvNRiVjotgc!${b%9D z=qNi&3i$jK@m z{;Bm!ubFo=7%CetCwMU|9e zj_Y;+5c>hq2!TM@*x3POC-h$k_Cyedc!O>Q6Jk!KyfU(W;TrRy8eiGXO#@I0n9*@c*>8dD<{x)}Cl zQ{$5^i;8LD0J}+Waxni#VbMKyp^j6OU6#VYwRCuMRds6L9pqB zKuFYw22|4K+-t#=TTb1LWWiG)b`aLyl4b z3<|ufU!b9zh+iF%jfSe0R)s_@5vT#TA7FyHA5|xPx~7+ThR4RUKIJmX8)gg4BrChi z`8Q#swAL?3G|caln5jxXO$VV$qP9L9|gQTI$fJ$J#a0j;@5BD3hlvf=atC3cwu z^gJ2#0Xr)%JMTsC_P&hqfN$!h`!?eUs`aC@@Mh7x`AXM*rA-@vYO7nUJWD3X#92RX z%@!-yu#8#CGU}YA?hTvBo;`$q{b<-d0Uo zT||Hu^>uKaVVA zDh&ZMgM^=%i5YfFI*J#uF4=o?8cYkq?FOn|%2f7g{Vbi2Q6flWR#6%?vdKzwWCC4n z4b|my#`d$}!d@6|b4qbO&2cSfl5f<|kQnW{TyK&R-xo<;NU6rLG3*_*R7=(l88&EB zQsY zgkR!`ys>h7-U!o}xodAv`0$YAv47ZJ0{U4XIVjVRj_Ani3~l=ej}R0dPR+;&`z9$R z6-tR*kkV=~s1Gptk%_Bhld1EPLX|D2qjh8==A){A-fo^){ivh~A2T)|Lkcvs8+~o< zYN`^rH!Je`bBsyB9Xw4Ooaqn0g}^G(sw=4pMwu*;{jUSP*x}grd8Vv%iSy0*6+~)P z_H=o9)4Sa)20^H8KfoFE&KT;vl4dCAuAYTql62%Uf49LwiVz_9C74wVdTQA`7A-u& zxqo~(TXZ;MS#&sDK3&kGDpOf`SutzMWMT_NG^tPga*yNc(CZg|IHm0;wyV&6v)+!c zd8T~!lB<+AI44uicoWK*(wMpf`q+6lnRmwX z9n5jmFDY4ke#`1w&mWUV*3_>VF4N+5_BmZheW-Cm#P6c&a7fNWD4kFjA- zm*ZX^oz1MA#r65miFsx!-#e`*2fnbNR5BP|A?%lMfj^-{v0mox&UTpgUAnN(LT3~P z`H&jIdo)6YcM|y5dA;X##7asaWA?^XdY1HQcJ1e$SBv)tw(Equ6{-uH^R62ug;F(l z#p@;3FbvQ8D=8IK(&bvIKS9y}IS|wS_Y5p5>rW==;pc(mJ89ect}3H3EIXfg#3J%y z3nm%w^o}BUlD}_$zsSf{pIK$r+m-eP!ES#(Rnl8Lt+M>fKkGU9-ECnjyfrs`vJ`tb zN|UCgHoZTcRbQaAT&UQw;DW zZ9i7~EoBClrailRWk|3jGUY1`an=tj!`m!{O;$`cGl&)>ocYm%KOY(jQavNv#u#Sy zr)sk=VF-sB5Ov^Ig#Mm>JHuz9RMDZN{XmB%5wcQRYwHTp`-t{u8d1K+lbcf0Xy_)U zrCe<1VxHG`pEZRbN!>fTmNXZakk$$5-Pe)&lAnF0)$}Ww zQ3saeUlC>-JPc;GWp?nW z-a2jRMT@J~yaSX&j!lKtjPP!5sh#7TcqKVBshQK_Yx~n8cSC9Z1aohO@(T)4=Lebs z<9u{}hNF%-GngDkce>jfs5(FHS%Kmo%?z`)@DndC_^hudl({?D2@ojmFAbgxbW_s~ zx&4%8aBk=Ude!Z$09MAwc&ZE1fj-1{+DxV`Z(Un%k^t+#pV9von5UA=NK>lacaYQlzf5qgc%YeF94w=ejfFSc zH*Qs2rv~tp+k85y&t=W_<+oBV51gYw@MGHZuc|}*T7|JdYJvvoA2aiKV`pbDTYKf4 zA?n8K=x#YTeEDH?^(HMz@Q5OS+8-09(bAD*(N}rfVL7og{KyS^rS@xS%R^UQHb?gC z5lF%GoTxkMo&Tc>oIfT8t2Hcd(vrjE?dcmTM~>%ma$Z3;Kl?qpweJ!31#aGi)AqLZ z9Kot2)it;JRL65l>|r_eg|Y5X?gi~wNtBIXHO(`D4uVoxtdkHm2lA1O=v>GoJ#vW*0vioN63 zeeYhpuw)evG1HQ>kp1{m*tO@?c23iNul{0Z^K34##u9Guosu^(CUz&dc(4-|y1ifVGgxY`7Zy-2Rf4z-|;p$c0r?Ur7#I|H6YS=U0#Lmn05 za@IR_NrsL&=Nqmaj}5AQs-}rlxKx_=zI$d*gLpkwaYvF-J3WSq9nmELq2SGihe^M5 z`iqO#Je|VWl(Lhlex3*6(7q+hE9||r&iM!K#LCIo$jEzdZvh}}WHnbEflkCh>>z*4 zX}ch0Vv=nb2AF+X_@j$u0J!T|emMZkbCl(d@d<)gRV+7T-|@amP_E0T0q3UYn;~iX z+{Ua+Ds)+t>RU5V8LoS(FllyXOHnn|C#{UJIqdAj%;e+tb?_;eFd3{)NU=ypv$WSl z!=wzAPmtCE*AhKa=boIKWr zOo?mg&?>w0PSu!j>kdr4mnlZHI-$j}jTL@b+k2Ys2>Pb}MNn<+~K|iLeT(MKy`CG6$hM z+!0Pj17j7|{)uO21zPcB8g8EK z5DI?`#Jz<#4dajBHPvDFjI6zXfBxqSK@6F;avNY~3&V)& z{$OvWv&P&^9$5a#VERAI+2Uy4RILw*H~l>=cWqX=Xm%9BHenI5rap z)=B8;ym$9QT7jC4vn%Eow(5vFj=ySjH)rpNXO^nomnUs-rKr+Y>Sq!cejc~SdEo?p zOfRaYi*)IKu6K~Cv(gwyx;ZR*-@+b2SkGx|-h5V((c~Q^S2%0H}=mBzIO<{d9_4Gn37r zU;Dm)Cwwm?G;B6zwpC)*Zd0buK5OSZnqlv3@9*W4vzB00UR%AAKf3gV#4-fOiN|;r z>Zt}PpMk_ntL#FxYAkS^@3bIKT_GaL0y{4tQ}iYUE>uDp?bi4D>6&{zjWjzfbUO~O zmh+Xrm=Dp}9)H|>O{Ec2%7AOUNbH#U&^6l0M&c6TOx+y<69VIelv<7TbIs1<>bb^~&n zt%GA)C!qg{%l?8i&;-h*E*Xnbglk4CaMrd$TTWMZe~Y2uj5sVj-1O&1c)*#-BV)Y@ z-a|gs;!b+#Y!OK2EoNl&GEN7S$C|Y|wj63`XjpS|)SFC;#7YY|eZR9MM^?1$4 zz+5wXFoAgL`sM;8rj^o#X6rgrOW*W_o1L$%1^dHKLans>ErS&gy|2U>>p}QJ|McY1 zantn2ifs3sS1%m`Y-2XsNuo3-B5(9_&m-bV(L%$S)NJ|ZyuRH|$-|54zPdQRKHQ{?r(5RS%h}bt15D=K zYAKjWv*=7n&oF3P3*CC^wZL?|iTyDCU)aE=`GfqyvrWkPMSSPIhza94yL9(I^aZSI|J=@#cFR7_{ zVdp@D0CJwTb}X)OqPe8zAwP5CPYTI8=$ZMS6w!II3S_{DKI5KL{mOxf4)$gT2S0_h z(O~#adyjpT8O@w*db+`aZ!W+J2$dTAuqD(j*c2;!d zn#E9HZ{1!f;Fxz)q}=Uf@2ou2750w=Yuz4C8pOD$uvPlt$IB#zyU%1B89Gs>ln~PDvrAz92d__|&$UoTR z-=s~{0UaZWR+{8G#;L@m(eCQJXZS&T0b0;_lc>Jf*nJ!9-3Fq)WE}qB^2Ow)LY@Ai zB51D+FLF{#(mGY=1FdbYH5n4iRko@7Q| zPB2zat(Lv~Vo@WmMvRY7lYsU8E9eMaKs?;`I?$5+VUNO9_SXa+#5&iQ<~^3uAj+E5 z#3LOrLuspfi=7kOGq+c8sv9j?PS=tJ;SM9wX zqP730A^rV9p$xUQxV;qT4wlelP z;*Q4@2MPlhwzucqrT6!p`T2L$i&a5!3s2ymy?^ozj=bT#vD<|6vZ-p??5%_nPZLI% zxQU7Bf`_7uiTCk>;mEknSf-W9I(6z{JDvr1+2&z;rPL9a=LEjMZ&)Wsos^M_I}n?5 zAf)ufO=Up2SEJhZaWJ=1g)7nO)~Ap-R&UZkF%7=B$C8z$w{pzm)N~^ zGfR{*gYivuF;slgOof>L_HbJusB2Dn_qAQeE_IIl9FrlIb{v)zQGTY6q zyKARZ7tsA(iP!lPd)m>?F9M9bnub6QgwdI&D|7H`tq3F}q&HlElY^aIJua`#kSk_j zz?Gu*iK%vo>()?OC3A8dP=U6#W@rsSFZ;^Ptf)}fSJX-zQk->6Ix{7CIV@x8X zCTt|59e;e$1$x~!yfCMq^!W;^#o_`pxxPXp7J2%!v-L5P>8ZL9YHWuDN~r_wYuc<2 z3{|y_SY;WUg<%$#M-@)Zqm!3cJnzZqaz>^vW!8q$geJ0k5fBg{g1nB_MY5*!VM{A*$y-s!=ntJKPFHZMo)A!RW|oqIeBH zu_fjc^eWcjroDwCo}w~qwMd1=@rejeAB|8=eGr)th-K9Iu+oU2gw_~fgM(<`ajLX~ z{{bWQ#nsbe3SMvQCzh&ZJOU{fnGJ1;9xUmm$jo=a z`N1pL(~3~3W1Oay)T)kW+p}-wEdVbq=lddJp+QFSY7%uJjTQ}D>p^2(ua`otn!$vS zo);`*8awLqnFb3D@d#Lk!6ZDPw8OQ!7Mk839(wd*l=ADYH4CpmabgQBlz#yGR26D8s~~^eWgw!n=YGc+lXa@3rH5*^I%{+1l=t z-BKhx?Stw$ynXx8x-Zz-r4buYT@p-BPxDXzi!Jm#eq zB`&-n8H5gox&GiY=3w3T_VXXn$R9JH43t^l5cFv;67_YR&C0C)xV_`)MUoaCqqx26 zNnHx`N-ZrdJvccjZ(RGaPb=fB1zoZQl*hpSsg!gO0TJy7APTL_qaN{{HnQ27oLu@S z6xf?Kfs4w3%i53YYzR5m_Tb&s&@_`@O`NryGzj;D5ml|4YW7*oTabo)7t+?925-AS zU3ssc?wBc$CicH>V3=TZh1l{<@va!j^^V>ixQyAm$0F{A;2q8x2EGYx@J+mTBN5sg zdp5?GZGwtBk5!@(>#WVdU=b0PUq3TqZO);u5;Ej<4ShDYx`+N+*M*waPjRDFhe61z zu-i8|1JaEUDtkT6zH&dBTA5gd%Txc zbiF>lW7c7?C;0!c_0~~Qc3=D`ih@WgN{5JmbayETNOyNj=g_Aa`<%1S-k;E#xPK|gw_$r^sRfnJQ`E$nyKz;5 z8Y%B6xB4V9aO>}=CjJ=8U9oh1JtJwyh(67u3J(i5tv4A=$Mh#vGi~5;3spp z`t7yB0fqM%rTvMn|t{BGS5ux;e6!(W6T0g z4%QsLeCfe0*7nQ(3uAu_fLw1DKe=pNFA#b-CCagzVv!8l7D8Il6c4;?h$4LSW?Y_b z0K3lzHL(2^Y56A)bwHN0cQTNxq~Ub$;mq|S6nQ^f~0cdE7b`V2Hwfr{mD*ql}28-;4%Zflraeut*IZY{{BxH z7#P|btAvSxBm3SsKuSCU0=HOnKR{)3IO_0rrJbTcNbxj(aZzg5?*NY_wg4N4^pP2$ zn4<&e=Dm_QZ0zcAsUeY^#?Dj*M&8Nd_Qq+-udCIx>6c(3!l`2Ug_GO=@4$7qnzVb7 zXnY%ar20t1(%!qoHs3$;eVJi4p|bB$Y)3YC5m%)K%~5&kQO_nntsgU(lt0q*j@oZ8T`Z%LRCAQuKhI$=$SD~zX&Cc{u+-%(N}JCfisSR< z9iNV1@}l2ryG{rSn~%H?&J4L|60b|8^tp=pkg9y(QmyWMF~~;*=YIa69$@p6iLGg1 z!_WWk_eSPqPL0hUo^~{1dY;S(+m1$TWwV~pjQIriwtL2>|K#&p6^uHwg+jv|j6C-F zX_vX8C)$G4EXp=w;&<@wc0`@8!k%_)>)RUEhWkD6XMyJK6H82dFzPtt>TRCeta@i& zLNr|FD)CJ6-2E~Cdad9kll}|R4817hd}3s!E&ad3zLT{%&6^VM@QoCsE*&|(H^*iU zI?st`Y4!A-*q*&wxMc&#*Qw1EDknm@XpfBY2EW8+Lcg@MIKu1kEOew*RH&he)_SA9 z&bVa8olQkpyF20ST#x^^1?*Ytf1?kLNI&k@ulLBg1vntP6H&sgNXPX9-JAlu?7V)h zUEPyg`#2B-se@W7iZ%C0B9Qjk7U)V06t1mwDSLGdJWHZG5zi*K{(X_w?7xMr<(r@ zdE^GUG5MbRd#^SP_dlCwnh63s`$YAhB-#9EryFLpAA|ifvxEfM)xq5U_kt!*s@(!iHxc2fEyUE-Nl9W>F>gvb>if)Aq0%=`=B#A7i?N5Sqmu0wj1h&HuzjOu3MC6zpJ1q z==cO^Q`;Q7wo4|CXv{p1d|#}8cY1b3`{$w=9?zVQMp7a>P=Yf4>z&V-j85P;YUFJH z4Zxlo+JBzXlgjt<+nHRy=eEK?Sjd^`h6?RoWK$^2^pxUlEDa70R;^6$zbk(zikVWK z_+jDa=hqiaZUdxJ<0S<;H|0OFY>Qr?h(6w22yu$m*`S(Suao&} zWUiswZsERDv?Osj+8@yXYe_VL>HlvaaARyp?*a+L6@vR%V?V z9UbM_?hz2o!XtbQ%&4fKzN~U)$jCVPf@DpV-8;c|C%Sp^FI+`CkO0Ta!-XlHZI7mK zOBU%GxG~0w^xCgXt=DsZ{@CGVuh@I=t1CNy$k;O1zFrcETIsaER*|%_cnQ+9eNRsl z1hgKg2-1i#x`Q;Ma&J4iI=nt31;?hl{cK5+oJ=Oqq4^km${w({XCI8fLI#Sdx7hnZ zdSWse-VK7yn37!7)v!E@nij6Q7J_hmTxD(3zQcpy2>vXfY&^ZY8eD|pxPhO`go8qG ztc@pTX)CWZO3`?H<&BD34x^56=-C`_KgrQ!Q)E&V*O`wuhtjiCJ`6}JzxMRxTO;`}rTi|DWRp`o1y8H)1#Nrp)iUnkam7^0JuDBpyq zVGHYmywdio!~Fbk%X7u8z_>l-T~Q*`-4haaF|pOcg7faDY~IbVTz3_!PF31JG(2(N z^W&kKCjnPmG!C>@-cKQMs(c>1c-;F-x|OD!f*N*~^)fDXAwP;Oc%QcFpH)`~*n^Ul zktbKD0^j@)f59mmz10obDDQgq@K~CN6a6G>()8S%t}gK(xYGYNvveB-ah$Kg3`Ky= zNguL<5&6F(2YEz{u^@MSr*%Odl+u1KrPz2WV}mEp^YRiF(Q-2waiZO7dDN8BGbP$c zG)+Jn%2S^LG6X5cVDt6pG9ytbHWAX}Lj{EmUq&^h^i3HRR?2t#KlBHx>M&c^Zd7XokdRMk zT<#KN&lovx`)!n`1SV~N9>WafmWeAdoMrr3wHm~mjd zsN-<^M`tHR$VuIig1&EGI9WL6#Q^g)&*)J%2K>w=zg14Qh+F5|o}6|D0DRBIIOoOk zjkQ1^UOrhx;80m5NnFW!%| z$A(`x^j{W$RQb&X2~XD{hU}JS);zY$QqC&a$M_+5>rnqWUPDLl$#>JF zG40MGUaqyuf91I+uQFBl-*$DV%M?S}TI-P?fD zMa|DY=tJqdyVcX&IZx(Js!X5)JeE7vR;I$j1y>z=yVkSmT$KG4nn1x1WorQ;D;qz( zX(Ez*N7M2!7n*iHdXJ!{vdtR;V|Y}v0Jb;e_QfB}7u;0p&8CFRU$zP>?O6>2`%x;# z$yLvaxYm8%VGd7Ed?~?{k&>m5wu%2Ls3N|^++CDbj~j!rS%y>u-R4z**3(DPoU{!Q z8nPHI-!)Gu`IDGX$9^J?$Xu-sD5>(mRp% zhitL@ieqcX4SX8{STXH2LClSfWDDmweky)3M{IVJiWJbfh?j*NZo41L&R^siK86*= z_b+ZYgNPN!lw}=shuP%-)^!zUTai{h`tWBlZQ#_W+=xTh=A^zP_m#Ewn6_XU4)XZB zO)itt#r_;a!(K(&g&~Vc#fJU4h%RocmNS@AiRl__#HXf;*LJ8#^QBy^}9D zR=yhb=0AI#bPv*Pky*IfCS_vbGPadAd1x2eFan6$KeGLZlHIw0f9GQOsA{PwpFzjC z;klW8olue1_#C;$h)3+iFw;uddD#k>vNf-50X}wxP`%#8tA# zaZ$bU0$;!nHYX>W&PlSNwFAFiLyHRYqebv~7ChR_%mcHGfHz%lv*9-J#-~Y6@isKs zmm*>vdfNc)1@uss1*V}MLRx~_Th~XsPev`u4f_03?|dauJO_>Th^D4-KbLHJ9N;IQ*x(0k|IB9S#HRiu}V{Meo5YL zc{2Zac8CskzCC{~0_+g$qbgMDHJQ=+Bz|mdK}qqsBfFK${Me$z*XOcdVH2MH*7}-vj*!{nShnI6^1S#HncllC9SWZ_ z{!B!#n&i!bh!;a<)n)6$XM^-xzom(}2)tx`yH!|S%uK8XvRt-6Jj5}w88#8 zOZe<%1+&(0mp1FU-(2t-)VXc{e3wIg&z{Hd-Tf=@QNb&q!+LU7x%omd82I3aB!)x@ zk8Sy;^-o+kwg?@$`=qMeqxwIr2H0iwNMr$#X%nNMw`j|qv}xiAcs#>LG_P$RiBDhEv$1fc zAA1o?Qg7!lage|{cM=P(XO2`;z51!;9{Xj$hvUEUJHP2CCQ1Ms-)2~NW|(OvO3d^n zHy*%1DFRm*nW{S{U+R1g;Ne$#1ph(a_r3h;2=PA`1I_D0y_suvPyGzim zBIm_sPkI0h@I{_Xs$scmE}Cw%qBV_?FX1%d=1>Qm9^*Ent6S_m&Ah?KuVYgzI8W-R zwyB4OGp}2JV+^JN_Aq+3sm~SCm=ng<>Wsex$QY0MfGaJwQ<5p_K@D z?}2c~=%`RFQ-C@<&NwICIS>mnbo^dDcgLW%SW}XWK2ap(WlKNMknepy@^_ibk7*Xgt*-|BdE63j2%$9-ugBK1 zsfkLG*_~eJN?{v2;_*@7i`(?smQ&qUa&}JK6Y;d*-kaPxYN-0&v1m(4*z;(kSAVqM zV0td6z8KFNn_ih5{KK8y^ZczGkppA>geft%&l^LOYSqil!%<$YMUS#*BzYa0vHapb<-TZVd6w2B}Zf7oO7 zsVWJ^Uzy}Suse>hy#89=a=>HXC~sHcZFxRVKIgQ<*7~UxzoEq0rF#Y{*vk8F#jD4Y z3W;SD7=2Dx&l1^i<$LVuLCa|=G6dv}F;AHC)c~e`l5u-3TKoPOzP%e{v#V6z{75Sa z$ENwMI$kV0xYQVREpbMsgkd-P#0buENh}&`V^1PZ$y%qyPaR6x6Y@Q!Q?3QBBS~D3 z#6ZeKPrM2!d2Y$UpKc&wm$9HzGRF9e5lAh7_T8pvM6hSfQ&-xi@@HoC#NzmBxgK?G z@%S{k@mw0s$m15ih;lb!%}y0}?hhFo=1=zvYGA*rxFcQ7YNJj9@bPGF8An<4>$gtd zx^ZAf%j2Cns2`Y8M+qSu12(s8DF@#ekiM#ohU~h`-VXv0F9@-Vw4z?W$w5=QQnvG|5&zG_k_LH6bQ^Gw6dIZg(8I5Tn*Tl-qWfUa*G<>A zAuBHn|qHI5+T;ELIw&c6ezX?1nB%b`YAJkmA_EkK(K zShc&puC`VPVE?3r(j{2rtS!kfRjN-Tag5dWK)WpwJLHmLzU{H7r3~^_tgFdkvYK!G z#onx)Ro{}@P%O5KHb=AFB0Hq48+LtH!q2p-DJEUUKv^OwhrRG&T-Sy%IX>#(PC%h{ zRME%w{?qD$V)DgRuy}F8qKqs}aP{Sv*97%>s<;QRWA%g8{&MUvGV2ihEvazL6r{kkgUBc6;cajfpa#C8Zfpu6w{N5`)ooVPpV+M_-q;T> zQ6azFML{@VH~FgRR&+6W|R z4Ol(}oOcY*B_FqvFNiW?z+>+*4hdv_Wne^9`QMEo>%6ib>C1AWJR!_9bcM2+ZJJl%<2=8DFEWu^9}h z9g-oOf*KoX+BWy4uePBg1k+N}B1q=elaVq>~B=s_iezs?@wL0*7vu* zmgEYS_fKoF((-yzyFA`Ku?deDU=onADq$^OZzX;;`)MzF++(NR@C@2DW4i?YaRjN4 zgL0+qIvV=7U=A*wbDxZOM3Il~G3ge;{3=kIa3iSxAVPVfxF2r<^BBRgT1ko;8UoF_ z-kimnjQRH={I$IC2qkLB%KgtoB#zh4i}S60YlF$pb^#62!lnA~yeyy2TS{h=Q80N= z1${@kpQ4zF|BJnA@RtQQp0e_HWz}?Z_a+~e_usfrHc=*VoKNCZ+AHG-pEM+{FCWs& zGv~6^{9wVqT`wRwFwz`Ymq#BQbEo-+aP6CE@7iYa8&P<58Ln)umDM{7ciR+Nf7t}X zp!y{e6?sK@QPJ+#dmaUvZvik5hMa$NB9&fcp=c1ytGZfdO?{l@!0{kmxQiY-Nz1bp zTKrn)qA7Wa-LvqZc4PP30wQCv3`et~NMzD$iJXbpsiDzMEHKBzM@L^;z`{|bE)IB@1{czN342{=TVvji(C{!?AoZQ6LSG? zZ6CXn6JSJzuo8_(LCv#H>MSK+bF2{2%>G$Gzr!k?UX5m@JW@WYF%BPdn(Q_0J=wixbPG@;4L$U8UT)YpSwT@Ua02} zj@&>YrE~W<1bG}gQwzm%gjJ0nuwvG}p?#^FRI81Tc|-^qvaELOk7E3OOY9Wc8vLUZ zdzwEytnjYFYk%i2*Ut7y{Ki#JO&4ykXEwr~~o@!IuKQ_@{@(&PJF zM)QVzaln7hU}M;vRIAYn;&i}w#UpxFHKTA+;LYz^>7Vpu`HVYBMcbmstYD1hc)xig z<$UUP?^RuvZ!aS&u&){$G+%p$N1O+{Rv?qpw8V^}p+D3*r>_yc3uT@AP4expC-~5C>G^6RFLrT^46|a)G7HFV2owsDXC$nGf=pLs z$!`be*X3m+O0JgXmzE+UA|kFxw)?+XTdNG)c8->bm$l*VB3ny(UoQbjuK1t+p(0l# z6l0;zhR|T2?_{`enE&q2r1RN z{hK2Ni_Mm+4}yW5a?9wKG2jAj7sBUKoP)0WvV}nUnN-q+ro2qODWm+cUD*apYMNm} z$A-c%y#mLlAeX`Lto|1HJT3rn$1g_2)J#oU7XWj98ShtlcKT^uMRskA|0J!HUOEI$T_#^;?~LXBmQxe^A%M&yILKo{s(9@6^7oTqb5$ zqc5VOhY|3&h6fZY8hh79x2N|l&I`Qt;=~?q7Olczw4iG^e9foVqp7E9GsXQ*c*+T` z+;pb`{+ZYkW0w3Ru;iR^u`ZGugd1ytVR~9i&%ms8BD**}r8eh8zP!6j#YH*1m3d_z7-=ox2&=|pd3XP4L3Mxm*xc_5td z|7iW4#6V0P5hUu2jEvN*tT8z`?~9NW)tHU_5SM9`zAJr2r_Zkz8m;wAk92-4Mv9jCD7WkxI@;^3QSkpcLXmn$cmCIS(7M=@if`bQ6K-pR~ zGZXMe`nWQ`)y~6tR$~LO;%Zn1uJyT&5xv-o=PaG-mv2nU^84AT%U54L51YXh z;^vNSXsEKj#y_#;_XqIqCVcgZY!9&{XdS348b5_+MQ#35hT?*3Iqcrp@6$|+sT@IN}5%%bI0Bpi=CV|%UvJhz%0fKjP6R0Ls{BYPOS8^8u2!jd|Pqk zSF#VVF-p(%?6XTSi>6dw2>U&B_58G(vjMp>@0`ZGz(Ri5o8H&OR=s9h7H7SSC={vf zanP*$VA2-(53Gxyas*W5_a9vzz?nYzr`Ixd$99Zg5r*%g-kN`?FT2*F5@|q+PL}%$ zLm64P`4bY8s=JMaP`lI5A`ZnhSvi%Xyyvz57|5RKDp0Iod2c*N9Ii?|3`NnV*!*?1G zSnGWvzQgLk8SdGi0|rWI$n>eG@21vwPpNZ^p_AL|<2IiBevfibs<12Ft0s}nM5oR# zWrn#!Y8i@U5EXJM_40%(AGyRmN%ed^Jqz=`Oxmp>rg z3zT&|zyI|}Gc4Vn-1f7oSP4e4A3;Go{T3A|kHUlIOZYJkJr5ZCVMk z0qn`6758Dix19%PiLsKKZ8*o;k5mrObG{}AVnkHqb>0pF4BsxZISV#oOP9)&X z#5K*a>VfK#Tt>H-Vrobp;6*^y^SnT~Bgb%Pm+78E0%;4x&fBvJdgLo_uzu~nL}W^u zePwZY32EF$6OE&w?B&)hJb)gonh6`rT`$}96rFseyLyBiw+EwKVZ$f^cB00Mc6ZsO zyuQ|Qkj803MS#I=Z*%)E?+058VMlcc0NztVd_@S1S~&x$`|V`ddzLpe0ieNIdQxNi zkEfTeb)~nN>oD^Dc=>$}iSgI$-^*Kb8_EtTg}CkB<6E*Aeb#xKJu&+{{gdVFt$5*i zGeV{>n&Tpsp`E_?&ceP--EyZqvUb!-r)|9QAjjYCI8Uc zIR#&}Wrl~5&Vra6U(tYwV`F>2Ld)F z2axu^9oR7%WV7hZbYa2RVbuiKos-8M6S?Ifa@YODiF4gda~y+f@QkpmS;HH zjrw@O&=I~o)oA|5?(RGTS@FC2AnA72XJX%H%VBCYGZPiBeK|>YSg|`+S5aKcYB(^2 zYxz31#h>}2own@`Qp+@kn}1u^ZVpX$IG>>I{+QD0pOJdwdiY*mZzPAv?V`fdcuZ%u zT)#Yc)#+rQd=_PAa4)2!731Y;*Bk^#&>L4MAlP|ob?2h<)^A;44ruFpR^O5sS?A_W zDx8IiW+{c`wqKANe??W%Y1X5sG^D)w)^!j6bGimrrSa?MdC`b&Im=2ERdY->aQ30NKDd}s9dLq`JrT;V#gL5yez6`;Jfw)F)Z zHN(iTWazhZcl*sC^IXZ5&=94lj<`w0qFW78kqK?y!hAe zv9|&B=*x5Wpo*kpvm<5vF$D!8of!(XLU73Avo5q46BR$gr50dV+d5BQh{T_6@YYoE zVD{xVV!;@>b%c%g1WjMR&cSgCAl(9#bvJKa04wR7^4zbfW75qVfBU$#;4S6L8#Q~+ zm65P9+5+!En$l+ItO~d9ggx4Abxbg&U4U!6{jex}yHkazM$#07`HJig3c*DH!IC;b z0shUy!uooV;22p$ac1lcVS+C7BA_RqZ`=O-fyZG9>il9t3EqbPRI9hU9Bq6Zj{_3U z!t2136^Zk(f8#o8j8wk%_iwvpK4&J^qsS@O%!EGlSD4lsLbQ;jYafLCX8vkh?|G2l z=8Er1U{mo$wu2wq@-^0@Zfl(Rei{&3jCObT`}nHGB45M zKA>#5LSPEPwy5<8H$o%2!-m#eZ%%u={odn_d&g$&0X&Lqz!UZ7jOrSqRY{2keP^3$ zHxe=ChrmaRGM#OP#1n0Jw1rt9WgQDuU{GNW|F&Jz=3KVqLgV^AB!cwuj87Hq>fI2c z)o}@#06HX~vxpz>uvYk*FvHbLL`+vSW7xO{@I~uJsryIPb{-9e(|TRB&6g>B?I3sg zmLA@t3|AQiLz)g1bAH{1`PjGii2vBjPyc$d`f`z9hIjN2W8*eEGdSZ`b6cV7YO zBJS=h>Cn0$H((*+^-8NKs?=qH-w9reooPEXG*^`kC>3pSox&d3vfy8Zql`Z7QCUY6(>wgR2#v^MY|CEW6Sl=N?Tb_sSA2iJ z#BY@wm9LW~%Q2tzHmU|BxH21J2;<}PdQB#n-l@4XrcT}bYA+%Qw`;u+6#TGvY=gje!f zwKt3Gv_Rz10UNI=`@)17Wng`MD+4O`*jiXgL9&c0dH%MB?x%x>I{{)gzLctZBFMRo zkh(7*$_f<+X7DBGdTl#LV`C${rkV6fnPeJBr>r1Gp=dC>@K;dRzT@=X?mT)6vo)yX zzH65vEGC9D(;5URxoSWQdHvhM6+G&u!+pEZX3a~waYQ5p6sVVLPaF&o51U@NR*r_u zkyH=N*9F8_yv66=(<#sJC7p|mqT!k6X-*V~7HY+SY0^0_zx`2xpD?ktG9=h!E*muF&J{;FwMuhCkIKJ$W7_AVsF1V-|>Rjy&QgB~1<}tDUmfuJ8 z#qlSDR5DI~2u?azhA$}VVP54n(VcI3bJ{(6QK~<3Pkj7q`$_&pQt*uUE#UW$6M?*;r_jv-);SJm$~OC2~sv9F^y&gsL4 z`u_bcd*NLDL8Ypp|5)c2IC+oK0mn3(2~n;WnS0bqdH4AS8m#+jz{^=*hyD5W>tD&1 z6-hhf@+S}Ci%HyOFQ~m-bNfTvzC0_rB*AL%K*MJ@debdcycb|X{HKDDT|XDYO=HgX zUnu`8bUMGBO~m}{xOhO`;g6I+j zOQjyw$d*;Y09-MHjTY!@Yd^_j*NtZLd85BBWt5p0 z^w*^Ha;;fA&@M^JwX~I$&9aaE666t3LK^+*)un4;XItl&+}fu=;^I6GchNA+S*17Z zX+PJD{L_XD8ONYsGX&&ZKlKU+b{HY`pqLWWHH;^2Aw@)3^WF_>c3FARF<#cLYSVgB zE&y69DQYJ-jef{Nv2nJ|3vZ7NV@I0b2TGDFckdL1&b~k#H(yAS88Y?@2O9v95a6G^ z`{O%R%(*{?V4I)v7W9CD)Ik>e=eU)kHQ@=)erQ4UMx_9(eS=$FeZ=ML4r)DK1uv$wAL*uw_wq? ze;Q>LvNS_{G6a0{Mnkz6+}KziyiZ+3#?4y~t>=`PY4i9M+M4gXba8Du(sE)QELFlG zGNmbmtf!Mpn=0sh)Lgwsi4pR^*TmkFG3x&XE8_E7ClN?Lp!7)5?RTdxJ$pwVMtY4< zYF(sTI{P;88(jE3-T9mPO@->gP*Iu0ebMe(0cqyL+Z3d=DR+@_lq8e&16D*Y*r5;! zC%`)dCQuX4Oiu$mI6u!N2tY-AX~CZ8v-i`ehL)5${r7=;aN${SIq_7ZgC5uM!>eaS zEnM7h;u3Aj@^9|}2rWD@y-3&7dYifOz@Q*)kn3#S4}hN(9qFa3up!a}6p7*WmJW@bG?% zA2I3T?9eq$mT}MUe^lU|k=UONbj}GR3B`AV2WJ}Iw>*q4%8Cj@6ZL74bUMg-=x$%l z>_w;a=|E?Fh)wq6c#$FKb|&nPL+$VK4% z@o^x~(T$v*t>?y!%JWC;J6Bh?I62J%vlc7_iODY~M^6@c|Cm_YdV8!CCr#-|0HW}d z2=oI=?KGVDzvYzYd|whr=X3mJ_m#Eq_vB(#Q4oPFGfip;UwU!D(L3W|f+W_#Uvt#; zYz>+pIuo_uKh!V9GMaQdx(SWu3R}99A?2K>nd5U%(HH8}nN7#t zR9??k@!ui^3cAAh^YfvD4I76hA+7rS&-bi;6R4>|Jkl2XarTWcLbIjho&y>OOZBTa zK^%NP^<}J%&RPQzf9yKGA}(>>Tb^C`)N+L}hkV=1G zDE&sHtgq(E_#JB;_)hr#+`ti_X))g38dk@C|&{wGbN~Qztf6(giWQK4T8p;d`hfMXKGa z#VJl+lk%}0M;(S6h5Jx)kLQ{&++MSy0`7Nd6tJR%0(;Xv1nS{xa@R2cw4kaZS#{N2 zzVAvdW2?uVXuh{UuVmgr7j!SEI&Z^Kmze0y_gVNo5$E9x4B6N7Z`=EuaY;ppI((m7a=tfAIpX9DUo=Ts!sIzN=MQ#a4i{Mdgr>zRR&b>XErrS zRmt-3HjdRGOIhCRmaW~>#nIfPNhZM9ps+MT0LX+yY-y~ougj(L#R{IZ#CxB#CKGd7 zq`NlkWO}EF00o?!oIE`B57FCwt;&OQK|5@Z8Oa`dNH5H*vKZ}5;UH;VgMRMKCLLY0 zCXZ>=lN`r zh>=7V6p?$1adV}@YPi`$IP`-mX_Ko*WZcZ;%uhdQ-YL%A71{H!a78N3wN7v6Rf(!c z*|3YPo6Oop=H#^T0=?@;8CcM@ZEyFVXQq)@0zHaDAP?a0H1qsAx6e^U~(Y=~&VdctIeXZ2a2Wx4&A`KJOtB;;}0OxtkLn z#IE?9Y@n2$^?k4{bG{Q8U9!9pWN4&`7I`?|9QqgwDF666|kz6^reBm*f3*JJdY#oakn}gZ`)jpZvv?{KBE;8yCI*ApZ^W|2hm=Fe97>xnJ- zN6_(3la(nEq=0ys{Xke*=duB;f=`GJEaejr*x26>&&VhT8ps-3^U%Dlo30x*ff6ib zR2uOLrIidQj%JHR*&HC$;ix2^v|@;CC|&LD!Q3i_%3g;)6hE$?2fZTo^1;m>O_873 zI%4j_dmC2YuBrQIRkp91&ru!yMoDA&6FwSNv_W968{Hp$I90)%vb2-e+cE3(c7Pt_ zwV-wBKwj;~kaUtdrS|fk;F7Gj+|z3H8wmNdgTeu3Q8zu8=e?d1$RzAser~o+`Ag8V z*L&{%`=`uNTyx2BnL3~3Ylv;gzXp&-8!(J7qkdx+lryj4ETeeULpIlGBx{O&1#SGz z^L$EJE2E+?P(t|n0fu`oG8@Lpa?YE9Ff;#@3 z7cV2WK%>S2+P=c4s*sC$XA$*<146Cn)sV|Cy#CGZRuTuun){a&4}ZGx(8LU{auc!_?epD!ra?9T_rIED{>ebs=cvsLlU>v?Q;=j z?LFF`Hv;-ZE|sI9!1foIi_JsjO;1x<2?29kHI1qFFy{^ z=WQ}#j?aNm4hP&LG0OU7FzB|$)2FV>;P}6E zz5iEFRRqby`=iZ75FQb6c6C*^@_#7y$c$I3S;RV~bI(SNnVESMk#lss+)RTcQ;$d3kj3F2i`{{%HAz0t`>G|9q z2n%IJ4W^pCJ;0F{c5*ryn}>wFh8{;AV9dUncOj}my`7p8&eBH;x^meP#V(6sxUo;F ztvcxm(;R4=AKx2p!n???=TjY#9paLx?Aw6@B9dZo5QG1IX$F~$^oOdB=S@-2rq2DH ziKpk7x@UIdA?)$fTla@6$>Mq3-|#7P-Op+{~t;oW^*k(fnmP zVx}`1{OAnq30ymP0VA}HY){<|ehOpuiH|Yx3qz_=g}Gat7$xuF_@4Es1^>%NButr| z)j)31W)1V`b>uUC|GPTtsUS&&d?mlpP8h%sKPr#k8GuTexaNvxDSnMHJ>Tq^9Z8wEGsU)@UlGoe(`H2)5L z!#Qt!4nY<1`DhNdPoh(v%c>yov!Wed2iqYm_>Xnw)FzGpM@)}L&+!5~Pgc*NONi$B zA4hiNp=23v|DcVFhK_E7r!49iyS_nsDQke}OkD~7ci=J~$NESKY(tB$a51D@g%0Cyk3z{`tqy6uoV^N=cR*Rf3jBivdJ_4t@%F4#r zZo3vENTR2+rmn6HFr@-y;^yw2O#3T{?>Tb7dgYgOH8@WXXun^z7Ch+d`RM8Cm9Dln z@i~_4kxVX}LeWV8mRKc*_^<*VuFrLnojmXzk z-UtIFLN*miS%u0x?MO!Z%Vqr=6cMriu~=Dr5XS02pfCUcSoKl=)h?g{rCoOg; zP9*=4R|s>*o_+Vz3$gg$zYRGU{#*y^i?7;k!RA>$W0TkiUs;|`@kXVnsb<#2j8giJ z9*a?PkAf#G)tD0-o29SsIA@QU-#3qZ&6VkRuKHLrrX^V@rzFM7;C%swDi5_0X*jgKC(@+FwqF`mFENJH;yqp(^~5MEFK zf-n!J$eX@QO8>FEeiRw`|9r?!@Z}SxF@`A1(6SWLt{Y74teYOK1jWfq;bzX z|AIi{`VG-T(hHs#x#PhOrT>evw+@TyZQs3BP((^Zx>UNmV+2$Lq`RA;VQ3ga=|;Li zx*LX}yF?m>7`nSV_o(0J`905m_wgQk&z~@}jGw;-oyv1bFwVbItxZ!2BFyr@#1D}@w%L}pRLq! zOmMT*R~~m`x2yb`iD`CV`8$Z(*e(iDizf?{gtoOQ$biJYPQ(AjH z3gpBgzeRDrK#GW-Z6;elv7Kwf-DL!2bb}x9U>;Wu8ura}n$%#2q=IdGdRcdPLHd!x z|12L}`5YdP1b(IPow#CQVeKHl9pv$yDa(XRMU@fqUsDOC-2{vI(Tp z>RXg7{p}m)W~Z3Ud3tvSFqSzn>r*Z*wt8|TLnXIk`o2E%cJO-^@A11zA8q((2Bx9( z3xLzQc1|2^>$+5i?od6``1enQX7)X1 zR?BU+UZ}9hm;@-Q`eW`(7u(=Io!;uq!&5+*BMCQw#}*obZ+Ab1tGKY6Dsaw|7{iOP zf&hB$v-a{nxZ~0m66# zd-}s#vrw@Y3w8i;nX;KpyOx^I$g1p+rnRBn>?40it2bUJ$BHphJj%>lmUjyzQNct%_aF&=hX-hP|fVTtDR; zi?L7e?O<|Hg=g866E`m)D-D=`299aktHtYQbDF=IMBguri|-F_I60@SJrkxw(Nz0FZS`=?!OKsW#G((6 zk+#N)P$G5A7kK+hjBb$d?hJgIFDz*#vxf6MFP`TC<=~#yy2-L8#%L2x!svnZdPJ!B zq?jqVnlQYOJx{!^BM-$g2e0u2bR0N_%m@)CM!^nKbCi9a#ulWCpy%6i)KT}m_ zS0C4#VC$@0``8}&bFx7_XX_HH;4rr2>TGmOlWW%9j2@T8ksg=bk${Bpk8>n>Wk%xP z>OuQcLPd4{-J?jwDY}6cEq!0WABG;DU(C7UXouk0a`p#mm+6PrJ2BqP*0Wy6rQ6RX z2zNfKZF2M|R?*m05U`(Wj%n4Yglm% z)R?L zJmjLsz&e={o5a@C{h;hdJzbLrC!02kk4y1vg5BxiYeGnJRC3^RiaB#lzO&wpQ5UOv zrN5R;{cy-C5Nf(>q}yGX1tIQZnbGh62=kWT{SLBxU&45NPm>S+*ha8dt64a1i99eP zwgIk7>wI6~o_ya6gT=D5Npjmwle3joe-i32$lcqzw`agVE{ zvbDC|YR$P4aGIgZ6Z@WpCB@K?(2TYtqdu~JFuQDQ?UksSEwWI(i_ga}+Q}`3mDc7n z#)m~?9nU)}9i2$2QhE+C52~;MYo$|Ygkhpy%1hdcI9c*-!O&&*7)R82faaemU z63&0|uD3B)Oiv34$h&SKt#LfFqKLWH(57g@l^wF-7yiwA`5j8yi~bHW5GUvnx8+$m zH#c{5d>ke6jL-nDlUGFPmc20Fxn*w&%EXK?62xTeG}u&}lDRqOAPi}Ud^q3!f^xF`Rys*Tq!{RyoEpf_C7>l4Cs;$FWQ!C4*E zO76-vPM%II51uHB?zIle-RUe!B*FKMxW43ZMsvcP65w6gP-<<95!;=DhD#IkRG4X! zIe}`~^%VeaC_D-te_br{9ZwNF@C$)GVthLzd-`d<667z*q5u}#O27b=xHLPxOe4+% z^&{U_XW4Wsti(dS#*UmT!;pZ}>@|fO@3LIH^z9AUw%I^X+khg-wj^&W0kqG%?)W7g z|J=2KHz_wRHcG;-hG*pM;}33$GV;v#g<5tJ`)Y$}g+I`(UF1YFBp1%lw(SLARpt}) zD#k^b_E>LVC|do|SM2wXz_lg%y4Kv{QWGiyvmbb3)!oMN1K zXx(42tkwgN-)C?#srh-jCX&lSsU8cV^03O*oS?qHTHj#QBpwRyR4Cjv-1NFrTYi#i z>%@EH{1vhLBOxU%nH=NgT{g0A)r#(!KSj3-C&^8D{=~3;glQJ1*500&v6;r>A*%&^ zhNkPL>ExfLT1$Y)@Xc)f=fe2MrLeT=iI{p~eNSJ1R(}3x1YUUeH@y&Fm~?TtC&$y} z$k2xb@ygK+;}0N=DiN<=%6uKxqn+d#6LYEE!>y6%O<{T8YL?Lv6dNoWccjMhi-WGs zAdth!5fvjMWzT|S91t!yZJAlY<(p>M1L~>)ohqdZoy)XgqtvAIrad0V!&6k&`BbAm z*Wq%u{1e5-$TSAa)88a1j42^mC`e@|@CejivIogS!s*^tNpTkoB7+5dc2pzYmEkE( zC))U!pn;P6jNa~qmZv74>Lc4Rq#!hSN76UiPbDO=o*ii^E8r#0R=|OCx9hV0euA*B zAgP6EO<8vSD5kv}xxZsbu5;}oB0?&nk6-CmkB`9@i4-Q#_%e=*TXdSpy46-DFqhT9 z&P$!J$f`PO|H91LvX!rrMqX%zV2%89{K21bJzA;9-Urq1Ap`~?J!UXCgxsa*Y|_|R z(OBhbV#^7uZDAq(vGvE|xm0OsZ6v%Ng3RkslbN%o=XT{|XZ^C94UhFy1-15U9ZWOx zq2YKT6pw|Ty~H6EEl+{5sQuT5b8mEXR6|Tuv>3;icg&$xbxa@?vwhnHH#MdC#O+pH z9|5>4E~ez=y-azU>IWr2Sj+&R!&t0{9klODE0)MD`z%Z~S1|Zt6Th#psHmiE_3PJ1 z|M+D6Z;3Z%yz6fvp1ql68E4L)ZjkUnpb?gw%>y0M;YoNU$7v&CX1Kh*cDm;HJ2j_B zaB*=hDAkY8=*me;Nm0Cg`)#hlnf#)%>hFf`@3;QW;vv6@p8xxwmtVb=evhzvO8Sbo z-0s{?{lmVt+@Qlrg>r3qaam+48>P-sjaU0Fl{FUlJ)JlG0){U)nV%dNNLjz|Iai1? zymY(FrrxoL=?6c>H~g^%`=0#LQ~O^gUZZ&P+L7j|B!b(R)L}%O`2DuPzD zsKRgadIOYij^l_xTVoMHlc$PxW{T032@{&m6?`?4cR3s6tz1~rZ%cIvzQOpyvrdvB ziTE2G2@O5)bq+^i8}2&IdE<`ryL?LW==JY2+Pe~JL#n7<5I*?T@;aBVW_n%l{Cug) zOt)upt4n|Y|KqOm|z9OtFqm0|jO!Y4@&s*97#F6CFF7q)v~at2eE#fzeNi# zz4vv#XwA8L9@HNt!BUb{Pn{kdCCUDxeTx+TYhIPl9+chCns#Z^Tm2UcMmqwjw;A`v ziE@{!sq=%F;bT8OjB%xgF=M&v8LVJF_fdD~utKEBOm|K(AfdJKB7Afc_rnEh)AOoQ zv}0IHdvFOjXvn#%U$4zbVJyIz;$3I5VGCDS44H(<0VK9qQpRAOK^<9kSNuzv-fclv z-&A5FU5SaK8{g07&eUuYy3G9gq-#vGb0@|;L4nxRfPQ6-FR%>mhezUAz$mS;WCoi} zsr+OdE8VNGgzd`dyZLu2#&L3bj5*E4TBJ0X4urE9HWx&akOKQD)LQYtGlEykcCgV= z10kMml=kbkLmrl%+xPsRf5dOCJ8k1L{(p?6WCKG!A~szf7$q$nom~=us^Ntu{;y@V z#=uQi1fHOzZDG*!FK#oCLjoW+I#e`cXuHRfy&Ye6a(qlnPmfqQcpI1t9@&N#W3bxHKi%uT?p1f{~^9OQ^t-C9iVb zHjWGu?ljdn0aJBhvf+k|&9l2{6LV+xE+D*8&F#ncO$wXi>y$mqnfh;BQgKxVeHxJL zUEsyw-s<>dWST?FZPo;D1c`*Iv#sEY$dS|}+he_?AD(DcI?SzX=jLSKBN0!2df(*- zPf1TDa>2}ZM2s$V-#&zxVmOVB+*grih%j&z(v94cH@#HU|c^k%6>;}Tm;P~`v zd&_$!dz+v*r}W9hqEVdk{$_V`p`}4%zxMIsuYq(qLe3=U%|izomh4Jyvj6CfK$~t! za8@#Yx%+_RdP3G#`uLaKl8(U2XJ3gCizA=Md^Mi(`Pz|Dy;jc;iHpO-CY%J$_ViGE z;XG=mm)}4u1On!jl0DLpCG$_n(<>WG-dBa`M^(bYm(>TCCXTafJtt)V71rxMahJ%w*9F1nfq_Vm+%vR#6{2ddnhgivm zmEGUy&fgvC-rj{J&Jw&R-B>5}k&2eEs?D~dJjKir=Jr=}2RTNpKmt-}Ef^^%@-zlk z{d~m8Guuf(0@L@ZsbXegq!M$UKe^RPX@!RUAFKa!5ZmwgGF3rrDUwpf zz5Hd1_`*gWPnfY~Xmkz0kOp5iTS+yf8qw%)XeQsHsk>a>f!GoG zWIaX^xSO2L#J7&{X~Py5Pn~2wC33>xco0f`48Mq0Rgy`w8jQBc=qetyu22)JPc>l^ zk$(kle71xq^!?}?<`i*??fBYWc5=GPR;7Kb$V18Kx+!ZuClM>bxI3`yJu@0!NMd^< zqj%#R>hTE-oa{&*7#N(JpZhKIr(h_CI>|iFPy?1u|6X*D?TKR9;X2F?{%U4?)kKf6 z@2%Y`D@kf5sjTp0w7*mqeO-eT<_vC{tMs+nNm1Yin{!+MV4+;=_|& zgrqzZL=643(+xi58A!HRhgHo>MtSEWHVl{XiptCHtq?x7A|{eAWMi@B#Jy)CPMfXd z`gwDm(n|;AKbwu{tF&BTd4g96N}=0s`wy&s9(xjmq zo0fhY8*60?B@5V9#k!Oi1l!&o)ivOqt+P|d&E=cJjJucs*AZTX$IGuX-aWUFh1)X< z9d)O#js9*wgY7o)u)X6OlDQtNOZSljKHAc@B>XB49kayxv)=^KUu!6}7?+`FS7}c^ zi$zqmJS`c>{|>uWKB6iGQqg9Ye$QhR8JY0QdwSyZYK-Ek( z+y+wU9Yyg!>0_sk$-b{yMI8IWC95SVAr%|8w;h>BCBm)ER1b>-L#h?K7P0p}#;fWi zL1%*|YXD${%N_Ii>kV6Ib|_~Sz$dE_#71V+bL{7Sy}!YzRwI&=gB+{h=p$G%umnli zE||UI3t|#`elVS$5lNc-f^oHXU8&Mu12uu$&r@g7D82uivgT(skHA9fx#xDmlI=J2 zEhx%-_#}E)$yRGo5|ky%iK~`ZG4Tt!hjZ+vY$C?*qyV=mWz7jg%gO@Nl}*nM+T>m8 zcnwO7+)%ftkR7D#kz&E?RUPbsf%(?xLAG6kqrMq>0_n!r2#1HZPT>p}^~4l&uqKRyqx(T_v%69FC_m29yN73Iw_az+#i>}~9 zDmCT{LeOg~6)tIm@mQoyoFxf(O7l!BEYlQ)h=jwi(kN>zUzx`8(4&=zGkeplOik2l2>L5K5HmmBN zhyhYn>ce^%rz53JK%`;Pu`wHDMmMTOQ?bf2^2SUxPXqcS;T4aV8XD80PL) zbhuO~Q>W9CPUQ4I@*zRghByNyCP_rw`8-Lc?5g>WyM`y?3{#3m*|~KojY7$Rx{cl? z;^qbUD*bd4#s}-t#oBct6pq`u5Uz+jT^6IIMy}$iWN|CUr#0f-74A!TFq#cJ%eetX zR;a-t=3DAZT1T!LC6%3kRg+&~HRF?8r@+Xh@~{%!gT>D!iPstw)Q)0S>|6$xrawyi zJ}~$pG}ei!nu@$inZkzBQi7-jt|ZJB3JhkQ<7)3mkJ;VbJ)Q@RzdatKqp|=#f#cb% z=#}`b<7s*VbO$Sa9V9KU?%YO5Ov*xmV7DvOpYKa*-$t+UF?^m){-{zXscA;GW(HS_ zRuKWEp6*O^6P67(qbJ|YySDk%qNZkM-1pHDRomlVGV7MpO9riWNtqdQ9& z)oVHO`B)Lv3$c>(25Cm;qIPrI(`4a6&9Dvc{t&GdD1w=R(9;>-6@z?dAVSFf&ODj&V{0@zUs@MlU-IXD3i5 z4l=|N1)bhdxFOq(D*nxy^HR(p`Cp5KU_R=%1!20~Y~gnc5a0fTzBKsbcGTa6+Mq|? zI5DtPuyACRIUy(RG1=gH>dfJ?SpRaKzYhJs~FOHiW#a0EvoR3hv1!hVC5+By4g8!o4nDJh+@bvnC+0)Qkw@OI@AN zoPsp@K{rf}7HWZPI}^Y<=IroW+;oJ}O2bb6!7^$ zr$SmA?I*6d57IWEQPd6FdFMos|Aa2~UZ9R`oa{n7;B#ds+n#O&tK%YVX|g*Dht~sG zr@n?*7!yVP3?#U7e}Myxu9@$CZqYwU&weo>~_w%zg6j@nCq+b2Ya-$B}3>ob}S^IbZH-Tt#~0x zR^%us>AvZ7GuN9mHN^~~R_v3jOU9m^ii_{23ZW7_NO_)2@?0LqD?+auHD~$3T z6s>^)YDaqe&aUaT7`WJnfG*|uazO`%7>?~FHQ1%PfCtZN68yq zXWOYu=P)0y`I2}pm>xSJXQVk}78|c1j}zSIOi2;o9c`UAznjRso$x2G$#xcahTFp zvF6KuwW3Ex_Sdrny(zkcry?{VFI8{w3`Cn#hv@A{?x=MJ>{Us#>l+iF8PeTESMfrN zf;AQpG*&YJ&gbp06`S!3o_~?b$35fsgH$(;Gp?pZggT@AOq;mb9 zN$;fSAX;I}=bLQHKtGS)(u$j<6>>;HkaucwiM0GpSIXsckfS3FYj#P?!nwz!X>ndP zZM@D>n?u;v=+)jowT8dByyeW_pjiG6hN!Ouy8e#pUGpAcF{(4&>EBD=T10q&oxi~# zlRk%s52!84O$n|RlTjXOut$#`P9;8wC{;Smxxu`y@J`4ByIP!Z5ws61!``{Z3Maz; z^_FhMERR65ow$?J@nuKpW)%Ujg>xrtVtZkN<=m;ns;IV7(F?w$C!OG!=~!QSG-(zV z%el7q_Fj*`Nygg6{(B6Q=2efTu;A^y>Mw19fXVdcM2jq|6Y`;Y`qW(gFU=cejWsf{ zT{Diw+AZHO9+KKZ<#k@Kua}#En0;`o z3nk4txJ`_ev8(|d{2U>awQQG*>Ln{{gMP#^aBr>E9Aakm{n2hNSesXl7JXeC5*EUc z-+y5w7l@Rr-7sa$UQn}@h=$l<7+hTIAYbtsPK;y|L zc!X|pI6}ThZO_mbjPkW9a&tvrA?TF(=f=7=a0f-wUAJi9{WW$OqtN@rB4U~Qx2GCa z(YKk1a#_o5C}*6Pk*roa>l1KyiaWSd@*hmgKc#kN6GSRIlLP(U_k$yF)CI5%xCG!? z^0t0cfLG(;C{dO_nDVLbt?=79_jL6~euW9XNPZW%E1ZBJU;g$<^!II8Qc96DC=rs* zXd)2cjT4a%=Tw60D}?O5X0Z{Rqqi-VrrLYXsd*zcH#8!~l)Z75>nv-*xQkAk^Tvv} zUq@H8e|2YTgeq#-|6Onh+SDvjcWWCcG#H~5k#njif{TaeB~Kim^b8d|38}-a0$XaT zZ)P|nV-Lp0D5*y20a7Hi8=r#!0eQ4EK$6==)XJfZ+-bCk#e1tQBJLRMxhIE?4PTPF zYMlMcC2k!miO&2RJ%kCO-HQSrVyNU*-#p4r@c;&0d0`+Qlj_GGfhtB-~Jfgw5d<`thENfyNy0%E7C z%ZQehA-BW`KtHk6`6%xm9ks(*C!ZI&^tqEuC+54)R6}ieCziAUN?)eY)^YfVX+Ubr#g+8L>9|ERt2c>Q`^EOmlRrA~0A9Q4xQK}eNlalF%ro{J~xft&*aqn+;Ah(-KWxCzb-zR?HnRd=(e0~@`;9E*jT1k0|z<7a4zCr5ei*9Anv4^gu5RM8r0J{2WJ z1BQGkug1Cjk5-lrGZEesm(h?RCbhQ4IVu8DBvkbL?B&f*&G+Wm_At`y)~PR5HIQPO zQiRaWf4$Ocj|9(prhmS1C9}v{{*>VLr-(!LSAg3X7Jz*Jy~|_x$*k?JCsjwsQZk-> zOFVTFvHf&|Ldk_x>ZB{92KcK(16gQ`J>y;G?U9qx)`=5!>&hEA{x6gLOeRZ!)`yZB zlG81!n6Iojjyb57Y8l53dFWa8&dc3T7xe{uyRiV)3}`~daH-|}*M&t=1$)k1O}9#k z>5;9DG<rkAO#U}`}d9c56{(opMxhqM?-zXzYR67+}GaZpbke> zb?V70mG_tr*jJT#WBrA^{t^)=5(RoGQk1~fh-@+TyL!QS?6lcYx7BXD8cmy%JiU-| z?h>*kU+2A^JtTKiD{D)s2%>G`Py!~*YPU3ca){s5`Ph6k$_P-8@*W1dUaZQ$(`6E8 zsp@+ik~hP%U-u2W$Nk)enYUmCw0XMZ5OHd?lQ(r{$a8NK^FBZaL}*(%wL_Z%}@> zrC02MJNu*(WqPXUJ!O+Oui+hYkT3tWO5syAAmn4P@84g-(?wI%2L}gX>Bh#!Q*ijo z+L~WDhb?ga#Keh4$C6WOaLDMDT)n zda4%vQhl3FNuu4ZU+x#Kv#l#Sy6}0qUUQr)jT>St`JYo97K&e;HowGdevn-+m85JV z2$uR~OC2e7s@oYTUz9H>#9 zNbqUyh{O8fN?Hs1N71VT|Y zv}R&$9B-+j8mY&ZgkBR)`oY+Lkz-=q;b37Q58>?7qf8$U@<%z$!Xb3jI-g`UC7}06#vEWba%>n6T_I)Eg!C6@prKP1)TaXT~?=Q@Y6cWxhMExJ! z8SkEnA5ysetQmouV(B)e1ZW~WU+Y~TeY3(r$c~HIlLuh-hGJq!^YimCiv;ql`uZe< z=I_Z9nYm6k;0DgJXlB{TnWL|;icC(`3F_NUzd-}}i@QHnNsWVyzp*Iqq`A3y@zC*K zvoEQC*Ci1ekreHCtw(AWRuyDln3zgnZr&C)eHX%B!1>SD9ZF9y~ zHEpmLJ$cRNXgf1qG{iSGVy>Nbo#JRMV3GPkAlAe}w`SYE1dk&Q@2n_E_hQMSEY5b9 zUr9rQ(frC>r^&JjeP;uH^I@WfdxFyf(3VFuDZ?VWrkHa9mmJ`4I)_#6^4b(h>V~N2 z$d;+GNZk!@!Cc2qY9RS$^hf+QR#(a=n?svxMMqX!%DWd8*JENN!pnWqUQORX%RjGEVQ?^)$RjuIIdnuNwx z%E?&F%foO*1FIwu1$~FK-&yznpkqlRL;#Hqlt``1j0Jg>`xJ(y-(9L@~yixlX{pnB66Dau~2&hiKvYZ^h;$lX24vvzxzl^qc{nNAG6r!PC zF5iD@9)GVm5fMZGx#Hhv9siH&{cj!>ks3l2MgEaQ|NYayBCEew^&e-CI9Q<6e;xUs zTZ1UG{}I{!*YACyAO3%C*8kmM_2c8>U_`H88Qdraa`YpJl-E@Vpfwl_ZbYEc?CdJT z1>m8dC}Lw{kx@`q5Ij?2247wsDJev%z3aNFre=a$1)*8j-P;iLxLe%Z3`|W;Jv$&T z{MSqW1c8zJpWxt9|IcgvyZm^4)%<^CAfiw?9ID<_h+rc6Ctf2+W;;L1v}fn$5G^wQ za~x&@#KZ6pK9Gx>TO$G+K@Hmh(f_{jq{S1H*odYJm_C|l&G=x+JVEi4SLu0-WNyj>SGqC)R-}LWc_}%{Se^NXAKMVsV2XN4RzN4e# zJntniu1&A}-V))4dtQ(yknLn^TaLK3zy5`4yI7&|^ea^5sQC^aT}fbR*{d-`y#btbk97iqVdVe}riN z9*>uzx2)Id(SO-GRue-W8ULp1`~{JPe=+}TFc{5osjfu=BK7ZCm_ziLLh8a}`y-ij zkIIVDmaCeSSBb5%h9Fw8Y0l&a-@ALRvLp=)t&aP03Wu877$TaxGoP?(SY{0co*#qL z9-5#D1IAW{5y~Rk)BnPO7<(ZAT!i+8dm#5~2aRSGv&3I#q>!_zKE48b@#Mn zg@8u}Bf3<7)`z@;GUsa&B$1hwf3YgWujNMIps7BkWDQ|K6pH{QU|kmd?2qLKK$gw} zym}s-L{jge&|iqC5S3J@4-ME^X%m z{cDU_uEx0TZR!_NRwrp}Ij?sYIvWAaJ=ee7etOBVs)!rRB)JUqGiMamS?$&mndKK! z0&2dsj_|OZImPBB_pr8B1?|}|Exk{T)PScf+bsvn+N!!?687~*T8SMz*LBynj2^13 zM8{NxfyT2KR+MHwZE?y#qau;O!|(;}h)v45>Jk(Y1kjL2CUzwOyEANG?ESuur~z7L{UQZt^p>#nz$ze5P*_QB!RKn&U%)o2v_^BS#{$ZVvg91p*9b}s_>eK zx0JE!t~qf0(zJt3=K28xYp#c)7Cl$>J54yS5vIwtHce-F4e=;9{O#2T1s^N^=)!&OxKe|F8X9b@*y|Rx$d(IuJ z;7*%HWq#dbuJ#g<3Yj?C)k^GL;;(t`SR9j6YCIN&b@^WUVKI8>N^eZwj)7<*z#_j_ z=<_X2f6zj83ZFf9rI|BxPjznb4a~8$Lm|CGq^8xR>HP(Pw~tQ{>Nv-yPepi2XKZoW z93)&;_#s$YoVdJHRPoA`UYMDjZ()69b!+Tb0$Qd)2jWPII*BBfT(9V?0uyS^>3sD0UD#8;$RwtiCfif=|QQ-}(f(iNIh z@$I@vbqW$tlHyF3IWywZ3KH8Y=uWA}GWo9o0RD?8 z{+HY~G5^?6Ow6Z7%p3>=l8}%TuMBcmO@H~LoPyLoL>};~{p^*P|FvA((rvYlGArCn zeD}n1Y*&eFF7x@3bH`*;P!jZITur>&uz-_Puk} zWRsuN7Wq+tEEOF@je<2hLm}{qOV$;Gs)h*)=GR=H9yxp7)g}I01nl78pwv?kuCpF> zxhC^sKxRt(dRakJ5(L6=vL58+*JO>)jcPtO)NuzrE?TJt{b&qsSEy+rD}1{ePP~O< z5Foa%@(RzhyT6RtWUQ1ln@6?MM&e0AIo#%FU&$YJK>KN}AmK299NVus}$TXE1yticrZ{#0ys3^{U zAAm&&8=hTLS<+&5QSb(Tn?qMKubR4^w@#ta5}6ckLmnrk_L#HO0Xt$ALAr5T)>x<4 z&Rw)e;;je4>X)km?oD>2ns#VY^*NC`Jm_ya=Ljbuqr5Uty8^~OYkl`NbI}!KoZyTp zvX`nLdolj~Q~NR}kxv5-M=Ab@QDL=ZRx=oVkj$xiJv%Zr=GScgP938B>F-Z8aXikq zyuIXM~OJyN05aZB(!x-qV=tDElrj|lmwV-qO-R~KAUQ-UX}u1@Ic>iQZNR{{f( z+s&a482$C)uN?^f?VaUH3q{0fN!8UxC(6~v36|ZMwAXr_`cXDFo?O!bQd*tU3)L{9 zu6%jG#yxO7GFv!9(@`e%0)6OCD?+v7w-@WJBqY}c;b+V^@3M}&u4;*}ku6<{0|MC? zgt26*1T7x&Spa>c<}*;bN%j?=rd;EoHruy#wsaysHJ?iGtNw z&A96?w;fWG<_bU2Gaxue98}P21mAsFDJTGSc7-W-q`Lr5uDBo{%F;|6ZxVaSN=#k+Q;Z?#2DV%zHPrh=q6I>qbXcN$<(j%e~70 zH%vU&37>VKX&<4yq)8C&(jyO=t!~_!-}!GcGxJy zJx67}VVw^LWbY!fqhiWcV+W5M60Mg~^Arh>M-7DMGGTRx`e}`Wz40M0Oj)m)4(v2PqudNC4YV~heH83I$%LZ-)vc*)70KM%kb3>th z=4nOabt}3uf*>1`yO|gLpMaJGcj7tU#OdkW9^)x1JQbK8Bk-FpV(^&J4gGHg(ERV% zW^mX>)}`KHfg#FPJRo|!eoSMcc!INb{X5|~tC!1_**z=8tB%r=#)liF>xTtk6s1Tb>Ov>9lHD zNe_XP8}}1&-3HxsJ5XfiCS6lI2Vc((g=IAbz2IDgdp*DFky)odqXXWJ9KZUR3f2c~ zKC>p(mkS90_TxyAVBYx+#i;{vLkHT`p&tq%&;GOA`O_!5F)H%;m^BdRSV4p-ZU2-$ z8!`%XMbE}r3&Z}bwh0T{$7cQBd9wWY1h^S>izj6=U@)I1nPhif;d+3JPB4}J7U{Ow zMs%x9gelvKugzhLEjYl_5lP5H@Mu%u>(pnKXPmF2bf4q((~YV|OKpwVMX~4FtvJpF z1sz*zHv1saCvq3wcFP)Eldc5WI(C?Kntr-YdR|cYV>JO%jH{h%ytT^$M>t#P^qexB zv0W0Ac^FclRGye|?>w^Q)TRKlmdk$Ei1(l|hl7{*1>$ZVYD4)fPPr|~VFgRdX+&cI zIuJg`hvwmAvliD7=eQzQSmPi*i%SKloBY!5NEmaxdSIeEd>+T9b#7TCSHl`o5uS=R z-&Np@JmPcn_DJ_XS8?74gwFi~F!5J)+@!+fsCfyCv)v#suivoMdlE7Ki`?WgzuZP8 z2-Sh!*fHO)^b@{xmb)asqdrP9M!ArhMQi%?-u(gh`z!bL!G-p=Mv~)g5?15@oN10E zJ#pR4Yjl0R3)}Y8?E>EEW!h5hW$1CzQYZnNH}=ZP=E{LbFp zLm?b`MB@yaB+VkgQ|TXZUN7hB5tT}B`;bU__(iZ)f9|5-`r%v3=SD%pMAqI(qEi8n z_mYTx&JpUq7pWx3PQ&=}Iz36s2qi}zilW#gYeNM^Pi61gFa$}>ajJO5>is09H($pVm-G6Bp`cX zJ-HY#JcBs8S2hbA?ZL;Y41d^%mk0j)lcN6OQAo8v7qXWwivf|sRP4r&QO9(6R{8QC zu5^QoAu+%vzbLC2CQ~Q=MkU0j+l`o8>h)XDTwQq z^~N+Z#xQOpU_wP&S&v540B7?hDw(h_vg3htz~XnLA=x`T2D}z0^fWsGo&`tpi#agi z%8i@c;aUUbK}iN@If~FbCI{=OuG_t?*EZ=xrQOVGnQkK|n|?p9dbdL&;(fk)zjj*Z z&1VmP3YLHTQGIKd4NstjWQqK%t{B_ERl`&yaFt8c%7nkp@5(5-e*pe$qu5|Dmwy*z z2)&z!UmkIFY`r#ZtF2j}q#ex8&ky{ivEnSd!iy$D$;|%}KrVpm80PX+Jd&U$;@11! zi{RZ-D~+9o8K5Vb?=?0~eR8VVnvx3X4a3`oJ`zR4Uo&bxfy5xD$yq0siv=&h#ex%) zGkOF~>#@*K8Be<7_EJzhF#4#Si~Q#0y@Z4Gi+62chIEfZ!lEYXm*m7!3W4Cde-A}q ziu~`f`1GDJa?g-p#GYX%-cn!HjVhLjEoYtDHby~x<;VGF5VehsU=#c$5vMN$IXJ1M z`H)>PPsVtAfoy|ZaRyrh;(O7;*nti3qtW$@d$`~8EZrsfoPDBGFK%0WT)HJ=8VJA> z=L=6Vr?)gYAqrc^Ra~+i-p+e;6{@l;lUC?n-d)n@}< zCnIX_XimFr1f3Nt1p(KveY{4fm9FBIDBEv!514! zpTx2-j!h~Vsp3nRTv5<4-@eI=q=hpIr$)-C?2BMCpNM4DO&fi9DvysVX{1dU{;P&@ zVf_d6XVc(PxN=%NerGqf;vv`cj!K0~z_eiUNMnRrO7a@|aE+uf^~bGg%7g7sN-;e5 zp6kf{m>)iT(z{tl_+56d-!_RY*S-_8oBs@46ZcwO3PE8r{m!6$v$6GS>Xqn*&I)v6 z(ntM#s0a#Leq)_X8Afy8J z!=kQmfS)~YzO5^MzJKjupcBxH{Q%onn9HKoyuwcBh4YMmj&^l%_IlSd+d9-AO!sR2mTCgdKcv4_wDA6y}DC{J6eGTtl^zuPAL7&$zYlmvO_pI#Jci?<&h@#1@wYF0sJaGLSS4kGtw z)1WJ>t@ZOHKF6cTfJ%|P%O1S)Rq%O`oDb=q&P7a9Bns#560j7Oy`QS?SG6ysrbDnD zf;w*zui~wVaJ|+zU6}0FMi+%Zp-!qw&B%vYkeD14bRYBZbY`jfFFy|5nvZh3Mq;zGFm+Az<=3OQ zemdOCy8oQ5lo-lMDqZkq&rvM7+M$OnsmYDT-aQSm9PiC7EC;?u;Dlg*(z$#zw;V69 z#t%93qb_WEc37ZkpWhhkZZV+tu^@c&7dynW)xh#%a`|EQ>$sK%!p2VK0<6Csnv9Ys zSV@2#2p-nWm&piOo!UMTXL?pL+&1qtS3lXF>Mbpqp4`aFO0U>+ zKGAA?1lqSnUo`ktaUJjo97(=c)5(Gti*0}3w$0s`;m@)-eM}_a`UH#QKb9gE{K5Km zbHg;L&|=UHF-b{L)>eR z2eo?RgaGtcF;PYq(wl)>x~FC7q)w%{I@aGLHry9P{$=9t!*2q?Mp#f7su<8690g zCT2f#dT3UMkhgft-*B|8P-cfK`7w%+Kx$v|UjreJ@moUg6NI#SHmVa5wRkp~HDc&N zb`hMvf9$|_2=HmO3iBa_@H6|8`~7=hLxbR335nTyIyy1k(a}-F8kUT-^y5d5a?CNm z_1Eas&gJdL(!kPEX1({a<}b|R@T;korpYFC{WHM74w4}3LqJUh_!D0GwTn3 zXoB)B!&tC^voiq0^hJz}jI1D@5}hw{tK|6l`r_i^3SbJ8$^9?qU_^KRRUJ#~_av1Q z$L@Yo+4*etdqRI5oyOk%^PNAxyCVGcA7%V=7M-4N|GB`QOA>n+h>`1mjWt}%1b<)b z&m)4Ey0EaYkBf_ICz-AwY1GQ~nvH`4K0F+c!6Dg5A^^KC;D7d^|J=RPPbMrj^9;;C%*7gK zchJDak$!==A#L;&qG{X%x(M@1%mtmRu38G`R<(DUBGg%wJpKSb0wrl*#4FMEn7bZ7A&^k zax{;}ERk!O%HPxcKLEv&2$9#yAZ0fJL(O3mZ>6FF2JCV- z#17~fP9M6JfQtQ6wuQ!O@|U)y(`)w^S;X>%U5NAouI{^V3I;kubB}CqwDQW?b06NM zAgXAb@9-1cr*C!&+%?LyN!RhwgmzegI|(zgZv7*oqA}q+6R6KP)E+Fa_Ck}vQp#zy zwX7~c{WrFgWUw+r8%*j7rf5pabS0mk8tF+n-4g)m`>=pg{1hYkhU-&NKN69sQBl*JPB&)6-oVT z9H!elR+RW3coNJjH&NRoxOdRWJ!?(3TwtKNy&z|(4SB|#GkSpl8t{JxV-hA6|I)ltdbv|C4Dw4`+T3Q1H&8j{=)=EFtQ z<&8`sAiB$wSZ+SareUMko{`!(SvwxUF;4JujA^4ecI=IWEs?ibQ)_W0lmE8>xhm80 z9q2u_LdSuT_mY-w>>pPBULGm)%*DTT136atc`S5J_$Am*lTD9(0UL3l)RJD=cey2j z^xv-0;L~ypBxAW-6EM+wucqZ5u|E;>W}ukQ=!=`-4yWj;NKT56eGuj=^k`|f^)qR? z=N66iR?H~!B!nv2_4Ut~5BBsyMbTr(6lX6GiNMp32#VgElCrY0LrSE{#J1aVitVp? z1A}tR6Zq$djR)#mbC+pWw=MLBJ!Ej^Hgj|1J3l|iJc%2w*LOdGWpzXYl0gTA`phxk z%}-xW$>1zI%U19m#EUIP+(4U&%XVM-pkE3~pAoyw5NDyH5`LM({L)_W;`V*EED-sbR>C!m|$Vz2OCrV z_nfqg=I7?mCv%;MS(|jbmp%k(g%ITVVuc)Ey_YpTuNwEfiou|C9m+K}S{)az3X@;- zCFFoF!yJtQFD@5cdpn))L>(tS+3L+38}=_4b)ww1`Bqq(PK0&J9FG z^*Z*K#b&xc1bk!iT9r6hY9RjdC>XTpl>|B?-}QnInib*9db>Q|-@|eMa-|BnzuN8b zeb{*Z@j`mbv~Nqqrf;KD<@)qht=>=&Qb3`z^(rtQ0>X! z%aM{rF;Jmlr^@b1^d+ZRC@f&6*1WRpMk|i)wgu32cepPa7<0unE!=GZW+dTs*T$E6 zzgi;b1-;cMn_7Fyv@65uMQR#`{=)n(+g$XAZ4T1>KI*?`r}#|=Zf?`tYhs-z; z(XY;G2b|O!WYaY{2A(u!nw!CzuhcIF0Iwsewj)wcwgja`j&OIccO9u4R;A%e_1VwN z#9FtZ5@CnV_TF#Z%6+C3gl`t`dOPo=3ovsT^TgA5WnjW0SekJEdCQ1JnL(ogcHwJJ zZamGG@fm3Bn3JE+x94F-2N5WyQn$Ksp)~HF5zqFPRt)ywk$o~AG0}Mh>Fg0?G~1@{ zIwVUkH`HgYXu$XiQAffsYFB1={TrREbCy)o2$Fqxyvo7m(aqkOL_C?V=2+c0S0kxl3}Z|Zb*dRMUwr>RE=-wr;Zda6=INm|0mI5+KF z_C)0N)WiAaat;JQc4x;%4AY2eHkR`;9N+VoybS z#IDgG^!88c9c;>W1n|gqlw-5Teg#!=bwA2Z0c@cc<~Dxh?>31dhm zkv_S7N<01!P4hZR-A99g5E}ZOx4(C2Ny!!6?^xxsMV<@W_qOBGfO_<^%lbcFs;?0!>5B8dedx%w*3(hO+1qRNbthoCcx9`lHQ^Qq&neiFlS4L(= zB-Me$rMrrai3MklcW)sYpAw$j`kzs|Ef8s_2;gU*XTp)(Ze z0#cA+x$1} z9^0*KiPc%1R=Bt02p=v4poe4$$v0AKk>$PB6$+~)abmt>4TK#&=H^DN&yNr8%{GIith4H4H7*L~bG>xd#6vb44vDd1zzD0vx2lDuS-@G?G5eZXJl*x+NKXPd2kRwH`FGyBdy^XQ0S#6{h^e9)`6Y@(t3dSG(%B8z6ytgpsnzi}7lwZZV8a|5(wL2|=!Jb0)db1-FpI~L}lhX0E$^2Pab0Z_8 zs+#6PR$?~r%3M3^+Fh8bv^8aseYLdEX4L)>_~YJzi!Y0ZmlqjuNui`w9Qfgur+~m# zcVY82)gQ_=K02gp8F|?xTp3$7%-W4_(KgKNeGJohw{p8l9-G;DuV-<0aY0RK)@pXb(@7emjp5}<;g2!Rg!YN3u?S@EkHzDb9X9n<4R@Z^^?nWmCK0R?bjeJVT{ zdrh%DANfF@yQUJI>1l%~%dKom`leT;)o93fSevYB>ijwzII%E;&}Qn3g4f_ndv7W* z%`}FY?)I507_mQf15!C-J2=OyHdV}M`_Yo2G{BohquIns zZqtFsY!2;m`*!yhGhBR+`Q|9%CqoQw3JlH{EjHaf%<*1jC|~%yfpdPZxFhZ2D2O~0Osq;G7>4J0 zGh2IZGfAL!SQPULTN;`=E$asorEvbq1SYd(m1AVIB{taonP2+#SiBP~-$lU9BHUSh zV)#y{JR@8uSkqMXqnd1Z$D@m?YQwF^Yax53M^ppZxObMhvf;ZAP+3?icvV!*b+Nvr zL(Fl9rXK$?^k|~Gg z)nrd}N3yf{V~GXMRc@19`4!{)pK%xKe007G|ACz}1)#?>odm-6p`AcfcVpDQn z0R->4xxNFs>|zooVW;QK{iF*Bp0d*S@Hhijdl)L4MQ(BjbB&8wRbAP=P%?Y3#PC6g zg-NdA6UB`mKTx8*BMgq*T&InM9*XWXUeT3OY4?76I=S+6 zsyRzaT$w|G@8p}kH_g=D`XUjIoolnR$Gk^g)La*rYcz!U3-Pc+S0lR2QqRq4pkY6~ zHOflV&j|1Hv)Sf^Y*O3CLL6UWymKpYj+%yL^6%=c8ID#JOBOcYng&0>1jxn~e>l&% zO>~F=jyrolRR?sl3l-i!?r<7>-asmVBoUn>0R{?}3la1_=Yu5}&goBD323C|dsz(w zm{~ast}h&2PHK&tr1YhAdUc$pw+M30G|M3s6`%9-vC$2-VmP6$_xkjMG? z@JToYDMj)deof|%G7q7R#ydtk+b5mNMc#K-aa?7sBm4D`Z@{b^LZKN+)mtu#JCKjx6oBnm zK~Go~N6w-na&O{EV6rCv<0VK`6DcPclM6P*8C7Fo_#NkL?O^+Rg9f@rkOJS6Y|DBE zj-xW)GaDZaKo9BEubhIlnrsOZkqJx153ROVSLS?quWnyiEYBUC)m?fI=P5#(CkQjH zs7#M)IpZ5@3w+=1)pk5@j7y7y+OX;&dQSC!@jfHBZM+_zxkS^cft@k|DKLBFVbnA{ ztv{n$)k1W4+;GnAwHSZ=`g5^wZwW5An`=`(!+kW^retj8UO*dD`6b+O-9-(?;v>J^ zF|dA>oryvX%Bro<%JdN>l>4e<7cxJMB%L6Mh_MC{5D>I3?fRM72Ur)guJ&^JvO3N3OmLMB=J~IoU`)LDjGW!9p&+4Bpw0$Y=hlAYo z8=s(2N%y_F9j$HO*yhH#|37tsXfS}F1-~sBVcNAB1ZhN>3BIf;aEExGi|Za92@^Eb z7NL@_IQyQ?fbj{7mmC*PiA_kRZ4wSj!XjPk-*2Jg=7qI;ny0VfmkQ?lg9jD?lXo)33*mQW(l5uCz8a*$$<8h&s3scax%C|SG*gB0Toh%Hqr8tdEQ$uvp+E!$( zT!q7C4c21r5K!M)>nHW6vqOe$IHxSyOmips3MO*;@qG$yCiaj}P9l@Ep-@>$a-nSG zo|F=(nR;Rd*~p3F&2Yo*NTHrx|Aaoa!QF{4Fs6~F4!wEn@g&wW@ow3q@&kfp*psAw zmI4OO^)GMsi4wO=vNb8f&6WA3T1zE5Fhdx<+`n9LF~(1wUCz|NrmLba&MW{2)nB@Co%*U=xLYfD4C>B# z9lQEnb;}<_RoDxUP0$qeK?BO|(&5A)Q1Ub6R!&?0?!>X1yzu_1#6Nor!U_{Y&bXgl zSDy3q7FS;F1Uni>8~31W@-re0QF_pk5t7)tEDPUN_19ecOhPy-{ek(Q}E4 zN<6*t_{sKMOTMB-<+y646BmU-c&AgM6WX8Hl0s9a{8XBxjO{C8r{P|4d`VnG#(R>f z*895?5k?}*vJa1Qs@i^B=8Q&nLvWny2F*~^Hd5MKfGHau^4vk22~sInJ-Y43xEVuH3z*uE?VOo3tSoHNr@3eEA1&S>xNoVXyUamIRR~NvV z5*7CgIL`92E4Ju2Xk_MV)|2&_e*mWPtRa}{>ZDl-Bh1>; zZvrgQU)oLrDJfwDyZ!65jt}qa_lQyZCCJcRZ!D(`7$QlSKVrQy@D8N{Nj?EW@JYL8&d}8BS~W(A2>NpB&vVDYJ^{F*(x9X8c$M~ z`qPmtJdF}|gNEHvIr}e1G9BYcGPY&^DAkkOoVr)0H+n=m9h9!2iBsSR5qEDjj_OP7-khV-MB;z4+V&w82Sa^PZM1eJh9l2Id59hp+Yt2i|W&9E^Pe!HZ zA-Q2FE$Oj*?cOw4puOAle$*EHtf%$ITtf<`^TQ5h1pl08HhNfkA&bRI%K%w zf`l^A-i4E4=5>Nyh4>l&8S#_psIUCWIhs|R;)Ap6LOEi@*l=QtNN7jJAF4!9y)f&B zwJd$YC8|QVe|jD56`*tZ?|q;i{(_gcT7ZE8ex9zfBH#?1_+@<(U=>+yYu~X*AzST?v6<~#G5ZUu>z70mjrVSDf>&EnR zkY55Je^SMG83os1Smc9BBJY?A+s1ckW3cWSm3%H+;HyaA6wn;Gf5*2cWA--RW{C;8 zxgMaqleiB{`aMpUKbROI9&EQI#)$PkUA`D%txMQk3Yhk(5(Xc#yOpCy3C~QXgf;4& zUk_=i_Kv06a~;mcq{c2=zZXg}5?ytn@g@@CX!18|YPaz_bko0RNU{AIPs)4FaP9g* zh$*B05On?J9Ce~*L9$F?a-?-?34~b3hT_XcUw92NRA8CS_qPOiKG-f&k z{X%FF!Dz0%uCG3)l-KC>OB=SLuieGm`HV!wesCT4BU-w>BN|R*#nSTfvSM|0_0G)l z2Wi)Kw>i&-PoMb-b9HvLqK~T<#<)5>S%+_uFwX$F>&69daF#R6uwTRp?#}!Cx_bhBZ2Q9J5odT<6 zb4NBN(?FtycHfZU;DD6i2LaPtF5e+{GFEBcXB8>F=!g2iB*v_n51YMkF3gaPfXr>% zF8=t@_37uOO*aoX>LJfMnqKa5+K?!f-iL-5dTk4e*|xo=jG{5I{^K2BBVad`wQh`6p)lv$QlH^NvG9 zL$g*N@$XCxx?dQ;{XfIWn1z*fe{XMsCcxUp#^qY^zcMw{u(VdT%(3ZDwk9Q{rGulN z5)nyYxPgawTu|>*`1ts^=UZRye=Xy`anjEOfU`#Xc~MG&kiQ_%>FM+zKbX9Z)*a;$ zwEx>lm@o~E;6JeP%6m&Ctg{tr3x?k}``6JN|DW&tC29omA8`J^M+W0R7x)V#5>UYa zzyI|^PFepiSop91Hqs@CY)nmVOeE?tC1qs0u_H3mjxRl`vXc8-ZZ4)xg40@f=VDq~ zn#CWow6U{uTMG|GJ5>9Sq^%KR`fqu7c)T{q{t+JjU=xK33k`Kx`}?LdQo6h4*N%TC zk!E=M&L^a$$vZi5Gcz;)0b=F-0VnrAluv0f81BLrkd#E=;N#;Xh|Mt;<@xhB|Dg2( z)_55bd}+R9+nvenBeLP_O-{CtKrb0DT8TT@dL+`O%8yVtF8Ry!XCg9*v}mh4Jf z%6M8Y>H{Xl0cm#F!1?6av-r$RB|pC=GmL6?wopoc?C2nzZ7B)B=337=S{N~9>v1Y^ z{lVtOdHDsVa`trBj)id?i4dKwj66~F-OJ$g?aqexYWG_ePmh(1% zRl<_?y~A%r00DXJr85$VYI;Zb{dxyjWlHmHWAg4N%+AH9%X=rOwyD4>Q_6TkuQHja z#=!Z0W@Gol`Y7$W_kLnll(~LlA*Q9h_JuQo0UMxeE?|^bfp7NZ=fCwiloFFg606Zg zXM4_b{c6V;er3ebGu%CM9`bYMgdUL96oQ*9(v8yT?kaKSe9cjc)n^`q4%5uKiZh+W zgj+q+WjMXRJTtd3ODAJvQONb!p{ZM1a*V9ou*~w^eL;foh{cKWniu`*)$@Zxzd1q^ z9mlV;`C5{NRo^>ojmGD5s%L?qA%i*1;q==-d?4Iw0dIWkvAQ8=_ZZ{%{?<_vWT^BT zXHd_&w<;tdmB!YnC0Z3?Qe}%FYE6zi&4#`UZxXs~!!tf@v0LK%6qU`#`lO)Y;h0JL|A5z+gTNKWSXn+jB>C~wq@<_7Wb~O$XD2;$3~B*W zbSu&8;@{;oT}FzmeBd_}`}(GkOt8>t&Yz#ZC?y>E+$Z;f`x>c0I>VbLYfUR)+0~mO z7=uJ;a$7FR1|RRpU6uyauORo2q7LZSb!ykIIF5P7l4HT1{GRQjq)K9n?5p(xCcE8V zCvGW)@1U{H9zRZ$ENH?p3v!FbrytqW_sM^n2QGpHLtCgwjjC+RC*fSnWMj2>voB^) zvaG4KHTciz3MpnU$d+H*JiiKYd%F)$;ex1$S)qrGf-;=T_#^o8~YNam- zRe97j=$m?$t3Woyp2lQNpBGebqq~|j-bPVx)NK)bx*>IGCsB7KL%c!Zi>dDryFBnt zO0NYQ2|Z-6SIX?Zbk?X8TrU5V1O0-g>PfL<1NF&fv+2MwK7|&qHE-buX`((jE!dVi zB45SyXNAuug+0Jkm7FXO=^Mbx)Hl&x$!}I^GpHzfW=I<`X71EEn{ait57rpeNB@8_=?PfBW>3#89X{k9~i>p>@yY zAUC4${l(o!0I%nneXf~3{|J6X@xLweN9s3vIyxwy=hdTD?HIoT<7e>l@VwL145E2^~E6d&3oCqvx0#O%MU+|sK*M21m%s|oJN{iNV6}FE9L7{ zi5cnhjwGzcH#u`oo}aIf6%H-lN_vC#)y-2k5SP;@AoJ$#WbQ8bRv%fCZQnr@D>>6S z=TfB+2YV4hUMBrh9w4hQ*ZVUs?<{6V+$H__Tc4Iz4Q26BF#o)TOfHV!HAz#pyMA=CXK_kL zUQA4kV@BFw58IeudD@H@5GM-1MNRdMzCP8NPQ@9YszF`mtO2YYd~+TbRHPaIQA1f@ zRm4?@HLQML-mC4CIg(pL8I--IpVrr{gp%Vwsbx1PHSRcIBWG01@%~bw$?h9VX5fPe zan=NzU0F5FP|If9$zj5?;_z?*#YWVWdudyza34wqb>j%f*?M~g~`D}ri z?2%f#^5l>^`;{q|2E@H9xCZ9TpQJdb z`K!=&ye5;uEH8PV##i~Emn6C2z3npA23UR7o-1}bokz(A#uxq{*tDUap?SwzjWGo( z?@7`{`QT+W{63w+ z4Y@RFSEr43S(+qyJvO0Srt;-KY%kL{LZI8(`q^J4O-9)r(K0l5(}ryLVJZyBoA#}x zR}gLmgM7(&+dbjl7WtGfY#BY_9Gk|1gLW>OakBhVmHwLqVOqD-EPEAA=NqCFRT?5G zI^2xjMD{UpM&W}`WB1ahaWiVE?P=_NuuorhHMX3wP4;EfY8nv|e2nS1BG_-F96W31p0u&MyZi4%L}WF?q1Ok@JKCz_CyXO# zVs0Lvon1zT!4_M4=CcEf>~mT#L`I6I-u?uPKTKJz*h+V~O%YJ%WTRrfC$+4L-SKfE&u-vzW7dWz_lvegAqAH?R}tfU6#})Ueg@2=?el--cs!%o?*(-2^{Z8CcTk^3LY~WaFf_@3?|JHoo@X2dxw9 zr^2F7ck4qPZA_vo60OT-TPg{~jK?A$V?!a)W%1+tut9N2aEQs8Q}WLEO}ZEq9PNri zf;}#lXKLK|8f&YB4Qk?~ciFffgIcl;&P6~C?hj`(b*k49Dc+#Iem|kuoos`a#O2_F zKRh4j9S|Qdd#3vttRYjInz(*_7cWY1tiq>-^4i1lW#)7W>Pa~xYvw5|dZno!$&JdC zspoEM3EqG=z|{`rW@PLQ=qQ=uz$@+A{K zN_h>HWzv$7?QCiC2w_M0fu1){!DF>_UsvFw*%pF>Pj2)*`yeJyhtMj-v;UMz@dl+g z!-dc?|0OZA=Z+@^13rT42CSO7*}Q@V?*=wg*>K@m@JO?`voqI7lKTq{Nz~5&ju>DZ zhd)zNIn1z39*KnPd=q${XluqZ`tZ|AiK)8YZTuFhb!x{wwy*Cse9*YgO>CwM&a5fb z9`{(yt}~1L@w9K2@Opcl4Xt%M%vE6RCkNEJhf@zo5NClf$?t0N6++EhOBdKO{L<(% zj-8th&N>F0C#NvsbkOyIJjX8Cihjp=>sfoTJFY?#u5ot(Yf5A9kJIYdhoMC)>86c^ z96G-uP9c)6^OtAGGOQ`rF*5Zrrp3+5O^u=UtS0sv*fboG3p<2nuV&XfVwO>z=j(V) zr562x)*Q6Cl^G)sHSbOsl>uje*1PPCr?y;qJ>Ka}be0hcp5MEBlK~CpwN4`6h?x=j z3BZMW>jDYC_L2ci1*0M6**%lJ|t1 zZ1%r$_Kcv)KG?jOg@2)qCv~5^*;iJ*=P6xd&5sGbZS<|v%1H)a3S_HY+S0ZiH-=|J zngXS=ucMVI^bLbOi&hiVwo=oz8%!y$E{@IK>^@qn{hHAQrI#G8=#lliC}MWOJ?VhS z&@?dK9Uf0oaVvGyO6MBStuEt^{{}TJR)9qoaiV06Gj52w`Qi3kQZp`xq{i$T5S$o8 z4=oW}R(WQ@75y=6XT^w<@@f}m&MOl-bq>;BUy5juJ2xCA-qIY$_-4SVLD~wuD=$ew z)VW>D-72zHkzwRvyV{|Mja*OE(c_rN9nW`fX3Wf&;WsrJ?ft%co7xSgfXz}%tY4Pl`EcpOlJLsSMZiF!Al{-4Zv-9qtuc8>* zg28su?7>#`)*157*1n^pJ4$&vX<9Iy#kp$=Q@nOKl{T5sWWn%7RNAjS{aY{3?F?ny z?i>egeAj4SoOgUh%uqi@#^c5$^5R$YBgK8j@3uNif((x~h~<68MP0&Up3^OqGujEF zX5j}PB2sR;P>^Fd3L@&v0noIgb=Aa#l2wx4+t-+{V3cxttNZiOyBq&6xvW z-F^}Jfcqd)F?)dTE)I5m7UQ%R`OcOIQQ3(>^$UAGU;bn zGGi8|sp6#<@rX%>9e7yRC-Q`MMAg2i;3wks$uHmiYU)B?_*qae(Nn7MQBtg!97BKK zw8;IU4%J=#ydZ)6V?X$!NT8hi9K!Y#9hfb=XYF?m_VzrebPGI7+L(3ex3g*oPI#SV z4ke>>IkV4~qM`x-$Vw{|x#;9TL?FTTM&YvV-=5}5u|rkSCWe|pBqB{@x}R@3eVZ?D z*W~2Di%y7PFi&AbT>PnoEjyq0qbN+*`VRlY{f=w7wzl*5M|#RqQh>h15ASi@Ue?(P zZ@*}6oes$<6|tmw;pp=m#T2NKeqs*rAwEsoFImQs2{)7#@9ZVrs*qT=-k(Y1+u}AI**20g2N?%+t_F zc0b}!YYGK_)sPIv;-)i?N!(5Y6|0&6d5Q_VL+0KIiL{CdNa`!hs_;G;%t-D&(S1=i zI6)t^Dsa#9^;(FKJq0AKetK&HDC5|p$L~0u(DL$JyF9H&C--&0uU~Jut)k{dAhb-; zDfh*Epxf`K)At{Q(J`}RLeOsy@V5WM;Kgqd>y4@T+Bi|s7#YrDUZ#>EkPlC(t~etW zS(h(`oOA3zPxW`8=PY()CXTl(J>IO-uJF% zPg!_QDC|?BMQJ(_)qC*K!p^EqRadfpHkxc&kQU(ul-=YGOTRgz$?{#4!eqG7>w9e} z`*|4&3Hv}QrVgU`Mpc3QQ>G&yG<9V$ecTQw3uH7@d?nbQCKBY*NXu*qx39wq`BGyACVa6 zh4>N~^yziPJw<8P8sk&&6;w`7bPLq;zDx>iesCKvX@4*or42O`u}&^EQ}^PVL^{Po z!-9WEv!I+hb!)TmQT&zc1zA7G;8qcC<<`SiP1QzUZ!aJ5DH=$um)l871+Bk+_IC(DKmil?b9zg+ zKFS$ZSHqWowQc+J^5{7oU8KE|3x3Q?w%5-THdr)D?u3x(v1?0rr(yGLQNjnl>TAUt zTk5>Z-g50?Qx1~WVfO@x8LQfj(e`7Ba_o3fI6d1R>=m}MMFJ#eeXjPRAAX%J9oKF& z<4gxPn~hYD|8P!HJsr%xrTfOwlBH)HY2;42nz&_XpC+cAC@qHldDIvYxuf79!8?gZ z0x8)ejL4qk{l*4Y1uEnQfgy$U0Dz9U8x|H;6@Js*9^`A{(%L+*`qt^tkIDV)Is zr2Z!N8ZKQ#ucnEKD*i?8l@aL4_UUL9t|j>yea#-8E1Pq;&~tw7JWh1B&*{;rH<#1p z?hvMGIJkIE@TcLnvoLzZS{U#zcCXKVa$_AZLv{CuPRaqQ&*f%qz784JbR;HX@)Y z6Hb$jX9jy{q3J?g9>(3E0n4K&3^NYA>cP^FWO>`cS<68&$@_C~`6+2FxeOlvd_uJ_ z*q#%I#}T(QKj-Rh>-_WeQy6gOgX$S0%~;Z>*6FpM?)z)mhh_YHgOAK2>yvR@GCMna z$`&^wBsy=-`i0Sj6?*zqj#PA()39gJH^q6E!zzyZA6}4Ji4M5J@Ov+YLwwHXK3Xxh zRoXi<;8)X29@U58l{UqAb40kz2~OoU`9}e=ms_Gg)BK7ODqB_N8MVKgQBFh@tAuZiw2R9MnBL=d2%C%Hd!P_%q559ZTyNmE^4C~;udN*x z64G%^ste4uer#xE#nRQ)_5J&Ij72IKKPSd2{mui3A2F@J8$~10h~e`>w%)|c2)ftms~5!V0dR$KLHYvaORO;x_Wgrv;l#v?Q1aYLqwPIR?*7u!!b zIf=B^rSe_-K3a>;H@VRk-*oLWb+}R~hPq}FWh4}dFHaINoMw|J{GT{5?+wd2s7Xuk zbsJ=rReNZe_u5^FXYty6@=#$_hX5bTyUtmqByuw5U!>kMObHscBR%(3T){Gv zRXS^wfV)>tWFX^qcIt-RzN9C;_PpT)kV#T!zcdMhDFzx%9op=e>3@I8A_A*>f zbVus9>iuy%fMPI8NlAy-loK|5r>qzRvF75!Ys*cDnwolt^0y_8bqnt>_{+KBi5fQO}bcE^ROB&I>gaM#>4K*-j*aim&Jv=uotLS8a*aE%45n;2xIlmY} zE)O5yV=^*1L&F6*9Di08mJIRL(9rwt(Z2=M8HQ;L?4n<071okEUZIHL!@gu>jE{@^ zhE<-S|3|*q6$a*-C^x!eJy!g+re+L-+a9!Uk583p_Qjf;YVZZ|u@|M1pM ztT9L;wqM`KLC9MSnY35foU7lc_b^G_kz#$A7>gsf!GqU+?woD@iKf~D;+Wum?y!=| z;Q)Q+1~F<4AtGL*+wBhOGoaQ{7!o;s<)%yHb+0k`>I=_Qj-eSc zbG4No%mz(R|3vQq(vxYN6jFRYMhr=`KCut)8Nk&FJ0Sa-idZnjsnY&;6_^YRc=0D| z86)fSuRTq9WZ}(JbqqtdtJP`i&V*=NK<%Z+p|;+ql$%HTl===WaaOQTS5po%)}3$f*6Vd-A=tkS8pH#`n)Uqk5(% z;{Vn5XL+Kn(aw!XUyt_%7dn{LW8p-69X|Y9vDRWR>@O&_$HM1=+js6{;z=s=+S`xw z+&vttWEWaKeHzJ|ZT<1jpm=(VIcDCmfEK&j;gOL*7$%B9A(BMCHA=0+Wp?woHg?=19 zplj~XbFn4zlzO_NIkkTZRxcL``N)Y!O@c?#&yYrL#Vj{3C+$X{E#R5(eoW2YR^rn= zjL**0)njHbC0cp#ptGmw4v3Y+fTl@Apt@yUf?3L2eKI{$#?FrVshdR&sqMK&`XLh& zOFp6iUxS9zM|gXJMZRl3(RyW6Jt0*pI`%Mg6K7PNtLoWmf@RiOcsG3x^{j6&5M<1PI*h?ouKvpCSEIx>IAN>>Jox|rD z)BIu{4TZ*`zxkYO_k7POPdPxo@nN6Sf>4!mO=PO*K#n~Q0MHy-a5DnU{*2_t zd^7%23D)p9@!AN!s?_RvOsP+%S*@h@m-l71;1SOBCbotEe9k^7rlBdFBiy-{gK#{~ z+bw;pO2_Gr)$^fe+=P%<0h#T19(D(u9#;{4HYGgIrpgoTjp4b;PKT1<;zeE8@fVPC zf}d3IrKP-H^f+hzpmu+dv{$%g&u}L<|5cK_6F;cM+MU20ZK0{{F1%saQ#&P`fybzX zEUa(;o|ram7F&Y`W~Cls?e_VmckDWqnAfbvX41t@%p^P4x7+8Xk!E_r^7wGd5zAz-?X|FC&&*x6Xe-k&Z?;XCs+_x`QM`MRGD&&Rs z$c2obUG>E@ULy5>W8nzP|0Ee?)OP>i&}qRtW%~s}+n@D7OybPNT4i9L??vSJo__VH z#Wk!3sBOhHxbohzg^&sPJ*bJzzv~kP>^905o*1R1y@D9eo7Pybe zb{d9pG9*XT-6-T{vQ%yy z0HC6}An&YH@ygg!&@(vLa%!#kX9ZcV5z9*v)&Rn1k`Dbc2HeY023%>Y5P&Vqt~5IF z6sD_K8Otv)BHrEGUJR&tCDDADhuislmL5gq?r56QAe-%;d`CodC# zP>2W=o6Q~5v6W+&%NAd|nomActQ=V!=I}2|HZw3Aq8(3uOyQDYJM!B3DZk--S;Qcc zGrRvn!f5H&&Y=y3><1~D&t6-uafL>|t;+!!mcsH{7${4-_dH+wW2%(en8J-3ic%JT-Bj-U04m^_PLVyoH{saIBuP10R9MQEu&+My zOp#h%O842#JC+4kFOqk4yxU^Q@VIl6B@o%tHi>B}ZR}Xb-jbce?KMeBZEg|sttY6y zy$VA19K%lHW3$s}r~d6(t|AIOGMeX;3G%P&Na*aEVxHr~Sfu}Y)%wFG^msbB&h>Vx zXZhsep7~EnvJjdSIZt(hbe}TvNPl0a&6#xH)bB8E`vvW^wiIoeXStD2i{_tkY{kgs zrn~iTh`Mmjy_PZOA&rmtp}98k%iuBRZx7QbUmi%hroK9q@H~ zlZ}TJq1qHV7QQ1F{c+XHFA>TWRN|lfiM?I76iwPS&+azby__?7@l1jLcigt>a3ORz zlQebxi{W8mHUnAUaGv=+14L0v`LaE;o)4*?h(8&rn$pJ7t%gkD5jRtxI^0_16No`U zUY^jBcPKZ2S8x1aqF|HMl7Yi5-H7;{RN?yC?+?Q& z*>M7$SvW-RTH8PKCB=6-3jHo=bNA9)<}Ag{$jO3#T7S%x-1hDxHc?;S_WJvFdtD+= zLW38ygwLeEP*V6;#}AQ%(gM~3tzP7Z8}Th~uzSud%zFz8+ykqcj*&;By<38KP~|^b zJ~O)CCBt*c&M^?r>la@|K#?GakL=kfx@4V%t7ni1b>29`WwDptQ|%VkZ#9K0tQ~RP ztgR3a5wCo1>&-tmO35&Y|E@dis1(F09NJpPdlYr4X|yJ9a%F#K9y;_ zNq5(dMpYzJp9IX1Ih|HPNWgD(pEPRO=n}zykrW}; zpX)2*!7ao}QIcPAPuX{`BhYQh=w6EgiwyFF(EBLzYJVw=bAPG)YN1mk@Rvvtiyp3j z)M$A^vBXSA*I=9)DNUeHjuvrJ@#fNYSY)xl>n5fLv6Ce;B%z`1uAe$XJ9&JO6tnO- zpVP>EdY(BSs`%pw$Ko{<*{5_LMsfPp2jnxByf{7Vq6q#oN?VS0jZOPI!pY&zHrWs2 z{FkogwU~9E{gEN^BsJv9>V!VpukbC6=;wUzz1t-E6Y)jT2D{Cm zD|kh$w5dh{$%Qjdcb`>+dgY$?Sl#DFbN?wyag~0UW6a zAofN+B4*UOyGWO-6TNgMN(>VZ9#_dy45c2YTHzmP!@GI*b1Uf{JQB-AtmmDYCXm!u zuBz2T=@|y8B;_oKnddGAIgvw&Klh(x z`rsk9_`81=0_9HSY7XMwwL_Hs4ODDeDX%P*HQk*dh3*QKqdF%5$WOC$GPin2!}`M+ zcNnDn@LyO{)Isn+2Tyd?_5N~z!8&5I7Ks?V8Qz~`ZDo^oau;hR3e43ThlLO8*)=q;s{db zwf{_2ACggC@Ej`EM!3oLK?K)f8*B%1GA8e5NZtC`t<;>-Rk3RR0BcBkShwWP(Nw^2 zscL{wr-*PY^5~8kIpIBem5d|M)WI{6xZN0I%`hW3k%KWGZBdc6oX2MI!j@`Px!t1k zuVQvCQ?L`&=s?BKyYt5q^tINZJXdYjX)766VJ-*HTll3-J1}K(#@eo*pdJnJ#*wx8 z+z_JX--JKAB3D0e$~p)yHJ@!ZZr(RJj6dMaM3%-BuU2>J!5W_~@s2(JX9op+{-1}@ zx}8Cgxa;)4q@;tTk#$h{)H7CAMqy!UPDqy@u$1;ty?yuYHQ*s6CGGa^v$CFmlrH8X zjF!XIvnHnVTu|D(d$0`b$&eEP*6fPWJsBu#Cb5pQH3RDl@tLPpJ4D3shU0rJ$=NK+ ztG^bu+#D}uvY<5aNObe=QZT1;lcB5MU7t^{IUbVIZq@@Enm*aaQ~qX9F?7oVx1N97 z@ZgyC1>9Z9;bMJ0lMLrRNxHhOyrnsHaXDZew3aIM(a zg>zF@Psl`gEOc4E6Y`hY>j@`H4@9+Y%%>S?9y1O!M}KeMETI$CKw%wcemSpj)on4L z8DST#Zr-jGDX-=gs>+Qv?bMDb(P(`{MM!z+f~v?}dY%aR=Ek_8oaJNSgol27AROdI zv-af+Sd91eb%JW8;^%+C>bzvj{s&#En1}8L2Rpm-xF!AF>)`{v(M#PtZqDHcj^+E* zn|;r;PHs1QAcJy4VrmaE!g$HFq_SfFUJRmm{!pU^Om9ruRlnEQ-|=Pw-oO!+fR@V0 z$k@@81+3vI`Un}vw`no29V{O{B+f17Fgws8;mJIGA*1Id236e&I2I?38vlncHE>PO z3m1v`8e!ap2YkaXA)$=%Rl7KvYc%fv{WnnupZ-;q z&|)Nv+IK^?rMlCAIWVsTG#!;v3T7z65dCAk?m7K$KIA|D{(p(G`v2)D29Scb5g{QC z*M{N(jr;@9e`8*1rMO*>mE$XE={ta*2N>fTh}1wh3Wd6mms;^O^X_s3jM&BM2@;X< zZmI3v-9bR3y1!MN9&Bb=*{~b&%>DllKRobeSpZcpu3Q>GPZ0-Qn|ts0O0P7Sd5^n! zc!(71r1Urw{B2NQQ33{TK=AKhKFR_JF`9&%^MEfK^tPQSJf){V5a1G|o@#>tS9WiM z%p%~`)*p8NceJiGBZt3#sfYlEnxD(>2~c-(a&~6o@OAl}&Xzv#4KFQ@4}T0u#8D^D zQFR<096&fN#s2$;*Facq*wEA70c?YTdWq6C91u6^ynA}G_i}WCD8K9K33(sC*~k7U z_x8HuK-Tq(dp7$adi3;$H9dG!8|VRgIj$0V`xy!%rfMTsWk#VvNzx|hv3qTLAJriyHgXxp3U_%=(s>}M3DQ|s=OSZe5#XC}MR3$qPS7c>4cD^$uN7Fd0kg;6&?%*#wrCO*Uo#MpH zgE{GfnMB3J(pVsO;5{MH)v@!qO`JwI9z^gO;`_q-LeDj&r}5tuzNw2UlKQ zhpTS4BWMsMtUD_kgt%N!#$}w3t&nbJH!aoq(d-#B6`SoX&m~r)BNm|3X(qrO+;4Z< zAH3mWSUg}pC&F3IRT!#!5LxZR_Byr8VZP8Wn54pyKP@1&kvOGYdKSuh0f*FRkbJAP zrDmPy{B~eMF~Xe{>{U))vXakd11UBl*mQgB*QKPf>H)1;{AXjK=6;_;$hh0!Q3~B$Ufza_= z^^?#(n_4_jx_a0_v-yGOKz?}2SD-(Q^5&m?raa;rAnMEvx*@>FH}uPXi&c%ibqt3Glv6rV%p+f|KhV?i zf&kUrk<27X<+;~+ZtD0z+>OxH{e&#b;6V1rEPo=6$Ans%P^3io1zsA-WsqWVdW$q^ z?bqyq#cF7iax&gkM|O+}zP?DjCPqi9K2m@2C%vW3?Fsei(hS)9 z&=HA>WF&As>Lw}of`e;M`uc0CG)u}0IcO4&at5`^8bXSS&tWvnj~Biq)&vdSpjVQG zCR0RS3JF}SSa~CJ0za>U9oHK>mE6{E7S)S>`R#^RSq#3tU6^NczCoscGDRWP@G@CM zMtTHc&AJIfEJ*n1$W&7x7XvS&oCvJu1c4p({8u9SHHs+HL}-ty8fyGxOQ zf_p7wqQ+9|c4}L=v~%qw!T6qY>up@;W5#i~Nd5!0sOqoHBtCxM=C2|gG+~AoG}!Mv z9Dh>62vOPJ*BN2%fv8)vVNEf$+XTo4AC}A*pZ4G?4=wAIc6PqO#UGb2nkC?g`k(>q z@YP7b#z_z5Sq77>|Ap#KZ0hZ+Horkpl))aw@JVE> zDhbH4nu3bAj5S1rgrG!*sr;lf?;P!8P=2sL)o=k`8Mfv?$1YOMzrcJV!@t2Wj^Yo( zG7?;^wBKqu9xFKayyk=_ z;|>lSJZk+L^e8>4@P{Aw5fnuXsH!f4t}vXVx`SumpFp{N7*5GwH+!TwXh!l5sDF%0 zv=yomlWB5ed4SEw`8b1W@8{8Us64%4;uaGHHxN56aX!}7uLtjC+%(Mm)P80(4#@>} zQrKAExFA50`HfbvGuWe~=%^d09e4@}C&s^l(SNlQSWBcommFWb*|}1bF=}dS(%nYl z7Oiu#UGr3i`J}FzoK#2v$kbjB75e3$@N(ql!tk&fP!F2w%+Om6y3yQK^ogUQ8K@wZ zN|^EgYvgfgiJ?S64)2YIuctZ%x`%_->m~&lTGA`7Hw9z2fl{uVTP;b~2v0{Fb1sA^ zsf6v#g{1(`ldUIlI|NHh0`z8YZk%|DC~Tx=D*ws*Mn zZBZizi0?HSfx{LeJmv*2tDmg*b=R(jI_NGo@PwR3hQ5gtzXAa&ZG?Kj0u62JWYGN5 zc!uRPZ{Ex7FTIkC{hCtjX^`ntWy zeE4hf$%OiL_zTp*dAfw@WnH6;E%$9%rG>@n9YYJLM|jNm)ny1+RePUE4T99^C1J(t z+a?cUAMZmi{yE=~ta|i{jwb_jt?npgF^W8-Q z{npFPS{a@1>n?$yR}Azwig*UDT-ZejZ$ai&4DxQxP+E~;}eg5`z% z(7TVPA!4*ZXOcV|Fp=P8Wa+!FMGBAIwmC9y;~j4}X`EwJ;e+>> zoL1OpJur>4&fSIKn_H?h0G;=AW~vdyAX3O!yBIe_r0|pZAUU=mLG#UFC2%&JlWC-& zK~uvjZHj|IqwLG;s|8S1>Q>uKZX?ByRsyLLxhB zW=yH(RKIA0UfF4tc$|{2#)`KaBX`kbGKC^QQ+Ff!LnDhxUN@P2nBaZqL++h3a9);v z+Id?7fF|sCP0i*YAU4UFzJWjdeth`%ET#P#s9%a%r1J-xLYeicUT=>Fz`c*u^}UX4 zkr%Fa0=A2PCL}o2pe{sua*8S``t!ZWEQ`l9!=R~;=_T3dT)54%SY4Lu{0HIs4nucKRJ_A! z7Gc7#DFwYD@}^5iJ`spQF7E`mAgjubC2Yc6&8Y&Co>^7f_l$GwSuxR-zDaGz78X#! zGB=B|tWTAW&CH^;KghjyVOA8t<620fsU2Dyfl-ivwE?0198?_)FP^DSeQU zxBR2%FOPU~HwOMW5|awy17|Y9#Q5XSAseG z3{UmT6gE@%YAOyHBi1J0o<~li+7Aj&0%W2ltI4>1ky@$g1W_H%H0|ombrEZg2Bj-J znO^AyW{S?Y$>@{cq#H_PqOUh<3 z6S2KEx+7N&Ct`Z~%ojP=1``e^BLp>OZ?VpH)^X0SG*-h7LIXUev<+E$a*&OP*IO>s zilNUeej0aAyTQ*ow64mFPo3V=X^@DJ4>CIMYT5Gl=kxZ_$jx-{OC_^_;_N+Vh|RWs zd3rWj<#7~b6d}{gBI3Ef*E5iIg+%z&t5j@?eQ8B)m_K~jJry}_QSu&q@cm~IVX1B7 zo&;gD;l#_C>T#i&3BKbZ?N;J*c5zn^dgs3XI2#`SJ<>u*D&|3J_2Ijm5I6R(lE}br~r%LG-2zZ<8 z+jIWbJ*6zB+2nMvGs&7rUtySV;vui9SXD3WJ!Y*P0^qLc{FhkRVX%MkY zC3M*M9@l_^d$?!96^B9V5;*mYwu^1Ped44!!5uEB};o*p@u)%bUokZs+n zI$;9BuytxWg_8Mq3~|?S$MpreR*`db#>Mv`$NS3FuG6j_4&*A=jP)qUN5RJ5_c9)N_x$2HLg_8t*Pawgu*lYT9#5a z+=;wxOPCMModyGJrfXuq7RK(}>HcfyXZ2$cHv=~zMi>z)Lw5ZxZTji>}JWj zDM;Rov${PKr79B_1qxT(MxJ`|p56K^37DLzls;vLt|5wF^3*2Lnw-C={!!w*E&%7# zfFi+6OM+*6sV*f;%c=0((>nCln(NV+(#}KagvgvGHvm(yk7Eo-OV#irtiOHw`#dTj z(&z4L+t2t|IFs42S~SI=@y=}ViPbv-MeLnl**>b#-~EDj%ZJ{^w0<8%mwEPT!jsC= zY>J7U5}oju&jLudqB;X3`QOte$<6j$I^pyBrDzve_tNkM@7SIP2N#>nM?V-xB)88> zLlT=UgibU3LI|ES`iv33e3=}QAc}Oul7>Zc-V`r#kN4c;v)1%NY)zG)SSdbERE{FD zp;6lV0o87@##0=zezq5GY|&jMb>~5;Z9Dlm$M2*789D=mL5JpP##5PqzvyOPZXT8# z)0HCp*2y=}FF4Hz`_TyVOMx)$nwKQa+!H)IZS+nspj5F{5L_?|7YQ3Lx9hdxHwBd! z!|{ssoSkayUW!duJ?2=jxUgtnaLE`Tul=f4BN7HHSCsqR`|SSbz8<~0=#}F5(kHe! z`OTN1Q|063gY?Qv0r3udCrwUw_c{cXMOlG%1tz6hyN(|gjEXz@mt^1Q35QkL8g&We zPnJ~UMy8R~ZhXEyjaMxSAc$9Jm)50C40UMl!Op&%E;3#|^4cr4SHVbml@5L)6vgZ^wj)3y{MzXo4$;g(4! z%(E)_MY+&NGtKQgsS?HeVf-zoWSMIMyVqH6tBMN^eq`lyWAaeX)=t&Nu%x_Uddbm7 zCYcWT`nHr4=zKeVSmLoi7bmNC(@m*P+%I}sf$_3Dt=k^Inl>NFbaec3fZvF2dlM2O z{!wC@=h^d)De8C`YFdwdrOYU@?P8HIXmJZ;F)5o78YPy{a>L@{tsQy)<3hbKp+jI{aa)ARw^dl?O6b%xzh z&cuMz`^}p-vqFEq-+bgXIE8{r$JibQgAJtrZ>CEic}4>Cg>mHI#%Tcrd*x*QcOO4) zhz3!R3Na*7^tvBy1h^@~iB{;ZJBa|>=6}id1Ky|rBp~pE09w)g14x?^YW_VK42JHM zCT=FPq@xBQh>%097LW~qz}&Wyt}NKt*qnA^fU!)D3o{dQKYS!AdhTzBQ}{P+CFL6C z@^^2L;*5;eQ@raNE<}C6)23w3HQJ!O1l4=W=a<8t&W<*|apHP*ruQe2By{!9aDqbr zV+iF*-viMzqV|58NJ~X@G|&~CLdVW6FWIk(blQ?$8$i4cAf4y+K1FkHj{nc^1GJoI z3rO5@slR6Q+&J(b7LDSS;Dm>z08p5T@o{0$VA4RPP7giUr#b9TE(p!=zuzT1yibTv zu;89WcylKE>$!2mRQuh;skm5(bUWTvePBgYf zReXi+DwsFQ=qpkMRkfcWCQ-So43L>jhsv|vOPXZ*6{pcn6mp!_4-6hrE1pV|e8F2r zQZaRuRzpGeUeQf{03|t63p{%g4#O``w zUM0%9`@km5PY1S1mTY_!Q(5?N|MSE>nHLbl0onioFDqNnHJ(rXu#`g2%Sl$aeramz z0AB-aG^!V9*x287`~y_NGh&HGNA3;L`&fw}TShdY&gi7Fsd8g+jKndnB23e{Na^!5 z$+to0$i0)3XK&7%ymaH(d_tg_8s!4^w<9lX9=wxDn-~~$yU3hs*gH~bz-e1^T{bxB z>=-zVI0`5edr<6^UVl~pb*WGId!T;5^n1HSP-dIn9eV2-#utEnm>n~FVL*OuABGb? zc~n3maJlNh>_XgHyZ*cw`v@o-EUBwv#EN_IHHH^lq$dryO9*TP^fospg)oZT2Zt9G z8Vk&yZ$mxHYQqm-1n+Q1hwXSJ>A+w(kw;NydKX+~#fF{dvFAtque|p*3W*}_K7}`~ zO)5+tkJZC}@4jz>+k=>tQPV)*(71k&vgSa)uAkDwE3!3vWu>~_YXdI7+);uNivu}e zm&n#um$Id!$b`$Ti2@gNLY+!Yj3T%uG-NTTxw(tpI}6+M&X$${vpdO3s8u?r%agPa z92Nl~8ejkf6hP4jMkwgItJ9wc-4em`=^=nu+W<`Y6w&2wdlyf#8p)T|loZdYzJ}u|=%diU;o*iRw zM-hY?xoDc9{QCCI&iTEq={YGl{xRZRii}1dn?479Z=p#YfOGC?T;csG&tfY{V6cOc zeMHJqo3FlVV~!q%YLPlH#2=}C8|fu?jT7d*p=-WUfEuGQF!E#f{}$4|zHUvcxM^O> zzv3ukAnKdkRmIp*izz}M#fzKv#u2=6H)w%LoN?n|F`OQg{7~}um`nepdLOCcnj3BG z(hoqOQlVP{(7iRUggSZnEoTBw4V)zQ(yTIgQmu-Zr`1 zSN7ye18qv@D?~UwUEtucGut`#jf=r#D&@RqDF2kj?p7;PbM1gdzrKcqSA}i;uYq~> zgN)GJ9)rH-ZgJVmNrw(B=2bzd-r{j(L2zvh9+;|ijYGN1l?|QjqXKen9&!rdt(tNu zI}$F@1eIT2Sh5xUG&)lwX*+j!oC|{TjA~hBfA;D%pz&#lFRK`iNtswE)5MsccZ#jc zQ8|yzXz%JXKLpIe{9Boi@&oBk+iTGbWa~p+k&FyLX0||N`eY8M@(kDGnFmd!%@xeA z%8y0=Wv746#c1*-*eTv#YR79i42v$w{6$l|MqDv>RjUyMp7DO_Oa=dj{IZUlbeUc<&)F^k)0!=)ZN#v3GFJ~OA9M%CLqNXBK%Xzp{R zCMUsom%S`u2s`G=nOkUX8K3)XE0;(7eA|_{-mf$j=TuyLe1MtYMtTp!DbC+p&n!PL zub@w8a7r;e%oH{6c`*N)#S!sOK3?ekN3t8@wfWjlBq(FQnr|B($%ak78~2|Zc>_7s zA0FpiYIMtcFghmEuE_#4NC1Ny8b$XG?Ln!3(L_v(6?jAWX+oeP94@>M%-7794dZ2RF4B9)JS%$bh8 zf%v8V)FYI)-jQ?F5~NEW(W=QO@Mv!p=&4*-rcs@jpWt3)E>D@MSsacEkLWQ!0$EQ+ z>6z1Nb0F?Hf7sS-K~k$)iM8A7zp-?Bg%l=7xk{c5&6?Zz9Pnwr7ug#2e+2LnxEc%|#pJ*NA)o6`vPAt@rRjkR9uGEM#`P6s zMy4M$^2)UJpV(NDsmPf=pbJ-SIxEw{x#t|Pb&ir8$FOyiiiAhKhx6Bt#4=J2Glkwz z#kv!U8%sL;6?MUhK8|w^cTuAH>r;0VU4hmY1$`4S*y*Nr&4@3f`P~WOiP}URFpct+ zl!<}RQtOVYg_3HZfitTBa_I$j_?_3V|WSlVd9uNvYFgxG@ zVm=_m@&pp`a`~srG^5Fi48LhqFAv-Z$Rxx-nXr|L>1Y3(hi$T4tF84l z>(h&e;%jy}-Nght(gZwdu2F8R*l7Lb0dXl(p|h%&*aKSJx$~#Z9w*F2jTUSdviiM# zK8->6+c@|Vz4Ar(vPI+ai5TOOrF1N6ZroD+)zX zU#$ya$l^oa2NSU|Y0(PuW~7#kzlR5mx#PM<@<2q}XS}86lFVZ?6AaEX@P@cw2hehV z+52Lyf_{XKETpd?gY%cZ5gZ zxT?l{#0B>DDlv=>)bBjPo=3B=K$$uwx>Laf9Wwv{Q^bRe(xQR4d2|tDT_KY2NL4j6 zTXy_Qy2t3APJQ-YL5%)sF+P1_P-L54=KVPxub>~)8+}k7Or!bs`kkHwO7sggaCKnM;S?!xQm9s@T^5n70i!18An#xua?m; zgu1Jwh`bHq0A#Hq6I=g+Xe2jx#@r~z1#%GC2OOs!d`s5O7n$#%BG;Wiq7I@aa7aXV zzq)ydM~$@3%*>pQGz1v;I~|hMRt|@7ab9uDt`GjOdj{K#hjqP9VaF`Y z1AvyrX9i~LmFohyqNt zQD_}dQZv_#u}7P_cb<}=B8U@h?Z+`u-8sVbn*{M0b_i z4TZrQ=Q#ixBmK6E@}VH+;IF$E zX-khOK^DJX`JCDL4sidZv!uPmU#7GyW7g?RJf1|4qf*yal9f-Jz$YgAhRoQ5wt0Qk z*S636WIEIuQ8-l|hnbQ=MTdMY7K6-qzOgfItn3Lt%AAb7e)dGx1owLc3UjLISVQDE zpDk~vl6QHqF|~t#kyhU$4m19c!`K*KIhoHR?+xLJd&fA}9TlY++uB!My&&TLbo2{Zt|T5P@)8!lkjGGHC+Gq%i#{76TZ}b4&0-&XA~7Gn z#a!++C398=tlOOUsoy6JlH8OMo}1t#42#BJ5gNfjtZxbFuTs)jT{pVbNqA=grw24ULmQT5i60F$z@dIo& zv$cTpnDppT(-%N;*YG?PpTUktQ6Q7K=`LWBqbIro#Omk_&%2OwHP~PY^R%w#%{iQ8 zy=Am$LFC~j^(ksTxaGzRfo56#7>TNmsKZSy#l?dwGd&2)xpDN`-1x*vhu|7y3-8A& zCfCiw*ucQRgtp1!5!@NkEuN5`&t9D&q?sb;6WQ5tr|MLoYyK)2`)R(oax)~w4izql zcJol@r@y1KmkWOfV2Oo`@AFCX;&m+mzT(R{f#yTUKWbKU1{`wd`uG-wiE+Ev+n_&o z-w)EsryKdacVK{7Lc#!uy;V{_#Ho6OG#fYz_?)z>*6y}7?`{AHb9FnD0}7wzfyH(z z+pI;Iy5&4e&m=3mWv*diajzBChW)L0HdcOp{^>_hTuxDY9!=qi=1}<<15>+qd_cqb z57FhPg!=Um!DZR%uh<7ZK1V#4e5d&0?E3AaIha+JX4ga*6x8b^MNPF73~!ZCNQKas zUQ}X&1o_!t%s53`SUD>XC)lqGzYYmV8cM=-Gn-+u+nA^>Cq77%XI%5#+D3h%_vwaX z9Oy#A1AFt4v|EY8xlbeJ$XgcE2>t7IR!HbQzGF&0D<$5cr%B(R|7J?+c$$=3iVeKe zArtFzs2|}?JK-@u<30~Ze*W|o$KP-Hw6nJq(;#A-vn?ueuyeNK$?H5df2Ek_x&*=t zgl?0e9QTlUmY0T)nPB`6D{seZQbSxX9ke%luC^q}aXa2lG_mWo^_8H(rg_$n_DUVH zva?AkXa-+RsPUs_o{MDAWaszH)WW7Xi?T42J002d+#EI;6p)cVraj2O?Jm@mN_FNGI`ys5^-BERkzV7?`$58oiHxH$RAP|B zsCvrui1cAh<*{B`g9|TNSGf7%TF}V|tK!towuk4Ce`myE(fT07?L?IP{8Fvxbgx~s zncNDl7xW)dp+{TkW=W6y&$)6xF%f9V4_nS@CR}6uGBx#*fYf?y8N0>PiFwbPe$%5R z&|?rhwf4?DHxzOZxr5qaAY#epjmZY9fE+Aw_@Vc*J<6WVM~3T znd7+nH7sHDV4=H*`Iq^^t3Va%*O6cNiRzd5IjDwGi$W-u*&ag`$vZ1mwt_@2`fLcF z$J{CAF!ZqFo%1$S8jQ4C*x`=d>VIxH0!`!5dt>R16MJW`!kR3+xjCRJFRII)RlCNl zxSDutuIx+SwDFVoCiq+^Y)s|=xDy(mH^||#GG5N)Rt7>M?E1d(SAomJ1qkRs@c03jY zM9*#R?MVi5?YD7sjK->^)CPufGzP<9kA=CC5+=3kplr)A(upe%G(3VFcv0_fd?bBH z6$;*?cCnpl3GKkwofL}5+GU(CbT?0gzA!I8ob%bm8eICHF}V5qcvBCoF#uNdiKpLf z&w8dBV-h!GDEItmYEO&OU)BbN{rXOlSWdS=2a^9SSk#m#(p8mXJ*J@l zdtwGYrK7l>NX({pudC===*MILy-AWBp~IQ->C>|(jGntk_$*bik4@5_%GD77AUCd?&*v31b!>W@!FI8C^$Y zei$pT=eNo7@@Z4J+12?yhJw7OSl9fT|4c$T9<>{6!>0UO<7^sUzo{_|=c1eqT#?d= zmle&6#&s;XK<3d#+=RC!TB`4pyzZGF>0wCW4?|my8Ehx_T9wX8Yhks0e_^$Qkw>Qf z4y^{t_hKQ(SomiiC$b}DP@}}zfcv2f4Znwwx^p6%R%!fFic%H(415|Uo~7$eGl8@r z!o=w$ytI1I{@cl@r((znUp`~LL|&=M^?^x!hdZ84C{v><18z8-&8TH(i~NM+&^HyQ zaFYFFiCfh;KdZ|f7p*kFecwBH#GEH-XS5rc!t|zsszD!Ry$VUHrtP1!(MTpA`r^p% z61G&C6V}#*U#*szRZEb@X@u|4z?!+6A(8w*FCuvoogWT%v)K>7)-TIbduG3L;aUEj z72|!v?(aNh10F6D_`&m&ukg&k=CCMU)EE^<8k)d^+m|d*c0jz4V$=B zityDXwCXFvN39v;#&wYrxqmTcxzEp`D)P0Ra5}^h>BLxiHW3c7}W|l7Wtgt~x zknbLqd(b|e3Tsi{ld`anWaM_)j#z@1<_J(Ha*pkygK_|`T)V=UN~fyO6g5kyh0~T> zB9vPwKtsr%?l}9(+4;_*@68S==|u`kC3&+-^iVf*GJ>)xGwmc-?g?XNo=~4hd&F4+ zKfocu5j|j_j#2p7jIUH*gO_^0EyDs&TZBL6-JGw{`(mSMn83?gRa&EmG$;1TH@#a) zbGVQ(%gYQ>u0e!U0%p_#D*VTI^8EXnJ}rGVtgEth`SX80pmiKwr2vJrOkkhVyKORj z22wADo)hnFY;vS!bx0#Li;Mh2U;6yqcrUMPcTR`v|JQ`kBT0_NDC^>e@Jn%4tx7l6 z&0{*trx{XA&Y-mqnLGCc9G77xR70$YNkV#Qzfzvufy{4D196+Rmc$++PDupB&m6)V z_nA5Bzfst}K=1AKiLKDuX8aeXA?4148)3YO_hh|@H=EBtMb5kVt%vpHRS=y3v}H*rB_!Rx%Q}IP{mN0{Is_9gNO&D^%v!59MuD68x>t`e6uPAmu=n7 zVO7|=8(I>nr7x|Xn)>S#bH)1PPnx;U=j#c{y=`xny#fe(3)Uqqlnij6(u2G&-~o`y zmoTtm_gw)?>HJfhMS{3Ot=8jNf)~Wi0VTct;!#DmA}WfQ zGUZsdZ+l{Uax(EAid+%LccOQ=SADSqKHmnbQqCQPW8#!jY#H16$#6jd~|W z+|a4egv+D*aa#v0E)ZM~LWRkR1TXroz{;m#1>xB?P-yr4u}_gB(%MC-U&IW!mou@h z=;eR{t?EF!dVVgDJo&xS=c5nQ)iiV!=u~JU2&!z^9*K*l9NX&9%)An0nkmb*7lbuA zKUj@dduNyp?dH9&Q<-u345J(&Hr^hBsNha*)tu{By|fs(0-v;FI5L`}**5ggu;Y00EUjPoX;lS>tAc zn{$E@Wq{G^dqmy2dzB)86_x6SyYVeXe1(m^J2;T%lcj0SH2cqlPh`ou%5n<}v)kP4 z8^uiR@_D=LUJCSCh4L2}&g^^)J)aq3?t>ZF;y-lew?a@6g)^Uo5m|*tj~N|%;}!%%mP2<)$w^ViMVWC z>p*vdq&;o*<$QiaV-IcQ5F)X2X+8qv8e}o(;Ymz|Oyml7sJ;xi+D@l0Kbx_gS3w*oCyMa##n(zBl20%`?o;aB~VZN z_P2;#lQFG?j~l+CW5WfBV_W}aF#M1$vaKppdC7hJE<*`?cw8##8~&;$#{^L-Tp%n03NlUD)J;;Ixxs_tJ6BMZ-gz zg8ZD(%2;Jq$W$GhzY)%Re4DYraaj-WM}O#V6mD#Ea?e=^HI*E>vwjy+p+8>r!PtpZ5`s+jOPd_tgG)C?cTU6 zDkw&b-zp&#$M0Rnb-UtGY1ubFh3r`wVfKs z?UzFo>`mm^9tn`>B74g#tYmH8u#MNI?+?vN)j3&8&(o9N6(2aKm$X;ltkb*V1&E_u zd896VG~kH~jaht-vrKN#6VCY0QiMDH&rFC1!9r6ry`0nX6Gj*EBm^rnlxztt-<*Dv zZ1xR&_pI``zhGt6AHTof81FdeKNL>yCE;`4B7;WfK(Gl~5nnM3Z34HWnGcrhqw(Qx z0V1*n1F_X&lIy9>#wWpPPKui{gQV@JW2xDqkeOIr@!!Dd0{`i05d)79yZ@I8lLqVu zyAEXZFuaID3fg3&v6EA7@l95cDu zGiB#nis!YIdoc9qXqBj^4171lyY>}d;(C;U?)n=2!g8dYjHuSa%K{=Xyg9uybIo6c zJiaNS{WdNN=q%IB%*Jac%hODq>Y{ojF7PGj>8(e3jwQX`KXYFv5%tQ`2Hhena!X)o z-!W>dAywLO$$HzEP*924U#ZMY27Rn?C$M7e)jBcb5|Fwsz}a= zJWxf7`n|pB@w3_aStihde%v!odUWjlS~R7?A+)XC(}iue54nZA^h4J_5sVAO5#(

^w6bBG?cY+wKku$H9Kd`FF5@jiVxQoBYWTRj1`|!Y= z2aKff3U5WPf%@zfQLpntd6ffxTip%KPp05@N3<2>CeA3U)kIq{bo zdCm5B5E|OoaJ)&CNsbL**}#5>1!g z3G@CRe~#~nJ0-Xwv{63#nxyklv;dUjA4UQ0$+aBe7OG+nkk!aI($D`erMJ%O%nH|;VYlt zSO)k)hKxWKi|vyO(OM+*gla~~iC|m!$A~af^rK~GDW#`T@`aWoO?WtX#GsCZMJHwa z&ifBuy|NG-%9EF3arvg2{+ftJDEg+?bPWBXU*sNgH?t9&yV%Uo~%HTnH(=GPjjmd%)<#LpRR1Vj`-j^~0_Rsv> zD|1pyG5CUSIYTW5%QnnMxsUH%1ikb;r2Ory%+zT-%FWV|OL3o8(H&jn#Ir#}Ddebuygr;}mubVdSFwEyz7#Trkxi6+e#e*!Fzd zS%HbI^QxNA-UpEa?P6g2h1{Ef=?8{a&FV1Ik9;ND_*Hyhva1-sQA_*SZh7J8jx*-+ z9HIMH^RhfQKp2}SI5oFhKM_!sm3=5ABt%3+v>2V3IAy5cNg_l&&^lpK?6@A!4CtKI zB{)9QEK=|5@0XRAzovP;VSL1IZPqI?6WDZvd8~-@^i-rGaxjNuyv#uZEpWo%&Fyoz z?{GbF}E#PftE9pE|ZCyw>fIABHegB>D{Rx z&iC$!;aRToSRwS1r-R)~rrE17F|fELe-xJo7ovIUU53kBKv1$X5-nkJ<(G%?PPJ!W zJ7a;H7u*$zY(*J)`t2Y$Y-Dan^I}SVy-Tl6A#?EJV7_WYeEgcidjc-%sBKSj*!9&E zQf8U1HN5H0a~M{Jy@~&M<-pB>#%e10)rJj8Q|Z^f$IQk_X z^$^>Q&b(MFu*>xiI7JZjZ~8S}pC&1QwHo>>^dT&9=jy3soW;pyISKD~&VbE6fj#?Z zira&DrXrXN?s=omym#fCDbu3f=_Z#{To;$l%Y+cLOnaMj70}bugLZFgIKgS~G;NU9 zDDg{|h)U-{d3l8@wY9k9<|Gg8*&qnJ6~OVp90X``$dv-tWxThz3K_g?R@Q7&-y4QJb|E5jjCGt$o+`VxfCdrT3vejSiH%;9A$a+lCI+@JA z(wFQv(yKG#I9PR^CG-MCTn2Tq%VrvRbFY3d8G76c)D#s+#7>L}(?*5V|ednnOXq+l%eK z1e2F5%5YxGg zuIZIsbz0|VIrt(_{4){{|9BOJ~o2qzF z!ja*=M)AlQoWq~-)MCZEPc0oUvCI{7#(878x{?WUYWeq= z-e@;L*U5UzV{T0MGBYqFSXcn2q$qH|mEK-l`CqMQts}ccD6|S_IQtm0rL2!n^EC4$_A?utdals%WQy8*(UkXzD^R z4Z(pz5=oeiaz6X;vq;Oq^HCKZSH!eHuN7YkvL#{QzBndk>q8&2#tw&?manjdc)JPd z-s1y18T0w`?cj zo_7ngx~&UKJ8OYOPn;PiSlvr+K?v2fd|b-UZdv`Ynp${0Dg&wLkKSV+d+c{cR`wbKYb2k8AJUfDUEwS;5b&>dx@S)QM?EKi)N zjm-w62RyR}(2UihzX^R;zI>?;cy09DIZ1YJikw1doRg4=E zd`zB>p9#I^mx#7Ioyxw2e_Txxk!+OvOcd6>5xXN*W+S6|OWv=d{q41~Sw#64#9fBGp*%yk1bx?@fp5fMZjq7rsQ3$n> z{6>+|VW&s`l#bdmb@AU&!Q1{!6wNFlbjGOJo7ctlXEgino8mU9zx=&=Gb&>+@h>s_ z@JSZJ_VeFse#P@bU#;tsn0)Q1?NXmBoj!^Hc=;QIw3%2;HV1a~Izgp{x1Yng+bsDV zZ0&_UiFlS?NfFZQ2e-JnBCr@ac|#`igj2#WX8AF37nC9G#(`J@VLQ+#XsqvjD4j&v z&INcs&xOs+#f3?-uU)3k56+z-eHv&lpL*B3v92^wZ!uZlL#N!pl!c<)4BYecAt2b4 zNthv1Yzp;@>XP?%pcFbuO@y4K&K`DHkuUJY)S?NPT&!%6DyqC=U26Mse*ZrHV`DmK z!cd;w$^yW+qfpY~d_QS7-Go?r_oRAGTKA@+p$C> zTH1ip$M}mf;CH0;q0N3eHg(x$loS5qTTGLN&HcD;EQ!$;-EpEZ76Q7xRfHaq6hto# zzts%&KHyt_`aB|`M@j|5pw~&Fw(b)}Ziq2BKJIAtA4+v3902a=>C^a8QxtP^=j5EW zf9H!d^30&~o#8XJgZ(?fuyHWj`P&ZBq_Z5`8V(1;e$y%g2 zZU>CkczPr|npmezc-`|Fhee&tX~4#Vy^i?AtcY;spp6>-{U>{}7>jzj}_A|6a2v7X&tz-C3Ao`3sV{(SBL*M;0yF1R4?No+Bx z?qCyUi^~Kl1i6pUy*UTN?1bm+u~Ho}io~{OKE(_ySLGtRM{iRHot4-+YW>~LhpgO8 zj6H0>Y`q{O{QKSJXh9nVmw8?UJ1 zPlB=)Hre?-=Y6>Sm>Ov81(-@DpziZwc)sZk`3n*hREiIv| znXjl;&&Zj3TTgec4<_rhQrpto3nz3B1A;_;c(nUFdwg|!Rlnm&BR-(U ztuh$XcRV;LTPfsV>V976RBxBKhwziZcRBE|{-E|DChCLc9=W2jJa!xI1MtC>GgUEj zU(mZ3?D^33eA9rp3|#y{QvGe#I#d>yxa@M=eN?}RR+Y8iOIC?IURboF56!^nV#KG} z54W}E%NF88uaQ}fb!&n!gH&<%lAJfbBNPuN=gK<8$MMA;&2)C8Uf$< zPBy6YZegbM6QRgesNSg^^Kcv|&E!qJ0M6~FT;ZAPT%rKIr`M$;DcozQzaNnjkrsUK zAaDp?mVyNQX|I4_{2!-T4vJ<{Dykt6f`k@c0L1)2;Ik0z^S?Dcv{X?SRa>(ET%GQS zXn#FJkN!Ff|M|C+l=cH49r>?^&F9Y_{RgK5_zfiOOgualbT3}?Ua72JRkhsPj*23H zczTv;vZ7;Pxc4av{A(MXUtGA!-JP~Wg+NYEg^T&=)2I2Ur&g9?k)!z;8D9WRAP5BV zz9@J9XM%zWfH;wDdJa#C13EhTV{-B>wm&Z+!~GfaJz)O1nPv!-5BKKS<-YZR!8$g-7UKRxW2Ay{&zYLlo{=D8m zuqm+iLnsBpfYs_+tda8kukjku{r4<--`HT_uD@z;++?A*Z{|4*eunr_?8XjCQ%-+$ zztz5&3x@f#prCAK53?E*KQgXUv^sg>IWXpmmlVE#jkN{)qtDrQ>p+D-P!&p zoqxbvxkX1|JamKgxmQdM8o%0rRRr7%ME{z?tU6vs6!9v6?MiPy#Dj*5Ff`I{F`pg&H~r< z#Ol!ijd3a5T#-L1Q&!z3?%e|W_j9L$_dk9@^7nxL9drW%-eTRQUH|!H`5yER41nLh zdw0}Kbm6sU`?)?V3mstPu##YX`SK;Le00#VN=08^(b$;Y%gbwiBwEejm9#W*L&59K z-|TV9-UhG|CMqXlHPXGD=Xr$rTsXDwf}RhsWtSi7(R_&v>}1IL#Vp*aqar75^NMgg z6}<+_@@TRd7HFWxE1Un`$IXNKy)|9keJ8cr*Rt@Kx3%vbI}LnYw~3>5hCh3|il&Z) zz#I+uaOmDkWlI@Z!1v0}*EFVoaCX)V2M;e|c)XbMV77D15lU0l8eoEb>GwKi zV{y=V_~5~Tqmz@F1pVi- zvu88C$B0u2H8dNL|DrwuHC&=1QD{ueZ8x)l%q>pznHJR~^ua)0A3O2EHj|!%F@H(P7(ZmFeJdq=Wot6lo-K+nBcHh5!o{eW z?kI0*giRR45}wUmk)=PN^U~2e9nyd_WudkEC@9pM&e^P@H zZ=RG{#@nA-bGNC7?%#cNv*Ift4M{_w@{kFQoft^1f-AiZ0GUM5iRWLxeQWYe0)o}u zUi&M6Y0IO4^Efp7_oZQo__gS|!?=vfnjyov^09%_EAp1+e74>t%Jc2;QLWlZg$>d) zLv3cCi}pR~tR75_Ijd|ZC9@?amX zr(|xOD3gJs>d-VstVs&x!5jgE9SI=J8E~(3aPuyOyfsof`gnPBO_Nh)wTmcP$L2dz zT1Z~4A#ZE-w^@s-aCiALwYuK{nK<*SiJM=)lu`GH&wmsDjdX}3fBR>vSXH?-WBU5| zxL)!8b+F<86&I_rP$t2W)xzeCw^tLWsP&HD%lR>LMIyZ7#Rh7fA1~XAPhT7uPPiJ( z@sE37+`qjUC8%#Yr;2x)>(9weQsIajPlJC~q&i{T)jc34&d-#!7)u&oKa-26el&j2 zb&A5;YjM06^>*{iOGo_b=9_Q=6xxB5b?HKVN=F}*$)F}@Jgc0R-hx|QDI0kYVLb=N zl{X>G`H9Y5;`G|{~mB$;jq>-as z#~F+Plx-67;lJMQ&>zTs_d=&Mg|+t|0Q9 znYjZ$`kg&&7|Q*CNw5_Y>`S!UXVTkV6hoo9{VX*M&Hb0vORHr{D&>l3Q$To>=0M6Iqo!E)LazJnIC$KvF@Q~|VXD%aoE))!G&uAK zJhaD(Tu2^BN^8quwmm`H&S#nLsxFaOo}0LnmzZBJieFgj2q!JioAev>B-rZ_0!Z#9 z>m3sYtAi5;D@8T)%cCXD#?tEiEIHmHo(qs0V%n0yHcJ?94lM8L_}29%vm^m|_^!M# zIl;j&sh~`~$P5ZkTP_liSiVs*J36G~K&S?|F*vZI!c@GvV?nHbaV^~^6>5ve4|$4k=P9`uQ?hu6|9BYQ5JBsG zjaf`9{w2Bik`eEA#Ud>sO5UWW%$ZtfSGyu1o@V}CxI|;GLplsJza#KzLfWZO;%U0D z)d~mT7VR*y2wih@-FLMYOcB)EhqI3c=~@a5tgLmWA7^dWx1Zuv`4ThIO0%s z^zHevbX?(do0(Fnoi_Uwv&|SQ_Xp3BrlwRDJh&@*Ge*LXUTE;QPeH~PBg=f@r zirQYi<@O9x7s8@E~j&nHlDp(}9DPKge45+VID7tk;P=vs?3(BzHgIs6{LwrjnwA zN3Wiv;#tuUQ|d3b$&zw;<-NDvEV@1*9n~^DE*BX8NJJInEzh85ej7L;uGupHpLd3! z7g;3Ff0@?{KP6M(Vc2iao={j`#;PYIO?mxxMpiyK1~926CXO|u##+L^slEBaLO%K8 zesH$P)|`jKT5VBGoN)e(hP>98b6lZUG*dBIU&0bpboP?S+sjtS<7~e}OQmgIv4-oT z@`^c8N|fS^TrSrOh8PovgMTHEz=s7MAoo@HkSaOoM}BQ(N=pAm(NKPZdHEDFv@4(I z;<`g6YmFc4#t81Skb``cpi6W13}4hdfuI6zm6;g7DQ@TcQ-pM0=$CIYGCF?$2Pn1tD)apOe&$t&hfm--H>6A+bk8O>M=t%kk(1pC^?5$`nhV zY3vgANvQou&z5n1#ZNZ6@}teH%f?~pc=fl}`K51U0+pnz-4ib_9Nu$bi&E{fDGIxp zL6JDZKr3&qQLj(5XV5(gG`itM!$R&E0Dkf(IP?^@SSN#y!hD%*;EuMrZr zE7bBEiH3B(V{qKheqp z@p<_Xp1fvJiGW4ldYSQ|digemoKo_4LsUu00GtD+`YTtcftQ%ToFk!to={-H6%!$a zt8(QIt)lX4Td1xB^+b}BP0~OXSE`sxHw|!5s@ab8>^nYSed68yXdPVeV}9z`-;TCV zm%VG1G*(sL0?nK+>?jpHJ0G_g@!-ePLE#fYJztYGH5GFwih@`8AEdLvQ=@^a4BoFn z9S?9GF+d5FMq2ab8}|L6ZmFVCTw+lNI9Shqn(zq;nG&f{WajU94^EwPBFN2|wgFbOuI#66`7?!aGe*DeoVOD{ChE7MC){_9fHqxBZR z_XvN-!_8*KPaw@N5(-MF-j%3ZZ;hX!x*zWbS&s)p%EZF2g%Rp%BI7?H&Lw(7eZ>7* z%@A>ijS_PiElx>z;_I`6$Mm9-V9O>+t?4s{pdelRLsZU%1k0$^leuKNRxsu%^Jaaqh4B=)D32ukQf6dG^n>pREVntk}urLWI{F zZKivx?H`0FfDC)I`PmGh8V+$4;H^jM>@%&-$=^m(JA#4h^s}I>Fi^s2L+-`SLfZNk z)4o~dC&<8+F*~I-6o1deo5M+)IJ(A-juv?;y$;XM_?@6Age6pv&o(s_jQF-GajKGb zK38;YZ!aKht=~BT-H0>DZTNE|1-8ZzKaeXYJ#m@phKOxQitpOtkmmSCfvW*|zBle? zit81#T|_|r%*h%OTRK*`$J7=*o}nQ?^E;16(u_ji3evURpJVTF6d=? z7NizWr^@{q_b^81BqBcAme^iUbewg-U=xUll{YfXJc*+tnqJ4LZHIp5ahHpvi{T|D zT%zf`(`V^D;pvT0J&AaT8A=YWby!084%~G57LcxTDBLimmF}{6w;|eA+0W$R$9K{U zJGavlDXz;R&Y(lv60Zzf9%w;ar9(u*RyfcQbOWif?8u}<*lgRRoXzUxf>+2IlfX!c zjt2~sCuYsvpkfhyCaQFOtqoOd3TJAbR@_*a?|LFvTed60v-`84b~(wBIjy-ZAuX74 z8t5K^}RS~oNuA%0~-_St{8-$yOhZ3+GXylM?HhA?a6pxAh#f!Fy3DV%M z*M^IU7Nz6=ffM+PDxdpI6$C#o`I$4z5qWxOgnrKV%w_1(((>I|q|BqOGN|BB=I3mM zf}4lUucSJmgwc;f*IJ*Z7O9cO@@C9O3g)v2f9Nyk>t-Ids^40k53H!=65iW?eCC#QMx#&iN>h@ptD)~u;q4Pq?igj-hB7d7 z&z#QdqS3MQ$=+6FRQhn#$e( zbe&gqAycJ~6DKJ^{09Sm1!47l_DA;pc>?-LAbN&Ja*k9*pb)2~>VziWShcaKLoD29 zg4{u^Q52}r1eEb(`9(IJlB?vKG{<*lzvpxEn(!(6;RpVO;}MDwHfpP)EG{_q6gc+ z8#0!W<-d4u1fCy`G-&)p8Hwf9Pr5*E%P?>oGm-9|u2olsUa81<)K2RFuOh4ieWoRz zk=Ve)YwoQt*Z#Q)On$sQT%tIqhAV)_;h7tfd*Wt#S{o4he3&8z#1Wv#$*D@2dVx@=4rgS@c$~<-ff}1|KVpA2 zXtWZyp7&1c_vjiPmrvGta)&AU3k#qvlDeIBneI}KFE}(FaUhsn5AGi~K&Wb*!%luP z&+&(|i8xHEYD?=WkQg)?nJ<^@FD?gv&DXO#=Yk)s7_yBSG<@M9;guripW0Ln)e(9s(w|hP z=ZpHyu7*@je^(prS_^#Y7!=@gG7%7F^0VKB?Lr73NqK#zwz$?3%NbE){`2N z9QNrBT`CSwTh4hQwqRN8o|}wo%Fk#!hbe$&%@4S4dHQu-lU4+H zYeO&JG@&`+Zj`@99(H>?pso0FBSjC&J>0=FJ3JJ?(yINnIqw}7zP~M_TdR#CJ_;aQ zV&RMnkp^#K$IOcF{~nuA)l_@Ek@b<4?o$45Ncm3!aQ9g|X{2a(-U1|JWHl14drrJs zDnN&-^P1>zoEtpFqSZL1C|ji^6s0WpxR;uzm&0DgoG<8fFPqbW$AIFtP@n)f5kPZ6 z9(&m0`Z($hTtU(fnq_X({ewsu<7$a$kHSNmFN{&8f}{_}VTs}(ysM*uz(_M)%n4>f`HsS3nsuSoZ=%1=AZ6yp;eLIon*qYF^rn^-pOLh{gYeiS%k{@odYytnzCC zVO;8ttl);xYG=AzuOl|~y`pv|#@NO0hJ}cU(TlcjGKpr1x&HWaWNOR7&e#hEpDX;- zW&f(Yus)%x5cgZR;_Wrb)+m?6li`WRh~$?r^Z+Z;cfIBGx~KfQ=k1yDa(aD~6OFQ7 z$@tiiO?CFb68|5**DED5l(u+LHQqzrEw?xo^#1rF=gh^l6QTGxPaZCZc%%Ur`yF`;q4)dy3V~_8y#cLS?&)0Y`fLIyrn7RlOiS+UFa|dujx74Rko_q#$7j6FvCyDR>6_ZVo z4;CU46J_7L!LXVr2Kps(ZPibg zXp5d;r2W0%W?hAxnodZF{lt4x?&}|P$E68)7R836AugKbW|%sA!|2Z(e~>aVgrv#m zD(-z;>C3dA5k(@0F_?FDBhnNdHAUwf_B!XCshdqSw0-QDG5{Si8>lyxP@YHM1rj1wW08@hxq01;Hmip=&h9}3y<6H?8k_#ji z7f?;KxT{{?9e4lwb)e$(SG^7RQ~zc%l>-1^?)dkAtV#b4Id?)=e~bP8{gcYae-*I) z-YIwc`2SOb6q1sZ{C0RN4h1CZ-`r6WtiI@dJCukH4=*bryu)uSjQ&T`_$sXhP)Rty zyfiM;1f;o+V^VF@3u2Fs>fwzOFGwt8+uD)6O^`o0lW9B9+y}%@K97J%)uyN+4fN`(G-H9LM!@HcAucwK70? zX$I+;;f7p{8$<@1>eV~a@$;W%dF=uPlDi>J z3Pv@wa0Z5a$V)MI)ZsHH8c@Hp5Vhb3>U|gAE;M^oo6uD5&gDO3pa1b2W|ZFR{KhsV z)9O-E2cpPv(QwY&qz(3Up@F*>04#To{<9ndfcC)lsw+w$Wgi&A{su%bmvy0Fw`K4? z?O<^IpIKkE`)l&E>Yk&-ndJgi?Ohi;6kQFC4K`xHN+odv$4sPkUHtu@M1ktAqRh^1q@|c;Pk~I5!-63GCm9Q4Smmimioq2+Vtb&t1}l zi_vGAf1}KOe>StlkF<7KcVN+)fmspl!?e+4g=baiSkOJD4ABU?3QbCRrXzJm*CuAPaQ5L8*6w%rg2BlcVhJ#vva7N z*^xmtH12`6AsQ#4zM9h~xf6VNh=W@6AFrDm^x|0E;{@W=DnyJ0@fLWZ&@%@(9E3TV z1cKw6`xu_ECY?^)&`Ko#iqwD6rraDIMQrB2}!cnJ9}bbz7$#fLx)O?VgZSHOCZ`q_>Bv);kzt-;KSt!KGYrx;>pL zuHF>xPjmKetn(!U??pWf%zl$zIXKr%c8TUX8iPMhOdX8{Joo@6kb`d9(@q_ zQOV&i2L~Y6C`^gD{)_ z@9H{lHjW`c5YVnlL8*;MIqARHUf|ILHJ0;{5X=+{pq11H_wKor?bd~BmU{_k&3omn zz8B!~lJb62iG_$GI~_8I?lKN&nvL_uD@m~5^txi4DLx%mU3%iXqtyZtzePewv-AcO z2w#`(_kdjVpNrWvhrHry(7fDLVO|y*DxxeN(8kPS)U4BO!V%Vo_>KI+pr9Pyq9EkWPWdxRNJ&qrKf*m-(0Bm3GUh!Ow>PR~rJBw)naBIl_iv9=`TMupPx5d-L^RW@9BQ%1r6b`57%V z(kzAziC`Tcuginm(3P<#o2Fm#T&L}j3vnm4vK1s=ow@DS=V88}yC5pc@7f=Yeb`bD zO&|d^K$btk_vB~3@%P&jt7?@-w1guCd_mBt`5LkOaZe%}{h{`Ao%7z%4zj5!g|0qE z$j$HW!flD9p@-6HHo{|v(`93;rQ3rWi5ehAhYSv`jJdkYIa;pCO-d<7k2tTck!&n2 z%@w6KInE1j3FBR#{mR^w%W1X&4-tQ6Z&I5Lnn&dYQz;?|v|@Z;_POYG4f_0<>0Q=_ z;})u*keG_SQ30)5E2aXM^Y>>83=?dwpO<7KJ3ajEq~@JgRs_t;vKbOSui|D&yIt}9 z#!vX2d>n>Go?^@=e#CJBXF+Ib&`LW38f-zlwmR%gRvpeMz2COnmWXmrAJ|aMw~&sB}_U(rEpiwHm|`w=JtMJ*DBn6-BOcya!4~PATL&`2(8?bZD5yWn8v$- z%=mo(70iGjZ|-wKnBx^``c{XUfA8wGC41|?eHE?_a33NK1#)Vd)BIiuIK1k%8wqPv z&i1`KX?Psw1kxdfHkj-6wq6-T_!btY@STBNyu`bjbn=1ZV8=h_z(@?rBz)cj?#U}E zIy)-4dbNIcURmkCoNM7ub0?eOT_>#reCr2JuGBbYU*Gf4;8ZPc4FG5vi)Zj;wP z-onSyeEfth`J4Mg#9p8a?^RZ)MO%<}e(rqv^?DGiYmEp#+wV7J>gawzsw-^9`Si-^ zdsWvY4Zr!pR?th~6Ke%+?W_&`Aq;=6Mrzs$J2#qSIZ&YNUTebpEzL*khufsiuj_Hw zrjt304R5^5(B4f0mlsZd9!SCLjG4A=I;hwaa2LCZ>^zzk=`K1iN1CWHt)C z@I8GWdX+0VW>hdG11%7Fo8(LgDoN<6)h}c4-&-lDIg9$0N%$hrDaK}QfT?0O#B&q( zS@`yA`Tb`>F1DF@{l3TLu$7_`MaM?=*)WQr8r$qA%t3y--UNCi+InLP4lV@}&OfnE z-)m~UvM@o747RlJlrPF?V6Dm*^NH|A?B3uwIB{ocriOC6 z_pQlO%txn*g%&GtE*Wv1pZnpjrNhF)Z+n?MLOs_bUR*D3KMW!N)sZ(5IC;beo>A)y zi~8t}9rBcS2P^HWlH|6yqxSUlMaceeY+CBqL%erg1XQn0@?4H-?(gb02LCt`bYJkM z)u3G2Uua;W9w7|Gx!B(jF;XV2uMU6u+yQ?9{IQkeSzz&A$O*3ljW+}qpCOs=#%ONdHX*PgpY$d&e=_9&Xm@14FMJ83+io?cF@^V;c zT>3LyT)n9#cyT_uc2%Hdxw!z!ZS>k45)T==&c2%5e7n4y@etk2yKf<#1)AI4HG9+T zQEM^#{2BHq!%VgeFZ@p0<4V;@Xp~Ef;l(>zcZnlfFP*mzHuffU05{l)~^_XPUKb#3=ez2b7l)$Nr0l;qvh#$X`GGQp1xvDrBTtmm(eWjah zLIAOzEU?$Sxgb@`sqEN}e-qH{Mr_eTRv6u{ zIM{LC(ku^eY{K`C?Q^KR2VjeT&lJoGC2fA3GFZ#%MG<>W^&FY|?oGtmu1wl` zX843A^2__I)4IXuYlH@J^Je+!V`dtKutMiygiI+$G7skpg^^BFDFQx}_y ztJ#&NbdfpZNkasml~HRI+FKl~BcEM=hkd=S9KD9H+G}x^?M}wIXp1?}lbg$|NXr7V zj(F2bVSSX{;+$evLR#@d;V`Zy7YAEg=wS`1!=#~x z-#36uqzO-4d|62FIB7&h6+o6wx9DQI0DJOv=8iNuSVg@KCC8Cv6u&$;m@vU;O*Da9 zJ#ilKb>ulM_=1UhZ{Y@_Dv5fC7mxued2GLKW{g#B2sD6#4~6HoL79>Z#g1@VGt z`5C>8NeX$7C_@R8pv2zBQCN2z^Sr2^*)<`PRQ_+ikOp0_I;SnX_nwJwH7q5hBN7k1tcd zG^F|va$5+!jD>BR;$(GojX1njGF}<^s9Bu^0i{;BFE~iG4Ws8cfj-7d6K#-|aZHd^ z^M(IxLb$P;bI<8yb2C(x{k)hA`g-ljAm#IzcItfR0RmM{#hxX|YI`y@HMFTXNHJgb z+{0TF@J*36{K$|vB?SG#zLN)MD=s{W;S2n9z`L=qHhNAbpB|uQ3|b-ItVjtJ;v@QC zLucjj+}8tRv?VwAXe3h!@i6qvCt-B6)d+l5-Q>|*!fH0v^=*@ast1|NL0eq^b2+cy z*2CtWA{->C_|{YCG=+_IhCj$>RVpML(G#Y@kwaKC<2xeW{JC-DrLGtzSFIOcw%j^m zcp0L^xy0)Xo<}4-wX{pVdY$ZIu*tdJ?Rk9jJ-rO3xGfhR)^Jb-H?;bM-6rO4_i0{+ zHMJ>7no_PzB*Z8|Des@YYk+Cof5$#aU9KOl2C;3$nX)cC4rrP%^iyNYv74W0tjPPV zvt{R;snd0gnZDXZy0EzS!S?WXXmst>SSYwhr+b<7wxb2^=|_HHC?=ZzNsG=K12%hw z#!e|5lOdVQ?bTNSd9M;WRbJ53Yp1pIJmG{63++d~)j}M5#@Zwne_1DAMD3*Ji0Wuy zXej8r)x+dRyD`ZE_yStQ7b4X>S6#8k)HA7*F&}L&rZUAP{0mFWj!bvNrK-5rCyeQ` zK}^uOUx`&M^=Tr{X4?vcs-zaUW4+$o5Vp81{;n&Gg_<8fz?Hm^34Zz37qny_Nhfi=M0Cw77!d!GAGsWD=Mc2n^VTK5QRKPihl#FIwqfDz+_7D1@h z1K!cM$nEY~hlP@hH6AAhTuNvjmtH_ITehGB-v>PpfMYG`XvoV2IJEDm4as2Dl$VrF zi-cry(aH@6ZT2Wbg4HV=X57`Y^v3TWw5CM&%{n%2a1K!l#EGHW4^OI&T880)%qy6(vDe?3W&03Py;ht_jPNm&zp zi3E#8j?5_IOWO0DNj5Y;!pDylvbyjL(iwye1Ov+m-*6UsKDfu1IN-fwx(>)T6^!W2 z5uzlYUT_yeDBjJmaH+fVR2 z#ocOoA^61-Et&jVSM<0|!Klj+^W{x1Y%n~W&zq^=tni5ojNZ)qlE0++fZ5htIJwK? zNE5J#6+!e1l?u}iS#*8SYMuWv?&GJEKil**L<^x+W=@Hf+X6Uid36c&^Gv4HeN{5I z?WTDA#&__Qg69ez8O1D4nhdEw=KaT%#G&b2pW%y4Zu0Y#=oov?c}11-aOtW&y)hJ!_cWB6LcSoa zG@DFWb{xWZqm=0h8@NCAIq7=tIqAC0ee^q(XN1n2iBO~{r^Cd|q$ z<-~nAj^S+s7kx&f8xC5{t}I$kq1pBrwN%QbzOd$m!Ip*dnA<_!_QF&r&D3sJl9s<= zQ(nqD@)gNDz-su}?3s)g!uxiS_SW@t`keUJus7+M(DGA?LMMDdStcPQ_j&bK@3rWhi0_*eO({0NZ*y*M5XNNJ;kt?& zFxN1}mdc7GFz(RPk}n&Z6KwoNv^?Vok}|;3x~Nl|UB4nMcYi);pre}C`~!;{Iix0-6fV6lhwhVTGBD;PT`^gE~p}!*UK{ydKwyZ>0I9fFB_&wM2IBA&=Uy%^){?1|GsI3$)k1n0`gs{3Q`! z*fzLu3kT}FSh`X=RXTNA?s)>%zZsP$@PdeW)`x8bQF`~TVEP$3!bPEI67|6^2yIu= zy^~(Y52bDoYi=zMaF>IxO^*sGA3a@5Vn&D4Wc*`^CC}b%=)! zzT~4<*+|Z0HVN>x^GGl~Z6}b7FyIu4FQG5U@p}iTHkDULC#TBRRBxeY)rhgJi2dw) zM71*xxI)Ak!|aECJeP>C3T}ubB7C_yY$IGPMeBKSB1ixH7a};8kVxL{E#)(Pp~!ZC zjDMP3g6Ji2NNUt;Q{lIr>pM!t9Mh>yv0Z29ii_3C9p6+x>Xnc%H2soV+xv8LrIes_ zNshZ34pPn6%8g1&5-ZfLj_&zv81=&$8}p-mu282b9yjn% zipB|uQn{}5g-%&;q=de%`p{5$bREyAeCWhMZwc*2m-nEttQIIgWrN~pe*QePCEe*$ z8*vR{-Xr{A_e4wWjV-PbF#9GG)R#-6=dr@-+9A;wk@8kn@PO zruWD<)N_6etY=T2ry@J*%PO9STc@GdCQS!rH`>EZbp?!g0g)pZtwibY+Qrta*t0MI z0D+4#8-O-@fyVaKUi9_GK59UHbgT%bV!u&BCjJ9+PNiWO)M@ACWDY3ryA!L*EC4y+ z7ls8l()cV4!W8$Av$Vd@T8oZN0WgF2w&=G7T?yZZnKFoP8V;JN5TA0Ti__VY` z8imr>`qog0>)_h#NBRFp*?UJdwQcSHwj)OYIaZ{LD2Vh0SLJuto5J-TK@ZIV;ciem5_x+9W+kYqy2gxpLtv%PA&-0l* z%LA%2vuLC9TlF1DQ=sVB%#+_bj03vbpXrd9c*U9aF>Ukky2u`3)7|AWz<8LZX(rV( z)VZtVVrcjWBw?ZQKKV@8t1xXj$rV61U2Ii)Pgyn7LQ-9f_Btmg(Su*yYNAz%%~Ni^ zBmCLmSyubAu+gTT7<7c~_px>tOHzNckMo1P0aQcaOAZ7LFEE8?!-Si;0gc>v`~%lY zxZ1x;XL>ymFRpsMFa>8;B^B1|*AR3NB;6eBW+ymp#bx;2&B2Dbp-Bn%ZsrA4swTNf z$({cSHZK_9#1IUukcE4rdHjvK<`p6LAr&<{d?WQa+@*W+|AF zh|Kh4%q8n8F1EYY1)|%RU5^6Xmd|dn7eC-O_DPy1jpZT9w*;2djLIFm%shHo66FgS zxaQ7S$U6LoR%zri;;;oA$qv@^nNODMf=a!4&0^lsHf!SOyJljMXnrT76>-_k`}S-< z@hKstKMiA-!{;CEmR4H?co4no>gwz>zr5vQq&#B|6{s?W>8Y`=CFQ%xMH@YNlmQkG zGz~ttaOlK1#;ncZ0ZS-vxEZzk_Rm2<@Y;8+MBT4!wK7#b6Ulvn)MpKGftY;}2hsX6 z`y18ohAMUPH_y!9GN=j+pY$vjEMPkP_SfKkWR8PgNYcP<|360G6!}#uFceG!+HUTO zwW*j0DhEt?6c(Aw9b6gGYl*-5NrNT&DO=CXpY_5JEs2XJ4#u%2w;Nl-C9L%(J#2^R zXAv9TEQa?8?N__IY4}Hv9(~X!p-(Vb0 zz^XK_VpaJAp*`hzL?u-bvqj3yzFM7VE>v)z6Ps4^F);AZMqIT=M6q)!{m|)8u$@kh zD1K#BCH{E9$n75c<^}G|a}3^M3e7u!O(Q zx|#0%-OiRT>LYr!9vq6Y;3(+m&S@>e-8G<(CbzzwaP!D>Q#__ao8jDFoI0%YjZUB0 zDR_XHH`DKH)h=DV+UsqT5ya`1@lf+wx}3DM^kwP~g{ypgI>lP+flmw#=U&Q(gi2K} zXFAw761UQMgmbU%4DdXIlOmt6G^OZfYDiV3m1-@BEr_XE^3GL9ircP=pA5dJUoIAC zluk?LGBC8^f~wVH8WX+sIVb76Vi@Z4S6Qt%elbQEJ8xOsIm4c zHfsHbM4qD$#i7ih@CQq6*lYj#L0+PHI!z(?WPRN|bG;%kJ#x^d>G$m_;ElXvwNNfF2RNEfF7r&8v+l)H-z&-M&H7abR z(6WIGCSW;Q_~6+=+Wh4~#qhhRgZH%rpySm!Zf@;c9HjAx^Ua$Cgyf?2EPhr1~QuJ1c)y-;p}_J%&IfM7|~ z#b5D5-_)41j)ik8=WMky zDh?^PIht=jqmFHj_<9nYuUJi7*jHy8@n;cDc@c}ZS`;eC4YSi&D-B%Xc79~i#%|kG z{jpNQhD{hSMdd|r56kNCQB|hbt$vOKk33u*{ANU zjXSU1TmR;;OHw<2-&XLjevU03{dP{Sf?*{N^aQ>B3^x5NNUJW^PQN~C4%54O*w|}S zzjnig!!n3{YWJzy*Qo$G^iH=8RTaAw<0Y#rw{vxFby9q#ig6jOym*ZqEHX5E^yTz^ zl4BZ0v>A7jn|mmEcBSQUU2ubprQ}N=o%H%T27Lt{VktM!1QqaJ|1_4kiaI)~+~#oWShkBo8qjhQCTfwk`p)!EzN;C>8`~psS2HN$7pjeMxcMHv253mEe8!MD<|jDw zo7Of}WIFEqso--qZ%`krC;9CW>|y#Uz`jyihLo=FL?%hW&W5tE<-~l7eKJATmLfkC z$Oq6@ok`_~4J}gwCm9%EfF1bV_?gN{yb7UhF?*C+{11HaT=8X8?$M&WLsvnQi_YDq zSpy>15ZA?u_?F-3R^S&td-nQS_&c8BmBS$aXr)SBtDKO(^kmDY>sf${4s10cHmVs?^3|>o%oTxM z{Uu!^oeWLu8w0Pw7x3~m0DmwHENp4=$a7NDd%0S5A)o$wq2%fJ1R#r&vaQHnKQAdt zoY$D$SCVzE9Q0g0@^lYxGfj0fHoyE}`D5O}s+^q5_($)p=46f6$|0{ro$gnQ&Z>I( z-li_0h)5>*EP`+G~e z-3KXU3%3{kHQOwQbK}G?l1qTk{9iU7wC}lzsGhZBCox#k5`7)Kjzv2p?etzsCA6z> z8^jIA*_KvXgGw-P897T&305rmhALbzP`N$fcn*a%v%}VTF|GFb@R5@{_XC$NzoG8f znB7td$ntn1Te~^yJ>hxzJDy^Ghr03C8%3{7eS0{+x|j9Xt7~tN9YwJ2?<;m9S4zGe z00ieILnd~gqekXZsn?qSI*8_Xo4wCa6!YOmU+EkY#Xs2?zH;dI3SkaLVk>yudM%eq zePNd>0Xy+#JD1WKkSvM9at{)a;CP^5XTRZBE8XmvK7r!yPPgL`dH(DU1n~`5HimM4~gsgOEswsTIh;FeL~16q;F6li2ru!1&H~ zEZfhT7f|&o|7k$|`9nPawKUA}{Q)_dj~5U9qTb0=#wIUX&7RQMKZl!WC*NVzJ;k+* zX;hq6tjyH6zDy5y(uTL|`y4r9ckRL5+fP!j+HhJO{gDOH)gyejwGDdr2hb4AHfa;3 zR<<0Ycgw=+j3W8To5`cs*T(Cln1i7l6CS6(i-~@?hIP6Szt{iQV73dr&NBmMf9-4w zby6}udyDz>Rr#Ai3kLOqHwrR7x}M%5C8|zpVXGv5JY}Ec_`7L(RC(~<=YL7yZB2yQ zG6s5Mnsc(t?xmi?B?kVF!=>k0wV1B2&CB^vnh$5kA&A9swCci0*52?$^aDq5X8to3 z1pGz(;$^UwkMMSjFhDjKgx>#?qsco>jt*gh?{hYdJ>61PzKUTrot3Q$AVo;v4;RM| zn|en-rC;;J>!9y4wrox(c^gRXq~Ny3-7tGF`t|g*^6IF+WC+jQC9a$$0wo zcN7t6cFpzI;%rllZED&t3hW$6ob0CGo9o37PgxA->E{sq2uT0WwNUq3vlGDbM-I>V z{$I#Qql;Ovo4L@CYddd_Rxk!0Aq@*$`SA6t_#mIqxIxTa;y~-lK(Pq^ob`)I(A(*9 zT$$C{y;0}!@9_uru6ODsN@0-iQx4-Xjqeu~k!7OyOq4QSQ&HG;dAz~%lDsRPKdwwv zXkJrU-YAoP8oYO&!*)Kjg!QWv>136B;7j$2#krXqg92fn{ZqLnn_6@B?vq?zny6+L ze)t~lc`OiL!|o{s>vOGI&-+YUl#^^<#!jERf9sZT+WuYrngFg8qoQY7Ah=@r*c|rV zZ7#J_MY)HBvS>9xQF!e5@y&9hIhztbap54k-F2jS)4O*)<+*3HpUp52B@VVDZpa*n zUd3ItR5hFJ8cP#Jm8xEu`Qc>?w0kA(2l*6V`SoVxPeOl0t{MEK`=KeC48uG^V9q55ejg?qq{!LR15q7@>Vog$w%`Gk_A1Lzjwvd3P zr+$XIy0@L2iUgFxLqaxETT?&$ja_8LiGa$oN6&-OkYeFW`%rp_7eP1VzGvZ@GI1CyjG z{64FHL1uu{!vVrw0438bUu<0ZCN-54=wu7fTfQuci^abS3X*&|b1OO~Mj0)n4Vd?T zuAu)y$^eTg=@(An7p3fH!scJ-n^fAAbG5)rah7vSnf-v`-wP0(Kerf`L4lEg3i=nt z<;&vFn+zPi>i>v`n`x1r($z8g%pgG6b}VOTWn3=#_DgT?-3Q8-wx0dccRuC*=K_9K zdnZPOfzlx^>1eReS8*|mMEJ@ z7=Ud7a9CHmBp|WSm`kDFB^7f6Bpcv_f`_<%1(Abh?hL=~^xwHCK&kBWb3pz3@xLKy zfH>f9*(72DkU4{5CyvCE(kAg__a)C~p1|{rszpdeZURzs0gpnXpFsnlcQs2MJoy!% zBNROaG}k&#CK5hL)EhDuwH%C_EaBI#)*k1YJ9cV=v>Bg_WCVM5mwD{)1`+oLoapcsXX4 zXr$6o`0a>ed(h(ieEXoC{BiiM4qc{5=0W_e1Haz>s@Es0nS=esES1PdN&@QM?)ltv zxpl&wDglShDTwl{UL}%RgBf(q?@4SEAl^&ePpn(XI^_}#`>v^shu0RhH^V*k# z>Pns-%8^)cL~*1NGPY;#PmBHQVi*~OEDmQhhXiaolQu!!BDTQ>8$ zt@0^(tUbQx5higjRkMwZ^4@-(;1W@nz{|HkBsPBe?c~XeLgRh%6BVwr)tei$uPq;6 z&L|c9VtmkORhAdF`uTc;(hhG`*zOvcthH?@Wa?l8D*HwvUN79C_qN6W1C9xaI(cSb8; zAG7!Rx*f+>IFYJzyRmw|WtFiLs}xB=_yiqZo|Zx(XVxy7T=0SYyF&Yy#C+k&3846i z4I&iDJ=T4yJ%F*!e^}&L!hO4%eEaS@*cw;V`Gm}{^>87Raz8=M1X1u#P|cog9AfC|UZwDFGgqfL1GNHGL;N!Q2=|RXN~F=r}V|g*Xhws&1Vpa9*0n!=)#U z_Xn;vC7nmUHB!ORk`SalRfa*n(r6#ehm9UUl>G(#a^7{K6g`>iRb%&J;}T5za*4V8 zDqh~)c`A7Om!IM1qlyRY=AD9!;&r0eeyINimZj+%1Pi(G)M~RD>Kta4{>82QX3}yu zdW9sVgaRM#W(m~hsNPMrm+HFS7HjY~)$>D!nY`Z(HK_lG4y>uRp;hTGEMf&ylCaOF zZh-7g@FO43i`QisRPmXq$-k) zcn~)~cs|$Hvua!2y2KN;_h)nwl8V;!+a_NfHIV&f;P|<^ch&;$q|OHgpWKNGmzqfz z7t=Ii;-eo~-&J~FWa`%P7ekMVcU-Mdd1wBHp_k$(dq&t+{*5t9&$_qo&a$uTR9p|L zY0|IRN?zM-VF~!g!hZ(ho-?nk@>7V>r<`#&SiN6)y!&%)%DBFtAeESE3GlXF3W?a^Pxf;a0 zR$X2>;~oiE4DTifUN2>y*09vtXh)4#xygY>w4sRBnl+avM4Pql#lnr$%tA=(sN+NY z^>vfV@ToFu*DbG7kJgib8SDo^I&hZ8DIe|&GjigEpgpS`O^Be5PUEKN9cq4FKD2Nx zS0vNBL(fo{l+M5<&mciH();ScFh1#3>V*{@O(DwFiBP+5+!X!t55$MrZV!pq>LF)sKW~GRr7hS)BHBRqm~=+9_jV1g%0le(C35atVoquC^va~ESnnmr2~QcnE@+t~zB)NoSsPpI6Nfd2T{O~>?gJ|8Jvwj- zJL88-n^Vj>8?zrk4T|%2^o?({sf{h)ZhMvpqnbKZD zBbOXqFExuaiIcgVPg@!U1SERh`lMfPQk43j*-)A64$e__6`zGubV`Q+pzuDNX?lOY z*8M;}U~lk_t-nMl+hI-X<)yp)Y~bnxkCO1?~OCg(mAj>Ei<=i zlAp;FwQ;W{{ohj*!1pcwZ{?SNJoC>!<*d7xKP`$)NQg;H3_&0e)!Wanis#R<$Lv$^X9-6d}wVl~vj&{?n_nv5f=Ns^BG#8-G)wXYN+j=&0)a-r; zt;uk@e!WL^VKiZ|hKi7L8&OYtP&)G1v@Y__{Ex0h%=hm`;V$bD)(fgU&#dS4Eb8}l z{Aya|#cH?hxf`;Tb=NHBK!#TfC1O{f9Bo)laL8; z9FzG!e%kQXtMkk%AMn_5=X!y@`8xMi>vzi-HuA~4QT_Q`Tx2wHFsaySKIAm>Hm30laVTT^|~~?3F+p>X%iYE&0iNT$*RS zYy91q-!k>B;@3ozp7I9&2K%1e&YtIc@k~wLG=vgm+j4L15Hpu0hAs;*k{NJ{4q=YG zCd!|*E$g(L_?PG7-Fk$NWc1w<3x78GTpn{OC1dhk;AP`RMhD%C;L7%-4@Id#jiEk- zB={D(xv6ivwqVTJ50v-v)g-B);_`&YN^3~yy}=v}mb&ofSLscgZI7?|S=V*T zET1F~>*bH>cU{d+oM4zo#NIW$WuINb1?%WZ3bvf82oJf+EBm8?c`}i?9I2kz$n8*h-b;(ifZ4_P+}!>9ve}AR z%7TsUuIkNq^?**y=WYL94Spd6f4#n+CRYS7-QUcFw4K9HtrcNwY3cmD8!X?%u6$VD zAeedMS`Sur;EQ=V>2rA+gn6$RMe9?Wlm=St6TEdt`%Xi}m8b%q17*11!BJ<#6r%Vn zhAz;GW4Yv9YCCL!}&|<)8XuKwOJ4$l1;bXri~UK@#0 zhSOA=3iGr3g(E_)DRD=eyX|fd;n(|aQY!v{7FFvKUk>%pgpMz`1Wvx5u4+a~eakK= z&K|YUG|V}1)%;8+7TL!|9g77*EXg}}HgrDZ_;&&foAJ(74|U8+afiLvti4}x#Xmc~ z%fB-TAr*Jyx!u|2lNbVq<3cuQUgYc{t8do`dmRREb(#^DW-h#dEE2pt%pPtWA&HDN zxOep{AE_#07?mcMIt>mu4>cM9gEa2^^FV(5J39B`g$oONrh0mBN=n2og}(dtO={>~ zijUF#-w5j6Bz))l&a+9AA6jQO90jbbtbS8PaeaE3lW>AHUHKQ6gXU;vmRh~gnf#Pk z4={ZawXAfH$MgEzoj*-i3HMKxX^SPA^n8DGe{C{>Tr~HdRMcYF6b!y+RoeSn0K*)9 z{fh^b-#xM;xiS$sUHg0lZhGll&7oO7cYWo@UQ5E&PY|7GiD+(C&B$nPA)WYN zS<<_^yPTafW}+m8)BoA)0@w%vIi~8#@oFd!;ORcWur^m45>ji)bm~-wKb4%$_M)S-a1ti7*qcf;S5AL zzw$Ewm5BnXT7LG-$-f-w{|w5IP7}5NA6W@tE`hLssS}it=yc>)>a~)oEbiPhk!>;% z&w!=?VrEcf24;54Ec4IbTjt7NS&^%~S%OYSgnp(`etp~TRM>O)5yyZeCT3=Xue?`9 zqJ3Tq1CV65Uf}fK%*;Fkn9D%!>}R<4uO!dEEZ$N_WYMkHHRC^~rTNcjegT-oHWn$D zC9F@ZtgHxl^#0AX{#Ql`2+DuKlpTP?60Waib=4k71PxwIV(mGg(H>}P^8>Ch(*D1; zq(339zg@#VIgviE0CRC#Nark>$bp>C^C_(mL>}o{?`!k#=|U1qe>u$Te16aE`)HuGgrPvrC)9j_0?%y}A;QuG0N`YA?}~wcP_Ee?I#E)#Ch< zwd(X^%Ayw!u#jKc-mv2~!h6=^i~}0{-?8l{@AT3>_)Mve9NBrK2=K>$=e0y4|0~A^ zV4EjD_{@G^M~VXk+m}lcQ%X_N6xJp6KEMc1NKR*Jf8mGJt2d*DE zzf6Bzop5EEM6^3ZTF@|LZo`{TymW<^L=&Whiz{-KScT zWz!MiPV*u%7t5gLCoK=W&J<8BQIP`VPdasNlPD{9#U$$Xxtnu}1I}AF_V3A%?JOYH z$-OR)&sus+Lz;=Q`#BnaVQWsyXpN}cl=W}1ftF-XNxpUA(_guu*K!cKwc^YKee5e( zYgu^B4R*Y%+PwASWg9N#7Ki;RK$vVw6Fj`h-R6{8&so8womSgaSQwI%G5x$46v$Ht zj06zyNC98g!EA1c%~~{S%+xI0@&!|TqPz`PGK@8x7|9Q`oHGe|e>yxj$s<=F{>a}b^vL1FEgo9)E+RpPp-Agac z`BOexK2fuJS6w`5<@h?qq{{C&W3zE*&|=S+8JKDATTFI-Ugvb*mKUV_*=Q(G158k+ zV%JV3F^-jr2Qn9UMVVraCl304NT&v~pIR_>ZbpdcV zc#O(=3irx8`u~grKvL`4tOZqz{eN9h4;GzXL6@i=KglF-i*7zV;=8@7cE=YsO1SZ< z@TuxQ`)E6DAhDJFk6pJ=+rpBN{=X1gVttiay{5_-~#*ZL8`EZoLg)HD~n?7GRBnX?5CN*1QQ0qYuR*EyDsa4Jbin>;w54n;ZyqKfpyi|Vd#lFil~ob9 z@wG0~+6$(>a=sDx2i5Kznnp{yP-p`)y!qQl@gR#mwXw>`#x*%T@B6p>5>E=8F;yO| zQ$XF8ZaSZY6WGUPH=C)kBE>Rrg*8kieKIACbz9yTEzCn3Z(i<_qG0WwV%(4VnuP)D@ z{@hZ1{FKBQKU%8%bUTb9#%l9LBUR6)Da|v*Yu7MSDyPNlYOup6NyX6UIWxdhcSW!h zaU{63A#9U7dZ;ekN4DFsUD`LurBhOTX~=#UDxQ<&l8hhqU2oqlGIVPga9^4JFs$9u zKwn|E53d96n!pcvX9cJB&B;||XZ8-Zf?l7_(y3PYOSPQ$l*Vkh*(Y#i$io-FzI)`vc9P(Cv+iHTDUgb*6jdxFk@ za|gn?Ro`he3tK^IO{{nnS(`ib=ZT9&VwSksNscvhKU$-bJRjm=ft+{o#E*Rd!(^C= zy@7g3z){3R`C|ZZ!qUciEMlwseDge=3f&2_8CH*}*;!;RL@B?>Z?3kJHFnFJ+K^6+4EZzs zlfI#7n>IRQ4M+)hN|=-yI?o(V*0UU`&p!s8IqZr>KH`tTFlGc<@EtvR_5$Ovt8c7L zT}C`STtpCsb%h1R^$s>3=&FLb`~uOkOLtGKh`jDUe}(z}o%Uqhd@O^*DCM{noXJJ$cwBMF&~cfQHD99X8QMIVm~vrRLn&RhU z?P^X`eus$-iA+`D@Nhk z@%=)i)(|?o-p$;wHznEC+hD<0z{f-uR+M!}5G~5Ny)Fo9s6;g|f`Eip) zxGTR;`>6O4#cZDd?z+vK+L;DMSM;*iVkO+9LJ@H@o25wt?t$D#BCu&YldTg~BX%Y# z*PD}6u9y<)lnc1)RCQh$4n3{VEwW3N5lA8I`_hR`S|$fC`X^1c*<>&J2ep~hH(j5E z+mPq<6sQ%TwS)@rygvopR+y4rRx&uDq-;dnXrGet@Vt}|Bod(O%m|F9ZwT!pOp5u^ zj!+Gw^p&w^9ody8hyBwgN`wty{9J3@XX*Kvq2|_^sIf(@=k6-2H1);#A!iyb;}Y<4 zqM1TVi|`zgzWAz+qAVNz2}9*Xj$%wSoq;y%VziTO*)+1>S5=Y`q7AcA~D~f+;x7$>%xxt6D4BX7Fx7x zt5V%$Q^B~r_yV5%Kx;lXOnFWQG+)>SdV&15UBdQpKVXMVzxIZZtY_Pe{v%4|ONEJU z4%s?M$qaS;wueS(Nke@%Cot6)hmvxZdIdOv{@n#b)zvs`sU0|(yXLwZyG}Q6tAbvm zj|;(Xp-a^-AN4699Q4v1mTjRZ#AxJ*jHx?T|Eiq{Uk(}p@Lu@T&-BQ{>tpfR6~ax5 z36*E=Yk6Urh$1I}A##J^*t4;-BOZBq%YCmr%1JNvHDnJ59v5HdFcR%Xu0c_C`8y`N zGqhUBs&egN%R3XJ@mL`^Ok+vJlyU*$5z$K*Q>0owOjy8K((}E9PpDIlfQ$R=L(rK+sn6%TV35wRYn{j>ew) zOR_wvbuDeOOk(&znKqRdz2C>HZ6{>fwo2;x&?;teEtS)GMK?v@x7ay8&}vXKPmG)n z<%=H}co?iQI6l;L@TyA09u( zm#oPtl@ z`v#F57Ilq+LafN{Y2}`p%0%wY&)G|#vBS|z+2ABqe3P*G_G3aVt}oqV$`eIPYW!?W z88U0|>R&#(f*q41m87Iq7NsfA!(+*}*OCoPJUdbgeRqT;t%gHB80Hi`|v!_a{gD+&!GM zywG#P{=3BobM-@{Z;>idI`A105WZq)E1tzq0kPlJ;J7zEtn}5|>5}S*Zk+^!ZRBRF z8~HQ5M+a&i!+`dra3c%ut0Sy$GS`lo7iQ+Xbg1(5$}TUzdGX@Kl_8Qg=IKF6u90qJ zdg~`sx#vAgl_q6h^Kr%L;3w;8{sQnDmJO>DW-iknwZ+mj92SSb*66I9h1Ws!aou|U zRoR~l_|mcz67sRr2J5ZX>FKqap+4NJ2j0p(s#gV?NQkZ8f|BW~^}+2dFPvBe`;g+0 zXO`1Vrq z2qAcKGn_i^GnprV6Qk2j_Xt`-L*wPhVt3JIPy!q%*S}5&r^XFoHWm+-NB2yI8?P~D z({3KROlXkGdEg>E2mLU&2|)o|5zlV@0WC{&aCoq?2)l9NB$=KPscfx{rapl>0NVQj3sp$KeCg!aA=i5YkxKYj5@`|fs0W~VNS8G7 zVqrZ#dlNaT=`8RC%dPifX6e)q9`pe$|1n^+i#-6AbKY<^Wx}_HrJWepAtO|GHC#qU zKVcg)G7>FZFRgDY+>1121-A{xPX$cnkivzaoy-QEmf23kvV=*fZ$pv%6~Mx3_7>DKA;S zlUh|K;e;=jT zkiuUB%2Q~Prg$^5 zmp60YcB6(?reOnVubfIz{6H?EJQLS+$iuf+t*I*A@vYx+`|HJhAeyd9Q3xhlJ|(P_C|+DoL9!palHLLY)dCd5QL zRnx^~DgKA(+M?R)>T+|DmjMwI!_vn25~OnZ)1fEHn_biy7uBkKyUWQB;BF?O2U>ZD z8|sqXdr_5=)9N$hp+B zH(Ls_Mz()0DXXe!-j=GZHBp&k2F;(x;l4BWA-{ZHSdoMSV|FG>1Bg<;NRFtH`*veg z62<&BaTF&a#UvkcHBc?k_Yl>h*a6TWgg2 zGcp#cXW_BlsnlR?!tMPWOmyWbG1i!OX7dJ?>jj5=#2$$Cn`8&3@jKWtv0HH2&tK z%>~?x7wzkYhzuJ!TptYmrHG>NCN8iYvfSS??$uLSn{9Q-#33(ye)T5eE6Yi-8e!J7 z!xpC=`nOsT4pwd3KBs!_Pw3P~EmK)AhF~LESSG1`{LB)VvD~(I zu!2(-G`~OcrOEesdt`x*+I;uH`YLE#ZyUm0^0^GU8r*af>W$BJM;G=jR;%XGoSeIZ zz$sE*BXrR6#q(}6R_e{T{`0QOvkXgPoBE{AZn7iclr|Nz-0AN&XIIia%K$`D5%Sl? zR2`p@d1Mt?L{}blbZbaL2WYjM$(9T7=AAab&4R;tF*u18KK z+%5ru&hMkM=`Prin{^ZV%}WHct#TqR)bhYN;N`$hEquPN(0Q$|D!X|sA_KPg)`;6+ z8&B^2F(28Nk+~-2Ir3ep%y#l4x^fM-L>7WuDA76g_T@x-oqFOSCJwNtvX`j#Y7p*1 zRo)T>mqSk7^@8ION>_uqJ^O9^5zK83nzp$3$&&8t*gb2}UDr~v0PhE)O`8~{nin1t zYJwP^q-hF9jDfQO;>jT;zN7v?eWetb2uB)EeEXVd&yej*Nx*HF)34@m!fu_J@HY-( z7SiIAbX>nZ?uL97mipC;taR`;m6Y5l)lhZQppivuvm}3FcAP4MTX@?_L1NT`o-Y%E z7vhMD*MlSTdtRmU1!Rr04|WnS^5a&Xfg7s!h0t3ik# zI4^+nfPy5ckz9#%WfmZKUHlq`5SQiCxah%N4&~SO_0jg}$w+!^nKr@Hmlzm{+JrPn zK$Yz8w1;sv7157VA-BwJ_Q{iq9SxN2hV@qiY$GuWqpEq1Gj3)$I-5M;yd3o%6HFaNdHCH5hO-i5n7>Z3szwcO2 zcqPEqh6b+rtw51+aVV6t{s9 zeOFT0UXsf=mr4I%x_||_d6@eWez70|`L@NOe2;*|#anYZO`-=d@e!jc<5Q43_aX`( zI_0tGN=eg#nR+nwGFg?Cid@PGXNpm;ZfCk}oQ2sw^B54z=SXZn>OW{)FOeea)H|w` zGBh==Diat4*{=EA$SI-FdPYf5;36&ic&Kc{Fe1L$5X51@&Nxym(63NK=NQV&qM|O)VU7ov{b^DY-8DIbW*jcd9+kQM96lbj0c+( zjP}U!9m{3nkyYXgVuj5PINvViVr~uf4ZE?bf8h*w@@?i3w$bs_-V}v0kJiFRG`x9| z1kAiDem|tO-FCaPdmC@6R8dhI`ks}vSr19+iiTP9Htj+^)iT=?c-4z(7-*Q;DgiTQ}#07Ne?B@`*s*| zRn-%+ndjYW%)qQs)Nh-rb*qlx1eHMg(fj7{`+4_OC@AnUrEp}4+mU)BrniS$zvIHPHA`6|JArBTn^d|JwBeCtOm{mAt! zPxrOaB4xx`pn9=vH-yl(!z?W=0iNUSw|AVJ;M?0s)+|*I7@{kPnPYHZASy#Gm>jQE z$(2TADe6tNge#)WwhgrHX+538mo328xkommo|O874-%DW`+)`$6=VfO5rb7u+0m8K=0m?#L~X zkCxmgRYUt;Tkbnr9Ij3*ED4d~;Km=(mV0px0VOSL`lW)QgkAsQUBVwGd#nkI>wNLH z7&)=-O1TPKB)Tb?g|lCdR^8Xbj1`Lag6QwVcT@J(&Ng?URm87zoKcc3p$(h(;Ac80 ztcZLB$=x3@xP~7+K(nd#Zk_5_0>h0e#{F3r_TdM22;9RTO*klBxo5?C1XTUqgD#T% z;Z#4kzZt*Sp*m*s^$v)pib;#Hlo5B5vxq^!H>=rp7l}(1v`b(zI=#V?(6wl}EJ7vk z`8Z5Qy3unIvIt}Iq=-YW=bomXUQJXCT&E4Dnr0JulRTmj=OxnnI$Vd}9%bwI z^&;%{LP@>Nh$OxbcyH1e%ymt!q{l;wiZeK*y>GBH#ts`fv*;UvTenh3i<$65Is&9B z(6q9cq*OyG#`R}wagYKJ_YKd$#|M&Xuykb_1+uCMg`>p$c4y6Ci(nAxA{Bz&Y=sg3 z@OD`#=7{c_W!S;&lj0)WVw=?B_D>%EB|SyByoY2Jt~OjY!9Mu8vX=pYD8 z&t7qj!kgEXU78Qt&Q{|PVs%0k5n<+vy{ROxJula`H*HCcxc4BR1;+FAV~@`SJ#SVM zfFNA_U3U_&QBbq;YvlOx(uFE?T3-F!3RR-?cR~^dTu4CIt=fH>}`J>x#Ll zFXaqWbozSB7zjuYwAi>IWpH>RDx#Q6m2oF;B)cl$k+zBhVhTPaQcH<4u#zOWx5FZRR~r{E6zbYZ7F2(WL+G@JX24EL za47Ecm{At3e=xpkaCcDbRdRkeXA^2n*i^b17izN-dnO$rJgV~BD?>Iw?~%Es z}<@IfSuA6DyNUD3Z3ph)Qly+j_I&1;nVJ8_^?wv-h@G?BE-xm zQ_nY3?P|3FR<60n-esp#yI zO`jH=T(wA6A=Av{JszOWrN<@jKObZR;lIk^N_3PYOB9^%6S*R#UOZywZ{#Ny&`s#X z205GzalabCb;Kn-mhOpDbkz!4wdT^euy)zc>yqVeQ>yC(c3~STs@*zPyzL;|`xuCu zv^!y{vV!`}0frcZ^#U(*Z+~YbuaCJ4v8vM@%SnnacU>}Vf4;+t>dX`1EO%0Ez`5=H z5W|s?n|=j(#of9LVW>p<#Uv?OmER!@+xrKr*+#{XT=OPRExj8Her^uYR&qo!iKTl1 zZ;EF)i4)Q&A+=l0k7dEML2!~+N4GSm9LR=&tQ8pAQ5MK_lv(LK@ZV#>uLvWxAg49f zC9)vPa}NjDgeF+#xSpb;bwo;oX&viy@}dayxWe;hPK9iD^XU$EXN$BQOX7wRN2HG{q7CJZ}eZb5fzQ4xV{ts-JT8AOIaTdSymD5DG^P7nb@iUC3hNw99A1p$$Hj3R_N%)}5T zrO22>nL~gu$AlqDfRKbF=fUpxI(@JAd^qPiU%NhVT|D8*vsmk1_gd@z{hxK8Pb}|S zW#CH!4kuN!a^B+hGP=I*XyN-1)6`K9h9GwR{ll4(w_p#`K!37yqqIrhXgF7}>yc3- z7U5=?N5rmV5Y?K!oR`X&N+j~jKX$J1oRb=}_^Mi?mAYFMk!b>rC~oqR=SrZ_q2;cBzT0s#&watke8G0ttuCBZsVJtT<9t)C{!{&NmK1r3Z7ML}GrDBZvS)s~rMi%i_?C0Me z>(Ip5zHQz)x_-Z6C4D8j|HeUP0_Y$pD)$1Y@2V~+`ao+xws7zUkf~|?3saDz+ds}* zT3TYs>(rM@zvx+kwY~+@X=S*EtrE7>{)@I9QwWQJ#$X3Ga7KC|y(7K0qWhVDYmb(( zb{7ttlU+%e`C|$4ya9dU9>{0ui#8Bw>C}#!VHQfKn>Onk8vF)G4v>ePAE(=~c1qf{ zc$vhO`C*yUs@S8_R>-&qBwXLQ=kO?&NuG9`n1p`^%1bJ1iS#E;j^#GDip5RTZ$Yi! z)BF}!yAZAP4uYaO66;n|^3o;j90NPD#YzCTo zJc}M^R_JTzWc=WU#Qhj9Z^B^WLTKSjU+1%A&rDLoUAAv%pfmgQzuMob+Ve{L47(?G zRK%VasDsg90U=gN0#rA;<5RFkiidx2Hwpe5!9> zV1A{{wtPX0wSi-a+db2h_?Pb43G(3s&3Fy}XIol+1G14i9|A`Ab_u`!PvBvnOUf>Q z$9*n8Wd2`VgaA^$0HaKMQm4cAO;!4(8J6gk;iRLs8s=JX!8vxdHWU|3Sl^)?0{g%J$7@Liir%mb>iuBs-pnCrXF0K<#lbU}r21aKR))m^377B|1iWI|MTt*U|>KG z?KpugJd2k8SZl*Q_xLY86@9=4m=E{uio)pWH*eVC9_9T|(0CFTYnTF>Cvj`Z6|(n& zp8%y>vuNquc3)Y>fiiLdVrhuqaWhKy8<5bcK~@ig!H8L4eW&VMmjw{e{GCAG(6OC@ zY&v-Pvpt*t*I3#WrIdFG)Mw|xtLKc5=K#&&g7i#@C4Jc}0;MEYq?-Ec1c#rkuM>GI zzgl~lZj<`CqQ15}rr>CkZCDDFr~_(Br-#XYC3*N7X71ZKFwOeq0 z`zuB>9CDizl|DaXv}0G)tr)i@y6qkg@jP{Ld1&t zVy<{`Yco!Vp*guh!H5nR^p0cF=V^&#G&E~uGDXn3o-Ag~8yjQq2-<+YykPL8lw>5iLi;&-~p2CJC69>3;#_KYL#RN zOZHlTApIBO{+Q{b&ChuMvWgM2WQ(=sg_O<2lev>vcl`SAgdTJ&-h))G7qn4gcQH2& z)w*6OUhBL{4?Z8^7n!h57OA-3MI_L5TRzo#f2yY}JeN&o3G+tQcYsn#67pxwgl6JV zUB#K?$&jF{TU~^?*%5NLWLQgj`CmXSKfd_})V`<8o>&^KszHH=aRP};wamH0ve@KR z25QgMiS>cno2;?&rQBMp&;o=|QtnxGYSFW?|I?FB=@st3?{`al^=tfwqD|7tKl)sc zoO9XRRaO1c`1WR$iOYK5=HW%CU@Usj^a-;?not=f`uxrsam5X0S<<3v{y_!=z zc%P2X(;WF8;TZJNvf=w$L&k`W;!~4!LSR5jje?Z)U@vorY6TxkM* zs%X4>v3jtmDmZwUBbkVtJ1-FAifYAMBbD@}8FB&wwe)I1jQRLBPFT2CfyIm7k$`9w zm~ch2)>pPn-8>4TBaxA(h1u9RjFJhwcOeG#{;`8bz2c0xjjGFCI=_=NKU4Og{n>DN zgtZ}W+wQhJPBI~)ai%G-3Eg&Qu0st4KrjmoxTQ;gYjgJSU^#C@E-o!CX^_Zkl9d52 zOFsNUuS`2D9gC-&R%Tk5N)w8i&$C)emfeX*j_R*|JeFRx*mhaND9HP*OVFj>QmjxK zXV9zW9MnC?4(eTcT-I-O^Y+DWk@cl{rFDMoHRed`hLROn&JB9eU;qHZ3Vbc1@9eGl7%8guP`! zy@OuJUPMQ9IiK9~Z@GT#yv)emJJfL@=tjD_mX-&L_4N0n!*GT=`tIx1;Sg2LydPb) zx=H4ltF*EQ%R^>!3;8~1W`@Uo_8+R{m6vhrl5&r0_XW%%QVG_BOasWsHG4u80&+zf zfEPr-=U*&1_>(VN@Gq(hD|(iCDU}o$pRL^uw#i6p>1_RuCNML&Q>hqMW0-mRM(WPNlwVedEsGrMf0L@bN#D{(To?kvVm)?v{*<&SBAA+ z?dF0PN*2G@_tW!-8XjxehxEssEhAkd@#7F0L>~B4iO%)4ugROdx<1}W##^~8E-W&T ze~9m7E}vSu-sdGNGRerzt}XFDpH}gqr>lK$U$OiGXC^Uh9{@xfrNS~HK3Pr0q35^e zxCR`bf6>AIzc=A%(AhuG?uu4wP}V7=wxK8 z=)BSu?l)leGk#|UCjQ9dQ1rdr=#26b_ql$B6hUHmKc()qPFauyYczIlKA~%g-_sP9 zb|Q;&k3=W6#!o>jH$M5Q`)A`r@vHB3=HxF-Gf|6mb%mY zMY&3EM(tl9$4lqblP{90!|aBc%@B%W1x@`x88AY_!JO#d9~lMo=5|=L zWYW%7c0)UG#z9m))C$#fq;lL+y39^p@Ic?~sYLc@>5ur~*nl}(TGJ9WvztrPxDOXw zv*RiWCycrF%;nnbng@2FdpMQ)6b0ANsJ^)U4PCRQq0C5g=Tg#$cGW3&+{R4b4Uf#M zbgc|XY1({JAmJHNwzV++i?q+`v_fuWf{s`~W@cP}sRIA-d`5Y(;Wk#W@n)Pen#mS4 z=^GbKY!)EO`WoC_QDbKzPc>WDaG~GUk<2D`)0W)WMgSF9v%raaqhkEt zMN>0{QW#gaH7AS4Wzff^2Ylz>#=2a!I42!+B{ec@EjJankArrG=R*xafC?ojFWGiK zg8t4KmaD9(a{z?&c(z_kAUevtyb>TH2u1*Fg}}85KltE34wsL;f?qV{ z%yi^T;VL8fYR_UqDYNZid;fduQ?uFx*1t&_nRwx{SYmi+wMDT-Yg%+Dnyb5G3m1G^ z_oxl>4%2a4lgU$peAc5>57W>I=j88}tUvPJaGvGIbG8a}kh`LYX28EgOQ(19GtqN4 zC-?Sc@6k+t6r*~HQvv3stE{%W(tKB6y|q8MS)`&1vi!V2fsQ78(S|QoV|wzQ|3b_& z^SY3B_w`!fDu+llYPVi{w8b_AjHOlX#vrt>U^ex+T*}^{uGO@mOq|#e#i}IvP4jGe z6TB_#}=G@%} z=CksboI4YHm2Fx~(D#G78&_0}mY?ZS#f>ePb+lo(BR=%9ftY`bh5R5H|D|{Ac4lse ziQx#D4OVI4={%qtwxkpBYwE0Dx`(LT>F6goE^Sp#kX*Z}84@Dra|oFVac656E#Xk| zLz+(JJ_SdxnoLw2PxoFO+LBEJ2Hn$4r3%$CT&Da8(wtw=BwI`55?emex3+LGzL#1% zan+NJ26P8!;Y6bR1URP2Mn_D%O@M9;Y%LL)_MLlMG8Th!GtD7)ocFWY&F5@jp+8R& zC=b-gOCzOYwnc7H}a_qO}2n%Hg)TIlS z@Oi@ob`DG)glVWtdt13P3VJOt&?4In{(9w+vxj@KggmqR$K~R|1T4;n@H65f0-8-4 ztMD+6xVaO3-+|aKdi>fJ-ij0TzIR+nzdxC>kg#xS9ChPRoR6b}e=$!k^&QN!<*vu5 z$AL{hd07s;AI<`2o56((3%3L8uyAyQd~xZL7s~F_vBG0s4RrtvKAH>ht>B&DyLx(~ z-LYd{c8SZmo^fob<%3+-N=W?y;r?C(5^0A*`A=j6T%b;lfc+X_^#ac(4R0`(-ktQx z_l(260ybewrja)#BWZXg533PepmE5DcYR*<*4eS#uYhGkcrYMHt#y+;?r70CQ%>0F zcK?zvtLIc12726~l>YQ}2Q*&AZ~S4*Twn5nAHo^la4IkPOCf(?F!-m*h_T{9g~$1Y zb;nkD%)Cs8fbwZzelSU3gO7?J7RYk*f9W>gkBr_!c8KUXK371ttqH@xJ=4m&8{_xR zr_l&mhIzpuSI;ecI4sNCy;`Y2W3@f%8*ljWikI=`%bQ10gRf_wy*}?`>F?y@UVADv zFst^3?r*q%EH3!cQ;EHLm5?L0Iy+t=w#$i z)kubgq0Z)Td?xL#zXfo{4rnR=%Ch){%0lRFxvrTv9v+mnUa%9#QLaJ0AKu%tJ`=f2 z>8;`M@M|ssgwDbF44xuYu{8v^ZNK%b%HiY?EuA z88MAsjYmhCC}bRBZy5~giGFV;`7k1^&V39?M4xcGuzSF)2m;Z*QaWv=iO?Kq znR#eWv@vk4SJQY`sXqZ#=M~?x$Ki-;Pr{%c+5E9a)g?|AnNh)8x#!^JMGOf-bhRlB z@q}|)>bi!}{U7*Jx1yRx(hWkZYH_ihLc(`(-H%+(t7+j8H$p;FhS`}6@^uaK zPlG@lkINlU{DNmF-na`>6Xh4=3!6@>o~5=N)ekVDq+ieK!n|~Fq^LUos5*3l7g0L< znl2PhX;J2FS~*!S6|3Wsn_G@^%|$w?>G3Pgip&r+JkZwtdb^zG<&~P{v~!|pRM#|K zV{|kxHkO>vDAb5+Tr25)s`06TN!ky$0P z^vm8Fa-qJ~1*~&Ee(9In3|_*u(Y{tOS3+SMuxFk}To27E%5)L(x{vLoKFeKIm|;tl9(E zM-=oC=%D=mVy)lwn!T8n%BoWA(lGP8d(mXLkOV{T458C!I<#0dg&7s07ltcuvtzlFLSx*%j;TGQ3r6+`0mwx+|+1;t%hWr=rgX70;G*(@+*l+WU3WbXA z=uWRZ#mk&vUa1ddJMXqV)aAw_@pcSr=~9j?>*a&-$wv`z$v(u5XU7sxbqU;_^aLZr zof#IP5B6|yHv;TlUKaeuzm3&g1ojjU%b`@g#Vaa4mS+oa%j5RMX7_-_L&o7#4IV`I z`a*7n!THigXA1WdW`2>=gy7^vI8BCk{Wh5T6C5;pY>3nt^wS>9EWohJeA12{A1t^d zo}lt$4lFdPWYzlhPCc>yIB&jDmn@WArujzRarT3*$9d!E2&!oBPg4NnmOQt&7J|*^ zM`g8~-!{rKf)Ql-5Yl)(iBVU9JuR}QS)%FT|4JnOq5hZO z;Yu}))}r>U^39s8Y_-l=6ux%St|Z{z!+2h7R7IA$epXHJ^wx}^^b~mg_q^-Ar4lt} zl?;|Nz&xi9ZxyPU2mBmbs*{ncGJ+0mMYA5<==L>2EX! z9(01uxC_~pOf|EKBrm~Y*Aara@o*EjShYgu+3VTp`6^sGd}D~>$FJ{*9D!!~qrr?V zYb0YDI}HC=45<}OpReJ5xIkSla`)?5H&gFzG#B;ZzVAIdRM_YjvL|aimsBX?Ze+)H zI#R)uaq-Rlb?7;d_>ge|aL8zx!BPIgyySMX84x#Ez%KYL)XI<6E-@QV!FpX~ygGBo2!Bt|#4Kt=FxfBmrE?QF z-szf^O}E%BRGA)M6-3K%%CNuv43z9_OtwMwMll60{UTcoW?HOfE z*+`^Zhe0pcV52xGWe>zT4v<8Ae%9a`8*G~=%#7R`&|&KB^Q;NzaTLB}XZJVVb{MWl zcF!C`p%nCV?rIsicOFF{g?u^r5ND@=5&5N`ScJ+K{`W`2z%1Pp5)b{AW{9(a*a06V zPNgobYG8^(CZ_W%tMBZ*`^VD>RR4QyVFT%;hNbnL=t19~q>UyO%U4BXqb*&%gijj zQ`32?k`9yiYOq!Z66a6^k3P{#<-8OfGVjU>haKO`Pk*S9BlAIDylNr-O_lobytvJh zaWXCRB10;Q6H3MPB^AV{BgD{v;mM8m$ock;SsQU-j%6(}feeI_`8_UfDSW5g7FmF^ zvquu*=q14=mbE$G0Y2w|WI@0k5gZO}(ir%z$WNl(PS>xewy1?d&YwC^d*EcA%h}_P zY!iB4clPxOTCOcUs+3zDFx1JJ5V4QK8@w|JIECfv1{0dSm{tehn#4InuR~AGR2}}f z%D5lCDHZdJY%)bMrp$k=#&jsOp2wzGxT-4yfwVIij+u4Fk3vG8PD+Dlnb;T8BDuC_ z>kUn~+P-mO<3mD_VAd59q}6=E@r1M;p$|a{6#bbR5fiNo`UK$yLb{;LUi7v&w+BRf zUNONM8%j!8snCfmY zEUcfJxjs>7cRXZ6b;vsl@+h&VH__&J=V8`UO%f-&fkDo9us)^RG+QecabUTDWU3!~ zt&)(0)-ol*zjh2<22*GH&8hzK_tdE@eN>05O%I$Cc_|^Bj8`2l`e5S{vc8mzNN+gN zkWU*m%f-bK)MZMXCwZQnF_*oEv(6VWduM~TzodkZRyc$S_Ke2XIzncy1~Q44F++ZmLU_sCiL>mc{mmPv88(QD=cQ z3Q!3P3k#!=4+FZHmKGeHM%{G6v^y0OfIf~F#9sz2j_DM{%+-<}UQ@ zFrsV55}$3?x+dNV=-(@JRHGZbd`dGL& zj2spDcJu40xWQfK)J@4XcdEsJLKG;byNbBvm#rx}#O4zRa)s;TZV+>o$PY)w(tXkE z)>U`^Pih^klLtOI&d@8T1Q9d82*Wsp!9KCK7Gv<~_4{C{$=34d!<6-fNbv_9k^;_P z{*H{m9Jjf(^`U4?B~f3x0v8S^nQ>d0@&N5a8(D|t?}ZN-E#Qs?pCp2;Yp_lW@9iV} zWcVj$n89CsR;on12%Z6{P1WanD$H}xId{2e1MA*7-l59YjA z!#P1)Ccb}ekEkfWEd8y$wxkf^>grljSt)3Scm5Cc$H|i?wdqq=Y*q|20rdyTAv=vX zP_#P=gHLq?sm|MhR6qVq^8;Bo-jL`^jg_S2stv6}qiPF;7a^ z4YAK0YK`DyYT{|Mpby~n6FAQr682{Fa;VFslx&Qe+XQ>8Nfq4+S=dFA)p+LDY#r=7 zp1EwOy>_IZ=cofp^vaMLh%ewV;t7^ffHxlyvkhal`!e=%GG-@5rQ^Zv@Ps@2EA!-Ump%>0~9)A3Js?{&UtbJ!iLOEdP5_}+{TO)XsX z1U%=vr3S%|=FdlOCCa|qdvoN-Hs5k@II8r^Je8X#rS_*|!>v z%dfdNj!6qjVdo`kL6`0*qVwd;Dd5mxO7lja&mDfh5fU>Ni@)L8-lnQeAsp9Myv>1N z?02e_TxO5a{k`1n)nsvsE)bY|B%LgdRfKyP0&l@@g^_aVq zGs?!#8!0|Obou$&_?K_tqIS_$JuJCAJd*WCe)*C1PSq=+zSTLy4Qo6=*Yik3?{&01 zV`zEL`=a$Nj3ELD!SZagQb>&)~mxN!J;Kg{LdHn8xA1S)s#lR zTraVAZ!fM(H-KHMlNSC<+k-m}0XrC0f~pc2 zw17FbP4_o8Hct68ozr(G+XGgB1SqOI4^<5iTdbfN&Ez=6NLc>_)#`r@Qa1b(n*072 zWK2C2qoNa8RTO*=fmjBA8O}So?)o-CEBkWtafmLEitjY-nG?v{Lb>JJfHj0yHb2ev zGksi%Ej1Cb!4+Ci$TFU%0wbLKEA9j}4ep9!rKaqdadB(l$7xFur2j~mb9cq@6k@RE55$INIk&p%BWQHiHQjfi;#QBZfEwNQ(RuKHJ}0l zpa5{nHRHb_cNZ5ItE|@mjb7i%{qIhAxexTJzTPx&guLARC8$aWoJi!?_4G(HCC^h2 z6of<)-iiV3NM%UVi;&3k+w^?51E3?J7%NXzcu}k+`6{5%%qzL8@Iy%j--3{1b=_UZ zKvla>XdypvT3fd%^no0Jdk4XHwgIu2XZ;_Ug}XqbrYX@;27nUb<4@mw=JOqiwJFxt!Sd_r<>(nvvS$6r9Njvt1TBTw|M^>#(X=X{ zhb}aZ%FfO<#%?U-Rd?ko{bwD{tN`jf_aa8y2oS!vs%f6RE8h}Rfiyk9O9-D!6xWki z&6g|kk|2%Fhz~8@Hp)xi4a&@Hn2if-3%NMTxO#bQS Gum20OlW+6@ literal 0 HcmV?d00001 diff --git a/Images/Modules.png b/Images/Modules.png new file mode 100644 index 0000000000000000000000000000000000000000..8eb65be85be108c6675ad4fb182456eaa5f892b4 GIT binary patch literal 70766 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 x(C?&^`Ff+$EEf4*4dAV#N+*G;tWlC4Hj&sm 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

FpfRbUMPRBu-|cBxs5} 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�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%0AX|c4jk@mDCO&BD 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 literal 0 HcmV?d00001 diff --git a/Images/README.md b/Images/README.md index 2e1acb23..94e8d960 100644 --- a/Images/README.md +++ b/Images/README.md @@ -2,8 +2,12 @@ Images ============= Contains any and all images used in the documentation. Not all images in here are used but no image used in the documentation shall be anywhere but here. -Here are some: +Here are some old pictures: ![Device info section of the GUI](pic2.jpg) ![OD section of the GUI](pic1.jpg) ![TX PDO Mapping section of the GUI](pic3.jpg) ![A specific PDO view in the GUI](pic4.jpg) +![New object dictionnary index](newod.png) +![Object dictionnary details](ODDetails.png) +![Object dictionnary details edition](ODDetailsEdit.png) +![Object dictionnary entries list](ODList.png) diff --git a/Images/RPDO.png b/Images/RPDO.png new file mode 100644 index 0000000000000000000000000000000000000000..0ee1b458c5bd32e85a514bb6f17459a2f4bfd753 GIT binary patch literal 214005 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%0DQ=#C`4Vh-zmM5_kJN9;=z!SF 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

j(0vA)!lO4$h!5aa$Te)6g z{_N*B@9&=IGuE#yZ@m`${6EdtNzEP7&YLMK84Cz6h!9*Q1RZL`16(;3a$mUj=+O02I1*kiQt46_Q?|_ zE6Iu;EwGCBpda`fr$&>v8DwJKRPV&hX`gBEJ)NdQYb!_1PZCAUTbh%AFMiQ*DII6~ z45+T&*ID})lauAwrBp&JSb(ep<0J`p;cgH)oY~k3(v*)Vkz!H0rl*d-$ zqHT`*lyvwaYe%0syXoCMMfPTO_DVN%-jwK6pQq9`t(+RE>FFbTvp}QD<1?zpTyUW; zQzjGyojya((pN>a^2UjD%l=m4CfcA&KFP7ZZ5{DGv$e@0vS|uJ-aR&RPc-P4@sw0} zSY_R*kx-bZW4HRmUhvUY~Sl)sExe5z4f~U-#qRR4@9kzD5&Jq zdc^KKUGUj_-Hj0SiHzM2iMT zxhYmuUUBA+gFZh@)ra9)mNdT0HAADPVl8}G%Qzp1czDx~?l!AGb{o~;qrxebji?#De=XpLIe>|nOH9nfT8Xx^6!GiK%19dR=E?)^k zMDlI=Xe_Ae16bXyp}~kIpod(kshl8@m8aVOnD}P8xmt-(vJhPK)YX;H)iT=iwy zV|AxiTh>`I&{Xuo(GB5S8r-y4W%^dAF0`qhl=K4=AVo z0J5WEDGx2xq3Cc?evuQzs}+)fI`RA* z8$w|bKexrJYRi3M^84t-q>8K@bo#qo;9cftO@Ojr)q0S^ZcEF)l@9VQ=mQ z2IY4TSJ8vC)Qpj<`}Na2x@SevW?nBeHEm(@ZI5II-YzV*kr}QlF?EZY*6oConq&%j zvZiS^&2AK!mW-p<4v(XXHXjD!lZljC7X5ejv|wS;W>t$=1G;kpeZuw=&Nq|4F&i42 zlOliAv--&N(&n@C(!ced{cM2|{l~`@jZruix^&8FX-n%dHZ->Zdn^RV)Adx4N_dHq z71$EgDimuGd#fNwZvjT&%-%;=^RE;$SPHLH!E z6MeMiMeA!HT#~S}lW*G2F#LRO-Qnj~u8$A+H8xNDZff4=4Kq$oaNLIDWijB^r~ByE ztTeIQ>a^_!@%QI4cTSDm-wlf@e37)}TYWyatL6oS6_Y)=>(-d{QPLcSh4V7GJKYWB8YG2)C*%~DVWBF(7RH=S)RJHzev(@6DP;PoK=QkF_+A$c#Dx4R3>iiTguOgc0y^~vDh9%`jP*Y_8nFs}+ zib|d^#-O{6xvo@ve=dTfNePK}>1dw1hn+@gbJp-NE!+P~wx7hyhNj31&Wo0Yg!0os znLQ8TdjN5D-ApO4+1YFQUeI9~gD&im-uLw5Vup{zw_MrNHOkk{TIe=T2ow4*mmC|`(*LTD^Iu0U~zGd zu9rR$@UuFCnBaPkCx|c|<^0$2}b*RQi1ip$0p~s0AN?vlf zRdulvS>nt2P^c<)Fpw=+ATc3?FBiCO`Jz^%+87~dq;l$oidve)Arny{zmt8b6U*Nn)V+T|G1qZ*0u37#;xUi0h`c(< znh9n95_;sTRORPOxfB-wxq2VsVrZ6Cn;iMqj{ad#IL0cjw#XHQb&NT0W&tSS+MU!2 zziI3o#j>PvDc<^QV8}6~oyHQAlw>9)|w2HVU}aXV~o~wtD>hEj9+{mzd&ziV5?2>F$^Np z?{;}b6(qhKu2D$;$RP4o#@hW%DU9~^Eh*oR{3kG_2W@>knQfl+XE~|`Em3HSyQko> z4o3~gkjQ=lLc8%_qRqHK;!v>eN_Kr+U2y+Yr64aWZQ`;B63SQ{mxaP|0$ zH=ePQ>`zig@}tortsciQa@k;3?;l(GiN+taj!)0u8VtQC`JPxdhO2RU=_@yRI#b6x z-Vqce7fhG?$Kbs@3WE$dWA>*C*%dH&o{lI48~8HzUTK~WWT!9OEx&BaO?C9X2)4eO zQt}_?LNb+s9yzpYvhgvt?^ZQrc`pi4OOoX4_qlf_2g3(dmxb-=YCGU;+lDVhALt8B zwVvLgt@*~~>RPb#Tl3EuEXr!bIS`I_HVkT7hKUMyuO$HQmQPWOnFSR0Z!6*RuNpJ7> z&qy+!@U8rqPpr8-ANnnf>Is!52rl-EbFH9^kJq!-dVbXgFGy_$fbjUvmTUoft%!zT z9DMEow2IbHB9LVD2J%#@XT)mJi$w%a2#QGC&xvOXCSCGPg0&@|V7@;)6LhC_{3!n5*qBG0kVc!_w1D!P*Lpof%>rO*S0B4mw{+ z_rh`Dd24vfDga#aDaOvuO_govIA_CpGX4@A>ci!J%=n1w9wU0F&@Sk`%5C}j;cB16|ueA3tDW+7_ z>&l#*pZ)#)MtxbFhm0+GosS5!mV$~3mQ(}R`)XI8A;db_)zbR*?b|2X?JHt>JlG~G zmSbf=X+;GlxAVEP;*Wb#Ssu#NU%xxMj}{S*CcjcrMv@{nMNPfFyZ;LEZs4%I&RHMN zKmibOvtDwr?Z8G{wbzc7VXvsfZoohkQW&i7uIb@-&K43Hq9Js+Rz8!7! zr>a_hi2K_<|4!NGb)#nf_@W&Sqe=PxLdfx4a;AO-&$LK+W%+K^uFkfGhU4PU!3tig zef(ACjk%;{$c9i;>{D22$xuhI9J1twNKGIRd8rt4d^_Pw^WHtW7|57frfyCd=!8YG zQ)bZ#R^o{Ob6C9&l2SBEJrTbvn;bn(ssWC%fb#&-Wa&x{;txq~{48Pf&(FrBb9%C! z;v^FmctxQqrKlR`vl~n-O`q^LH;_J-ttvd=sQjQ~GoJrSSLaT(T(SL0V3us_JCJt) zB>(Lgf2^#vTNblowRd*xkTxp=Cy&tW!mVle%SvNV!KtH^KjGn_VD@z{XTF0(l?0~I zB4{81Pg@Co;QJAD7tv~#8|m_;b@iaFvSr?%o_YL$%_!>P;`z3b?I8R1$9{cteo~fA zHs)_bA4V?vUTqm7afefRmROP;Yfs>0T6EF$5JUb61!TT9V@w-oUO)@415EJurRNs`;o<_2?Cm~%{=*qk_DbTg^C%(tH(0T4 zD*xyBtG%7LqzEtvCIz+d)`-fbl)qoN(H^Ok_~0pq7N3?%4>ot4Y?xXgw-rOWtYR zl~`|9nPF!Z1_?Jd4o+8@c5UE`+dx@GqtEj{O2U`8)S;Lr>j53&QrXi5P$J$;Z+=R} zLPix={yD5sdv0AP>|B6;LtTCS+s@wTNYoDJFJq>PMF6ell#GnW5+CgnC|&d!bz ze^TLZ2_^pf=-KV$6$g=<*WU*It@q|%$g^1Yt= zzi0=y<~IIK=ZkxXi$7`O^CfphhZ%NSj`e>_6E;PQxYOr1V}L#jfrNxa*HvCR^kXhy zCE5nzdvNbr*!Jm@@G&aFy5RNUk5YurcPja{BV|i&cG#iiMtpocLQhxba$GdLRuTa; zS}HOGgxop822O4BN@}9Lim;xXHAYwQ%6vEc$g!58m45t*jFLC7BO%<6|2>@|41w8P zhB&AIlO0M9&o+z<(?wki4N(a>%-(x?da9&R2`8fdYX<a^a=lsXg6=FV4Qo}-UY;aA};nuAb>W+A6yz7fN+99 zjO>5?gkOgL&kOvoYlwRZg8% z_Vc?Zzauwqs}ZT=FT7vX)Mysch;rBmjv;QBlMVfUS^LaBbz4x;FN(LVNY_P5e)@;S z-^vTCY(o;3JCZL&EJDmJkAeTeT3J$sTA?>I3!%Ga?9)=yQL~1Y#C~IAp(o4pXnnN;Y%#Qt-px17FY435c(eF; zr?x&NEv&!yWvmE9rzEpoYZkVs;X?QhPq}?Gj_OJ&SvaP2SvEp>`=|Cc3RmK8 zFel`)U^t9noDi5bk=HW%U@TsGg_k!hoHwk;Z~wM7RVRDJhK9OdJQqyPp^_TCbX~x9JCxV4#MKOyC%zoFK)ZlGd)Q_5FO5Rcsd#duih9eGCv;hL z;n}d%KQ}}-lpitkcm=MW;s>TK)fKF*znGhwYcb(pTwEZwJE^tw{loG9#s7eCabAyP zjtOOA>!TD0m#|6%z6^g7BM@t4>%J0d<*oE=H_&4txQ91&^LXoCBF zrvG;|5bJHJ1ke=G#Jw+|k#b)6OK6a0g!WuE@0-+VZwH&`Ru!=!<>t*|jf>h{%JJIy z&<&3HOaD`oPRdEUG-6hVUZ6qk$DtRN`u)DA(xH(0ybH5H>hku~t8nJbIrAtZ50 zn4{QNq;Ix&e>f-=ljmAI@0ubNu5Lu|QuX=-jL%PN<8x<==@ZX4*@j;BMU`Zm0If z|JjYxo)MDP3YGG030fQZ!PZb5TFGK>@y%Kas3z4BUFdF#264@@KKXL0OX#1Ii8l3` z$-6qmeR^7>Jylvj^&%I(Yp%RE6`~UeUN<{FdFRJn8KG}Oc6-o9v1`0`!|$MTGVKza z(ME=UG2jkbBlakxOAzrD$U>}jT(K!Hrhy>yhGa-I3;7ADWr3#Gn>huA-GK#c`->W5 zQ|8)noo320T};LjB-ou3xP>lV6?*BdZ-=2U$pX$8I~G%WmOY!ATu2u(W0{tEvj zs+FCc;LSwA4w^m>!T&pf4gZO9IlR1l>%>cdQSGb@&Yn4)J)5&9FXPilV8Ygz=@)jl zYN!yG_(hNdQ=a=HW}80EAtX+Yc39ADv^k)uW4*L62!-fqEq;`I*>EH6QykXAm)r(6 zuBwJ$eD@za0Rqj#Vk#A?;};Ihx)R*X|;AZ`%z}FMXg9SOJch@SuNu; z^mh=VOMJH*D!IyJWv-AJM_jL9S^msJ2y!Y!w3iPQCEtpa?fBKR_%0i+otlX$5VBX} zvy1?ooraXj4d(t(hqWhZ%a0Hn723IzBx?wO&}*ITbL09>H6W(bgGZvpw&zBT->QWo zku9~X7AF2&LJr`&4g{wuM1%Fb3zf0Tz;OyA*Bl71dp_iSp_%rc<9Fv0-kzY-a}})} zvuzv#0pcgl?Bq-bV=V_>-#i~XZ8f6hxp8$-*Ng~u=Xb-m4a$W(2i*G^I3L;*y3-Jd zJG4TQn@gLJpA%deTNkfd5F0YwlQsCh;_yU^_~|2@`tCf&IU22)b8%Xg`1JR1Ogw%0 zrm6?4n2#QPQOrN39_r}xGkm)T=iINQbmn!5elz!XN8@NvA#t1NWN?<&DHE0j9S?#^ zeQrEHf4OxYoKRimNsPD7F+?X_*fEPkJyzb0Jd~6?-#%hP)zmyk&J<}Vy{mgyd`@!q zv4yu7QPkgl@{8CI_e7^@tg9;5&O8l-Uv3?<#b*Ik{8XXokl}`UE{5o#+=fxvl?HwT zJ#}bMx{k+ffMIgqgkA!+q*i)dIS|_zZ5Ilny__<@m!ua<8yI+w<%Q%JI&f-YMVsi@ zl3|tEtuHVuj0o(R9BMQ2^unbwKU|pHoiq`iM5yjF2}M7(W*n8@s8kdlXs8z|%5Uxr za$}Mg@5b3q*LPzAG1T@8?$9*Gh6(<_^!^P_;9vdQ*WDV8RrXbj42AYUcxJzHO#hC9 zUHK=ryoRc};xx}0x*C&_tGN9fD_(OgvF9!Sq50NA|dqrzax`CdArXXF=_tfPG@@ z&mLQ@Df3kfcf#gnmEgylp7v2D7U$X-(@%md8T&YXrKNgIQ&X75$I4R#GjEIU=aV}# zGf8*pvKBTszNbdyENDm;^C_O{!ddpZSC5Sio1@6?e?DlJ$72+eFtSSYm6r+T!`f?; z^%ZRF0>?~^gu{kz#3d8db)a&!zwF;78aS$94b;>>nenns$%=&iY?|`IDu@Dxzj%=w z29VJj)Tne5WtmWZ;e39R5|@4(6MalEbjO=~Elc95kqn5!YAEVzbmP3#_-0$xT`$D= z?sMhs)L;DmtuD78>V^By@pm$C1!hP6f-ovgs~WI@{-#MQ%aWS*<4*=D@`dd_3W~9C zGqk4}*Qe`|)gET1gaW%~ z2LF2gP4*$P7W*$CbyYwl3Z7l@R+Qh0ZghCO|N2t2XdCVnOxT)PHDpda)7=` zVH~{-vp=Pb!&E&(<5fSLL(|^iapx>mNhTzg_ey9J+FyJ>u3|5A{Md-80aY>HylM$z zzeC^md%yBZ&)!c*&8+R9aqdItf(eb3eWi?};{bc5s+8{N;Z@0TBo{70$z<5Llx}U* zjQT5^Sdj@~v6kG$QLxY`)12WK$q;}LargCDP3k@fr)wk!(*XkmR9Xindt?*qTQZ~S zRQjm7+o;r9k)3(YP}cXmf48_3z_g{K#?P%wm`%{7mAq+GUYI=1Zx$v1`S}RYnwj6gZ37ipdl@Gp;Mg7gC#cmPumAB6w?i(rBj0 z{DIK9sfu9@Yq{e&({njC96Ni>(T53VvJso5vaKSmJ-m`<4ft&+DcU|hP_R`nMR@o% zJ{?BQB-DO*%p&!K0Z<>=wH%hq@50tVk}74xUyc@|mPmw~|tV;k^H z>10xxSzOp?tFG3{aP_kbBV^f*)s5@{rU8LCJ2x#Vn5uAs3R9)`2ZJodllxA%@$KwP z+J~bjFadc~>Yll^3a_yr5UguI;gTpGjd5?peb9y-o|JHG1SqWX=W^|dkgx3^^cvW40rIkz1Y(g&<{V1g8KU|pg0@(=`l2x67075L9OqC z6HB^pj=9Tz4$`1a+#dq!w?PJk16Ztz>;9~`x5fH6dTe?tlA z4xm=EE{@Z6tqZXeY6mTb&ai(MMC$i&PK43X8qn3s)B=1v8q( zRIV=x-!|wZui|!~3_@!O<>^=eHnZ=f?uwJ=GF$#d1DA6$I9rQ7Y3yZDK;AOFUj#i^ zg?&yzNcGvkjPAI&D2<0z;xTob2Y-Biy3P#T0ZqX4^Wk2wj!(l?Pj5e+a2cDC3Ve6? z6+SG6ULSk^$Gz)i$G4d8`?>D$idjtEq@XE8D!f!k7>) z?g}y+Y7v9&ZHJ0M#X(0KZEJ=J;8J3qp}lU9T=IYwM1-1kRLOa7A-BaE&7?Zenn#+{8NcXqqUM}TfHWv z|J&ii$8%x{)Rr9@(K)Vo_gr%yc8)xnWe^+$W|db=V=jJ}DGe8up1`9+lA)^9&wfd^ z7B;zIogE8*yo$184T8BKGk?sdHisOqzH985C|ErbM1f|O(mk9ZiHnr%dM2@39mbMW zI(mX|VTH?#wCv-^fRiPKq^%|5uK zE@#t@K2C$&SECOek1NT1W)jK6?pmCAMFSv6BHM1E$3or|aQP+_2MWda)w$~X!5B9V z*{;4;U}CX_MQFx4ZM4y8s5Kxa@XC?k^x$|_g|V|7i3>>c?1@jR*)k6e1RV(M>s!7^ ziaZp7-rcLvd)JWp0EYTtSS>mOGKSx?M)DOQ?PT(pyxQ$$OieK#o>fOO1$>U|P)4bR z31;o=%=7`g?<8ELNX4_9B(6{{{Axk`Ad&fjk_8i^_2Q3NkFtdfaU7n9Eq8Hcd5^{E z?i$n1RsKw%8&pdl(DB#oq_q>-jU0BIXeiUx$Wvt=_&D7TAM84;!7h(_w&% z!C=H?vL71rl>AJ;&2!oCD&y|-g)1aT!1ZNb-#4E1zbaVoZgj@ATaq~jU4NQA|{w1!FK|CgVJZn6{I(!?z^bpBBw4Rx zQO_{Ykp+9yEDxMmi0DFA?8>hb$Sg5u<1&4PZ%!b)*^Vhr*Dl9BLg{);kg2K1ro}~% zm!KafUPZB%rLX4`n4&cY=05UwkY|GeVUo{}7DTl>Tq+5~0}2exKFsR=OvUNyK!Bw= zo=B?hsF(!XRky3(%G%(cvFr_^>Cis@rrTl8)efP=f<{DBr=0V$9nUXP@b*>lwWm)K zSI9=(tl@*Fbp^2YxGI|t6jzvs;iERx-9PJ7dyS&{f`{dU)Svm)6T44Lpo<(gRj?qer+7MfDXONuvsf!IP-Yw>da(d zM^+2GGV48yVpK(B|3iYj%#oBf0#x18H7$BlpHWvP99_8KR^c&5HvR%@W1N5UyALG) z@hL)O6jnFLPQ1lz_UQa*fmv@Vu)m!&HTFPuB$?ZT(Ip%LL_ z{jf#&*C4_S;WbxU12Hi%r>do6ME7BQaqYD6dU-Q-t9LGCQd2#%|T zn8@*niQM*m|0<`|&h?EzojoZ3c@}GnMBhNrkHWhYNxTmn-WUMs5-R`~wbx7y1~3Us zJ?O|(*zFvzj50Cbem|JTlm2OxIELA(qftC$(R$CL|Ky-{$Yg!t*18&L;TUHO?3-%N zWz3D7xmU12x-pWfwP95M=p_LTd@^llY3FQ!&l_T;5#dt_34?Wfrn5A(xPr#x8fWB` zbp!B4x=^d$acQZi-Y^R-z5Xv>%TLBaTMAR)5@ry4a=lmc8HVaERCUJlg$W*=Yo(^y z_PUk%iSB+bmxRvdDmV`qr=2m-i3Y_Fr31hAZ;Fd zNVnE>HLE?!Z$#6BO~<<@^*qFskL3=K+fK_(z}Gk_-`%FRQQoj9%!mBBUoSPaQ$DXO zQ+u!uTg37Pr#6Iq;(3GOW@rByrP#04UGY(Gn%6(cYtcmKDF^{NM=MgF9**Q( z$mH>B1}~x0EU7c7;aHctR~IzJ2myt`OS^(H|HKVIvoc4I8s`UP8iDZyqVV#j~{c0a=w zfvEW8@Mew~C3a{)k`ZJJ~7P7 zH{9E+ykIDC#?*V`O0;ba%4j$TCNF=q*vM#maO#7Y1L#*A}zzgc_8ZnGG9Y+b_~ zN7J$&14(-@t(G(z4{lM7TJFk7uq%?pi~**mXN&&nGpbUYar%{I#%}oYU17~?kU+Pz zXnurR_j?|2+A_45#cYWY19nU&N&9xbeNM)=DWb`$7JSOtt-Zl-)?2rY8?wTwvNwB5iQyI;bVEen!DLF&mM$k=lUy z=rSJH-HP`eSVu?6G3x?)+}dEmp9yFCke5jAZX>-tBd6@9DDJ=e1%7W(vM3&|T7C)<<=1MZUV0z5vvLc$DS46~w;#KPE+ zj`GOw=4uXw$?}<);HM-%1kPsd?6PG=;zBZ_7w>3l70sXG)z){$e(6WjYWw;P>48uD z(*C0}gJ1HbjgGd5nth1Q+O{vV{%+$GZfKvKv5y}OpGPsoy;if6cQVm}Lg5wC^JjpV zniqE%QJ^mwq)f>kN`UZ#IZwNIb5>%TJuEGE*78YxyTA&FkwoB#UdRUmBibld1Y|cB zN6S3DN%{^nAD}Hl)&=F}6pSwbDSc3i^6HEy`|lIm425a(a!t@%Kj8nN?5(2OYQMGb zwiIZKl~UXa6ew=Rtu5{??(V@|5-9FaN^vXh8Z<$Q26xxu5~N7*z?VMH-v7PFH{SQ) z%|S*ENLX1}Yu@mlMDd2wpJg!Y@Xu1#cyau z&_HoD)h4GAp{Qb)<3~~wQD9UnGCN`MBEGZ{H=C#H#CJ{hMa{uQNys}hir z(|w)OFA<@FBrvnkG!+OU$ZLA1l=&58=rJ7{pYXCj?)2_pVWw~0*6G}plczWQC~_pp z)at{J_!TicVOApU4YqTYx-mv+EoF44S>L(W_{wc${wBGZ@%?LxN~hJ8-4YrWdi-!i zb@SY^>)dDhGeP`2`SD@HgoqSvmSo0-K848N18&q?IEKvnmeNH!%@vKw#H$r%055^& zd3?o~_r@9~T|UoztBYd>bU6UDhf67hBj`+;m3`P&cC4)IF6il~x$)^@v)aqzu!(Y# zwj>+V4{4cPqa_$Ows(?v^4rvwoyZtqJIQ99S;alO3T zAKbXCzO^R7kGH(p2W1vw)ZdFS@Uo*wq-*EfCtlMwtTdWiGGV$60}^x);Us3Iefe!7 z6%syZDmG!5+cHg=Lznwa)c_u0)h zD{yS_BmFeK#%eoXWBF=|FYyQ8iF||>TUU6F>uviwtF0py^0N}jbyr?9=VGsQ;&!ij zu&cd4OD`>>Ui$R;*b?KZn(D?nVtBajB7zn+e&30ZKemq@%M z(pZ5zF{pC_nf-Y8^~VrcoQ6q9wx;O{nZC7j{c2`H{22CpW#>f$5n|7MymMUR>gm`* z@Jmh=rT?^;TUg7#^^C=a8BKID*Do(hxVpoOqd*m(2>~1F^K000wayBTSk4&Ypg3@I_p)?@0=By&5I@o?|LmZV z=gPM&z9~}L&;2Et*je(@5=Dt8muGeWDY2w$0Auuh$rt?x4Uj%~>e~nh!NQ#T&xlpW zQ)AY%1V1SbDr7^}N|ctRBzJRZD3q_ECg(_zeJ*+vFLoyxHbV~kx~^+zs5!b};RC5; zvfVn_iYfQdZFVS3JBFs(weUt>1r4(<%@3sYp=OK|bey2L*~52$+$Q#sVL0>3NL;4h zlylhxG9I$W&mLseo;4h0M%#oX{l~sq&W>c zOf)H0Nr?yZBbZ>lt$y(#cI{#G=nlG5I8%9xx;2~KXTR8NZ({me5^w5eawFmNvGNO-jp~6Y%>`P*aVtC}F@3}+TM-|s|0;DrSm^pmtn%5%TwpU-l zs4>Wy0B^1ee3Rj_xYdxMo?0KeWTUL%b>S&U?_v`xN}&1;K_^?1LXw~_+=T32UYs7OIf=DH;8o7Q~O{2j%hn7$PoQ1o-VMb}l6Ag5RI zON)`7*cg(8E*&_YZ@ed!i+mq%b5YYc5w&Q^Fm3V{F-NR*D8kO65tC)?p949b0U|@p zyhx7tsNE6v6xKKmZgayv63EGYjwik^d@FT^&1J~@W5piqVLl?W6RJFhA8 zL#M>J=Go38pLHFbIsaTBKN#g6vzU7n1G)c12~cQ?XnC99KuMgpD5C@pqeSei)5`SF z^aKyX^V(JvuAd_qnTO|N%<0LTDed!Erx9|Y(__J@=FrD_*3p%JDk`1TW)83}BD|ve zC4Hjh<8a+Y0_lW?i3=~lLYj0NDAjaW`Gjj(-1-Z=XBp^<40kwGrGfBg zSoV5F&L}jHz|!(_QsQDSsrPM-ykVu`>;w78@5(OtkEOKs|eV{&&d*@*u6F8SIUWP z>UWAB1f&L33gXfdB+pMYeNY*&x=nN8{9qPCpKQZ7yXRd*)(`8A{Z%tMv&%y2O<&i7 zMPd{Z$@fPs6Zv%2^%WE?F+A+TgbWScv2l}2?LQBSX+*WGC%ot~e@`KvbTd}$(!X)h zP}Dz`ykwAw*)hg!FDcZCfN}&2Y6!Zpj=CjZ;=C<$Bg%W_1>$Tk>G#P>81OxuYyMQQ zmNigjEasBZr+E!8jx>@>k5sF>?mjQC;}{*JN!(Qq&(6IScEs}qF2=$cMoKBdzg&BM zXc@TNx6&>Wq3cfF6Bs3NDg}h4X^MALa=Uvw@{Mz>Naiwc3|nor++4d&|B_v~x0T*a zerXlfCT?qgSjw}wf$|+14aFf3G)f&x<7K&W^mI!I7IPl~o~9;~aJjui!#u~iu<~li z7!h6GTO7K>)U38q5J*^QiFtltzE(x_1trNMHa-kJ-k&9+IXk81hEMeC3ysN1T)W)A zzqiRf$_QOF=!)MWe-{@{zY}`f`2BP; z>YewgJ1%d%F(rsitqKyd2!n%9l~-oqN)cVTM%s60;$F_K=qu%{ri??I>nv3p0cE%7 z8?<7nA3hii*3~^t*PQlOFp5|=ha78UvY#ir31x<#r5`0UR#wJtZkoIMo;}x%E<_u>MoqN;^)t=ynvZ%i$S8lBW*J~ zr6?rsq{iI5#|at!&hOjaI={+vb#=dr1q!%E^;LZSf`$4hRU6gE#Hg^xTR#PG8WDDtjCI#;)R(ciawN4Xm zE7u~O?SG8=$1xsh%U_hmIUjzbJGfs|Yq{v8vaM=O!Xf~r=z4;ooEaZZ%^hy%r?I09 zht>E+RJ<>YT^#xtEyttocBsiY_1|Z<5gQDIW`=&BvD2_-QKLx|8C?pITr`%P5-IS;bZ9Tyr)!tArkN#<)`ycUmob^ zxmzIjIraPS=Y`DCILc{I zU>8^H`B2W%pDnEZx-bH&1eNT^taBDDeXB*Li?Z2+dY=-KfLIhcJUACFqNo96<2F( z1je7x!oN5uDpTvxl2StY&DfQGp6wMYX8XDOHRgNhcr+O9&MS;cg?%lK9 zSXhVvv5?Tu%F4=KW6s}B0@d2A9nM7)f0r!^@&CiJrEgLZ)(lPmAMA6pSEtGHv-y7_ zf;|orW&eqQ&sUqE;p5}~S40@HyFAsHUmmA)Oca&d321h zyoC3Tv)mkN#FW63mHu`b*5uKL@9}V`v)xvgFat0AzHZYw2mFR%Bvv9}<+7NGlv9IW zjn=p?b*oQ07~WoZYMW9%>#8)~@0J6aeUkS5(Zl%a*;8v9n+{7b`ooNkZ1_mICVcSacoH{iut>mM8N? zBaS8QOkwr4R#YivT5S#EtvX`7hx5m069qtmMP(q7U@^mz=+-r|UhICF!IfyRGj-I1 zBl{wmUJ2Gn-gd3@ccCq~J`ZsWaONe}&BnS#g9&F<>n5gtQ%4 z%}cP9s2r#qC9087<*_`!1nyUA-d2oPl^Nqa~IJyI~6aka_E6Zy*}-WrLJ& z@6}QBJ4O<-lYZ0{EI^3512QwS34a}Oh$3&(#A}_5=wgCgK`F38{QUh^+PjzYQB;$Ik#&tDrnzN6R@OdvTsb9B*&)Qef{j9T^k zT7>mI9J0@s_0W&LOYy2O$Zc-}6+H`b>`47dZePb5J$#RCE-qcjVoscY;#1;C^FOU(FmXSSAfS!Nx;!K4(5aeM#C z!&7IKOu_u%^^xEDt^R?1hrwsb$LtvuVP5cpYjZ;%I{qa$-h{y8v_0ZS6De+RHf+to z%1r1v!EsQgu;*zI_1*7i%vMw-dsY5VsQX`saAGtZE@=M@bSu~&u05E>_Isv2yS~i( zl3IKNpoXH|_bqI%&_*kn^6Ny$BGN9ZT~~~nC5DCR1Rh4Okl?Dbm9$1LuNlWwz1D!D zdk_BA+y3M0o+Z$4*N;6wD(GeU((8-|%gR&)NtA6`2_9Rm9>m5ROiJ*$^Ue=w&;Tjl z=9;hBjJEP>N0R8HAIupl=$+su*=K){uflc#PjknD*2zPe=(CrW-raO3sjB9*M`9`6 zklZngu_wd-uit5PyIPJts&W^ zu@`+RjpDHl4Gq8bR3Sz&M+g6lxEHl%E^u3ASkXb@M8Y0U-8L}mn71Q-`&aK1kBnCf zrC4=aH}XtC`=*7q!h@O>X44R*1GdWCg>RCjUD5qN*+2XI3*6V=&ed3mMkQ5Q&8{GS z+z>>>K4a{3Av+Guu$)@}4bHh#M|UPYtKAs=vMQ3fUTX%U;(h;$h&rUoMqDa0R!>Vp zNn3;niY8NC0t88E_q16Ezbo4M)jP&rK3@dwA%$u?1u{%qu_iny6Pzf+w?E{X4 zRkj|y)36a03haBPP~DL>ibw2VMY_0SpW90zrvRd+w*)ULCk&LPb12KTtD|vB zf%BDvsX@Hz%|mYsq>VMG1No)`;yf2#;#lXQ;-ua|NZn4bxE)Vd5d&`mYPq|iG?@Dz+b?paK2 zY!-5$9GzpVB2=k-fGqKn-!qLK7GM~;`=NT8e@3(Cu}qk29W z8XEptJ=*mJe}#xF*Sa&7Fh#s&=*GOA5z#{_F)D{w?z&ap7SC+LnVh+i<#I(>%Q9{< zsD+ke*{JM(LREZ~k7NYdlYiv;r3gBD;SFgEW3%iUT(piIrUk7#-B3p<^Azausp-#z zdM^=1yO&!XWv`m()yIdgd7sDd;?F~}dfZ#XBf#IMH9HDDaq)d8r?I2OeqGEGpRU}> za4M3?w0FzqibCgfsO2Q=#2QBxEgxLNcF$sjn{RGx6py#^o89Q+?!DL(TW`KkaYPw5 zSX$3_q$dWYj0p#1T*X4a#tKv!Ka2}8BbC$-=TTm-TCSWRR*Aw`6V+9x&NN)`dIVdr zN~+@V$5ivDj_C;RpAn!avHXRZ^sA3SyD-BQzg3wPDev?Ch@I}doXZZ~$Vm7}Y*TCv z)607!Z9eRG4jcpX%5{ z)fy0pkannsy87ScwNXr*@E3cUC#Y{iD{H+duC;f6>$s+dJD@n&5W6q(=-MQ&F*TQ$ zKCISNX57ml1;<@;I_ln`F)<8*Z7&|35Y z(Csy{|JB{(cfMawnaJgm9Tm_77cf(9swN?Rv-38A$gykbP)u;R`mww7w!Qf>)FzaP`advkY(x}sFhcig5MZjhHrZ>&P&hPpo6|fE2 z)QX%)Z-F{7QCI5076=t|?pM+e8e(a=^7w<^qI{PF$MZ2L~UHU=*n$y*;KXR%8*Y^7*+xvCJJiq&u zcQ5a+95Z!Y3GiT;_>vC>-W0&5RF(LQ=b2j$lnKbwP8!}$kAp2#mE=Q@i_i)H{@{$@qu~l_vE4pQiZB{F84f=Yow-yW;fl(}^ zqF#+<0do{sRymx8ekOD|_cUiz%Iq4SxuLzE;K8sH&Z0{)hHu5&ln!_|-}db?8;Rqu z#lIevM3GNJn^<@EaZ_^F3spaRJM*clxjKnLliRy5{i@Lyo9@jKDkw!7oU7^ceTnky zTPs7aJt>sYS}M+>ZA7|2YPkUU_$jtlIMv=Q-QT+UZ#gCUH{nWEf0V8M_@JWD3Hebz zZb24mN9$by*Zwo}LepV>=pqxK(`t(|csZp?o-mqnr(L_G0b}_Zb2|@pp~p(9FxzRv zDWAN|SyT{smGp7sD+T+2gJ_LQlC3Uo#ad5tGWc*zxxvnGxYT`7+jB06(F|J)TWc*A zl(mSzgI=x;MRlEKzz&B*d{m_U2=S&^7LEgj7i@Lz8jmSHo3s+z`Fc{1T#1>-9V&&M zy-~~jy_jiP&;vr*9soL)MGz<{2i=ec01ZGQB zJp_+C-iO7&FKWRxpvuZjOYL@of$cwjCPX7>%C#?6t&~XxMz>pitts)u^&^Ezh~1-S z{D1W}%8ZG3Dyv^KUSEjEQa5HRL%ut%oU`2DWRW%ANbrf>Xeb8wT)ZX>ODbZ2Hz@zk z^T@Jm4QV&;F5;|C%?2adrV|$AdcRHJl&IQ%D0kF+MYPhmJWvjETbiog7v;MbjQ6T{ zj1A6pvHS$v{VRrNv?AnA_CVref%lfd{n2sd{8yH__~;336$QlO7fZrAko#xTyoV99 zTXs36cmFC03j6Q9>$d6%=uaQ{m3!;$xS_1+mb~g_xXhF6d!L=a)p4q`HJKR4eH^d2 z@FGS4AaUkiI6~+sdO^g|M%{yObTse3xwsSE*#Te4>snMh(u1H_^KWMzdckn#`?kkv zpXQ4J{pVCjLcg4(M%ucTc|2e`Ip)62&BxgfmB=0f5wN7nq{WG7DQjDp(Y-TY96J9< z2-uI@^{6?8Jlm)vl9r?@$V0Vdor`G1H$H@JWqTNJrfjQaMBERElR)r^2h~N=0H0N~ z|A88K2@gR4Fy5m(KmU9P}!1=FanjNEQgXE1lm)l z54laB*Nguo&72ab@&I$5Z+z%=h0lW9%&u+^m&9tcIQt?nxVqXf;fCJd;OCA(PUvkjNYw}u+0W(Y zuJ)xZs{)GaKjV7`$LN7BZz8Y z=%8+8XTQ0|gk>UebhBhpLpEq94OGvPN$`$-p0q{@@{@x z84RSGiK=SAn5|SAA{UPKa+ezCsHFzo;H{tPRM^dFC{L%wELV9V+OoQ4vbxBOJ<08K zx=PEK#B-!jEH*%D<5d-+?amJyw?sFMwGJ?#lX!N zRvv0ORFBwIAEVky6kv$%7;ogbk7O3r#34MGpNZ^;8}I&9(Pf#Cy>7#4xt$^xXhXc? zHxv$G0)29xbRKDojF6Zl`N^(0ic3wUMQ(3T1w7<<$RG^e6`;T$Hzy`i+d|~1*=)p1 z2xQ`z1Gf~OmcmaOg%H}dWo7eiG|@G-&{yl5C2d#0XId7W`EbV`ozIGENy{BA5BMWQ zB8f6{N%4WA>`AXPRW@8Bj{ONysxR37_L{}fJ)T5Q@!l3^BEQ{8uBk);GS2!r9v%6@t# z!|aWNxz6Dfu@J*&-NYIcNGo6%)c?|7ufHJc@{yIDu32g7H27C>839ai* z6eAcXn*xW^qvnh#th2>w17*uf(vJ?YNrv|gdA+F1wxiT9pDNkFewOu}o z2?~q%9Dj;IG6ixncdTr)5t0$p9$vqkEr#kHUWsYD=cB{6)JSr2|2Qu`A7jhktz}?l z-bWRV8I$%ns0QFj!_lB7P1^@D1>8x?3$x?QkJ0iM7>I{f%(okOj;70}jXHOIAd%Xp za0%Z1PdPsPP|cQMkV<7iaZk+Rt2nxWkHG3w9fO3KNN|4u6YHz=ocIMgOisiogODy# z^Fh#*V3+@WfI%3Gfa>S5VISndg4&$f+zo?4gondbtD!C4>z61?Yi|00ckWE)4c%N` z=FBpB^4g*gq}!sm&r~Wa3VII1zH6{%Jg~>LfTL^)8z76-N~Y zGfmV&dF3l z68%^#Fjb?WfZh$~hKrG$WJooy4KWOsp z)ot=2S+-<0rH<=kBd>ifYY7N*8fp-nVKXfQ61LakI2AiN#6-2Fk{sHOa{+3-$3^W| zym+ntvRl)9l(OM*!^SlP;+qVi(#5C6e=| z3O%pp@-vS%-*exe9>U}^rEjUS2FLna_rJ39eXj@kWfGgV$8u7OR<`(ncz@gGA`&RUx$Fsvt^GFD?%t4}quZVuzFPvRc3 z$+E2SY)H_mT7D>Se7?*vvBaL~P;9q(KfiXXeUWTb?0w#1do_C7;*V-1ML~)(g(9El zp&eYqs+y0j#BH)K9}G83G!QAQg4iTqMvi(OHjm@VoB`xDjM2t3moVeyOZF<{k^jQZ zL$=Y`1~ESv+9Fu@J5HkA++YYYJ1yi_v2i2pcU#o+12?s26Traf@a^bWYZ)F2OW@w( zb4WGsXuqYWdgd^zGW|z}sQ!ZP@_Si|_m^XWqaKxHzkW&nd0+#Ew~f?)Epmp|HV)m< z*-gb8NLNWop+F5~jryLcWP8j0Gr&6mmv4b=i*r{;3?4Hm&q=fn=2cv=#;5@{taseq zX39gf)9Zx=HL=~h?>Z%rBPqi~w3J-xyzjrLX-y9M;80Xl9CDQ_EKg;y+<(pPz0u7r zx6HLWG_u^sdL`pVp~OyHUmx=Nc%gfpc-FP4AmuP>rq%{wh|AZw_Qix8f&7do18BLtz5Ym=|+@`8_%d*XWZxbe|Zr-Z^Zadcx`p#C*%?4TUDP zi>iMqUNMeswlKyxW8rHFJ+6>xWswzm4=P1^KIcag8?A5asEj@Hh*i8F-^%{lkflFM zxQN&*&1>#gayG_B^U(=EY9Oy;*jH$%z37>5X}{;Z#nn>vHYbM8a#$QG49@9HOM@eK zI_j~!Z%dL>TV1Hb6qt*bS_2Eth|hXEm({QI->XkgPM}oh>f?P9XG+s_Ptaql5fxgg zmp7QK^E%QR8fffB=;#V7rt_U!+@gS zM5F#O#D*zdcRfNep1NVYiBl`hiqyxJm*fg_HJ9(E4Q7D#6Q66+-5pzhv2e8hOsfAe zEi4aJxy8t1o~@NtsiYn9{oz8mN~MwHTDSfN8cVhPt3!T3tb1zQ}2)5W~9LZGoOb=P(VZ%{Yzm180G5BNPVq8-vMiE_9{ z%~`hJ2nGW+7)Ok5;{CWmMbVbOeo4}%vy_yVf01}9$Wv)GK)*qfmcKLUolh)LmC@fr zjAQoM9GoUIS{4eiOj|tYF1)llcTXVw_EI^YDPqNpV?CFg-O@BSp>Uz}!W%$V>{xGH zv%`InBzLaFYhrCfO-wbOE!PN&iIORdx3jj+ZkG=MIE`-~F5&6RWWadb%pLfb+qJnC zxk>#F-?}7B36Z(!r`uR7nRL&#cTLr_?k$hgCUfcAFTAa6HhGeOAzgN>Ct9_FNyJ@b z1f$n7>dRlrKBvh-^+37)wpm7{;-?%bc#a@ZHNrDB{)-}p*VWNoiOB1{R<%7!!dOVg zXP{RGf?~NnVXLZ5Y4{JTYA^0vMuEd924#b2gPuClNz!T{)u89-Mu_LKBqR0)d1Lg4 z%dftrdaV8c95$JT>Up8i?%<~r36pZNvgUQ}1OVJAwP~OW&H!Tp%Lu0PNvrr;Z&X5r z?(NHV|KG`Xt|OKW6kmvIMg8RSquM1WeCpSDX4LfcgBt69fVSiFd*aNOILS%TVqKj4 zu||~0=Q7iyi&T1L;+jVzz-@uKfln?a&p&xL|3YVe<42Dk&gCROs$;t~ zPE>CZT8g8Vj{7bn=Lc#-(~<#&%q~IhTdo6$FloKJSbF1;m7azc2eKGwSQmQza7F2V zgFL=kJ~lKzss$CrU$CV_GbqD@!d>vbT!{1{6}ATFN6&uq8kX0Sr{0baadgk;oGsuo zrt&|06VCF=g87|U9QEn_RT_)l)Y!&ieL78xLstb!Nv7mxX2r zh!y8Pn;2~3Yd@13B39zK!KLb(^&9(@?Ql;hjES8)Ymq=olIFu)nPxlCP|?HhK=M4o zdH;0yqrT}A@4O`u>E|h2D_wu8=MjB*4m0uOo7OY?BImh+2gQ zzg(x`)oc=iRaT`F&^W1J6rPsJY5)qB2*H$%txcdHSf(llqtyOEXP!Wdsdv34CR4@7 zXJs(0YR321Ph%>sE+}$_CRaQilF7)eOZZeRn={7q%DYi6fw4gDvoP0o5-uj4%uRWY}DJ{xG`xhAQpVzfEH=fM5L`-9aj!566msBQ{w*ErzK_01#l z!*6^Eq-vs@`Fo9gixTcc#MuMCucF%n!5Y1Fvu;U8`L zU|1HK%s5(TQ5Q7O5PB|o^_C4;jHj}EH24#zV7gvS8%q)8N_?V_^|813L{Z~}r_?Ng z?@Y6>&??Kr=XEXsEfqNbS=zv1t7eveVqN4q1|M0fK&IyR=iP(Xo{gWUl8CUM2Pqy~ zrK!J`)ZCgp88duLr`I~}%ig)8$jyGc_wHgcR~slcVb^t3!2M_sR+%TG4X!AAqOf%~ zZnTw*>bvyZ#Mmue;Za?U?EUDO@0MgtC|{iuObnot%@ztuwK3L8FCUata3hm4u<)Z9 z!2mqf_h3;w$zxv|yVC~kWC8cjf zhGZ;NpO~0nu&$Y0iBP%0-Rl0)e3TxZLw4XX35g58V1>kyH_S;O-RpHn?4USq)ADNX(63Jq0(*`^b z%l2vgFbFURi(AS2ISEAx#VJ>RV}BB;mZJYQZj`8!+3w{oc%q^1GM5}HDi*klsz~!D zbY?!gfC-vBMv)?oIq^Z%{mCXIY?|f$bfh9j+zwE&RExz1wG}}$_|weq%C!Z!5)za$ zfOFYQWeow1*s!v5|2yDBY8vcSgvFh^{2*g`5HwHfSMZmv-f9Z{N*=b1Ao(F%p+jhnik6X_o< z4E_Iz(CjJyXS;jd?%U4JdW*4~B28%nVZ-6hBSXaMV?Oq(UIR0_syH00!N=RJyEG5E zq|vg~6D>}OX+g%+9Y5^MLE~R$LJ?LIS0~YZZZGZa{WBcv=44Q zL^Upc#GtOoR&|f2o|>*u(d0W>p<=()2Tfo#=^R1I zy4>)7*EtierWita<<5y1Dtr-OWG_>(5c{c>5?`CrZ@ndb&i|K$8aQpmC#AH@qI`w# zdj>03Cgg`0kIzFl{Y!vgFt{|h>*i6|daZ>o?QkV_E%$&2QqdD8qKy7vGl3k zgmx)0(P4q~2Cid{QMJ^mxO0=PKGBtEsafvYJ}2IUCJ+_?fNVn6A1u^T8iAwk4J=V% z^|Sfwq;d*r2R)_vHD>n_KtbU?XS$Z7nUgY6jTOpB>7PdP-zR53;g|({nzl!;Fu7Uj z1KX6yy>CK@z1BjCbTpGbsLLCj(kje1Z{loI4H;k2^Sk!^d^XqmEjfwuXX&uQWRCrT za7!F-NQj;P4!R*oF3dkbP=UX;pf^&~On{#usm2ol6}jwmZK<~-_hnN{6?zx3xkR&E z&L3A3#O;F%9|M_X&`D$E$C&zjkNVYNA#&DfXXx#U3oyvr%TD+NJmcdl*BzV)HCX~K zHm1DRknZ2!YH2J8wj|^mv!A1wSdf3mQk8FUs&#c^ApSdx8W~QF9_D-1VPLewlAu@2 z%CYflt?;w?$cJB8N3;zbKFN*Qv$vPthCmQ*6_uRD=VOY{%&}Qnep;74Ilgb!6{h0> z*e>6rCHEkn0NQa)_k#t#>W-P@XEJqZMWTI-X7obtZ@M_30l+hl2LC?{9OAQCNvN$a zLc^5ytjq$Ox|COP1H+aRl6by5BWo4&wl`;0wNCb=2*E~9p+)5u(Yii|y58 zs{@*o*1o{*MLa>~{CO_4o_ttX;YG+%a@Bf103R|kl9UUApEJ*Od;gMGR~16C?& z&0hVkpBJf`m_3+9)$7vypekyKhaoS>fuZcqVBJS%qZP@Av`lqDK*>}dlC5s~*aQKn zIDKnjXxi)LDNG2GgXNJ!twpyu(s&f`(v>zUye<@13 zsG1X=q@&nWZb|Fdlatgu%>57}xI*s4fhh(c~W&;GO@6m|bDvMe> zSsYnS+-{PIn@m4{LWSM^N=)PFGRd9k}sff>)#2u9il=Ym7nRIfhQ8E89P7{!ELzQ6L^5V;S$gPmu91d-pfl5Wwk$9zjqLVEk!As{p?ugi@!V zzMglk8|5?QRsDQza(recboChKaC~p_J1Y=PQcCK3rgtPqVtI)cPFY%LgI+EbW=nGldC6i4(6+qhEeb_@cPuO zt1|RibZak{yR|sO=F!fu;F;G(y~Pgbh_W|kg-b%h}c5~cj+yxy*08e^IP*Ka+DJ(N-+7ef)8Id#$! z`$KLNWt`}sFGp)H`5=O)gYfk4(UqPD^H#+}nj zWfed}b&JnawW1xa7Duvv=aX|%bJHyXm6MLJs4HW8!I)T)%3GvoO2$u9%i=scD|7@K zpDIV&SHCaDVkS#(dD-z5&R%&O>G$5bTO4p+Y^0e;56o)0Eno_9Fnky0jD&Pnu==fe zuNc;3ZIR<(w<8DjedeEGXd8HC@E+*s%b#yPKR-&Bk3?M6EZI;E{~XUt<)TGTqzfFx z0_dt}=<oRDoT=;iB zADr+0stb$s$E%W4Hy(tA4Aa7l?CCV|ILEm3A5n6(;2WdR0Ujxe;y7B5Ury4>2Qog2 zIOP6kZ(PN%zFrT`*6vvg9AWtn1@Yt1@>EJ~H43FI()KmeW~kCBwdb{ zof>AdczjOh3ti)19!SPOwE*4Ka7$d(16y&@b0PwJ%^8ZXw&;ay*ynmi5CENeXTdTp zH=)aXgoUDf!a#D_oO*RCF91=OX}3t;zq$I5no7JmCeBxPVCF{ZY?=|%0VIv3KX~IP zenoPoX=m=ZjZn;Ve%^>J-gT<;?EE@UvtSZK)oOE+g)xAnlS}VaAN7XS#!{o#CBjpu z@Kkg0hi~)o0P6%rk!Q@i?rX(WYHtyk5#hf4|3OJ~X1398SJJj_chr^<*gZ zWg2y-r>B4X`0@G6myiESi__B!d<+LGX zJ(-yJp33d4Z>@-TCk7P5V{hcRQoDp(^O12r1$v1(0DGN=81ilodv*|O7vvguO2OC5 zwh-dD<8Hsb&S*=;{XmYZX;Y_W<_z%_h5QfDfNHnOp zsiPG5VY~TtmY+?q_Z^ox5dARK449jcCb1Z*MT&8YVkT`=cgoDXbrbQKgS-}j!6mK< zaxo%VZlCt%^PZH}8eCS`kL`_@3?vy-sh^()Udvv_mz|}vFHRrKD1&;l)mH$pQ9>X4 z<$Py)ZQK&z?nOvROXWsUgT#&k$nV*3UOk7(mSE6B_f<*7IMS*yOtkr68WM5Ve?4K{ zk=t-`@M9EZsWVC~lzB7dEqA%KQgVDTveQ9us%Z^*nX7kmFWauan1Dd-<(qV2po9fd zcmbM!F+9w<8?nuPD?`)nv5(jkW68U_yJJ&4onVygFEEnbzuHxubm!Ln`0+7{`Z5_z`bSBrVpQWV z8v0N5a!34MI@yxh9_ZB$HWH0V@hK@+B|vA^Hj?vXZ->V8&dyJ&YH9_jX&C2T<)SCr zBdY(t_3!)FT_yMv_AXGiql^7-B(#DY=;ezDXvFLx-*v>zXNQ%soFPIJ(f6G4h7_ni ztZsfC%KzlQG39Km86JeGJ4r!<60%nM5Oo&dr(HSO?3eWhuV2d3 zttY+m(M+QA`rU;M|Ko~D0}u#QoiPD=41ZrdTb91|8fE#6{usGcrOaW7veZyUfSu(y zQ0I*v^k3@U{~qW+8rlB{o$Kl9#%dhwMT*e~O(LuIYf+OmAs04Uj{ri4dmLW}2L=Ln zAhBUbpE4B1@n*Nw_4W0ukBvZw^r(@RaPY_fmO1|~!vEkK3Y-wz)qlJ+?pF9R^REx> z0l4_lj75U7{|!1JQ(kw;u3L#--PmY{`)cSP0rG#&UUo6{0LQ_>@e-kW_3G6pGqL@cW-M6+1y?IbRuAV%#k4jr=x=i;= z6Rz_X6fz|`8>v<6H19*?z}|tPncWBYQv{haGp;5Dq?beO^X+CClEj+79oq7#+%9Dg zH1H-LnjV)Xr*tVgH2)O$wu#SSGUTN|B_HJ0(WCUPH`*A&3q=%@`qCRK1$Xu%9%Op% z{i9Q zp)mFN^Q9LJc&YtbMOnGg)t5iSO9fl1zpb0nHD?Zn&va2NG$aXDRpjX-&-a|ik$XJr zPaN88A92}ImSv}m-t<1DFf0615z%^1LBr@M!$zo(T;sB4`Kc)DXEc5?r{w^8bo5Hu zK#ZWBy`221P8Xq#ZlgUNLe>6jBq(*+}szV(&+Ot0DQK}sw)&n zQc{u=6_|dvFLR|2U)?><0&dewV^enjdJKw)jm1?GbuDsL@x0;Vc?hsdJ#%?HLSALu z6j{j5_x&c$V(d>1w%m(h4`p?=%F32h_=J^dBZjNAkY@43vEH@@GK-%Epf9POpfDMhL81 z(c!jsb{)7UnX&pG)n>EzWD;h7MfN!wP#FYD-6D4SADZ`nCI_QEm)&O_Y3a7O+EHag z;e|Xq@>?z)SJu)0N7Y$Iwb4dvyDddpidAqaQYh|jEl{kuL-63i9fGvQy|}x(2A85K z?hZkMyIYViJ?A|?zO}MuWkn{FnP;Bav-h>{yH^VUAo1y-XlX+Pje%cd<9_%c<7y^p zA?IdAuLlW@Ki8-(Dv12DPl z-PHct4#-z{|3ppD8@Jg@I09Nm5xFQ<7_Xu)OTg$&j%@ z2rhg*R@$?+dNowr+P3(`wL^D8bzN*Rn}YCQBYmZ{|HzXB4~T>aWutJEjY?hZ zjCaE@Jt}iVZmK%uOl+pqJg9guvQ>)xG`m+3X4o$QVlbr1#_+= zH*F?w%8;DhKcLICKVVUN;L43h*(S7$@WZ$`@!NH4hRw0&53N2cFVZx1zaC2nR(GP; zFxXAoZUq2627}EJRLF)N)mFImC+0#5BAF1rU$fG5@p#mT=)(hg-}kkMcu3h(Rm$A| z61wrDIAsPS6W40V9UYPQZj9wt!ttMm8z1oR4ETQVK_cCJ&$;ZF<|VU*e|>!jdRKYY z!mfpn6f8GA0AI?(e9Y(tsdCwiH=Cx;%KA&J_tRx-d~+FiAA3_IaUgs5vVijD6Tz~9 zb;*fSZfDHnHH#nNL? zgQs$SF#AqYr_@zRD@DRxjze1;?Trg+8K6CeENG8kr?L`9q#Q&+iM*I2nSX|E+3(-! z85uF#-BS}2XW^KQcQ7Vgq-UvHOiGNjv6xqt@uoF@I=FdKbL4Roy|_ft=%Ui6bC#8O zFz*ydv_$8(akSq!8p9DfQ@K8jSb=)X=Wmdg^#*E-E3<+<1j1_YLOz@eC!w@BTkyjKlIeEkaJkIuraAC z=hnK(IIm8=YA?<*xetT;iOX+a-DF^!qedV^S8){Y`a6!G_wsh`9lKF&3d?d0 z>x0bBduk5{!K)+tjat5r;Xd6|L6{x4j7MNKMR2&((;Zm> zdD`%~Vn;VgY1C?0P`@qZ_Fc#Men+v#qm!tc{IOy$HEV5cQ+!{>h~1?pnV8pGh4nz) z&JWi`&X-H?h90-mFJK*sUDK)j8^v_1OgT0O2DfVz&dmstj%HIP`r{$9Zw`!7i(+BO zxjCvg2&%1UbNU>qr3I}7c-y#>F!C$ues5FtrQhk%Hu$Ri^*MN2Nl8gg+r{a`YxkN* z#U(2#C6vQOQTe?W$mh5n<-K|-TZTqTX=yP-ao)&c&v-ZbXC|ay{Vg0Btm#O#=@g90 z1Dwd>5m8EuTH?EF;-qT(Lhg~<<=fWK6M9v+X z3_Q$(qHVuj$D~^#@7w@%_?g?We@k^6+ay{AZsI(|HHB}own`LphbW8QJm;Kz6a`;D zSJHG5wZ9+qJZQVdkon>7f6xZkXSdNSFQ2i3L})B7SOFGw9ss2?C6FV+>tJo-+H0EB zH!o;jVt|j4cSSfinF#lne`%g`!LO?e*OonC-rE_1KGzw!dsu@cCq}Wf?2q+}YKKt* zXmz{1UZfA`kyP;7-i;}uo%Dr2?+8YVh0Y$kbxlj4NuFtH+;W8^{ePncgdjpK9;+Mh z*>RK0`A9o4-6}0)R1iEp5I?i`T?ykSwt~B5uEKoOl7r(prJOv-!%!WAlI085EqeRb ztitv|C*8!!iWQr<+PL)7W@b$yH^D#Uc( z{h?rm?KsnSvl@D&4xi%UtlWlO<2Ziw6$Pw-qh=|da4;Dg&Q=Wc2M-?5Ck^X3_5UExCM4GPq3ggw5v=6(sHj%kjC3kT$bX34jzO7S8%D}>wM>#1q zAgbkEdj>fJug2Wm9!3a8VIxoKW#+wK!{Z&Hq7OhC^3{8rIxPA63M_QB#d9{@dTXB6 zkdZSmiTb0w%Jr-l^2A1qwe&^#D<1TmDcAEGKYz0No?Er~S)N4>oqV52LtM!aDR%+M zukI5ZXOp4qrq)_MKj(5%tztVf8^7{T!A?eXXDZTrj{??mN8!ourKG#0=RAJY)Vv;f zpHVS1HZY3zEGa(&E#{&uiyNnDfD=A++=wLDx+WQLRig# zN8A4b&hC(mq1k1tKEzUXaPOvs&BW@Rze4%MkGB)~rPONxFVO4U3vE#;AW zP|#{9I&O{nuhF@y-eMTl(oW-j+|Kk0T~h08*~LqHfj!OL>j;nD-4z){b-7C-N6 zt~_tM)y@?Zy_Nu$U-BMTbn5ZItjm^C2hmP#X39mPWJsk)Q8E6K# z8^VL-=d25Y4)Ym&xeaUu<(VD&9=d0A=`5I8GRMlU2D_GN$Rc}8D8%m#1+4`m8fvPQ zUGmB|3CH>ds54H2*(y#w!`w7T;YAwT7fAx4a{|T$?2$$&6VymskimXy=DIGZFUGYN{N>ptN*9s)fR9>O zcKy$sA^Ur88~eCNwgB91wSm)zbB|jnXXEJ}(NNOq%Tez*Ie8^tS_9#fOLQDnt?`-g zZ|dJDgK#R$FQ#L6Db&Qza)zz-bKxa!iD$Pl`AiSj_Um4yS{-`nm~}j3CVV}!w>}bj z2ylYW1;g>OXxcriW{u!r^lHn|I;@a<743Tb{ysp_aLwI?z*7WCUhklh$EK6@)CVhC@=w)xjl0dTI$okZX#;^oX9Eh-JDiUbeg4(sKWhDi z>l4}|AU<`@*pXA*Tqy`&p$E_MvDw*77ya1$$)olx2>MFVnVB8PuT5`}k#}KO2OXV` zSY9B_&->K5K6l4&nzUHaY_lsjZUgdGgzp)&c4RTUdiRaI)#9Ad;Z9&8h#o5t4PwL8 z4Hh3}uNlzk2Su9QKjU3O3#V)5kD94ricF^;SV#sEMpIX;6F3#X+x9z#z()@Hk0u|s zFO{Bl>$tx5Qeww>Os*4ljXnR_D2Z)ue`$-f)&6`i5pInRzJ4YqHL@Ofp*K=z@W5K!`&uQkA1YLMP7Y&&p&9mAz8R~HM=WKEDdaY*P0hb(c;CB&&8pLK?M zlh%+7GjUrd5W9L!+SVV*(#?)wZjaF~UEf3zYSm`AJbC{z*Y}9Z-{m2cYnO;1la(8K zmg9}!wC=-N;-ZRs<_6Y%VH`qMxw$VHj|NYTkTrlv<<+OoQAUH~zA`rX8jk8Ge2}LZ^p};&mb$?<6=c zN&t;(TY$#R1cz`!La`r;xSc@BckP$YKJ;$J6+aDtE=dJMV)pxj@Qe%;zDjZc-Zj*? z49_w>Y=PQgbs^JW6}~j>l7!M_;?s|m1segKiVu^f*3DFYsiqEIbbiAiH)^jkX zJl^q}yrBkmVVrX`kW8Vt&h6e4@mZ1P(#aWjK~#x|M1NF;bEHuR;fYFaier();(k?| zdG071u`_tqf7Ex45l$}lOCXbin4n0cKZ4?aQ)d+tj$|Jz>?0e|vCKA@-5koD(1LiF z4c97EN|vP@j+y;lIja$DZtYI>x>^eKgYc`3HOVS~@DLKBpP3#@n|%R)zQz)Xdc1%W zztyfe0Va^U^ay&=AdOIhQd8Eu7_n^>?9$Sm`Q{q1cCiA}#NQKtrQq_{!nsWK=;5G| zR`ecrsL!u&c<#nSej^dFR)X$3GF*MdH$!eb8ko<7aHW>{wl{lB8pgY8$t2vm>3PLwqrloA8*Buyo}H0FVAD5k|?InPfzQVx-ukB<$b zTSJk8Z&L(UR?^wtalC;>Iu@a&3_Z^?bADv+QRoOjKhBg0uf?Y09xOM zy1%0p3sw0%#B0R6XG^ZyjeM+MpsJA$Z!~tk0&f%2F8hk|hGSCaafj6{mulb7&svXO zP#&c0hLiEetYuRt-%g?@JGs137Ey4&34A+YS2U1VDSOoT-b^J$Pb%U`sbJYx_!Y}q zc%}o1+faJ~AkYT#6FOv!)=;y#>TNMcC7a!rWC@x;k%*Csws^<`w=d!QWg0!N3Xo!eaeEC54 zkOU%)suE@PYbz|rNwKu$NV<-$nNX4aURqqvnbE$o&a$LNw(lS7YH%l^KR{n@`A2E? z2iO5EnVa@v3spPPu9U!)zrCO3vu93z@lP~w)cj2b?zwd><)RV<$Jr2$uO*JzPXA&< zf=w!pea}vBRSWdprgi0&5VGh@K+q~4$O+Goa<>?v7CQUOtjkIJR+NsFR6NKbwj1vZ zGfYM#M$SR`xs;xrkwj5*f@OJbdv@}I21tkGd+}#YsCwy_`xn1LaHd$~>Zltj{BpW6 zFfWwQt>_NK#6zl!JDXv_*=~0rz7P}vgkhgTB;AxIS&Oic!)2J^Z<}W*V#4+svpGpY zNbOgMir!+~nA&pNG2TXH1*TA*HtK(8g2~%w_?j;P0Ks!WLqs}Efjc>6>bHiot3F>- zj|0@t_2AZ%eK8EHakxE{k6RvaGV7ns5H+-1ifla+zY2Ve-Y--zk*&j=(RtVDDgarc z)zMivIsiSTq=fU$%^O!vraQD@UtO7}&-N|38n29{q}ET)Pfji6r~u|vz#-+u#drV` z5TxxF#vws}gxk#NTC80R9$v`PjnS45^{DVMk^YLMWkK&;FpTXPD=V+iP`cGsoa?)$ z$R%$C{bxpr<0(1qJ-o=ggzDX>J)>EL&7q(O#S;jHYM3>wsGhAzKvtD#d zD*IJ4i9YAg$4pXYb1-Ik%_qp+R>q)KZk$uCeuz_|U&B>5CPUL*fc?oRh+XO#jV)gj_FCi$R({Sp z209L@uzb@s72grs5n>eDdc6kqx<93Gw{QjMdFgBoG)8)gvqdWS+#p;>1_568bLzS) z%@G~Kx1^XVpwAr6q$@K+Pg#Sf^1&JQAsJnD2>n%fgTWenpBUNUV*|S}W)>XOncDp# ztnSf&pmjzLIM=NrxkWa8?S+-L=_Vk>*}AaM3kfT3Wl-ilw5l6F0|ErE&@Hb6TRbYtt{N$=z zuy54@;g`y5%TPvY3`s8L%9J4Q_3GEOSN*o3d>4gQU$9^PG8@g5>LKF)JQ zP;!4;j9cE~46vLXGP$GSO|V-L_nQea5`-EG1;R!LOL?n}M#--ZZj*2xok*ysiz=84 zG>nVBn{+NBtBq&xgq)6@o!a~4Qu>ESZOumM7XQi!E0mb-y|co0Foc^uKBlmCARIq| zuF6bcs%~thmB-tSy`1(#@UqM+#l;7;(=B9o{*c+XYvq4$ zet38}In8e*zDuwL)sxCxe;}LA%Pg2nO}BX(qZ<55`BFg5NKfypOtPuFTT%1xXi;O0 zZbvzEjjPrr&;uU9fr)R5FjCa{=2k1P0W-B{b$9mc8l+NOVUYtHbMSKVwUS5PW8k)l zZRZT!Pz%|&F$4W%KeO2UQHt+dhi1_EjowA&c8dp*rwca?haF|qOo+KqJcqA0*chVco>KnlF8UOeBGxs7 zefXuTY+^Vj@(hu`K8X+j3B`SGO}TuXMFtp ztA;C(N{iY7M`CPp6OX^?OP85ZTCL5(c7xiGE2oSHW$H&POHvNIDTNZoqLNCgPYiJ% zH3?eZKDPGYzvVWwp6jh9zR3jWQxqAx>he(aPg*=Uus*~ly>(| zW}c*Gu7zX{8+yfIdGu~BXi+wIl1Z6^g}krN*Pife>Drz-DGv@B&xS_vv(aZ{eL0?- z<<}s8i9^~uEZP=w@7pod+)Yn99hf=$n5_zzV%wy}dDFCbvlE~IjdD`q4wA=EwQY(2 zbLV(9k`A@vzUb2bQ7K{26u?X2>6db2^rqeF1-p7Y;q@Ufb75tO5>zTyG7!q&SS{L4 z?#j1?oD^-bMR#v#djbR;{acZ;`A%plYDA(v6VjzAN16Bo!$m7rT>9@Q_&#aEpLj-FWeS+<4C-MSf>_2DOhLp$%yI z>UY8Pm%icl0D$df?v8=mSuTlL%69tWs?+@~=zRQ%^w;Sb4vp=Gs|cdo+UM*V=a!9q zh2yAYYV!EMB6Fk4+)y&-_Av{~#8l=ENqxd>_1^w|bxlnd3grF!I&KKP zpf<$p6S~R(yW~@Fs%>y#W(P?IRw3Y+i#F;_?_&Sy(7ETX{SK@^z<00V5A4J20Fowl zt2H?!cD04cL|-$@wbJ5OPB0(nW&Xupesk1r_xd@12Kb8?eKbH;fXT~_aH4b%U$&Q z6M`SaQ?gd7S;g@!O2m-#dWj=h%Qpz==~d3kC%3oYQRdu~-eRU`x>clgmwf)gOkv~` zfL|?_8p@KiOZmatoA(u>ST#8GygOec3Mi=YJH_)yIl80tclxfr`H0oz$q=_e)2BrA zqDu@qlL>pYW-GjXT~}Y9jBZ+qcQYwNHM0a&`iORrW{u-4drVo7)Aa#}XmT_$p_PV1 zWu{8tQ_#cokv~EQ$iy!xIU#vPb7(%9ZS1IW?r=yU-cy7pu`l=j_%V)*Klxw?ls7OC zghzSQICEsAKH*Sr0~@M95u8^-YTX&5;%Sb4oT*IM6Atru9A?#Ou%Q57?^VD0Zn(2S z*;DHMCD^I9PjZ@0z??dnWY&qsloh~ZXM9-jK!fkec?xZC82*j>BHfB!BxM9ejy0?EBbHIsSC}pTZ)~>JU9t*3e zz`3O)Xx0{}sZWgHEjKO~cua~C#wPa{+$#12(#zySWdwfzy>dyNYdqw`q688-!KcHC zNc}t1iSAm`>hxByaY?ws&ziYQ_zJc-v8KT`?8k--k4=8*5 z?ulT$U59@w87fyZwL*oKOK}=@IZL9==B%6}8GzxOb*;DP^_9GdO_0?3XzS3Ae^eDKwi=Ad`KO;rJa&lfsNlBq$lLn_RCo8r>K%C|1Kl2{?U!vWt@53Yf z#E*r87t%q^N43g{E*UqM`-&HJ>goHa`VQ!xvpl_&#Rz45_4zm?q-iWdf zVdA(PZV{~qDN3iMu>SP-`RVVTVGBqXI^Ip#j%>*#ff-pX=K?Vtrc;V%Ml46Thlp^Z z&Tq*RnDllDt2;`q>6>KWwp^P{D%lPGAvrRh$RiY! z57;0d>9X3gkt2RD?`sFq50ac1Y$XyDda38lekUs|DeiX*uA^HLKMe~t*XqDE?z+e` z-BSIn8RTS73iNSgRqZ~scM+NN40^i_|B)U$n!J5D2qI*>B$-3t9j$y(mwzP{88=~l z*n84KVZ3Lkc@P$)Sl57b(EcIWnraBobTck*CWHd&92 z(^%JnsWiX6H@I`^RB!>U_uaH8uJ59NZ2i%vK_x|-wpaUA>@;#M(O@X5?%1LXmP@=^ z+=o>mXZ%>So3-O5pX+ac1mQ>?EVV`SET?OrTq7p;H;tF_q%u7}l5G72Zglkds;>Muw#P5@aQ_x*84`Zdc>qnf0cMQGIM)!I!{^5^-gu(T3}fxQT> zmg3!lM}Gr(Rk*Hj6{MugU%)V~D2zVyYq-LWVjd8sUfshaE}5;dkDW%~$IZBSaPXeu zZ$IkDW~R{6)S~(;C?j7=h*fK5Vq25JO6VEK-eH<$1nI~$`D2efiM+o#O5oD_nZsd@ zCvsW@C5;>@wC28%CR=OSPNGmgettM8Q0zsg-?x^2t$Gv<}UhthFly z$<0k7wP%a(^pU35?LrnWaw}5%!!ca$YXv+yxXf3)!X4eJyC)apHAa8RsojQMS@)JS zCkPzQP3kK8m82?=g1Zpxe`jT&Gmt0h(d*FJmb@fAsskz!+CJEF-qGVu7FZ znS?Ty7MIxVI;K@m6DYY9zyUYU))h^Zg3k?AWge@UIIxT1U)wb51xCEl_@E@bO_Xv6oxkq=dZqY%L#pn9zyhhzX zj4KdMN(p>Jru!gG=yaDi5HEMii=EOOo6iFcm)+~*&#f<&Jo3Cj>9g03 z&N9!m(js0W^{bId2jrRiX;0zV90N0RIrqnpe}u$>VFjpO+&bBl3SCP}OGCWW&AH9Z z3tr>faHp;IHGCHBuS&l~RcRw3Z~mhWg9l?>y-j?y3KK1U#%?8OZ26qM;RT4*|AwWXhbj`O2pvTQ=sRO2H_@t$!4Y?%Yid{&!!JZ``CvesO87Kc%7!0FC zmP+z1e7jY@i={=ncGn7rFfLx>J)4=yMg0-LN3oFF;n@aTa&B|QruD}aM&hIYp``!5 z{5{l_^E)_L7qdn>#<>~kF!$>5^}n^ICBOXtcmKZwyv~9AssH}Oe|ZC>%h<0k`+e(T zF*8x#VAV3DP?k6H0`q_G{`cVtq!_e}Oh0OVO$~>WL5EHzQu_SVy9SBqfUqzys=VIk zxIx^$l#|`mJ!&Hd_}H%VmeIC~o}P`5)c_O<<=9ZeOf38O`EMruJE%@z+BamOwNkt1 z-MMSBXyEb<_^8#0f%lCgr>{tA>*2Xptp$04cFPE8O8g8ebb94kUx*JU=1;q!c#Nhq zzgs)9n9TJ+EJgPYrFNuwfFcd|4`ezPk$R97k+dRzJ2^VFot^6;p^-K&0T>&%AeJQQaChf_+m=sfdpDgc-l zKJzFw@Q!t~QQyf!+wr$|0pJR9a;FdD)<0q( zt+$n^Wy^`*ig|vP*Deg(ZC^*}4o}_S%QjT5ozrbqYe!g(^)WtH!;>EeeeJJTO=j*P zPGsW+Kr$@ClBnvdOkcCkY}p#C#cgl>Vax?h!F>nG;A36>phWMkno)u?8->N+BZ#38 z;NhL)RPm^r?-6y+CxsS~lFG^kuRVT2LBSM&PBNl%`wa!Ll(n4i((*Dh5L_WR`;Qfu zP$YbV#=yvk1PFMqah7M1(CyH^gZ)ll8>d6Rm4(GeR@SJ)#fH?UnVZ{NcCQ=z^OY1J zG%`8X^$EPx=#ZC}msE)L>J_Dc05KgMol^~D`Uuq+8w2#y2pKM(^Z(D8Cohksp`k%% zY=6j%^Uq!~DM?yIB?dW{RlIK^g?aivEb0((Ak1ttgkKhVhmgYRqBe*JY0On(<(kGr zwoc}UG|oqkI4a5gL?ZGl3xROnxc*u?PO7T-U)Q4M09)ZrQ{g1dFtRJ6SlL}`J^Q$r z*S?aY?J1zbm#WvjURUHpYd6}*^e%3&`rRugz+iKJ3xAyY*IeQWEAm-DUB0^VZ``H#LL+#b3+zrk9#I70$L{+TuoBMRp{c( zC_d7;kPKtD8@d#PQ44SKYnzY{Zg&6!Ko?cG)zW zu@x?h)GvY6RQ%ZhV*v|`PiG?yv-~n_kXFN0upf_Q(4u-f<{r1wIQ(rxFQ9sInhSMp zA)0cv5goYhtn7+Nb<>B#nUjb^hOu^KvnlGo3D7wczv`d(aAV_KS{*u8T|xF@EdJ1R zAc$4O@+X0fm#r-e5fPDznVAXzz$pI}ld@g&U)3S-?ERIAMzob+ih=MQiO=~?Wg~sj zTXCP)f{p^eeicp|_wYNv?6&iYlcMmJ$j{^$sgLW^bzx&=EflfCp~$~uvsgG3y5H$u z0(XCYYsFI~Ql6HxcZZpIy8nuAq?z0Df@c?$Gc+Tzb2)b$jyeCeP=^TVyYA z?rgP|7oc72f}|Pkat3x}SK5QNzTJ!^FL`w=jC6SX4x%6p0c*S_0#AIdJ*P4G!^Ri) zRa+ekvb9UX#)DtuBrdGnE^>i${YMQTu{kb(FsV0eXfDj7p1jRMvh2Ebf4RV*(9Oz# z-(Uvbi!@Qq6KP0yOo(+ViqKC=4*UK_YC z=k`}07bhY1N0vI_Nl?@XduVmTLk!q=nP+(PxG^~-+bZ0H;6PXEK1Iscg)_Ss`d2im z%fSz;9$Vy1>yeMo{SThU!X++_&^~oQzl}xSqcyZh;Cvw9CUPE5AQ)2YW@+k(9VH?Z zhJ-u&qvd3E09DnHUbi9E#zS(Odz2-1Z?;Y;o*12RX_r{j{|o7kgR;{?55%pPo2O&2 z9cT)d97W~R!miM&@ZT#aD)M%uSD=O>8%7XR|3gmX7sedU$*!Fcu2-o(^|HGb@M5=f zAIQrVG9fy#YNb(LFA@HRyz6*&~eTrF6!5s`<@dqnBzy^uD6O8=x<9^Pyp&pppra3LBET*_bMtA{El@= zR;snPZCXGZ`h5Nc`|ktFnIOgMl(=X#ZX2Hkyos~YVi&BBRrSP`aSsO-sz3$u;E7bBc~H#5$MO1`qfYLhc`MeC&Ut++zK131H5A3MwTB zbagUxhddH5T0HlE5gG*^TUZT9bt3x|(DVl53_9FDE)prG9ew}I~b zs$$FR9jXWPmAy;XO77vZZuwJ8)^ChZP*m+zx9Ir-1^IgQCsZ}dud!2=?%N%9Cu60l zf7Q>oG8|x@$a~3b%FL9s>DDCfFiJclx!1gkR}c0lT_RqeW6>*fKX?3wH(6kZUZwM;7!Of(UtKtyOq?@VN^=hbZr#mum8zkzF zpXa*PWOxRvnM;#Uj4FB4qwBXsf^BPO4_k zIvi|~Ce|I?YKuQk!AwWTsko^%`6F8-@l&QL8-qZogE-ZYxT2oar@IO6R@dc9kK<&~ z)01vd_HFP|T)Fi0!!w;5KDXN)Zh9Ev-pyec zGy4gusT!y%K8|C&@V2Q+!~Q4!gpAzUak%>r7Ltb_a|nH|hB)u#^UcXAx|4iH)V8$? z@aQg%S29WLTBDOW&1Eyk#Dc?O{*{@s+nTUIhw|?+%l)kFyG3nuUDNtI zu5CY=%aQFlOkZnyLrFuUOM&(`?!gbYn~yn5a{g0?=9<}eho0;&yks9+8OJqg&$j$P z^t z^KeJ@tjs22M2(;poD0;6Xb`h=lbSgAJR9c~DxNu|rFgJ(jjPhS&HG7For1_nk5`aOC2o59 z9Kpii`NipyAp1oeW>l+9smww{=r6EY?CQGn1PT^%z*d;(WQJhrxDi}l#?Yjvyg?%- zi6}|?yXYczQIf)71pth-fL9AA*RoHOgXMPXS5Q|=Eo(bTm=5t&t=ntuFR-M?L91}2g2hb7i>!qy&6a9)4y zFc;nIGp?!WtnZEgi%a10%%ZQYIB6L$Te?|cJbdR(%F6PwqdhtB9Ltkr^g(!`C=6Z7 zKypPOW?{%Hl8%C|gD(iUm|)25%0Suq(>)XN*CL2nkqVub>M@b|k6m2GoaVkRmCs z{9*IbM)g&8b&X38^*UNb>Z*+Dcag!Xw4>o$Cx>29&zEq!o9Ci8olNnP?+A8a8bQ3t z7R6JlvlGU)Te{mHWHy3dE!nHTZx-K;Bbe4ok()Kz#{HXR$?I^)WW&#y#FI^-lltBU zN;oJ`kum`37AjiO{goceS@Bq5rEmx?@}zeZimhx;rU-vUS+n&lY}=TmhxMP^T87t!%{OhCJw z0AxpXyaM<~OL1}k{aAH+dOD3vAq@ZksDo}nW`_N7+x{-U(@cN9Un6%#R@`f0g$mFl zB_nfi`C*p(^Vc$_cJE7JAY zDhG0f(K74R{lW&Oh|li3X3OzL@~#4_2d1vB-g~s%GMZF(`mZ<<{j92y%0iwowJN8% zf?B|&sIps9kFAm419(i>)dRBbpM%8KF;FW2gWi@DShld+WgTd71U1;v&|9^fuqCGyRhITn_Pzoy7LX4ux~22#0JPx;dkX2}65haE z4=vDlMo({U1pz=B>HW#86W~T38jn|N43((w61wEN+lWVLF<)z{&EQP5mQH`RI_AyR zegw_YVt4cfjfS;!Ve7baj_4e0QchKz4Dw-9ZDtDiI&I`qGXgk~^`(x5zx>d-u{V-V z+Th3OjV<kYD;wYR|)BD{;Fc95ccE*uM& z0a`9EmX@TwwNVP)DGYRb}TZ(dFnXR2=7_&A*1r|*LsorSP0 zbDe0M@5|j2wpHTmdyr4pCz zPkr;Nd%@g1HlX)eyprNuup8<(!Pyu!=XSeGFrJ7rE$_9x9UCwM&|p)npzV=YT6Gzm zAnN4A+s(ek9Ifd#fRq_j3M@Y)bs+KL6m3L&C2#W$pSVF`p@ZI2eL{rfg@m zL3Am4TxjB)>|7|7)y`BoMF~76lsNt9bDZEUTl=!dULv$k#CD}&OMVcToBj{9^54m7 zdtTP2oR509uu>62Q!G4R?3fKXDTseZDZzS%@hQguW1Jk#(bd)nI#W(MP@y!No^bjP zznoDvD3q#X&Hl`r{*ZbdtG687PUCkG{swzvMu#?VVF|^=BrjIkEUUOWDLfs_pQ0{p zl%LX(lT?!SK4$7-TIbp+@mZU`qLtMiQ7n%>vaN>JvGAKNo{$&HFsn_%#(NcWABDQe zv>__%)GULl!e)!2!p1CAO$vi0mzgA4#;NyPY!qA@RleP3^#`1|cVqkaM}d!TPHZrh z=LH4eA8^HFBw5rUE`-y*km-0*MMhd4re|)86PTH^`NslXwHgF+?UZ;s-%IHki?g1; zlb7cvl^=nwOb2|ilOleD6-Tg$JH|=~4Ma<^vKsz6Ry$g%a5lv=EX$DR00p-`W)iqR zUZR%GRV8?%^PH~zLU}($0+I35#y!3ocdr^Y?=@2tU?c0LfrcD*RWKt zi&ghP{(>6UL-u-t@U2RU5%@#X(`w=*I@{QEtKm068J4bbMl=%AB6J`bxm?Ov=ZTP?I0tc-*_Cx7$k^>vj*qPs!H|PoDP*6|bKKMQYj52^=`@ zCDz(b=zDTyUZ`pY!Az_$BQy8G{;mrgJbTwCM19gL41WQ=XNN@AR*k8}>?1GJd{ADG zb0YJ%aC4e=dwzlDA=xP^!PfI|9U&vFk$ z{4nIaNO_wdGDSeKTKeQI?sAZ>3!YtGVqfYOLYl{7j3-~=SIunx#$N?lTgTB9e}5}> z@xhl$O2KGCU3^EgIT~xQ!?1V8k7j!+2T3t)q2Ectx~4$p4wLee$sB(PGQ-95)cDpp zvqVR*dE!jAOF+*LVIY(ykIgy$mbdS=quNB$<-bp`c|zF_7E&8`_oC$@N~v${`9G)& zx2OE8h!OwGi=i3#-eZ>7e;4W@cPethAxTjCN0-fgB)OPw@i?TXo;+&F+!sqP_S$CT z4#>Cbo5G^mvza4v;jaDlr`X9JNtOw+`WkB0TP>n=yRfo@cXC!WHQiWbx9k zY{z^C%;k9dUbg4)O?WX>CjYJYGC6*$O%Jp)vFOAq@>AhiC&>2xbkLkIEk$f3l-a7; zX;?4-obkX~c|6~paaDJ=B6Rup_-4G!;C#*3jQwwSh{(N}d6v!1M>H&_tW{~M@A!6| zW@i?^4qW&O$f>3YgLjX7&m#toE8ck+jPg49jYZT-tDxJrAt zemH2(?eCI^S)bp=%E&OX5vGSHPMm(hyO{Z~xwHB|= zqdudd$7iZsju%};BJc3Zm_UpK*xNVcdUecpXVc0%VNuS=n2HuRC-D|n^iW3p$Z@r!^qofI$=5WV+M|Jt zLe#~Z;s~~CLF!D8`mTJYnVW>4dafzCqYE=U<9S8q zB|?d<+aun;4fL&Tz8e`>Bh=aVh5juL?VD#0br+=`{_rUd^1d3L+SGcTrgPN+Tg}A8 ziB1N{<+?`6AWI9CvB*G$<3?`1VBSG44AzwV|^#x7VaI z)ty0i1W@nf6|7fPk!e#J^0Rf_tHjm2KS9%{zpg(viL03TVfA`X!n{)Wh@JPmOI5(t z_XgcI(^=5>#*o+5*CPX9ENowd%&hq#INqA&;*&dbI+4Hmk|>y%sn{H%E$SVxj(EyD zBM84tKrPd)|FzU&XP!69Wwv6Nm1X~~vZFd)jN9&*QF~a4`-H zYEu9e^v47pr+sL55D$4x)Q{U>K^y+6uM-wX9rV_+%GPi-I9sCVULf;t3&qc`4>E-B z`tH2Z=?`i#s_0nsV{b20uiqsLW?qvwwwI^rx}d~nXbG`aWm2WrIR)3MdjwWf ze4YbB!~5I&BA1CYuiu3qmq&f}YcSZr4@De7YJ2WcaQJL^Iq&zt={l;PjlER(WKBF8 z8T5EfHVw_CYK~7lXuYO}zmAQ)2?ghG(5eDfiBDxENN2v9%i=n1en83{HD{@CWfS{5 zZktY3-3^WG+bJsFNz50bv?_s)db$*Cl!q>?N*?$T>BBBzGrv}d!I8ZG{hkZX-C$Cz zO9aGKi_nXe^I;wPe9@h$LkvwXlDkz!N_&H2Q^20QMi*8cy6bgKn63``0$o}6Uvp5O z3D<|8Sx&%+*ZV0Ty=4-s%U#l!pVcM1u%?`PjFAkgxVKozw;0bqsv(7b+ghB&KZzxIREDP@el(Ew_FMnt``~KJ%;}jR99_YA zsGE23ti$Ce%G+%n66X`-bmtR^boX1Q+l>H`ZBpy344}Oq5GQ;aO6B%)vau=uQ@Ay` zJ2M7wkAs7pGjnq(H)cC%`-ZiE!U#}D>yK2*$tCW9!TbWtF#01|%WOKk7M?qKk)|#P z`-KV-Q;!1Db+|1e$CHMjqc=llS}AEZb*C+OHYxyF>$A& zUZ6|7EAe_8^;qZfMVl3JuQC`Q{lP!J^*2bpKyX&yY=jf!k zsf|E2G~|QlZ(~YrFLvY=_>Jb=@;YwUcjPrZf^F}Fh*?i>Oy6e#m{`ZgjF0W$A?2Y_E z{p5JMv9~}O7NbOhBErZd2j`S*Rx)3dbyqX`T5P-#&T$g71z^l zR7#%rcwS7pxAO}}!36CiiSOLCiAQFpGwsmZ1?^w1<)Rts1@bbUJDS!UeQ51ReE@)w zs06*gG0BryXuPM}K0a&UT88h5$PawFMt{|_w5Yl-lFsE4fI;*|c7EA;RZRA)nD7$= z%KXO9FP8VM;}0{N8#0`Jf?f1YUEnEmylZfrFZKhEzOMc_E~{45T);^)*gBhC`_(5m zcfNb=(Q&73Qw~+^x?0zdm!T`c;DEPJ5N8B3Uq`&|(KL!c1hE*>n9Y_LTSN@?rhPwp z+3p`|5KUY2R5mtYd>^vkaf_@1=B8}UMvIWc6Vj?>x+fW$Zn!C^A0dA1`=#h_Kf zJg#>ysm$csuh9)Z&5sse@Nx)8HDm(>k)zo=WD&7=AxtaV+ro1L4xxGOK(z+qszJIe3*Ag%v=My`&c^8W*5cgOwCRcRkkYH+JmFn;!NA~QjnBCXvv0# zo1ls;ma~W?g@o>=tsIVw#v*cao{7aIk$0HKPlJfxgeHIkYfnu$OaB!7 z8CXrcbbp6A*|?08D3A8}O^R2k$^z&deC;wl?<)Z{Y3bK1D=S;CUz&Q8?%yZk$kS3& z>s_Dj`1<*2bf*_R&d!YOpbNGkBo5OJL@J5@=#l;7)@SBzLe(nAx0jeiTgyXFlKFlh zlT1WJDsfcCw|tFjdA;Y~iG{HlGJJ8mSJ0;Sv!ddSm)FDLhy2{T^I2C{gm*!R*s*7H zC4@`WBm^i$9EGKauD=E~e#OI>iXc-Ba5k_J5VBc$=BlZXkRT3Hd_IbP8yuu>c^M?R$nlA7ky05xBXgoxziWGp6a(<;P! z84!pdC@AOy1%(9G2rvg$wYorm8g<~ww4 zsS7Wrvv0P-$2RCR>c!&@2~6H-za+c<@n0|~8ymX0_Oa4v4KKs@rBsv^5;>h#Mu==1 zlGq$j?$zRkt@&<3qy62QyJK1KEy^otLY3M6A3Yf>`w0mZIYk!v7^|yUO=%_UP5DhT zP6AdxOpDh{y!G}imP4vt?99YpHu`aw3iiabG$lza#;>ft!jPOlovS@eGIGx4UjW1h zZ9q~aJbP*6cut2{d?&F4_noCKw^M?flQ#!oP(JJ8Ca!bZQ8>{c4E-)C&ysMcwN-XO z7BuHG#btSUMb0`87kly#QVsz2)y82f7>^4pe0hW!9$uTjj>ndC zDP$A6Yn8O=HYF)#$0~y=Ce2W+UcXZRXpoICjEy}ha?#4K)){&Mb($$3i$-p8K0d^?*AP`^T%Q7o&gzH zI4G`+cAFqF)SJ`l9+s4H8@?E$I}Id$^w}+Kxo?c&SOU*T*J7+je`PfqN^LPqTSpni zolR*Sy_Ph#ifC-OvoV%aG?f!E^`K0ZFrEFVrL7(K5~ciqK_Mqn?lMiMzJYGvn|QH! zKW@IfcD{fQ_8n-AJLr<_NCf=;Lf4JQ{li(%ZO=g#PEeV2ecQBmZOV9K?!UJ3H3D*u z6Wtt{9Lvu4AoCGT2ljSVK* zHz9y*@R_OY%dSxoixfuP75j0a$)Sb4OM7HUxM8HWOKL}4^)#;=h91vQX3j8T(+Hwb zEi99vD5eua)zOg()514TX-L*i;izD6A?!g;irf~J{swu!P>%lPs1A%s+>*mJJl0aC|pBq%7@KXNd-3A^4TWHAh^ zL*5yOWGiGq-~mMLmS5hPe@6|YannHb)x702I)-IY(1T9dHPOG>&T}Zj49P0w7QS+1NTohnT_v5mFY$pUE9k0^jb9 zGRp4tNUos8Rofv2(i+25K{JMGRnUfc`OJG+}lqGvu)t zP-&`K=p84s1smt!^Sj(kmRTUaRp-2w*U&JLz4oU}P96-|laCS`^Y)-$iWxPje*xbm zV4lD?Hn(X1S(*#-u#{)5VdK;9ZUovxT?%C>6#Z?H`&hk zX(7sEN=t^nGRsLkEEr%fuox0{Q~ZSkEeo^g&2Y_@(t84S(PNU8gu${vX1v5;am%f@ z$m%DD6=_5Cc_l5hoh72ML{Y6=&;1#a`v8qeqC235KngNKzbY2@_!&7A+>qrO>ABQ$rvf$sKDJZIX zE8M9mXmn@BYJJlYOi$F)O)bbNdXC1cJt+8a$8#v?B&g;Fjc%}^LJFfy4xKT7xFoOM z;=(#YJe=I$9HxvL)Vv07_cCp75Wg?(_U>D0S>H)m+FZEUEZnhN$wQxSk07aw*|9{P zKVOI3?yA*Tha}H1=)KFfbo1wqxc6RqxTl&YF!w<$YMV0#h}l`!{SZ6Ed!cnf1s$qU zx#ky?z#9%@JzR-ux%Er%dK(fjeu0S3##sG2_Qk-AVlI@t&TMGOgk|ICxIEpa3^!JJfJM1}AjC!I%$1dWH!>P0G$q(J?0NR9Fyvs(DCTC=Y7X=U zK}c;;RkUgkD$FmP9;9Nj>U5pf<~usPaJjl@S!RqNswhq=D3=ECx_{2n|2~6|t;vml z(;v85@tZZfM|<8Z8Sc#2(bJ!I+Z-{MXlHy@QFvYlZwam!L&IJiMnxWa=4Ohx#=_3P2Sb7jjb~93XW~~9+lA^-V>sIn~I77i=49= zY;rOm z=d!G(V?sT^L5ZA46UltPDJX3e-QWQ8oMEXaivFpB0lCfOOzKT{0F=QQ^&Jaa#x*>9 zkF#{0-d^WYygQ27=G9ua%r{9riY_q4y7Gi3<@T@oz^qkw4tAs{X4}_TNH=R+hEg8I z;6?z8PJnxRgM@|gO=|MwtVmlY!l~ucdxORi{6dr8a^SE<;-$yP($azNXXV6Yu&YwD zF`wF>PuKFUsg?PkW{VOrJvDH_7v<%soSXiV1FoR+F*{?Kuh= zP=1q%^`fD{hu;(6BEABI_w{d=pT44#h2IC!kjiG;}gU%35b5TK0+$9Y3-f~ zdGx>+PQhrjlLaeUOcV8!*pM)LzGA+oRdx~j?fSc9_<>f}7O6+yt(9uIKu+pxE>8W! zJ`?(W%iPuNfpFCnHs~rU;H59d5_Sr=-RA9rsP?ayqqtQu`Z69KO;^j`tgIr!!X`fr z)Ug93RP<0;S=o59JV_Z|e+UExQ=crJ%t*f|r#dUppa($%;8VK|1LBI&dMxKLm?z^E z73@>ju5$8*<_Z}*ccprJ>E4z83=B?og%_vVl-G2F071EdxvkgOu{gN4d^O)If+bBg z)5>Zp+YYp3(oKd~tU}6l!iFeVYa&-y-<&m_Z4-h<>v*%E^b>AN(hZUYdGDzrgrTS? z6XyUnR;d6dCXK(E2U-j}EMel8RmjEy+J-C@d(5dNF;}avnOkMQNSgR*unw!zQ{;yE zJ2*}*o&3Nv$uItSIc;+SJCPi?D$UAW^o^^mZ&eK0*Z9aRuL%+Yn-I%TF$_R1>pQL+ox?zdDjz=n1a-`H;{t14u|p{np#C^Sk1 z#hxZoFX*5oDm{rICXo7VP8EgJ6geSJGSOK!aG__BMc2?GTAFrcA+PM>uvEbqr`}jy z!F6_e;rx)pbnmWlX3oqf6&=bezpl49HN(3ln_cs_pu;H{;Zt8^ksO}$Eu$DEXIqy^ zG}d^7VxB`9YDMrxgTMvm>YFJNu5E@{XcEtSRFz;->myxvk4777>$1@Ox<6iSiultR z!l}xQg@{Yr8?emfFhsb%+3G@89F?qONR)j~Nz}%tX`=-Qmqc;&0)NHBNPIip5hQ;9H z_N&{AY^&+=U5p!qxGhXuDJc>o%uNY(@EYviV9La6c6UsQ(VvJxw-+s7G&-woKIo*d z^^);*7&@i(r7?8zm967jeeAcQ+ktrRQ>(CE>*gPm5pg_DeG-#vUTgN(H(bl#^71y<^<{ZL@IDji zrS|kh(vN1Rk6yU&{%A^GT0ot8s$1r=i#GX-Lw<6#Kk>2bGg*0rD}KI|RVkKSNs9m2 z(qM=XW?0cueG;mfnq955oX9PEC^a(%w*z0)=;O@e-5pz4Q_z_|~CG|7${JA~yH6@@l7@&yM^*zo% zCt-EGXGRLhuYSn1Ll_*9>z=G?i{O#Ygb}hCCDjO+@gfPjrOxR}<^Jlvjw2p=S!Nr0HWr)+uv` zX}9Q#rt*4Qz5wPyJ1KJNe^UCa}FH2jTaVvXjBAxm?(e$%RwgMh5Lj^;n))5Un zQ~DM>lL~U$S3;W)CyqKxI>M6Rn?@8^<4+IhVrh!+cF=oAkE8dbjVCV<;Z>+Rjl-#2 zlZ@1#)2`hwwgiN=RskN|{>toP)^qy*&7iS+mtAAOm0WTIGXBVJpt$pyYh)G&5brkU zJxgmiES@p9{PKzOnCaHk@MciOLTBHfUwvj~?0j!6$=^Xc09rgWzw|9nCBJuqZ4fk; zJ0_-X08#26p&Yw@!-205k_(gU*VTMT9n7VK7DM$d&>M|=`&2cpPzGfNEjldBWsCB1 zG-OIAN9Rq$;=&l}&znO^AI%Oz>g#y`*wLVu8Td=!P!*C&m2KueIf(m8!1!?wgJyN& zp_8AVA0{E88QQ1xFr3@o!9noWP}-)OK@61~B{lVLU}YE24t?*P&Vo~`a2mssa6Xxi z3Dm$iRY6OQMtGA&ldvNAJ6;v1ROjEaFgXhc1xVrA?Bb_M9J7*;BAB~2ymNd)hJi9! z`7VF3^o-wJw(#rt=G4IzbV_%L{l6)Zzo-D-;AlSF1sVojQuyJrYF@RLsH$cH7Q0b% zqn4#(I$8dXk(Fm^YC7N`0g$jE25crKCLbs%qhn(~Jk}enVN8E?gjs!O#Sf@ttuPzC zIVSqL-!EP+m)KUNJNOkKfmMvtEcK-;^NUMqAzw@}@}ZZnb~Y+~F_vA;o=Z^lno}1J z$R}o?@jD|`VZB;tVIAj9`mu(~b@&PW$MxQh1Os)-K$b2O)i?~LG^PDzvE;Wl-H4Bu z5q6257EgTU0WBz4-4^O^ZK2hhmQ}llsandR5YKeRTGuN~62d@8a>Ipe2=vhr$GsCm z^VjqR`Q8B`{+6;x@2pyq8b@3?=VIp_`ECIS@rpBNvDZwHu*bn?*3;ZT2DA5}A%2+e zq5Jpolugg~SF{nuE4_JYii##*M~dcZH-|_aV#6xqee7a0StYlY$E=*!j6z2FFQ_Qb zoO&n>P#exk4U!HV7w>MQU$}DFu5{@!NoCvzhoxu+Cfz)7^0R;TJ>|qPW;AV|W!>J4 zDYHQCHN?!+I% z#MKbrogLnuM8G?_D0B2ZcU2$Gj@J2Npm)&3S}!Lk%CmvKZbtW|S-UKGw_ zo|U2l-XOoPqYvFqv0Ts8?ZMFT3Oozhx0c_nvEmUMy5J*L8xuwZAKaUyRb%?>> zw+WnRiZdjEwvkW&bZmgSpBG@Yu^Juu+`LC-_+q%CqwCIZZtc)Ve#6TPcnc@iV5INE znHn(eoZYJnItg|0h*damiGC!TqoV{6TW}?WkUc7T{uoMF>UMEJ!O9A-x=lKU#86~S zg;paYG5k>pzm*U+xJ5{(&NvZ2nluK>Nr5mfwOSf#E1*cOP%r46_96kU@M-+Pv+oF3OvU#k zJBXOwJ4lJr_Drti+b0bUXuw#nrA-Gb8^K{`$J+!IMbmVhi1Lpi#AZIoXD8&e1CI?< zkaK9}dQqCfN1r-O6Nc2shgHV;klZO(PfxoPurMcM8c;FsZx)0S5`=E~JAA-p8&m6Q z9m;W=+i1v6yRFCA(-IZ!l9B*nK@{{GoHVS7G)A)o2S z3H+lk8`}s-)qAlUpLZBIq*=plHcxnhFw3KSs|*z<^|CVeL83rAsu&(hqkX+Ih}Y_{ z9241;9di`2NKoW*DMl8$2@^NaWG->(mYCc2L$+8Lj}gJgug^LH(5VCj7Kw^tmk)EK zP*zQ>?oH7ZC88(NKD6nQbzTTPXMf{dp=ujgZqp@Jqw+$C|lM?6~u3(1Fsm}oc-}3h%Wf=!C+Aid$M@P0D zB6nN+qyvF8j6?&}zp}WG+P8{7s&DRi6wAnLE1@eA?D<)!Kl0?#Kg1ZiOwx&+z^$;_ zB{;VPb@Fe63ktjo70ER;aZmPtM5xzVa=O{w z9NgG{v&iePuzoVi@M2H0pT^Qg1Q(<0D45~x+t_F&2&E}?Ub(d(;cKkpvorGf?5Noj z#qj-JD!p}TF}aWqRC4Zsicv`KVDVN)4iVSc>eC*y$8FD^J;&6JmC%n1a^2Uz5L4k8 z$I>_-6?e}X6DKV;*!AY?gXMoS;1|8YDRYnF(8>|**C;CubY1Ip8ifvv63vvQg8Qp0 z$nthl=em@#g92r8DH*+cw5L6;Yi_ddmvb=lrOWE4XKVR+}I$>kFJydE|Pw}4YGnLZRUH8aU*(fcj_(4EN2qN0Eu|IDWu*Qga6HP-$ zL&4dCuOy1Eg5(s%=YXekzj(>1rld!km2UmkOx<9+;q>7h=l!>PsKr-V*E3N z4?R6rg)2;a{en8qaV?EaaeIAYp;REUv1>9&4vP_c|B{Q()Y4tNUjX57o%UXYg~6P= zMcsqqjuqeWm^+Tu;OFA=52EXo#hcmO5Bj363>2GLZYO1xUJ;Huh|UjztpPr9yosYv0=44iz+s9)U4vatRDtsD> z>L3zGEmRc9fuiE=2Itd{+0~lUioBRz+sWN;iBrZQQX2o2A1fi0Gn+9e_c7n2Ok*EO z!{k??k7+0e>Lw0=>T(gH| zWc0qX10%V)C|eNs{IFd=l2H>*ItK}${a>2fcRjeTS7)PBhwOh!%*VzIA9bi8Sv;rmEZHp?iLw&NrA4Dr(B8&IMCVGnwglV#@69 zc%p!3-T6<9mkJ)ao@Wd=4CilHSkRe0B(2L$Uo#XHMQqF_q#LXszc~$BI+3v@AibZ9 z61?@mQNsGs@NBSiLuzZa^e7Bd`2i{JgORz6N8#fPvzqsh_3t4m-m}w*4P0xCK|zdp5I! zYwOg`72=h5F8bQ#=V74pBERP$Y^LJ z)tS8IssH-SZ+)^VtH$IQ3 zq0h3L2usNBooA~yn3~2gspPDLZ?(&LX@+$s*(YKR<<~gg3UU$;sX`}|VbN-)BI;G> zvW|lj*a?c7Q@%1s1ugs~x%k)=0F)(FfIyu9=}v zu->`SlE|+GTv`M4B{+;FkRx(C^tbV()!d$43T$39;nJHBjyNbM4VLYJf z>lKMgValV4a8=Q%H@_YNGe{R_$49e4>2Wp9(=1fDOVl>FpK+!!cvKn%9R{dQnksw1 z?r%8c-6XlWlx8fLMDivnbn4IbXJVBnl2d%F+-|!<%BJ<)7eLI81)S!_1u8dIHUd4t z(5dCLqX>X;*yt4-oslf!M=*QN7lcxx8<`ZFf)uV)*VyB1ETA63_zE;q)7-r1E+~YudAbQGHJ$ui&;sE|KmGYa8qOn2b91&Ok&$Re11TW8 z!jiSHKG7%Uboeo-KjE(`qgD`byJja3;(tr#qjt0GDF9mx;N6M}HF)R55xd-|r3T?_ zkHhKrbz*8O0I%i`wd@Pvm%IJ_IDZy(?d9LsbAao>=aSEW&Q`yH?Z4~&PciSWT2@lz z{~;FyRDmdg-dCe}uCvdoCPPCY5C}N%KR*a;mezp z!}NdtGl1?wMt<}^5>NlRVJBGl|Nqg0{XscxTn%;NYg$_`k|%Pg=9A&OST>5J_QedaZyh z{tI{fXJP~U#igWBpit-^Y|HkxF}~|JpuoM(-g`7w@>xouVG!VSyx#23LQN{2c0n_L{0bE_ngyz z&F3F0`M<4&NXnn08PSwKbC9?D!`K|g{vHcR2>CDrZCq5dBd53>A@lPya?h_%^kwzj zk`HEvnTA~pZCNF>8!}$sZVTEx8(nF3&e+7Dayfvn_S#|p%7wgU|Ir}$8C{u*(X`Bb zOQ+Y)K!wq-z)WI59>J#ZqW)^-Eq`#zs=IXs?-}>R!Dbzc2SY%_X0*;%{GZ6AZDonn zZ+>XeKjqOHa>*@udvXp5t*XYx3~S4a8BQ|_@qfaCmTP-yjkXal1YaKfDKz?eXKS$6X_X1aCxtblmfmdqWcEK44eqmc z#lXdp#X46HkGr6D=gHve7@(mm2n4dWwXJyFrnRE|DlUCeq2W9Yx@@Iu&+PS)8SnMx zQbp5`Iz^y9X*V;`2ewM+`ghSVF7a`WE9;7iTGI9)9GM?_ja=5C*yhv|m^S;$*O2k_ z@p;IhSUMEtGuHL0`Kyzd>2h;{LxD>toqHanIbY1rVgVS=CmId!0o%A4tgQcSF(Kl@ zs7%%IgGqnE(T+ZG8WX-Md*=qfqnjB@v!@y!^rt;JX96GZwyZ}WqNnTZkmdkx`Pg8C zh6>?;1M=OGbu}*qhf4`xO*NZA;gG=`Kr`rTAU&CkZu+&i&|dhQl=Y#O0Zl+Z6pkCX zCXuI;V3z)Ivi+F249-5CUUDz%(*d{Z!yIw@WcYF#@;pO17tHHa>)!95{zHUL{SwY} zxu(fGQ|(5WlHk=*&ro2<6=A5A%2aaBk?P)ZujP^p)sRu{o|Np_c-9xn@NNir5R;*$g2)*;N5cbJ#>uHTk6b46Tm z=5OQ>>y?5IWaIkGpC0W92IC!87tBedGsI}Rx41BRXKOC+JLx|N{pQUb5}a_c&*h02 zQkx2Vyw<7>zWil`ZpiDjt&<+c7MmASw@IGvdAUSCT_1Cnl2GZofD;eqVs+Odx-U8B zO1D1}a7u@osXvWFN~m0hak`udW>oBbdNUXA(Rs@cWvhRVg^L?}D1me+#XbzeP!C}+ z{)lY@9{DQi;NY;iTzan8R%g5cq9ffurn2x1JOBFiZ)(EWv%ge~7&%>oqgz(Sk$PAy z+CBIxH{K!98@P(O30M0PAKn6`eOK0+yK^skWfAz`nk#S`WHKSN@)(b5+IU<1w(e1O zdKfy~B&+R=uF2`9YqyE-Yv+9mcOSa?5iP4RMhEMT2|g1Z$Ks1~8Zz-X_JVQ@sIb@~ z*WiSfFPoZ{hGV*ddj0k2F6SVo7etq&ylNi(oIUhd8F^A4hu19wv_qEjv0h)&%s+_N zdeTmBwq{05Sf81}8OGC*W`?x2qrutMNC6z49i$2M^4J&Da)WMuUINzS$U8mL=OGFJEO2ykEhvmtQ6A)=Y~gG)oz` z*M{J^oEg?X`9j_ABZJ8N5@)n8uyF+t|CxS(dVd?Fei0 ztylLqeLAO5+zPu?At@goe)X;&5gZi`b|qjvrYJtA+7AeK(()awcxwY0J_$)i6jivE*3l)2HUT)u0vKg|O5`j&*xvvsuh4^ue;A1a^ zDL>HlT_tlTaq1lKlZrH0TS}2Oo%32c=d{+xNJvI<56Xl4cU_8K*-Pgv58BCX=pr1GUSzPW&}Z z73p9zoTITO@Mq#hu(E1ZYrE`yTQ4>puaNT*bMt{6`PUbjw6eEBBy(E)YK z>)3pM+5a%K<>;i*YUcV}*JUR@ldIt~v+Wo)U(-BwX<_cqy>`ZQrY=4#z858KPdp#I ztapuHzIyubPNlmED&C#hNEEu|g{4w$rtHk-)wuHfUb9a>pSi*l!O%dJAx-F^Ok7dz zFX_Ce7U?$fxN4anF|bid;6Ga2_?1$9%mIDXRF9(&y!P5ra(vv4u)J(?28I{ODRgDk z72OLn$h;|tr6bkJ>TUOHEY8miPS$K6Jwd07FJcOOCnsMZ245NVpv-Y4d`%w&&ysL-HKw*T$ zJYc-8A(kgD?mE4Mtn)QVcdh=&JB|NA zY`z#dRA|WLFTEF$HaYKQl~0$&0j4M&u*&SB`tdVA-TZqDFicv(F3l5tmA#)Ud%uX- zJuU8{1G-MNAl5t35l7=ph=e!|WzPJye!r0?OWk4wnjqss843>sFJE^24WY%%VaYca z5PCYn-*&+X;RAYe@r25IJ(~1-mC^KA3a7Q154!lR-*-!*+78#hPqFWn9d%75g{d_? z*wCcseJ}~}%j(dYZmxAUmmC)W$i#kBLo?T-R6ML6t*XN=Vw=L_h;c+nk zz__sEOmX7@#@}xn?ceD7S{BR`fSy;zUWu>$+gJ?ssC_&K*Ybc}RsZ)~4`)yhOkLd0qQ}e- zNl#B};$v@4uOUfWrqz5Sf4lGV%OWxzRn^pc zWvx}*N&oS(>^1Fh!m49DpA+oH#qx)#3Kf-=3Ybd>)}wzqG_F}p3sWew!bh^3IDgrk ztl1N=oWJW=PeSfMAeA8!W;t4Hu%B5;?6%5Y3m#OdLjv zlg6vU?EpfXVcQG>$oiDg_P+C)o3a2(lbpOWaSB6zY_GEF{w!4|Ajk4|cr$tfO37^Y zUE{?qH}29`T}L-)J!@GnY-3E+b=*VFPEX$R*weYkEG?-LC$-_trV2IqESJ*L`~fll zBn;cy9E)h^`|QiWCW3aNpLrkU0FRupjjtw=VC0%v=dzb2o|sPzEQr)jdA(+6+*U6U zmqKDpFG23o!P&^|#E-O3XhX8*Cl|@;c#YzYk^>~$hUU=boP;bfoo7URGeDVrr4lGO zTD8r6h@9Fqiec?D*YvOr`F!|VEDIhxR{LEh?kc#LL558wr$YZu0Iu~k(dGswt=tgc z!PMEGjM`;Lx-fil)`NFHPRe3nh^N3`JoonBDUz0|K+n^aJhMYwkM)GhCtt z`LB>jJWW2%*_q|}*g*wwxN&RZJN z*3WYNLp#{TlH=3nSM_q7XxLU+koD9v>-z5kg|d`$bsfO*PKe}mTjCPWDWE$z_Q2no z*4ChYal3GB>2izphO^jkQAA+c!o$C2$uq^t@$~2nCk-Xk`6Y=v zre%XpF*WgI)3dqC%#+oD|Cu(siw^Im!h!G~z=E4WIV&F<`dYCX5v&Am;!)c=OwSR(2KTYS&1Ig$x&`JA-*{lV{^^ zD4D-?v%$k;=;u8m8-r>4JGU}(@Pln7LTZyFhHt&S9=60o9YdG9Nf*RE8NWobeKj3v zJHT@60^~3L9FC@K`F++cGe>j0nO;P`=)P^VCNd&h@P)$ygNw*nrkM&yeBHB4tH~eGZeT0fef7@aG5z8bmuBW;P_0F9ec!I%Q0kw6>n*}u9}F~{E+)>5LOzX1 zkpoG&7X|G4vcT=lL?ujnGjGkxz5lV75iPNx}om&b7iTF9y$0dey0I~ zX<$HdQ?vK0@zgAS&?6M-+tM)8eM7=44=nL!*YG@D&$ynJ!7^zt0ovYS$(8MUsB-Mk z22+jJU<7Gee}d*ozVuQ@;g(mo!^1+S>OOBO?!POt=vnx;_Q8vCKuH;Ybw4zQCl{ot zQJ}5OTU`zGPB8VnI&Pfd?pSuaoH{&M9wq#Gtg!Xiv_M_6=5DSKr!WTv2$2Cd^PJ#y zwow}~Rx3;h_CQ;@FJYJ259A{JASt*ci;uVW_VEOOgv(=rPEh!QSWMIcuJhhxIL!00 zJ{K1k<{NBbVPX0e_%y%PpZ1qedsTW4CQ$g6fZ_go+tea^^+od@`B31NP3{&5%g9!Y0y_YlK{Sw62}&71rW`MD9%)Uq*?!R_sj`M%K;iI-;c- zeBe0S&+}Fl>Cod2m9Xl09d0iMF=cSiiCpv7;~#tk3zWyZxSm7kx#%DI z#-m7@B5Y|k>&o#eoH~*}|333AR|4Xym-1d0zUEscz*$0Q>l9PF{G8-|0gLZ;!!tSr zJ~9=nsFH5htiOE-5B1rwmB6= zGeS6rM|@&&tf1Jufo3;9-ps>h;~$qS!HC#5><8q)d(JWdnKjdk+Bv^zcJyhx3P14% z(vTxy@%=A&#l5bVPQ*PQB3h271n-00jI=x0JML`CD!a{=)hR=X+9o_riMIwHF9}WA zE|lI6dEMV3ku+~vT4s>QNe9xQr9b{0S{F`=hECCW=Wa&%KNb%Ui_ZRKaUY7ll`?N7(+kW*DCER$Yc36ssu`pTe%D&Va^_a@;r7z&R0+e&ll8)Ke$NpO z>(6e|MI0k1p%Xh3FKAyOCYm3SzR=29f7}npi(Z->CC>gZ$VPlAI!@e63~F_W=}0)c zOy~0+Lx=Bn5YHSaF%urKxTlNy+{%a+`UH&J%qqVsAik6#*Ieao%Bpkcb&c?6y)5e7 ztVzgzHS7bGW2ynnqMaT(WPVPKQ>&;tisKo0ck#g$SjpA$oz-azn959JO~%QvU|aT9 ze*beOa_`|cXN+DW^R%eAolHmdL1{`n1lO!a#TEBGqb%CCAskqvr`6{;2V{=cFk2$D z>MrHDbttq6RzK$n#{0v08!QtL#8_m8{GmjLUiHT*LbKbu8+x0|dk*;d;oN}@vqomX z5_82tdI_(NK=V~HU%l;3J5R7Nk^q8{O}G|%hl3zNYn|@DU1|$k6f*5kq!GMBFV{z} zyim-2JK>jmZWH7Q28H+QsPPMw!Y8@A3p_?t2{Ce*%UK5(!UW5q)^us4Q<|bXnyk{3Tf>#3j1ml7xZbrQZsCbl z1gp4)lpScU^t{zD<#N0X-BpRexXY+0#-xI@T+6YKhPjMab4i4E7*K4ZZzhiuV&LmY8ch>OCN;I)1vGFx9NgFqh@=!|A ztRB(fZUW!?LLa!YF-2YsqoJ~SUR7r}`wl%F+-p4{|6*4Ui#@hkLLr;vnfgwKQq29% zYGOd80*0kryRrRSNW0vw0p6d%@iV-?3C;M8XmDTg;)gl?4bJ_O{|UdiD8eIdd4A-G z(f7AqHH9i*!o%k0bU*%)pUE2YlaqSwf1qG(4<>vF=(M}Z4alN(G5K@mdv*!J6lYmY(=W_=nYzYFJ*NQFgGkzy3S@Fjio$UCe4ZrSv- zZEm{rzgwWtmf)59uCtir44ZeT{Osd3pz<4&Cc$bx@FoI(>`PW>Y3!!AJU~6H<6L12 zATu5>)hDs~);#|Yf)=`Ytp0#g{z6ddrh@&=xV%eBn+1Q09tzDit0Ef_?LvTfI$sS& z;`VT8T!N`XsplJg#zd@(mtw0-!GKKv*eYjo-3^y-LJu{$S_4QV8`8r;h^lIYY-4`6 z$*)wESbmy_6D@g2)3ht^MSpSqFZx+}fIJxJ@BcmUpAz_gGm$`ri;H)~0Z;0j?Qcz2 zUz;O+w|Hn%$uG$$SUP%m>#X(<8rf^O4mL zm%b0tX&IRz_B$E(w&)nEN|pN`B`WowBLaBdc{3k!_l9q_n^(3T&Uamn0E^~+y!G|T z^SiGeyk{PN75KR5_Ny0n|0a#PKP`y}*#)LK4AixtLR!DfZ*6#JH^x1&{IP$0(l_f| zk3`B#pX5zXpX_ccy~U?mi3WUF9%yvKR09QwF{Z2eceLE*E6%CQe8CSI^p;q$*}tA*$1k*-S_=k@;GE*r1DirBBkwyq*R#+OSbZOt8JCxK$E+a zxRS-##a`uaoQD@M4+!ZWj%QBy`DQYl8pV7+;A|y8XtG0YRk7-3%y_-m_CRoWWr_lk zU6&mjb@w|eq-c_59KYdoK}@%0^I>`3aob5iR-!FGL*~P)Cz%%=PlA=8xmKMnLYM>O zdAYQ0h`v|NOyOLQm8sMdxBYIu1II8hS^#XbmkC?ATkuUgyj=P8NC22(Qb_^lxvgb^ zeK^8_QMKN4;APeK^0QnY0Bvg|ZYC^S3(E%3AWu4I^~geE*pB&w&=6B8tay)}6DyKqZ8u*`G4- z*il6b>F<7@gzW98&D7aN118l41WNRZPyAg7nFccb z2uHY`wymO)OC=G*4a0uB;J=b=mtA!AJi@OwRHj)r&+6E={k&N-sKP(R*&1`G9b#-< z>Oow%_^9|V$h+<3bmmD&Na>r*_7_Yn+;?DSOCp1MPMP}M!6k!HWH$w#^0_!^0k@&3=v2D6^f$V# z2QtCmz1zfj`atF-6(1zw1D;}d6QY#g3Pf{@v{@ zl;z_r`Oo5qYvMeL^P={+m|&(}`(laC2bQcuC;p1Ca{QxX!Kb1IeV4bbnw_)jjFC?Z z=@YQ%?ng#V$;(5cW1upj^6V751T34P&(=0eY(@MBM~@%Qhax%sHCR>m0c1Yc*^t3)i)Mtj9`a)kiRM=aOX zFO>y#UH9TQMQ=)zXWADqJm{QqjuxHIGebr&4sQ9_I9q6ZMo5 z9plZ(Xf;_!cBLMCEhV)kZZe1LjF5&OvAUWZaSIU^iNPMHHS?i3JM7*I*zgf5gz|H( zP*SR#%BssntJwDQeW{|N;jq(@LjHEj5R6-HC9j5fx;3v`QwCb4-3u~9s(!B4rfh}k z$DVuBRJB#I{B~O@2U4uA&=_Jj$bl;qK2^WGpHXYkWMxH#k-W1cakJycOoNL)sr7>` zj-I)ahvwsKmy5~{YR8)8q)sru%puy%b?7#@G;~jqYDZ?H^mLxRUiPiv_5FNh*Cf+A zi;LA}DtqYtk6#&4t=R(7?QiF%)=e^pTDJWW(B{ktqjvWGfc4y6V3l&1|MQEir|Juo zJuhG4Q+%CXt^mT=-Vp{kv(MUr0yG3AteB+^IEPL)5R};`ROY2{Qb?k;Q>$#IP@s8d z`-V#U=gg{A!p$$m09S{PzAueV105SNX&G*3?>&S67(4O;3kf@?%}}YIszF|1 zw#d_C$o6h{uKm0hPF;3ktU|DMZ1Z(??b*Q4N92ZTqL}}Vn<6q}su2zL@~*~IH5Hl~ z;|?f#nek4ormrWC2H6vX9==jUqB6zh(T1=HY-rtFl=AHyOQ3VYU=4e=Mn?W zfV889_7f(L#j{zgSeF|r84(@!zv|Xj(~nK6ocrg@YEqkpjL*%o!%n;jStq}n!+Oc zZ9t&v(NTlmj_(^?{roKV?g>15Hkfop3D)1Q#Z&-SZmGA}MHZEmxS=XcXX;(QtlYhF z0o>Fa`CD1k=o)`~2@|OFN3u~WGAzYYq*aT{_X7j_ zCO8cg6z5PThDA9;0}YK|RmSW;xgEW`63HWHmT`GJKZ%_wy~xtB!OaS3do|wQ?=*uV zzP3FJCxO-W_p+)adV2)NgVP4g%gfbg4(fNBw|#W;l-jAj6Sm~vy{)?Z@a~wQH>?|t z1J<_kyE7rayR$}W*&4qA%sZpQ={uuWiB4Rg-s5z_R_j@jGS;tASUJ3<`l#5oP;Dg8E1dQw*c;BbHL@WD3$WpcV z35HTIHen2dp`Uljp1f?%e4lGsBjvIuF4#cFgJNkG5Y&SFvhndqISp%N<8Z>71-0u0 zDJrs~=1j`wbp27OBSvqwT$nnC*IEi68n3zAj*fuXioU%!mU8p`K#XKsl{uC?#|ckR zO2f;vb#iiCyC+6q6JOBa&#mPx1t!Ja$0ghfl49j~KQ4z_)1yklto?Rf8J^0s8~U57 z!78NNN;_*RQhVpvvcw@NbbbNt9fn2@1<`A~5_MRo<$%`unkgN-Wc(HWZtG3TiWBGF zJ(ldpJhtI$I|CDFFq^B(PTLP$mY(>dy^j{V$^s?&kJA_l?c#Yc zWSz{}%?5F#W51Wub9aTqMK?IWp8Uux6Ao$Qb`gkb&I}d4K1$eKz3nDVU`UfarbCQ!L zYzx=jxLPr@m%tt5T|7U#{iyS+vEMP&j3SVP1Nw37eQJdTGB1_NYZo1kwURl zl`?2;p!_^{Z730x%hxgGxVO313qvt^(R#X@Ju?TAWS%f`%p#D9joI&Nr81AiA|>d3 zHQscw8)RKfeN^dkke4+JYQ)g5!N>Pav&l|wWufY!x)2>l4f;F_k4eXxi3-elHP88} zZSbR3t9j?a@ut2)$*G0r=jo{OXW^xQ&;wW&uT8b3vAUay#^HCRJ7l}-j2v)@PJprM zmV63z%$~A^cw&``4{eY2;1%}JWvIiLS1$hS-0@xlzKix|3QJAT>R`^hy(KVjQG{}RC5IKJ}lgxjWF%>8B`G-y} zPbGqK*AoWa=RS}Eic5f26fo}8%JA`#@KXqNDc-}8IZJ8S$ynE3f0FLPe~%ncAf0G1 zs(kO}Vk0q>Q!|+W71+?woLc2e~Te##tpT+0-yPP7PE=b?^`;%zNZMyOgxW^ zNU%UYkXdH?Zk}LZbH?6&)_1Siw8!n2rTJ#ap$*(nZNzQ6YuniP$CX^!$7Z!V#R79k zbPSkZ$+i|N78`9jxV}}+jPdXIYKqyc2eCA_))R@5R#~}awX8W)67LvY0gl2m)g$vk zD*Bzx+OuxGZu4;D#wSb781kWvzz8N)Tsl*3WN5C?ueEX&om1Td)r`?%&ri9JsQEC{ zYeRE~7IoIM=Fi4so$?qv$R~30lB%-h@(u8Zq+hU$b8~;QRAaIQ1t)JynX=jh#Cx8h zJ>s7&mb&q9=^LXITt&Q_5)NLa(0iJ?0RkJ`HzsvM5~7pyP%hB-W$BxrWMiB)&x}zCb&#Odg$Pp{6m=pYo`F>r|&Y|N9O#Gzw3iwXFl#8CJ=CQUF_y+ny4XD z=@7cO@JFtf3u-#B5yf0C3C^6S`WBOV_q*^b4j4=ve-|r1Ol2I=_Oqk z2@`B^*$@!2c1#e{NC|>~;#RS))4DQSg^}VH|^OS+e>BkOFd9W{M8{EqC56qC!MsC3a|BctYAallYT6 z4sXUupZJnvs~s?vy*Ef}&Nj2ClEcUyUF)J@)5&0ke2-)MUYb5nd#*Juv2pL3-bZ8m(+%!8ER=C_Ge{GQ$a_O5ho;R!>_imrbX=7Pall?B&=+X#j zTPjjugeGw(HL?yIL;{{P8sJvyE&tBoWJt;9hS~*%JPQq#PnE&S;HJ9aW(Lc7~nv^CSmw?TAUB?uv>bo3~ zZKBb|-Ku)uJ(L9{V#xi|X|sa(iC-W*Z(JEzk}CDp4R)?gJ*tbAlUO^-JIvQ(U>6X# z{?abXU^JfTbX|G{qu_cj?CKSnBC5+isej$mHUL;T0eW>|mVh#8)OXEOs?IyxhQP6T zRS1zbGv)I&8-{}e1NxN?;nZnCNy9$-;qgeKlS^FKS0$=TlG(kCF2C`YLmYEwmTbKu z2;C>v^ApZq(4z2a&gvUAY|p}(Gzii~ZULEz59#AEqrVIyk3$A}wM-iSg<&{!GdwXG zQudO2?yT#r3mFBEi5p)+8P{`J*sOp|<%<^!eTRYb9ga?g4JG^kvQPvr8`-FrEI2eG;y(IHYQUNYCg66}x zL()MZl2AJ0F`gw=*|0wmK%O7>qcjPCZuBsixV-bbv>h5T;XUA?I9pb2F<^UI%YBS7 zreLxw8yqL@3Wc7j!E3Y(-iC(9zq&bg2gB)G4P$f@<6CdMUMzCjdbaob5#=PRTtHt| zAAj@K*1Xz%oXoTB(N^Wt)H7NKEE1^zHIvfPo%0NiW|v?I=@IbxK>0;J>*r#6?9 z9l}p~#|ON$HcD#rfL;KkZokyZmoBRAv+RR_U#u*>f)I#(d_P9HGF<5}VV3TFz{@GXu zHkM&#(au(lqkgly#lm@oFz)Q7Jv*53$mIjG7iHwp4Ue2Tz*HF}*>{^t3Zfo_FmA-J zxs$rb8A*Nkf%>=l?|5~1zTTJMKBU=imx!olHx3i~)OxQ5(%wRG>ISaUSoeNbXFwLT zMb2b1Z#1~e(tLnsN&c$uQVm8hSh1$u%V0u1(bwjwa*M|U-E|b4Ur8C_Y(%R=Xa?t- zeSH_mGs5XK^mS?ddf%hv=0l2ePeFaxyn6)A4!z*;C>3c`x%<5|Z~oNBbNsOkY*8%ho@!A@j{r>uClooLohnjTkd>J%}7I7&Z z+}gW!9rKGvsnnUZdXz#YSeH8Hxl%_)(1QlqT9pDr+<-y6saM#%|Hz3Dz`lX5ys?hl z{2iV8@eWREH(|V-&oZbaCjCqmPhFQ4!pd2&V*Rss!j9g=i-~ZZf1U^e&7ZMLtP!qX z(>L%BN;SHnom=Cpmg#f2V>E*sF#(-sKz-&tfKWVBu&ZmM)&yp=kiL3MmQe&bcj+jhgFV6i^+Wzu6jI@^H*_puvkR&gP&D;s#@Fv@#0_n zDv2aX#275dAQ<7gVrE@aBP6x0U{ITct)gz4I944Sgoitn^3SNXtSs@7@Fz7W)A!RA z;oE*;Z8dsVODz3!{hsV!ghQ8UWW-|DjhNOmen@|rRj)f=i5&T|5R`b0x*B1Sns=_D zcuL_2?lQ!|D}vVef_-$GTbPCu@Ks)6M(3gO#=Ggm<0-S;qXZtRAyWNQ#U=_vn*QNv zh26O@&M?I5#28wI$+InTEMYjPs%4iTN(c9l)+%$tC=-X+>R5VN+nu_H6NfdaFe$!M zsS**T^Qdt(8Uq9O`!lhlUKrym0%W|!xNuu7?f!RCv)2lbv!chwgvxRYu{jb z-{AAPn;JTU7RT|zD>73LW?qXRRV1Lo0DP!MH)NMQ5~t=G5#_D)+oE1*=I>F{$M4=h zTCEAQ)t)~=&XZ^oSB~Z`{p(j4sMqg)zs_FqYs}cMJJNK2;W$9?&q5-(-%8MQI-e4g zOCfdKAjK0)35_RtlPAqz_cb|dGQYGl8y;n)g`d5jw{YhYvSR$`-g)$@+`6&C_D!5{ z=d#U{laq>w8~L0S!~=ebuxvn3a2fw}@WHnl%8cU07eAJzg2#*Z_YWqLyWJby2yeFg zu!VkJ*+g6m+L7`k9{qg@fif|z(LJZU%06UqU6>akjVXJgsvsknswmLdBSxxfUd>Z; z(^C(i)8_QZBr%((W?~J%LPM(uxA%- z+O6f&I*J!gL%(Wi;RpxHVb;ib08mw7F0t)1Qag(v=({*^LTdNQso6kcYeME1XqpOg z;DtX40t5TZJnUr;#_WcRTOXRJ4pZOn1Usn_Oj8HaHnCBjXcp%lL66bLL#=qW_V8Yv z+@$fyyd8Pj{?qAQ($8$+$vCg`Jbt1c3gfsjA-zEBhhMGEcQCQFbU9Z$z_9c2lbh_- zH!3$%DC;l4zkg#&a<*r(TTJG;xwCHb6dIh{1FOf_Lh9|Ot>A%hEf6T(b#v;1+DF)8 z>IX9gdfAofq%A3Ln>TtfRYl+Y)*Lc|;PR}J77>eJeFAJ&7()_-7VJ`qirWJelbUu= z>DJuW>kL{ZIsu4X(=`Dh{!uwE5h)PBR5dxuWi$T{yBx0-1KGXa1CkKa-wJ88W5_O$ zJjO+lqtcZpITFuJ0(7=Aahx&^9l}RT##U$38dhXPP?log=VUHN?uXXKg$Fn;1Klv` z{wD)7u(cve@}4>fZzzfdp7r#n3a zH|K!eCa`VLUpFzZt*QGcdd#p}8Ym)ioYB{EX?%jD%{8Z41<|@u)Ye`ia*+IKBM`JVS$T3$#M ztMyCf%>u+U4U;srVy>H+RF%880{w~l0dDQno)Z_1S!rq*F@(G_@0AkQ=j+VC1FCBb z*XJ6=Y59gH@N8$A&-&T%0Z`Tx?23)z?I2cZLvtncpL;cSol^TX7s{pELQO)Z*RlWr zHT+HvXTTdGF7FsUH3*Iu>PJxpVwDwliHg`(gJJO)+nyH$~;n z5_J4x48^q^Y!V3(+hcT$8z_KS>-sXi}u5J;KpD=dLEWDdrxPmYB?oi@B}t41O)LWrYxS zNmz+~RNaoNBKf<%A3j%klo5K$K|NmU?q}pKUA4295}mW{So$e-c!G3?=Hz+A+F~Ra z=fG+06FSOcmqn^ZVed4v$PL!M6QsW)gR;AlAQBqT`BvzO7uDG^(y9kk&SNVED!lt4 zF?g8Jhhxhs$S9ZIXhd9QP9|2*pY`UEqB`3vA|s93+x^(`j{4Y@@dDJNp7rSx8o_Y_OYlr~EBsPHr>-gHCf` zfqz&j(a}jf^F#=BoA_*7(A`HE8{`R7+Sivge)MS2#i>_2cxB0U^F*1F2|am}HC}*s z$H@|X*D`h-j@y`TXI7<*O-O>R2$EwhSN$_;+D;=_WM9|w@+}KV zdf`xI)kZ^G%<+wT>!)2&Ub+iUl=igPfBH@`S#`4F2su z+B}}oROsnE&%cBFDCidV>0<`dH$|`YaDBxp+w&b|s|>@!qhs^UoFEAld{lH(V8F!8 zCf`bgk%2w6V13b`TfIksSII2CQ5=r_QZv38j2{Qu<$enid~DbBDIvRPuaHh)S`sp{ z0}E|jx^ugHJ!LEl5R_a(M!vy}CuXeMY~!V^~0aqBfH`n=3ClN;kW)4Y07C zqYU&7l_-U&TIE^$7X;Tbpi^1On_hQnwJAuwoqYS`3Tuih() zsTVN7e82`BU!813zsJey*mByxnVyXk$^tu8AOr^5JSolz5%pchMGO__9BZ@8Ln|>3 z=bru!oPy|6ofy$C?dZ62-34r}NRsR=?s&jdEzBbV#tXeX7;RbR$1%Yv0UJ(@(T!uJ z&-yMF=3gaSL+Igu*4uU95&?dzG{tQ{25^aZZcculNSAZ{2eYzg+Hmul4={i%Q+yQC zhaYXLAKrO9yF zN0M^m+J1hzbq!Ypy?anCTO14MVhFE$;Kx#hutKT8dEJ)N7O#zcS*9VH)UY+?H7}!D z0;~p6)23?<4DR6V&QdL0Ihx$VgKy~=o%f}$XG>$tb_W6U!ysy#naUf4Z>}w_kg1AIdq3NjK9CLY+3rmL4wEf zxxO({j_i#aO|kYIlOFUP&UoB?sBJ>4q$TIhdQM7vWft5KgI<3d+8FCQ5RVHp{^Yh_ z73(*g%1X#`ADO7KTtE*=hZ?i$Z`Q2d4v>;%>QnqNkTcaApXN03#VIcNgKE)JiO)H{ z36kI#=4GrE3*WEVn-}QaCqHobVdHN|g5Rb*)LV=}-WxGcyO~o2@jCwG>5I-wk7guT z-t+S#JH2zFBclIqi=9&lW047jO{Zfv&^Lxhr}@v^>a*WZlvVn6uoU89U;CoB^Y&(d zQ12Bfzn!%f+&ED(sz^kJ;r{LJwg-N=@Aa;4r z9QA+|^F!N;0`>T-Y68y|YPNY4;pur{FV3yo3^%ZCx2Gu&Rd|&gypm&(+S#ny1IkHe zHJ|-g%Svz2F*r8&gAS|H9J83P{3W2C$7QpqEwJ88`UJ7wzFIAQY?gGfH@BaAAOo@nuluYD^u%X(Btsnpgs_b z)YK$Xk_w0Kdw`2#p2*0rfZF5TMHSwTh{3+`Xoh^*TjO-In?ry=mo__K+ag}1SLA(r z=wlw@0$SD-E_H9Ck7*S2-J+faJo?MCj9KwHJGh4}KBQPkd$4JmG&01GI~~n=WYuZ0 z(-Uxqh8#u!recUHJq3IN{9| z-Db`Rlr;E?Jt8kg?~`tzzQ=Npw=;4BtL267S0*J5Uv*3c=R1X-gRmjLe9)w*T_9Xr zovuN6^UssK!=w|^AGk3}`FpGU%7L(pwUb0x_$RtxN*`oVjdIq`xLK|osvlr0Ze&<; zi%y=fIBzXH7WZ)&6&rALfvkMUt$4b=5@j2{dPfmDqS%7p>m~nl-0BzR^yiM8A*&)u zTG0i^1vFRu`zeS$yxkYeSdlA8>oD2EYvfK21^5p9~B|8^2i^QvXC$?<-U1*Qm3DnxBN7awR^yPr}V>^RV5Y zIC|jI&1v2S>5e|1FG+N{&bq}B-*=foEII!l0e~F z!Qtg5HufL_rCWG=ieO^&&D`Cr%A^o;Kb||MDkXzyU3$xNpCQI*`G`&HS|#SpQLtXD z!Jt8v&IN56!92apKe7|5Zq#_g(+BpFnl!Z`uAUF2L7bcxXQlhOhnrNBZ??k@0N4P_FAn|}u%d1AeUw~A>E!(dav3k>KEHJT z!iD^rZ?O0_vL=@N-8lF(%yqELos@nqZ?5_xf%@!l_&R&z^Yl652Q#7LS0kZ(MxcRR z%u1qiHJ@3)?*7K+q@xvaNkFldswE^NuXe3gF)2tqYv`J}N~4jnFnaJLyda9Z+#rgp6IyQV0{{y?~+0P!<;kyzxo{C#&3gz!LIcl*fuaZYPcofQ+%Fdb* z$N^y{(mo}hZpQhXzJ<>YQX0caw$xQLANly5*T%5(d1dcTUimds{q^_m!xKMaV^b}6 zY#KS}fT!PfLW0}THMTVk1D&JvjL$|>9@uH!WI%sgpZH_6YFx%35Q3<8j4)ABW9Jc! z^xMsRuW>9elaF*|W(qH}RcBie)nGt>>mrM>Ft@%#$|Oa!KU(g zDl6MdU!$*yT_?O3Ne;15qrq}iV^->stkAUh^BbPWY0$IuSgGNk?an*Hi#Xu`M*U;@ zE3R{sHT;jCnVo10)+4^jj~ECTd*bxA=T9@WVqudaBCt~T@S_xvWm;h!iA*`_;_#hc zNOuWxii8{s|GEBI9b2W04U6AtdENAI2p=GE4hit0B8!W=#r$GBWr={j2l^te>!SR> zT8e=MDWWeEoOSQ9YRAV9N4A#ANgIdwdyVIRqO5W`%TXv_ly_0ex0#ZHO zz}3T?>}xWXTRY|pL-A4qw&zu6dr^5C!%=6Iy=H5Dp2%_;WnBh8)b)L`SyOnxPWeV9 zO?iCd!|s_`;wjmgawa6bnFZ-_34HN6bVyU@+?92`KRR0LuWgDZ5Mtck9}r%l4}!i7 zhwca|HVA0PGelZ-`j%@AT|0ia{#U$i3`7{K_SMixC)r{1dB~xb6slyWvZ%tyxDUO( ztpm(pTBLDGV1C*4J3lYG{ei*RCRQdze&9cHpLpi}ZOympc;K{#=QL0QA_NHiI%5bf zwOe}tJ_4H62k3}Bct%uJJQxjYAtDnAJm=QsA3iitj=sEMxz{7`?5Ua99T07SeF6kp z>^7))@dw37p7U;Ox)-q#i@x$U!U1?zPf+$VhPb3lEgg&@2!`Na8Gt15m(G%sON7R^o}Ln} zM$qW%p22wBLXQ=b#PA-%6hv64rX@1DX(nQre%AgOg++FahGoh=es}T0JNIjG=5zVA zEe@d>r{niFzDV1S63?xRiY-0&xuk3%pVXepee+TrD3J>&1c-#`o>N_-+z8og8@Z)n zvq~s=ePuWv6llrgDPm+8FRQuz>0Zc}>y7O-GTjP1u&5%l$afq)##G8 z;HWf*;NKyu3c5NZQ|ZdZ+q?g$XmKm4AWkslfmHe6!&E$JvXW=>%cR?JVrHp(>0|zK zYvdVN%()Q2;weo&?XeHuiauYT#@mj|ySuMRxODU+=9PIyeu@N4>Fw65Fj;sP7P+!& zLUJa`F8W-td0rH~W;y;%1|iat{(8Lua6cu#$nJ|TIkQi|`n+RaZ12<|@fU&#{0&6| zt4xz0Y+HGj*p&B8#ydBsw5nO1Mb`({)-Rj_y#j>iq&Vqk^BEe)V!@*#RxxZY6j$Ps zcB5AIJx%MzY|5VaN<0nR`o|LY(a1+Jq1Gj&z6|U?`vn2JsvTUVl8n$!~w04cCq6Fs%wfTw}9sjL_g}sSNQQLKRy60 zq!V~lsGw*h#=&pTYh@7d@ zxyx0$VE25q+iu4j$DO%~$w8k~wc*jvg1hJlRtB>dzsGEiIFW-pILIeP)3#ZEsdQ)l zM}^N@$738BV@K!Yp%pc`%Box+Y4gR1R7uSatQOt#Sk|ZZYSuz=9=q%AD1A>3lKE%Z zLmlp^D$@|8p!4Cq?TzR_rGEfZo6H^&{aD`Z*#}ZluO9f9Keq1I0q6Q0WK%_rVs6R_ zxT4c%7R$Y99)^278$3GktD*sz_prRD#j%qOVgh(|N3}?dSiEFdQnM56QQzzR=T*H* zq4Z3?ejwqfnIBHZBwtmOgwleITeOVLJox|8j9nB;u!d(>fB7Qm^;!yzroD>C6J4__tgNhpe0&;LuU_@h*3|_^$H)7%T_Dv*KKLCXx+K81G#khNT;y;7I@>UQU_2&)R zF%=2+o~?rotju>&@H*GtnDY~$5WTb+yCJ<~ zkL97N^OuB7K;V=)iVkieCg@+)`mGhmA9G(SB&b+pEisV(ALG*9s$c?hj{B1w>lLjtj zvSg9vO8)mZ=?8O25*(h*Tx9i%SX*1W&cNUo3drHE$}zID`}*U@4^GX+mGY`8$)O6e zM*2MhHEnXz1a8$p6RZR;-y6Mf;X6y_`)0O$Yx6Fytik8!fqbulZy3;uRek}X4@X%% zqtK|mRqp}hQLD>uCxlhD6qmphsJr)B86j^z-I2g${EuVv8t z62^*Nk;C0g0a+6Zn^C8YOe5wpS%*VmtI{nZYGqn>_X^3M!=rVco0fY2&ye_rzScP9 zwwLR=eq2FYyuO?st)Q9LCw_+}w9)!`r!%UAo860ZG6MX$c75#MA@JjhS%JmlX`_a2 znXN|RPk3iu%a>YkNDA)m1^Q3Ex3nGU&0-nZCKQx5s&II$-38xXf471CA0pnrFV*j^ zi2mPY(_eSL|KHW(!~cX(|MSMX*uO8{{J#%{f2<74@3x7EijE%hjUp5j6}isQXmtP3 zkgk%F(*B=6ZwKXJv_7y>($WJ93k$NPrrO%E_E1|`mAF;j;Ua$5CDS;p&f;X8lEc-$ zQ}Lz23rlMzSnCmX0CRwk%+9t>fQt}SWGg~FS~rs)VhzY18pBvot5`6K(ZNb_;z*3O zBQI>Wa4;%2=KtSG<8pIH2dJZ?LlNXe0-DW#Eh$llLZSQn`#!^pfXWfX^2+O5{lT5Z zO-&ZEva&Q??a%+M#_*_Gxtd>UsVN@I;*0K*mXVnn$1*-9<5ReucpB=`Wfr1g(;)7}5MtX*zyYqR8A&KOB8XLhrX_8&TwOeHn3~m?5g)qi&${H8amAbrsiJv)-cB_>t^FJ35!e*7W zCAXk6K^^1y5>j3-X#%T_2fC%L|Jq4gcQS&Tn|ru<-F+|ABGX42Y`odSxpva+I@h+L zb&Y74UrJn?;M@y+7A6SW)@=}&-b+B2U@HE+wp-6je4)Ujy^!e4$fK;5m|fb(Zx>S# z;r}-*vA8Bdx~L~vaVEV3C@A6f5B|~Zk>2t2<>P^YWN}y6Ck7p((0oXbYh0jGni5(W zIaM@6ovHV&6yMjf8d$OG85~=Yg!sf56|NoNtb!e+*xVhKt|9h@zOgQ1Y-`}b| zekcD%@5TN-g4Y)>3?vAU+WqpW0O0vNK;pv4fXQlP=OhEhw$y8oz38ni-a4ThR5}x5 zw1!VBM=PuEQD3ku?-uJZE@Wpft>B&TJUUp6hLERW&I6#L2sF((@Sx3l2ez5dq|u5g_|tA9sw z_ZI|W46pEMbX)qFzOHW@Se7sRYKhyg;%SXIl_)}<1e&kAGbJ_dp7M(`UU~H-)8SoA7VYX7Sf9JzUVb;Oxso7pX zE9oS!vrOb5twLZ*)w7|yU$e!OaqdtTC=pV2m+dX>Hj@FgC;D}^xYBWJ$9bNR0Nl-Y z(A~4jG)%2S{DwR8Te2#p8*aV)E_`3UeXn0TSo&x4@APs#)Iq>mm6v{A;l=_~W!FQ*pn+Jd=PEj|8>D|8=+Zns z(VJDLP}Zq&VBhGiFw($ri_^Sm3o-hz{`c|q zQ9nLu7{~QS!R_$QNvw#O8)0#G^B}yVC^F%!d5$!qj0%ZGy6M6oc8g7VKIb+`<@-|l zo24Qc7xzWe7TlRKAv&tFGPbg!ftVD&{!@xAPI~kzUr5`S`ZT+c^-(z}TnZ(7dA&l3 zc_ga84n)YE$n$~~yHayRF8BJ?tu()odLl?(jSolDyJJ!3StsQ0OpJs?R&#y_{G(v1 z>V&hz;`7qnxxj;XuHqz&a*6&uxWXh~jm1$F>}2V2Bz=(k@INZ-*)QoCNRMgm;vF}R zS2`ddD3I>=h_WS<*5GU13^5u(!MefmklPXG^Wo#LT;JX^o?|*jOxr?Rsq;d(t^PSh z04O$ie0S85Hhy7m)Lo8H=c6Zi&rlW0*n-&-M)Qw_;V>79GvgXdYDH1<8C$Mj@(KPk zvl`4VasK#il9^&aBGmVc`HA{Ve(yJhbBdVqZ$&0+ro)c!SLCKw;(s1I3paK5e}<~Y z?Nncs>D!w#;G2CP>X>7pW)Tw`XHm(E@fStB2** zIp@LcBzg#Knh2>w=SuP(s~~wWQF!w7!JIH_u3ud*2l_zq7P%J&BUcCyj5nILPENl4 zs(w?;z=)Gea`el;t~NLtICLPuf?KWZ5Y|fiy0l+|EgRu!)($vdWC?47KY!v>p7jAd zL+aVjv}By=t+P8 z5s=<{FUm%mfC8a+q$NP4*CdD(rG=KzK}zTyLN6!Vz4z~Y&u{MBnRD-%xifcm{-Y#s z-u14vo@afY_4zE0H7ke3V2DirWt(!4ewF%>Ou$Ro`lHKrGf|TI`5C81vOezUUAz#Y z&@IOrfzq_{k8fWUY1v)R|6_<#;ldwWR=*wy))e8p8(x^fHzIlJmS&sFg>_u^uIn^6 zUS*Irey>RV5%dwe{Umc#O--ua=Q7~yq$4m3T5omdag@K*KIFNHZVaHhp4+7uu<&!nx7AZ&p~aIjdyMTyn7k)qe3=!!jg zblF#(`}h+fPlN33i<$LmT2i8-$lTKBBx_BVpUS*`ME*l~<%*$fFEh%vuj)O+{Chb_ zYO1F_qFC!SIGM^;L}5=ItnB;o(R+Ei^k*Pi4j{hZt#&+xy~oEAiLjZ-D&<|v$=ynC zCur<6e}gVZDmg z+|p!(J2yJ>1*lfC!tUp?_jD3{g(LLy4V_UYXtl6#VI5-331p&^iGA;fCN2_l12Z*h zYip4Ob!u=o>L{{nO4e>(-zk#0i^JEpcMKss2=s+~CfSPD!y#JaCEpc188&}72Grjk zmh>i#o9V-5^FzZDtct?s|9CKezR@Xd#ZzS6inDJ*;S3*-c&l(-T)SLRK^#U|hoFfR z4F`ZATG?YOcKT=7faRYYXF2MktMsCOyqG5^0Q;kp4@aleBRiWm-tBS3LJL@rHmfZ} zU$as_;|rCm;-my?QTK4(PM1w(7LOh+UsCqNO=FY&>pMKZ(?XR}Jpq%Gz~W~RElY|5 z&-(oEX%opA6|a@rjbetG2_HDY+HEd9tNW0x*=K*8Yw zd5=Y200$EgZ;t2>cfPBWGVnjcrIsa=#ho%QDM-LBMnYa*1?b2|;_516!jA9tYs4aqO zA>TiUzmKl^L=}5H?%{Uy7Iv}3+u$0+ez49!%Y2~-BRKIx{{S=LwWfJO08@E_w-1 zTCQ|Ipx57TJb%&7TL*jCFJEV4Re0Q{+DkN=P@YW6;zdHZIZX2>sJHq<>-h+?51qnY zN^*;jPoQz7E}wOveCSQ>akmz6iRC)j;weN6Z&_{Qr}nPhdO1ynQaX&hGhLM5Ox-L= z_ndYbC*fR!|1dzwjt3-lGthO=O)k90(Bh`F9r~kB536JXPK-|`YjfK@k1t8@lY9P* z0kTi!E&g;CPSwHmz4QV34jgFu(^Ce~kMpmmU#8BU)?&bsxx^8HQ=hu++IqLWRTp74 zE$ib_TVF%`lD_Ago{x~n#hb0Sh3A|z;lPh&DIRQ60ILmN;`)kHWeQ?FG&=W zYs+BkDIpdme2snyot8pe71k4Mbb9bGHd zt<~a&6!$GDu#)kIIZMSe!sXS2{X_0LSlKWp-<_2cq^3~Guw?D_KvrefJmrHz2=~Ld zJCqX3v#o+X<%e=oqWD*%>4fnBPkr@<$?VS-V_&chXTYxT8#)CkF84FF4>itK%-g5d zvNnD^j!fGU_VPNggcyhICP2jLDWc}zwz^cdN9Al}0q1l!D3{#a*aT~%ydGXp7i+>(F^%b4O zfVPm_(1p`*6&4O3?Q$vtq+QTDaC&C!El&Rn`J5euLv?GpD=hPxjh!45SyKwK)>xcj z30Vyl(j%bwoHR!FcES)W=kjB&C-D~q>ek*i3-&3$1de#gNnxAP4$ zNB#Y4yBS$guN-K+s`xIt4*v|D&nxpA**jo693GeLVOIAo3a(ck(17Jq9@LY0?swMK zZQ2{{R(jlEeo{W%oc^hKWBY-p#~Y}fa@MgDM*h@7!4DxFw*{cb;uB8J7K0O-p0q$q2klEHWstlXSO<9(_YC zb*4BjgTk5|OA~ty5R~`pE9QzpBg@R052D|+yi@=@ekNz;<6+a*`e@j%9bUhD&2O{U z!rNFrD4RXK@P1JC9s0LwzMb|~_N9gHgNmza+zyLFw9{J6;xpB6fAx+qEBbD0ooXEjew z*CXKicZ&SKo8F;^q22>iDuz{uBj0UpUDK)wm~Ra)`LnhoC#KyxEx1JqUJ`W*U0>(a zHvV=Fo{u7AKgqBP!d*A??lr4>(7}Ta5hkoB-B?giLj%6{nLK&~HB@{Bc4i?J-*8?hF0MVA!mtYBvEp6!`)a--#*oTI$sG;CK# zTFGLd?TR$xNqxYq!WusB&Y<(TT*=Fe4za;ns7H_M`*a0%kp=zBiVWcX`RMS$R?5)R z?0C5157{yWV0T%On_BR5HoA<&FW)}PM8#xu|K$=ZQ}lV6`=1%6F^URD&hRR;dXe=J zRBHTlD(sHY$xhj83Bh2=DBVB*8976pbSkcN(aTF2wK2G%M{m>m=}L>hFUQ~Y=pL@V zvMZGae2J#FV)V2q1;>)7+1p%Bmivgu49NO)bO;*AU#_=O>XkA3V%KZb%EPdyGGhl=3UU;XM1WO|vFwl>tn)RdW@Lb^+NU!N@3 zaRWmhptQBSHdg!^000aO41D?VDxYw84Fr-k5ResC{p@@t6cjsm1RVu~Y;7|A z2Hsxcjyh*ZK8DBcBl!}~q{p$g$aeF{z5%4UWsz6mc_m1Q+@`j_Ux&8B|izB&eptdmtXLssj+@$3!5_PTUZS3-7`ebQw z3sSV)O3k>e#kV^+g2cW*<+!;?uH8ySnwq&3>zGKO(Rbd=US!QhA%o8|OG1LLN>3FA zD?RsrNEcw)aWYEV{8A8?yc^oeU+FpcIL=kSl5lEvnS3slAvRsR{vchQX>-iuCXOS@ zb4@aIo>oa}kGXj}j4l1>#`Hn+Eu3En9gctsti8Ci7z~x0i6dWYD*T3f5mTTOV&?8^ z$0yB#23I$)LtaRIhu_5g*N-MGg4KaCCyv)F|G@^y(D&2N6#oG$(*HMD5l5kjT3WQA zU@frIF*c0dMqxV8xe8NVZV2Z+a1fceTVn_;KpO$=*AP!LHeILtO|(5#B43=}{W;z> zmwGKVxyV9ZNJON4a4^9_eumgl9-42C0MAG$E?r+TxlGKFIY98l}TF~ zWN5^td+}jrt>$aqmhh{3PiXco%^OfO{sa%+%biAC?ZyUbXXNMS$Hc@iot^(}gh4#x z)i?I%sQ;%$_}>3N1;zhQy|J2{Fye=XbmueVaOA^Er(>vr0S|f6zepaoGdeo@blvkm zlL}XH5!j08){TuCFv*hunb8;gWYaLZ)k|ePehld@&((XqOGQ_AxuErA0cV30&s-{_ z1R$NeuY_w_>V`I*AK|evTBl6Rg#!v) zy9Mmn*~ef{-`P$0HP}@o)>Y$?0)qoUw^#;g^z8kcU*g1I2i`T61jBN}-47B(b5P+3 zfhVOJbzYtles7gcecQRduABgY6#G@CZ*7ynABTx)J`NGXs~%s zU%^&AHJF{3Y;876K>W0CiOKivI$|?D`I40?(d``|(-B}nM!C_*O7(|Ejf2bkfFFoNc_*{j z6m0eTuG6)oXhM-hKWY%4BJ<#p?l<<(F`s(MAQgnoM=dA(g?X5ro|6Lv=#<_Lur{k} zkw2ev`_5ga0t){5>zOp&_uZpFQx>e@9jc+D;=D?2}CiYzLMOGz2c zVoD|Xt5{njz{UExz!Z_6|8=sndA_IrhQBcg3iaWq>5CyRwFSA!AWjjp6V0h&>SPad<3Oi#|1gYhdpDiOU{E!1uhh>EYHk@R?J_3_UnV zS}n^%50V!8Fq+=2!w*SXxn|zJt^LL|(fo1s;!bpRq`CH zX;ikDj7H)bHP7Y7z#i4wheJB*|SyXD{#jzy&s*#=ctzmxRpYY zeM@vw>>7(S(uI>!4LSj*(dAJ$fJZwmF{BYt9I_#FlY#NcfmkvuXsg<;KP12p81aIG z^I=olXD0jNAm%xjFG%B;1&=OYVu?bRAozOXqrnUFq75aoWDMIZkC#qni&aR&^akvE z-(}sWDadO78kNFecj4xE%QGbZf^_xOa2gkaO3F!9!9z9sTbfG_pw6rs<^HPMT+ZHq zsM75PGOQlIiHHwqfDC`XWEHr$g^qGcqu4OB-KD^b?7E!d!R1NH6;rj7OJP{qY^)UN z!-Qv!8{i5{{*V1TPskm-S9hKeT4EnQd>9q*`|v7o+1koV69|lCJ6I;V9m4>+2ZG%5 z?gE!B(32)7_XPhsVkfT)^%%qjN4su@T+AW4rzsRD><=YMdl$U8ja$gM`pXZ%NAnrl zoLjd~fC}w}+XySOBJ;|0YI)^_1PJ;vz~$4!TII11R?TT1%Y7Yl*1BD^?KZDtQeX|! zO-mpc1{e{rRjO}pkX2air?j2d#+h}jXJ?a~m-zKT@Zp|4)qcnA#)OUF==!}UtBtQ$?9`GF^Zvq0 zlNhJ>C1Px<=P*XzPe)-e#wiqqgSLfmOZ!-2)*uXre`lN{EZ(Ai^1kzUNf~5rv5e{} zmDuaFjEoRDi7kI=sEM(Hr+b^DCV!ZNxZN5!)?rVX;F3Qk?x2m-hQRqeGdpd6#XRvoj7ul6GxZt51A( zrfKUd`K>dxE-6}i#tnzK_wTKB^z>JLqhh^}+`e?V!bsJzi2+noE_bm7xRosM%Dj^7 zVZ3c>6i~`v`oyA9?)7)&LPv!9oirP42`b=ZS;A)8G56)ZYq_+aIMgud*~C#P7`~^C zc93n+h5Vo}{N4FWK@r$5Pc9V>M9%Sjr?Ph@@>IVEz*qUT4DEs$ zTs*84Hr@nBF(5T(+N}2fAj9?k6^N=8Z3U}JhBT<;eF?OzwaP$TwWj2YHm)%agQwlY z`EQwZt95_0_nP1+@Hc=1sfA(5LNc1$IOV5iCE8OM07#NvS|p%_oz%Z?bs}tRkZqbA zv%nv)cb5oBB6*lIR=OcNx(A^TpN6x<79_>e3i~<7m;=MLe||8b)2oi;J##9 zHa|XT30Kc@7dIZ5K$Yyj*Bb@9RqChTL@v$=s(K74gtJGf^)zR_3%`F4HI>uZa7&XR z@iqYE|C9_7rU>vUvMIH2a`9+9_vrvx*|^8$mK3O(!QlYbn4-G07DR!7+nc#T9T2w% zjwLejX7P|C)_&}?mIMig%9g;p?&d8f+#uZVKAB5w-R=Jr_of`8E_GmIRrD-lO0IOv zrZXNIJ>*Lc@>x1*jV>r46VX}J0NE* z8!bk$%6%@*N6)#wD_RW{5V*JiWOkOzlkb}PD(XI0!zv0gb1ze1zoYmj35N6PH->QqgxTYiLDW@?|j(TOC7blNZTMN`<=V?@*>9`gL9k*T5LGYD;(BpBh zIe*Ud3%Z^@p6Zd?b_XUY6aH3_>7xA|4)%S?D~cd7Ku37cZ99J#>{i*{@^|$rv3Ree zSRp&!cvU#U*CDye7KiTx5=XWUE}io$WTHp5WHon#kDyAIov>1U{%EjWnNLaENwtF3|u0;Rg4 z$mIBJ0P###Npf;BuW8IqzhU1LO(K}^8r4EBGpN8T?XzTH`|%Tpp78ipsW(x)UDldm zW#Bw6mlKiI3G@h$gHd%JzP@rTeeybJzK2ppxf`Nh=a(! zq?=^rNraF~!4lCa*ytj|=}#E*|Uv`cR!r$BX#z*+YKXcP`5X=~Q(^E%H_ zN%lOBj!}ezAPC2K5$Qv$^hl~^+3Gd_s~B1#JS8XaL5y(MFljaas>>}YpR=nE%B#tjgld!aqQeo%PnuUGGTbwJX? zN3>`5iMBQjO)DWW)~hgBcAT*>)pe4lp~d8=?#zBAS*6i3@|ELYXepO<*#VcS#pj|s z8&j-bSh*C#XK-a1JU^P*< zYEZ}etX0Qvzg9&oO8ZBfDvRNN*qoq^zg6LXDwF6M>wGRW7T>3 zV);w(5sXVZy+hg4JBA}QURW6z3_)To?sdtSweoPvs`8IP?6K%0gSo2~ljz+oi6thv z7PD60^HWGo0pO)Vi=tKD-Ux@)o-!aD;2<$Q_}vJzMHSiSi9M0f0OzKLv(vh})2(dd z6S;zfDq*=&%PMd^!egjk3WA zcPmd$=8hZDJa9L+Y9Vvf>9sK&MO%J}SuIv@fJ_pk_?M6-YN=0ZRb3rqy<{)A3NiLd zTT1EBiK}{@A+=u@Uj)rNWV7k7enZ#Hh{bUwr8 zq)mM(l6S5KW+h6r0{gv=-{tcH;!3)};AOgpe+5Y6Rr2{@s%jO3)t<_sux#2l=(5ItdsdWta=kwF3(b+nQj0H|ohB(lJEO^{^?92=mr}T2{)8&3k@#+W#?l zLEF=o+|>mx_>wIrE@{`U&ziM=Pqu|)z7Ub61`j6KRO+wG$bEk#{g#+kj~JdP%5Ku4 z#iobT$h1;1Aa#;T<y#bB-pCv+f4C)=wPoiHGm+Jt~HRGKKo7bx9h%74p~# zrkrJe&&s>99!YDdti{!nD)`en_7)sgSJY4zh&>=sjBn+yF9c1h_Z)nGPnRhLFECiV zwY}39k+5{Rp8-zVNToxR8*H!zXiG zY}l82WGZL}YG95g=gzHrMf=UqDm}pkHDuYZmW%rM)S`_Zik8JdcfN^2*^{|I#nWAL z>C=+RH0aI|@>0Q+2kTNfngnn)xZ3mlKxRBYH-&9SMH>@cyyeHHFF&?Ka{rJcC&%AD za7e>~r>r*2MV8b}sABPg5zpclErWs)*7`+Qd)6WqhX6TsSuu4BrQ$(Yz|K3wU8ye_ z$JJ-sT}!G2#_thCTG@6#&vO-59_7wEi6c=|3^EXH)Q;E+zG0^^m3niqwqta{p;fbO~7+@YljB4vf3&c0pNs^>-`t$Zwz|iqQHsUl_(wKTI=y8 z_+IfXhPw;7C9?t7oVW2Bama|)mY=xMIxgogx0MDs&2>JAti&+Tm+4I{Ika#{c^fm;4eH)cy*U**1!}~LbO4oI(CUt5%&9Df+p}c86#rSK81H_3NI29QPOLd`3VnalwkQhW zu+b^QjvWPa$#kxq@zNn|tu=#EQmokK(0N(9GNU=KyeEyd6$k+X^nyc3JtHTg07sY(8Yj5vlbr%~LW zvgu|$()}HWEvcWLym<4b;Kc{>Ieo){1lt5mQznb*I<cyU zU8?;r2c%fIO4cWe&9uf@j9^!_%|c*VRi)C6z2sgQyB1C+J#$R1iUWoSEyT(?h|z4D^m(=+k`a4FscY5P*<0WH0F+1eI3%O~uAwQiMWULF!)uXk2%Xad-9L8^5 z?PT-%aDmg+F{ZVIN9$WF&#HD#a%>RYg7FC0yVOY#^4=W zyefT?CiR}k_)OP@ortI_1Rw3rB1%eh{A2Tx8RF)8K-RwkVBxAS{(>)_VGHyrE%)Tf zxo{Sb+_{e`V4alFwmL8Gc2TR)^IKaWEI;H4HG$?fqfV)562P>9$UB(wdPawhekw$sUr77udjznUdUm4k1^#zWv9xD z#GmbIUa8)0zvia00%vtET0jcS9mur?Fe$|rFcO~^qpR-4egV+ws|YnkKNE#>y|D}c zGR@_jqaGg7f7@>-hch;DwuyFN-p^1a+w4ju=|Wh-2z z-1&U3%C#DZGo2bf9&>1-LVLk3fdzFTGRiVO};Via8Bz< zZu_&*bRo`H6Y1TnEVHjDl*kh_p4J^R_Pce6wl0r!(8f&<%ADizAdAv_0yp@;Zszea z!}`5*2dzNBPn3>37{27!a3@x?pl{l{?evo^`wc`~X=#h^GydR9%oA-KojB-oxZ742 z4=9i8Bim&gWl-v9W{lsOa_Fwi@yc9KD(P8vp*}D#wccepPC(#Qdb+v4Wx;Lf6uP7U zIpp4ejjD5I6D80K4P>lLI;g)E2O3@prR2_n8G@0WU0SvU)yKXP_e}Paw?IR85)IkP zeW0|XL}EK%fu?mK>9Ql>C&-2zTUL&B{EMBwTB}f{wV!*&|+&-`3_NsJGCVP2g{ERJ|K%=_< z)zU-#=TW7hQtjLEs1jm#ReJ08{v`Uu{ z@G1&o*Ew17`rb56#ujNpqYE_VCs?~zp2vC62XwG!sGg4I{Hj-VY%3gi24k!%Zxq?rUKb~E6dwZfs$67S>EfTTywJ>u? zUHb+f{k@X?Ms@`eh^74N_lF9e?UUBJ@7{%r5XHYYf6MO{8>;g|iP-WE%%$B*9+1`e z{9FlQ`^Ka}F;TQIa9re7yC41Qme`9XANQ5IY5gYlo3T8x@p+JuNA42-M^ zSAZDzueQQuMS6$y{EUEQN$-jsNd^h`I`->V1h}upJM>s~p?w0M$(-e!x_|eoTc<%S zQD?xGWA0PN-5D0`$EI04X;!P0_=-VC_rFgu#p|L$9VK?uTMO=64 zI&puMBjV^+dnbmQshN!a_lqN0{l1K1PDA+)x+J7$eX=kC;5fyX(AWDnbFW7a4z6$X zx?sJPA%Gup{SQ-Q-4Mc?k(49k*m&h+Zt$tH+gfyaw~s+W!2C730E;Mg_4WLRU@?yuw!W#pc5B{; z`DcWS*r7}sEpE`N@9L+Xw_WuWSh4_K@5!KS_I7u5)!zGbE?do=)qc0Ag9fEZ^Quat zOOZmQpP8IqqW8JQDvVg3R*p=Oi&i%2JJ!K^autfItVQ*zObrVkgUDCb-^0{FWUxk= zwUoYe{hG8wL`hTo%u8*y1m?W-IXyShB&D*=CVudec)~evU>+f0qkyGm6=3KFTHYzQ zxNB8QayhV1%D&J~g%mxWC|dRwJW*y0`3O4Owy;zUT?}jR6?WZ`T0Q(FF1-;DKsZBV zKu^}vt)uScWx=_>WI7Y6(=xNnfzqCTZxtxy>{6KDF9&vEkc#n;!@ zzYhu`u8yyr^KR48)FdlwFubPx+Ay#j`pkDZnn;}u!ZdQf6+^RpP%+nKq!gM4+ zr-PQpnLu!X+LM;PsbwiW9Fi+pH z&&FVR6}vD9!Y!PiN75@kcaAFT3K_|>VGj0QpA;`^Q?%K6e}`Ji8OywlF2=qs=H>+h zBdW*Fzo&C*_9>Pq;Nk`sRvX$F@x(cps9qkm1e@BWwQnhdG`Pjr_I=4`E)l{6WOmi- zBgTf&0Fj*BTD_|9XRFAq7}zJ2Ng7VGN|z|9VK=en*LFP&cL zWM-Qb%|Bu-mAy`*P7}=0%n9g`$E1tkAtDH&(Y(fo@3!{J(u2poNiA>3Cy{ikQ%E#m z=hXZ$?p5m|7wtD^6neay8fe`PBI_DA<#+izx9nDFkZ57V<8n=2eeGhye)z>1!e%`Fy>^u8UJ~vq5{W{16lHJ%4=X7X6}UIw}Mj3%JIhr#25@jub7Zq=%AF{8|%>AfS-5*E| zz}e_DHeNaKs_V!p)CX0P+HH0Q8?VT=J65 z#SnJyGR2Z%mIoL0$FuPCgK$nHc?O3F?Ba(H+%h9YDlPgaD2_`0H=)_{hIuZk&`T22 zi;IO{zC3Qj{?6i!Zo~h<C>)>ZgvQNvsCzah&Hv$xH$Ux~&4#lNUnyOugn=gG z-_1vESe0@$zjp9EyJzo&P4c^KW$g6CL|!yK5I-;p)^j_EGC> zX=-(`J>!ob(u)VmiLp&#Ufi735I6a@5-#ziuCtr)l|@q9tQNYasa9K0jDs!-)Gw=+ z8hvapQEI$pc)sdN-|eeH&p)%hOLUFF^zDtVV{j?ew}c-*e4KZL%~0P2&!1q`J+NKd zD)|WPNq`Xr#qEdxe2>R3{-Mph`h((cWu#A6&i##mKe%=NZ($|5M;G4w<=25PuQdMc z;bAxb(dYU11Am+3UmN~5!@q9x+YJ9k%3pcn|DVaBT|!cFySTVGx8CtBnOSyc(%sEX z!OP2wOcPXeb8~ZAedF!zZSwZ*WAmHuBD|VWu!w~rH#ZP9*DRcj2%1`lR_&ZVBr;4I;U;})9 zV`0H^^KaTCS4Z+lmTmZ*K=HW=<$sd8|FXt;M=z(p+noZr)c^Uz|GP}3Nf;hZa$h=H=z>S0Rzy?HwICrKL|1NMwYK!{dYwg@Ay7>(tbAXQ{Y(m1qGvv-x@qMuvRX z;ew6@o#z|~Q{4=|?@E;pjYeyN!MplF9Sq8O|EmcE&xu|09sXnC)_mXuL*(ny(0 z@_3oU%VDn!8Nb8lxI*z?j!fM}zYW}|!$#rKiB6(OrCw-klv^1t=O9zP!q4SbRaJ>K zs{-{tb#z;)tE+#EifZjl5{!@(qH$I0Iu|nIX#N*-GA~*FYGaksQ>(Z2(&brQkDRo% zwKt!YOm_{$r(v!7^IAUM7tBT=5ck~L+S*j2*E0U&;&R~^-mpimh~6n1^yzw}rl6o; z1;6uF(zAR#ak#tFHh=D2BIQK5sG!a7oBs6ZT;l5|qookC@LHuLt>C5vhBo1$*gcoV zDev;~zn*EKCL~eEU`Z56J5SQ^c$-XlV=yI6`1jjiMgE^&tzYU{SXf{xD=S^;ql(C4 zfYYNTB_*8v{L!tgtpz0|d?hEC)6>%-jGqsWUfE-^4U~}qOf%p8N|!(5+UPNZ_tnu2 z)fI;l5&WU$d>D3_GJ8#{Dc$ABchb04(KBb4&XY#7(&-{vld?13wbj)~yV0taY=wyI zva+&@!;mN<6Vt0b+*+7}^v2B4#%xJn`*Nqu(_}&e$LV*;1O@GrS+8z|(TvaxY2Scj z5?Vd}?j!T!IzV^*)`uEWQBp3vf@$d=Cx|_{-cVGuQh6z%gBb20DJhwQMoUXbNUTtN z$S&I|NS(M{>_UGhM{`pI%X=5pa8F&T;fcsuo#KX4EW0BUz;)c`LD2M4+$sBP;SRk zQ&az$PJk;I#(VcXSF3N4LqFUG>+tsNmztyU+S&u^XmR~^03wIXQx@AEioe-iq+B3-9v5g_RSEBS!7T#LeMRvb(#jj*}gwn``tY-ICp*wDFZMT^2w8wD$BA zJ3KrjC!xX`#^Xq)4so$h$>J)e2lwgY=4Q&8R#$YN?rNk3~09j9j4Aw zGrm(IOoohSd>H35{+yhx_xt7Q{z4N0t8`BI5f{_mh4RwX(vTUHqA;(P!34X0#zq%lzrKe6RDw#nRny7t=+IQrWUX+nWG~ot0r)AFArLwe%s$XDqdT z0oXE+sN*4xojq42kHy4v%;`O*(F9`IcwCNr(9@x6(GQALZEow5B@XKvQ>VHgsYwdz z#>M;oCzK&I^5q)`N+G71_55VD&+O`Ii%FN|)#%fyrtKt8d#3vbpPTMUG3=e9LQK@% zpa$C$%hNke&YRP?nVhFmJ*?}wp= zeD=E97&9gfroP)oM#}ELo}J@~SYF@n_w-SDX;-=>(iVP=KYAOSasR*vL&tm))SJfN z^>zvuOtV+-G6GBNFa3OPfvbU;IV@}HUDG^&r=@XbTNmA5*;C@Yz)D+B6XecB5g+Dk*01_?o%Vk8Cu4=>DuvJ(+^b&dwKOUC2k3= z#9Y&o`je9Vls2|Qr83I&ut?ak!SUdz>|NN1qld5ODrV+%mKOFgz;om0kn5gogj+&7 z#24#vd|)wMPO~~MY;o4uu{qX?YR>0Bc{Ap+hm9aDqqs3=#AVq#9^-q~t~6`)r;>5iaI%od`?N@4L`XGzF(K)@VsCa_JOw7aA}GmqnmFz5;wBav|Y{WTBF`HgPQ z^ZPt>U+ZjX)UaZg-5KWetr^;zVkey1jg>Ec+ux~+Zj-e=Ry*E9`2yCwCs&=^j5F(Z zsfB(UR3NP8f{+qkr}o0m`a%F-RmBHMU9SQRON0g@rkKPPGqQ*yZOD$4>p`e8A> zn3T|JH8{q!Jn64rWb`Q_!=FTdYkRJxv#NAq@>tzzJ%24M0awRXf|**XnVP=nX>ft;EPPbrPB#s_L;7i zWeO84krp>sM@ISaU-q|EC8@|^%{`TN&JMrrk6{DErc-TZrXz44L2YIznlwZ9TEVrm zPWovMeqi(*_auEa_Nb|5dI#aT`I+8y?+r*51{ULxznqfgdtDYHmH?~a7x~B=Ey!Oh zP+}y_VSZhT9(J%RznL;j-#pq~&r>3eUW~-8@4tG9!iWdJ^=BZqjngX@HE?I+uYAlZ;p@Wo*B33 ziaroj(X*@I|KKh~FMIe+w^P^4-(WMHai%qe&_+Etelvewq?voPx|P5zX*!RBg)6ZX zM-m5(Xd#mZVsr7MCgWZlE!h(e&3Sf|r4|B5Z{V7SvK%Avs3?_^01JbFWnm{pZ8shC zS8nHy!4~`=mfN1EC~Z`WP8gaV#VdWw^fLOkt3n(|Ejlk3In(F19?CfBVrbw`XiD53 zFx@;ZnOf*LeC*JxvD2{SDs{SwYBR00nNEdsPj`Cd!ZPo(Ml1~9RzLp2e`!fQD#D&O z^@!0SoN;iH#lgl~=7WcQcsGQ`_=9&j4OlFJj=I;i3E??P4)u|y+6GU2cH(Y%zKO$V za?=PY#NA)1jY^%HKG>p)m8f|)I0*@epcL&(EwoVp5K zvP;@!AN~~=!~2WU4c(4|bDk@0>diUO4pX9!LzM9LQnvW$SknFbVVlx^r7p)6mPwL= zbDe-9kf;){dvm6^#lN^Hw>`I5 zc-5(-;P$d(*r}C^U*Vvqd~-H$YH;;@cZ=m9Y8uXqjmof>e5!A5aZW5{)OTuoo~m5J zX-IeKfG&!6{I7x{?-CbPc-d-fbQ=w}QgX=#+dpSPkZc=|slD>JEh=Aj7 zAg9CjkwlUte{1`|rmEENsdK~r&e;Bj;b2?eqTAEbgKAD6^mLV1FL-Zz!RsJtzeO;( za_mhra<7F_R_dYq9x7BDC-%qvWZ1E#gQiHWom20KO3s$3_J!NZUd1xPx zY8k{Hdg=shs0Zh@G<8vN(zH#-rKX=XWa~ro?!VO?Okh7QfU}QZKGOu+j7+{Qd`ZO6irLi%uBOdS*vB1 zC?+hfh?#dZFC~iGRWre|jB?YIWlbe7V3CGK8ES@*t!4&_p~0AVK}A$j_K3DKJF`Fc z&(3&$e{;Sw?|kp~zR&ZVc^_tPoTqRHPUT3@D@+SY^2&d(HCo-F@R=D9HA~%*2z4&O zC~3aAIrt4&1S$8o&YXe8W8Rl#i64>*AeCuyG{>SB?IfvJZ<`mK>%p})k7mS^A~GbR z(pE2hzKG!MGCfu=Z?kBCpj884u@3V-Nuf6(-#%|S^5}%8Y{M?|ikZI7>PLz3LZ#sa zg;HqD6w0&T;$~0dBy|(w-{0K=7Z#Phw!pu%q|A3DaSn~TxV~|ivz@1pxhUHv(a%Nh zfhJMR)GcmPBj$D`6+0}06KPHfSg3QFZG${BP&_4A)0{fk+&(W3gIcB0WC!nGp_b2L zq>Mt6w;DdBh$gz~Oo26R9XsUMf@?(@z3BUtqN7gZmR43-G2oRei)l0{U^Y-}D%e(Q zVrFL6E)tmlzca@qbK9@+vpMXThn%;#m&H+XF(MWjFF(yn%ufl1B3br4WHP=6>SEJ$ zsfkiH_8_EE@s1t@r={{gRMVr*aPQqCzME|#Gwzx<)q#tnLor^34BI@KvxN;oI#bOm zG7WES!npXG?3CJMa85w8`-j#L)~!8#A22)f{8GwLd$d(gf1LTe7QN821x0b`Fc1DxD~%T0YjDoIJ;UHO~_i zRop0$ov)LSkCC$jvOiRp?>1pv<}0TW4WUuUWDd1ja=z>ylz*{o$H$LDlrzUMx+Do^ ziuMd=#mo5fChbbrVfR{F0&o*KTL00xb|3afOb556p;!MxWm0HINTt8)i+>;^mxyS+ zuWZnG*Vh>Uz0TmioD@!mk16YzJ^o7)3g!`b)`u`QH zOg=~jPSp4ee$cqIg;zSUMw6tmldIWY8v{OB1K{=Q)vGNZ;;8VWId}LnKOY~TB_^gX z?3?sk_VnpMI9xw9HPz19IlMW{ls@5PZ||$CQYaLhSA@-aPgdo8f!WEu5FvUK=IhaU<(|_DPW9YUtf^jfNcU+S_#lOiKD$njg5_*iF{6v&WmR#EEX%D zqoY@(JDTM)WPbks7TTID8B6eceM4)g^hn}wi&^P=ZEll`s$04DTz+yuC$M!`Obm%g{921l8ERY6w_5M< ze#R;?%7I)OA%+|=z%iy%s(PN>k{N2z({B!I^AkbdGHt_gCvv189qrVTsOFLF`g0^p z)X91+GG-)J+ctzAgLs@cYVgWBoo*gX7>M~{OEa~1v8qgXgkJL($+P5i{B_$SVigGk3*V`>%seJ$u zYa)+H@~i`kWkr{aTTPOLI4ahO?hq|RuogcSXDU=o|?rtr#P~0tefkJS10)-YS))x070g~X5;BLhwxVuY{ zAi;jw@7`zcbI$v_uJ8N)AYAigW-{xZwbrb;*LuR$ROATpsPM3`un6VfztzCP!VSd2 zx+nbLKIX|LvPA~-?~bd6oHSPP0L>PranI_F@*6CyvKag;GaO9&q0@VPS1c@|wm<&v zbU7ASU}4>Y<=?*1@-p6?!|{76ciDVs;^Hi{tPp70GWU#CtDwrU!EueleWGgrU?yO0 ztw>#g)YFrYZJ z`)3B}v=s&{_P?h4=W+Vydx8I}Z+5KkK3`x_9~HNdt^XsGigK_@M%VLyjZNzU_{Qn@ zHgO57(snR@CfUecfvNO>}?~GHf z(+uax5f|5-0v=-F|4X!un(;UUsAF%JmEmIgpGYK9UQzKSgYfEaEo0-BESXRO#lMmITeR~!_$6g?Vo8)^J24nYP4kl-Hoj zZsc~R`esV@nT$bKR!{dy(u_^zXjuv;EV`y))I)hf8?~yW;XO1`CLjgU%sW=jPlz_K z-*|f@qYf0E7l$lHrUkkcQWw_OH`s1bbVP<6=1+=W|a&drD^RHt?6kQoCYOq zlNNe<^xpjK(8~~!jp&*E>Yajmk?-Z+8@KZlCFT|c2{-9l{(22AUzW6cHGaer(;e(z z58Dd@W~v+{>I+lG3jxE$Sb078a3i=sd>)^xsq^RWj1W&%F7v=Du%BAjMXReSog}UH zO`en=_kd7(+!V2R?k$X>SKnUlKXgUdQ6NQWqabb9ZvOH>?CPZLcCylJjz?1;$Wl^& zLv~wxaA)2NW!VPU$YU$6O*xaisvdh@%5x4&Q18uP=_16MFb_#AkqQnavRZ8Zqz3?u zU{pNBx}?s7IHz&=>hsP|Jhza~A+%2@(%jd^(9PQop7Ul&uKQ}A6ys0v^Hq5J9;J7{ zxNZ#S?Cc|0174EW>%JN4rxv1Grz!GQyIr5zH@&VE2+=L_-RPe{ZK=)Zj(SK-*JhlW zbS2&Q8oNo+yvW&Z{N5AM-u_u9;8#{qH)}v-SC$VC?D*s1*D>_PpK2WDiiG${S$;fc z`%JRDd*WG%+;Ezec|b2ZATmv1?0%utczbFqSZor|hml^?q2W-JjLWdOl9GHoG+c55 zPIm96E~u%8=Z>j6kC2e9xHzPC>}S8daaZIqb!AgtZxu7m6)G|FaPx^OrSUUmoKFUL zw2&gG}wrzIRCCu|5?$<)CfpB zqd@+8W|F!RJpU_i2ihIy9MCzRVq?>IyMAF^>yL7TtFE9u=RgrRj>nii9@5A_=-OWD zMgrAFL6LXd;f2nPBUi!z)&Qhs3UPd4^st++tc^Z$MSDj34&XKrt1S)rQuutb*~S%m zwpaS-B|%9_LB<9U0>Qw`SMl3qK zW$DW=E&Ub}a$iAFk!9Ri$Rw{3N`qg4z;5nb1Q@i?l8S4ztx`dn6StLtG?Iu5l8S!F znby!ib^Qmb=UNA_=Hx^FF_;Ee?%Dw5#7}fEt3zdg6yM9!q8fE->b!>1#(YIri82X5 z0;>3TD-M&J^JG+EZbHN%l%bmfoH@p@=8R!gDL>D133veMt{`DF)HK6ccxA8=trH;L zG>~rVRV8n5=W0cLOM6Q&?+rL#0Llyj(o%*Zbw0_*JFEzf<{rVlNhaN@EzBJ?a}+sK z!BRR%bKQ&Fo&~-AZTR$lH$hv`IJLmX$R+Ka(VJAPiIHV z?6oD4chW0OlnXQGT3SO$Zh#+)L30mAEM!?z9#+?7IK2tM;L*fZd8Bv__QUhhZUR?E}%@oRV&j|17}Iy3q@yC-8u zDX#dG7sL)grsuks5YtQ^Zo8A=4HH^U^Owk_AE}zh+JN=ji#jtEO((-^r`PIh;Jev* zYh%W&!jSEsKz)IH(C42=vJ!2&IP9tn&wa8ZW%#MjvTmUDJY#;8Yi?=ex0mSNCpU+I zP}@9U%~6W&$sJ?O{=uk(zai}7zR$?OjZyLZg@xhq3_C8<8p#Lr?cWD{_tH;t@9gPq z$b%3RSj9y}W2!<6etZ>HgOcKNK08H|Gc&Hk@5rACm?+cI(rW4GP$7l{N$VvZu_leD z;YlO-+Y7hd3w#<aI)~9Al$lX_gYhYN8DJnF1^|Lfw}%zM=HxrDit&t%B0hmJm@+w+2!8wh9uzrZ%Bo z(2W+dtH5)B1?FatYocUP1UkjltF7jDv-iw)ljpB4#`_`jeVte8Yo^l%@C&D|ygN6D zN<;>0)4B|Q>Uxx@2VBYE&QA1D#{6xO`VLi$V)|hJ42kxjGNrFV>NxISmOu5TvFb5K z%_i<*j9-2v(4&xOKox10sT>-7BSu4tHNKU(G}AsZ@<=ymphNZLvN@>t~z8D+L!e zF3!%wC02R%ZPJ7<=kUx;^T6|UvaBQ%SNi!Jhp1z|s~zip>~Ec0N@_qy4x<1ebCSK} zfF>_t)f8MmgX|-ua3OqK8%XdYV<)o3o|J)~a0u26Nh$Hcq7IJUUg)GFt9+`ZbsXvK zTfgY&YBOmWU(&e;MJewTDdh8z%+*&R@SxPenH)u)wQw?PZ7ES}+Cay_7+gSh&COY6=($9I9t=HRX-qA#^7GFIYF=c8 ze9~!?g3-2o?V&@yhNfsan!4|9FL3P15Uv&8jm_uVgq|*3U5r4lV$RGTx=TW^s#uV< zqks%VD4+_w2dka0pK$ganSKn<01j1wGj97cg9}HH8FWH_;iA$HA;4z+GjbMg!ok7e z+nA6dC>b#74{nkTup&86qW?KjWYFc!^9FJYvh=28up zY`l^5?%K_h)s0lqdV4c&zInGgGOtpJAhX8XdRjlB@cB&ESA}=I^12G|I&}UtP?Ql! zO}TECK^tf1wcVjc`oDN17cct~DQ*+N^Rp=EwDb8^x0*z#_IxUBTZ1QJ?qwyIHgEd^ zp4aBXW+T?0X*)w}qi0VVr?Vyc-A~Kgie_K`nX2ulfOqj_+t2LSch*sjMQA&PwFXhC zNUaMPdU_fZrBz}u7CiMHoCDrq6dKe-9%pmdTy9gg%Cb79(8V0eQFkfY+A3i$ zjqXZn`U;Rmb&~xV(4QMp=?GP_WD6t6ub6pU94p#^oWJtckX5H%fw_kc1{w}DSNltbqL z_B!RzA88Efe4d)(NTp^o;O1p20I`~ZZqy<=C};$Wb1*OmCh-VE*Q=g-X?kae;0ex^ z^pvdZA>$79>pM}}zbhIV7_`5YG`!J3)(fe86}>+ei#(x7!M#k?+$lKHwX`OvhOVgH zQAF;+PAFpz-WIH=cY*IFFvGwbD%APoNt`)8o>khJQCa}y7=!o#-;h+Di|pvZ>I}S9 z7;S&vV1xsU>dcIRZV@cwoxP#z^|!2x!!(7M*%-;&qk>~NnEt2s^jHj5WN*O)^W!1% zKXJw=vhc+F-x#Rdr>O3MZaQ?mcA|7CrEDg7kZ}*qOW~NiU#g=3yFZyo_?6#bjTM0K zhKe${`4)th$HZHMg+B|?znAoq1%4l=(dpNF@w|EShDO}$TYiR*!fm9R;mW|2pd};ACFb2cAriF|I1iRreS%Kbe>L>ukNNjwr3&^Ec*- z2@*xp6^i*{`v+Z2O-_a-PfdAxx+-Cvzh0F*Jy>u|!d~f$=^7kVz4bF$DIHYs@~Q?w z3kxl_M!;x{4(b%S=G|?!vDP0G(?Uht&%5fm5t!4$G7_1^K9>ml7G&%}&uac&jaKC; zshn>UvFK&v3(WO%*tmbj$2=AEg6GqU5w57O-y2L&(wBT=IyXhVsp693qJ=ftTKMRg zh_xoAlT0pgpL@Fo)@k(#x@2crJ%N-V%!j?F&8*XMG(lS7vK<9uqRc$O!(~V?sQ4TB} zsAJ}%M)1ORujt((ch3VhmEz&UO_76`$FzU(t_=@yT4GBXk{?Yx4|^}ru%@2%QMUdRebh)eW15t4N}0;`_~+Q9Wh}8 zvO&$yc4&H3|BWulo{JnjjNiDxOwRq|JP6a(*@MTR3FM!XpP#?9cG1?idr+h7?&Q=w zJUsjxY9AGKG`yvCWn{_zc~jVh))S=Bxq-`KML*#GXCpl|u7o5#IITB5GtPN~*^>Rn z0SpGm#m7?`hYzrdiBVTX#B5<-flP{GJ7d0DS7Wz{w2{r z0=khs#`?>X{qrzPMf%^6{MVRa`SC6K^u~W#{BjH#9U5 za;fUzfJG=7_M=}K_-ZfkKT*ULG7R=XPQbsl2YZi-dbCu)m>r&yG>H&KIAm4()-8Vk z>MarQ@bU3o!9r@cr8zioCeIGL`jL;s+Qh7I;~T{}{M9XVCN#jAR-eAav$bHi9lDpd zs^n*SyRf?a>V9wL>Gw$ZJ~AJMYYa%IU9O7nU*$%M39*>ai{gqTib=7o z45;?#g$*p(NhR{}@`|!z(F}e9HyyR0ZY|+3z9_Qw%}R66eaWCVLgH<lO$%UVd{)1{2X%vmZP{)qo4(T?%>DXB>Hkom-W4ri zqsc+~C4O{=z09q&Z9VB`lGWd~@-=hP{Qjd^E7nVzD#i9s3b44Q7E8Ks<<{V;!+POUg-T%rTIS9j_s@7lIFgaJGRtp z?6-L!)CG_2%zUvwmc^efoYsN3e-iwc? zfFRISl49%JLxfO0V>|E#-Pb?BJPwYlAlZ-LRdI%YTj zvBlky>*KIo6}M}vw&7*-O8rTICm)j9Zm@Pf{S!edO1R{@c&vmpLjNpa!mP}m52kB3 z9=(2`@m~MNMlu=oV4;6u@D6gn+bYR+^HrWiUG$gUv5PYi$5|ij34+?_uJvN`ixhXi z+jAw(?G+0>z`v~PFEe$MeMW&L*wr^ngkEuR?gTjuAbC4bubIff#It}LpSm; z@?~t_F_d{{#sg*~)vDsQaD0MdyQ^rIKI?RR!c?m2*vggGIwT|3t=#jnp%4gpqARBj zmiYJ)^f|FKWe z-|oojv%~4`6qm5DFokhOp|s1&<1oD+k-dfZ50A_Fyo*b|+U1qo&dYw_V}+nx+8dd^ za4hV%+4NZl`Jz{>)Ze~aSGhr->LwH!_fAJSGgt^LPIr;Vmq!!nKif(%dgHF2l92Fp zmTOb>wUFZWhnG|5dsIi%8v5mSIK7D_AFSM1fwixtXNyWl<6|2=pHXkzwwCk?l{>G< zjvRJQcR$124OuHZjy8mjPb4^FXhIV`Xdt`8N2Uj-MY~_8I)iX};qF2eW-Fj&e3$ne zY|J&C@sf>1dioSGdSF$|#kjCDn*MDsTR<0psy_k~xvd_~n|gd~dSO6#Ru^l4SiORc{m*GV)HQ4Ay?sn=wDKJ^g0+eGpBzQRdPQ z@Br&-eB1+b88npZofaFln7D3K__f^^w2p1`dj>y(b4>KS%s^!pGl)71Q6n5Jx_@W` zL>w%8Pbo%h@#HySIkU6Tw4C7G+hb}nc7y(M0qRNelC=g!I*x-Sr^5^#{dW6ECPw(9 zvk0c)nTLg})1rd*@%K4yzrwFBmDd({b!-kC=W0Uzx+JTo4S?Qy?^O)NA4SAE)hxf* z6Li&6HVou&?lvvSb8zyzH9ysMAp2zp)3Xixb z79ftBJJzujjW5!%adajL_GPj1?wAUt;bn`ITGIynx^0e?!1~W3#m~J=#pesB2`9$2Y(G6J&$O`+Y|OV`xz=j&}(v&0iPiz(bkj&7zQC6 zn1J#kaiimEz>T*U=9ej?#@rT2<9jiQRqAO@i}P?MxvB78Q+LiL<@oCllBJ zCzAHN?xjZJ?f<0DH1VQjqT4x^U-?Tz)jnoMdQz#ykSO1n?skHD6M2v7&V4}!<(YG#yuZ4Y8Tj;JFE4J~4&A%vw0ke_ z#bTA(KgJ#B+86|<$`5e7z(i*|ulEdppN-+xe%X9*l=a7{BPsP>1mAf-_V|y+{%o$_ zmra^g!~Y2bq*%=9MMEpD4R!7;5=BmGt7%hp|2WHBTI-@)#auX6!MB$|IAv=3R(iRN zgp>?>Go7lAbnUkZR$iO^w=1_9$$ek2za}?{$3mexU9ytOl`Gc2KFS|HcktOHTnC*$ zJ&QVIww!IYzg0t zM(1b*(1^s%0*NV+G+rO(XnRGDI9OLNNx)bf`eb`&mcfC$X zn?@#my5U&H&lz}gwlEN{YuwY}|IuY8HS_pDU*f@Wr4F^NzWJjy9I^8SS8D4`zKB#~ zWb{G2f%j1l@3=!BgG60V>Ec$L%t=V*#Zk@F?CoakY-L~QLq4X%nD9Ag`-Dbn6XfJ%AG*VJmPAYSu;+q(umBAG$fYQ0@>W{g@nd7o z+Em&>(q(t>$$LY^_OGONy_!Jl?P23xi7)sEesXMWT<7aZ+?w_xx{0gfcgEi9lC*SN z@7J>IueQ8M6D3dYEL?Gi#u)q46nTl{c@2K<1aM6C$Lw9^#Bk`YE$DFEg7O8gWcShU z4c0GXF3z`lc`i{#g8N}F@-B{}Vm->5Mw461ROv*>i$?}<9NRAc6;1z@@LZ1EX~ru3 zulR-MEOw&CmPELc^n{fo?}gN-g4TXNkxPx@RGy4OA@L6X%tB@+j@W55-!rW7=r+ML z11@UW(oD8<+@)t^t-0u@M-|%zZok|4TyZ-BKs}oHd@RNMxvBv);crQSUCsw!Ls;|* zIzQ>UTlCs_bSviNw{L-Jt-iHFMMzFoAKJE7&yTKyeTRM3rcF>;vO2nk$(@HH)`B%tv!gqXoNi2I1#=ut>=!VicJ~1i;AB-5(tadPl zoItSL$)#&!7Nak%M*4@zsAG6e=(byafx2_SW15)>Z$4TI6Wy4d5FyDXrh*2Qn4(G; zC&dzJ{IMpbQ(HGD_>xEhm<3k!1QB}GqQmB6)PA=!_sO1F(~3y6Y0dT8f$RVhJQ4_g zj$2;*_r;k?PDw(aZl-w!8z;Z?Ekf}%N)fNX1s7&sUL%aQVjThgE+;jAXQ}@R&u#?& zS6F5=Yv@#|VU$G}QJI_dsq?;WVS2u6udUXY zcyPJ^nJ9;^n`j>gM`>1ch>x`!^*~%I?b6mIr>S(On7G@7l$ZTHr-x<1iqmkkd5Q;( z;}QDu;4nipS}0?qt*t8yDQNX+>>*)%VJAM3#VVZm==aV6(EFI`*87Z%li;u!siBw( zO3vdqFwi$G4(T1=fNaBTBI4o6f~p)J!Usn1#8Lq$K|-kcVYv0EPQe7QhC2=a0Q5B= z;ODaiT)Jb7`#PMPdr3htq`+M%vsGH|+S*Y<+=9)uzOS#J`!Tmn3bC7X((pS=Cr0w> zGqKcF*ueoU@O>r`KE5qYx?R~2D>&I3XDmKGj(kkhWZ}KJQ9}ZkPLi#q1*F6SV7zTt zRyKUIS$S6Jha7Cv@LkA;fGXR^sq>9>j|&szJkJ!E(D`x~6G+D+83wIUssxc7t$CV_ z$;y@d#y7oE)a;dLU=}nznTQXcde?3T4yGpPa%}Y%)^zlVv)Zrw=Dg*2yqG>+^E<+W z(}HULAMWYT=-O&F{Ot=>Vgs>4nnEW&E^sGU3Ohvg1Nvl3iB2l$p~P${;`}n!>#42k zl`o;$Xl{5UEs1P__uWHaGDCbSW)GuM^(o=S*IQB_c=V=^lO#^pVx9G&8}z@{>>H?NGy8_@Zf& zMKnbDC7(x*ls-I(D1bQzmNW2<^!;MrRhS@gWfwPeLMVWt&m#y(+wBUzWIrI1ty5QD zi7JT!9dzZ7Y)nVJiOu8oIC+4+w4UJ%H+S`WH0Iu)Q(zT{#tH0oj^=pXD@E=r-bef+ zQCk}H387^FNT3FHvaAGG&;u}EyH(}!xx0p2R*bxMYdKu8_c_b0(#ie*2AbpIG6yEO z?{)8jH#dOglAPVL!z4nl+~T3)xPzIy(#^sXZd*lX-ZEdIGM8S^DVfjXNw8Q(@wlE? z-QuIowxK(WyQxi|Ndq|TM56^#^`Fg+I2ROpc7YW+wBLQ-ogSHXVQ%Sc`<9^bA))AF zd_o2zK6#m$u4r;`1qFp&XllCI)M>d}^E6+adJa|hTs{~j)ON^W(*2`>ay4$8f=ryR zkE6(WUn*FV5V9)gVD(N(1O-6LQX$WF?vimC_bpqp>DLR*eUs!UQRIC;TMKR@2u6#@CzZxcY7F-94Q1Cj}vog|xHN@gJq?m3h-$eieVHwh@%-!Kv4)HuPWT zOh6(Lo}9j^nSD$}A~liDx*m$6Eu>%UEEY_b_)qV{}guI>?q@|Bj^6@FXbt zpzhxX0-Z)q9alEPV(UD1$&|slBW@NM$%2E^4E@vM8(FizxA#tpW;#M*GHpd0nKRb1 z=scaD=VLFPb+;Bf&jxlX!z1QYkDH6Y_7p6T-F6Vzt7mDf40IeNAXSw6vt!Ziln zJS>X7{zZ#Vjy4iXZ?w^~+Pg&_)J8is`FR8s6kTpsh+oOxOVE_%LkGQa(_YKcTw8L` zpdFaLx#Zq$1!xEcbTVh&HtQ-P)a!R}jlE=NLK8wZq^8=&Be^*T+Dyc9Z(=^1almZ`qtmb2wrE_hL|mV0u+sGr$osc zDcXvXkMclWmk6(GNOIHhi9-1Qi#Q15>t`1gtsS1J>nM(5{+Us`ZNsWyGgKpNW^P9C zmUY{#0&QG6n+=A=X`gMm!)B|<-oFhjfaT^E1f_(?UQ=x+!`B6gs>Q4W zX8gi_hx3WmOP~s80UR6xdcpz{TvdljE7l%%QQDXUtcDJRb{&c^4-SS&AjZiysg$F0 z8sE&+%8GqVk81FsQPVcG{Do~0>D)a1^#v;{++MI?ErqT`!9>$I8R%_UbhMpxZpP*v zpagK!)0;6pSS=vNBw;NzjC9^bc~FpX47d)hk7;;U&uXQNxqg7X;$X>#)~d`@bSf!+ zi+WOgs*~?ry}$0h`Tj;gD^bIE?tOZ)fJ!ugmTE-TNYn9$q#TDouKx9@pI~9hi`De5 zKd1wDY^K5#9dX@r68p$0jmBq zUGAp<+lB~CjC{2JQc)aoHNv`$A~qQB>7OQ((-rfdoYt$&Pt0Pst$gVu80VPUl{d~4 z=UArGC;;^vBPL-lb9L_=KQVk&ESukNdu*td`Xn2h23YdWiqX;!^v#8Ad6s$O54w1^ zM*aeCSmamD?1en#ALO#M8XA&z8V9EbIi6&`eB=`>l|5t1(oo0sNkvAS%)z^j&yLzeKwOgu;(!tc6{D*I8 zUw9u9NS2=PZ(QB~4RJ?#_rFOl4DI~r|ABV?|1UVycXM;gsj8~Nko9k9D?#g5M&2Bj z>~A-oZ@BycC&+ttNI)G+@Kyfz<1MMZ@K zJaqopEui#ouEH5%!-G|rF$Qha;^O2SzcpxFefq4Wvs3m~7n3sx(*zf*Z+FSV;qb@z z$gI+QazCN7($JV`Dd7PnmcA)14#+n@!K`|cSUS|82fE-YA1BcheVQF1(oeNd3ZQfkmr@< z{|?u9WBHIhVq8mCS5rqP?*NCred|MgF%TKu_sxGVwmhDFQlznG1O&1W5fQoU zJYU2ko)_m!V=`M^wM~Wa00ahI|l|-ZjBWqC9YMzOec=6AQk-| z!F*gZ_sjVi*L-e7ld*nB3C;fsyn{_}P^kh}-3}$d*l!V#4Xbc_Hv9)dsj_o&ynEv? z2jT}QEF7&G`@!|kPIUdiDit;dKy|kj-AGBqjfb4(YTXM>n&!DT+9Rojq7PTP6eT44 zr>U_dXpiW;3*Q1Rq6xUI9ltSDl^AL=BqlMaksG! z34iRPD6ZQVg>>cX`(ih{uJ;Y&%Bg%wO{K;ZHVE$T?`srqKw=58VrWE;3Vs$JimXB) z5V>pamYJE*{W)I}8X7O@H;a+aq$&iKNxmnCP%@3Gfs1M9Es*i}d8b*PfoxDl7>t$C zeT94%PNk|gF;8$JWWT^GTn$jnA&?Z+?-bONS0y{j$yr5usX7;+>L%utj6bI_;?~x1qO>jT@hfH)!cYu?`Mt_D;U?mWFQUW#{RAv2@cNeS6_a+A# zYiVg&s8=Sv;BfEWJsMJOom-vW0)*ww)dj|1re9y4#ipmjG7mO4e;zm&C)lbQ^-fiN zORqaEeJT2-a`n3K)>~ls0=$}#pk@SkYpE?@P_^4kUyW-#Z(O~_TF@6|wvfzFmC~^OWle@=o~PXmt%HE zQ}OoA9zgq@a}=S6!@zmXB)@&}t8f{E1ipY_1<*oj)`GEv3NKLP%Trzb#nml2ayfjr z^}H?sOj-Hz+f?h&FmU{(dnn2$;e>xkN1uSf3N`pfoLKPD@Uwq;qUbvCN8LklCrX2c$ic5WQH$&R4}R`YAo^h9x>L0x`DQeya(+UOd8!fc6&+N zSX+j0d{PgJ_04QJcI>A;EIX|=h&bsSwPXi zsBZkXSl#!|?lod*Xcg$5EQ)%BflqHia?p+RgKU!wq zwVkNmr1lUGZ+RP5A{(XlEj_&`z~kg0PM~cs3kM5R$?USy6Ref<}Lpg>hpznC{DVPrQDL@kSprWKH?Xc}~gbyX~V&{Ig>#jn9 zG9HdP{<%||6KAy@yE)o@X_M_WQ`t`Jt3o{U&U_4SJ5#dW`ja7>IIo;>AZRJpXVE63 zXTL^Xn4l&Iw&0h(;n1Ws6X3YLK4{i5ea|Bq$9d~PK#_7mj?YGw-wjfSZ0&5Ng?N5r zYo>TT#5RAZ$WQ3dmi*XY_<3h&-I8e$A4CqCu40*wh?yPLVy~x$Z1a4QEMC{69E=SS z?{OJF+HyUf%FJu?{pEB&Bb>IGj7ZP-L{f#W$muW z2`+frRt#ZEiDzL#i9!4roL_GexR;8E5-qxBE6J{eKC-2bXxppX_BK{8<}g{fLXW== z9xsktUscyCgug-CCukb0V~5U!J*hVq6tq^hW4ZY9?kO4RP9g_e$xl2sj;Qs1kdvv! zq+Im){c)f@e0&{HIkXAQ*dPVJTP4>{{vU7d0^QqxXl;UZuC%T#R-D+SwgvmiuUZGP zxfD1E2`=yQJ15zS!!E-3DBt zSG8s*IL*2~xe>(+ak%Tel6reJKL$_K}X;-^(lAme|;=okpx9*&BoG0OOdjFt%5%H^#w@=Cv z8ahu43OHf|UHI_vDD%aXaA#bRa=Bh~ASupbguES>?i>+1rn5lnBQ4KH6uGv7(Ro^n zdp{I8v*coE(O4OH1ev8t3m51$F``6B%FW^WT{7BN0_>)JO}ZD$4PWf+Se`(6S)#8# zF>`qb#*pu>{D$T$6QnkQlI4^~3iH@#{bOR3pCmPX|8mgKT|o?r#3=ugjnDM<>XbYV zf!5-Ho5pckdOD?`UD8eHeM}LQhL%?QdVlK0Ue&^h#OE=W{GOiiPxKZ0KSf2Oa>L#e zftky#wqnlv(xgoTxl}^drk8mf@Y=-Fw;nYlJ_96A&}go+;)#A{%dAe;Uz!)TkFsD! zjehG!YuiFly90$&6*Z%}VofJaPY-_{coh*+NQR|w1z72NGve5I;2X|0w?cnJO-I9& zJq^F9YFpe>WL9RFoJq|HnOc5;Tr7rqrV2T(U`qW&W^W|UW?k)OtG_QVf4Jt|!?%I^ z&D9ZG#w9CX z?5|4&AMlHfc~rHfch}o=p^hk6{hN-85ep(4E$*^^2NBD5uBWG1#eMngmgEbZ60hZf zk{8h#NxojZog%UEO%9zln@X)dm&-{N-?ix^Tc}O?R`P4a4_l@LW0Sn4 zjwY%Ur!2@-=(udl1?xLvOqvE~G6&3CMzmLbV>*#F30LU>h zTM>y3lH|7@`6JkRIA&y=h6N@Qlh}HM2lciSoY&u)^E4AVjfij`sutopN$T^I?Vi63 zUX;sNN84IC_k)8s*8uX%XH7?PHA3`_oaa=b8WNPE26l7Un>+VrQ)y-(@L;*u1i1C4IzdnD*7_X=a?V_t${FlvW%W>_g}BrSof=824<6Ky6BB zxmE+)nA#BQd7jUmOEfwgDS$E=`1Q*a6SSj^o9a9d#-*?UQ3eb9w9Rl*5)_}KUwH=h zdPB0?ar&(H8UbgmwJ_&H+xJRr40B9zHz3x2)>{uX)1BanUw2NNtf$+})^+qIeIHF$ zNnPLfXj>Q~OZ9NCa0pL06Pq~Pac%lOULnO9JuXZWyG8l7MDo2t?USV#iGHb)>M%vC z(^d)QjO*U2vdYdFo;f49pIhgYP@HivdW3Hhn|x0VaG*cd3Mx|3O&4!aLEx6+?L)J! zq;Ag5ulWL^Vr|&899^}gq8j?fYHjFjC|t%2GzsO4GsKF5yt;H%-1T{>o4z*t%nH|@ z+V}_-CD#z8=SX=>qgX|3IGXnQEYqii_Z!{#8yf5Z1)5M?r>EU4QC=7?V8UFA=wURI zc?yw7RU7laNlomT_r84P`mkMfVMk{zR3|!`ERJE1K}zgX&^I7K!OX8#x^l?Tv%X)w z_mMJSxh7&hH;lb2e*HDqfIs&ccu!<%*{@m!>H$Du&C9t5dMNJ=W3P9txXU{l?iN+r z0$8TXzT2I9KNCcDEmup?;VzK)18P&qolFNBt~PQU&o_56FTBSb63Bgc5OvfDo$%dr zZ~ERw1BH4^Dk-TmDii-Ri3oEAmP&lHz)XeaJ7i60zL`n{NOgn=G?Z|0wUMcxdGIy9 zg4{>~`ig6^JI%Lg{aX|{nX!A^oGMp#8^%okQvrM-y5|ZLax-}x#nN${>l?MGnB zbL`|e5}Gq`j^Tsvsl#8ne_UK6M|L4q7Kk!*$cUJS_A^pWQCO0(-j-MO!=3-*1$pc) z1@L_BnaQHlg;9&=u~X5s^m`desaWo6?>^KA}Th;Gn`vSyt9cBkgtD8L{>h z_(Kcb33WwE@5Apjv*oeZz>d*eJJY4*r!QRL?w9wFb4-a%jYfkR?JsQ7=bX<@+NW9{ z4-SFOJ)AqY2na*HYau@)@CZ^gObSgr=iIxLwiQoet-`-(lh+bvwpX(tlO?Y;I5Pw@ z@b4#ouXn-?9l-f;RhaGw;Vibn4X$)%d3*Nf{~i&-dCnkNNU<) z0eKg#`8(j@PV6$36(FMK&BukSagkQDZh1<&z@{|C{8OtyU&`-I2hWSMLtOqy?V&82 zhq(O%%l6D529pQ++RTFlV->pBUbz>!v>|kKbR~4g^Y3vewXlRGB+^@3rLT81Kjc}K z+G8!{)D43he;fsay@=}K<|Prrh>8ZzD3RCFKt_GZPk?0jqk>A0&XzJFF~vR6_=(pt z`m|pXZYFEdiwjrZA10jYiETQ0hB3Z`Mfd3VZ0gszwarX~W+X&R#%jH5q{7MJjo2+z z612R>U0fw(43OaEMd~j-PUVb9>RDmRK^6QTA;_K7&Vd`N5k#rsxy;DY__2lVa7%2 z#E>sfAxrbFmA2RAIDT~vPhp&M6jabP8Dp9NP*X<1SDQWdq3JZ`UVX6uHcF$A$CB2s zTE?8)_w@R+_l9$Iq#LN#5Wx@(_ty*uBAKpZh%j$hL7>p~g@sJa3)+|jDMfvK{mCau z%nOyGjUOk96!Upr%+hT%q{{cf^7;h7NiNN8?%1~!Gy482g3?cW z9pfPk_1XIzkhw&V$)AqTncRA!h+ZkTf64MtWV+TS`P7h$jiu-7$BCm3i*uz9C%F;T z%P-)&IDJWi>58(#nw92KmmbX9zRYxrGoi`PjO;bTRJxfEz%DrpS_Wug9JY?}$(V7* ze)WMF^XPsCixtrLuNrvFZ8@xIPM;P_r@`zl1^?0qCO4!RdEGZU-M6s-?Fg#fYIb+J z&{GFXb7w4&gby-5m66f;QoqSbs2jEanSk=^I~}4aUr$$ViI_Rdd9TDhCIOI;foJZI zSj(27tU2eZO6&1Ub^i;1${Qc?L-p@(JFRSHj#q+qI4!hP9qS2(dGT%KTA8jRQmvHD z(sUn*gf8nFbEhjF_=Mro1tf_vd6VeXd@-rAxty*`v7ee3CTjRpchC^-oA23CGk>>Y z~C(o zxK-9Vc!lbyW+5feYJ&@AjwWtC>mnU24o>#C#3A6AmDkas1+p%xo4iprV;9rmG{4Ax z#}26ct}M3F4Pjvbb}3{(uILsdBA!>nzZl+~rSAPS>gH1MB;2qj_;V{2>&d4k04ttG z*j#m(rQ#@ptc+)wM80F%AZq$i7#=n0?>pJ( zp988>OenH2x1+})#j&9K%IG5}4uOBPcxI^Fp7m4%A6`l8Y8Ro`0AwD%04S*PoQ^#n zqvm8`*-Dbfnb9I%SX^8*XCmbmaUiZi^FrY(dW|oLo9N9cgo>r+Pz`Zfnj1=IWttCM zE81Q#1r;b1@OA3j;Ik-Ab;-t?Ojmkj(wit9^MkRj3(0ogJhpk;msbeQ<3?d!jtj2k zq#(LF%cZ2(uJ8P?bqSj;Oh?vz5OJ$+t?Wp3c-hGVv~l!dbToC0MqHxY`a~aV+{}FEen%_ygj=Vxe&_^vs!|q!PRhh1)cJRfZ7) z^%}yp0gTWQ-RwO6gNgNbZ|y#8jVKoy)up8mcluL2Wp;ig8d9V_RiGv-*RiTatT?t( zf065B;&CuTpHpgH5_qrub(`dz?VjXhp=c(g`B@1^I#L$LSvFwj$>_K8Ly*M#$GY z&JMb>e)Sam;2#AX-4+{KYDu&*I@ zGzB-*2t3__DR5{{qhRgz#C!+7VWG55F}qg zpZL)z->f78Q_dNcR{VWV`?>D*h{NUS9(uk7x>4eM599X@Q5L#VA?i|ZClU5DOY+yR z-k|s;=>ZuAqEjo&xosMkhGxa_VB25MgKAN2+LybP_B*mSlPM}SIby+b9ut7Jl>n?t zH|MsTgXgXIKUfCYa(;HuJ*aeQVDDjOWBd*`u%YnYW0ystx^$(&LKqVe^CwMiWJYW* zkoVEdHGrn?<^^af;R3e!P~Ps5ygVjp`2Bc`gK&BivCv&P!t5BqE3<|-Qq&$@yN;~9I}P3^SjpZu#PJ98E7mc zw6*c1uJkxNxBqawb8&>)nR-m!)o5uDW2mVz+`Xzjv)Ay(T@ZpB=?$0eh251gW?}O7 zITr?`{C}jqWmsEL)Avi2QYf@gibH_{#S0VcXtTx zE668aj*zJ#sk-RWP5nvrs5N%Pv@aEB=s6Es+;te*5v#K zbMD@dtbg0H8m}s8^xB}#HGgH2%={oCPLWjXOZD%B zSV?bnDi{NEmP1;*kD_R2EP+THJwe0JJPn7Tp90$+&^y}U&5@~&w#wJ$@|@INJ%i)J z1l%jHaXvZ^&W%0cCF9m~W#@vu{QRDGPSamD8&Ft^A~zqvfYWD3cQvW^aQ}wm|Mz@dta2ApGo?>T?^ z?QreuG(|iyxbMxWc>l)tn9=}M8&}-RFjvm-yJF#y_N+x+WzTs5LO=SF1Wn zadxieZ$K<&t7U^UB%ANs%d;xVED-q7DBHZzPeMJBP?#)g0FUqjlAku6{}nwlK)aLm z6TnG(h2jGUO0;iBhe7n%CI!qa3Z|E(z!NkpuuKTMfP7ccvH5ovr5ck>eqWT~@J~fA zqYHY#O<94*{c0Q-Wc2wf*9H=%ee3#t!=bVJULQ>W^*?(Bw)8^w>*l9F{qRSvCHX9T@e`7` zzAW#6NB%xc^ZU6ivcn>yQOw9I_#*`EBds8vwN;dVHLFcSCjLnno4n7Z*WjM&sOg67 zQuLS{Q;_)i?4Uy1rKUSe_yKJ|%^{rm@%+5uflvr!r37yqqF@epe|7^nF=;9Lt?OFu z-XKKb3Lzrp%6emf`G$3TC-U6~VLQE(<4<2MAK;1lyW+esbQKc{oSnP=t@Wu~?R_00 zHi;UaPup8JI4TDO*2nu`o1U4Ebv%?Nj2ym_my`QAU`I$ql<6?84?-hNatK7PJ^{bF z&a1XGg^ex9Rq%{SgTv?rb5qxi)}CEfc8L>*hv_N%tA$e97FhOl110&bZ_w{8B!s%!~$Ax zqR0CxP2Kq5o{IIU_9r;1hv8ZIp(Et`H>!LN18wlpz#V#@?F8OF;hI!4XdzruPsPGz zdJlNE7ynvJxG8&Q?rQPU_oOqpAty}*47m6(jB;S|QR&aK>KU8s==AlvbwO2~D~fvG z^6HP21c2{v5XxH8~)c1Z$7JzP{2b|5ZqAsVQ*Uj_# z#*n*YV<{A~z)6FUzE7zrSX~8D6Q8|=3f?;O`PB{ahg9Fsbbl_6;)P8OmPQs2@?>As zLqh@$PAlR`ZqSI!k_$moCTtd&yn*?C=)GTR0>rW|sPPn`!4@%I;?PZ1fFZm5r+8Gg zzVHmoroku5c)3UGhSNGygp@MP*J;oHfxQZ3ZTz}l6YkD#Gkw>iabFwPs~Hj+)gRwGf; z)>IHHfAI(fC?B)Z@_P>+J2!p~yDZ?js4&xbaV;M7;@f92F>b9|q^jALil)8{oNrn; zH#1!E?G*DykXt2l=v|ry2PppNjigiFqb2}ACx5x$u6ohj6X_w#5CON%8^VHTThPvDKU!i)N zj}y_4Xa=S)YPX3X&F@3DNg(UPiF8r*^F-&Eqx9K!CU`eDLEk$xh7cJW#n|X`xtZpH z5H$D3NSvLVxg+0IwT(S&L!CI5Wo~4<G*VKk1zM8t9FgJZ10dB@$4*y$3A;W%`!Uo!_&0`%)yIL-+_nhrO81>Q>O(z zQ9lpwP0}CaBdE2*O=l9i> z=|%Ur11a}hK-4XMUHxn&`nz_$^uUjUnR=}c{(Yoqo?>BRS8L)HHL?9<1#5jLr}8F` zP0nUi2F;?ZXlN7$+9zYcZE?lAXRBQXr*FeF9$P`5P*CHGji zb4xHVuQM=~Bfq_*)^n{AY^y7#m=Z;k70)X~xxYwm9{#btn>0Y4(P$B z^33&P!zgtWeB1kK%_M!2wY?}a`(i_&@%s4Z30fG(op((FjrH6m-3_fVauwy7#^&rruMqYmOQQnCeAM%;5y zCsjh05WauvXFJ{$AfYEhU7?$kCv!f?yze5YyNk=O3Fj+)oYR%3V5nCoeKOsFuE>}+ z^gV3pg{|gBi&=A##fi3Evw=1A04<{hGo;zLRX>S5%3MIU`l69G2nz?t;THJZi~liO z&qm{27_o|64y7+?$7_&XqBHaSeiWuOLaBEF*p616{JvKMVgT2p#s<{jLv_Y!lgx3W zoU;tcr9;oFn!k|KdG>d|T3R!AjP^b`02S*l4}K)XKcaeN_~DHF({Oq~t{lNNk1#>#-xuA$0GkWrR%OVM;SmS zr~KBiHxH#oK^u1FR>5ASHZ?|Hgd*!j$noyc--kdwCl6S6Z&CEvzUD=itr;Q(e7gVW(sB6g=&Wm@ zm{N+f&3NQP+gfE=ggoO9WNi3btL)AS)er-Rkka_CZI-q}b?X$MC z6IvK60!I>0m@&OfBk65(K&(efR-plRgkb;jAo<(a_sljIzRf0iAF;W;w?75pBUM8nIk&i6@% zs*V>;*C(A979oGbIhzt^D=qezh}SjR)5-JG{{m6R?UMRBGha-7xnW7d zp)*H8*)E_ih5Z~(4c=PI?yYUp9v>H0KSaIoyorM!T`^chNKeBTz+T36kU#tFk)V%) zU31{9>6XAZ>q+p63E%`dId#MrNc%{4hr}_YV<5+Na!U=|Bu73@plDzK=#DTi^JCz^ z2-irg57hLC)um;x&JVU~w;)?y$oA$Lb+ykonUr>e*vnp zYCoh$j94vhhwc90tsXX>@j&7U-VRS<(zF~My1n-6SEk=anx~eVnwqmK+oP)S5D16B ztPTxX8P$M-?N1=R zWzDYfQ){~)Haf!}c`MteXhV_`Jc-J!pQM;Lk0AFYL*k}(6H7F-B;?fz>lZ|vj!zk9 z;BP9&Z1EXwZbcSiIiWu@Jl(&Vs;CsI75yZQAuN*Sr0)6aZ+Tr3FU`b2ADTDwGsjT< zf&-uOdCpJC3`^$W5zR8>l0?bmZ&lc(>8^#x|?m*+O=S&N=g2tSyA%1StO__nbkwK2T88!$m| ze~fUoil^55{936WI6eott=iGswC<)bP?3c-N!D7+SJ|vpokURaM8CX8TwOLs_e)TY z;nycVL_0)R0boZ%ozsdIQl114VS9$9cjy|&7JY7=Mtt}vqq)`eS%Ypy8pm5-N6w&& zla5kJQjuH*lRr}-^Z23zQ2TM@@?!8mN{rl1`(`qf^~o(i{(klzjX+D;-8R2~Ni@ zV+42Wvo~+;tfb_&N?d7plY(hTWfidta}ezC!>e=ZPGbJ0p$#HQ9{UbUM#Z}CJ8Ruz z!^1d|&8>2Er_LPp`wtmkkmY2%0eFsl{}eJInE+p9U9JR5>i68u<;SL|xTAJ77CYQL z7Fx1bO0;9@xOUsZ6TQmehapZ8sh&6*dcw*6v?T(wp393CbP2$__tOS|_y<2Y1X3=# zgo5)e91FIZ?%1vS^ZON7zDc}=U*HSO7g)6J=9M2xK$XNug`7#-8Ff3Vc1WD&EkXN! zL0pVgkI!~Zr|iNR9G0x{-N^!S6G%iQsoCeU>JlrIsU{=!A79TKr}O0hKq5b?tE)_r ze)@KW6%;Xb!DCLC$ypOs&lvP_f3%CV*xOns>dLEj?J(nDrtf)LiaP%wD-1oQH2(Tp zP`g-&FYn`J>!N(F`U6>u{Zu`ibB^qsoYoN)_*zzW_D=98wedUjZ4$o&Vud&kUPO5>-VlOT{}BjY{RxOYFrJFx4=FfQ||YH&BiDF+&zO_^wkRlAewJf zXOjtchY2;qV=!8$WF;dW#@`i3GbA; zf@j^lamj9@isH>52lhO7cQ<*C@6{7Nv8(PieugeW~T`0nJE8Jvj@5{4d42kBu7d8)$&>f;ddgg zKbAvc;2Ugk@u#&VX~9t*h&o_HqMzyHidh`UwEPNvtn*|9*b?kdk3vp2XFB(G;jk{* z*CTb8WsLv#Bh0qH?1ZTZDNax3blH zT}(psuLU`q&YyEOov@E`pr4U`_@&Qumg=+j^5z2PZ@msTu=$p*wCS7<>LB+vz30n4 zU}608Bn^fe+8$c?wyZ#-i+Tg2qrWkNOx`|vYH5d#rVY;ZN8iBKy0POmHQi`kufBE- z)g-faU5)4ngWnu6XUN!8BA**eM=W#`yh5Bec+-i@h<%>0zcA-(^kY-|bm5A#BYxD{ zPAce67i&H^20}b{g4vz=YTnOWM4qHsfWmvTeU3yb5j-@k(E#x@*< zGg#u>?eI=J=Vf&?EPm9ci72R>O;}CGEDd6S$k=E?0GOJsGE|b+q$9B?R*kVE#R6q04#0(-a0k9 zpLG9<##bakP5Qr~J{`Sdph0i-3b*d`?stbtBH_I&qMlj-fw2UlVx=31Tbj*^SLu(1 zb=KC2hDK~?*6xC7*2=r7*PxY*TtZh;9fKU6A7jnYu^_~U@ZWdwn)T<#=abcrW|bTG zHb%|ej`)nO9goeIcw(sWr-Fm|tK0~(yC=F6(S|D8)b%S5%>xU!WC}RdsBozLcq{Mn z2b(XU0M8B89R2IJ2@%h8s}sgYyPd}6QD@Nm^*)`F%~k!V8SUhiSEAv#_Lg&p?Uzga zFfmwzqq4y};WcWZpZRkrY*;?CfvWY89|s4=4QKaogR=~`i9nezRep)s`S4SuV^v$* z+$#+VV4DSEsQ6N(0OY?-s6O*h?XBwQfO0a57o@3lGj znW-W&wW;+kOLZ4|>zlY+Yrhu~ki;s|r8`9IA-Yfn4L;fm4fh!@mc@0uP|fG8Ev6{9 zkz(R(hFBxTJ?&^W#2MaM+^pU2UGAK+(uS|?(MLahm@)z5leOjD$P^VEn3|WVY4yUG(F@|Py5tDy+kup7D1`&|`R zI;}nCw!ph^dwj6qyW?1A!}Lj|r;q{hIJka|M7=NPT6k6vM3k+UT1IfOdb~C&{N4La z;qxnUCKIfg>FI>RlDggFk49~t4<9{JFq*NjVYBt!5pjDg@^irv_Oq^lh2?oz8M$C2 zgcfm?j~kSY%O@&Uvz+{P!ImPQ-Adnl$TJX`G2DZAod0)}%gIuWl=?BjUSu;kYBvkL zzeH0k@8+r46m~)aHY-yckMR}_AQLvhtL&;(sRIF(=Bhv-YV%fl(lhX0t@U?Y_ih00 zQVsaW`98(WxygIngYQ4PKlpV`E_|?iOz)GYYz(*T4MCaGmiN9P`rT?lUyEIDWANZh%es4r)!a*vNFoy1sIAFpQk#w+uC^z_w z&9$$PH+jL^GAI<+@_A-#N`I=Wfzh_KKn8^WpNwj zIK8`~Ir{4HEWI8|br;LwVV%3OwI*3sxZ;=DfVKroF=Z5SR*T$y03$$8h`hbm zoN9_yC3P}jXJ*F*AN zwtWewKf8%kmyZnvXr7+RFi&u&H+`u`WHCmoYe-@f6ph~fBN2II6g1R|UtfU7a(dP? z#*q<;)b>^(>=_$dI&XP;Ff(9R=E0H;Z-Vc1oAFLgY;8rC*p+pfj2}(oI4n5^>3IMN z05_iF$g|DxT4PUA_#E;eY?i=z(UMcwnXkfqlJ3n{HDxu6Q?ma+Lopf3DxEV2-#`JI z{W(~8wrm2qewqTydsT5Od&XI^ovd6M!y~vG>f*ru=TSq;$Rh6ZY5LvK)4PX54dN=-llRB4HO&XNWZsg8fK#7Rkm4HOq`X%}u zL(Xn>oQ|eUZLLT=LiGGXsO8S?mF+y?d=)f8ZVZ<-zd+=I^;X4P0B#>uA375wqZAZsdy3YCom>8wNr*?dTZnV~QBKFNI>^68zr8OX;E{g&WH+im#SXUiR!ljSEzB#Z{FEEC z4lBuEQ!KQ3lKlscDIors+vN_c81J1ZZ4Q4CK3!pA@Cr>``{O~>ptoU?&X27Yq6LS_ z65A4lrUyq0?RUbLo;q?i}8*Jt>IIb*gmor%ZGeGBou_xkJVqfS?B?n1o?d9s9SBnMQw9oP&bQY8NMDtuJ3h=|pMkFKtBqtxi*;52e`8C{#wv7$WYNqInrvU%IkOn=`7- z@P}68J|M-Q<~K9M&}Be#rr<+c?Q-w5*WR?jwHgpzB=6u1#`wfzvbJa&2rt|G$3|q! zr0&SBV_%owz~;?76OSs*S7n?N)9uIvF8|Y)>~S(@8&xhN`AjMhRG7zo?!i`N_0{=g z@YUA1qO%o$Zac7`;^a{JXb-WzccfaUqY$n#^DbxU7O`?J>J#aXcT;2y85Vu~qBaEN zpM8*->qHaeWsovp6OZj+Fc;ngaepo7xt6<8sgBAGe7^1N<>j;zNMb!MSLe1@LbH-l zQW90HQ@tzs#DAAdmbKC2Ht$Bw&g4{Kd@tZuf0-=U-M0{p)9b%28Li9R4j*2p*`U6VD zd`25WMdEQ6+r^Fvs!Xq|`^!luVmYWey6-+^HKaP%ON8kST1v?>uzEB7#t}DtO@^2z za7dF#onjQ1WQc}%hWzQ#+aF5%S=vnS<7SCe?VC<)2V!ybU5Cwd#EhRdMZBcybs*lp z8^)5@9C#mMUf7t~*L^_Crr*vxNpUB~Nfx-8Mm5*#%U){>eX7z%g6ft&{*dM5XU+un zCY^BCv6z@p{qmn_+B(SvOCjuU;vudthO@H-05$tDgIO6z`!pA88~GGI`Fr1) z@zOu17#0hHh>nJ= zl{AF+182qjwb*Me={m{@9c~4to<{zy4kW%&1FtAR!%Ge40?|&Md)6h%d`iv5!uof~ zOD4LGj#TX;&;@bJEeCQ(P$@tE3m?BK zN(}$!Me**NSL-4blHDASzUxJLP=xD_(t4*-`9|m zhskEo;10*;#0X_lIpS{fEWWz6lc4_dcqx&%Pg}DaUE9S3);73 z!U;k4rY76jt^|00hfkrzD(l!oGy zA9l93q&()BmXZ^Jdkm2sIbK-WR6rA?i^kgg<#R{fNz)wtAxBTGH}7W`yawZ39^cAdbogGro8FnvlC43- zEB4fH>D;+($#K{pg&xu<^eh)9E#5!0Pa*#D-2pd%>5_E#!@Z0zKd^IBg~MpI(nmV4 zpylBBE!}P~mB{gsRtNM5k)fwjx>CRdYBjo$$J?bU*nq5th&K{^wxT&5LswSqEiYXMiWXEj^=oaGw;=~;FUVdfMUI8Jf*eYC*tJ0`3@C|Q>)wllDmmpOON|o z=xxYCE@ro!+by6@9t{Jr2JDQW>waB-Crm?nM*aQz)*`KLp_;z1-^RazuK%bVGWGof zN}%+j)Y^`8UIF>5qPiN`$w?PzIi}pGEOMZ#$Ru1pg&n7QRH{=Qb$zxK8x!+o7$Slk zUbh9;)L`_WiLGwadec$fy6H!~f2x=ulm}`mlHxX$3%<|x#~;y9MBz1S8%WDrJ;kPr zVJ^xSTk;t1BC|O=sAye}7xx};fng5RVl1+cJ*e}49 zo=FZ8x71i@)OCWZ4i~YHY-UqzYMJO~jm6|z@04AxG|5 zg?eEw@$QS*4QJ-wxwiSWc*66kw1`?uERjL520>p>q#`4Os0whPz<2@T;>U3Fg;b@r1R|S*L=pHnusX9Y9v}{Eq}5U1@;GRl((_r_NP-DNT)5 zVEe_ooxQ1iB-Wem>J)L#`>wjk7r*>2gr;u-&`Me*+6{xg+G(6Zt+gWfAxy|dhXGEjql&Vh?*gPC4Z@6Xtc*;OimC?XnOD7ziPru8#z zrb~2v4qyj&c$0{YsHrhtao)ASKjxi8zf1L)in#MD96J_hLw@{_tSeDp?~2Wzf_-R| zVBXapMco*A?v)YM=(F5xp&84V_`(-fSByuqAil2$u2*7m&@zu3qbff<8jvR?|qY?6*f3D4^4>@);T7PY*G- z%Bl{cT2n!T#YVj0`vnZJm1-!`O?w>i1`{84nLG~vx9;z1zbkygt^+T#7^cPu?Z^M2-u(UhH`5|(smBrG{9s;V_rz)n zfpwh!C;RuV2)|k1Yjo3)W^FuE49M|8HSk;8MydYbM5xHQ$P;nw0y!r0TOt2DBVIj= z=FY4``zx4o8b)cZ?xrx=Pm~RxopKkK?0M%d_K`V1vc^ClR8+z7d@XoVk!5U#motWY z3(Hpm>EI=`N2D%sgBaXjgvW*e+S%&HJoXKPqSS_oMVl@je`jT3IiH5E;Sdny8Z`Sm zM+(t9GY{E5#}Wo0UlVas^pTfuU1ZDn_PBFC`+{h`ISgDT^$*!b<5-SvsR5(TY`% zGqYY*>KZpZA|D^>TY$I|p=w&*yW3^a7-RaG6itP%C!eT&EkAx%m?9Pa%R7z0Xa#fI zPad}H*0xzc4!gj3rwIRTi&}{^9FPW94df=7aP0E%UHRYSG408GzOe1d=E}<3M++YP z@4A9uzVg4Z9Q*$pkueI#02+3~U872&bB!&?qLt;jd!C@>S^5 z>uea_I!0dJ_Bc`W6w@@eW{c?Il<_ujD*WC}OX)1Ah8PWHe69Gxv6`bnvt{g1X0zr5 z#!v=8xoc0pEB=`adR#vA>!FMb{A?$#*${ZEFCkAefMwCH6U;zVX-)+MR+8O=^)0l6 zt1jbIUrSUT=lfjSdpvNu$$fRTy6^R1_|BU@Q-sQCoYR912di4{zme5;HW)}nlN2T` zV|2DT*wNAPl9V*0@{DUK8pr9&#D{_1*qgxShho z7IsX$_+KhdZ9FVimc-b&xNL%lg%HeGmY2E4r|Z2D)FRpsThdf>Uton-#ytMsxg?E2 zAjti{u3FghO;dC8U7tsVoO6K!#08fQpFVvT#j-Us%ZBC#^{GBEU3ZBfbKE>1By$P8F)RMwIfOLU^S0`Z4qqy#E7PvU+5+ z4=}W|D+Uz{DKN7?{T|tBz)Sr4HKo30h|0?PdRFPLE)3eiZXf6Wnh|H&jFAWU=~nAK zFoZ?#(&?(I{=y(i&PxcXzDzQR|M%+u3ssStjM>Rx@^B6IB1mcWUEezuNxA=pSp4fM zgh!IP>)&%R{%0kAz5M@}Mi>2G%k`hI-<9zHH$eSAWcQ-tVkFP$*;zRTA2cu^cVDMc z$eda5HdOw0Jg*?1e?ZlBZe4LE+7Q)1S!S2)rM$};o;RTQu04mdNg-Z9lMErCNV=z{ zuTQ~Un#yW`uzKJvNu~LDddh~h`yczf>~}`EqpVG)X2bVu zVR!bwYRM47ivKqrJ|t=sf>nn1ATpcp#qw!4aODgmRj$W$Vs19~SH|*3zw!C*7u=Wf zMwo0PSZW6LQxO>Yx2UM=gUbJT&zMJ0Ai%-O^cK=F-rN3J=tENH>eMz_8x?jX(}%m8 zS8Vh5qaBkDusLS_&WS-oKVQCbX+7KEBBr!>_OCp%4PrUd0`ExAgGb}eN3_snEp(wg zj2HLL)X$s`cj=DFMSb7Yp=9pga~uBaeYpZ~uvBv8d-pYuUl=r=B*SXEx<~ywU#jZ8%d5vDH4b;g_3AaW#-9;mU&1N7B=;0>~&2!`stq zZ5N3oW#Z@$^$|7Nnk$QbFYh2F0{z?F|MidmeD09(ulzn2`y`ZZ4no1bJaUGb+#p|Kmeb7iP8cVCL|KbFc7rl;M416aL0mJGrdk02-&A zvQKrjzPjU6IC$?^$TZhHW)N%wF z4Z{;D28q2R7Qv&%mdRWmhm78f=`Vlm+~l4rb>PR?U;iIavIA*KbArBQzfvBn_~!wVk*h?C+;%XOAo@!uX+t z?ES6z>^Hhs+dP1)ZQDCHG@H2smGtns#kJ5-TEM zO+DcdT(;^8mL;mvGX03XJ+Pl0yEt}}g|r&5pmFIUY_P2htc_?|QWSf4AM zhb_psj*{!2f^6h`Auo{W zd(WDmgP4=JXOOrJ|Dwb1Em-J(6AfxYV%rd=KHH=DT2{)#7sQ|trB3Z-1H(*V0pII( zI25W^7@v@<7e{4q`{K1i@N4F?Ue()EV|usW)0F6S#}M~xmHWQ3pZmTkIyYn2C`FPwYj{_jkbk zJNNP@Ngj1at8mpPZ=9wG+0_1uKhL>YUL2)8*D*-FT^yJX2bx}(p||%;6G8CzA@m^RJ=a;% zqnbhA-<0)9N}Iu(0k3UpFM=_ZQUyq3H}L#o9&$rE-pX|U&WnZ+)>-B zQxgOfO$##nWY%cpUT?XF8SNLu{$}C$P)6O~T{r=GmTgj@@0T(bD+{@jgKF6L`=s3K ztMnd0?>nQ!$UbiT!C-|=YSt>VQE-WkEr96VG}iw8kvfNuiy+0?^K;q!hG8AFe)syn zx6W3f_dyr?8mDNgA8_f&IpY?0*9B&D_(lWh?V?=uyd5P-xtYL}Nd0wbgyot=XN88+N7yzQvas zez-zOO~RXs-82xlMW@2WCf|Wts^}B0SFa7hx5r$%Gu07PzqQuisFNW?o|t1;x(ALI zj;*azr);+{S7t3MY|TbfszrOxXjw))i?31`Uvtt8bi_(PIO7c6u1U|he-~&cx8t6U z8lHMULSV69^+*I3Rp>VHCqYSFRl+Rbh9T^qYoIQe!9(y@hk&4A;h-Eg(bsx>m|xk_ zHTpyY%yD(OBiMe13asKlI@9@eGE2wxJ?|1Qp!6<=yH*BxgHTp)^F0n2u8wCCE^a;hABU^<_ zkwkX`leOiL*ziYuLOY{#aFyENe`Quy_Z|HS9u(Vq744UwJFtL^ z`xT-jfZIE?&*SBt{qN8Os;Q{YSGP}I&4FIG2Z2p}^KgZ9G#1hZo!rmbI@!N}U#32% zba^#?gH56wRDtzuJFLZvb**Zi9kQ>(mQpRT7d~4W9ST!WcE8yiez165A zFsw+gP(FWd5fVw%N*$>h*Hy9EZkDB0YrLYZsAf!APr|t3JSpexH9s0%6K_{sq@x!< z&{axTM!hYqWd3g6|31J>$Ni-W%_kBIom9K<-cS*5pAw{1*1lfHl6+)yZIhBXFC78hg0mj{Zs3& zm1UhnI9%G6^!oe7C^T>9!2?CzVMYYwvmW^`9^f0l9?fnk_oBQ(LcKKTC>RU>- zWZ$d9<3+hsvd!4JuC-q{;&cs<)*NcPJ0LnP@*c72B?YL|(BMzK`50NChft+vA?S+C zw81ngxD}+27KJoIZCi~y-lN+0%jHxyetTvCirC8Gm94XS^X)%@`G>r(J^1qkYf^w) z8>5#$e4=76{hq<6m_Ge09y2P)`Cd_V;Cm1C6VP*|%4Ed<3l3iq>1?B>prELl7dQw2 zMY`X3e?suqzUR%fUmHuHrBdPFhHHLSYe_MSS z=7%ap-A&Wo={Cd^W5-BOT3udKPigLQhiVlr5|qq*&M~95X->;rlr38Q?p~@iX^D@$ zb$XrJS)>UITFj68qm9w1=HJfe+=92OWUL$fj>|-y6~{gf;{=npH=63RVJ1&3gMn`< zRy;2a>tvq8d}i!ifYVF-#o8|GP2Cuyyv|E=x`*0e8#!#AIt(>Sa4#i3)M(LXH+W-n znI*Xt5EtF-LQp@|sYLm@Ap4c8+33E0uR*4 zKJOx)neBb(1}0V^mD6u(0D?U5WI&FyO_Lo zbMpY9r>@TcrWIv`@=mTHk#2EeUS zaaPR+XLg^e8;#93C5x5TlUj8q|B5g^6`+@`kobm;gX5m>ioo*R?^YaJSdezUuKX1BWo z@_zz~;~~egFPda=e9d|nmOYm(9KeWV=xGW&XqH^1MnrPV>BVd9a$MXaiGgb1-0EhY zyP-F#7Bp|2Cc7JIS-&Iv9y*qW(fLmcP31${Ye#LDG$JE2nT$jZxL9X9FFo!)xq}~g zy7E7L27YWi$nE}ea<#5RQ=OsWq|nW@b}m{YT3+E?e>IkV_SMnXPa&KLJ!@v^4~zOQ zCb9V|-9}m79Lc>a{E)Cv!zKfxP%n&r*`~VjktLGe-vEHif9=@nm$|)ZJ-G6!eInmB zlip^Y`+2cm`Sx6jeZ01IlPxQIw&|hnFy}CPj_(cLm%6IB_)lMoWuz8sLpEfm%hx{9 zvM#-{OOi6`A`CAOk3Bpl zhvw02zAHNF4nQf@v?rZ{eCMeXM2b4H?Ue!G7g)C+H={}F1D6uwR)B7JjXqlAi34?~^tYQDzDCSQ^?#g9J}AYBX`SLX-7bbc zNC2CDTH+9(KnQ8`!ie*~Vxp5~_DDK9(UhO4cNHoGgehy`!KK*LC4qD30U3X96lmWG z#zepQk_@|=C^oeP0-#{SeEGMAbfMUnFDVlGrc&QZfREdI8GolO-4CIT)GMbEVGVw_ z(xHg99}$GBF058Pv)xnZUQ-DNdb;xDqAn~6{Iiimu8Yd$rDnn;hseQ^AHM_(es^8) z+#fd>qHNqPFJoxR_3HVfdWR?B<=}|zv?3||EDHykhYexU^XA?J<|T`S;xEhnnZwoh z-*FU1r!D{nbOTOy=Yn6}K0hGcsxWdWaMum(U@|M)GNc!itc!;G)BC{r>#_IL<@$b3 z7HR#FTAYwRcOPK#TLi?j&kgK`$UT?k?v-x*?*uug2#Qm_yU>d)+{ZX|n8@FwbH>HuLAmgWkNrLN4Ti;41>thDz1*%wcwC=Qw zAXW8oKE@=)zLy_2)U>!x0_WsS^yvK`2oButDrUeA%(qCC&FsNC!(8XC*!|<@u#kU# z7Xm=cc^`G4z<{+dGV&Ly+G%H}JP**-*kj3;)$ZUFPIcU#O9;(;RK_!{)MU-E)3hSs z>6Q&H6g+hAL|LQ>();+l+BFgTJSOVSmJ-}9KFpn;z;EgM*trdw2dT8f76V6Cj)S*xzi@9*!UQPcqkc zHc0NGmAmx8UIDe-{qZ9Rl<@1f!{`2B>vtT>^kA-Vj;LL(BGP z))%oQ30(!Q3NeYg`TV_kY!XhN0hNnawO1bg6{#%|;n>^)H4s8S@V@y2L+kwF9$M!W zgV%2LA%-9w+rG+~)b)<4esIF23E94#XD$^|hcU@CM*81BL+e?t>mCo7TopBRzKZ*^ z;d;z+dpa9DxDV2kM$Nj+#DLh={)Znk9sMu0R#v?3IaXS2uUqIm%D^dGcV{*Tv*mqi<4Lw+Q*W@s#yU_bRiZ|@S zQbQXwCwD~E&av)GAI&^z>T0b$z!HqlO5zazRwQkSj8vp0wBa&dnM(B8^fxy! zRV)07PEYNX8YIz=RwLqhTX#9`-HHmCs5!SvZs0O`!k3jpITl9wzX>KRJ}{qVB+JK>ZRpM;9-Tw< z%MZS^DARdo&=IlTXXE`!+ri28PO#hhGQD^aTK@q7)PQOvi5)J-%sZ^7=g*bz>-CIF zuhs5Bd|)QEY5lp8+0d=u%cToMm@I0y!sg}}Odr$laGfdg!0Fd|j%&d3abt^HeUMbC?NzIg4U)c!LgBT#i?w z{`hAj<`}&Qh~bOmTFX7_c&!sQ#&eCHz!_amEBA-?{8l|Xz#jc0nVBFAm%miM@f8-XSE5b4$76F zCKw>fp-6b>G@`$u{%Kyjy>eOPAgE|_a=Ne9Z_OkE>68<`Qk=8$XI%4mV!orEfNs4m zNp8fdn`<>ZO1htcSsqYQE!Dh*p+$Q8^&yDXe>Ydjv z0f5h!2dH-m97A<~xGJAdBpyLAz71Y2Qq!ge47H7sI~TE+S)RAGnsI~gkk3edxwZ~- z|Lzgjre1(0FB^zDuo(Ej>;*Txlu*9Y&CHD#RzU=1f1S|Q`aX@R^L&(?M-E%c%{d;b zIy!2T4~BF8HJ~peAn%q}vOANS&qYRI8&U%J-QWjuoJQu$-EF()7|bMmYv-2Cm!bpR zLl<1kUT2Cn1mkj0e@gTcQR`k9X4^ay)>uUzbnEgC1XJTX?d#QqfRFTKd%y;c$hV4L z4)9-Z~XOBAAT;k9{W?5z7{^9@BIAK%zsCVx$NAwD+z zWV#Sk?jA0P27;mrQG92MYQSi+k3s3+r9L^RHG6u>wQ0N)#%e5^C~_hD$|EpHN~K+E zee!!A>S3ERj-#K0=HotPRJJHnp1n1Z8dUDAT*Z`;iFb-x@y6cJW$gy?NzqKKoL?l> z8@@-ik~)_+cg&P1hsxXc{|{ep9TjyOc8#hih_p(#C@9?nLrDloBi-HI4I(i#(hbtx zGjvGzkV6a&(hS{s=BfAn&iU3l|FBqVW`23!SMF-wA6T<5EtlX zBf3;eN4@-3>eAZtT{kfnoY!S4NS)8@6%f2afw+iVU|P{uPgYwW^e-ADGs1J;Z#@o? zYz;S_=QPS8QBkHtiA+f9X$fTO>I|6h#2z_oEBJYHf8pe}UKm_;lI1S!)6inC+l;_( zoW>|+-sbf~!>>j@SSl%KA&gm_8<$JNU6;}Ce(|K(*tPYCRXkFaNmEdKakxw7jhlJI zkCI=cQ1z=1h2WVqXafRukvg998&g5@rrYIx=ugnP-&|^W&5-xl*CRp6IoEp~(zAe* zH@z}gG_1YGUYT0zx5!)oVXc2vOK35V!d1m1C+K{PVXE-!E6xgBIcJ7(x#=oiZP#I5Z(966g@ctGT|&0UY%&1ku9dNN{}*^`)u>pFi_l> zz38iM&wpaC0t{kfaNiAgZ(nz7|O*fuWSNw2-l|u>8$f&tr#dlrOYsrQ@36pLfXmppV0y z-QAN;yi3+DtBUei1SDiv)-Zb69REm)M-untl~$NF>2W7sSCb7_bx!og`6{6l$%Gqh zt$lnw;e3{c7gk&TqN#-k+myhezl2n&P|om%RcN8S%tHAxyw7RD1%{q1Eai#ac%7i2 zBqD2ziO1GzZ|~UK)oM}PMV4V-Wi=*5Qw%jCTBnsW`CGDT?r?jh(s0M$O+k$|%E9>b zk|9*GpH}ZtoL9vJP5pRPJI5uHCophAWtqZRU$g1jycy>gXjwQmZczyyg6X)2>b5rd5o`2& zy4+;`^VQ~ppO)v|OCg!Fa}awWC(Yus=Cysr9G`xc>^xtl13YF8oBfgCc4mYWEDc*6rGrbBkNj8~<_pZdCDem9q{9{Qlc zAD9!$??^3w*%QVn9>lBNt}TB%YSoeY$TYg5;7tv2(M*+o(=W+Jll!?@4Wq2*oflVk#pKTlOtqP~nzetA<8gnH|m5WqGC>IbVQ@E8F=I7m5&u53*o z4v1{mR$0%9zY3_#cl*ZQ8s$U!_NpgtK`36AI^Wv&k%ORghmcXB zD|peG#oSqTs^_zUGD%mVj{LWK*Sbo*ZZkL-W3$SBz&r84fyR5EH5gOA;PegHjFmYb zyCnyWbpusMhL_knooj~I_P7RrpP6gY8oiT65(K)%L+al4#twg@4|n1Pd!b0f?wYLv zLeUYT#vuUILuj+I+#r5Zca@{7ciwbvj|ucy9lpC!cvHkUdWpdDHT;(2ci70cuLqkO zWx6>wr${-n#i6BCT=8YDAmLEF=WhA;_=RZ~|8$5$SSE8XqYV1b=6BY$gm*52ye~pa z7qhV#xU26Kh`C&aTHYxU3w1;mpb(ec%0w#J{K%IE#F{lkb?efZkEW}@O%jN{q1~?8 z4jF|{+bSSBUXbEAg4<*vO>MO8@4rd(PS8~+GQv=`)+_^TW_?0_&Ru(2#jyEo1-a!|Qh8Dfr zO=H6{{5)c)LDT{Vb!PAfYk2M{|IQ(nC(DC~

9&5jd4urhyJy=WL#Yf8bf{_sOR^>=cfC$wp)#d6|6<} z3Z(M0)efISNEceyRgUR%#iA|1nD{=+ltikTiG@Gdw-p8bsKj)L)Q;V4gg&ucdtlI; zA=0DV(JH7p>hr#1rgPLXcE!Iw~%;Lg8B zDgoG{TFDegI4pnZozS@3Xy?#?n38Ip1hb!43?;LQaE0*I_vS}UwB}E7d*E@okolk} zYb^>SC+qrOZ4YWZ91>nxpGzg$SijRBep}Ic=-FGuIio0gkos;v=4*E($>*BW`PM}X zi!mR)Ufjj&Pdm2YdxvD7(&=i0OV8;_#rbCT=vS9dwXYY18f?D%+Xq-pOv-uv{i>;< zvf{bNr-d$~@s$$=PL6Fq+*sFxgV*}!2Wsk<4HKsi#)5yS8&04)Z8V7e;HM$xAI$Oz z->Uu-7oAdT%EA|o%68v~mI9;-Q@=m9VL?DaSTe?l46IW+sMl!o#&>cBC>mlLD%;7w>n-*WHF{Y^F@w6d?%!6ngujJO55>#F zI?8Wj$WXH}-blnoecYF;XtCtEZ-3kVrsw*~Rr!SnDaNM-tthi@YC&%|0_mB9o^ij| zaeikg1>$>SU&L0c{qVeIhRu3YyR5B349xQq8XVq8?z(uB6#2Yei}vzDInY{Kxo@;m zcb$3zY6b+re4|L%RBa@%BxYRfZY|_zD3&Ss1+9sE0{BkHVz`DhIQ+1k!2EU80SV$v zhqdxbBhj>q}m3l*bp)rg1E+0Y-1djGx}jsa#Bwg`SWE25$Q<7 z^;OZb<&rDIW}>U}Q(tJI93Nw0=1jJezLRs&s}jq=rpEOR!a(7}C{Qzb8szo_EN;Mu zfY-}tj(9(aGeWfGD-RqF#QFMd#8c-Pv)Wa6XI;#nlJfxN@CgxG>S^wmYP{M_*EkX3 zSnp2q9L7^Cxn)Ld)XVCi$BT(u1#8A^#4tgH+n%B5C#`VR1XpqCnb?*ibk>#p*T=KL zRam9tIVb)X;yijSQ<7VmE@YI1UFGelB>Y;DhS=?ry9}1klYrqYy3PqT(uB?+JDg*x$MPk zV&4SL$q>O>vg#ecuKLZEIG!c#f_?QLAQyedHnHpTNjk@Tb+T)#8v#ij-|L&Pq^&p# zT+v(sI17s|?oGU7*CieO1#qBN@T;xn?@O;wbXB)ld7vbE|QktOD zrLGaIRuGgoItdzlom{sZ3J(wnB##4e>R9AU%oqqV-=ERzAOygntw)!RWNFOUq~r)% z5-lcY^HMd7(v25-umf1^YO?Vg5pNpWxX|EW)N52EbTcG;aK{^EcJ66?z2c+|Qu*M?%|K{t^mu?0@BCaL%a_lu$>_;(n`e`5$-l%K4M&n_RacvNDC#ed z5pmf1NP9_`JGuLWnSsH{oZL~X-qr>6r31J5vUe=&(H{a^^0R}|wpVaQx zKoJ-(?23i{@u?2N$U_{DY}9(WqM|vHbxUe}dwI+h^Uq;vc92qln8-i>hAmD>f8PWT z<=4N+(?i0?cbuOz^NIe`Ui#-D{PWH9%fBw~A4~qfpEBc4JpI4GptyuD|K|k%`->2a zz`sxRe;yQBr+gs-{QiGQ7Op*`Cjb4TvF)uGZ0|SGKpDcVoosyewP-j^FyKFrPWA~SeF?dL^swR=P z#z~9GzX~GDfdj@l+1dX6{gOyMKL%ywDI2P|0D$$)&ETY@q|^FETepXik&zEHG+lGc zUIxe~R2lC|`*=Q`5x7$89+cA$(QM9xJTVW13a|Ce2bA87-Q6)y>RA?LVDq zmj#1=PC)iY_su5D3I8d_so*p2|zU@3}|Cg1`M2y?AB|=)Z@?HQI`?9^`8nBWAzIg-eC3tje?+ z62&~&x~r$6AMa5)9g|(C5*6c20l$MB?x_TL83?NCzXf@`$4z2SMyKg4T09e+kE;6y zd*vJRDNoxGW8G`7no&Uv;a`Q!NR%Kc1=Hi!HIgLt8JiS9q(6@QEQV0nNsr6s)h|FPA zch4AAtEX>0L-12&d=&A%)YQ_-aH(Bc(N_!E4$Vv8(E`iiA)1D zxUXK5r>*Swzh{m4StN*gT9zA%%~)}L=E(w6$L<|k5DBkN*ey^^W#r};6?v)b@bUtu zd!~zALW_p0WL#HeIbviUO%F2sOKJG_%YGmagyY`$x7)@)_dThCD#=UL-6$N@_xCbL ztY~p5K&6JNz~kCA`|M^Id`*64-~L)`$j*>*2Xe^$wTQTfZ> zTOc4LBIG?kBd(JLx_EO2)Yk=pZ)fYid)_byuP*Kl`x0q2vqV_lsr)gsmi zKo>*fu|JKZZW}dcCeDBbdIu!ku79rP6r;ni)3g@UlBulBi9A(1Yk}{eSi2J`3>C zR&pZ@i>40V?#HGd+Cx8ry-5JZx2;!f+}1~a=;@0a3zU}JOA^;K=ZhR+a=yA=FP(X_ zkBDqfq9Y%X<#cf#8-oXbWg73ANumO{i9ACY*D6mQF(sLo7qs&-GyeZRFx(soLZlM~ z2nJKF<=h<=eadYqj-ijkQ*sipQF*cJhDIT*_#6#2x8Qdd!;kn-0LOhVrQ^KKjQw1d zJtk6RBvbF}W+JRi?+)E*lgZ?I&?i25-lA+)TG-$zNZPXct*x272T=@7A%}+}(C03d zw}l}Me&NcfVtEtmY1smD+>r&aGcBT7%_-um%GK`tIYnCi|F^G2t|Vn=93=7HBrqci zIj=#_z@XEyMGeY`sv{|3pf9pC?=W`?;%i*rJor7nB;qrm_^LF`ycQ1QC%5G0Ah05p zh2Sfz!p7D0B&3bF5?ru2Il0CcwB>bV(eqzOd@SP{hfl~zE1^V2%5oMT(^}D}ya0Wq zFU_y(2@_>19oheFX{|g|oL2(=`J>Zuw;UU2ZCa*EDxQlTUhIFfYxpXfKw)Vtta#D) z#6w5Rv29}S9LZ|6y0ryLT$Tg%7&`cR&Gl`G$(yJ1xUDKu(F=9_i-`Ph_ zxxC^P()l<~9eCww&7F3t{VM})VUZ;@De8;LgCM%h_;}mzOuAfC=V)5OZ^FUQCey%a;tC zKg))YLh2bTXUOswKmN5jvmp?$XAKAhI;~e_nV6cM{)W^d+&^^rD^@X2*hNnE$EKw0 zq$7uJWUY>t{|QxiNgWDB_w;Az&;E&2(m4Ex+1O%a$N;_g6LI47j+PeI&UDt+?Ai2x zO4ZPrz-d;z;0oMm-}{gdtPg+AxHq)a^z;t*oi8sh-Ga`3v1O&VymOQynZham6+&%e zO@BO&q+_GwA!d>tQubf_?RWKg4bu|ctULd z5hy7YH9TDYMNUPG)6BZa3M?-lGDW6Gx;S@uq^c&xxGgL1h6|2E$0P-Xxw$zNJNwCd zg!o@3w{v1)VZV&dZ4t9@k*aXuzu=Fd{!3_hx1y_0Q;5bWGmX~$jpyYsU|h95h*;4{(I=)5VLp=HEb02vyXU4#-yx;F# z%PQwYmSuJudDGhcIXaKK?5(TY9|D}o*}12tg!w;mbfn$)=pOY~vrS82Jk;Gm;(SoE z(}{ASKW%#V!Dtl98*`%Vo0opRiCcn;(sCXcw1{#_x_o>RQ_T_xz#nV~EI%0zhE0k1 zSYVALVq0e=@rh{fgKs(*_%8#R8!!Dq?h1Ugey13j*N1eBvy(p>yTWpPNyBx$vgEgH zwm#QpU^mAEPgtgEG8J_pIa%6Ps>Tg0eib-Vk_z78Jo?<=QFw@9Mc>CrJP1U)fJ!X* z%jpj)|l^U6=wTH`d3nBP`xi2TH#mpgCL%4QieRi;~9;>8)&jCPiDii`N07 zOm80^|F#-E?vto66H!Mg=PGr#xVdlP0EFMmR(wIG3%$y6Mi*ZEj)WAACml?pwhK|4jPrEf_FD|QJ1@L6uxAu~ zcxYqPt=+WNtpkVU5+#PZPadk091B)4UTYFBQ zTe5j{QC^uJ>BF0fV}q)k(cNy8yd5pgSFW+ZZlhA1Fo!DOs_IB2yb>H#<}sli4QqISPo-bW}Pl4ZWWqpw2A zx-kqZU6>kQkF@(G$c5I4&z`()cz)rXa^QtPqfd`3oJ zq+LO!qKKM5cr1P=f}H4!WuDauMr1SHQk(A;+SM8YdwKsuKO$L6S)foB=9IosrkUDI zACA&AXt*Wz@9krR9IS#UeKl_dMZSIwJvfC+sg3~ zYM|q7lsLM)q^VX*XUL<&CtFew^9YLSKE%l-4BAhv4o)8y*k_pS8cwN2j=C|;jXZU~ z3c`I;bm+~bYD7CElsdA&8?Ije_yiwwk zNnIPJcS?&q?0fj!s_sU|--b?$a<9iUb=5Tk)Ix-)g;A$Spd^S}I!&Nk>*M{9^~%S0 zMlgz9xX+RNw)CUD9VGYJ5!d$d^o(LkS`QpBqZIcuto;?ob`(x&zWb?g*valO@j;(| z3Ws`|-CRHCtc#NDc2-IvO`O{ zBxYNyzOT$z(lHH!qVBki8GS)+rj;%Srx5rXlqLW7AYN7grQtb-^rvd&7>E@I!&IAI zW_8@|_YU{O3L2vg?WL^Ncr2~DI3sx~5kwyqLe+aO^h6jfd&j|Ck0y5SlZdwfciM;t z^B5H6;6Q-<>$x5f8X$1)e(nB-Xj6Q=bF}J=@{76lGwP8>GVPmZcBSinJ@hVjThoe5 z*@bqWi-8x*Myn+{`=!Odeieu2CMuxzT`M*3i6*jK#YYnq?Ep-w>VV&8$4o8jD~$#o z393$3@T4LW$ZXja<7zX4yXMGFq+D|XuH7L1PTu>gaP&2F1zZHHZ10%DrEbLiK0{=8+ zSJAP&$k|}jtWFdF4OyTgT&*+K^vF?2InfBE;o|b z4&|og2DNJObz+eTA)lc=C!u1~J;#>!p0c`Ytq?_9$F8?+&w^tzgoPBzHF`P_cbLh?^T%#hf)nlI7Qbp_I)G~(9 zD6j-OgC1&jpw+4=czJf_ys3z+^YLU}MDj63n=gkSTzmRAsGB3iYv=Y`HfNoh75}c| znA0<%ja z>74T02sd>`l$+~S1IEpj1-C2fFU(#Tmgd#mP8`{#-qmxb?e26UWjlRA-3TBCNuc*ej)pd3@#JwSrI-_w5xIyk37Dp{DcYTf=m=qqq7Sn3h{yD__>2 zf*lFYeqo+F%Pj`HhzrC{CGb>8<-)x5rm0N|&E9JEb1ZEhdptfPd|SfU8xs!?!AU7l zXVhQrP1xwgU32`I%f+Q}zrSV$K`7k*;M>53(C?MkGi{!eGH~JI;!Sx=w$yO}f5OPc z`<85k20#Zo5p7mi84LGCF${@z)TifF6jbnNc%(x1(%pUI#BkT%U7YiMSE&NRX4w?m z4on6O3-It}lH6Z?T5A2yb-P+xA7YRaRJ05@2|m_+F& zXu{R~MRRSOczNo(>xgwA}Xy6z+YXh;4JwO~BmSgneobz33&O*t{iwcP(jHqZzg| zfQ+iSC>CB~xf{M`PR2|o4I`iZzaUssYLm4PENE=2R;?&7qsDpgM_jz z))hb>G7Hrb?&OfUAdePv3HC}N4cQ3P?0DL|;tr<%?MExmF&<1x$$}uo$&B4fme}On zg>&kUqN1v-q9`Z2&$}bQpW3aiM#dX`@>}oLVj=tQHKOx83QOJNnr|*r14<|qWMJ9k z#`x;R&fOfY%E_9`zKQ(zf>v&Bna!j)2ZdKhrWezm3Q9^}eRilXC>Vdq1=)O3wi!4g zLOpZo(``?~@q3_#`G9Z}U(2Uw$J7~hI;&rnudYih({c2t{pfsWiEV~Ny?mN4@pRak zRe#okG0WvdOqxib-)#8G;(>M-yTWV;&SgEDDea&WXE{2x8pji>>rg^r$n@=;4AE<% zGFmLy=`R{N#l1ts+W&j?x^&i~DxTgSWuvxu&SaM*b|6HGVyt%LaApi06HYUoQ?!5#35_g;~D=I-R01#((!w~ zl%;A*Q`J2PZPsc~9?c2a(iMww?YmLFA1&Y-<8Z$m4c{hm1+@F#b1ZqEsNKyT;(`{e zdD>~`6vc(7RZZ`VgxK5!pmq<(EDz^b#uYMv8s}1fY2QE5hs{=i|ZS zxpMDCc=u@I!(psz+TG_0?|lc`G?E`PyM@>Hhm?PWFfM8ieu+kInN2WFDJ-WSH3)s+WBq^|}3Xja^xm)`B^ zJt}wkESNL(fG?@|GWa01q8?h@&m)`S+FLFub?;#xUoG8}*M_fsz3;&AF6h*4_j{I@ zUpl9zAeT~J=&dlypYXE4jt?&ox9?b_&`AyDc`w%HgqQAC<>OU7@PYDA=3A7G`O7#1 z(xLK7q2Y5HT8GKATlcd$Gmkx}Khkl1ZIem3Z-1;zeHgtvuTD#DaU++&xy7}Il`mY+ z$~UmvzZbfhZ*IBiXK`Pnn;G-cr*Gyy%$qY*`4E;6yJkp|s?~5&FtlTG^sQQPD^r99 zrn~N8eIem}H%%jBJ&;3X#4uk1Yb>x9+I(5SVu2SEAAKlJPy0$J?`iFko$4B>aB>j%v9r~0CR+b3-jSIDm= z*W(b?t{KbGR=pY9-lE^hO2UA0`#m6Wi%V(aPSx*?%K5o9@7qzF$5UYC{T^WijMDhL z<+?2Ff&9_a2enptHlf4yWXAe~bb=au#tGuOp8f6(SLXWFBIuBPy|R8a?Vc^XUS*8+ z!osw;N`s!UdjDgimt#L4Vz(VVJU2C=oTg!~!;f`uL+I%DmAjNFi-}u!XfMkvX%+jD zAb9xP%>k)(|0V5Rp&h$bB3zD(-*?D9_)D>;+`c|@<1PNfUH#*F*5e(P&;g=+mlti; zl(b8hEX*Gqn+kNZl__qay$B0|mMJQ}dd zb}3{%m(Z1MYSUSXYxZw0<|YOF-t&bqrh12_!N8Hk-Ls=#nuv5l&e=%-_JP)#OZM%> z{ij@s4;(xcm~5?*4@>0QMn}||X|2WRMhL}=8M~E@ESc3N2O1)Wu7HKpEC?B6Nrx$A zZ}}zaq-sqBU|9pSrAMJJ_DiS(>XOCKN#uM_!_Q{)G+ehKw2shrvvriarh1m^CjQ;m z1Fui*o>yLH#{m78X}_z+SG9q8KXZ^sFzp%R<);7??;tc?%OmLaa}{-k5~D1Y@O*HEVMO}xYIReK!TvbK1zQ&U|3 zbvz)mMM+jDVPG=rPe7_Ey>@Qfd%>9P6?102x`caE46G98Pi4`$hb#GB@x zBH3oPo~j5Dc@WAoF7ySYo@JBbx`njkJ7XSR>*WP56g*Mb=j{rZ9WzdkR(8j55J$@OaiRAK zT*%|`pd;|=W(Bbx)n(gZUbD8j6~45{b;#RAj$@~Hmvb{|)z5UdmgqjX7tX7$d_dwy zZ|RF8?|s*Dtgy4TxfC`qD=rIACr~~FGs+Mx1@xqPRaFcO!(B1j{ zr3X*z&vduL^@`=YP`3+_`4q3ya@;lTElQ-ZrxG<(t3CW46fCZGb*$Vh%QaH9o?o(~ znI;z0SlrZXx#!_E2OfvcXj_@Y$<34_a(ed`R0Q;7_jZbR@8R#Etbj91|B}>0%dzdT zQm1<1jOIllJ3t9{fFJodm+5GKYWYnf4!vASMfuEZq4G^zvPZJA0mcX>8L zx}XgPitr)0aUeeQ&_2J{IUBfW^|q^em0pgMdb%q;mwIdRLajdr1Yk~4g{qqhq-FWp zAc?IsC1n)#`%&rqY*q78*JuVTc_HY(^^C*V=8Md2Bz0a%NlE(h*h_5eMB!i#p!xC& z&tVa2TXQ?kD!vu3V_sMeu!?(1vDJ#ftBfFhh5}R2{o3pG=Je;Z!_TPEsl#B4$z*N= z%($E9D;tXabzC;?LD;J`U+=3&bmiK{Wzw8pEVHHIpSZ;+jeibxO{$yjyyRXnuoImb zk4o$Mp41WWGnsuiZC@SimIZ@NsO!ok-i$)kvMo~0ZJB5;B~cJ{*yg-a7BNvZH_G3< z*7tcHryKXE-)9sX#lEcI9qhffY723ar9h)k<=Ic@#8+Z5f)^2qoaxRo!TT$B@~)}G zHUid}p~$M?3m4^08>4Hha8^A>{IBQ^Vx&XG3MR9Ib?V}gYJHC%KD`gRF$6T3@@8J- z$16bcbDruc32G_(bmhPRNGJxH50N7JfDDD1{$7M% zwfQMEcCl-U5(p>{IH0Xpuo^A8Y0yLKsB8VRRXDnYg8^fRz^?Yu-5&O2W( znlb9~G_Y6I&=%k#=(8{_<>gD^Wm5;O`=hpT@U%o*CZzax9$b5_v4mn=r&e|JlR+d~ zaLhVwah-zQYZZaMX(fRzcX+*P!2L_7(SoLy7)_>(@{-~5B?)m;KiD7icl=yAZB2vCTiY+R6_%;nh-RaXib5Uf=(3h)$a5s6EgEsaRGDNPoz!p2CdF!fRW#D#E8 z*GuFIe3MBwI;&`7JgW11O(To#FIr1Rt)9+Bw1GLE@C`4%BkAU_LwQQMDgVad{ks&7K^%iCqqZ*4Ne&{f$gY_w#1XG4CzOhKA4<))ZeTNUgVcUl*P`!d)Q$Qp}QmuKH@2gbh#x4G``=g8F51chW7Gy13 z=N2KDA9x|KiyGuI-VLGm=pV4 zoiEA|Hrb5aIJ_ONSSJ0C+^Ik2wB-)Jo1k=}^`D|cm-ipKC-)X^5@Y^_VZC*}T=sjM zL`O#_!bF9`;U7PJ>M&+E;3P5mxk`$osq4r?_WZ?*nAq4gZxZz_@2sg}3jnQoMxUUd zK>f6nWAw`5p@d;2kD8?X?#Gdm{Nj<%6D|QE*}*MbUuJV-Ln*nw8|#%HYl$9g8FcLs z5{Y{{l1i&G8m%ty?td)LH91njS1VbpAlP0#?% zPV9dj+r{}P)gJuxO{KnN8H!M4WJ}d>#+2{z``+hki^SEnBGPV58LcfX+SGmHyi}dt znS{&w56zUUP8*ujwnOXvM-uK=iP9+(fM-Ijd?5QBFVqFcRT(F#@!N18`m6Ez%sr$ef)Fr6txr5XLo-;4gsuGZ(uE@H7A-#wAydC ze5E9kJ?jreRy#j0gChjIRN2kqfW9s$4F+(9AE${`ZX@2NWdlZ9Mwnf>HfJON|2$ov zP*=NOt-b`5qjSGWRG@)9XNEGCWVRF??q)(GCEu-f04I*Nq;K=y{c07g4$Pn=9D{%R z+G;^~cz?*DYRfCKKXU1?apr)DbJ9D>5PQb1rV@DOOkM2Sw+@jo7~%?k>kC&p0i`2?&w00&akv$6(*^Qc)Mt} zS=tFX9g58C!r@k49JLp3$noXe)juvRnN{RF0&SY&PO!Ui0m)Xqs1DA@&ydVQ=%=cc zrsu)rWff$dc|$iGW%7(M)Y*9#Ze~c{)>`MD*U0d#09r2uc(^B&c{RCys4Fqo#=e`{ z5}NK=3_J{Yh&M1&QOCL_4Xc)*#RJqlZXtR__v8q;la>8o2bk6-;}aW34`WPX}hy~NK zHx%oY+JGY3)?g48m_J9yZukGE2wWyGTROh`B^3_Wl#-S%E-UM10sv<4@bNd&B}@4& zXdoE)-#Q4)MAW{tR9BCCP*Wqj&vPMs>V*`zm5Soo*xq-%q)Gtekd?Y1sc!4|`dT?@*|Ba%*OFG|b1uCerSSnQl>84lV6 z-92|;j{DBDjNrOt^Fw=QLE^m%lA=sqqJ7$ZineVP68FZrDh(BsrQOizXgXa_u1Ic# z#y35^Xx+-b<>h63$Ce6&P1k}8Vbeu5qrBcTOizBu41wG1wmD#Ywm|2%@?O*Sag)O&$(Yqo)GPfY$srIBXQhZSbpx_m5W-Tzv^(JYZ5%f_H^OtbQ?}(-=b~) z;#Aonk&5xI&(ZNkXP*)%zdD_1G|E_Ia43Spk9>Krut&$s(+#6i`|_!YLoU(D{GpSE z#n(6-6z5wGGu$bm?Y#E%2}PAv5YWBsU-vv`GUgk;d>x3=B*Hj*_U5 zci`tNzTPZ`6D|o%HJ-tED$D&=PzN2Q&tR0JBAi2HbYNfbrZ!`O%^Vx2L_s6dt%3va1Q!~6l}|C zR6mvIv0Nn!V+$n&UwLM(Qo9PNSf$UX8nPYl!MDe&nIT@fMf8&MJLF43?PC3Uva@T~ z$OwuZK4ImX-pWE&weGg3P1f`2*zafbGx8KbxDeF)_lXrkjN1zjfZgV6bBG_)6uf9^&zY zN-!w~xcTVWvuAC&*el^f#e8z3IR7F!C-K9?^a#1}r47H8F$e8*;X zDtd(cDzhd0O+9>40iMR$)Q0jehY#-B+Pi$(hFm11 zQo_q6-}SEsF)#y)Pak+yVNSRT`Dc@forz6Ir88-^O#lVtO#7n9_ZJ!`=PHm?5nAbf zUO6xbf*ku_h%Q~Z9=*T6e?|53!VY*RkSBAxqi}@5Vw~|`tk|ew<0ec#?5VQU8h5vZdSncTjq{VP6Pe@R2&>i$jas%66Cs! z^%urh`z3NUggAveTV@J=WpJoNYWX2Q@A>T2V~0fa*UHYiut|q7YtG@5lSjG=C^b*N zXSV$t@xEs0?CbVKON(^|zskYxlWsN2<r9k5JkxX0ykOuI*S5-W$@d4bfIN9QpH} zBdTc(3dcu*4bI|pL9dY%mxs(?BelKah4u`RcFxXsu(}tP%cysr`vs^GkQeb@IPYo4 z;_S#;IV6GK+e!aAVFT`8%WaEbXNun^R&~w#A2|P-`hORLT=ZK9Hjd>RoCn^~Xuj7R z6kaaqrPxyj+%w~;?eQ}Qk1r0H2j4eOb0JdxXdm8MwzhAowfh7vKdz!@UUlX2Kg`lB z-0uR}Uy)S1HWb{$%hWYb2iy_9OR4QKOhI&Zzq6D<$bo7fGWDxxP8apxmUdqe5^|N- z-itI~T>JyL%~df3qqejph=n)>q$kN|vXf)*94W1ROhK##s%jA zuC4bO*OF#U<~hca8FXC6>k$#XudD3M@ zP_6qy&UW+#7kfjm^Ytd9_i?FTfBE1WvUBYfJ@3YTK1pg&vsP z9?h`OV4frJ-IB|ajn>iVgX{PRPa3ATapwbm9{1UW9tKL}Oo`ZGGj|z}f=i7He7?>& zcE(dm6BA+&QCwwOJXw({Fh@~vz0VX$Uem1vkYY^_*-guPX4zfZIS{y*$$$l(O9uL?{QD>Q-x2Ev`kV^?D~Ho{W}>X}65zXPQYBZh&m#X76lB6d)? z=Dbn>W|StDy3rSobtdHRIJT(1NN{Ly{6B2HWk8f&+cv6#qDV+Lh#=kFqk__%(v5V- zkkZ}VAYDTBeIWQt-o_l|V9N4C3CC({71VhFlR#_V6neQ){63d|g2daapE|W(n&6rK>m%%5a)F>*DXOg6%CX7lN%ng&_->Ps}$1ut*5l6jR1v zcCOB*@E!wBBa!Ab^q1?qcV$2yM*w^Uh(quG_K1u;fVwD_$N076YCBrXl`aceg3Onn zmVb}8|L&H5o_fA+-@8>Bb|KTq5)antq9bJ0;cefjMj7Uf%kwG>F|F@Jwj<55*Hd}b zYFZlo{`_$np^^8S`o>vR|3Yhr+$Dj(m{d4(FAs5KfA1}19#yHsFm`%+CnOvt{|ZL( z`yu6as>p4p9u9m$9JSE;r?cw|WA|Wp7r8IU?$Lv25|=c;G3(pa76mlze?;-zi%6$0Ex!X|HuGS3W{orrQGkRKl&c&qtDb? zGW90wjJlFp8xnST@V(=aYV~GrMVovtRNYtr2}M;|tud~iB$~~1<5C-7kH(BryD%{> zb(!OvAM9Urm2=9wMet50MlRaf^_9nP1(znVxy_HfyuozJYAg#fh7!!Vaiv)?e_}J{ zHR(PZM(0S-OZ}czMX|4uWXh^!=+>hur3$W@QB}prtx}8H=W0_KoY5W2C&&~`qw98- z(B=Q@i~ap<_Nxd<63W#_lO7fCvpnDHTNjt-cbDX&G3%m@xiIF(^A7hRxI|;-DRf>IVo!I>w=5RQ!{-lYA=*R>=LCvGSq%rTMCokBLAp& z&zMS_bAwoxQ)VA=K$>y47eN^Rt* z*hFcK75OxVdt^WSjCREp%zooCb@ylW$;I34JAIU}#p;sxkbG9!=fNKH3mAd)mlTSi zpZZ;z#0bpX^$9S>M9I{@-%47nR3%A@FOten#i~zVm;03^? zrS}KcS?+)2ppEHAUI_r^vi!kA_YU~rtVbzutf4h<#O=r%+FaSb&U2Ivj6q5?of}Z* zLkJ;lm%@d3jYxo?Kb&Pc=--(<_n#w_==@olZX5OUqp~V2cR10jcUq6v`wkrYs(6|E_`%93kZ3v78>LTlyQYWt?Wh^G5b z?lM!hr%@czw~;TWt$~q(x=WKr%}#}Dp1Nv#XA8h=mW_)acb+dROEz7@1-waA&12)%x5biKq4h^59`N;j5*vl>MVYKNxb6|aW|=}YwV`69UZQ2lIC0qR zV8Y|(^BkA@+V8qMvzm)fADMOf>rgvDmaW7`o`2|9Ar?gyE2=@xBt__Y<=qiYd+&!I zok-xT(_XsMtq{VDd(w|RU{DsqY3{5`UOpkae#$me;9<2B$<-z5ZuUUr|EyAi=PQW7 zvZuQ2YzlJnOubI-R2hVZZv&BpaR0EPcmO}^XB9}C$eWUgLj6enJNu-Ouq!^8-DO1M z79RDHhVSR@Guzf~?9gcW_f7IXN^$O36!~qX3rMUKdiO@RleQ-a35rNe{=lafej9rL zLtLt$tB>pwl@%rFo3kW)(Z|&kuhrrkH;-_njFmX@g8OmyOGJ+ielN{M&(ry!eU_xY zkfL!OD6k;PBU%%DE&s&kht&EyG=zq!5OeS$h{Hwf$=pO>zy7&LEa)9>!48Zw zq|@A=h}(k8KN$U&ycIPTr44d`7&h)~`d0g1M4JNxmGYN2mzQEinD6;M_|88LUdU5O z8LF^-h8*Miz?=UeyzkH>%xIjNr#!Y64XgR|d|{iLn+S*@W0~su?k;wo5rR+xa5$(R z=`S@aMTp+9^I`47r>E9;#3j~{yX2E}nfY;X)fMM)WsE(ALM>LC$DruFYn~}HV-+6( z@BOOUDFYT{aczq~7;k<0a&JMWIW^@j&s|9y#ChU$8@e#9@Vmj4Cr-zv-%(%4tIHY} zMAt7*2IyqZMRpOkc=}kBHizN?q|q{K>x^i9;WApH)~`=WAAgHI)%257B0OBGn;@y$ z-0Zn5<>Li8$8;0GIh$g>A|?H*cH{VI1a+w`!-J7% z2xfy}IQeJeUWSImc|Lvl9gjT&(01`dyU&}{)TQ}#k*G2aNYQrN32Ky))foZBD$CL} zLwYz9S5TCxrXE0jS6%U|b+2rJ^bj!fpZ#|KtW1|*=31VGQf)iC`+TnUY-)6CpW%&k)+d#m z=c@S({oD0osvwUNM|XX*1>L4oIvO2hb|Y2;6-`zplxwBOK^g{TZ{*^tSTCFzr_lXn z;W%7X(}3N5b3}zJPsWd50u7CBiCjplZcEoOz)%@ONM?dV2nA*LQ*^JgBME8cOg=rS zOuEy?O@aYlleaPN>{2dSSvKwBa~;X(6{#Hp$WYp6d^=sdu zX#Yz-Ly|6gCzFKUvclqz){myiU;HrB*pkgV)(}!F#z;G2%DH%HJ&1`Y6D;_eTG9uO z2mAhxKhOmW8XA%ihJ*-l(%3qNej8?1ZYUbXLUeuz1d-ERVZ>wljOtrdp>6r>;GS=? z4>CJaABV$*Mqd=!@VIwq4~o|WeGX+_=CMruHoXlz zF*~alRKfkuE|1NAmm-}3G-Ztu`w_$QzVsL24C^;bRbRKc+w9TS}a*cs;K1A7@cA`Y4*IOSh5Fo! zo`XnK+J(k?D3I#mHE%{im}M}L#q8P6h-vF9nVqb)m7Z;+F7pQ`{2RrG)9}bVSAER8 zy@c~192*8|UL&$4zm1czx+$$~ctGvs^K$NMsregw^74}^{ayIVMqk|X7@BFaj5%l{%r777wCyUFJ1-c(PbI0dAnWhVeq_@ zL1z+j;Dl8qz69+xW&wRXT|K=xv(2&U#zKWBy_@ey&6DkxkbV6@$^?1k6llH7$3n!f zn|P2n^G@PnNXqY44}ymY_$?12?2OTsB~43?4rV+onyNSN=d4nHP5Fw^I`MAsJHJ1C z?iKs)RZHVG3hzl9{U(v110OvZH*(P>&HI5UMY5^y!)X#vceTsFZZ1%Zl@L|%1+8S{ zx!o~Sw}@V_=J9m`&+M3hSiIS@H_3(L!?k2zK!zLBq1qxMX+L*pcv{_mUbpmP=au!W zPVrkHMpG8H#8?|zGcv)hsHaGUjw{@Gga9$|**hR%+d~K$foy(B-2R{R6o(sQP-`ni zbzRKUqr)PoF)g2sz7~;6g#bkekYF2$v$<2wSkfVz&MTxj69@86Mpca|{{UY9S_BM# zSJcKm48~OYvzg;0MvOF3=7ZFRYp*B_@ejwa{ zOIP%r3qNDLd?}Kk8f9wLjG`MVNe!jQeUNz0kI%ho@bX;lid?3kdo}tq1kcNh+}#y> z>IEG@Q+8rPvrg5i#$ZI`lW*sz^MX90$}b`v(7bNHrh=q1zZa-83JMC6vUwBym3iG! zP3N~+j{KG=E{9EkM^aD3JguIj_^S^uQB|p8o7+q~;itk2=d6pB_SABk zx0j0$E7rn>(k!yOBKGp==KwH+#gNV^GgDzsAzt34SS2PbLeI-Y*aB}cO`g=0cT!1R zvV;>9Xi>bki~+sa@Wdre?>X6X)n90g$h-NfV%dL_Iz92}W?d%9t1)yQAy^wUx|`^~ z9Pe1|5B3GzQ;OnXs|-Hk0e2}2SiSto0=~=Caijd2!!-W$N!ZudqBWWK_V+Wtd$jAu zraZwx{(Y`vF!lzTG>w2jnlZC{sgTsCXWq}fuRYv1W*)T5w#__GIFPZ(i_|ykXx-}A z5VyTwwW8t&^PI&l(Jn~7XdF%yb)LD-7tYQv{&C6(VT~VV+W4iQrR)n%&+HknQ-2-s zRm{ktuEu1Wq}6qe>&U~F!edxQp(a$e_OZJzc&D~zQHjf2^ z)GiK*Z->RtAFb%^0pk6Rjjdt#zwXIr%c#IPC;8_MgwZF|rsYE=CDf5=%O07jq^ch>gK$rneJt4X~TwK}~eHqlQo1 zT^$xhOy_K-esyWpvX#UAbau5rVeYvY1!o$id9WRLCnmG3Pm8&V(?6n}y{_QnQXvZrj~!YofbxwTZ+hp7N3YHS*t=@hAeKfVqUxRiMu{B$kS(EGU+W;?E#2 zFF&-tVYceLL){);uh~cpYD+JBY>7`(v);5A)IAaMY3t>dL&q$>;Ym!00h{BG$$Eqk z-4Rb97Hp`c**u<(L6epHxyhq9Ojzi0x=kkK1kKiFC~u3}enLQtK6^|WzS1{iv7E5v zoqMK9A4#K*Vx!O673W8k*@~DNk4~El*5=0y1v$*hPz--bpWy%w(wfMdq1N>%&G|DM-D`zg{%CbP@gETzdbvnuDIp^yR zko#|VXH;Zly@i*e<;N=nKX%>nWc-y0!&<9CQET zFFpKnfBCkZ3vMbt&MV~1d!EdQ1nQFR#(M$)^;tYO?vAbgQR$Z}Tl7B!9qBT09dH79 zbq1LAsBzl^6F>d>H5!Ek1#hrsgATJg9JncZcL4HUf{{UNCo|mI^p!W|cx?N>d#)rl zY+=-UyFzcZBWW(hwOoU#LbgJaIbB91JlAd`4jT~sGB7sy3fZR32pRGiKn|Um+(ZMI zxTY-&VZRQ?Fc}CbI2>eGo-2N#B~@Hf@*&R)m&*MHYv*7Q^N8~Lt2TtyOlXYj!D3d( z3&&OD1lQK=bNbalkq7ddK}qWTSN3&{lTDRpHQ@E_*}m~k^IgTe5#gxkdxO_6JrvZw z%eTzPsP#Eu8~RI1hC!)W@c_a$S-Y+MY-|tjFdjbFoU5d)peD8qSVeUmW%v9kKC&D% zT5657(pc|nBoNuCNToQP$iABrERLEXx`e1tV_rWp3Z3iWJx-k8!%(^<(x2!pQ6p4L zZH=}30R=dZ<$dOxfQ{<(Aa#(&}DcMSroAq;w)3xBE9sG0r27_EFtw61Jxmc2D6eQA;Cd?Jz zI86eZrq#(!mkX#)&oA=fcpaPSK2saF47S2gqAW|T0m}~`x9Wbp-IWX1Be5R+HljJ} zWFrb^tM4X5pb-XSU#&$O_e|p6(x;`P z#iHw$bOvxgg6k=G5xe!GvxQp}(Gn`1V=>2aKS>J%<3_9Vb@4{QzraID+KvVH^4MEx z%*Hcg#=bsl&yzpQ_t);${P6SN%5N3FMjgz#}46-+UB zx~My+^!w9t&gbg`A#;%gQD+aNV8{0#*nSpQ;dpM2sK`u2HMO1v15WaZA5Vf^Z=7UV zOh6NQg?M9>7un+ktZrJmJTbS5-w zLQD~UHS4eMYObn28ogZtmp0lch|Xfn9uMYK-M0XL>0}Tcxg$}Q%yC-hQ{YR#k%nJ* z_FT#>VC*ISo?N$fo54JyHkWlqwXg1mz(dVb<+LJPxo3Wo0^^M-Y+w0hdIEq)D`a zlSr9ngp%ET?52JV8CYl(qz9hv;94Q)3L`Oryg26stK$B5gc5F6Ip;LgyqV;p7w>~2 zh{y6Dv3j_mHQrZ-Jjo@F@mKGjzB)%?L;WE}2DtHkkp@amjN4jsHTFxN=g_ehSNPDk zm^{+ANzUofNXMALm^8EEm5~3CbrBlEcN;PYJ%GL93D0$oaQM3*-=AH(@!8pk z&M72+bzCfV#fYYnks&aF5;@-2lb^W1is#qJ z0aLs^VFf(F6}9Ts_Tu=dK)i%GV*4L$@|qk0mnI5^OjKy9#73<1r^>95*ShK7Xp3>ddL@46<%IW&$-t|Vx^^a&}w#Id#N z($nH(YRX!RYp-(k>d-MApD&d0)EK}pT(i^6RZ$UxGU>G%uHvdyzcG@ijDTq2(@&J+jwE*Ppt18>7o*5zdDPA0d-M)B zgu7_;&BW-+7$?Yi`H8LL?gqAe=n*h^CWYa8b+iG3Q`!xTdOj6(Y@brdtk?WO3Mp zBCI_NzW>)64AF}ek~$XjF5DP%Odu#5mX?g)@)Qwns}tj^kE#^?f`WeCdDSJwDoJXF zeYuaR^vtDVwyrUxBwvD85cc{=**Wj;FKp&X(r0i%;9gCsg%%5D5-|AP`R^qmZ!f*u zuP!bQ?nIt%BEyPWa}xSyc@}3n8j`++oipqaP<%C1Qi?v1J;-#M1R{Bjt@e7jW};x( zhjPtvD=TY7zibhB)Z$OmlFHAfn8+2;V8&0|UwISxwtv{7ch=O&MJ>yH_4p)}vr@nH z*DDTwzTg_KbB(&Ocu#Oyqx*ZpX87ZxHJ=P~U7cW+x!?k8pe_>2cA>eVF@^9KFUMNc za4IGyKgDKdE3J;S$WeB_FL8TI5B}+$UXmF0@1|N~XAZ#CybuVokK8$$nYmxHP!B?qU zn9y}c^v#K~HJOFm(R1?jUD5M(JfZWj$P2Bf-;CLWIDV7^5%|9NDI;m36;sIwD zIDie8yWsn^O~7{3m`hFGh%C(3RY+*&QT@%f=TwqFp|#pu%{9Ad);p2!+8`nO#y+bCj9l~fI+UQ5M%N=q@P=3!v=aI zzXtW^&H4lR{Fu?$Asrr$)zpcwQ-S zA6IC1JhoUu&o|UAJVRLFLTY*rl_$axPT5*Fx*m*C8mVw8XBN)R3%Hgm=1?np;hfdy+j&&fABZdL2m{KvTPZ(UwnhLZhOD@zOu zLv65H=t{S3AM6TzE2y_b?~k^oPsfDlMXHW9+^A!>Ws!}IYjMhM!ST-L2jhJ38;g7ekZrp8O z#CteKbCoIG+sr$VJJhZC$51^`5dnyx5VCu zwh)+OOpOHz1Z6=QwPaw>wB%MEMiYu7@Ljugh8>4oY;qmEQ2ju6C#7;R6gHUsgcYtT z#Hbx_em6PA7&L+7WR=1D6z*jX&SPXPq~mzzXw0@==+5+YX`yaSO19Q=)+hjn)STvh zO~{5r9fF@`B#=&8Pe!!(!^}I1YBA=k!4;31P4Uc^-k0KJ;_;QnV(zF-@*;!33U_RP zu!AsK7XC;^Tk~yy6kWqXh>&WSkE4J;COhx)=QD_GLWM?uP&c}U>ydF$X%RPH5nV3m zR|Fa3Ee_F!Z|(^-l#a6fZBtW1LW0vQQ3iKOrm-3FxC&_Bko;qvDa&@`JV}W3Zg0+U z&CtJ{>p!E{=Z?dpqt0Sq%~@SwhsdDPQp1DUiiG53qw0+P?ffqp%L(+#guFJS|ASBk z-D@kVFDV(kL6+2*uhy|y`JaTUJ>P<$8fHd~cH@_oChG6Rs3!c6j235-Ir!+3y^f!P z`C*uLYhI!u^t!#x1uYuy+>uy?Jc)9b9w8m3J}_L74G)>-eRuC=a4ZtV zL-doC;81L{X4eN_5#4w%?MTb#Mkm)91<$H3Kh4+||Z$5sAKajh>Y zIE`Q!YWQk6hkJ5|C;c~%%x$O4DbjtVObs`W5gj74!F|!XTeV0>Tm^c=QvkBBjcL43 z0q0T1Vr%bTWXdmDZ1>~qHrXJ}u2ZF)6j>61US=!m99;iA>p6|^z9$ETs~AKIy1^#o zOJs;Ui?dfCGwX|WD}^4{3^d=>PmhD4aVw_zU+1C*Ia98#Lxs-E1PN!fU?hpxS3#tS zwyRr^7T&n~-L;!eSh78ExtcZ3hE->D@jJy?F!U_-q=RT#kR_?^k8RE7**y3Mz3sgd zy5#v|f8?G4b<1{qn>)Ad!y1iy#|0+nnBeO#%BRLXq0=#~&a^T7lQrPiYcb$vp`-uw zFd--K1tuow4+Z8!eA_p98G|?1F1v5aN{xPZJod|GX)V-v1}Hf*Ff(vd|wfx>9FP`#$B9sA;Lq~LlY$16sm>m^kc zcw5wgk1GXWKQB&Vsbj2lV80yO0%?;CSsbU;72xIbqz=l!4;@Q7+S`!d?flMkbBOcU z*cTKgLjLe!!UX(oZz5QF?It*^RzQvy@~1nRr^d;Zd37CBL@T~Lm^r7@muX}u=o9Xk z;4)&hlc~4GVGiBYCU#7K`G|-hY|s|dim4v^rsMPmEn(wk2~?wgvv$ z&OYlJWvvlx1Nc5>L26c54PGPJUgKfvCH0SJnYn0HURiljdFXir!Qt-XY9Z zPvwP;3*||m*$J37R^2)4{aqe8L~(8vGS(-+s}N!UW@5T|79rR=;`U% zG;QNU*Rl{+^oReUD3+Y7AlSVxkj9o*h>E5P55Dsw7?kYLra&u%6imo{itU?aV$){b z7RdN~2(Pu4`6o%XXUuTi3x%1n+A?nvMu6&`_SW#p+G;m-J#f_lXO?Kw?ngGEMfccP zbW{{Z6VJzXF~$}IWVwy$y-H0@?RR-*SvU8IfPg?*M<;S&dGlQ7OGc9S!)!UE61_y%VWzo{g2Y)JLerrz9_@Sa`rOU=|c<2||OtMfd1z zmPB3Ls>?Rjt-6#SllXXq{yvM;-sRY9m5irLBW_@JhyM2@De9`sCxD@o1HNejzYUFS~J}`l)fUU zJ)*;e3#slngSgC`c^=|XhB0Aip+2m9PCVVJYM~2tPcKyAH#HPVBnw(BHcSFD4E5#ZMQO_rLzlOVcgbF$!a-Y90v_?ImC#Tn|&2S}gLmFc0u9msQEplA|9tq+sp zHy^Z<0iv^5t*_>_;%WfR#4oT8L@$-50Zzc zK+W=g=`Ls>1OtKFItdaKx-)OILy{>L*!agBmKR=xbp3ikdgpwD?6}tY9@qQkWUR?W zhWNC9x_@}!_5|JZ9?B_FEVBvDZto=X@0QpH#*d+?b}WM*=w8ND)ukc8*$)g^s}^M{Ml|jdst8@-O)Y7eC$Dw@3#k5 z+Q0^bW<0O^`dcseSu{!Mm(TV{manW4g!9_Jl;RS^@N5@>@*=jac7$9JlE#tZzj@#P zz`ui{$8v@p<|i=pmJk-a4)E=$nuJxWt}6$OXgf8G0`3UoA#Pa;f1dY3vf0PTS^P zkz)vwUGWf0mHx1@$^jLIad5X6HwK)2dyAhgnod$yo!Y!1m8O|q45G_ZkyX}KlXMP8 zZ{Z2OQhdej<7I-xY(b8Kun4p?FD@+vf%eZYlVMk8npiT(nGq0csa^)v(arh5s_BFS_HN;mF$zF>I-i zW=?Q0KBpA|z~(&b?vWnt#xNUoWgUAlkD#%EcwDJ<&d{oDnEK7}18Z$nSJ+^C_?R~w z%~t4|ZcOCv5A>kzVc{jy^6{;VzYcSYAtmeDT74^p-I^f933%9NwB_y9BzNk6IFA`` z{)c&ah+}*@fk5TN1%)SJuo(u**wPn!aFWfwkLl+G(*ZB~-fO!9tH*ObxQ665XW6hblj3*|EjLEbuam9*2zb9Sv z$7NX<%9+RciE41h94(A5zRj(bpb)igW-v@?4~g& z$8L^=hh;^kZ{iCEh4rt|l~=Fk+?*^zj88&*^9xFWm)>px)Dx_^_`EGdc~|&9T2IfS zpp(NvG4HTKz^;VP*9|U0%kt~%kq!tbJ{-{m5+ed05S|K(BS|7@7nxA#KsldNQh(mwCSaZ0;lC-+8UN0n^jTXMpu0k+cRIW%ivPO z3(mT?m~&g4i5XtacySh<-l-B@z?VLX!a~Kt6BfW{orcdei)6K`C}Z9BCT(WT&)tQz zEsj#O^$q%L;SDOU}KO57m*cPbcZ0dNWv)*T+8_S5~krH(3R!kW> z9=6Toev_>2+>LR~2Xjdu)3?)!jNBT2ImQTY^0j(;~!0H5-|s$*|&Z%{TO zXn>qtbCWpY8`a;23kb{=9EF>FXTnE#>YtpR+6Q`mmpj6`e|V5M+-{ZC`p@QL(a^jr zZqxDbt2Z+-F+to4H~01ie?CY0D|M+KCB+yRS(JBD;afMzb@T9O>GO8{+eW6690>qk z9%8Cgh?CzP7x6!y4Xc@IYKG#^lU%W75V3R#3%5?Nq@UAn;+<; z?z>sHq&FQFL^&k^gavdy?2@H_+W)yO)4GEi)N_ZGUs)tj`E#VVKx{=IG5?w`4o8WQ z&yWcR)R^!{dF0mAk~@WhGa(qbii8t-cBQaKDtDjbO??$b-J^VvbcH~+1AE_@o_wUH zA$9Fg_?2fQAsI@=zL-3zT0yM?i1J1<3OTeAdHZ!3s=4Z1jAj8|(#ieeG&#h=toP$a zv;~5Y&hVt8*Dgf3crC5yWH}>r8us?%i<+9*TIv)T|F3njl!?hlo2I6wsN&*HKpIs~ z>VzuR97m?wo42oD^X(VJ&iWs=$^Qj731}+3@>jGyI0Rh|^`Vf= z>)Tt0VP^1Owp!(!V2Ax3#Djv9sSRNMp!5dq{@$o*Z5|;nYS)?JQnlJ@sy^O$+M;MW z43Z{%xQXx7iHd16=C^$^Bnw4!5AavPvD1#&-quO`ZKU7N89MHz--A2cc-7@)^O7x> z5egNznc3N$!;uM__v0)!ZzeL;T%1?*H;#{w|Aq?04~mJ3A|V7yMGxblh+=2oZfRrl zc%LgRJ0}~Dcw=K@Brnayd^KsxWWSeTJnx_ zaYvy$!*E#UCaN@Ju~oIfvF63Ugl8UUPV^ZQh%*5$zT&KYpVdLD@>YTzN9Bq|e!W2U zuP%r+3#dGA)s5$9ady`1S5r+yO^pRZx<@11xIzD{lH^x&{zPYHzB~u*MJSX&Sw&mE zOv=;9@#EzsZAfhcs}?aGh?k!=!CBt_{{9QM%9MVcKnKIsrG|>G;*z5FRj+{DZ=3QW zP)){Un7fM0`qB`KnYf^u5e`CE$dwAKxlQ*_8~t)~gp$H%SuCUa%yKGic+qLyi~YqmhEK{fe7w^MXfhmh9Ue8}5T3lO9! zQ-CQY-I7juioj_*)ll_nnxs0jrd7aOP<#9HoP)OLcW0zgeCs96nFc(?W$R_hVS6*6 zs`SFCy;>A=t#msbZQwP{q1s_ZJubma*2(e@Md;!_2lE)7Qt_ErH+z32qFMVv%6Ew9 zl)~s48FF%RejW;Yd~b2$cHTQh4!m{TXGKyml|%^d7RSbI+jEVW zl`UeR!^ia1tx-MKzjXDAimHQ;>MRnTW&Gmdx)4oLjooZx`ZcM+ZS?7q^c%NpJmGQ{Gk zwXl6iM`=67^vDl0Fg>(1zCUe)R5gGy)0Ci8vP_qMg_z z5pe)f{N91@Hoh2jT5TwkF_w5`>Rx~ zR5re#XLAYv9`~>9X%NkQqr_IVwJPNu9Q{xAcg_^{19qCkqud`erX2e^@fZ0b{;$@2 zdsc^N6Em5*n2 z4;rqwBsQYxj_H}UK}g1)es1v}*H}Wa95e-r1ge!sw6a9gN52d=es8^RNHX)AS`(Px_H6~4zl%G7~?p;7To+BA+R&Bl1d_D@{QaJayK=>ic z(5M|til$lyRU$mbt$v2#-(z}rg<)^n-{f$@cv+Sq5NC073-)!-l>1h1!=b1Zi^7WB z-kWJd!%6x{-MgsF;8i?#A?AlV+Q2b|=3*nCn`N(Zd-9Ij>C>{S^RoC9j)6}mSpwb% zJSSIh3TSu1oxJ^slj3$~gsa;o+%~hoXx-4+ioC|BeNE8LNrRoc)J|HECzvM_C5f1| z%i$3cCXBM+GE!Zd_|ckB$3$#uJ!?3m;Tv;hDtmoerg%YolAegh2rc6>;nN1w>Wu{B zlj-Sk3(MxvPlr0y1psSh!(iP;V`TCB?bFl&1d&IR&=UqGH=FQ+phr?as!=7swZ+~A5*R8uZ zqBB~a2E-I|o=Frq!Te{-k)E@?hx zgeX>b*Ww2OWP$aauWR4v+nX65l++CPKT#9+L2W<0ri-^upmY3(xdd~Bfbfu5D zmbGD;eVOml0@QfOPzYx%EG~`c#-qIf&6n&{OyCe^_MMz6r#b-5+|lJvsK!-fQd4a* zInCl&bKP;=rQej*lCXhYJ#K6*$qM~+n9f4`$GW5Wm`A1qnz+(G*87TGQH*XcdbcU{ z!iOZ$qEA1t@TbP8p+tEBNmb*Q>VR~4yH$z%c@r|E>%rCx12*Zs^7~&kmSeozhOq^ zI{7?D!Nhg!;`~iN6!P0h#H2Ej7oAj_Gy5=3O(;mGAAL@48&y54>FCwvT6{2eUg7>d zaUyG*VRz_-qtVo_OqI0qexXPYCRR^TY)KN{#Nk3G7Tb&8#v7T@ug#M~kwRoiI*TP2 z8_Sx`!bq+=xfL5>fS%m)56)Y=TaxG@ ze0p8u?bQL&;u+VALT@7WL^~#uOF3FF-(-<{PPk5n^~Q}gFdqe65O-fQf|P(Z*zvR& zl>8FWpG6jE0{9MuPEW$9O_mkn4E73_!mHT`*AuZt0Z92ShV zSAV5ErS^Gt7X5H|{&$ie57Q#b4FW=C^8k=sB~F#@Si|gBzey24ybhE2DEzq~;oLBE z(FT({vJ(YBVJ9eEASY32=jZoOtkE1SRXcMTsm5qMlZb0I*z3~k7H9M!blPu4mAdXN z^D3T-Dz}23nQAQh7m74F_g`5#0mz2tG_6*cOJy@k84rRee45a&SX6|We}alSaoSvk zM`i01lGA56F5jidS$Mu7s-AH*m(6(sl|c<4-dUgKvY$ii&v>iAiP0@UJPC0 z;~>$IAxqJFOB_biG1IF*}mhc zGM9ul0^j1-=FN-67x;$xFC4B^VJ4z$ubJF`VCtw44ODeB9+q>d)EzFAP1mS$qv$Pk zVWJIv%ad5Nk5OYX;fY^-D$Qe3UD>Loi+T3}=9=*yCf=9wL#QgHURr0V#)&x`u4=Tu zx_6xaa1^ojSpK3;$Ek}gSYT%fbslW+Q99#P=eE~nS9k(QRIOP?rx2g!sDz^nW^5t`PZ!Dn?y@bZk>^e@ zW*P9x(FiNZ9x)vFDJw~k^T;GV>X7|rNQaY49w$7%Ccln}47OBRSOAuF^X3hG@9>tn zy{U-6Ebr6xPC!C;zX;Npw7unqYxDX_D@VZ|oyoN#c`&$9aJ<|;4)2T^T!pO|<4xQ9 zsbFnz-C%KEI~167B zbgjz%HJnVwuu_DYDYZN670#umR#l$wSseCkx%uYo@T>TDF!v&JeY&9M-8WfFat=JE zRW|3(!-g43cuT(5VKn|}r!I1NN8#`@GnJ=Yt)7hkj_zbH$Km4BtNpfdOwwWGHIBtv z-dZ~od_+x90WVf(`SKLIstBFpfPSqlnk3*RDwdmk3C2>kqyW7ydcaE2eAP&sNrNO>sczjz=xG<{UNQ3Npe&osR=ug#aeg6ii5cc< z?8OheOVy&&z2epNR$EF62JQ}aoR1%9(V5pZ3dpzo2rcYA#uIs5({$knz}-DlGBGTX zE%?Agu*?lEfiR$i9twq?nR^RmGM&DkWTE#hbFVZ!@?&y9)e_Ltdi?0JC>uGA zkH{u@ug6>#XOW2FAtd;N_m>!&nmt|5N}9ZGJ7X*D4RDK>T;F6u0RR4oJwKTT|{*(>z^ z{WJNoDUVK7W##yD5afS*tMFHc1$LO3dh>A)0=BZ}zPi3T@(u*p)>U;22R`Y{bODM? z*sr%K>tGcHHbsJ>B8|zzp2DY!=wqN`c5`{9BR7K&$EWX%ik1f|s)PAkPmYCpIq%n- zx%xideYq4F0=IS#T*hB3U%yDZf0d!%rpA-he6D>TMh^9Q$dYbyu@i#|nWa=zBuz$p zcRkgw3|6r#H=4=|XM2^zr;ZJ9DoJm%BbT$IK zLYG*WQGTB)F)SKdM;EPAJxMS4Y}d%8_eQidEM@v1;%Kj7KVbYKBuTR`I85)8qgQW# z7Ra(|KSb9HvC)S;Uxy5Mp|^a$fG(7;{h&I%K?!+SL#_$#=o)yV?x?ClS>F_Xa}!VV z|4{apQEhcy+i2x(DaA{1YoS1KcWVp9r9g2j?(SY%+)`Wv#U(fiPAKldg9iyxB)A7T zx!>n`zjMyNbN*%Qv9m{#k-64f*Sy3jko_@oS7Lu<>0^iYeHV?Z*ws}8-4|+}*vB1h zK(-&5rv1a>27D=xcNm)OOX*Ns+Oeor7mM2U>rIChROk4^eNL9*LoWc{n<(h=4}pqG z-{>e!J3tC?qns*P(EHh-Uus75&ujr(kkQ_9m%or?C*|;$#GsouYQ{w20F3cRhxv0x z=2)fo40bw4@UfL*R8-NekH))N%X;0DwfT(p;8)OI{2@UBeU!`zQt-?dx^IcEAyT_92&-Ac5Yor` zUd?FB&1ajO?#(vVvdpFhA)PnK9`3q%_Q+{3gukJUHhWG7X#D%<9;_30l zALy$ev@j9FPje0ylyXa4h6|)Np>h$4y3ibJIVf_W!PVw-tv2UJ77S8Au(-@j=sui# zHRHlzIE68z4el*s?NJh=YX^s`DJ3;Mtf;vdu~Xl#_E*>_f0nxNzO`(bCg>GXS24dP zO;MYjIz0C$_eOowfcU}6$tbSnC3Pe(gr%CS-W`*G=0r~~M^w7mYNG|%30 z`skwvY{Un*^^SAlpTJO<@Lj3=Yz`!VJUT{wMeTRTUr!q_s|q;}PkZ|GESdY%TkU(44!aGl z;{IQ%CPzc(uD~&mZe_Mg&gr;d238tTn@}-YUCGnDbz58O7}pn`|>YR z{IS7ej`tx=$K8L)Rzna5j^>l!!U4)}``V-N4g)`FRS))r-n`nGl6Q2($r8#W7wb*? zp(SQ}vad2yI)UpVDZd{dQ9{>Q8%Qo3@S;GI#-i=?@g{=h>T@5__N{D*(w%nd-Jw>_ z9n!r`9I0tF@;+RWC$#t3R3LAPh;ZB5o3PJ>$L(dx(avUjUf$HACZBMNHaLP33Z4dy zZX_V)E@+CI20qRS5K~yp!zT5VbfLZsRDzY?c5a(TjBCSG`YdjW-tkDbMfCycj)s|y zH+~Y3)wyXt#(UgO?lNle+?ST#{6Yg?OSq;NZ*y|`o46q@=Sn0dXGw$T+~bhe zYyP3$o9?@o*5%Xw4h6&z!XN8NXidpJ%M*MnTDga`YkO?^XaetiQ z!ORtzE{b|;t^4Hyz&qyf-ohjsp^OybpX4;FQT5g@7)nO0j+J#@dO0wIDq;@Cd15^{ zk>kPfYo#YY-`jWmVQs9*W(mM&4VdL-X^OiERaR8oKk8UhwDMUnoz%jm8`Ht}j=j-{ zD=pw<%j(WLan-SXKQ#83Lu@8f=+K76;vq(ko73<^k1q3BFY|T`KJJ@IsPX0jq%C=S zL;$%ckLKQ#@uQFg*!&i)`c>y9)&&)a`c-V<)uE%>m`2C272h+f3Yf6wpQxulva9>1 zY5s1tTyx6e=vFWG(nV)B=QX0*vtSmQ#_itw`)+*F9Y4kM@rd6#;C8(g)Vvcutjp_- zYkJUrCP+qjs-f`!4f}1`8|WFEHL#Q;1G0bjn9urbTZfXv=se=Om?E^4M-=7v6(t{d z6c7ZldlJNX;geAx1#*4YDwe)iVwev2)zh0#;_hCnSn_OFUm)z)1k}gwQlzNgx6BfM z#YiB6apK-*M}Ow-E6)Raq=kAi9YbK@Bi+a~n=v{4kX;vyzb6YDTYZoZ6%CEVK33C0 zy`D4II~tYFl`(_mEMI*bZ5T$&TTHy}vC#Sy_0&yBNT{p3n?k~m-@Gq2;bS;)cd2^8 z3tU|AmX5w35t$I`Cs8HF4DGIA`X$-FUEg>P1dRS2!YhnoP>j>2s4pxG#gLF~pXeJ> zXB#d3-G>yF=amKH@(aNW8h1JuXK;WB;DC)m`RQqy&0ZfNQ7GKz^uwC7de_JJeF;^^ zjiM2Q0LJ?MaKhE{{%`zi>sz0F1D~SqOc=eryvDzp#B@ZkK@pPDPD11T{&SY7xNU9C zn~uC?!dCyA@o|KLxxESAkDLSA-Mw-bjKS{i->4)Ij%k9C1+8M<#QZaVDK2}{&G|G) zUe%kpxkkanLxGgiW;Q);OX>tfph>=={Bs?Xwtmhx72@G1`x5)Ya9Qm;`BZk?p3%bd zPVw}MUp4^mjn_r6EeoV)#(6%zXr4MVA&U8^p4opU9O;GzG+DXG zUGc~(FOFYw8o5fab+O71j&9hPIzF5QJ$HU0r)CAmq>1U($>UAP_=xZ<*>fATV*`%U zh?b0FMXa%S%04@&#aLWqfB6x(uLduK^IlvCj$kz4aXFoBDRxw8#(jx1Qd|8x%GORF z7@o-?eNR*94VlN*6B(5<_(XoZs7$Q`iZVUMX}Z6$Z*~KR-Q0~GFFyDuUM6Oi3U6

uFiqvT-o7FW%Ao%na9boG^VBUCx&xN%Gdj{Zb`TTJ(Sj~$ zny6_3m}RYra{~`6QYnNIc#z94ZrGyV9l&>0q%JrfMcr6NjtU>_ExG*v4@8583G zSqak8vEtv;De=Z!0kERFlo+uKN$5Z28&xy!y7LJ`p$J zjHisMGA6-7E14wnzp{+8ejpH!$#OrmB)XS6+7y4j167y3VT6Xbt_A(`Ih3Gz+1310 zgb{psULUykqXsgyMoIpXafUxxOI-~M2qd8v`4R^xU<-kI@xy08HI(UX4otM?=it{V zplg_^UW8RNZ=!B%2WiJ}&wUWWOtt}vZH?=F?GfUp)^3yi4Y7_k1 z5A6Ys6g53*Hi-UwI|94i`W-PnO|6H()bwPzXbTS#6L7 z_q$3iwb|Mc>IoI^9Z5+<(vWM!UOJH#V0QHfJ1S&$0vk(=>_@>??S`0C;{~xjjZ^xt z;osVN_Hx|GiCk<-E5^=L(=MDzy^Y=cIggwI0Duu+f|uX@_(8p^qrvn+FxNkSIw zgnOZ4(`t^o1VdB9x2#wzsU)9PDwcP1n^Nq>AgXX87WhwCTWof|!xkv*hND?DV(cTj zc4d~Bb15&q1i)LE;46PT8TPh>)EaOZ)Y#8h2F+qd4x_nUUCcfp}imnM%Kn;vt7WduEMmEG7^^SW|bfRe_Yrr`&rsKgXu;y6USkcd_3;Ou#hsXe>N5$V0cKzT|w(s>jJ$0~Di+VR8 z7iK$-MHNlSIq{qUSm#DuJ-+7rd8bG8h40eB7f3zvP=%19)cmDaPuj&@xXaxCJ1YDa z5(qHWc*M?$Z`>K`>9L*_6pQlJv)FXB_Er{JwlZM~ZP3hVjL?CTXSgFBD`H*pJ-eTK zY4J}@E=%jcAIDEa2%TRtwlMEMXL#mbUaZgNDSEbh-PuJ_+OeLb zlb`@&r2}sp_QsMG-ga~C1wA(Tv9R;TnVkwgqyI&M?rgZ_oaJ3)4NLwTDWE5(=8OH(-w-et^rhlZnN7p*{Ie&# zW^OOO4W3WDW-8YBx*WTmJYf@;o|8Ba`8t(Q8&erIPdz%_m8R%sB^oigkp7DHdkN%d z8QYtSt53DTbT1~W)YGGnfxf1C96tHD*8W0VH>7f-BhpP5Q_hxWoLbgaqsPKoGHBO6D@;=Jp`!kHLS8RTlP4;Q^IxqH^s z=rJ_~mkn%sTrV09p%}C%wsvXz%7M;MG}n&`e$!bnGB-z(kdfc@3n*>uKrgpP^?t&N zN7U?yz#_oqc^L+qsS$#3RXhvZ(1MJo=F0aSckfSLNU3pTm28O^%c`X*a3EtUwegmc2|1NI&b!!KSQ@tcU&JI#`+&=raM(|c{k-gp6ayn$U zveWhGQAiK9;yW#xexySGT(dhDUYZIM|M-;t@NIqeQCxc0x`9)nceepG%Ls!GRb_nc zb%k%wBb0r#>j;#Wx*x{w)zM(QdFjjAF`LR(1Ye4Y1F>=Lo?SUS3%frJm^lyK^MAkC z5OQZXGT73%>;VCtX(Y=9K^vg=_G*hCejNTTlP!`W!AMVE^G6}8KWj$) z&9#>&LXuY>npq45!RcUc`L?;~4n>Nq)V)UNyx~P*SGR@|wRC(Lpcwqb;4@*Kva)xy zVqIJ9zJ{W{xFI>))hp`%*3|#-ts-MGUSq~ZKWCq42il7(FA${I?a5;A}L8^GzlrgA!+I(QgXQ}0X-7j^aQJjjRb(>cR zJ%ekw2Z#w&uMD1q)vNZ*u2Th#1nv#n*mV3E6{Dp7c4JqS)0WwqI$|;ZgAW|C>jYrz zk~s!&ZO1q3Uy;`DuEn*HoxcMZNrfxiB{-j)Fhl3(xjYj|&?~}XW z_V6rDV4n)t!8fub-Mm!l?2SrSDI~b*@ZI8 zRN_J17=Lh8M~1}%8SxI+;(v=QP(fg?AN7%Dh&UWQa7Biv&Zx!l2$a7n3!F`Lqx$MCjE`dl z2s&9V0tei@Bj7v`YeZ0RGfsF=VUe^k`n{e@HC03TInS~IE!3~O7=P%?5IbN(a z*VMyhg)I}YgELes3B=gm&wv+Ey%ddmGqbVP@Z=+xVPhK=#to8`1f7XcAR=1T3bPw}sra6~YEx#!ALDzr zAJ$QoaZ=$Ct^ddDFe+w2%G(-?`bYQi-T*UWBiEhn=Ni8Pt^(^&r0KM&Fb8VAEET0O zygOZ|&M@so#Udpse1NtpFfXmSB3hf2mNR;LoT266;R!k&AeKuazL;^GQ=^UnBtffx z?Z>*VsCet(kl6OWcluk{3wxF{@t8{hA^C}8Z%);I&GvXQfETEb2A&;v)zhHvTl9cSZ7Rr(jgvyj6H== zFa`Me?VXmshcQ%}e(|f->US^op$$wmpKc6Y1%vZa;&y@DP0tKYU76eASUyx70+8gw z8DJ(n8R3*d@U<|(cquB*|IJ71Q3m~Kk+~0=82uVC7EEdL%w1N*wekqg3z#|uL4Em+ z;`9-Eie8WqLK4YfW)2B5VCH=?^!yp&!K9zv)p!A4(>a&F+luPsNgQ8jGbkavoVRXL zX~IwNfFijs?8;2E)`P#)W8u5`*GEoI16M9{QV(->ZrDP}6E6a$;c)oF-pD!|p zpWk219GQ+yhK|F?CJ~f3;%xKlew*B%EQa>Hp7q0Tl#4F{wQA{{3Cezl`xG z?oX`BUutasz$gDDyJA)ozA_9)@;$20kU`+zFYxb&U5`ni{IhQMo8*zbz>P9f()nG8 zHX(b@Hw;I&B>k+h-Qb(9%1hsNjxBpMJTgmKJFni%&qmbh^K0%c4}o z&75-oS|0{ntRtFeC1$1wS9coU4C?k8B#-w!9^O? z>oZ<&g{Ku%1&5pBHaieh3NXH=R(S_{+~W5~faxwq|umyoVMSr5r9Dz`$!|H_l2A10Pitq}%Pn z8|dR1zm9M2s{OG=Uu^FD9yV0Cxp)_CB=<^?H~H_Ql6zZbJ$-wd_riUh>@U)V6OP_+ z!PZ{CHY4ZYPt{8DZlcI7Qumo}{F0UVSv7=`F5o2lpkUJ0pJYeuWa2ZRccLLNH9yH0 z{jI^TeP~v8?W@M8`WD)mOTg^a=P^qQn@8|>LF?2b#ZBc2f{xD(BLc zeKMhmC?Di{XT#bmX?9x3>PTd2YNpC5(Ce4sQhdw#^~qsi=vC%a4q#!SLMQ8OZ-0N% zuV3E_3K&2-)eZMF(Z)uHE&hJK*AVY?URQQ?b9z@#PgL$rFL0O-NLaFmLKQ(EB+Sgr z_LM15iBcrMJtdaMfYHJzk`ls=oo0qR3X|JC~9UD6LVbll}LZ|rn_;==# zY!VD|%ll$Pq_3u>tlrariw;a@#kh`7tyjzrVWaQ9Ua#)cD1R+w3tt=BZZQ~?x+0}A zzUB)K48#(fsXJy)_53ueuCm-fc74}@SWUT{bzRk!)H9kGq1}#48vG=;@MTeAvCeDG zsAhY~SRmb2{D`(1dczv*&24#LY0kQIp-!_h0^~Y|XH_3v#=faar;U&KnKLw(cD;f0_O129Pm^n1pUahR z0ZqMMJ{4~~IQg^r*F=7#jJ}gMWK*5lB-wK_UoFz5i#grl_7;wasOC4#sasaegi0hLQPPUOEK1?aqyHL`p^o$=~ zasC$7FTXsx)sjN)@Sjgfg=Q24sEIYU*bIruEX8!JqX7p+mK(1>$%PYItVro)e|)&s zR#(ev&Z13;z|S%jAy3ssJ!ED4 z)-HLD$vMHvr+izGl>E>Fv+v0av@LKsi|%M5Rc#(B6+YMWbE7#+9zD$G;Da3*v_D$ zT{XeNFSl)-ueWFJkC{=?pSD!K5F2U9y^G(@^)GOyYHg@@KSdXwEB}#r^F#iDvn5kw z{^rWr#}(Bda8%p!yeLHj2@PdoP!^tRP#4}1*kzv;ddnHeNCM_B|Evk)9 z9dB}kTEu2NTT<8SSa-p`yL+|{0_F|1jX~7KR+=q;9qjWPnzC61jI!jYG8aYv!o^I# z5^!l;Ty^9XxpScGY`?zz-n#=P%hspFglm%f?67belg2!&pLe*kkpTt#D?l;C1zU5V zBz=G5s|zj`7xO_Z{aqh&Z119n(Ns15bjoCrgO2a04`cidgwzcE~LvNod zptBQCM~7on1Zl%-Hl0!9t==&sY>o9aoLCDyV`A|1LN#7^j;dm`^ZwArbdqS*F%Mdn zQy4p?xU7itz8YjPn;ka7LwSs%%#A6(<7Dab<(Z7_kQ}B#K-Ws~iV~D;B(x$E= z)a)4__;kiay)!tyX_nh8;nWJqe0Z;DYD|Uxy)Uo8V0c%swbYm*wv?o zqH$6=vti)h&>h6%$0O~hScbgx)WLhH4mGtC=5AiSMZprBFgt(!O8Pwy2r$Ia#~&%^ z%{c{JI4Z3yu7hc9G9;z@MUj2%wDbG&$oM|!A8R{Shn>@VeJd6jyi zanD1~iyxo5D1_9D6bRIo=;a81YueUUvMC?KGb9{u<{#$eh`CzJ1zW=)lso$I&l>?!G>= z`BI{Ls@m?feE`|0!svmP5U*9QEcxV**v)HILPxsd>PVb?S_$Bi90F|rlW@_mBky2` z3da9WYmdnmBl~x%6t9bZvb%^ykg??%HVj zU``?F*Du*Ql09Cn3Myk%Ui0CpI68R6C7_s_Y}}SWL)VkjE{dmqKbesw*XlDGU3nbU z^_!zesNKrgo*k%w}wB>(Dnab#ZYbE3<@W!6)*v zpbG(cm-}Y9aOC!$+StPKMuX?L8O@@sksgbJ*a<~@fZ$q)z7LkoOz7UAgt3Ym0Ed`N zmB~->9UeBt^fdqE)-E6dfRp6!{VUnNSlhr<<*gP(Yab_j>>n-$+Q$souJ)bP5+Tyf zXXmp9nTpya@!}7IBVSyeJv2mTEnFSN3lZU(n4w6)`3vG)G zC0J=@`|CH0O0K(q5}cq*axrt$*6Y=Yv^ff$4+(HbLu;DKFfrZJxq@5c(bEVWXkn(>QkF4YS ze-hlQ(=>AIHf3m)Dk`khri`kATu=c3Il91}mRmaG`JPm;8_AXh$yVcBR#5sfmXyV) z)WaaLftxMwWp6oo<^)IR_b45nN`HThvf)dS=N^v@}n`6>yEOyLDxwN~x!q~F~;@+D) zRedgCvhX%hv+i$(A2CSBaA-5l?$oHyGRCUjqD?~Y5XD?slL=J|Isc1m9I6KFuXtt$ z9p2)x1Pg_4=$@3%xQBU}{4YRY!uRjk>m>(=%5E(bOD!$w&PYt8)hsV>W=_t*yO3Kb5;l_mW*qJbaO(lW}CxnCl&{Hh6W@o2#OGf3p_4~3P>Et6`Y z)s1ykEpt8rPl&X`Z0gX$f@zw7w{g==okY6?KYVuGY!bOYKKmF1SBnN^F^_I}m4kQ( zr6`9R8j0WAvAy-QW_RT&E1ZE$l%+b7yUnX+E-uu9;a`$keyZ$AeM4OYuu43QY~!b_ z?42H)r8;P?C!kjP^5uQPGb#}cgsM>l<-DHCXFV4GBpN*ti63vOKi&Z^^?wV*Y&>E3 z8;~x_^BSN&^@3Gg*;9pMrXk4Z*)>mK0L9L{3O~P|4a-nodGVvu#EejKJYnH5V#&!I z!iSgfMGy?MpcJ@EWEW>Nr`$@22F*BdZVW^m)*UZ%1o#zx&tJFGZ#h-Ca=}4+Q8SnP zJEwdSUmcu;5?hZF%TaUMQrEz*KyC)N^~ResCTAGfuuI6^`a9Q%FeM>(>~f}c@tx4$ zAH*-;Vks@!{w*(I7YS(scoQWhs;N3jUdx$9N@dD^(xai_*x3)fe+CbvmR5G-u}o2c zZ(V>-do8COx@cNmITqv$Q$%s~^;(-FW0(A*LCeifPQv)%A!?7oHH8UH7v`8as-)D) z26yoUWYqEgfPJsSPEi3Se1KO#QVKW{`_#e55+{lxWg4FHCD}DnsG%<*Bc-5tTT|Oe zO;e6)D;1Xn3hB|m)LDe>Aa~1PQI>lvCaZT6gYPVpHH}O@&-^mA)i7nL>APFdnXL^v zbggse9gJE0gGJXi)@pF+y4v*eCuLf7UppE>>qX6yM~m`#U52d9NPj9Pl351N$ob^8 z?84)*G{HJL*vywQ7$ zJE?YV)+OHE8)6|TN)Dw`nevl)OZVU-Ujg-mB>53Jd%adKAmzF|hkaqMVadsn>dRJZ zUZ$S!pr49+kn0UbC(YB+HfI$6t5dsD2$cUIA5;)KZA3L+r)n_f<<(buE2FYwUmG+o zD7noINy`QGl&8uU%dA6W&IC5l|NbF#se^uMd=FS@Cv#+?0lIqO*hIUQ#4) zVjo+Ix^m(cZkL&pi-^4LxZioIKg7$z0xKTze@=9;OI!NDfH7efW^m`Bh?*}X6Xw~u zpsN=i!afYa$wQE|_y5Bby5kDbIxR|0G(mRO9U67>2cz!+VCAOgu~w5ODWO};8tPio zn;9>?IY`-ewILEcPaBQJaNQRFE7`iDOvE&o3GRK~BkZXU`?SS$QH{S4bV0_Hjh)P*Z^A^-6}ijBZKbln=Mvgcf_V151Hdpp5dCHsWd^ z7S#XF>EVLEZHC&KZF;|)tuL>SZqxF&bg-zdF4^PqbL=JG8p4~q68wZjY3=Q#|Bs#X$ZyHHVzMi)Bkq!_uAfDk z1!R}nyV8Z(qIV~G_4Tt@SXqD9<|p?~^_lY9I43M&$40)hD3mJl4NK>+;+@iT{fn~L zP3J3&M{u@`o_~G4k(8UIIvc+;1F@B@aSvuCt@mb~VE8__~ zJm|)b`|*83?;W*GKBNH4UEx(&rQo!$ifOc>%uR?)Vc4cFyYnr}vz4p^By0tQx^?4J z%HPv%tc>+?7b3zrTwT1B>`hX;50^V^jlP!iPD(OT^)kk{wA9+iZvJUbg>KR=Zyd_M9ln0$bT!*W;K>Yq6t|eZ4Z!8u@5i&n4>%L_- zDNQ?^vS_iMs#mDtUt>x%r$6aV`jQBa$E5+~rW|5?L$w#Tj?RAs$B7BV48YMbj=fPm z)##X(prv6NjBiMqx5Y0<$N1mC_*7i4wj<$S->(K^Qoi@+(m(A6E}fB4=)tAdtJpsIO7yQ7*?pfh z;4UTN)m=I*QP0vBEd5Feew!$G{z)J2V-CCCGgyPYHC?AQ15N;Gv5uy!bHsp)wP*fZmu5M z+>c}bZJu8od%k`4=hJFP(lGyl@5rBnG!qMZbsSnL{ZS8rO$(*axMW(ReuK-Ek>Koy z9s#!0db=f|YXM8{1Y|x2a*)0EKr$4@QYalo`^ucFNlQ&r>wzlbr}j_qPvfvS2HPrUd9kguUk1LKDIA-vGbCsD zM4#~*HS^$4=q{GJ>-SQ288$+}kWQXY10bZYYR+Io(cIiHI6C}>Ol1s3dAppmGyf2u z4vNj{YPufQ&0{h^mK8_06f5JuYl9K%sF)*^F;bz29`i%${NEaEH${?gOi+XSX#3Lr zrBNYS+T_eK-p=9aVT7~RF(fu@m~QPnQSN=0rr+=RYW%C5R;?(l<@IZi zk|TIhqx+&61ZF8zdzJ^7OG{Kril#cUlsS5RpesScj0Fjp7S8`+ly1RUA_L@GCOgW$ z-kNed-l@1(=WqG0Ex50ENOjj-YF>rGi5!*Q@$ksv0gelN6X2BhyN@P;#>%!jjpx$% zv#y|~i?y`5b`%d3xw)|NP~Ar%2k>1wKEW64v)S|gIg8N`19w*XZsPW@wjD=e#8hp4 z@p|F5y8*S{46B(X*Ru;o?@C7|Q(J7b+a{lyFI%3JmLjI^`Sagwq zvr4>Ue}Df7=S5z5GjJC=hS)hcD9&$t;cV^Sw!BnvN{;fkb++rxzhBg@ZiI@9pzAo{ zSJN5Um~lh5W7iCO2Gzhx4f}~A#J4iWkgx$iNBAE#%i>MK6bh<&j}dvlMcyiCPh`PI zn%Vp7-ys+9e+1hClBK!CVJksFG{dRJLzX(mV~%4zuO1FQzMR4tXt@0IS~yBi!u6}= zfwf6gju}#>80&l9gGyqY{dA94rxI?V~InUhOndOb0pK~>y zgeb9WJ7o!dpKJ-dB);|{dYDp8!Y(I=C^r3`;of-}s|^(9eJAH|gTA}HSF9AWcI5QT z)*{~rlVtb7C2;ASrI;EWkXH%kZMm=FdQB;D`gST!g=<4eQ)#)V#j7@rNw}&5N*n5( z3Pc6fPA?n_jvNrMmeC+x4(=^L6U$ zgybsE-AbG7s?Ldpuc?3yot09P-21s#nZT1w`qhk5tGI{KP*3d@sl}gi(TYXfbp{k^4_KS z({$P`zx>o_U^@f;!tkgx%U3x6mx6n(6cRTVP=-Rm?J)qC%B_{SF9N@{BErDrp@r;6 z91y0@HqBU)oO;WvXp>hU5wT1~b==_1+|v*qgFYgmd#_7KZKLNMtB!qP7dI+*ftZXRvsVT>dB}+-P4`B*7d7 zSYYCF-BE->ZroBi4EikDwCi^LrB=(2SYti)3RA^QJ+Q5{JtP#w1c{Rj)Gi}kW4Sw{ z>PXtja*PqmxSVEp!HBob{Uqq$U!IIjf6WF;_|3X7!3_S~GAilTS%^+CJ=e?fk#Nqa z?ToC9VUXMu8-$e={(dgHXIB~vcw1Zl)6bC>OHSF3&nav%YM5Vh@rmQ->(@mz3<@d@ zsd3Fss~h8S1&(BuFwJxc=Y*HlFHg^GFwa~`##8H!G5JP_!wjiEPMMW=IPa8n;b%}a z`HB-0^O!5kjuN*ZDpS1LSQ`hw-$Shj}Ok;YHN~@hU&xHN=fI zyIE%((Ok<~TT!q!#~x&~+TS-k#$_#N2La)N0?tZ&M$LNEwI1iaof)`fsR^{?5RK(A zB{A9qr>i;b$+FXaE;sEJQ8Jjd0+`NN1GF)`CjMhEsgHZU9oRnBG5j{=eYi5#w&Eec z+2wt`^~}lOX_mskt~2RP%opF#PQKU-A(eiSYi?ivBzZRH&U^t1=i1UGZP)RavuA(V z3|;x>euK#W=bs8eRu*SXD}rzw;7%6qP0 z&Oh5dA}>q;q)YxuB2~14qUam-tBSR)J%>C{@vpOW!r1uurWPB9|6nB3C2d9$b?Ov7bFThQ5oR$#8j* zIpA4UWYHVgwP?Sxg}m!mu$IK>zgZ>Y35rC?@|Zgu9Sye_{*jbKO}9KPsT=54c7_EZ z4AGo)P7Cr5r>|whuGeRBl-E0byk?YF`{?d|HRBg0QzQB>%q_v?mi`fjg2@xGxUW{! z8w@0Jhagkbg3x^KRLs0Nk>*p8`OCd$d2-GtR$b9bHK3iY`ET@QvP}@R&dv;Ab5-U^ zp|D~Bm-RgA@+bz2b~S{!JMi{f5gWdQCAEV6N9UtAeqMy086@e8e}cPq_W0J;H+xH2 z5Ejm3J*%5hYE5*icbXj@e$2|W47#t4KW^orDgq6P<^hfM1~jb;RR_>dz9e!8Nn^ux z;Aq1+l`i@~U(gZ2C|S~{|Hq=zWtY5b;206=pH}yf(s+H;4)y5p@~7qz+1Bu|!WdJB z9xD}(`xPnzaf1EY2NI`VqR`J2KSjZA`^ zARu^#=~ewHPUvR-mduAULnh^n_~6cuyc{%V5EB>9%+djM*M|gAC%CvH$KtEgfojhl zHug+kA=U0`_SCyYI4Hm{3mT=em{=N19@AJYmILR#=WG$3hFHzYHrVW_k2bC)N%U+$ zCQU^k(T$ae(7jL+QU3>O0>+tQ8skxs!Sj*4#TfR$a3+#!{(-O4DP9X;E`} znZerBh083Nfv)pkWLr}cf&-YVAGRpqWj+hg(-**kRPMtIIycX&e><`;?HAfA@B=fy zJNg%yL@J>%iYAixe`8`}b0tH{(&Br!!PnW+XC8$Pg{HTtiga@2^t}(Jt)#+o$|zrI zXF>INE*+JVzKQ0fHgm6kWJfJ7EH$HC_OtxItIo!C&M9eE#P7@+!eUuWuYirDZF}z} zj1}8o0#@oUE|67B!H2)^JjEsOi%ZQ{dqa=38xF2QN3#T7n!wS06YkjYEDRpKpJe0X z%qk+DuHB!v-P{=LW3Z|7%o^cXO!5OmNTZ=bvdJ5Bh9wsPEn;+T+C11hO*EAiMW%1# zhHd8iuF!$4%k!R^p8o0deddl`wWw!y7B_=@sJ`tFL#K-)8!ze+5K_V8S( z>+io7n#TZ%qZ<{_L?on@TQUH-;o6D8O|-e7 zG@hY;TAg-cryPtV)#~-EYD2-IBFC8I=yV!f!=*?0YLpM# z!y)fL<`%D~EOQhiLM>o0RqgFbYvOSlq-WBfs%nT|i??KtASS50{9uBp#-nH`I3~ci z?23HTCOf)XKHvbyurO2LUVRw-%BvCsy7l7E1?1byRb6S)L$LOJDN5-P1k|&~Qb!ZT z7Zb*?$P&#$0X9N4-K^%RZTk2!*v^nLsgznTOOMqYBP&@|`haegzg?u{B3fjxHk2v97^PquDc z12~xF-2O3aO4+l0|4*^>GA3rB}(ixRpL5mVshl@?aF4mC6HK$-%jHtP6jD^h3#I_QDmF7}{B%P9gZBVzPS8IvoTH+E*GNDJ`m)UY8U9|03%x1ET8N zu5T5U29a(N0j0Y`L_iv(Wa#b~VCYa<8tE7i=@@$Gke2T5W`LoG9(cy{I5=pzElqE!V`@oOG`>-=Q5s=KMMRg%^Uec-z`udjNE4 zWLqHXSU#OMEV6I9M_yO5UAY`z9PeCj&QWuSH%JXm5oyx2FfOTu2dR~Rn3~F7|CvtH zf`-TZvn9z5`q1LKunVj>+V4aR4$PYr@PU@5b@iNVp+%3k(U zmAn);8_-a8;(`{yLk)A;Ex)(3xGreWu5o_1LK6t7lX3^p){5!d_&3?3k|Ou5G*~ox zD_WFvvxLQ&YPmi+;pdg?A zoGZ~p>6rx zmEB~wYWc7!oD8PXHTPw*VI@C0H3!YBskJp$g=S!))8wcTXH_*drGBxfP+Ui zloMSJ9wYDuDUFR=*U1-9Lo8|%Y?Rc)lafF(Y%y>(*zr01Vn=G)XGU4y(u)gUK0dIV zxMkj_(;(+Y`)yaUbW{1~OLS^#eWu~`Z{DzgmO8$&2z&boKQ7NJx0|?Du-djXd!qY+#(tpJk(hrnIq?+j!!4yZO?7b*mj!)Bb3p%m+r&%BSjyo_tSvUpOxfMo<>H0c@Dx%Cr9jAotP- z!g888Bu!;jOK2?Nxd$f-OsKbJhqBM(Fruo%s4+x` z&@Obk7*Jdl0c=D(c4#wUR!76FA%5dxHX(eW`98Ffe{zRtG!omdZgFTt`y+u-xh$X& z#YmzHy0VEw^@O-k0&E~Z>eSEwqt7PIae4PB$?Y);yh@p;E%p?p+0$3l0n!Br2T#_d zJCQ$7xB7Ro_MkT!|3X)g#m3zVCMto=iz?k<$P6}T(&~vwV)_3UzWdMWF07pEAAvdQ z$G=LaozO{?SOg7qU|7cHQAB(0^M8UJ;!sEbQ)l>hRfziYu!u0C|3Q-f_qSaFLI3+` zSUCzGOV_Mg*9#fyLKe#YSY-}7``)A^$6hTpV)Tk@yB zV`Z($M=@0ShF>dT9UZ)&(U{_d$=9 zl>{3dj|v4KesALyJ~E2s%cPj{-qp2+=nC^6tv^r=^)Dw9s5|-ZTL=1mdW?!}w+j9( zCMGsb(f$D^zvW;O>n68C#R_#sR8g~gR}brJ9{zt{=&ztY@z(^bls49u18Np)eEc&H z``zw8H;^pz?{!RYGcCK8pL|p%$0P=ORSy4Cb$_1e$A)bYY3UUfh`4mJ8Lx|XbwWo* zWHy#|;{-Q(*za?VM^IK=QcKP*PL*bEhUc`qUH#QAVna4xEttNXi_-`Pk72f5udEfn zyASfr=;RXaHBTSsuV#XPv2H6%TYXqj;M%h~OA^8^5Z+!o?zoSa`r)`fhG@I9OkL{@V~Ki_X1EJ@SH5_$l6|WE&Gd6W|STw zkGlnvJMi6q^ln27I1upZ*B$t#06eLc@ZQ-+G<||P^#MGkc;ddP_ajYk$ol$u{o1N% zT*;x1Vs6Cuk)AsNaMC?@*zGHH_r$WEtWVl(Dd}gkh!~H^WOfGUX2P2fY+xD<*m?29 zIPATFbBaZbQvg)7!?@m~48?^P@6L0JtheXSwkcNDRnjGR)^}nDNPZuDV~so<1`*LS z4u8I0d7Jn^>}>VtZtomfSm5l4gYN!@OHc$OqdCFa#geO=AzgpOZvBf3C197gb9-Z2 zv?)NbnwI5xsE+kJ6(;W^TRVBRrqQjTLLqGNconRZ2J4xDgD)D~=G(Z{DO6h{t0Ij* z0?P^FQZ*eT8oHi^{?fz=3tOuh_0{C$t9W^ zD@+;^sw}0vpq9>UzIaTje%4p^?pIlJ$Q>17Tzn_c#VVW8p%C@e(-9*r!}&6RWAkUO zB3R{;30PQ_P&@x*Tpjl+6n%YTKcF)<6sDI9Pd~cS9XUR|(O3td)gO$H36@muIMy{z z#t!DM+=pJeo2l)t4@JIH6D--Vww(|Nm6vnn-FbO=aCEiL657WT!fCQiBxCz{tZ>8I z^%7O_=O(b(~1Er{KVimb0(_E8J8+a;x(}` z+rWonM%hlD*yk2~FmE=v_lP8u3~K?!jpP-*{eG}f*=2E&2knZ%k4@5*j*1G0mf;9zcp{7ecn?PRHRl)@vQe? ze~kctS$EUiaGSu{@1+q=Ox~nk9yw&YodthZmQtXPQi@6-;x|3y;9^t;T2F^n%lMt$BoUePh$=hFwHnPV^IyUk~+4XQTTMIprhs!S^Xsqo0%HW!AOC z#bV!E$YFyJ{DSBqgeZH>*N4~mgdg<36b&iR@fqlA6XI2Eb2NBxgfZIHaAexpxND2> zz0;ketWLkGF_AA8w%&JoWwxympdV$GEI`*a`v1z@r*3+w4*$yB6>aqeU{+Z7e#;)- zo&ZDDOb*l%i0SV_g8<-iVo^;FM_weW)#nr6+br1H+e7cEt%?n9SpspSZ~?+oSe7+0 zM>X!7^Qgo^!=Q`Oye$Sab0@T={Qr@rqh@7eUvsRlBGJcvO{r7^F`H%X{v-M`vJ)*1 z=y|wCG${J*VdvtjX(rWa%I{~JO&+UEB`CUz8gC0UzF&))pD^&)QT$KVQMtu5hkw5c zZF7jHGMET?=8MJAkf55Z_;SV)?AerqhT$NADrqc7dr)wU4!w5_#d?p!@lZsDoZY%R zKXP~8*YodxXbw3YwaVxSzywjeRvre78yz0}qdrht5yyKbVM z!Agyg^I*!_`|N*@e!ncg!9?KUZmBnyWFI5N4>NuT%=)M{!EP)5 zih2F>x!$;M!ur?%2Ez4?hM}yqKGRXYpwq-JPQ3#J^P;}S4kJO`8udZ)UBH~O+`%L;r`EMPDRhvA!!TJzZdk&F|yYx&6kO6BgOPtmjOLYknToiPf7DGsBHd;0`87 zb90f%O1(d)eN{3hWO7c`nZZKJNw@B=c~w%B!(9>^bQwO{ustr~_1xgTAde1&cWBTS z1v<)~usgQAi7H81MNQbkA^s4rkmgvcMVXKnle&t&dyIbfsyt^j^`TkF8>YMC z{vy`&Wo5r9vM2i0a$ayT{uW@yc3v{KR^Hi~#2eJ3*y_2yTzYK|md^EyE6 ztsU{)j(tK%@;TnVW%piNxx4V5aj6EZjFX#^!}6v1#e8&W3~Qh4O26C>!XRvLcUX5$A}i@igko`)BSNtLd^gPJAOv z6gjX^kH{w;On(#HwjNQ)WZNrJx={0t4{WR`WMX^(+7qoLdE`DZrYAor;rE+;Cp{Gb zLBCqk7jQx(x{&R^3vT<6fepX@^pDLlEWY*Ni4k15bgFT@wg{S*4Ry{&f?Qmx?-M0M z+B@IdrU0UV5c7m@?i-&8zhIn5gB2cEZ1S$J$7U)v(whxajPT;@t?-iQ!=u%W2xTX1 zZY(JRE`54pC`azz!b7z@sKXpn#0~*#2Ku<$37vL2+{6MB905~pKM73hPraAk4 zzVh3J_n6_e*@1NyR)e!0gg=EbxYbCosTqG<`xZFCTh`Y3KB^(4xg-Ccd}Ng>8E);E z7k+-@0P#_CTve; zU+-7YSfqu=cx$_7u(?Ifz8p|PfYFG25SpPSvJO+;kvzRiWcljADjxAC}eWBJ8x8&OBUwt3yl-tjC zcy>Z4H4bAMpPzqE;g0w-HqqznE!J%h&&XO_Mq`QzUOYS1*PEY`vGjTj+f%G|PyaKe z;*WAj`E|r>gEI*W)Ky78CJ!ks`YSyeM*Bvxj(uWrS8RBC>{4Eh$ei;KLGVdW7DOv6 z2v=UOm|oYAvr=%tBmW603M)@Wt@-y2@$vC(v&*$o3R=FBt}CL<%D#F9dBkw~;6`DD zVs48r@rN*uZ-3i1AMDM^y%rpv-1*+zicYSPuBwD8@u1hWbu6?sM;o?+<>ed5L0Bj|`f`-D?3U-|PvQzM0jnJI8cSniU-;`$!KX0IBLZ`H?&-dn zC29T0N*3vIvzHrTA#)=|zZznZ2yC8hX+mym z<`!UYQBhgW90S=Ar@O^dhYhEyRDgYO-ZPtr{yC@--Uc;peGEnCCn<(9l%>g_TQh=0 zyC66Dtms?PyjZhGC)ypny{X}Bc;$2=)R0~#%3C?g`)q?~yvFhc@nuv|`Pnf@yV9ob zrGwA0q#t53LeyocvsB6cqry6GLEPzy`eISOVSdO$rdRli_!SYy-RVl<()$Hm8~iFn z1A2p!l3|ru9>x9dv{_O4skY`>(4GC((j6S%-Q{d3=4>-fYFb<#u6Xg((1n^#*4a8* z0d`b}n!NE3|8%zY25&_${)E>1t&i>2RIuut{sb77g64*k06z?xzhy0#qGahq5?djp z@rCwd4hgn$3pZ3MOVbicxcJ3eCJMJ5?)~={q1T)BtR^$fT`LZ)=@NHqJEeNp$*sPW z+^kF+_d|Rfr<3u%Csn6=lvkb6fS0v*={q#dV-z6+WsT7yhDRd`yam)T3<`%Dz4r8S zuEqXxc0N}s&8Mr5o_j^;DhIvxD!zl$H8{lEN}}GKrgnu&n^SGb$R-+(AEB2Trs2^h zYGd99D}F&}^OD-v-={y+OS&h-&|IUJmwP5(#xHL;uC%2MJTwQ+Ha|~S!FeD+y6FJPF2hv#)KJszKr5qV`M`%Zb#coDzb%)vLvtRbnwB{?TnNJ7olYBmA84gZTt^xc8*c(B58mEQBQHw2d zWpBc_T>|Qsq2wZ7KwfZZunA|{Zu_V5K*Gm4zD0iCv_j8hXZ>Hr=QQnOfGHy5+Yb{0 z6e1cDGlt54Y`}u8&E6Qhkq8gj3#KaW9^7o#R8JW5&P|LjOWNx0zgU1~H$XwN=1n&u z@YWZl$i$jDlkqv@$xF~zJLK!3lRbqjTsFQ|+Z>O2j-T17C_T;;n{e>eOoF*ZyK6f6g$L`PMS$o_t36Xw?` zv|E8$`#%An#Pn5@2TyF=y$%9Xco`q<9KZW0@J3ZrT}mgJG}EtLG2KSNKuv6j4LnI? zp{ARtFd9JaK^{ex(aY^}ZLS9$jjsj8oL)Klb^F&A0Bhy99>B`1)LWZ0vxC`BC|$pq zrtnSCCPy=$;#1}PEd7>WM$yk>dbN9W^m$c0aMyDn6*eK|-s86XT}WBkloYLIBP48!E8G@4xpi+ zphN<@l`!{Dl*r!b<>ngi1xSte42MarzV5j(GggB!LO(_w#OwsU^tRIw9iif?uT3UN z`eIT`Vj|!o6p>V9A9a+Q(~yEJQksQDc|;p@p{xvdr!d8HSpHgz5*0I_da`>;P&36# z*NrJ&`y1!{BBv|CnxbRk_@axtKaFkkZpySXic!KdF-$Z&VV*=TBr=33e(PGSagh+g z<&pg-#=6c>xid!R@3IW(26qw$B9reUMii4ufYqWDv)9|oFR_XX)gJnJVk)jv$pA8g zCjBp=!!U=d{j*sj?TCizq#qmJbH%3_L5vbfhK;J-F8B>i8*^EzGC3+3rld-*CwHYc z>lIS?d|#`hEJb9ZSw|~P;c>W4bJruG9;b8Ka~Y?ZvkB{BxW;Ixye3K=u84Z!4Q zdY;&W2U5kje!Q^NoGTZkOk9~q=iC~%ehQjat2agmf^6{7CH%=nL&7XIL@!5permH> zmF1}AIilnH2V`hg9oglvA8OtsCv!xPe-nx#j)n>xq;>*E!o~&-g&v>HBdEj-6xDPe zYSei@r&fpJKO8@5^E`eGEqgeQ?l-Mb-;b=}c&tcM-%yC7ns=7pia!xLz4*~Z5_2kw z*$4^qYi9ozkkE3Vy7TkJj=m++lBT9c?$+3WKnQ1I+epO4?~+|j@i4ahdga!j|IjlG z?Ew;H^WGKT7zKg_N#|wJ{ub!gj^6V?P_)l%IaDR>&)f!yU^My6Vh6Vrf8Xu&iLnnc zuCjUqG7a^=la4DE=SPSYEAb1>7j6T{=lA?IPEGTg6mq_BL_!(nuBC!{y-9IKSR zY@*(XITBW+*J8A(b9)Rg9HNuh5cED3O%dQBYU9W`pXsNLc_fj~x=*+9o`yIPGMSXC zu9l{NOi>`;upR&0gfgJ^n9oWf4Wq6nh!%90$#uZrWJ)RNpnTiex zUGws5qHp516EkjF;TfYk3Q7)7 z7FN7tE>SHo?_0qHKo6`MSEWhvpzDQj=(8EU?z-~S#g!P#wqf~xtg34>LxBy)#z5Ld zcL|ARXZGqR@X`LH(z@jBC*#q?KeX0**PD)ZG7XnU+;^m3!psAq!wp(S3u!WgNrKVl z0>-3dA3jxZ(1|nTnvuk%t`rXC^4mmM4<_n8EDbdHxP5$R_}MLoG3EjurQG}T>1|%o zgkpExkcQy14I8KQxXMQ|gjBiWWe&ncO)n z-QKg9cLtfiI@I;Po8)TyakPAC>gO}TFncif$w8Kkp5vD8vIHp6V2)=XyYY^>D8EXY zI;OPK&g&=)t3ZH8(gu7l#vFb&2duzx3Dpu_l5R46<)>b@es8!qfOI#M)^H(*rh;mo zE1L9ywYlfsMK%mLtS3z+y9{kQMJk)>IPHM-#3%6EqH&^W7yEDAq4;Rcn1&4rb1oK~ zY-Y~~THQ${47rjBmhtLuLkLLt)Vob9D143!2Xpd&1~azt*l$od*YbndC$-}3F^vcF z>P}j+76%~7Bini;$l_zLkI+O1@}x|tUqqJKS|so3tZ|sfa_)KqI3)Uh?)k)=v90C8 zA3UO^mA&XNNO~)WK(pMw6GoXtb{h=KyoU!>?2_uuF6?JUgo z+(fEi%WR4b(uWJ0lP*8&Y8Oh=Jsgj(xJNT#o(DGEbN`wW_1y|48B{Vy8E#A$(m9;o z?#}47T8T%z2A3K-&cSe8-E?+gZC`B-opo6C$q>RgUY)TEd=xmH?6w8dzS*;d{=&rk z3Mw2)_h~(V7mba=V@2@2gD05eMMeu zrm|Qua}*TUhVI9GW>64DvC)TN zR3stJT{qRT+7J^7}f={t+>MMoqfHdnP*Pm|Z2-eiyujLU~`esCN>XuyEO0|dnzSL1Y7ze*d zsudZW5a0{8A z9=M%N)su77re9*)N;vX~-^ug}FciDPzrUUqAD`T2o##n%$5?Bb5-hOW%2SD#8~T%9 zT9&AV!i2l5Wp~hIU$pCj3- zjmdhOgS`doGS%Lk){MJpQMa~J^h`fR$XNrZxw0)XlO1A{@3xH24b=rC{d#o zi~C+i(hQ&|+PCe!!>MU*Pq(fU?I_Q>!EUP;4Qrh7>%sQ!?<*0J8hD(fmBx)%bu{FE z91-f@>qz4VhBV}9;N84hcX2_q52%ggW+0joFakW9q1^h<-D{~>G8}@CRn1TXh48?v zHfXtxrr-QrNv~GH=^o+E!6VQesfyXS33{!6bHun854hmticn8=trD0<-;dx~8@1eZk`9V{u=dJ#- z@8!%Q$oDS@czUot%FX3PbhP-D7b1pM`6E#)k41Ht?iRXDGW}~N6Q_&((u*_S%-3B) zJZVOU^7%41ISzRm)3EN{lj?V6_PO165`7>4?YFIGSUszk!bNqGG+ox@Q-ZFrPA)DA zT4tgH`uFa+RMj;@`ts8&s$1#G={z@NF6>!);BhL~3lPFoBC9Ipu{5!Z6MV*!(jWP? ztpFClME}%QcO=#^!)sQPKX94gV3bt%Oh|L-=E%x-^7+$XwXsPVb16ffEU_h$eudK$ z5b$@e@2;C33PJES{9KV=93g&7+ZLX8X2A`wy7f4qRXMp2@poSE-IuerYIE|vOBLlr z4aBYbR8uh8inSC%>+O;TKMFyzo1Mzy90)@a{=IKxN&(Gg~d+@w1!f_n1h%9v;|ys3$#F z+!ww#jN${P?t@Il{-@d_tXg-w*0vsm=pmLztI^l($cfN3VwC(UIQC}fAbM%oHg(0= z><Ecy&gC6q!irzPAgLI!Fr_iG}EEU#sK~aJ+W~#K&N!Z zM+%RMeweY}d0lGa-@c5JD2Jm4O)@f59@Z7lz)x+^rDhjwjima%H&g|Aj;cePd()r+7uU$j~!kcMw&c=dDi6gM&L^g1J8x?CS`l9**D*t9pbQ#w(TMvgq?}! zHamBr$x~hF{{9Fy5C;C9pgH-u7&$OvvY*ZgvU?<+(-E?Km@sObjBq<*F>8Hw;5z#} zJMR&PJd>MqVEaXICxy;}KQcYpr+$WCvh5yV`&FJac%TYj=T1@}nj`7~VHYlLO8 zT}p#zH~*)-)EQ?Z2lKN~0mxSeU2fphh7sgKYH4#0l>m~cVwpqkk1t@qDaX&eM0Nml z26ayf3$7bYf+@;4`sbdZOJR!_+0JH+%Ilz^DiBP_RT{U#zUcsW6^_NBR9D)SLB_;C zL(FkAG>b#Ve1-x1`YeN|*uQ5IB&7|6F^iJ!kBi&K!qfx?%}sw^(^Jy+sAyPs)qQ`s zv&IFf5uRL}bivQ1p%wKS6T0z#YE#_KWeQs1fgz^&JCSstMW%bTl+{t!CUBYf}14&*OnkjGe(- zJbB2SPa-s#EgtR%Yw^AaUMTtPH0&U#S`I85Xj_t565>1h&d(-X=k@7pgDWHP*fuyX( zF`1>5GI=r|NvH&j5UtcYJdMum(OfZ5?wjzp)CLI8&0mcWk35HF7O~bZCSLpsY`&iS zx!$B_0V2g^PP%yInNETYom=#3Qi@hdP3_kDsITyqU>W#IfU09dE(w(eIp3e37xClSC7uqoS^Yy z)7Inq7Uwry56!Y}ib#>5C*$y*7#;AU-~`W%w@cOp25NoF1>a@j=lE5Hj!f~db6}Xe5Ka9Cn&t;(_>D`X$g1}7q=D^dWnCC zOO!l2ZX*ydwUQZ92Zr~F+qQ8+$fr$SE(^(2>%Nsd%YV65+&NdBJlV1(7#wXnJ$074 zZX7!F^Lp`hd;fo_I9 zXUz9t85#(;=1XuDc?qA90vxc1pT-dSi-zV-$`69rt_&-~E5WjIi>=Y5D|3UbSBm56 z-X|&0uSJBf$*ir~%ecO~U+%=xw5128zI$UfW88PR7lGC$Q;eUlraBujQ>;LK6aZ~- zlNxzp4C8vSr6u6Ahz}B_YINFF+qj@+VtE&mf^3@2jFr@jXNmtnA$0HO{BQ#9u-X~P z--!!hXI@`nEUSqPs#2z?G_O&hqkXWY_IC5@xX{l!mivGw>&4_W!N*c>mP@+SEw`C_ zWTtKLt~Xr|@T%FjE?xIn> zZa?w3NSIc4uZXTNR|q?`&W8PwxxZPzJrH-zFqPGI) z$sl;@&V)}mV$qMEsH){4JFCQl*-oP^;7w(R($kCg%idlT-}#A%)E#YpYQXG0!T!?V z@zgKh1g}lR$p>m$w)IAsN>6MT!j{V`hVp8uSQH;C)#Oj0TJ}B8^{>-6ZtJQQ^!-a` zXmVKSE*O|0zJp`)Cecj2K&uh)3z|O#-ImM~<@J%N8-d3nd34{Mt1d_`LOo>+AJ$~h zse~yjHF8h;P)qu`OH5s7#8q_qNU@+&7*Rb{1@Ewq$+TF?m+rw z$XsqNmFWsQD3hx1bv8@5qhZsJ?~>7iesSBd;Cc*HHjKW0=cT6_03ffUL;gJQ+wQK_ z{z|shhy@@bSWZ?Q<+$rv7$A&?-T8)j{bjahDBH@YE9}gRJcWY;aJVzXtx(FpPw#VP z8pjDp`5+~H)pL;-e!Ba`@DH{&HdXl|o>_h;W2c$<7cvIly;Ga#^_bK8AyO#y8cVN1 zbbQ~O7n~y8O+~}d&{0XGb14gxuB!nRCG-3+nGa2AY-Vy&_4DTs($c|y$*;DrPLLzm zUvX)!yylI@HC>KX+1Zr%KN|R9pP}Mk$2C8!RkC^|FaNm%#zmgm^_ti*wTuTUt#dj%pth&nw!v5d=TOO}XpkJQJy_7F3L>-cVftf2>Ky zY{|JC9WeM~Nk$36QEUymu2t7Il#!Pwr*3gjygt-tr6_m!AYWZ*x7%Yp2V$ip`1sY9 zVM^bP_wtI<+~ftG&D=2$`@U4H=>z}sF90h$9^<3Kk$TL>R`DZR@8FBpsQ`3bhNXHL znU^Hg%3lNL1++P+L>9?K7}6@$rGOIl;w!48I7-2@D$OC+Ild>=weL#DK3H^^Eyx76 zlY%28TfIjw?ka|}FXZqs zi3$Jxb6@Osl@&QDYmR%Dd;*fa;DYRQnt@fI?T9V+7VR8F4Q3a|~S{Wwn!e zmY>Jw6$5LjTS&{Y)dthaqP>-{wxB~AuAZyAJOM)SXqf3`Nzl!>#I*kGgb!)DBCv|A z&OB|yj!CsvkD_!dcT%xFm@ja2^B|(+;S2j2_M48zC7QyzpXwV@mP)S_8RWrHgf!w( zK@6`Fbh4u@zu(eDhbD`($2m;qnX4@fIR zY>||8>I)^^3Qv+iK8H}$4n{slZ%MP(l2ZXHR46rj1lt(n-4RO z0C?j$FWu&`VyY3UwS4v|pp6t1YCK}cW@jN;O1j@0Y?Q)5$ zj^SRXec~MAS`5CiS#iY^5Atv|a>JlE87E>?!s?uX+NO9M=0j!dXQaU@E;2tsZ;Xzz zlQhYHHu1HMXkE9sEuXKx6bps1aBPh`fsoZgY;6>O6ejulhvY)jo9IbqK5Z8tO9LjX z>6O^nctN~l^QDmThj~Kb0H8R4ZATbjCv0s$kq;^n!!f>BIWk)lln9V;v9-KcOo5M% zx3n}4*TxZgXH;$D*=f?$THUiIS%IsuPJ*pGO_Jpcgg=nT5bPcmf6kx*FGp3prQb?z zAR^ToEgWXcdRFIrOXY9N!tx<(?Qe6p!&M4ON(hHQb92aH&gK8+wPVmd-)COv&b*XZ`|iKnu=5)^c&qk@zw(BTh#svOyV0GhreE1Lbrk~?j z7=ye?0uvAcV^{a~6P7dT{0jnWN(2L6&6k>(3_iEnJ;nO#>s7lNDaQ$EOIseq7O1AU z2(9ICo}7xa;d(X4&Ex03c!>dDXhY`dJPBaP*S4l|%GmX+b6_q^&i`g`Ui zt^Y^JMKDN0MV7;$eogvr@h%jJA=$*#KQtuG5)p@wfznzfTu6?;&r=wBzyJ1sB;bFQ z!CeA6CzW5;UrI2rFq6@?P#4r-EO7W<%DiM5FTy%wP(>!)X#ZD!9Q5MB8$87KM!fpR zk=XT14migltw;vWMccW`{Ykv#?3d?oG=^LzD_={d(|g~x9Yg=6uKW0{6vM{|-Wj`% z)I@~_=N=r3FQE*qjR&O7KF!~%-0U+=sxI5Q9H(kLnYL5ge^B~&a7^L}WVCjIQ61W> zwbmnjPm|@j2=)yT4%!{76|BGdY=ys4n03mW)YJbqe&=2$vFdcN;UDf84Pf~pLs`h- zHZk7;U9XEnGjmBsSt*Bc|WHey(g1^eM85Ol&38ee+#jFpT5iK znntKleik69CU+@GRfbeK8b|$vd)TY>y2&*I1 zM0FUTlcOkfAO&!Ne?o8%i-cXjk8hyHGr7uajJwQ$=##A;cORxuf=vn4$NlhEZHzJg z@Q0muo!DF>XEGi8H6WWPm8@LkbdT+XilL0|$osYoR29#>`k$Q~ll^c6w)syq8%S31 zw~Id`PzgK;p)JJm8N@IuJJ)h^_2A&+mrtq>WOVEn!iwyEPgOEH2X$Ohcw{LVx#{|8 zAxw3x9DX>0w=$g0r@vk8$p#9I@HgdAl0?*NOy!HwTJy<;sQ>?0W%D9^xjFByZap{P zTi^R~eP4R`Weo5vH58A0U%QHvqEb|3;6qH(HRXm-=sNm<5xdIpT~!|?YnYxw6M!NS zCB}z6x7o1{W=2CUe~(Dk+8?*$*S*!CE_;|dliqhx+t0e|Xj3`Lt$Z7ppi-+Y2;dmput*m)8%%zYZo z1hiVAi?%RVot{wM&Uf|l>A=hoNgXRVkjKU~f0pYYA>*RL_gyyH>FRila0bx!%@%IG zpd<&$>z3JC2(h4;aF1W04roz}k(+62)wkyLzBYCoHLfT$FJTePSP0H4zyvS-2HNK3 zG{hnw5uo zeK>elIWs`}EA{rIAb)dWM_86bfB*OUAYq$@icV$AE`iyPJ+ehL3nFV=rmS?nipgm?uBHM_PcWiuCC zBhQPqpy#O?s;*|(94q&n*Kqx~AbcbcB zn3kX)okZd}cIz0*PH7j@nxQCd{{MT_G_*D?yTxwv=1ZELWwU$O1-8QZ;zj%rj`wHQ ztXZu{Du11=m~_}8ApIrk+O?jhg%_3;t;a6;Fy2s}U{DNTkYdwq=X51Y6(G_JTrb+1 zl7`Z4QZC9p#G}6N7@lRE&?iexC%P8X#a(9k1W)Dz7msB`Z|h2TVwPc(YLFxvc|u5% z=)FEKxQRwr>aMZiYU#(T=!aW06W#g3ItO=rZ*kCeW7NrkD3Qt?>l@OiJd>^~u_sig#B2lC80jl-pGY{_W>iWrzrmyTx~TyzLL((W#bqw)#&NVHG--=KgAYK$WC?I#I@!|2vYlj-woFvm%YF>+3<))nd;n zMItZo1O*#b4+`^P_Hju8D2I@bI&bo(ny$X$Q7QS;dCH191ml}UOz#+g!Lmof^aXoi z$*&&vj7%<;dW%}@=#)(8X z^Ipi^uqlDX!80Iq8GqvY_+yE=^j z%i0G>@ks?lp;J~!$+QJ7O5aNN%iq1^b_cF0cY(+Jb2)x^k}+T~%i1>@!FkHx%a7x$ z>BU>@UDLc_S__8<&fV>fSZC!1!{#VRnGXW)bCfnvZ#?`7=U#1)m$o3AE?6p9ETJyS z^#0CT(cxWg_4ZrY67RRrNV91S!skmchDHD|7`uJLg4?#wS7RcMMWBYUhw%U9AzQaCOdsy&<&HVn8VX_th%`Y= zb;AkeVs2CHt)prHSaS1M;-G8vsa>I@Kp&)*$;RhT zeJt5;m;&!U@~K!*YeG6NmENN6M20(}D0g$(xpXo0?ImL|i~Kuw_WZ_$$AM$t)y%y= zF(3WJ^Hy8}oonsH=|3X@kx!;6mX(&|>*>Z!^M>RQM%zo*Xe6rZ;kP8Q1J0`6THDJY z?~YO?-Eft!ZlWy4q3+HzBmV6i{?`hAp8N7;sWji)#eU35q9XQ=7;7scm@kDCu_(I( zR=ELK>Yr?D3*H%ts7#)@}bp5o{E^AfWE6M8o6- zxsEBJOLsHy^40;n`64iC1x#{7GS-#%sJES0_REj^t1r3B;eyiNL&M5#enR;(XC53m zs0jw@x4+4Ho+pCk`#VnskH`6CEV8S(miTv`Ikut3RgVSX=E3Ti zrQdZjOir6t^n5MiSCqw^#PCg|O10d;A4c<)$3LoE`o^@(3ed_qWzHGZ<0%G`TIS5m z&0?E5 zP^41%Iu>7amiA7CEx)S!aozWvW37^#BP^yy7|bEB_DxKH9(3uT^9|K3s+~7Z?zw|d zq#zEUjlOy+!-GnxpLEa}xxW%zui>1x+b=L?{JMkMM}UDbATg^S7xLtlaIB zk}pF3Bs>;_Mm_E{Yotd7rk0%R5~kw$7927udMUiq`(5=Rir9ztB>VLb280mM?bRiG zpx&!>{xDL+^NO0s)NrMvWuTc{Xtbcb_fs?J%21MoaQsQXuU<(ou*bZ#8Ae`wIJZ2feB={jU?&xUZITEbxIY5_&&R9T{=R;`rwmH z^IY4V>DtfEr1xL_OFqIpU#n%Nh1{KozFPosJJKrd>=vFvr=G&+q~s*q-(3%!ABne5 zDOehdA)1C%TjKp6wxrw`h*cp&KV3eu4f?w4_XhyQH1Iu#MT>`1HQes*t37A?>{GY| zwyVxYVvddF(Vh)uiLHdR$Y7r2l`z;3EZBKEis^>m_TY$H3hUZTF`W0_S*oz@P45h} zT@tL@Dtn9D*zO8#(UM2?S~=P-@YETj8Eh2al$DjC zSV#4!1oPXwVk_2_-Ykoj@H6^0;}gDkavi_edOnV7>;BGCeupcf*=Ay0&Z)NaK zk8D?RMeW!pXs>9rudIhY&K$#z+GItmj{$e~Wi!5is0H4<^qVnPY>^$OK`9Eg(>giEY z+M4_nYAUMIg(lTBh4`XF-m!hEevESUa>=D_89*`iCu@8o#jh-xZbOq=Nk8=d4{vW7 z)z;QVjh+gnv}kdMV#VDh#T|+}!QI`{;_j}+-Q9~9cXxt21PK;y&UwG_jd6e7e>XpN zMr7^mBx|il=JU+?!#wMJ>mnw=>$2fudYi@Uy^utWHErSV0)PJzGaFSRUIavA;Cgsx z2I536EVC`l?RHI9R!c(g4m`MZRxo7Z9_-jD&!L`_kf3H~tKF)hGq;SZ*iANw$Ws!s zN$13VT*KqFRcb3*UDaJ2^E9^Ch$$;c5fm~y6%@364i1lKBg&EaEK4;o3=b^?7aS#s z)_pz_EN%9rpj38m7Ky||%1UgHy}vfk<6lN+%G9)9Id}HWTxW&{JNb3oNzOGb+{B2l z(|BC3q>;r6UfoIv@xVdpF86?^V;hBEi>A5+RPDPS$0Vn6@C#W=a#O zKMZ=u8hz12^X=kTG`D3V`j#L zfFG6=HF*@XgU3xqP(adhW>k=G#1bMy|Z~%1Q&vL zNNS$L@aQU(;6iG7B|z1+Jtw|9GJ_)u;|+<&()_fxPi%8GER}%})R8~PYG^~bO`d!B zNfs%cl_2M*9f2aie6R%Kd&+YndxyTra3{q64UG^}u7D{9iuFz}`dmybqvnE+jD0>( z#UN0-8AHXJf4CMscY<33u6Bm%8O1kxD#_d+5*>~NfHWwdWQF*#XTUES>El8cYeYYEMv(Y$^`Uy3i? zzdMI}Lq9uJ?%O9ULH33=Cs@@4Y;?!6!i>IfxT{oZZPm1bPk-)WZxKj>LbsxjWwZI^4VL z*Jn%_LqT`v?^vRDe4v+#ZF#e$_g2`W@=bem_xdbcgG(ReXnvu;rA&<7kotxM{6r3t z5;5|+FqpMzbG+yr7Ei9&Xm^>xUgvh^!`G6ki?Sty`esJ8tY@t+ucs}u@z*aHe2q5} zV76!yOg=WstZw5*QNEwsxb+H#elzk{%f3-!#|uy;$_ujrN@{?+{`_uY{&}fi8~8!% z^5oj#xTOSIeoIBFr1Xrbf~fPmi*sMZ z3@`-uy26Ye7d2h-H&w}yb8;8;3^V;X{!u{;gu{#ukjsp`?dX-CwTT!4}$-|_0DxT03T!B*0wm@N9eXlwHI*= zJky$w4-kqTp`tH!LNp-3gKM|Zor8#|H$8YY^aX>EyUogyyGOITW)F=w`WDm>^r|)V zA`3YyPlRmb$fg&Vs$CRvng>>lndgo1If70uI#ThE;yAjlJ}tApLz0pzP_*D4I-=~A z;NFX^-&66~2lTt+P8h)=$&q=%N!{swHL#~VZ5hZuid7(Qi$S|uQ-B`;un{_u{w z%tJA2DdzA|H@aeVFunraY~olpbY4t{>G8|h@mp@rC|H1UXl-WL2(a?F|4CJ&DJ!X9 zwdBs1$(m#}dUKBUhQ#7etuuD@dL#1cT5ExX7E;2=fpe@vf~O6r**}p~?kjCcx=2#9 zlRGXtU(2u4W5XL+R4T5u3OlM8MbQ9i1%ovyJ+nw$UW6!TOFUDY}jrkfLbwvA^2|t>qtO6)AZ7#f=XH^7rw1 zDYHyC#}8Laku!KRuPmb~e0U@HoIehOpW;p2zC&%OCo}sSu4>;e%-1{uo(^w29s3DK zEYHq~IE~)F6bc7IN9MQhE<{Bh8TR#A;;%$~m#h!YM4spG(#`awtO^prBAKD8|5#_y|MV_}bhk~iv@E|)>zr2JP|z7?@|mMjPt3S= z*X$*6nrLvUm^;pTxNv)OgZlS7V3cNM*00jXLIaBmquaNqbWJMi$|CYtEE zF6EN}dB4WK3Ej_0n3htg{XYk}zPsA%SkZFk=+w9N=wLH(gRm;&)o7ct&oMtV*CWTL z%g#9nEh|d5q?8!PtJJmoBxai7DfYVs*%>YB$k>v9{Ckn1T&mM8AesysRB{f!OwC(n zCfX?c6uhNuHL;^2+x3d(xGX}nJG`d4BCYDn3J3mE9yc2^du`-sq0U2j7Mv4(T zL6wmez9FUGm~*3O z&=Ur|6BENo#}f@M4c<>z&ul#Q(8-(&B)C*sjo8?@GZy-Wu43{wpt-WRrp4dqrD9yI z(rw62{UTMy#sitwyaDlLBQn*SJc5Z({8heuS$|ff(a&s8*|NSV@>w*5ry^L?>MwI? z-omVN6w?whhdP#W>MR%IlN2h|t%9~LBZs=$4<$|E%DzgjaS2-`+N7X?#3XF5{rSG> zI_=~1)wa+-m5}e1pPUnkIM4o0=VPg=sif;ksa4AFg*7cl&wA!~-KiY#;3_N6OMRwO zEVXPDm*nv(uzhKL5T`qH2?cr*+YXD{>l`?q-889{x|B7I&r6BJFq|UFORP>GewFaJ z2M!doJwKN_R_IOSQnV(zq~~m$U4IJgEQJS?#1MQK4KtwrK16RAbjNg&Him@ z?C-zC5h!Zb6rN$yl=;;5M;|=*GjiMz2XgWTVC335H-}M-DM_!NAG98H0h}khHFgM6 zhA(ORq}A@(7hdo zjF+XrdMa`lOwFUBz~zRn2qNT#t+_23eMp}y3OXob{H|Ev>#VlDX@Vl66E8-*6E7qh z7MvOPLNVDRIb*faOBiQAx3O^LrKS5zPW@NLMRS$A>n3CVDvUO9ZtwbPwi~<+TpLqN z#!)i14tlAsg92k5Afoic8itT|6zlv3YBU`%MqN|oPTa+W39Mgke*?x%qW$pD%-W^y z2}jqHFNe2=k>&3we8fH+?HlzjcJ*)0-7TD)*_tB_F?)VXKm>_M8?v@~TIs4GjC(iL z`Rq%H7*ib0a~-5%X3D8vI1Cmrny*fn(cRGK9=p{$5BusSqz!9wnv`v)x8p#L{fNI0 zHHRjlt&g2KuNKK?3T13ES8x58_fuzv;l8#!kSF6T*EZVi&-1_jp=f?hd^&F*XRjt< z>a<6abzeLRDjg_w(P&5vvFplgwOVNyWj+{`%-Pu}<%U4xvl=GdGAEu?xd|RbGVQ@t z1Le!rPKlLfG_oMJh|%K4%GchL^WE)nx8t)7=!-2ae42y6t&kQsuT_%0ZGO_N#xgYl zmjD^-Zq2cs`A0IOTquo!yiiQ}Ot$HGvV6rM+f{ZjpIR_!sgdX%LL`wHIoldP%w<`v zZL=f#mb}yAG-L4hw+pBnU-vu~WEcUAXT$3JY!w5L6n90X@7Jgl6ughgCl?HIxj3Ah zpDw5(4o59O$F=?QI>yO|CE`;ago(!)ptI>2dV-5=>QH=8X^ePblD8KJZIGW~b$gZ>%5-7Q{&uh`{w)?49*ids7=LQXoBXsF@I?ajdT5tKtLKDtug+Z*4*)y! zEI`mXTuO`W%#A*ac>UYur=%%qIz`HTzOVpRxNKYQ)OWKkU!84~Ts#?=HC0kHT+KMm zLGc>Sb}j$=(Bv+k_qwX#{svb8?!~5Zc)lf%=^UIGbQO3p!5>`M(Dh!o$h)mr51xOb zh+XQzbr|m!+P$T+zq-=_?FF0EbY9b4Bu%+~o|#P^+NVOhY?m!&_w`!695r94@A{!= z{kzsoP;s*=vM)E)oxjYnIFl*5NSPC z8f(I1i3hiemWrahDbiDuUoUhF*@&WV!iW4ATn;-3nBMwxGZ+2yAg!%CNMv>N)2< zR5)!4s91r956rcmN9kLgR6E?;cn(TC zOi(|Wk1+x$Y$s8#0lMRDG8YXhGqpZx`N2<~W-l0@)+-x6Xgb_WlTS~U%m~h1=nS@_ z`Dl!@%c5{Y{3WgSguL@KA2}$3_7yw+ijeb+u79Nim8=tUzM>NWerK0Q(z!8< z;T;+o56=?2=KMqZS$lB0c4)PB5$DhE7dHm$;NWiQaf+aX|G{26ph^7dcJv)k1k!7) z>Wsw1-pH_;jo*{!#)?i9zcV$iX+LHW={Jvk>pVL1cl0?>`f6NrHir?OL9`g~>Vu^? zKx8MF)#gTOA6ekfEXXr8DH_j+eTa>U@yj|-@qr|nM57{DdN^~ifOa;O%k~W>;v>dN z+pidRwdsoXWg+m}FqvU8=Y0fS2jNwgHhYfgY{jTFmbCmMZa?bT!D95~!{7S`?5xMo z4<6C>=oqx3!ve2gnObi|n21QFmy0LsPAk#0bPWC+;)<-a)Z)>Xl@0^slziVwqCHIm zs3K$kFm){|HK)kSk{(n8UU>np5B77HUr5jC_vcmsI#;*ylx%B1fzEGQL(;#MD4L!Y z&ZhE-p3U-Vuvq>MYFU7LdT-lTqahYJRM-jx`I2m&J03H}&xdqg*}h3rIfh_rc6sKL z83^9F3JO9HmMVuq^ika%YsA(l^7l6+eJyeL1wo~W&NAkdzH7=-qlcpYwEhhk znE3oWL5ZQ0#XN_o@4lg{_Am*-a4NQ`qCK(rCp>Xl)PhF8HX+ow(L>X4J5u z2p=$Ta3d!Mg+8#uI@$2q9|V~2NEGAg%##JX6V(v7$^CEDR;LsGT60j3|bycuj2mRI_w{I*j!x%`3Y`De=*lSv~H_YSApx|Gu@d09Y zQL~f3qe0iuh!k{Z_f{p~(d73Rsx|X(^QxI!ku$bMFbxXA!oexc4fk62n&*EAJiT2y zK854WR6+`8lM5fxZF*WNXbVcjjvk84zY~NF3*RV|$D_t3Y=Rf)oA{8UPj-7@K56OQYRti7S zEuoB|VhSLyui9G3U^a014O;Zvck9fwZt*f4f<(F#bHAkW+jsbn`lBTPReO6zn%EW= zcNPD}2I;!3S3aMHAIU|0GlzI9UM|N;(Ali#t;*&btNGK8aFGk$bwdvd z=egQ!!g443Sxt~H%{QBKcs8Mp0>f zR{6G7v)fmMR;tv@DSq-u^^~aac=fk^6d$=BcFHQ0oJ%n4QP*_;L@Npz-zHOk0o?%o zgsMqj@>l72U2zS!S;G=d4pdY&Lq%V#OUlXb4QP)#jieOL*3Y~U@1)OJZKSrAy=~VQ z4JhfzgC4`R=|;*e27_jmCUbp*#1KDx!QEDrb!J!F>k=#OH?*|u$=xYA!Biw_I&1$k z#6wua$!p=&B-F%Ps6Bv&RjTk;&4lZEy7o}R1uPs<-zN?i=%bAS*onuG z?)Rd(uSgs8f7w0b?}a7jQc9#FePl6W;kk0;nko2VTCR|o?Rz}9U^GB*7-B!>QuTNS ze3+ldzZvz7Z1=mxgtgXXuBEF~*xug`3>o}cQ!ZRE9oqkK;=EM5xbS0jrA*lZw{4}k zi*KS+YE-j71_nV^1ibpMpjm;Qk0hUMHt_r(^?D~^PwxRayLpBKz}9>F*CBR(A`U(| zym2eWE`{|PL-kf=EPgn;mitT<*nJVaU8uz`Kqee;|A0Ha zw$-b@`NAs`S{=k!%twSe$@z}jm66@zjk9DbK9;tmt^7NA({|6ZT<#Ku?r`2kpOkWm zU@w1omOlkkCWm&>sSgP2+X1Z)`*#V85xWy`lp2z;gRb8(b-I0`DEJFkxp7Qi0qhk4 z&Zzr`XL69{EG4=y83Lhn(qR-6C~>S}xbt7?47qh`%0W6%7fa6DpdMsGi{D*t>}anW zJ#&P1CT`0AsKs;^?O*z3u%4(aa1$)8Jqh6S2Y_^(E4g6ma@(v0pq8-Sc$w?DZhwj= z&jZVMX#qQ7$2l`EUXs+eL|o4dUD;kQKFk647ZjieE6&Z~z?Y8k49NkyCR+yc@n{n-ss@BtJ_PefGG5lSB}tO4 ztbkiAJK(^%V7u1dQNET&Do(AvBo3q6IOUL7*(P7_6*AGj;&#t%N23dNuylUdJ-fSw zmP3(A?c<(?=S5}bP5V99VDS4dB>3VUQmp&OC>1JUGgX*{<~e-J>73DyX$E(9Y519} zIm?T$(F5E!`AtQc5;`gJKikc(hR}&+MtX*p8;(A0{*7ErADp_Yj2)vqGBS_sW!zk0Eb2=2 zwCexyib_15^~{GYckdJknx}sGu6TZ>$nV80qVjG~0u>d^B~Q9;#q^wEJc?1o=6i!JO1A>mM`Eg0S?`cJ!=B30w& zgDwyC&(PGUwU^a<9?exbLre1c41MFfcLW03UYtk*9m=UPJNxKb^A*W@flLr#gwjONVGblzhE!S+b)qKqtfpDeKc z(ST5*?pRWV$m`&1Dz6_OO0OvJu%TqR>Ebu7|(TxIfW9zmy&6I%Mm=`gZ8^ z#>Tm?k1~Q815zTIda{T`2cq_MhC=kJt z_2n{oF^nIyVHeb#ug~IgpyI@R8E)T>6F&W~+pJf}Bf66j0N~$wkVmlj0EoO`81?$Xn5Ed5)UUeEaZ!6LfQ1)(n~(G?oVe)G~9fkV18MN@l|}) zP6B&94(R%<1D4&k-SN2UnBNJK?%4h>A}yLZLa-f8eeKM-UcC=5wLQneBxUc~XO-gx z#101QbzI*K5nZiMM5F-6+yzFv(>Dd$5oW7lV;yhEq4T#6(b^hEdL`(<+$m+Zjw|$g z&zYSEtCj%HQWdi7$;>D!S-m<9hgutjzU0vN;Z7t0r zZz+25$Ygcp+p@g8-r0eH(#+kPpu}?#7B=PP-qRIA*%VAt(!Rtn<4$9*A6fEuFk%L+ z6!1eDpC5VO3}&bepVY!iBawXeWZ)YmF%DD5%O9xL^eU+Ueq!rszNWLkMmh?eG`j7- z=P;1*xPobECBCiwji1*t!7a!1)FpUF&1fR$zv8F2yu9btxmoPmctdn&L%-hBR_U$T zT>U-)MCMxz>?<)L&0HqrO;iy!9eEg2K+EH_=OnDxDY=vdKhs(sJ|b^2^?mqaT3ICE z4ai8T0LP{)x`z?)I|u|wMw_R?LNDP$KV1RHcoWU zQoNu~R?QAxIrI!v-s|daF1pMZ1<`*^G!M=!n2Ij9?9_c)KCiPZ%sUE=URg@5hi{Sc z{5)EWBK8&qmDMh$HleH4Y zWc7V4hZe>iPMCus?W{4Rl1|<4MULxv+dPr19GAYd^VsbW{f2mww*$)ZQe^Ith6w4w?f^0A; zfY|A9k$lEdhbQ}+H*XlU8~#F?`Kety_pDqY{jL5O1g`3ubBb6#9nOW|5}T zs-&imbO9Xq@Efv-OTlPzax#vh?AULzNy3yJBD4Bsfh22IR#u?&sEi)hkt-JmhsR8= z3j(9p3~by&PhYEY!I&An0nVQg$}HQhnl~DM$JcTPQBqgOfs+uJKi!@EYeTB+RS{~? zcM>^M><*?v(41#Gw{>r;30n@Ie^GiC|F#>0BVaxjR)Cfs(Bi466&|4NUj6+s(=h8=YRDxTP6Mf%><(FsKQ6_ zXdE)BEgomLMU&k6SgV9a-^jiZ4MsMc`Yo)S_O&Y+4${Eic|wi-XUCcb`;W*ovt?eb z6L z{RSzMd_@xeJLkdI(tmJ({P4pLDC~1e{;!z|L9DqI%Nw7HIsaki^e&17BnZ2cQ>(_m z*D8{U0{>0n_e6?x@ctQ*%m{^|w@Zuc67U!Q{Oo~eNeACcC}s{eSbE_N^hMs&#|^d-e4-~51dNlj1_r(VV#Mm< zci%s)DXk|@wefo>#I@PKGCVKbiy)mC@3{gRGKh|8(!X^w3-MCKy0fva%B?Gk9%(c4 z@j-zG4PauQhIAiMZlLfAYr2=K*lLqt-zuaNOFUNy2M&tmaz(K>TiS6hmC%;`uF6f@ zZ;B(aeOg9~D33etl_8kpX>1mhOaAWv6^wL$KUg@+>i>^Fg$PpA$3HVic%@T#k-}nB zL6`yE7&+E}2=ki78w&R;XlT0)gKfHx+^GQAwP0steOy#T>E@?|X7F z0<}9RCO#p;=@#aaISiFOg{CIIrwlg~8y^uZ-az=WL-!(@`za zed01BN7Ez5GV4Tmd0|}9vB-$3@R1cKCOUz{UwnG*e%{e}|N7bwNpeVGYL;Ao6!-Eb zITx{%R2IMM)xQA-01WBY5#2SKK9fgJ-%HBN%WnYnRvRoaGq~-k$;f_+N8otE+=fix zDsP+Pn2O!~p}Fs*NvBfaw6zy=v+iv7E+Q@iXLq{N#832M8b0t&!2q7-Wg9NI^$rUQ z>oMRNKcIy#>;BhJIK$SY>kn_@%+bB;=kbvdqnF29o6RmgZTMo8+MrVx^dd}4OUvG# z0dx)Pw4ZcfdM7s@E0J_oGOpqFuACT-_N{rY2W4B%GPS4ir(h`=L)5wN8a6P4;FXU0 zd()eGV6FS5()yOWTD{Y6rS@#O6P9_atQ;YF+O z=*Xs1+){DP8O5K&+j;1)-qSg z=1XS2O3`w^UaKN#lP?k^mc3$}*IOyc%iS?1$#$lX>23{Jcl8odBazFT=x|v;>xTm$*5z<%wP1(7z>EOlM zZzv1+mm{k=zxY{Q-1ot$(RQ}Armuly)KM|b7qI9WU9aqFfjxRLV)7`~nJL?P7MV=A zld0w!dcAkgZvOZp&~_XvvpqEGb*td#9;M(sn_4#WVl0?+2LA^qc;S_S9NgUA`W~^u z!4m;~Tgy{ZKi4;|%GCecw_GS0e-3Efj$6L*iM@S&NNg-0WqCFr3Rvz72kjXU3k6tm zPnwGax;Is+R+*l_wCiLlD8-K5)V-mXnoG3Ew(Aq0HM->2{pEHL1FR3;sCUl&nH%Uf zmw07!$~m^{r1?ZBv!-QTS7IN3S9fz~N_34zZldrtjPptJu~;|wc}G$X0Q&YWV0HgF z4>Kf+893BL1=^t+dP|LZDDI^B@r~g$<((phHWgAIzPGSObFI#3H}fO2w>&MSzUv!s z=g35AJ6@~CE&y}{Y61#)Ig&^uQJ!nm6|4i~!oCJ(B6 zb0LK((sQHzLRQViu5kd4;K0OmmmCZRX!RMy8l*b(T!rk_V-?C7jb-7o6m}JNfPU(s zRT_<|v#V^tFfdgu0IpSyR8~EIa=1`K#Xt6{}4Pw1-?Rbvc&ef* z;|gjx)nuTxMqR%>n<_%wUzK+(Ij~zMeRoaT6?CcYDRKszn0kUwi-7TCPI_o4uPz%0 zK{;>iWxsxZPOXz@rZ?Sk^Qm~UFZ9jm8j@yCU@J2$Gz}6wr6J$Qty*^ zfWJ&nl+PR3FZ>dQ!r|DKW$^LJmIgkxTfa9y+QRd7793vM5b4i~aCZ$lZz%>aKQ4{L zJosSwuN$zV3tt3578*4n#Eo2aUnCshAe~%}7j1pWiJcQHfB``PRX)QdfkvRra+6?q<1YA7G0vPKGq z>CPeMYz#A@x4*-klfoeya~{OUr957Nr&*HUtb*0o*>%OyhS>U}>kA_(PTU|*7{NaF! zCkA3>5?``!<&9-X)vCczTjrzvbSEK`em2xND5zijT$IesCKwb*CMb_vB;0>XI2elL zwZdQ~2mHf{OJleJO6}u!qWxjbk=`dwz!_1hBEil^mF_@%lls=lneZEftZDBluUuMD z3VS-adB+<10nTSb=>U8-%MbNKC}hi%OSzx@)|F{8P);hvXkv_K#vrQc8Grh(0;G}R zMu2cnGG`X8#zj2ZPg=NJj41$_7%_{oBA?J~4#ty~RU3F5KNMi#5=v@Ex*PI!u%d%N zpQ$BLTtn`a*z&p$yu)&jfhKZq^NSE_P8?Xp`Q6>?H*nl81lEj~%Cs}wea*91w|_fs zDvW&TW2GMW5`YbmWy3TJQrgh$ziZ5?GrldZ7_%!FI0`NcINhjCP;AEiQQf=XPS_Ou zEZR<6{>?zm8JLGwZ3gkKzS^0=&aQdnPX>AurwbE@`~#}khC$nXFF79!udVy1b^FO1 zI~6)R&xQmxa7iPOK+fa?;z_EiOFdZrv;qNv7i@|demmUi58!%E^H(fY&RBG!7SEW=A}rHy?shJ&7Iofk%eW=BIkd>|wm7}x zZ#GjgupTrVH6Dt`K3#4|#-`u6AA7pCw!emv*tgv?RQ*a07p(AsaO!K!rc`P6gv;|U zUGK}>X*5g;tvb#{HPdRIjgq}|nqF{=$3#HNtu!akdkKzfXMgym3SM;owPtP}xPNhN z=hd7i_X`=FZr1|YLnFW(z5&3I+@y@UY z!aA(&T)tx=^b57u2G~p?Q8UD{&`ZV(nD2>b^69tU{cp-o)e)|9SV}G4h^v70Xl(>9 z?6&I*h@%~6Rh<7>PMwkEDjU$(80o~>c1~)sX!D~)_dhe#K-uc#cUb1O2G+v3rj^@R z*IhcMk%Iv?P@WL0ZpvWhR5^*z^mXqb?3H%z(!StQq7D5w$QYJsH|OlJTQ8IKY~_)4 zOzexL%BGG60BR5j15;Gil5xV!K4~Nec4flQ5_B<<^|z$~Tn;K-k#(!gs#qcW>fSxX zU)?ztabagA`O`E5Y17cq_pbK*1w*A6L&6N#lmhdR@_BJjOAL%RIK2UH1;IWjAM)}r zOKcd-7e{bC?n^<}m)3~1)@AulqfZRJx5PLgm!EXlO%Q!qe|D!4_US~pP$5*=a z31#c4DUL4*HvJ#YjTZH}-OMpL5ry_&ib?hrySw21Nw9bK&*wDHn~h%+uN3z$FcK1vXAIcO5~hI9=%(j^fuLzN zuLI+xxp<`lbsX3!`jGlU*tu{|pte7*p4eppf`7I@bY@o#TDEzSg~&5Ag6k(2>V(W0 zF9fbN&Vg+a0Sj|>(S_j`J>v|oPu4bNll!yoIlEy88@q+$11;$%!w-kTBu@bBMQ^`R zd)N)P-|c47t{SPqdW2p@z6;vwhELkT>&=&(WYLIX^Qg?pp(I{QOP>Dl6gAib*j{ke z;}uA{JFa(|c+5@Kzc{Ip)I1HZQz&__@!*y08y`TI9z8i*9DlDz=kQ>MignjBw370s z^ig-aS4l^#XBy5SL%eMv{BU*h@le#rip}}aZ&1hH)*NJ)HB!G}Idqh`iHf6~H{;TL z@dcVrMi&4pmAtAwaNrr@@8ajBo7A`fCv>QFJn<)~Uvz~4Uyr&4?x)?HCZq}*(6i>| zr|Lk2){M(O&oh_;xf7h--52)H+qsLHKuyUkQSGb$T=vjcls1Gm*x0Z0c-;^9UIZ?D z(}FsODH;D#zfi&r4iT5k9^QzIq2o>XZDLbiz?TAw!nU~k9^)@{OQUn8WV?zDhiK_ zD;_QgrP*QjS=KM9XLlh5x*GrW*w!4pZO3#1Y>mm8n4n~@w{1C_R;w79ojtZFQC_|5 zOdHE7DSFv|my9=YAnNK9;uU@I5B2(uv)@gIRzWvw48rV?%SS>5gEkk*-w;%xZtldcJsy=3GOAB|+bFfhtfgX^A_ueW78Afu(K9nVY|b)WyLyrSBA z#z^{IQ^&b?P3)jGU(U$0r%j+Hm&WF3@FY2zK%Ac~^{EpEOI{wNIFYl4KmwM1(LI<4 z*jQ`{tD72*`u9RQFv6h9I)B?y^|&mJ!Hj&^=m{yD`1<|vUA4h(;&S!JW5}S z)iwFKoUViYqhs(+YFIy?zeP-Hg1 z-GJ8Y(IR={l?M7$(2*&_6&By5L!i9n- z?RWDc?Dp@xfd)Z+!lLDG0t(ArGs$kB%1k9BF`K=SR+B-0KewO0|M0+9FA0?a7zE-o+a_p-A8 zwk?R${T$#W=b=PyUrnh?pUlvlpI0}&wxr_Y_>xbXxbe;h9$F zG#zEVe7($6_CfD&BxIjWs1w(*hkDEp$GLE#=_Dk1PASCkY_Lho)EuBE;GiQ{1wqs?LdKsN8((OG3B}@FDEwcETOrn*JoVGt? z&-oM|`O<3MsMkP^L**$aton`q0a=qJ|3p8w<KUOwmt7^%&+4VEZeb0bF@pqT<43h^Ce7-ZC&YKqWBeF5aF)w;Sa? z4;!7FfVN}M0K@GeJ$FGHI=61`F>vuEJVIAksoA@74f~;7U}N{48eWGc0!vhBrK8DE zc!lQ|A`u5MtVhUV&f@f=A&P9?W(&StI)u0?Z7IB)J!RfojbL%8No$BVJ5U%i)iZ1b z4VQ7N*BZ_rjsQ-L=Z)_&X4)y{o-oyXS?zedXn*L&1(;NBjGN0T4%K0LQ$;;kdtT=} zSt61C)pT7mlOHzG%+nq@AoQ_9_Cp6mjaGH|2LfEAt!(KW&S}LP=P>01crQblc zL_<}FIg5(WJAL=j}8mT zS$(^#Do@uGfiyrS#4!M$&+1!%O5VdW#XrPpERRDo-W#6CHkzUX6ODSi2=;!2{7KRY zuFG73E^19jJHKTs>A)Jql*MGJX6}J>^c`UDFIeFqRSrj-B%gU|M1+uXwpkGsS$FxY zARhS-NlM0F!am+f>dBPO#s$UJSP-bCJO3rT5(y>2u6fO$_qn<8n%g^<_TldMwcn=4 z@H7kdsbfv)XwpdmbMD2pJL1P|+;h-Jb19oHo@h>Z$1oYIG`3|Pu6Zhz^8wWDjh6E# z;nbiR%NiHN%y9oF(-4lf={;&Q9P@Ee2LAl{55CEv8keNz=nQ4TV5h?*&o^RNyD90Enlw|L_~4(Nrzq2z zJ%H+y@Wp3NUAAb)cZl&UCO8_fLuw|%vKjXYnu?8@utr`~AK%LN!5YTy%a+rd1a@|V zYT9zqqXW_)zUHzJW35&3*S01Z0_O$DE+0UdMsI|%S#MO$St7oIYkbMpS`Wmaj%#L3 ze2dcHJKI?1fBeW7ers~!H+{5q?P-j^pEJ~zR9)xd%_~kv99B<`2U5H1FG{SnKMP=AKFU2fBOw@uj76yk?4rVv+m%PUyFT?p)=MDU<- zr4fi{kz^NskmOxE96Yis*s>6+97o;xS~%(Ch@;7XN0BEr3=oqS7sPhsN4dq`B^jY% zrSt!XQ|}{ro5o-q%Btq;ox=5eHD-==hJ~fT-}Is68cRit0lizc3pa!2c@;Hv(fm&A z6rE~gl=3;(9un6F=zwBEc?3WM(^YMLZlQFq{pNu?Cd=M;aO3n7-QEi=yy0WP+Qz1T zXeeaMz?J#<;==M9xtP0)Hfx&P5S_p4qa)wmLoD2nBRBu%XcsC&J-^*i>`s8phk`sZAT*Qp}TNCE&^~^HQ)F1 z+;>Dg4nI%**+%r#pYy!guMUNr&`wQXe%;!vwx-Nyc(eK$Fev#xxz=yImq0z6cV4QQ zTm|>-A-~h%s*~^c^A}_ zF29GuqpIoNYzRK$cS1*EWgVN)?-|OttM!~z7t-rasL1rfi6jo}2I}lREK=1>qQ}Q8 zOTQdiCfm_}<+i4Oat$b`b*XWZ_zo5%iBVNso6XGC+Mxt?@8=sH}`Xch*9U1Q# zs9x~oDU`==D5%II1udVQyhOSK^(BKigX1)EhRA>vMI~5|lxkaan?uQyb3RY^4hG;a z3ud>4^UMJ~(u_PO;ln~cp)-Htkcl}1ctycAjdNRWplwUF$+vw-C|pz3ZoC&h4JlEp zXf@_wYB!tp9wyG#c6UrsNd*dd+lZ_BW)D};yT;t%f>NGE;`PCy3mdi7`D7p}ma4Lr zp1i2(n-HgnlJM?W2u-xPhYUI+T@2oMEi#@Ge2YSTaxZ^?Q(0R>6q;85AI{z~Dz0S< z+f70ONzg!W3r=u%2@+g_dvJGmNN^_vcXxNEgS)#!L*vj$V+{?rv-dgQINuoe#~t_I zq6aJrs#dKzXFcybiRZi)T?LT+{JQR-s!D0jDPmNv9J_WqU*KmKyz1)-_r|DpN{&M` z)j26W5!Bl0Iwi8KQ<^Gr!&$^9tL07Ynzq&Z;YPT}7VjwdrlmY=$R3(YuT4q~uh87~ zvEwQO4`3Ur3ft2ZAKQRo6DgzDD$ufcTLh-$j%`o31G^2eFtEyGS~47sTZumTW@-13 zMC=1O^hz^}{X|6;pb1_ZM5g3(t+(e z@he$XPya88w|r|#BQ|zEJw0#L>PsKG6dys>Li=jFTNBMfI8Hy z(sXzLcCrkJb5}p>HsxmXJbx#K?06JFaSj#^c+;OgwA>Y_#_v|+xT?OP6F+$0`w)-u z;UrTDPC%2tw1lL4@dBXxv8^@s7)ms4Z?4qX#T7si`s)L?RjEDaQ+%%SfN+hoJ3@PZ zw_m+8JCX4B+wmcjk85F8_NJDP9Zi>Oltg|prlvbtReK-~+zu$^AT4TZEmo``}1-P8x6Ay~tB(I#1_Mt^o{4_-U~=5`H(h z)~}{wXTMrvxorYmOi{Dv9wOfl!k%orE){Uhn06;KX2?G%D#s(?NtMOnP*H9A z9ZI4t9ru29#dawd1?}wXrc!+C;ZK*QXPcLc3K`?B)r)oRQ|K+mA75v6W>qRGGsDk6 z%_r2jvK}TexuASJZD-iu(<@_-@i@nJXhK7<1VK(`np4OcX{4UbxgWzD<4Q-0>J6nc@f1 zzh7@Jv}%R+bfmiyv9Wmc;X(WPJ#Y5piefa5y-YaEoeeY4jH*K!(Vh2QalM)xfnNbT z3+A&azTYvW%{f)FS9=~}jE+vxoprXXZ3mT4AFlk)6-g>uqLKVL5|w&L_h^1Mk@ss`pTX>Ep4Gj2quK7pJrwA1>PU3}*UnGf%W>{{&4pH2Sp)s2}--bOpdFgC;P%U3PUY6tAf2m!h> z0?YSc#b*oQwRy>*a+ev4s2qQ7N@xkx1%E*<#}1{qUDTR(`_INJtLt0SK%+2tl1Gud z%B(=cFnNbt6?kB6L91pArqb70) zY@)c%VUs4CzgnM9Adak0-YDLdfVaCGybP#%8zwFNNy&e;6D^Z=zb{Oq&w*9xZKSL8r9K{QzC`dQmKoN6HRP8Rt=(&5r+;%?=Noa2u+q!tMJ8XHA)w`1awmpc|% zuqAUz_%R{ea@po#m9PTZ@@q+dtY9mAak$jJkIm}k?4I6m^bQ0zMzXPR9F01d@v7Ay zM#F4J-)%Zj)7W zw42@Bt*ok|rlv*=+*Z{O5q7=5zs~}<9$mk4q=RrOxw&z*F-c_az*A6{1N#W~lQ_{^ zmK;-4(^@~67rgTg6TGf@0+mpMJ5?)4_cxh)>?byRp4Zn3oZpN`g})=8B0 zF{vO9_v4U+Up#5RVNVR89AD~t1JCjA@Ua^e=RUG{Z}`V8e)sz;S&G~Lu00w;Q3>f} zh&L&3tpp|g3s7$2DV)4~*N2up8VhboB;9l(Lm-GK6-wzom=;A zz|K3^JK<}c!H)s&Wlp`aCUkjx9~}@)S@s8XS`M3ZQj+b+bGFzQa7AQSow2DBhBm}f z+;-leph_7%j*YhXY}=GRV*gW(6ZN6^J6zGX@Ds!*E_ER{xKrkA=bAUTlfkd}_tB8- zeZOMyH2=`#>~-^hMoHvo0+BbjGApy2KtW)~!#w#^SDSRCEvV-oKo(qDPs8SBLXg`{ zc85wdvX7)bsMKQ%UtYaJ5ZokxhtdGFXLY;*J&7)Kk)&s*;jFi;KxyTLxo$@z%1MIy%SqJbor7 z1@2?GowY8!7Z7qV2)pZRqK#zkKXsd3S~~FjtX8ZZV9wX=_VG zOFP7`o>6YYMF_7X_4V}`uw=kAmaeX@YPBn~u6=zotcFZa<42b|m}3LreCxC^lj+d` zS(HMP*C3=I0Os5HV6Y-VgK>P}Cz#Hp(hj}xhwVV6zJdM8R^V5ss%gf6LZFs&ha1;Dl zCAbWuRl%-0(79DN3!tT?RiO{aI$dp+g)`ahT@&xO+;6xYrt68BfBt7FS&hk}@1BCC zsDAO(Pn^ErB64Hk{S&84fpC@~s*hHCNorjZex$e(tb#{!^zDiWxMRE%GMf$SxC&Lf zW6qe&QG!V!m*kfg?X+NwA-UH9hkeD@{SZ>6u|G1cj@`^7)!e$*naT>ewMQm6BB!`K ziJBF;eINXYm~PDjnIQGBHAa;T7+|%TxnJXDpT{!30R5%MKfw8I;>>jHKeo(*f^5%| zJ`Oc8Z9gq3?~ak4u{rSAq)7z>dFv%uTJ2lR&(4U=7TZTXAp?pBu)Q4yB1~zk=48}y z9vjmW*w)*kD3QLK2y$QoT_gZ+-y=S`;@+f)_qoQQDH=y5+AVg{%%BPh1W6X_sxXfGb{Z@^ffDD`IcTpcAH1f3~tYl zy_k=1=M`+IKtU+`*X%*a-$yfy9d1|zcQyJC1>V;x1^;r{!A=97as|WlF08os2Gi56 zdM_Ut`b*>SVC7&|=7p*O+x>phwLulF>DS}!KllBGUh2V?eLs8AVgE6m!>QbTVpYU^ zeAr~Y`u#47R|$6M*oC)`ELukE2`*lPD^|%@H!Oy zZKgj^n5^GNIoWOoee=VETF;d#aK5fQsp@X#!C*2=aLsX$xLEK21ZR;K;m0KZZjJwL z(xPF{mWXl}Vh5{}5=MUz7wi`q_vR1ETp1qrneWdUEalR5g<&Mg-g|(6 z`$(KCM^gmOjjwK_gGi+D? zjSMB@SH>MpEPc`_xOlbj%`{ELuK>(-x(WWnj|U`(Y3b>T-czF=;Q4r@Dm*Co_o4jv z&w4%{6M6l*<(ykxMQx{G-Z!O@*=L~3M&GDNukS0a+_l3F%?Q^D zt*qG1g2)ut+%*3nWOFfWetPnultk$=sUgYI5bk>H%*Gbymn3Lortz4$<~ zH(26lyWNGcpaDa@Fqe7$G}$mZi;#l76IlqWrx2{X6*ru0`XbDxj39X2a8^7iYMT6_JOH67Tm_>yBM(e6zp#Fg^qm)Mscv%zw*~YD zubw_CSNg*b`d51#jw_ot7)gn7%_E=wbS})zxts*fA@&Xnu3KALUbw^?HoECkH3=WH zh=}|wprrB|^f@yK&P;Y|(jU6R$iNu#>=pC;#2$80`cn?ozOZ$8IExOKQO}JPXnIaX z!5Bm@5qbp^X=7vmWjWZ>1XNwcOaCwcmPEYDgnXfcn-AInA8_j()qhFQ&ToyK?NUqeIP%v|m1ua^%Ew`cggvNqOv1#NLoFLma);If)h%zH4d^K(#2u_9Rvp_-G%;|mo7otp`z1AG z(BGO>*s~`#qPfi-2bao9h`ngm`#A7bNhoC`ZF%lM3wf`A#ZKXNCvQsqJMWPVp=X&Y z2}?>eV;tYy=Wdo-g$i6c$8<>#6x-AX1e^gM5?*ON4g(yEKQ*~7=FUMDfplH>~(kn&8ZuHb~nTgDrNBI z;2lzaY->FRYCZni7K23#n@NKF_MxQtk|7t7yxY3#qdjEeAfQC^hzpj%Gw|Dc0MXx~$u6W&YrTsB%~AN{0cRz*Z`@}KCK2u&}*y}G96S6&|Z zm>GK@BI@7RxQpAl9BcZ9*gGsTnw*a9Rb)Rf(+jGwm!%L^b>LDpTcwZ>)e68MZq;Q{ zBycQ$B`0i-xzANRdw6K2A-uV8D{QW#r$W-6N{+M)+C2UR}n8sE2SUF#@+!d|o%~fM}>ZN{KokzzJIE`;exjMQGRX{UL))#Nv z#z0!AFuWg$KH+UijV{-y_0o9hDHL9SCS__SgH=wt8MB!%3?WGoC&%X4tJv>P)~IDS zM_+A*H+~w(v=KP^6UUR*+N;)LJnp=@(~&Vx$W>#uPt9ewG?CO1r|UG>uglZOT+1<| z><_tfJ=n6tUeM~9Fh#2U3L!I&dJ3dkLHOB<=cFM~k+XAcniA{lk5sz5|LjzKJWJQQB6VEReS29lrJ*HGT zn>|NE)Sx@9R{IF%2ku0tQ$R$EX>|08;fFQ69a(#4#lJfT7&`gh7r_>U)QkFBb-`g3 zaLEh4w{j~8cJyNw9=N^p*`w?|iaa~VC<<?jP_;j zp2*4b=N55UMa)M;720|ur;10GZ46aPrj8u9lPI8~t~T8(s;SK$dE8rIrJVm>37ZE1 zZAHXu^BWE-s+qPD8Ln{d=*X+8hl;Gi%hZHM`p*k8YDU#~L6yVX%yzb#^zwemNmM)c-OH2)o4D zXlyTO;J!3epl?K@2;A}Vfudc@+b~(|oj$4)oOso!tQ{0hp9OyY^MiM|r{&VD?kMx5 zrrDvSEVvo%o{ghhT%7dzY;kq4dcS5vrlG#)0HO5BWGRC~jbGE${oC|hU-<(W$CQ+l z2fBs?4gNyO-f^}SRYh&^x}?t1#=&TdDwY}XliajkLr7|vd*h6ib6k0>Vtr&t9p8q~ zk%@6(I*#OnqqDKS>&{%Iq2N_%u5$nSN#y)y4wLZeΠ3L-2q$O_vCt?ZI6d9zlLg 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

1B; zi$#ej?C+eFMIZTX5w4rg#uA=_Uk@S_)zpgD z2l1rbabwiA)P7 z9gtIzX>^>_w!4?Lej~I+9X_q-!_9sFS_$Q3?yWV3lY$Ntfz{6a%64^^t8M}ms>5l{ z+p=6vI6Aoofvsr=6f}P8FM6`N>OEkMQKwtdQ1-UsEO0qrnSid2`{JGIPsv9ZyXW4J zAgic`)l(Si3w6;<)pf7C#vhBFbEvi_{{yxL;Etv4gEhveHBpJm;^I$%0ActeI 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 S4#BmRw&xxO%x%78hCz>Gu literal 0 HcmV?d00001 From 7d47d326e2d2c58d92975c02d621cbb96e52543d Mon Sep 17 00:00:00 2001 From: reza0310 Date: Fri, 14 Nov 2025 14:03:53 +0100 Subject: [PATCH 212/226] [DOCS] Images rendering path update Some paths were wrong, I used the online previewer to check them thoroughly --- EDSEditorGUI/README.md | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/EDSEditorGUI/README.md b/EDSEditorGUI/README.md index 5911d8ab..c7acfff4 100644 --- a/EDSEditorGUI/README.md +++ b/EDSEditorGUI/README.md @@ -20,7 +20,7 @@ GUI * Support for saving XDD files (CanOpen offical XML) * Some module info is displayed in GUI showing available modules (eds) and configured modules (dcf) and what OD entries they reference. Full details such as subobj extension and fixed subobj are not currently displayed and unless there is demand probably will not ever be. -
+ [Available formats' list can be found here](https://github.com/CANopenNode/CANopenEditor?tab=readme-ov-file#available-formats). Pictures @@ -28,25 +28,25 @@ Pictures For those pictures, the file shown is: https://www.hbm.com/fileadmin/mediapool/support/download/weighing/pad/PAD4000_P80_113_01_COS.EDS ### General informations -![General informations tab](Images/General infos.png) +![General informations tab](../Images/General%20infos.png) ### OD manipulation -![OD when you select an object](Images/OD selected object.png) -![OD's communication specific parameters](Images/OD comm specific param.png) +![OD when you select an object](../Images/OD%20selected%20object.png) +![OD's communication specific parameters](../Images/OD%20comm%20specific%20param.png) ### PDO manipulation TPDO:
-![TPDO tab](Images/TPDO.png)
+![TPDO tab](../Images/TPDO.png) RPDO:
-![RPDO tab](Images/RPDO.png)
+![RPDO tab](../Images/RPDO.png) PDO editing:
-![PDO edition](Images/Edit PDO.png) +![PDO edition](../Images/Edit%20PDO.png) ### Modules -![Modules tab](Images/Modules.png) +![Modules tab](../Images/Modules.png) ### Profiles Available profiles:
-![Profiles option](Images/Profiles.png)
+![Profiles option](../Images/Profiles.png) Applying a profile:
-![Profiles application](Images/Applying profile.png) +![Profiles application](../Images/Applying%20profile.png) From 884f022946229d822428c4a3610dd7f0bd4154e6 Mon Sep 17 00:00:00 2001 From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com> Date: Tue, 25 Nov 2025 07:39:23 +0100 Subject: [PATCH 213/226] Bump actions/checkout from 5 to 6 (#201) Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6. - [Release notes](https://github.com/actions/checkout/releases) - [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md) - [Commits](https://github.com/actions/checkout/compare/v5...v6) --- updated-dependencies: - dependency-name: actions/checkout dependency-version: '6' dependency-type: direct:production update-type: version-update:semver-major ... Signed-off-by: dependabot[bot] Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com> --- .github/workflows/dotnet.yml | 2 +- .github/workflows/release.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index 666513e0..ee1bb888 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -17,7 +17,7 @@ jobs: # runs-on: ubuntu-latest # Error: setup-msbuild can only be run on Windows runners steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Setup .NET diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index 9c7628e3..50ec824f 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -12,7 +12,7 @@ jobs: contents: write steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Setup .NET From 062ffcc8ab2983bd9484ca51c405781a70121e64 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Tue, 25 Nov 2025 12:21:53 +0100 Subject: [PATCH 214/226] Add IncrementNumberAtEnd Add sub index in OD: Auto increment sub index name if the name has a number at the end --- libEDSsharp/eds.cs | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 0530d652..d5885bb8 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -1281,7 +1281,32 @@ public void AccessPDO(AccessPDO accessPDO) break; } } + ///

+ /// Incremement number at end of string by given increment + /// + /// SubObject name as string to increment + /// increment for next SubObject + /// incremented name or the original string if no number is found at the end + public static string IncrementNumberAtEnd(string input, int increment) + { + // Regex to match the last token if it's a number + Regex regex = new Regex(@"(\d+)$"); + Match match = regex.Match(input); + + if (match.Success) + { + // Extract the number and increment it + int number = int.Parse(match.Value); + number += increment; + // Replace the old number with the new number + string result = regex.Replace(input, number.ToString()); + return result; + } + + // Return the original string if no number is found at the end + return input; + } /// /// Duplicate current sub entry and add it to parent /// @@ -1341,8 +1366,11 @@ public ODentry AddSubEntry() newSubObjects.Add(newSubIndex++, subOd); - if (originalOd == subOd) - newSubObjects.Add(newSubIndex++, newOd); + if (lastSubOd == subOd) { + newSubObjects.Add(newSubIndex, newOd); + // Auto increment if the parameter name has a number at the end + newSubObjects[newSubIndex].parameter_name = IncrementNumberAtEnd(newSubObjects[(ushort)(newSubIndex-1)].parameter_name, 1); + } } if (originalOd == null) newSubObjects.Add(newSubIndex++, newOd); From 7a2de63a446b16f35dffa7d8b4028544de803f03 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Fri, 28 Nov 2025 07:39:28 +0100 Subject: [PATCH 215/226] Update sourcegrid for .net 8/9 --- EDSEditorGUI/EDSEditorGUI.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 42bc8815..a3422a70 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -99,9 +99,9 @@ - - - + + + From 401707879c60f09088ba69986115421d193705e7 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Fri, 28 Nov 2025 08:30:01 +0100 Subject: [PATCH 216/226] Check if the sub index for PDO mapping is still valid (might be deleted) Prevent crash if a mapped sub was deleted from OD. --- libEDSsharp/PDOHelper.cs | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/PDOHelper.cs b/libEDSsharp/PDOHelper.cs index 1b71d0db..181ae27e 100644 --- a/libEDSsharp/PDOHelper.cs +++ b/libEDSsharp/PDOHelper.cs @@ -366,8 +366,13 @@ void build_PDOlist(UInt16 startIdx, List slots) } else maptarget.entry = eds.ods[pdoindex].Getsubobject(pdosub); - - if ((maptarget.entry.prop.CO_disabled == false) && + // Check if mapped sub index was found in OD + if (maptarget.entry == null) + { + Console.WriteLine("MAPPING FAILED, OBJEKT NOT FOUND"); + continue; + } + else if ((maptarget.entry.prop.CO_disabled == false) && (datasize <= maptarget.entry.Sizeofdatatype()) && (datasize > 0)) { From 72692887927e2520b86d6c54547bcd583ed8c24f Mon Sep 17 00:00:00 2001 From: "github-actions[bot]" <41898282+github-actions[bot]@users.noreply.github.com> Date: Mon, 1 Dec 2025 07:43:30 +0000 Subject: [PATCH 217/226] [ROOT][DOCS] contrib-readme-action has updated readme --- README.md | 53 +++++++++++++++++++++++++++++++++++++---------------- 1 file changed, 37 insertions(+), 16 deletions(-) diff --git a/README.md b/README.md index e4209fa8..0d6d48b4 100644 --- a/README.md +++ b/README.md @@ -88,10 +88,31 @@ Collaborators - - reza0310 + + robincornelius
- reza0310 + robincornelius +
+ + + + nimrof +
+ nimrof +
+ + + + CANopenNode +
+ CANopenNode +
+ + + + trojanobelix +
+ trojanobelix
@@ -149,6 +170,13 @@ Contributors + + + reza0310 +
+ reza0310 +
+ heliochronix @@ -184,6 +212,8 @@ Contributors gotocoffee1 + + wilkinsw @@ -191,8 +221,6 @@ Contributors wilkinsw - - pettaa123 @@ -228,6 +256,8 @@ Contributors DylanRobertBennett + + rgruening @@ -235,8 +265,6 @@ Contributors rgruening - - Barzello @@ -272,6 +300,8 @@ Contributors DaMutz + + StormOli @@ -279,8 +309,6 @@ Contributors StormOli - - possibly-not @@ -288,13 +316,6 @@ Contributors possibly-not - - - reza0310 -
- reza0310 -
- KwonTae-young From 46bc0c855216d9f5346ddf1c0d1bf41250f9141e Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Mon, 1 Dec 2025 11:52:18 +0100 Subject: [PATCH 218/226] feat: gui2 profile import (#200) --- EDSEditorGUI2/Converter/BrushConverter.cs | 42 +++ EDSEditorGUI2/EDSEditorGUI2.csproj | 11 + EDSEditorGUI2/Icons.axaml | 2 + EDSEditorGUI2/ViewModels/Device.cs | 12 + .../ViewModels/MainWindowViewModel.cs | 111 +++++++- .../ViewModels/ODIndexMergeStatus.cs | 49 ++++ EDSEditorGUI2/Views/MainWindow.axaml | 42 ++- EDSEditorGUI2/Views/MainWindow.axaml.cs | 253 ++++++++++++++++++ GUITests/GUITests.csproj | 13 + GUITests/ProfileImportTests.cs | 240 +++++++++++++++++ GUITests/TestAppBuilder.cs | 12 + 11 files changed, 778 insertions(+), 9 deletions(-) create mode 100644 EDSEditorGUI2/Converter/BrushConverter.cs create mode 100644 EDSEditorGUI2/ViewModels/ODIndexMergeStatus.cs create mode 100644 GUITests/ProfileImportTests.cs create mode 100644 GUITests/TestAppBuilder.cs diff --git a/EDSEditorGUI2/Converter/BrushConverter.cs b/EDSEditorGUI2/Converter/BrushConverter.cs new file mode 100644 index 00000000..c9edecbf --- /dev/null +++ b/EDSEditorGUI2/Converter/BrushConverter.cs @@ -0,0 +1,42 @@ +using System; +using System.Globalization; +using Avalonia; +using Avalonia.Data.Converters; +using Avalonia.Media; + +namespace EDSEditorGUI2.Converter; + +public sealed class BrushConverter : IValueConverter +{ + public object Convert(object? value, Type targetType, object? parameter, CultureInfo culture) + { + // TODO: Get theme and use the correct brush based on that + if (value is Boolean bValue) + { + if (bValue) + { + return new SolidColorBrush(Colors.Red); + } + else + { + var currentThemeVariant = Application.Current?.ActualThemeVariant; + + // TODO: figure out how to get the default forground from theme instead of hardcoding it + if (currentThemeVariant == Avalonia.Styling.ThemeVariant.Dark) + { + return new SolidColorBrush(Colors.White); + } + else + { + return new SolidColorBrush(Colors.Black); + } + } + } + return new SolidColorBrush(Colors.Orange); + } + + public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture) + { + throw new NotImplementedException(); + } +} diff --git a/EDSEditorGUI2/EDSEditorGUI2.csproj b/EDSEditorGUI2/EDSEditorGUI2.csproj index ab887d37..6ad75646 100644 --- a/EDSEditorGUI2/EDSEditorGUI2.csproj +++ b/EDSEditorGUI2/EDSEditorGUI2.csproj @@ -14,6 +14,17 @@ + + + + + + + + diff --git a/EDSEditorGUI2/Icons.axaml b/EDSEditorGUI2/Icons.axaml index ef341445..5583834c 100644 --- a/EDSEditorGUI2/Icons.axaml +++ b/EDSEditorGUI2/Icons.axaml @@ -6,6 +6,7 @@ + @@ -16,6 +17,7 @@ M3.7547787,12.4995322 L20.2466903,12.4995322 C20.6609039,12.4995322 20.9966903,12.1637458 20.9966903,11.7495322 C20.9966903,11.3353187 20.6609039,10.9995322 20.2466903,10.9995322 L3.7547787,10.9995322 C3.34056514,10.9995322 3.0047787,11.3353187 3.0047787,11.7495322 C3.0047787,12.1637458 3.34056514,12.4995322 3.7547787,12.4995322 Z M14.5,13 L14.5,3.75378577 C14.5,3.33978577 14.164,3.00378577 13.75,3.00378577 C13.336,3.00378577 13,3.33978577 13,3.75378577 L13,13 L3.75387573,13 C3.33987573,13 3.00387573,13.336 3.00387573,13.75 C3.00387573,14.164 3.33987573,14.5 3.75387573,14.5 L13,14.5 L13,23.7523651 C13,24.1663651 13.336,24.5023651 13.75,24.5023651 C14.164,24.5023651 14.5,24.1663651 14.5,23.7523651 L14.5,14.5 L23.7498262,14.5030754 C24.1638262,14.5030754 24.4998262,14.1670754 24.4998262,13.7530754 C24.4998262,13.3390754 24.1638262,13.0030754 23.7498262,13.0030754 L14.5,13 Z M3 5.75C3 4.23122 4.23122 3 5.75 3H15.7145C16.5764 3 17.4031 3.34241 18.0126 3.9519L20.0481 5.98744C20.6576 6.59693 21 7.42358 21 8.28553V18.25C21 19.7688 19.7688 21 18.25 21H5.75C4.23122 21 3 19.7688 3 18.25V5.75ZM5.75 4.5C5.05964 4.5 4.5 5.05964 4.5 5.75V18.25C4.5 18.9404 5.05964 19.5 5.75 19.5H6V14.25C6 13.0074 7.00736 12 8.25 12H15.75C16.9926 12 18 13.0074 18 14.25V19.5H18.25C18.9404 19.5 19.5 18.9404 19.5 18.25V8.28553C19.5 7.8214 19.3156 7.37629 18.9874 7.0481L16.9519 5.01256C16.6918 4.75246 16.3582 4.58269 16 4.52344V7.25C16 8.49264 14.9926 9.5 13.75 9.5H9.25C8.00736 9.5 7 8.49264 7 7.25V4.5H5.75ZM16.5 19.5V14.25C16.5 13.8358 16.1642 13.5 15.75 13.5H8.25C7.83579 13.5 7.5 13.8358 7.5 14.25V19.5H16.5ZM8.5 4.5V7.25C8.5 7.66421 8.83579 8 9.25 8H13.75C14.1642 8 14.5 7.66421 14.5 7.25V4.5H8.5Z + M3 4.5C3 3.11929 4.11929 2 5.5 2H17C18.3807 2 19.5 3.11929 19.5 4.5V11.3135C19.0218 11.159 18.5195 11.0585 18 11.0189V4.5C18 3.94772 17.5523 3.5 17 3.5H5.5C4.94772 3.5 4.5 3.94772 4.5 4.5V18H11.0189C11.0585 18.5195 11.159 19.0218 11.3135 19.5H4.5C4.5 20.0523 4.94772 20.5 5.5 20.5H11.7322C12.0194 21.051 12.3832 21.5557 12.8096 22H5.5C4.11929 22 3 20.8807 3 19.5V4.5Z M17.5 12C20.5376 12 23 14.4624 23 17.5C23 20.5376 20.5376 23 17.5 23C14.4624 23 12 20.5376 12 17.5C12 14.4624 14.4624 12 17.5 12ZM18.0011 20.5035L18.0006 18H20.503C20.7792 18 21.003 17.7762 21.003 17.5C21.003 17.2239 20.7792 17 20.503 17H18.0005L18 14.4993C18 14.2231 17.7761 13.9993 17.5 13.9993C17.2239 13.9993 17 14.2231 17 14.4993L17.0005 17H14.4961C14.22 17 13.9961 17.2239 13.9961 17.5C13.9961 17.7762 14.22 18 14.4961 18H17.0006L17.0011 20.5035C17.0011 20.7797 17.225 21.0035 17.5011 21.0035C17.7773 21.0035 18.0011 20.7797 18.0011 20.5035Z M6 6C6 5.44772 6.44772 5 7 5H15C15.5523 5 16 5.44772 16 6V8C16 8.55228 15.5523 9 15 9H7C6.44772 9 6 8.55228 6 8V6ZM7.5 7.5H14.5V6.5H7.5V7.5Z diff --git a/EDSEditorGUI2/ViewModels/Device.cs b/EDSEditorGUI2/ViewModels/Device.cs index c5f1ca85..568bfb04 100644 --- a/EDSEditorGUI2/ViewModels/Device.cs +++ b/EDSEditorGUI2/ViewModels/Device.cs @@ -8,6 +8,18 @@ public Device() { } + public override string ToString() + { + if (DeviceInfo == null) + { + return "unnamed device"; + } + else + { + return DeviceInfo.ProductName; + } + } + [ObservableProperty] private FileInfo _fileInfo = new(); diff --git a/EDSEditorGUI2/ViewModels/MainWindowViewModel.cs b/EDSEditorGUI2/ViewModels/MainWindowViewModel.cs index 9d0dfdf9..5e05163e 100644 --- a/EDSEditorGUI2/ViewModels/MainWindowViewModel.cs +++ b/EDSEditorGUI2/ViewModels/MainWindowViewModel.cs @@ -1,5 +1,8 @@ -using CommunityToolkit.Mvvm.ComponentModel; +using Avalonia.Media; +using CommunityToolkit.Mvvm.ComponentModel; using EDSEditorGUI2.Mapper; +using System; +using System.Collections.Generic; using System.Collections.ObjectModel; namespace EDSEditorGUI2.ViewModels; @@ -33,13 +36,115 @@ public void AddNewDevice(object sender) var DeviceView = ProtobufferViewModelMapper.MapFromProtobuffer(device); Network.Add(DeviceView); } + + public void InitMergeStatus(Device profile, List offsets) + { + MergeStatus.Clear(); + if (SelectedDevice is not null) + { + foreach (var obj in profile.Objects) + { + int mergeIndex = Int32.Parse(obj.Key); + List objectOffset = []; + foreach (var offset in offsets) + { + objectOffset.Add(new(mergeIndex + offset, false)); + } + + ODIndexMergeStatus ms = new() + { + Insert = true, + OriginalObject = $"0x{mergeIndex:x} - {obj.Value.Name}", + Offsets = objectOffset, + OriginalIndex = mergeIndex, +#pragma warning disable MVVMTK0034 // Direct field reference to [ObservableProperty] backing field + _object = obj.Value, +#pragma warning restore MVVMTK0034 // Direct field reference to [ObservableProperty] backing field + TextBrush = new SolidColorBrush(Colors.Black), + }; + + MergeStatus.Add(ms); + } + UpdateMergeStatus(offsets); + } + } + + /// + /// Update profile merge status by checking for collisions + /// + /// list of offsets in profile import + public void UpdateMergeStatus(List offsets) + { + if (SelectedDevice is not null && MergeStatus.Count != 0) + { + foreach (var obj in MergeStatus) + { + //first calculate all the offsets + //remember that the number of offsets could have changed + List objectOffset = []; + foreach (var offset in offsets) + { + int mergeIndex = obj.OriginalIndex + offset; + objectOffset.Add(new(mergeIndex, false)); + } + obj.Offsets = objectOffset; + } + + // check for collision with selected device objects + foreach (var obj in MergeStatus) + { + foreach (var offsetStatus in obj.Offsets) + { + foreach (var ob in SelectedDevice.Objects) + { + if (offsetStatus.Index == ob.Key.ToInteger()) + { + offsetStatus.Collision = true; + offsetStatus.Index *= -1; + } + } + } + } + + // check for collision with other offsets objects, collum by collum + var numberOfOffsets = MergeStatus[0].Offsets.Count; + + // Check each collum from left to right. + // you only check for collision with collums to the left + for (int i = 0; i < numberOfOffsets; i++) + { + foreach (var leftRow in MergeStatus) + { + int rightCollumIndex = leftRow.Offsets[i].Index; + for (int j = i; j >= 0; j--) + { + if (j != i) + { + foreach (var rightRow in MergeStatus) + { + int leftCollumIndex = rightRow.Offsets[j].Index; + if (rightCollumIndex == leftCollumIndex) + { + leftRow.Offsets[i].Collision = true; + } + } + } + } + } + } + } + } #pragma warning disable CA1822 // Mark members as static public string Greeting => "Welcome to Avalonia!"; #pragma warning restore CA1822 // Mark members as static public ObservableCollection Network { get; set; } = []; - [ObservableProperty] - public Device? selectedDevice; + //Used for profile import + public ObservableCollection MergeStatus { get; set; } = []; + [ObservableProperty] + public int _insertObjectsOffset; + [ObservableProperty] + public Device? _selectedDevice; } diff --git a/EDSEditorGUI2/ViewModels/ODIndexMergeStatus.cs b/EDSEditorGUI2/ViewModels/ODIndexMergeStatus.cs new file mode 100644 index 00000000..25ff1c30 --- /dev/null +++ b/EDSEditorGUI2/ViewModels/ODIndexMergeStatus.cs @@ -0,0 +1,49 @@ +using Avalonia.Media; +using CommunityToolkit.Mvvm.ComponentModel; +using System.Collections.Generic; + +namespace EDSEditorGUI2.ViewModels; + +/// +/// Viewmodel for merging one index +/// +public partial class ODIndexMergeOffsetStatus : ObservableObject +{ + public ODIndexMergeOffsetStatus(int index, bool collision) + { + Index = index; + Collision = collision; + } + [ObservableProperty] + private int _index; + + [ObservableProperty] + private bool _collision; +} + +/// +/// Used as a view model when merging ODs or inserting profiles +/// +public partial class ODIndexMergeStatus : ObservableObject +{ + [ObservableProperty] + private bool _insert; + + [ObservableProperty] + private string _originalObject = string.Empty; + + [ObservableProperty] + private List _offsets = []; + + [ObservableProperty] + private bool _indexCollision; + + [ObservableProperty] + private int _originalIndex; + + [ObservableProperty] + public required OdObject _object; + + [ObservableProperty] + public IBrush _textBrush = new SolidColorBrush(Colors.Black); +} diff --git a/EDSEditorGUI2/Views/MainWindow.axaml b/EDSEditorGUI2/Views/MainWindow.axaml index d2469cd4..aadb8de2 100644 --- a/EDSEditorGUI2/Views/MainWindow.axaml +++ b/EDSEditorGUI2/Views/MainWindow.axaml @@ -1,7 +1,9 @@ - + - - + + @@ -35,8 +37,7 @@ - - + @@ -55,7 +56,36 @@ - + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/EDSEditorGUI2/Views/MainWindow.axaml.cs b/EDSEditorGUI2/Views/MainWindow.axaml.cs index 8fc2bd17..37bcb620 100644 --- a/EDSEditorGUI2/Views/MainWindow.axaml.cs +++ b/EDSEditorGUI2/Views/MainWindow.axaml.cs @@ -1,11 +1,264 @@ using Avalonia.Controls; +using Avalonia.Controls.Templates; +using Avalonia.Data; +using Avalonia.Interactivity; +using Avalonia.Platform.Storage; +using DialogHostAvalonia; +using EDSEditorGUI2.Mapper; +using EDSEditorGUI2.ViewModels; +using libEDSsharp; +using System; +using System.Collections.Generic; +using System.Diagnostics; +using System.IO; +using System.Text.RegularExpressions; namespace EDSEditorGUI2.Views; public partial class MainWindow : Window { + readonly FilePickerFileType xpd = new("CANopen XPD 1.1") + { + Patterns = ["*.xpd"] + }; + readonly FilePickerFileType xdd = new("CANopen XDD 1.1") + { + Patterns = ["*.xdd"] + }; + readonly FilePickerFileType xdc = new("CANopen XDC 1.1") + { + Patterns = ["*.xdc"] + }; + public MainWindow() { InitializeComponent(); + LoadProfileList(); + } + private void LoadProfileList() + { + // load default profiles from the install directory + // load user profiles from the My Documents\.edseditor\profiles\ folder + // Personal is my documents in windows and ~ in mono + + try + { + List profilelist = [.. Directory.GetFiles(Path.Combine(AppContext.BaseDirectory, "Profiles"))]; + string homepath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Personal), ".edseditor"); + homepath = Path.Combine(homepath, "profiles"); + + if (Directory.Exists(homepath)) + { + profilelist.AddRange(Directory.GetFiles(homepath)); + } + + List newMenuItems = []; + + newMenuItems.Add(new MenuItem { Header = "Open Profile File...", Tag = "opendialog" }); + foreach (string file in profilelist) + { + string ext = Path.GetExtension(file).ToLower(); + if (ext == ".xpd" || ext == ".xdd") + { + newMenuItems.Add(new MenuItem { Header = Path.GetFileName(file), Tag = file }); + } + } + + foreach (var i in newMenuItems) + { + i.Click += OnProfileMenuClick; + profileMenu.Items.Add(i); + } + + } + catch (Exception e) + { + Debug.WriteLine($"Loading profiles has failed for the following reason : {e}"); + } + } + /// + /// Combines different filepicker entrie into one + /// + /// the name of the new filepicker + /// list of filepicker + /// a combination of all filepicker types + private static FilePickerFileType CombineFilePickerType(string name, List types) + { + List patterns = []; + + foreach (var t in types) + { + if (t.Patterns is not null) + { + foreach (var p in t.Patterns) + { + patterns.Add(p); + } + } + } + + return new FilePickerFileType(name) { Patterns = patterns }; + } + + /// + /// Eventhandler for any of the profile submenues + /// + /// event trigger object + /// event arguments + /// On logical errors that sould not happend + private async void OnProfileMenuClick(object? sender, RoutedEventArgs args) + { + var s = (MenuItem)sender!; + string filePath; + + if (s.Tag is string fileSource) + { + if (fileSource == "opendialog") + { + // Get top level from the current control. Alternatively, you can use Window reference instead. + var topLevel = TopLevel.GetTopLevel(this) ?? throw new Exception("Internal GUI error"); + + // Start async operation to open the dialog. + var files = await topLevel.StorageProvider.OpenFilePickerAsync(new FilePickerOpenOptions + { + Title = "Open Text File", + AllowMultiple = false, + FileTypeFilter = [CombineFilePickerType("All supported files", [xpd, xdd, xdc]), xpd, xdd, xdc] + }); + + if (files.Count >= 1) + { + filePath = files[0].Path.ToString(); + } + else + { + return; + } + } + else + { + filePath = fileSource; + } + CanOpenXDD_1_1 coxml_1_1 = new(); + var eds = coxml_1_1.ReadXML(filePath); + var proto = MappingEDS.MapToProtobuffer(eds); + var viewModel = ProtobufferViewModelMapper.MapFromProtobuffer(proto); + + if (DataContext is MainWindowViewModel dc && dc.SelectedDevice != null) + { + var selectedObjects = dc.SelectedDevice.Objects; + dc.InitMergeStatus(viewModel, [0]); + await DialogHost.Show(Resources["InsertObjectsDialog"]!, "RootDialogHost", OnDialogClosing); + } + } + } + /// + /// Event handler for the offset textbox in the profile import dialog + /// + /// + /// + public void OnOffsetTextChanged(object? sender, TextChangedEventArgs e) + { + if (DataContext is MainWindowViewModel dc && null != InsertObjects_Offsets.Text) + { + // look for "words" containing numbers + string pattern = @"\b\d+\b"; + List offsets = []; + + foreach (Match match in Regex.Matches(InsertObjects_Offsets.Text, pattern, + RegexOptions.None, + TimeSpan.FromSeconds(1))) + { + _ = int.TryParse(match.Value, out int result); + offsets.Add(result); + } + + dc.UpdateMergeStatus(offsets); + + int columnsNeeded = 2 + offsets.Count; + while (grid.Columns.Count != columnsNeeded) + { + // need to add or remove columns + if (grid.Columns.Count > columnsNeeded) + { + grid.Columns.RemoveAt(grid.Columns.Count - 1); + } + else + { + int offset = offsets[grid.Columns.Count - 2]; + int index = grid.Columns.Count - 2; + var cellTemplate = new FuncDataTemplate((item, scope) => + { + var textBlock = new TextBlock + { + [!TextBlock.TextProperty] = new Binding($"Offsets[{index}].Index") { StringFormat = @"0x{0:x}" }, + [!TextBlock.ForegroundProperty] = new Binding($"Offsets[{index}].Collision") { Converter = new Converter.BrushConverter() }, + }; + return textBlock; + }); + DataGridTemplateColumn colOffset = new() + { + CellTemplate = cellTemplate, + Header = $"Offset {offset}", + IsReadOnly = true, + }; + grid.Columns.Add(colOffset); + } + } + // Update column headers + for (var i = 0; i < offsets.Count; i++) + { + int offset = offsets[i]; + if (grid.Columns[2 + i].Header.ToString() != $"Offset {offset}") + { + grid.Columns[2 + i].Header = $"Offset {offset}"; + grid.Columns[2 + i].Width = DataGridLength.Auto; + } + } + } + } + /// + /// Called when insert objects dialog is closed + /// + /// + /// + private void OnDialogClosing(object? sender, DialogClosingEventArgs e) + { + if (DataContext is MainWindowViewModel dc) + { + if (e.Parameter is not null && (string)e.Parameter == "insert" && dc.SelectedDevice != null) + { + //Merging MergeStatus into SelectedDevice.Objects.Data + foreach (var insertObj in dc.MergeStatus) + { + if (insertObj.Insert) + { + bool matched = false; + foreach (var orgObj in dc.SelectedDevice.Objects) + { + var indexAsInteger = orgObj.Key.ToInteger(); + if (indexAsInteger == (insertObj.OriginalIndex + dc.InsertObjectsOffset)) + { + dc.SelectedDevice.Objects[orgObj.Key] = insertObj.Object; + matched = true; + } + } + if (!matched) + { + foreach (var offset in insertObj.Offsets) + { + if (offset.Collision == false) + { + string strIndex = offset.Index.ToString("X2"); + dc.SelectedDevice.Objects[strIndex] = insertObj.Object; + } + } + } + } + } + } + dc.MergeStatus.Clear(); + InsertObjects_Offsets.Text = "0"; + } } } \ No newline at end of file diff --git a/GUITests/GUITests.csproj b/GUITests/GUITests.csproj index 499faeae..0f2d4ad8 100644 --- a/GUITests/GUITests.csproj +++ b/GUITests/GUITests.csproj @@ -13,12 +13,25 @@ + + + + + + + + + + diff --git a/GUITests/ProfileImportTests.cs b/GUITests/ProfileImportTests.cs new file mode 100644 index 00000000..c25170ad --- /dev/null +++ b/GUITests/ProfileImportTests.cs @@ -0,0 +1,240 @@ +using Avalonia.Controls; +using Avalonia.Headless; +using Avalonia.Headless.XUnit; +using Avalonia.Input; +using Avalonia.Threading; +using Avalonia.VisualTree; +using EDSEditorGUI2.ViewModels; +using EDSEditorGUI2.Views; + +namespace GUITests; + +public class ImportTests : IDisposable +{ + readonly MainWindow window; + readonly MainWindowViewModel dc; + readonly MenuItem? profileMenu; + readonly TextBox? offsetsTextBox; + + readonly ComboBox? target; + readonly Button? insert; + readonly Button? cancel; + + public ImportTests() + { + dc = new MainWindowViewModel(); + window = new MainWindow + { + DataContext = dc + }; + window.Show(); + + // add device and select it + dc.AddNewDevice(window); + var deviceList = window.GetVisualDescendants().OfType().First(); + + Dispatcher.UIThread.RunJobs(); + deviceList.SelectedItem = dc.Network[0]; + + // import profile + profileMenu = window.Find("profileMenu"); + Assert.NotNull(profileMenu); + profileMenu.Open(); + var DS301Menu = profileMenu.Items.OfType().Where(x => x.Header!.ToString() == "DS301_profile.xpd").First(); + DS301Menu.Focus(); + window.KeyPressQwerty(PhysicalKey.Enter, RawInputModifiers.None); + + // fetch common ctrls + offsetsTextBox = window.Find("InsertObjects_Offsets"); + Assert.NotNull(offsetsTextBox); + + target = window.Find("InsertObjects_target"); + Assert.NotNull(target); + insert = window.Find

kSmdZpw6i!j9=eX`UhEpqU>iQ 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 literal 0 HcmV?d00001 diff --git a/Images/OD comm specific param.png b/Images/OD comm specific param.png new file mode 100644 index 0000000000000000000000000000000000000000..ec5b6044c49fce1d26e3f233b74b5a60f4d96c1a GIT binary patch literal 293856 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�|T-+1`&YqffJ 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 z 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%0AksuELD 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 literal 0 HcmV?d00001 diff --git a/Images/OD selected object.png b/Images/OD selected object.png new file mode 100644 index 0000000000000000000000000000000000000000..1ac405b3d7a00c86e1777d9f1b6874311be2f4b0 GIT binary patch literal 321633 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