From deaf241aa5cf7566edef86a5078ead4c9a6cbc12 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sat, 1 Jun 2024 13:12:53 +0200 Subject: [PATCH 1/8] protobuffer and compiling changes --- libEDSsharp/libEDSsharp.csproj | 16 ++ libEDSsharp/proto/cia301.proto | 290 +++++++++++++++++++++++++++++++++ libEDSsharp/proto/cia306.proto | 215 ++++++++++++++++++++++++ 3 files changed, 521 insertions(+) create mode 100644 libEDSsharp/proto/cia301.proto create mode 100644 libEDSsharp/proto/cia306.proto diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 3bd702cb..dd6374bf 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -24,5 +24,21 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/libEDSsharp/proto/cia301.proto b/libEDSsharp/proto/cia301.proto new file mode 100644 index 00000000..4af0f6b9 --- /dev/null +++ b/libEDSsharp/proto/cia301.proto @@ -0,0 +1,290 @@ +syntax = "proto3"; + +package libEDSsharp; + +/// +/// Object dictionary basic data types from CiA 301 +/// +enum DataType +{ + UNSPECIFIED = 0x00; + BOOLEAN = 0x01; + INTEGER8 = 0x02; + INTEGER16 = 0x03; + INTEGER32 = 0x04; + UNSIGNED8 = 0x05; + UNSIGNED16 = 0x06; + UNSIGNED32 = 0x07; + REAL32 = 0x08; + VISIBLE_STRING = 0x09; + 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; +} + +/// +/// Object Dictionary object codes from CiA 301 +/// +enum ObjectType +{ + ObjectType_UNSPECIFIED = 0; + /// + /// An object with no data fields + /// + ObjectType_NULL = 1; + /// + /// Large variable amount of data e.g. executable program code + /// + ObjectType_DOMAIN = 2; + /// + /// Denotes a type definition such as a BOOLEAN, UNSIGNED16, FLOAT and so on + /// + ObjectType_DEFTYPE = 5; + /// + /// Defines a new record type e.g. the PDO mapping structure at 21h + /// + ObjectType_DEFSTRUCT = 6; + /// + /// A single value such as an UNSIGNED8, BOOLEAN, FLOAT, INTEGER16, VISIBLE STRING etc. + /// + ObjectType_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 + /// + ObjectType_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 + /// + ObjectType_RECORD = 9; +} + +/// +/// Defines how the object can be changed from SDO +/// +enum AccessSDO +{ + AccessSDO_UNSPECIFIED = 0; + /// + /// no access + /// + AccessSDO_no = 1; + + /// + /// read only access + /// + AccessSDO_ro = 2; + + /// + /// write only access + /// + AccessSDO_wo = 3; + + /// + /// read and write access + /// + AccessSDO_rw = 4; +} + +/// +/// Defines how the object can be changed from PDO +/// +enum AccessPDO +{ + AccessPDO_UNSPECIFIED = 0; + /// + /// no access + /// + no = 1; + + /// + /// TPDO access + /// + t = 2; + + /// + /// RPDO access + /// + r = 3; + + /// + /// TPDO and RPDO access + /// + tr = 4; +} + +/// +/// Defines how the object can be changed from SRDO +/// +enum AccessSRDO +{ + /// + /// no access + /// + AccessSRDO_no = 0; + + /// + /// SRDO TX access + /// + AccessSRDO_tx = 1; + + /// + /// SRDO RX access + /// + AccessSRDO_rx = 2; + + /// + /// SRDO TX or RX access + /// + AccessSRDO_trx = 3; +} + + +/// +/// Object Dictionary SubEntry on specific Subindex. Sorted dictionary of them +/// is part of 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 OdSubEntry +{ + /// + /// Name of the sub entry. If OdEntry is "VAR", this property is not relevant. + /// If null, parameter is ignored by the JSON exporter. + /// + string SubParameterName = 1; + + /// + /// Additonal parameter name, for the device configuration file (DCF). + /// If null, parameter is ignored by the JSON exporter. + /// + string Denotation = 2; + + /// + /// CANopen data type + /// + DataType DataType = 3; + + /// + /// CANopen SDO access permissions + /// + AccessSDO AccessSDO = 4; + + /// + /// CANopen PDO access permissions + /// bool + AccessPDO AccessPDO = 5; + + /// + /// CANopen SRDO access permissions. + /// + AccessSRDO AccessSRDO = 6; + + /// + /// Default value of the sub object. + /// + string DefaultValue = 7; + + /// + /// Actual value, for the device configuration file (DCF). + /// + string ParameterValue = 8; + + /// + /// Low limit for the value. + /// + string LowLimit = 9; + + /// + /// High limit for the value. + /// + + string HighLimit = 10; + /// + /// CanOpenNode OD exporter V4: Minimum length of a string that can be stored. + /// + uint32 StringLengthMin = 1000; +} + +/// +/// Object Dictionary Entry on specific Index. Sorted dictionary of them +/// is part of CanOpenDevice - CANopen Object Dictionary. +/// +message OdEntry +{ + /// + /// If true, object is completelly skipped by CANopenNode exporters, etc. + /// If false, parameter is ignored by the JSON exporter. + /// + bool Disabled = 1; + + /// + /// Name of the entry + /// + string ParameterName = 2; + + /// + /// Additonal parameter name, for the device configuration file (DCF). + /// + string Denotation = 3; + + /// + /// Description of the Entry. + /// + string Description = 4; + + /// + /// CANopen Object Type + /// + ObjectType ObjectType = 5; + + /// + /// CANopen Complex Data Type, if ObjectType==RECORD. This property + /// is informative and required for some exportrs. Complex data types + /// are defined by OdSubEntries for each ODEntry individually. + /// + uint32 ComplexDataType = 6; + + /// + /// 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. + /// If null, parameter is ignored by the JSON exporter. + /// + string CountLabel = 1001; + + /// + /// CanOpenNode OD exporter V4: storage group into which the C variable will belong. + /// If null, it will default to "RAM" and is ignored by the JSON exporter. + /// + string StorageGroup = 1002; + + /// + /// CanOpenNode OD exporter V1.3: Flags for the PDO. + /// If false, parameter is ignored by the JSON exporter. + /// + bool FlagsPDO = 1003; + + /// + /// Sorted dictionary of sub entries + /// + map SubObjects = 9; +} + diff --git a/libEDSsharp/proto/cia306.proto b/libEDSsharp/proto/cia306.proto new file mode 100644 index 00000000..58adeb2f --- /dev/null +++ b/libEDSsharp/proto/cia306.proto @@ -0,0 +1,215 @@ +syntax = "proto3"; + +package libEDSsharp; + +import "google/protobuf/timestamp.proto"; +import "cia301.proto"; + +/// +/// CANopen [FileInfo] section, based on CiA306 +/// +message CanOpen_FileInfo +{ + /// + /// Actual file version (as string) + /// + string FileVersion = 1; + + /// + /// File description + /// + string Description = 2; + + /// + /// File creation time + /// + google.protobuf.Timestamp CreationTime = 3; + + /// + /// Name or a description of the file creator + /// + string CreatedBy = 4; + + /// + /// Time of last modification + /// + google.protobuf.Timestamp ModificationTime = 5; + + /// + /// Name or a description of the creator + /// + string ModifiedBy = 6; +} + +/// +/// CANopen [DeviceInfo] section, based on CiA306 +/// +message CanOpen_DeviceInfo +{ + /// + /// Vendor name + /// + string VendorName = 1; + + /// + /// Unique vendor-ID (index 1018, sub-index 01) + /// + uint32 VendorNumber = 2; + + /// + /// Product name + /// + string ProductName = 3; + + /// + /// Product code (index 1018, sub-index 02) + /// + uint32 ProductNumber = 4; + + /// + /// Support of the baud rate 10 kbit/s + /// + bool BaudRate_10 = 100; + + /// + /// Support of the baud rate 20 kbit/s + /// + bool BaudRate_20 = 101; + + /// + /// Support of the baud rate 50 kbit/s + /// + bool BaudRate_50 = 102; + + /// + /// Support of the baud rate 125 kbit/s + /// + bool BaudRate_125 = 103; + + /// + /// Support of the baud rate 250 kbit/s + /// + bool BaudRate_250 = 104; + + /// + /// Support of the baud rate 500 kbit/s + /// + bool BaudRate_500 = 105; + + /// + /// Support of the baud rate 800 kbit/s + /// + bool BaudRate_800 = 106; + + /// + /// Support of the baud rate 1000 kbit/s + /// + bool BaudRate_1000 = 107; + + /// + /// Minimum size of a mappable object in bits, allowed for the PDO mapping on this CANopen device, usually 8 + /// + uint32 Granularity = 200; + + /// + /// Number of the supported receive PDOs + /// + uint32 NrOfRxPDO = 201; + + /// + /// Number of the supported transmit PDOs + /// + uint32 NrOfTxPDO = 202; + + /// + /// Support of the LSS slave functionality, see CiA305 + /// + bool LssSlave = 203; + + /// + /// Support of the LSS master functionality, see CiA305 + /// + bool LssMaster = 204; + + /// + /// Support of the NodeGuarding slave + /// + bool NodeGuardingSlave = 205; + + /// + /// Support of the NodeGuarding master + /// + bool NodeGuardingMaster = 206; + + /// + /// Support of the NodeGuarding master + /// + uint32 NrOfNodeGuardingMonitoredNodes = 207; +} + +/// +/// CANopen [DeviceComissioning] section, based on CiA306, used for the device configuration file (DCF) +/// +message CanOpen_DeviceComissioning +{ + /// + /// CANopen device’s address + /// + uint32 NodeID = 1; + + /// + /// Node name + /// + string NodeName = 2; + + /// + /// CANopen device’s baudrate + /// + uint32 Baudrate = 3; + + /// + /// Number of the network + /// + uint32 NetNumber = 4; + + /// + /// Name of the network + /// + string NetworkName = 5; + + /// + /// CANopen device is the CANopen manager + /// + bool CANopenManager = 6; + + /// + /// Serial number (index 1018, sub-index 03) + /// + uint32 LSS_SerialNumber = 7; +} + +/// +/// CANopen Device description object +/// +message CanOpenDevice +{ + /// + /// CANopen [FileInfo] section, based on CiA306 + /// + CanOpen_FileInfo FileInfo = 1; + + /// + /// CANopen [DeviceInfo] section, based on CiA306 + /// + CanOpen_DeviceInfo DeviceInfo = 2; + + /// + /// CANopen [DeviceComissioning] section, based on CiA306, used for the device configuration file (DCF) + /// + CanOpen_DeviceComissioning DeviceComissioning = 3; + + /// + /// CANopen Object Dictionary + /// + map Objects = 4; +} \ No newline at end of file From b62a3aba98ee084223ba9fe4631a38f0ff2c8147 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Sun, 2 Jun 2024 19:54:44 +0200 Subject: [PATCH 2/8] fix version bug --- libEDSsharp/libEDSsharp.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index dd6374bf..fdd702dd 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -34,8 +34,8 @@ - - + + From 8bbf367742a89a1d25980dd245654f6d77df2951 Mon Sep 17 00:00:00 2001 From: Janez Date: Tue, 2 Jul 2024 19:33:53 +0200 Subject: [PATCH 3/8] Added protobuffer exporter/importer. --- EDSEditorGUI/.gitignore | 3 +- EDSEditorGUI/Form1.cs | 86 ++- libEDSsharp/CanOpenXDD_1_1.cs | 1151 ++++++++++++++++++++++++++++++- libEDSsharp/libEDSsharp.csproj | 14 +- libEDSsharp/proto/.gitignore | 1 + libEDSsharp/proto/CanOpen.proto | 168 +++++ libEDSsharp/proto/cia301.proto | 290 -------- libEDSsharp/proto/cia306.proto | 215 ------ 8 files changed, 1407 insertions(+), 521 deletions(-) create mode 100644 libEDSsharp/proto/.gitignore create mode 100644 libEDSsharp/proto/CanOpen.proto delete mode 100644 libEDSsharp/proto/cia301.proto delete mode 100644 libEDSsharp/proto/cia306.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 1d051a94..6f5ab219 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 fdd702dd..cf442af8 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -23,21 +23,21 @@ - - - + + + + - - + - + - + 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. +} diff --git a/libEDSsharp/proto/cia301.proto b/libEDSsharp/proto/cia301.proto deleted file mode 100644 index 4af0f6b9..00000000 --- a/libEDSsharp/proto/cia301.proto +++ /dev/null @@ -1,290 +0,0 @@ -syntax = "proto3"; - -package libEDSsharp; - -/// -/// Object dictionary basic data types from CiA 301 -/// -enum DataType -{ - UNSPECIFIED = 0x00; - BOOLEAN = 0x01; - INTEGER8 = 0x02; - INTEGER16 = 0x03; - INTEGER32 = 0x04; - UNSIGNED8 = 0x05; - UNSIGNED16 = 0x06; - UNSIGNED32 = 0x07; - REAL32 = 0x08; - VISIBLE_STRING = 0x09; - 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; -} - -/// -/// Object Dictionary object codes from CiA 301 -/// -enum ObjectType -{ - ObjectType_UNSPECIFIED = 0; - /// - /// An object with no data fields - /// - ObjectType_NULL = 1; - /// - /// Large variable amount of data e.g. executable program code - /// - ObjectType_DOMAIN = 2; - /// - /// Denotes a type definition such as a BOOLEAN, UNSIGNED16, FLOAT and so on - /// - ObjectType_DEFTYPE = 5; - /// - /// Defines a new record type e.g. the PDO mapping structure at 21h - /// - ObjectType_DEFSTRUCT = 6; - /// - /// A single value such as an UNSIGNED8, BOOLEAN, FLOAT, INTEGER16, VISIBLE STRING etc. - /// - ObjectType_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 - /// - ObjectType_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 - /// - ObjectType_RECORD = 9; -} - -/// -/// Defines how the object can be changed from SDO -/// -enum AccessSDO -{ - AccessSDO_UNSPECIFIED = 0; - /// - /// no access - /// - AccessSDO_no = 1; - - /// - /// read only access - /// - AccessSDO_ro = 2; - - /// - /// write only access - /// - AccessSDO_wo = 3; - - /// - /// read and write access - /// - AccessSDO_rw = 4; -} - -/// -/// Defines how the object can be changed from PDO -/// -enum AccessPDO -{ - AccessPDO_UNSPECIFIED = 0; - /// - /// no access - /// - no = 1; - - /// - /// TPDO access - /// - t = 2; - - /// - /// RPDO access - /// - r = 3; - - /// - /// TPDO and RPDO access - /// - tr = 4; -} - -/// -/// Defines how the object can be changed from SRDO -/// -enum AccessSRDO -{ - /// - /// no access - /// - AccessSRDO_no = 0; - - /// - /// SRDO TX access - /// - AccessSRDO_tx = 1; - - /// - /// SRDO RX access - /// - AccessSRDO_rx = 2; - - /// - /// SRDO TX or RX access - /// - AccessSRDO_trx = 3; -} - - -/// -/// Object Dictionary SubEntry on specific Subindex. Sorted dictionary of them -/// is part of 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 OdSubEntry -{ - /// - /// Name of the sub entry. If OdEntry is "VAR", this property is not relevant. - /// If null, parameter is ignored by the JSON exporter. - /// - string SubParameterName = 1; - - /// - /// Additonal parameter name, for the device configuration file (DCF). - /// If null, parameter is ignored by the JSON exporter. - /// - string Denotation = 2; - - /// - /// CANopen data type - /// - DataType DataType = 3; - - /// - /// CANopen SDO access permissions - /// - AccessSDO AccessSDO = 4; - - /// - /// CANopen PDO access permissions - /// bool - AccessPDO AccessPDO = 5; - - /// - /// CANopen SRDO access permissions. - /// - AccessSRDO AccessSRDO = 6; - - /// - /// Default value of the sub object. - /// - string DefaultValue = 7; - - /// - /// Actual value, for the device configuration file (DCF). - /// - string ParameterValue = 8; - - /// - /// Low limit for the value. - /// - string LowLimit = 9; - - /// - /// High limit for the value. - /// - - string HighLimit = 10; - /// - /// CanOpenNode OD exporter V4: Minimum length of a string that can be stored. - /// - uint32 StringLengthMin = 1000; -} - -/// -/// Object Dictionary Entry on specific Index. Sorted dictionary of them -/// is part of CanOpenDevice - CANopen Object Dictionary. -/// -message OdEntry -{ - /// - /// If true, object is completelly skipped by CANopenNode exporters, etc. - /// If false, parameter is ignored by the JSON exporter. - /// - bool Disabled = 1; - - /// - /// Name of the entry - /// - string ParameterName = 2; - - /// - /// Additonal parameter name, for the device configuration file (DCF). - /// - string Denotation = 3; - - /// - /// Description of the Entry. - /// - string Description = 4; - - /// - /// CANopen Object Type - /// - ObjectType ObjectType = 5; - - /// - /// CANopen Complex Data Type, if ObjectType==RECORD. This property - /// is informative and required for some exportrs. Complex data types - /// are defined by OdSubEntries for each ODEntry individually. - /// - uint32 ComplexDataType = 6; - - /// - /// 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. - /// If null, parameter is ignored by the JSON exporter. - /// - string CountLabel = 1001; - - /// - /// CanOpenNode OD exporter V4: storage group into which the C variable will belong. - /// If null, it will default to "RAM" and is ignored by the JSON exporter. - /// - string StorageGroup = 1002; - - /// - /// CanOpenNode OD exporter V1.3: Flags for the PDO. - /// If false, parameter is ignored by the JSON exporter. - /// - bool FlagsPDO = 1003; - - /// - /// Sorted dictionary of sub entries - /// - map SubObjects = 9; -} - diff --git a/libEDSsharp/proto/cia306.proto b/libEDSsharp/proto/cia306.proto deleted file mode 100644 index 58adeb2f..00000000 --- a/libEDSsharp/proto/cia306.proto +++ /dev/null @@ -1,215 +0,0 @@ -syntax = "proto3"; - -package libEDSsharp; - -import "google/protobuf/timestamp.proto"; -import "cia301.proto"; - -/// -/// CANopen [FileInfo] section, based on CiA306 -/// -message CanOpen_FileInfo -{ - /// - /// Actual file version (as string) - /// - string FileVersion = 1; - - /// - /// File description - /// - string Description = 2; - - /// - /// File creation time - /// - google.protobuf.Timestamp CreationTime = 3; - - /// - /// Name or a description of the file creator - /// - string CreatedBy = 4; - - /// - /// Time of last modification - /// - google.protobuf.Timestamp ModificationTime = 5; - - /// - /// Name or a description of the creator - /// - string ModifiedBy = 6; -} - -/// -/// CANopen [DeviceInfo] section, based on CiA306 -/// -message CanOpen_DeviceInfo -{ - /// - /// Vendor name - /// - string VendorName = 1; - - /// - /// Unique vendor-ID (index 1018, sub-index 01) - /// - uint32 VendorNumber = 2; - - /// - /// Product name - /// - string ProductName = 3; - - /// - /// Product code (index 1018, sub-index 02) - /// - uint32 ProductNumber = 4; - - /// - /// Support of the baud rate 10 kbit/s - /// - bool BaudRate_10 = 100; - - /// - /// Support of the baud rate 20 kbit/s - /// - bool BaudRate_20 = 101; - - /// - /// Support of the baud rate 50 kbit/s - /// - bool BaudRate_50 = 102; - - /// - /// Support of the baud rate 125 kbit/s - /// - bool BaudRate_125 = 103; - - /// - /// Support of the baud rate 250 kbit/s - /// - bool BaudRate_250 = 104; - - /// - /// Support of the baud rate 500 kbit/s - /// - bool BaudRate_500 = 105; - - /// - /// Support of the baud rate 800 kbit/s - /// - bool BaudRate_800 = 106; - - /// - /// Support of the baud rate 1000 kbit/s - /// - bool BaudRate_1000 = 107; - - /// - /// Minimum size of a mappable object in bits, allowed for the PDO mapping on this CANopen device, usually 8 - /// - uint32 Granularity = 200; - - /// - /// Number of the supported receive PDOs - /// - uint32 NrOfRxPDO = 201; - - /// - /// Number of the supported transmit PDOs - /// - uint32 NrOfTxPDO = 202; - - /// - /// Support of the LSS slave functionality, see CiA305 - /// - bool LssSlave = 203; - - /// - /// Support of the LSS master functionality, see CiA305 - /// - bool LssMaster = 204; - - /// - /// Support of the NodeGuarding slave - /// - bool NodeGuardingSlave = 205; - - /// - /// Support of the NodeGuarding master - /// - bool NodeGuardingMaster = 206; - - /// - /// Support of the NodeGuarding master - /// - uint32 NrOfNodeGuardingMonitoredNodes = 207; -} - -/// -/// CANopen [DeviceComissioning] section, based on CiA306, used for the device configuration file (DCF) -/// -message CanOpen_DeviceComissioning -{ - /// - /// CANopen device’s address - /// - uint32 NodeID = 1; - - /// - /// Node name - /// - string NodeName = 2; - - /// - /// CANopen device’s baudrate - /// - uint32 Baudrate = 3; - - /// - /// Number of the network - /// - uint32 NetNumber = 4; - - /// - /// Name of the network - /// - string NetworkName = 5; - - /// - /// CANopen device is the CANopen manager - /// - bool CANopenManager = 6; - - /// - /// Serial number (index 1018, sub-index 03) - /// - uint32 LSS_SerialNumber = 7; -} - -/// -/// CANopen Device description object -/// -message CanOpenDevice -{ - /// - /// CANopen [FileInfo] section, based on CiA306 - /// - CanOpen_FileInfo FileInfo = 1; - - /// - /// CANopen [DeviceInfo] section, based on CiA306 - /// - CanOpen_DeviceInfo DeviceInfo = 2; - - /// - /// CANopen [DeviceComissioning] section, based on CiA306, used for the device configuration file (DCF) - /// - CanOpen_DeviceComissioning DeviceComissioning = 3; - - /// - /// CANopen Object Dictionary - /// - map Objects = 4; -} \ No newline at end of file From 7c5963d72e60e0571900f9670052813e5e202ad1 Mon Sep 17 00:00:00 2001 From: Janez Date: Tue, 2 Jul 2024 19:45:26 +0200 Subject: [PATCH 4/8] Fix path separator --- libEDSsharp/libEDSsharp.csproj | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index cf442af8..65b1754b 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -30,14 +30,14 @@ - + - - - + + + - + From 7e24cecdb91620f951c38acf0e3e02c2209301af Mon Sep 17 00:00:00 2001 From: Janez Date: Tue, 2 Jul 2024 19:56:33 +0200 Subject: [PATCH 5/8] Fix path separator 2 --- libEDSsharp/libEDSsharp.csproj | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 65b1754b..e9e7ebea 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -30,14 +30,14 @@ - + - + - + From c2670a238a4b284706bef64ba913893b4227abcb Mon Sep 17 00:00:00 2001 From: Janez Date: Tue, 2 Jul 2024 20:18:36 +0200 Subject: [PATCH 6/8] Fix version --- libEDSsharp/libEDSsharp.csproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index e9e7ebea..26a8dd49 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -34,8 +34,8 @@ - - + + From 6d04fe0b247fd09b19d20d34807fac9135214a53 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Tue, 16 Jul 2024 08:03:17 +0200 Subject: [PATCH 7/8] Fixing function name & CodeDom version --- EDSEditorGUI/Form1.cs | 14 +++++++------- libEDSsharp/libEDSsharp.csproj | 2 +- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 6f5ab219..f273ae02 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -306,11 +306,11 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) break; case ".binpb": - openProtobufferfile(odf.FileName, false); + OpenProtobufferfile(odf.FileName, false); break; case ".json": - openProtobufferfile(odf.FileName, true); + OpenProtobufferfile(odf.FileName, true); break; default: @@ -378,7 +378,7 @@ private void openXDDfile(string path) } - private void openProtobufferfile(string path, bool json) + private void OpenProtobufferfile(string path, bool json) { Warnings.warning_list.Clear(); @@ -753,9 +753,9 @@ void OpenRecentFile(object sender, EventArgs e) openXDDfile(filepath); else if (ext == ".binpb") - openProtobufferfile(filepath, false); + OpenProtobufferfile(filepath, false); else if (ext == ".json") - openProtobufferfile(filepath, true); + OpenProtobufferfile(filepath, true); if ( ext == ".eds" ) openEDSfile(filepath, InfoSection.Filetype.File_EDS); @@ -1278,11 +1278,11 @@ private void ODEditor_MainForm_DragDrop(object sender, DragEventArgs e) break; case ".binpb": - openProtobufferfile(fileName, false); + OpenProtobufferfile(fileName, false); break; case ".json": - openProtobufferfile(fileName, true); + OpenProtobufferfile(fileName, true); break; default: diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 26a8dd49..43ed12ff 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -23,7 +23,7 @@ - + From 7688755206bafc82a96302fee80e491073bf45aa Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Tue, 16 Jul 2024 15:39:26 +0200 Subject: [PATCH 8/8] Removed PackageReference to System.Runtime.CompilerServices.Unsafe --- libEDSsharp/libEDSsharp.csproj | 1 - 1 file changed, 1 deletion(-) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 43ed12ff..a5c42523 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -26,7 +26,6 @@ -