From 7b8ceba96707e783e80b559867af06827517f33c Mon Sep 17 00:00:00 2001 From: Ueli Niederer Date: Thu, 15 Dec 2022 09:19:47 +0100 Subject: [PATCH 01/17] Extend dirty-notification with an option to save instantly rather than just falling back --- EDSEditorGUI/DeviceODView.cs | 1299 +++++++++++++++++----------------- 1 file changed, 661 insertions(+), 638 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index dc0453a5..005e34c0 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -1,47 +1,47 @@ -/* - 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 +126,345 @@ 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 = 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.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; + + 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(); + 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, 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 }); + } + } +} From 5ef3e831b60bc166f0a36c0c0a453880fe85bf19 Mon Sep 17 00:00:00 2001 From: Ueli Niederer Date: Thu, 15 Dec 2022 09:24:11 +0100 Subject: [PATCH 02/17] Make message more explicit --- EDSEditorGUI/DeviceODView.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index 005e34c0..e8f1f7ed 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -132,7 +132,7 @@ private bool Checkdirty() if (button_saveChanges.BackColor == Color.Red) { - var answer = 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.YesNoCancel); + var answer = 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: From 813788a66d77c5bdd909cd188fa000a16b35bfc1 Mon Sep 17 00:00:00 2001 From: Ueli Niederer Date: Thu, 15 Dec 2022 12:03:44 +0100 Subject: [PATCH 03/17] Add autosave option --- EDSEditorGUI/DeviceODView.Designer.cs | 18 +++++++++++++++--- EDSEditorGUI/DeviceODView.cs | 27 +++++++++++++++++++++++++-- 2 files changed, 40 insertions(+), 5 deletions(-) diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index 927dd188..40363c1f 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(); @@ -464,6 +465,7 @@ private void InitializeComponent() // // 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); @@ -495,14 +497,23 @@ 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; this.groupBox1.Text = "Object settings"; // + // checkBox_autosave + // + this.checkBox_autosave.Location = new System.Drawing.Point(702, 148); + this.checkBox_autosave.Name = "checkBox_autosave"; + this.checkBox_autosave.Size = new System.Drawing.Size(139, 17); + this.checkBox_autosave.TabIndex = 35; + this.checkBox_autosave.Text = "Save changes on leave"; + this.checkBox_autosave.UseVisualStyleBackColor = true; + // // textBox_stringLengthMin // this.textBox_stringLengthMin.Location = new System.Drawing.Point(340, 99); @@ -1036,6 +1047,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 e8f1f7ed..f0594101 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -25,6 +25,7 @@ You should have received a copy of the GNU General Public License using System.Reflection; using System.Text.RegularExpressions; using libEDSsharp; + namespace ODEditor { @@ -132,7 +133,10 @@ private bool Checkdirty() if (button_saveChanges.BackColor == Color.Red) { - var answer = 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); + 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: @@ -629,7 +633,8 @@ 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 (listView_subObjects.FocusedItem.Bounds.Contains(e.Location) == true) + + if (isClickOnItem(e.Location)) { contextMenu_subObject.Show(Cursor.Position); } @@ -640,6 +645,24 @@ private void ListView_subObjects_MouseClick(object sender, MouseEventArgs e) } } + 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)); From 226383f4559ac602dd53b2e12f6d725af218e57d Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Tue, 2 Jul 2024 12:28:37 +0200 Subject: [PATCH 04/17] 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 1608e9c1f1f261bf09ad8df784f2ce8c0a8c3b87 Mon Sep 17 00:00:00 2001 From: Lars Elgtvedt Susaas Date: Tue, 16 Jul 2024 22:22:53 +0200 Subject: [PATCH 05/17] added it back --- 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 ba45e03ccac2f7289eff971290ca3766687dc40e Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Sun, 1 Dec 2024 13:09:31 +0100 Subject: [PATCH 06/17] Add/extend some exception catches to provide more information what was wrong Show filename on MouseHover in TabControl --- EDSEditorGUI/Form1.Designer.cs | 5 ++- EDSEditorGUI/Form1.cs | 67 +++++++++++++++++++++++++--------- EDSEditorGUI/Form1.resx | 2 +- libEDSsharp/CanOpenEDS.cs | 9 ++++- libEDSsharp/CanOpenXDD_1_1.cs | 10 ++++- 5 files changed, 70 insertions(+), 23 deletions(-) diff --git a/EDSEditorGUI/Form1.Designer.cs b/EDSEditorGUI/Form1.Designer.cs index 6ef5774d..7f1e72f2 100644 --- a/EDSEditorGUI/Form1.Designer.cs +++ b/EDSEditorGUI/Form1.Designer.cs @@ -290,17 +290,20 @@ private void InitializeComponent() this.tabControl1.Multiline = true; this.tabControl1.Name = "tabControl1"; this.tabControl1.SelectedIndex = 0; + this.tabControl1.ShowToolTips = true; 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.ControlRemoved += new System.Windows.Forms.ControlEventHandler(this.tabControl1_ControlsChanged); 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); + this.tabControl1.MouseClick += new System.Windows.Forms.MouseEventHandler(this.tabControl1_MouseClick); + this.tabControl1.MouseHover += new System.EventHandler(this.tabControl1_MouseHover); // // ODEditor_MainForm // diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 1e9d0ca9..c168eb7e 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -26,7 +26,9 @@ You should have received a copy of the GNU General Public License using System.Windows.Forms; using System.IO; using libEDSsharp; -using static System.Windows.Forms.VisualStyles.VisualStyleElement; +//using static System.Windows.Forms.VisualStyles.VisualStyleElement; +//using SourceGrid.Cells.Controllers; +//using ToolTip = System.Windows.Forms.ToolTip; namespace ODEditor { @@ -189,6 +191,12 @@ private void openEDSfile(string path,InfoSection.Filetype ft) { EDSsharp eds = new EDSsharp(); + if (!File.Exists(path)) + { + MessageBox.Show("File " +path + "\ndoes not exist."); + return; + } + eds.Loadfile(path); DeviceView device = new DeviceView(eds, network); @@ -327,6 +335,11 @@ private void openToolStripMenuItem_Click(object sender, EventArgs e) private void openXDDfile(string path) { + if (!File.Exists(path)) + { + MessageBox.Show("File " + path + "\ndoes not exist."); + return; + } try { EDSsharp eds; @@ -449,13 +462,13 @@ private void Eds_onDataDirty(bool dirty, EDSsharp sender) { foreach(Control c in page.Controls) { - if(c.GetType() == typeof(DeviceView)) + if (c.GetType() == typeof(DeviceView)) { DeviceView d = (DeviceView)c; if (d.eds.Dirty == true) { page.BackColor = Color.Tomato; - } + } else { page.BackColor = default(Color); @@ -1329,34 +1342,52 @@ private void preferencesToolStripMenuItem_Click(object sender, EventArgs e) private void tabControl1_MouseClick(object sender, MouseEventArgs e) { - TabPage tp; if (e.Button == MouseButtons.Right) { for (int i = 0; i <= tabControl1.TabCount - 1; i++) { if (tabControl1.GetTabRect(i).Contains(e.Location)) { - tp = tabControl1.TabPages[i]; - DialogResult dialogResult = MessageBox.Show(tabControl1.TabPages[i].Text, "Close file?", MessageBoxButtons.YesNo); if (dialogResult == DialogResult.Yes) { - - DeviceView device = (DeviceView)tabControl1.TabPages[i].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.TabPages[i]); + DeviceView device = (DeviceView)tabControl1.TabPages[i].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.TabPages[i]); } } } } } + private void tabControl1_MouseHover(object sender, EventArgs e) + { + + TabControl tabControl = sender as TabControl; + Point mousePosition = tabControl.PointToClient(Cursor.Position); + for (int i = 0; i < tabControl.TabCount; i++) + { + Rectangle tabRect = tabControl.GetTabRect(i); + if (tabRect.Contains(mousePosition)) + { + ToolTip toolTip = new ToolTip(); + // Set up the delays for the ToolTip. + + toolTip.AutoPopDelay = 5000; + toolTip.InitialDelay = 1000; + toolTip.ReshowDelay = 500; + // Force the ToolTip text to be displayed whether or not the form is active. + toolTip.ShowAlways = true; + DeviceView device = (DeviceView)tabControl1.TabPages[i].Controls[0]; + toolTip.SetToolTip(tabControl, device.eds.projectFilename); + break; + } + } + } + } } diff --git a/EDSEditorGUI/Form1.resx b/EDSEditorGUI/Form1.resx index 29de9ad8..e9b79be8 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+kH4AMgFyjcd8GS4AAAAJcEhZcwAACw4AAAsOAUC+4UEAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF + HW9+kH4AMgFyjcd8GS4AAAAJcEhZcwAACwwAAAsMAT9AIsgAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF WHRDb21tZW50AENBTm9wZW7cllV1AAAC8UlEQVRYR9WWz2sTQRTHkx6SQy5RxFv1JDGHogiVIkqFEqLE QigetKY3iSUpPYh/gD8uoQiJIEKJ0UNNRZKjTaQiHozePAk21eagCC20NdW1plTa8X3f7mw3cZNuzSr6 hQ+8zn6/M29nZts6/hWdIu4T4xZJE2cJ23QvGAyKRCJhCXgp80CN2qNxTAyVP5QZZVXhn6H5mRlGCl5k diff --git a/libEDSsharp/CanOpenEDS.cs b/libEDSsharp/CanOpenEDS.cs index d4be60f6..ffdaae09 100644 --- a/libEDSsharp/CanOpenEDS.cs +++ b/libEDSsharp/CanOpenEDS.cs @@ -825,8 +825,13 @@ public void Loadfile(string filename) int lineno = 1; foreach (string linex in System.IO.File.ReadLines(filename)) { - Parseline(linex, lineno); - lineno++; + try + { + Parseline(linex, lineno); + lineno++; + } + catch (Exception) { Warnings.warning_list.Add("Failed to open file \n" + filename);} + } di = new DeviceInfo(eds["DeviceInfo"]); diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 5c682027..91a7d659 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -100,8 +100,16 @@ public EDSsharp ReadXML(string file) dev = (ISO15745ProfileContainer)serializer.Deserialize(reader); reader.Close(); } - catch (Exception) + catch (Exception e) { + if (e is System.InvalidOperationException) + { + Warnings.warning_list.Add(String.Format("{0} {1} Action aborted!", e.Message, e.InnerException.Message)); + } + else + { + Warnings.warning_list.Add(String.Format("{0} Action aborted!", e.ToString())); + } return null; } From 5cb1bda209b0940aad1baf6257201b7ef008a45a Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Tue, 14 Jan 2025 17:43:29 +0100 Subject: [PATCH 07/17] Unified header for Exporter legacy/V4 --- EDSEditorGUI/EDSEditorGUI.csproj | 10 ++++--- libEDSsharp/CanOpenNodeExporter.cs | 38 ++++++++++++--------------- libEDSsharp/CanOpenNodeExporter_V4.cs | 27 ++++++++++++++++++- 3 files changed, 50 insertions(+), 25 deletions(-) diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 9dde5d88..642834ef 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -98,11 +98,15 @@ - - - + + + + + 8.0.11 + + git describe --tags --long --dirty > "$(MSBuildProjectDirectory)\version.txt" || exit 0 diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index df728b8d..78ea78d3 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -461,7 +461,22 @@ This file was automatically generated by CANopenEditor {0} https://github.com/CANopenNode/CANopenEditor DON'T EDIT THIS FILE MANUALLY !!!! -*******************************************************************************/", this.gitVersion)); +*******************************************************************************", this.gitVersion)); + 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(" 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(""); } private void export_h(string filename) @@ -503,28 +518,9 @@ CANopen DATA TYPES "); - 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(@"/******************************************************************************* +file.WriteLine(@"/******************************************************************************* FEATURES *******************************************************************************/"); diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 786bb9c1..4b52984f 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -602,8 +602,33 @@ This file was automatically generated by CANopenEditor {0} https://github.com/CANopenNode/CANopenEditor DON'T EDIT THIS FILE MANUALLY, UNLESS YOU KNOW WHAT YOU ARE DOING !!!! -*******************************************************************************/ +******************************************************************************* + + File info: + File Names: {1}.h; {1}.c + Project File: {2} + File Version: {3} + + Created: {4} + Created By: {5} + Modified: {6} + Modified By: {7} + + Device Info: + Vendor Name: {8} + Vendor ID: {9} + Product Name: {10} + Product ID: {11} + Description: {12} +*******************************************************************************/", + gitVersion, odname, + Path.GetFileName(eds.projectFilename), eds.fi.FileVersion, + eds.fi.CreationDateTime, eds.fi.CreatedBy, eds.fi.ModificationDateTime, eds.fi.ModifiedBy, + eds.di.VendorName, eds.di.VendorNumber, eds.di.ProductName, eds.di.ProductNumber, + eds.fi.Description)); + + file.WriteLine(string.Format(@" #define OD_DEFINITION #include ""301/CO_ODinterface.h"" #include ""{1}.h"" From b995b396894e3191d9b794d3c49d7cb0d5fbff84 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Mon, 10 Mar 2025 16:13:48 +0100 Subject: [PATCH 08/17] Update EDSEditorGUI/Form1.cs Co-authored-by: Lars Elgtvedt Susaas --- EDSEditorGUI/Form1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index c168eb7e..8f017f84 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -468,7 +468,7 @@ private void Eds_onDataDirty(bool dirty, EDSsharp sender) if (d.eds.Dirty == true) { page.BackColor = Color.Tomato; - } + } else { page.BackColor = default(Color); From 760a177ac245737aa4f116437cafd25cedc90ec5 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Mon, 10 Mar 2025 16:14:02 +0100 Subject: [PATCH 09/17] Update EDSEditorGUI/Form1.cs Co-authored-by: Lars Elgtvedt Susaas --- EDSEditorGUI/Form1.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index 8f017f84..16f743b4 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -462,7 +462,7 @@ private void Eds_onDataDirty(bool dirty, EDSsharp sender) { foreach(Control c in page.Controls) { - if (c.GetType() == typeof(DeviceView)) + if(c.GetType() == typeof(DeviceView)) { DeviceView d = (DeviceView)c; if (d.eds.Dirty == true) From 404560582289b14049496b224a83e3b14fae08ca Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 10 Mar 2025 16:21:50 +0100 Subject: [PATCH 10/17] delete old code fragments --- EDSEditorGUI/Form1.cs | 3 --- EDSEditorGUI/Form1.resx | 2 +- 2 files changed, 1 insertion(+), 4 deletions(-) diff --git a/EDSEditorGUI/Form1.cs b/EDSEditorGUI/Form1.cs index c168eb7e..feb390b0 100644 --- a/EDSEditorGUI/Form1.cs +++ b/EDSEditorGUI/Form1.cs @@ -26,9 +26,6 @@ You should have received a copy of the GNU General Public License using System.Windows.Forms; using System.IO; using libEDSsharp; -//using static System.Windows.Forms.VisualStyles.VisualStyleElement; -//using SourceGrid.Cells.Controllers; -//using ToolTip = System.Windows.Forms.ToolTip; namespace ODEditor { diff --git a/EDSEditorGUI/Form1.resx b/EDSEditorGUI/Form1.resx index e9b79be8..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+kH4AMgFyjcd8GS4AAAAJcEhZcwAACwwAAAsMAT9AIsgAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF + HW9+kH4AMgFyjcd8GS4AAAAJcEhZcwAACw4AAAsOAUC+4UEAAAAHdElNRQfkCwILIglO4xvLAAAAD3RF WHRDb21tZW50AENBTm9wZW7cllV1AAAC8UlEQVRYR9WWz2sTQRTHkx6SQy5RxFv1JDGHogiVIkqFEqLE QigetKY3iSUpPYh/gD8uoQiJIEKJ0UNNRZKjTaQiHozePAk21eagCC20NdW1plTa8X3f7mw3cZNuzSr6 hQ+8zn6/M29nZts6/hWdIu4T4xZJE2cJ23QvGAyKRCJhCXgp80CN2qNxTAyVP5QZZVXhn6H5mRlGCl5k From 7937b10037cbea4ce29da6063da8a5e512318df0 Mon Sep 17 00:00:00 2001 From: Charles Hardin Date: Tue, 25 Mar 2025 12:54:42 -0700 Subject: [PATCH 11/17] edssharp: add another extension for the EDS file for CountLabel The count label is required to compile against the CANopenNode v4 library since the definitions are checked by code like the following in CANopen.c #if OD_CNT_NMT != 1 #error OD_CNT_NMT from OD.h not correct! #endif This problem is exhibited when there is no xpd file that has the custom properties and there is only an EDS file available. The StorageLocation is an example of setting the custom property for the CO_storageGroup and this is adding a similar extension for the CO_countLabel. An example eds for NMT 0x1000 is shown below [1000] ParameterName=Device type ObjectType=0x7 ;CountLabel=NMT ;StorageLocation=ROM DataType=0x0007 AccessType=ro DefaultValue=0x00000000 PDOMapping=0 Signed-off-by: Charles Hardin --- libEDSsharp/CanOpenEDS.cs | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/libEDSsharp/CanOpenEDS.cs b/libEDSsharp/CanOpenEDS.cs index d4be60f6..0532d839 100644 --- a/libEDSsharp/CanOpenEDS.cs +++ b/libEDSsharp/CanOpenEDS.cs @@ -387,7 +387,14 @@ public void Write(StreamWriter writer, InfoSection.Filetype ft, Odtype odt = Odt } writer.WriteLine(string.Format("ObjectType=0x{0:X}", (int)objecttype)); - writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); + if (prop.CO_countLabel != "") + { + writer.WriteLine(string.Format(";CountLabel={0}", prop.CO_countLabel)); + } + if (prop.CO_storageGroup != "") + { + writer.WriteLine(string.Format(";StorageLocation={0}", prop.CO_storageGroup)); + } if (objecttype == ObjectType.ARRAY) { @@ -521,9 +528,9 @@ public void Parseline(string linex, int no) } } else - //Only allow our own extensions to populate the key/value pair { - if (key == "StorageLocation" || key == "TPDODetectCos") + //Only allow our own extensions to populate the key/value pair + if (key == "CountLabel" || key == "StorageLocation" || key == "TPDODetectCos") { try { @@ -618,6 +625,11 @@ public void ParseEDSentry(KeyValuePair> kvp) } //Access Type + if (kvp.Value.ContainsKey("CountLabel")) + { + od.prop.CO_countLabel = kvp.Value["CountLabel"]; + } + if (kvp.Value.ContainsKey("StorageLocation")) { od.prop.CO_storageGroup = kvp.Value["StorageLocation"]; From 5a6f7b637eccb704426327e22d6e89a332fb59fc Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Wed, 23 Apr 2025 13:05:35 +0200 Subject: [PATCH 12/17] Bugfix for #181 --- EDSEditorGUI/InsertObjects.cs | 47 +++++++++++++++++++++-------------- 1 file changed, 29 insertions(+), 18 deletions(-) diff --git a/EDSEditorGUI/InsertObjects.cs b/EDSEditorGUI/InsertObjects.cs index 52d7509b..a2919d1a 100644 --- a/EDSEditorGUI/InsertObjects.cs +++ b/EDSEditorGUI/InsertObjects.cs @@ -159,24 +159,29 @@ private bool Verify(bool InitiallyDisableIfError = false) int j = 1; foreach (ODentry od in srcObjects.Values) { - String numpattern = @"(\w*\d+\Z)"; string newname; + string numpattern = @"^(.*?)(\d+)$"; + Regex regex = new Regex(numpattern); + Match match = regex.Match(od.parameter_name); - string[] words = Regex.Split(od.parameter_name, numpattern); - // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); - if (words.Length > 1) + if (match.Success) { + // Extract the string part and the number part + string stringPart = match.Groups[1].Value; + int numberPart = int.Parse(match.Groups[2].Value); - // value1 = Int32.Parse(m.Groups[1].Value); - int nameidx = Int32.Parse(words[1]) + j++; - - newname = words[0] + nameidx;// nameidx.ToString ; + // Increment the number by 1 + numberPart++; + // Reassemble the string with the incremented number + newname = stringPart + numberPart.ToString(); } - else { - newname = od.parameter_name; + else + { + newname = od.parameter_name; } - int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {newname}"); + + int rowIdx = dataGridView.Rows.Add(enabled[odIdx], $"0x{od.Index:X4} - {newname}"); int cellIdx = dataGridView_InitialColumnCount; foreach (int o in offsets) @@ -235,17 +240,23 @@ 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 pattern = @"^(.*?)(\d+)$"; - string[] words = Regex.Split(od.parameter_name, pattern); - // MatchCollection nummatches = System.Text.RegularExpressions.Regex.Matches(od.parameter_name, numpattern); - if (words.Length > 1) + Regex regex = new Regex(pattern); + Match match = regex.Match(od.parameter_name); + + if (match.Success) { - int nameidx = Int32.Parse(words[1]) + i++; - newObject.parameter_name = words[0] + nameidx;// nameidx.ToString ; + // Extract the string part and the number part + string stringPart = match.Groups[1].Value; + int numberPart = int.Parse(match.Groups[2].Value); - } + // Increment the number by 1 + numberPart++; + // Reassemble the string with the incremented number + newObject.parameter_name = stringPart + numberPart.ToString(); + } newObject.Index = newIndex; eds.ods.Add(newIndex, newObject); From 5be27efb985da6904cf0d1ab0dc39b4454808341 Mon Sep 17 00:00:00 2001 From: Dirk Wieschebrock Date: Mon, 17 Nov 2025 14:22:35 +0100 Subject: [PATCH 13/17] Increment number in object name when adding new objects --- EDSEditorGUI/DeviceInfoView.Designer.cs | 30 +- EDSEditorGUI/DeviceInfoView.cs | 3 + EDSEditorGUI/DeviceODView.Designer.cs | 6 +- EDSEditorGUI/DeviceODView.cs | 4 + libEDSsharp/CanOpenNodeExporter.cs | 2 + libEDSsharp/CanOpenNodeExporter_V4.cs | 10 +- libEDSsharp/CanOpenXDD.cs | 2 + libEDSsharp/CanOpenXDD_1_1.cs | 3 + libEDSsharp/DocumentationGenMarkup.cs | 2 +- libEDSsharp/docs/libEDSsharp.xml | 7054 +++++++++++++++++++++++ libEDSsharp/eds.cs | 36 +- 11 files changed, 7139 insertions(+), 13 deletions(-) create mode 100644 libEDSsharp/docs/libEDSsharp.xml diff --git a/EDSEditorGUI/DeviceInfoView.Designer.cs b/EDSEditorGUI/DeviceInfoView.Designer.cs index ce68a85c..507fc7b2 100644 --- a/EDSEditorGUI/DeviceInfoView.Designer.cs +++ b/EDSEditorGUI/DeviceInfoView.Designer.cs @@ -60,6 +60,8 @@ private void InitializeComponent() this.label32 = new System.Windows.Forms.Label(); this.textBox_concretenodeid = new System.Windows.Forms.TextBox(); this.groupBox4 = new System.Windows.Forms.GroupBox(); + this.textBox_revisionnumber = new System.Windows.Forms.TextBox(); + this.label11 = new System.Windows.Forms.Label(); this.textBox_productnumber = new System.Windows.Forms.TextBox(); this.textBox_productname = new System.Windows.Forms.TextBox(); this.textBox_vendornumber = new System.Windows.Forms.TextBox(); @@ -142,7 +144,7 @@ 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(12, 332); + this.groupBox5.Location = new System.Drawing.Point(12, 353); this.groupBox5.Name = "groupBox5"; this.groupBox5.Size = new System.Drawing.Size(377, 182); this.groupBox5.TabIndex = 63; @@ -283,7 +285,7 @@ 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(395, 313); + this.groupBox6.Location = new System.Drawing.Point(395, 333); this.groupBox6.Name = "groupBox6"; this.groupBox6.Size = new System.Drawing.Size(339, 202); this.groupBox6.TabIndex = 5; @@ -414,6 +416,8 @@ private void InitializeComponent() // // groupBox4 // + this.groupBox4.Controls.Add(this.textBox_revisionnumber); + this.groupBox4.Controls.Add(this.label11); this.groupBox4.Controls.Add(this.textBox_productnumber); this.groupBox4.Controls.Add(this.textBox_productname); this.groupBox4.Controls.Add(this.textBox_vendornumber); @@ -424,11 +428,27 @@ private void InitializeComponent() 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.Size = new System.Drawing.Size(377, 147); this.groupBox4.TabIndex = 0; this.groupBox4.TabStop = false; this.groupBox4.Text = "Device Info"; // + // textBox_revisionnumber + // + this.textBox_revisionnumber.Location = new System.Drawing.Point(139, 124); + this.textBox_revisionnumber.Name = "textBox_revisionnumber"; + this.textBox_revisionnumber.Size = new System.Drawing.Size(226, 20); + this.textBox_revisionnumber.TabIndex = 38; + // + // label11 + // + this.label11.AutoSize = true; + this.label11.Location = new System.Drawing.Point(10, 127); + this.label11.Name = "label11"; + this.label11.Size = new System.Drawing.Size(48, 13); + this.label11.TabIndex = 39; + this.label11.Text = "Revision"; + // // textBox_productnumber // this.textBox_productnumber.Location = new System.Drawing.Point(139, 46); @@ -743,7 +763,7 @@ 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(12, 146); + this.groupBox3.Location = new System.Drawing.Point(12, 167); this.groupBox3.Name = "groupBox3"; this.groupBox3.Size = new System.Drawing.Size(377, 180); this.groupBox3.TabIndex = 1; @@ -949,5 +969,7 @@ private void InitializeComponent() 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_revisionnumber; + private System.Windows.Forms.Label label11; } } diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 20ef719d..7c0a1bcb 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -23,6 +23,7 @@ You should have received a copy of the GNU General Public License using System.IO; using System.Runtime.CompilerServices; using System.Drawing; +using System.Linq; namespace ODEditor { @@ -44,6 +45,7 @@ public void populatedeviceinfo() textBox_productnumber.Text = eds.di.ProductNumber; textBox_vendorname.Text = eds.di.VendorName; textBox_vendornumber.Text = eds.di.VendorNumber; + textBox_revisionnumber.Text = eds.di.RevisionNumber; textBox_fileversion.Text = eds.fi.FileVersion; textBox_di_description.Text = eds.fi.Description; @@ -140,6 +142,7 @@ private void update_devfile_info() eds.di.ProductNumber = textBox_productnumber.Text; eds.di.VendorName = textBox_vendorname.Text; eds.di.VendorNumber = textBox_vendornumber.Text; + eds.di.RevisionNumber = textBox_revisionnumber.Text; eds.fi.FileVersion = textBox_fileversion.Text; eds.fi.Description = textBox_di_description.Text; diff --git a/EDSEditorGUI/DeviceODView.Designer.cs b/EDSEditorGUI/DeviceODView.Designer.cs index 11eb304d..7913ddb1 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; @@ -507,6 +507,8 @@ private void InitializeComponent() // // checkBox_autosave // + this.checkBox_autosave.Checked = true; + this.checkBox_autosave.CheckState = System.Windows.Forms.CheckState.Checked; 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); diff --git a/EDSEditorGUI/DeviceODView.cs b/EDSEditorGUI/DeviceODView.cs index acb113da..4e3bba42 100644 --- a/EDSEditorGUI/DeviceODView.cs +++ b/EDSEditorGUI/DeviceODView.cs @@ -220,6 +220,10 @@ public void PopulateObjectLists(EDSsharp eds_target) }); lvi.Tag = od; + if ((index == 0x100C) || (index == 0x100D)) + { + od.prop.CO_disabled = !eds.di.NG_Slave; + } if (selectedObject != null && index == selectedObject.Index) lvi.Selected = true; if (od.prop.CO_disabled == true) diff --git a/libEDSsharp/CanOpenNodeExporter.cs b/libEDSsharp/CanOpenNodeExporter.cs index 78ea78d3..a5369c10 100644 --- a/libEDSsharp/CanOpenNodeExporter.cs +++ b/libEDSsharp/CanOpenNodeExporter.cs @@ -475,6 +475,8 @@ This file was automatically generated by CANopenEditor {0} 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(string.Format(" RevisionNumber: {0}", eds.di.RevisionNumber)); + // file.WriteLine(string.Format(" OrderCode: {0}", eds.di.)); FixMe: Missing OrderCode file.WriteLine("*******************************************************************************/"); file.WriteLine(""); } diff --git a/libEDSsharp/CanOpenNodeExporter_V4.cs b/libEDSsharp/CanOpenNodeExporter_V4.cs index 4b52984f..ca359246 100644 --- a/libEDSsharp/CanOpenNodeExporter_V4.cs +++ b/libEDSsharp/CanOpenNodeExporter_V4.cs @@ -168,6 +168,7 @@ private void Prepare(EDSsharp eds) // 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"); @@ -198,7 +199,10 @@ private void VerifyCountLabel(ODentry od, ushort indexL, ushort indexH, string c { 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); + Warnings.AddWarning($"Error in 0x{od.Index:X4}: missing 'Count Label' '{countLabel}', was added", Warnings.warning_class.WARNING_BUILD); + od.prop.CO_countLabel = countLabel; + + // ToDo Add "dirty" to indicate unsaved changes } } @@ -448,7 +452,7 @@ This file was automatically generated by CANopenEditor {0} gitVersion, odname, Path.GetFileName(eds.projectFilename), eds.fi.FileVersion, eds.fi.CreationDateTime, eds.fi.CreatedBy, eds.fi.ModificationDateTime, eds.fi.ModifiedBy, - eds.di.VendorName, eds.di.VendorNumber, eds.di.ProductName, eds.di.ProductNumber, + eds.di.VendorName, eds.di.VendorNumber, eds.di.ProductName, eds.di.ProductNumber, eds.di.RevisionNumber, eds.fi.Description)); file.WriteLine(string.Format(@" @@ -625,7 +629,7 @@ This file was automatically generated by CANopenEditor {0} gitVersion, odname, Path.GetFileName(eds.projectFilename), eds.fi.FileVersion, eds.fi.CreationDateTime, eds.fi.CreatedBy, eds.fi.ModificationDateTime, eds.fi.ModifiedBy, - eds.di.VendorName, eds.di.VendorNumber, eds.di.ProductName, eds.di.ProductNumber, + eds.di.VendorName, eds.di.VendorNumber, eds.di.ProductName, eds.di.ProductNumber, eds.di.RevisionNumber, eds.fi.Description)); file.WriteLine(string.Format(@" diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index 165036ca..a825b0d2 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -310,6 +310,7 @@ public ISO15745ProfileContainer convert(EDSsharp eds) //device.DeviceIdentity.specificationRevision.value = device.DeviceIdentity.specificationRevision = new specificationRevision(); + device.DeviceIdentity.specificationRevision.Value = eds.di.RevisionNumber; device.DeviceIdentity.specificationRevision.readOnly = true; device.DeviceIdentity.instanceName = new instanceName(); @@ -1160,6 +1161,7 @@ public EDSsharp convert(ISO15745ProfileContainer container) eds.di.ProductNumber = obj.DeviceIdentity.productID.Value; eds.di.VendorName = obj.DeviceIdentity.vendorName.Value; eds.di.VendorNumber = obj.DeviceIdentity.vendorID.Value; + eds.di.RevisionNumber = obj.DeviceIdentity.specificationRevision.Value; foreach (object o in obj.DeviceIdentity.productText.Items) { diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 91a7d659..3a23c89b 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -962,6 +962,7 @@ private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool dev body_device.DeviceIdentity = new DeviceIdentity(); body_device.DeviceIdentity.vendorName = new vendorName { Value = eds.di.VendorName }; body_device.DeviceIdentity.vendorID = new vendorID { Value = eds.di.VendorNumber }; + body_device.DeviceIdentity.specificationRevision = new specificationRevision { Value = eds.di.RevisionNumber }; body_device.DeviceIdentity.productName = new productName { Value = eds.di.ProductName }; body_device.DeviceIdentity.productID = new productID { Value = eds.di.ProductNumber }; if (eds.fi.Description != null && eds.fi.Description != "") @@ -1264,6 +1265,8 @@ private EDSsharp Convert(ISO15745ProfileContainer container) eds.di.VendorName = body_device.DeviceIdentity.vendorName.Value ?? ""; if (body_device.DeviceIdentity.vendorID != null) eds.di.VendorNumber = body_device.DeviceIdentity.vendorID.Value ?? ""; + if (body_device.DeviceIdentity.specificationRevision != null) + eds.di.RevisionNumber = body_device.DeviceIdentity.specificationRevision.Value ?? ""; if (body_device.DeviceIdentity.productName != null) eds.di.ProductName = body_device.DeviceIdentity.productName.Value ?? ""; if (body_device.DeviceIdentity.productID != null) diff --git a/libEDSsharp/DocumentationGenMarkup.cs b/libEDSsharp/DocumentationGenMarkup.cs index 83fc7cd0..1b0d5804 100644 --- a/libEDSsharp/DocumentationGenMarkup.cs +++ b/libEDSsharp/DocumentationGenMarkup.cs @@ -104,7 +104,7 @@ Device Information | 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.VendorName, eds.di.VendorNumber, eds.di.ProductName, eds.di.ProductNumber, eds.di.RevisionNumber, eds.di.Granularity, eds.di.NrOfRXPDO.ToString(), eds.di.NrOfTXPDO.ToString(), eds.di.LSS_Supported, eds.di.LSS_Master, eds.di.NG_Slave, eds.di.NG_Master)); diff --git a/libEDSsharp/docs/libEDSsharp.xml b/libEDSsharp/docs/libEDSsharp.xml new file mode 100644 index 00000000..35b5c105 --- /dev/null +++ b/libEDSsharp/docs/libEDSsharp.xml @@ -0,0 +1,7054 @@ + + + + libEDSsharp + + + + + Section of info in EDS or DCF file + + + + + Write object to stream + + stream to write the data to + file type + + + + Returns a string that represents the current object. + + A string that represents the current object. + + + + Write object to stream + + stream to write the data to + + + + Returns a string that represents the current object. + + A string that represents the current object. + + + + Write object to stream + + stream to write the data to + + + + Returns a string that represents the current object. + + A string that represents the current object. + + + + FileInfo section as described in CiA 306 + + + FileInfo section as described in CiA 306 + + + + + indicate the file name (according to OS restrictions) + + + + + indicate the actual file version (Unsigned8) + + + + + indicate the actual file revision (Unsigned8) + + + + + indicate the version of the specification (3 characters) in the format x.y + + + + + file description (max 243 characters) + + + + + file creation time (characters in format hh:mm(AM|PM)), + + + + + provide the date of file creation (characters in format mm-dd-yyyy) + + + + + name or a description of the file creator (max. 245 characters) + + + + + time of last modification (characters in format hh:mm(AM|PM)) + + + + + date of the last file modification (characters in format mm-dd-yyyy) + + + + + name or a description of the creator (max. 244 characters) + + + + + DeviceInfo section as described in CiA 306 + + + + + vendor name (max. 244 characters) + + + + + unique vendor ID according to identity object sub-index 01h (Unsigned32) + + + + + product name (max. 243 characters) + + + + + product code according to identity object sub-index 02h (Unsigned32) + + + + + product revision number according to identity object sub-index 03h (Unsigned32) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) + + + + + indicate the simple boot-up master functionality (Boolean, 0 = not supported, 1 = supported), + + + + + indicate the simple boot-up slave functionality (Boolean, 0 = not supported, 1 = supported), + + + + + 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) + + + + + Indicate the facility of dynamic variable generation. If the value is unequal to 0, the additional section DynamicChannels exists (CiA302 and CiA405) + + + + + indicate the facility of multiplexed PDOs. (Boolean, 0 = not supported, 1 = supported) + + + + + indicate the number of supported receive PDOs. (Unsigned16) + + + + + indicate the number of supported transmit PDOs. (Unsigned16) + + + + + indicate if LSS functionality is supported (Boolean, 0 = not supported, 1 = supported) + + + + + Represent object dictionary index and subindex objects + + + + + 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 + + + + 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 + + + + + object type var,rec, array etc. + + + + + data type bool, integer etc. + + + + + access type + + + + + default value + + + + + low numeric limit + + + + + high numeric limit + + + + + actual value + + + + + true if it is PDO mapping object + + + + + 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 + + + + 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 bits for the given CANopen datatype of this object, eg the size of what ever the datatype field is set to + + no of bits + + + + This is the no of subindexes present in the object, it is NOT the maximum subobject index + + + + + 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 + + + + Returns true if the object contains a subindex + + the subindex to look for + true if it contains the subindex + + + + Return max indicated subindex, or null if not array or record + + + + + + Subindex of this object if it is a subindex object, 0 if not + + + + + 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 + + + + Add an existing entry as a subobject of this OD + + + + + + + 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 + + + + + File name, when project is opened in xdd_v1.1 or project is saved + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + 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. + + + + 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) + + + + Try to convert a string to UInt16 + + string containing a number + the value or 0 if unable to read it + + + + Try to convert a string to UInt32 + + string containing a number + the value or 0 if unable to read it + + + + 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 + + + + 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 + + + + + Try to get a OD entry + + the index + null if not found + true if found, false if not + + + + Return the number of enabled objects + + Include subindexes in the counting + + + + + Conversion class to/from EDS to protobuffer + + + + + Converts from protobuffer to EDS + + protobuffer device + new EDS device containing data from protobuffer device + + + + Converts from EDS to protobuffer + + EDS device + protobuffer device containing data from EDS + + + + Helper class to convert EDS date and time into datetime used in the protobuffer timestand (datetime) + + + + + Resolver to convert eds date and time into protobuffer timestamp (datetime) + + source EDS fileinfo object + protobuffer fileinfo object + result object + resolve context + result + + + + Helper class to convert object type enum + + Checkout AutoMapper.Extensions.EnumMapping when .net framework is gone + + + + Resolver to convert object types + + EDS object type object + protobuffer object type + result object + resolve context + result + + + + Resolver to convert object types + + EDS object type object + protobuffer object type + result object + resolve context + result + + + + Helper class to convert Access types + + Checkout AutoMapper.Extensions.EnumMapping when .net framework is gone + + + + Resolver to convert eds access into SDO access type + + EDS accesstype + protobuffer sdo access type + result object + resolve context + result + + + + Resolver to convert eds access into PDO access type + + EDS accesstype + protobuffer pdo access type + result object + resolve context + result + + + + Resolver to convert SDO access type into eds access into + + protobuffer sdo access type + EDS accesstype + result object + resolve context + result + + + + + Export .c and .h files for CanOpenNode v1-3 + + + + + The eds file set when calling export + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + Register names of index and subindex that need to have standard names to be able to work with CanOpenNode + + + + + 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 + the eds data to be exported + + + + 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 + + + + + + + + + + + Returns true of object is not disabled + + index to check + true if index object is not disabled + + + + Return the header part of one object dictionary entry + + the OD entry + part of the C header file that impliments the od entry + + + + Returns the c code related to a single object dictionary entry + + the OD entry + string containing c code for the OD entry + + + + 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 + + + + 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 + + + + + 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 + + + + Exporter for CanOpenNode_V4 + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + 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 + + + + + Generate ODStorage, ODObjs, ODList, ODDefines and ODCnt entries + + EDS object + + + + 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 + + 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 + + + + 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 + + + + 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 + + + + + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + Convert to/from EDSsharp and CanOpenXDD v1.1, it uses the generated source file CanOpenXSD_1_1 + + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + 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 + If true, device commisioning, denotations and actual values will be included + + + + Write XDD file from EDSsharp object + + Name of the xdd file + EDSsharp object + 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 + + + + Read protobuffer file into EDSsharp object + + Name of the protobuffer file + read as JSON string or binary wireformat + EDSsharp object + + + + Write protobuffer file from EDSsharp object + + Name of the protobuffer file + EDSsharp object + write as JSON string or binary wireformat + + + + Documentation generator + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + Generate html documentation + + where the documentation should be saved + data to generate the documentation from + + + + Write a object dictionary html entry to file + + Object dictionary entry + + + + Write a html table row with 2 elements to file + + element a + element b + + + + Write a html table header with 2 elements to file + + + + + + + Returns the datatype of a object dictionary + + the object dictionary entry + datatype of the OD entry + + + + Documentation generator + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + Generate markup documentation + + where the documentation should be created + data to generate the documentation from + + + + Write a all PDO information in markup + + data containing the information + skip disabled PDOs + + + + Write a object dictionary markup entry to file + + Object dictionary entry + + + + Returns the datatype of a object dictionary + + the object dictionary entry + datatype of the OD entry + + + + Object dictionary data types from CiA 301 + + + + + Object Dictionary object definitions from CiA 301 + + + + + An object with no data fields + + + + + Large variable amount of data e.g. executable program code + + + + + Denotes a type definition such as a BOOLEAN, UNSIGNED16, FLOAT and so on + + + + + Defines a new record type e.g. the PDO mapping structure at 21h + + + + + A single value such as an UNSIGNED8, BOOLEAN, FLOAT, INTEGER16, VISIBLE STRING etc. + + + + + 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 + + + + + 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 + + + + + Defines how the object can be changed from SDO + + + + + no access + + + + + read only access + + + + + write only access + + + + + read and write access + + + + + Defines how the object can be changed from PDO + + + + + no access + + + + + TPDO access + + + + + RPDO access + + + + + TPDO and RPDO access + + + + + Custom properties for OD entry or sub-entry, which are saved into xdd file v1.1 + + + + + If true, object is completelly skipped by CANopenNode exporters, etc. + + + + + CanOpenNode storage group + + + + + Minimum length of a string that can be stored + + + + + Deep clone + + a deep clone + + + + Convert from XSD to EDS + + raw custom properties from XSD + + + + Convert custom properties from EDS to XSD + + XSD properties ready to use + + + + List of multiple CO_storageGroup strings available in project + + + + + Indicate that it should be exported in EDS files and may have some data about how + + + + + Max length of the string when exported + + + + + default constructor + + + + + contstructor with max string length + + max length of the string when exported + + + + Indicate that it should be exported in DCF files + + + + + Factory for making different canopennode exporter + + + + + CanOpenNode exporter types + + + + + CanOpenNode exporter v4 (latest) + + + + + CanOpenNode exporter for v1-3 (legacy) + + + + + Returns exporter based on ex parameter + + what exporter version you want. Default is CANOPENNODE_LEGACY + A exporter + + + + Helper functions to convert integral values into hexadecimal string + + + + + returns a string containing the value as hexadecimal + + the value + hexadecimal string representing the value + + + + returns a string containing the value as hexadecimal + + the value + hexadecimal string representing the value + + + + returns a string containing the value as hexadecimal + + the value + hexadecimal string representing the value + + + + String extension methodes + + + + + 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 + + + + + Unified interface to all filetypes supported by the library + + + + + 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 + + + + Interface for exporting CanOpenNode OD files + + + + + Export file(s) + + filepath, .c and .h will be added to this to make the mulitiple files + The eds that will be exported + + + + Includes all info about a exporter that is needed to show user and call it + + + + + 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 + + + + True if exporter will expect multiple edss + + + + + Documentation related + + + + + CanOpenNode related + + + + + 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 + + + + + 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 + + + + Interface for exporters + + + + + Fetches all the different fileexporter types the class supports + + List of the different exporters the class supports + + + + Generate a PDO network report + + + + + Generate a PDO network report + + where the doc should be saved + Data from the different nodes in the network + + + + Write a html table row with 2 elements to file + + element a + element b + + + + Write a html table header with 2 elements to file + + + + + + + Represent a PDO slot (mapping + communication index) + + + + + Indicate that $NODEID is present and the COB-ID should added to the node id when deployed + + + + + The OD index of the PDO configuration (aka. communication parameter) + + + + + The OD index of the PDO mapping + + + + + PDO Mapping access + + + + + PDO Configuration (aka. communication parameter) access + + + + + PDO mapping CanOpenNode storage group + + + + + PDO config CanOpenNode storage group + + + + + PDO COB-ID + + + + + Returns if true the PDO is a TxPDO (aka TPDO) + + true if TXPDO + + + + Returns if true the PDO is a RxPDO (aka RPDO) + + true if RxPDO + + + + PDO invalid bit value + + + + + PDO mapping + + + + + PDO inhibit time,multiple of 100us + + + + + PDO event time,multiple of 1ms + + + + + PDO sync start value + + + + + PDO transmission type + + + + + Description of PDO communication index (aka configuration) + + + + + Description of PDO mapping index + + + + + default constructor + + + + + 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 + + + + Insert a OD entry into the mapping table + + The zero-based index at which item should be inserted + OD entry to be mapped + + + + PDO helper class, control all TPDO and RPDO in a node + + + + + Constructor + + eds data to interact with + + + + List of all T/R PDO + + + + + Why is this not called from constructor? + + + + + 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 + + + + 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. + + + + + Provides string escape and unescape functions + + + + + 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 + + + + Logger class used to report problems with import/export + + + + + type of warnings + + + + + Generic warning + + + + + index/subindex rename warnings + + + + + problem with index/subindexes that are needed to make canopennode functions work + + + + + Problem with strings variable export + + + + + Problem with struct/record export + + + + + List of warnings + + + + + bit mask used to stop messages being added to the list + + + + + Add warning to the list of warnings + + string to report + type of warning (filter usage) + + + + XDD version + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Holder for reflection information generated from CanOpen.proto + + + File descriptor for CanOpen.proto + + + + File information related properties. + + + + Field number for the "fileVersion" field. + + + + Actual file version (as string). + + + + Field number for the "description" field. + + + + File description. + + + + Field number for the "creationTime" field. + + + + File creation time. + + + + Field number for the "createdBy" field. + + + + Name or a description of the file creator. + + + + Field number for the "modificationTime" field. + + + + Time of the last modification. + + + + Field number for the "modifiedBy" field. + + + + Name or a description of the creator. + + + + + CANopen device information related properties. + + + + Field number for the "vendorName" field. + + + + Vendor name. + + + + Field number for the "productName" field. + + + + Product name. + + + + Field number for the "baudRate10" field. + + + + Support of the baud rate 10 kbit/s. + + + + Field number for the "baudRate20" field. + + + + Support of the baud rate 20 kbit/s. + + + + Field number for the "baudRate50" field. + + + + Support of the baud rate 50 kbit/s. + + + + Field number for the "baudRate125" field. + + + + Support of the baud rate 125 kbit/s. + + + + Field number for the "baudRate250" field. + + + + Support of the baud rate 250 kbit/s. + + + + Field number for the "baudRate500" field. + + + + Support of the baud rate 500 kbit/s. + + + + Field number for the "baudRate800" field. + + + + Support of the baud rate 800 kbit/s. + + + + Field number for the "baudRate1000" field. + + + + Support of the baud rate 1000 kbit/s. + + + + Field number for the "baudRateAuto" field. + + + + Support of the auto baud rate. + + + + Field number for the "lssSlave" field. + + + + Support of the LSS slave functionality. + + + + Field number for the "lssMaster" field. + + + + Support of the LSS master functionality. + + + + + Actual CANopen device properties. + + + + Field number for the "nodeId" field. + + + + CANopen device’s address. + + + + Field number for the "nodeName" field. + + + + Node name. + + + + Field number for the "baudrate" field. + + + + 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. + + + + Field number for the "name" field. + + + + Name of the sub entry. If OdEntry is "VAR", this property is not relevant. + + + + Field number for the "alias" field. + + + + Additonal sub parameter name, for the actual device. If OdEntry is "VAR", this property is not relevant. + + + + Field number for the "dataType" field. + + + + CANopen data type + + + + Field number for the "sdo" field. + + + + CANopen SDO access permissions + + + + Field number for the "pdo" field. + + + + CANopen PDO access permissions + + + + Field number for the "srdo" field. + + + + CANopen SRDO access permissions. + + + + Field number for the "defaultValue" field. + + + + Default value of the sub object. + + + + Field number for the "actualValue" field. + + + + Actual value of the sub object, for the actual device. + + + + Field number for the "lowLimit" field. + + + + Low limit for the value. + + + + Field number for the "highLimit" field. + + + + High limit for the value. + + + + Field number for the "stringLengthMin" field. + + + + CanOpenNode OD exporter V4: Minimum length of a string that can be stored. + + + + Container for nested types declared in the OdSubObject message type. + + + + Object dictionary basic data types from CiA 301. + + + + + Unspecified, should not be used. + + + + + Boolean. + + + + + 8-bit signed integer. + + + + + 16-bit signed integer. + + + + + 32-bit signed integer. + + + + + 8-bit unsigned integer. + + + + + 16-bit unsigned integer. + + + + + 32-bit unsigned integer. + + + + + 32-bit floating point number. + + + + + Null terminated string (8-bit chars). It may contain control characters and UTF-8 + characters. StringLengthMin specifies minimum buffer length for the string. + + + + + Fixed length array of bytes. + + + + + Null terminated string (16-bit chars). Not recommended to use. + StringLengthMin specifies minimum buffer length for the string. + + + + + 48 bit long structure. + + + + + 48 bit long structure. + + + + + Data block of any length, don't have default value. + + + + + 24-bit signed integer, should not be used. + + + + + 64-bit floating point number. + + + + + 40-bit signed integer, should not be used. + + + + + 48-bit signed integer, should not be used. + + + + + 56-bit signed integer, should not be used. + + + + + 64-bit signed integer. + + + + + 24-bit unsigned integer, should not be used. + + + + + 40-bit unsigned integer, should not be used. + + + + + 48-bit unsigned integer, should not be used. + + + + + 56-bit unsigned integer, should not be used. + + + + + 64-bit unsigned integer. + + + + + CANopen SDO access permissions. + + + + + No access. + + + + + Read only access. + + + + + Write only access. + + + + + Read and write access. + + + + + CANopen PDO access permissions. + + + + + No access. + + + + + TPDO access. + + + + + RPDO access. + + + + + TPDO and RPDO access. + + + + + CANopen SRDO access permissions. + + + + + no access. + + + + + SRDO TX access. + + + + + SRDO RX access. + + + + + SRDO TX or RX access. + + + + + Object Dictionary Entry on specific Index. Sorted dictionary of them is part of CanOpenDevice - CANopen Object Dictionary. + + + + Field number for the "disabled" field. + + + + If true, object is completelly skipped by CANopenNode exporters, etc. + + + + Field number for the "name" field. + + + + Name of the entry. + + + + Field number for the "alias" field. + + + + Additonal parameter name, for the actual device. + + + + Field number for the "description" field. + + + + Description of the Entry. + + + + Field number for the "objectType" field. + + + + CANopen Object Type. + + + + Field number for the "countLabel" field. + + + + 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. + + + + Field number for the "storageGroup" field. + + + + CanOpenNode OD exporter V4: storage group into which the C variable will belong. If not defined, it will default to "RAM". + + + + Field number for the "flagsPDO" field. + + + + CanOpenNode OD exporter V1.3: Flags for the PDO. + + + + Field number for the "subObjects" field. + + + + Sorted dictionary of sub entries + + + + Container for nested types declared in the OdObject message type. + + + + Type of Object Dictionary entry, similar as Object Code from CiA 301. + + + + + Not defined, default + + + + + A single value such as an UNSIGNED8, BOOLEAN, FLOAT, INTEGER16, VISIBLE STRING etc. + + + + + 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. + + + + + 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. + + + + + CANopen Device description object. + + + + Field number for the "fileInfo" field. + + + + File information related properties. + + + + Field number for the "deviceInfo" field. + + + + CANopen device information related properties. + + + + Field number for the "deviceCommissioning" field. + + + + Parameters of the actual CANopen device. + + + + Field number for the "objects" field. + + + + CANopen Object Dictionary as sorted dictionary. + + + + diff --git a/libEDSsharp/eds.cs b/libEDSsharp/eds.cs index 0530d652..d6febc6b 100644 --- a/libEDSsharp/eds.cs +++ b/libEDSsharp/eds.cs @@ -679,7 +679,7 @@ public partial class DeviceInfo : InfoSection /// product revision number according to identity object sub-index 03h (Unsigned32) /// [EdsExport] - public UInt32 RevisionNumber; + public string RevisionNumber; /// /// indicate the supported baud rates (Boolean, 0 = not supported, 1=supported) @@ -1282,6 +1282,30 @@ public void AccessPDO(AccessPDO accessPDO) } } + + + 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 /// @@ -1325,10 +1349,11 @@ public ODentry AddSubEntry() } else { - originalOd = (parent != null && this.Subindex > 0) ? this : lastSubOd; + lastSubIndex = lastSubOd.Subindex; + originalOd = (parent != null && this.Subindex > 0 && this.Subindex+1 != lastSubIndex) ? this : lastSubOd; newOd = originalOd.Clone(originalOd.parent); maxSubIndex = EDSsharp.ConvertToUInt16(baseObject.subobjects[0].defaultvalue); - lastSubIndex = lastSubOd.Subindex; + } // insert new sub od @@ -1342,7 +1367,12 @@ public ODentry AddSubEntry() newSubObjects.Add(newSubIndex++, subOd); if (originalOd == subOd) + { + if(subOd.Subindex == (newSubIndex-1)) // if new subindex is the last one and parmeter name ends with number: increment number + newOd.parameter_name = IncrementNumberAtEnd(newOd.parameter_name,1); newSubObjects.Add(newSubIndex++, newOd); + + } } if (originalOd == null) newSubObjects.Add(newSubIndex++, newOd); From 062ffcc8ab2983bd9484ca51c405781a70121e64 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Tue, 25 Nov 2025 12:21:53 +0100 Subject: [PATCH 14/17] 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 e29e2a1b20ae2901e48e66a7401e6a71b7caa250 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Thu, 27 Nov 2025 15:44:14 +0100 Subject: [PATCH 15/17] Updates nuget extensions --- EDSEditorGUI/DeviceInfoView.cs | 4 ++-- EDSEditorGUI/EDSEditorGUI.csproj | 2 +- EDSEditorGUI2/EDSEditorGUI2.csproj | 16 ++++++++-------- GUITests/GUITests.csproj | 14 ++++++++++---- Tests/Tests.csproj | 19 +++++++++++-------- libEDSsharp/CanOpenEDSMapping.cs | 1 - libEDSsharp/CanOpenXDD.cs | 4 ++-- libEDSsharp/CanOpenXDD_1_1.cs | 4 ++-- libEDSsharp/libEDSsharp.csproj | 8 ++++---- 9 files changed, 40 insertions(+), 32 deletions(-) diff --git a/EDSEditorGUI/DeviceInfoView.cs b/EDSEditorGUI/DeviceInfoView.cs index 7c0a1bcb..7641f07d 100644 --- a/EDSEditorGUI/DeviceInfoView.cs +++ b/EDSEditorGUI/DeviceInfoView.cs @@ -45,7 +45,7 @@ public void populatedeviceinfo() textBox_productnumber.Text = eds.di.ProductNumber; textBox_vendorname.Text = eds.di.VendorName; textBox_vendornumber.Text = eds.di.VendorNumber; - textBox_revisionnumber.Text = eds.di.RevisionNumber; + textBox_revisionnumber.Text = eds.di.RevisionNumber.ToString(); textBox_fileversion.Text = eds.fi.FileVersion; textBox_di_description.Text = eds.fi.Description; @@ -142,7 +142,7 @@ private void update_devfile_info() eds.di.ProductNumber = textBox_productnumber.Text; eds.di.VendorName = textBox_vendorname.Text; eds.di.VendorNumber = textBox_vendornumber.Text; - eds.di.RevisionNumber = textBox_revisionnumber.Text; + uint.TryParse(textBox_revisionnumber.Text, out eds.di.RevisionNumber); eds.fi.FileVersion = textBox_fileversion.Text; eds.fi.Description = textBox_di_description.Text; diff --git a/EDSEditorGUI/EDSEditorGUI.csproj b/EDSEditorGUI/EDSEditorGUI.csproj index 031e286d..9da7a956 100644 --- a/EDSEditorGUI/EDSEditorGUI.csproj +++ b/EDSEditorGUI/EDSEditorGUI.csproj @@ -100,7 +100,7 @@ - + diff --git a/EDSEditorGUI2/EDSEditorGUI2.csproj b/EDSEditorGUI2/EDSEditorGUI2.csproj index ab887d37..0ad22a6d 100644 --- a/EDSEditorGUI2/EDSEditorGUI2.csproj +++ b/EDSEditorGUI2/EDSEditorGUI2.csproj @@ -15,16 +15,16 @@ - - - - + + + + - + - - - + + + diff --git a/GUITests/GUITests.csproj b/GUITests/GUITests.csproj index 499faeae..30130d0e 100644 --- a/GUITests/GUITests.csproj +++ b/GUITests/GUITests.csproj @@ -9,10 +9,16 @@ - - - - + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + diff --git a/Tests/Tests.csproj b/Tests/Tests.csproj index 5fa46514..d8b94f2b 100644 --- a/Tests/Tests.csproj +++ b/Tests/Tests.csproj @@ -1,4 +1,4 @@ - + net481 net8.0 @@ -11,7 +11,7 @@ - + @@ -21,15 +21,18 @@ - - - - - + + + all runtime; build; native; contentfiles; analyzers; buildtransitive - + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/libEDSsharp/CanOpenEDSMapping.cs b/libEDSsharp/CanOpenEDSMapping.cs index ce980ef3..8eef7c87 100644 --- a/libEDSsharp/CanOpenEDSMapping.cs +++ b/libEDSsharp/CanOpenEDSMapping.cs @@ -406,7 +406,6 @@ public OdSubObject.Types.AccessSDO Convert(EDSsharp.AccessType source, OdSubObje /// /// EDS accesstype /// protobuffer pdo access type - /// result object /// resolve context /// result public OdSubObject.Types.AccessPDO Convert(EDSsharp.AccessType source, OdSubObject.Types.AccessPDO destination, ResolutionContext context) diff --git a/libEDSsharp/CanOpenXDD.cs b/libEDSsharp/CanOpenXDD.cs index a825b0d2..96a515fc 100644 --- a/libEDSsharp/CanOpenXDD.cs +++ b/libEDSsharp/CanOpenXDD.cs @@ -310,7 +310,7 @@ public ISO15745ProfileContainer convert(EDSsharp eds) //device.DeviceIdentity.specificationRevision.value = device.DeviceIdentity.specificationRevision = new specificationRevision(); - device.DeviceIdentity.specificationRevision.Value = eds.di.RevisionNumber; + device.DeviceIdentity.specificationRevision.Value = eds.di.RevisionNumber.ToHexString(); device.DeviceIdentity.specificationRevision.readOnly = true; device.DeviceIdentity.instanceName = new instanceName(); @@ -1161,7 +1161,7 @@ public EDSsharp convert(ISO15745ProfileContainer container) eds.di.ProductNumber = obj.DeviceIdentity.productID.Value; eds.di.VendorName = obj.DeviceIdentity.vendorName.Value; eds.di.VendorNumber = obj.DeviceIdentity.vendorID.Value; - eds.di.RevisionNumber = obj.DeviceIdentity.specificationRevision.Value; + uint.TryParse(obj.DeviceIdentity.specificationRevision.Value, out eds.di.RevisionNumber); foreach (object o in obj.DeviceIdentity.productText.Items) { diff --git a/libEDSsharp/CanOpenXDD_1_1.cs b/libEDSsharp/CanOpenXDD_1_1.cs index 3a23c89b..ac8e3df6 100644 --- a/libEDSsharp/CanOpenXDD_1_1.cs +++ b/libEDSsharp/CanOpenXDD_1_1.cs @@ -962,7 +962,7 @@ private ISO15745ProfileContainer Convert(EDSsharp eds, string fileName, bool dev body_device.DeviceIdentity = new DeviceIdentity(); body_device.DeviceIdentity.vendorName = new vendorName { Value = eds.di.VendorName }; body_device.DeviceIdentity.vendorID = new vendorID { Value = eds.di.VendorNumber }; - body_device.DeviceIdentity.specificationRevision = new specificationRevision { Value = eds.di.RevisionNumber }; + body_device.DeviceIdentity.specificationRevision = new specificationRevision { Value = eds.di.RevisionNumber.ToHexString()}; body_device.DeviceIdentity.productName = new productName { Value = eds.di.ProductName }; body_device.DeviceIdentity.productID = new productID { Value = eds.di.ProductNumber }; if (eds.fi.Description != null && eds.fi.Description != "") @@ -1266,7 +1266,7 @@ private EDSsharp Convert(ISO15745ProfileContainer container) if (body_device.DeviceIdentity.vendorID != null) eds.di.VendorNumber = body_device.DeviceIdentity.vendorID.Value ?? ""; if (body_device.DeviceIdentity.specificationRevision != null) - eds.di.RevisionNumber = body_device.DeviceIdentity.specificationRevision.Value ?? ""; + uint.TryParse(body_device.DeviceIdentity.specificationRevision.Value , out eds.di.RevisionNumber) ; if (body_device.DeviceIdentity.productName != null) eds.di.ProductName = body_device.DeviceIdentity.productName.Value ?? ""; if (body_device.DeviceIdentity.productID != null) diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 3e443832..04edf6ee 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -18,7 +18,7 @@ - + @@ -44,9 +44,9 @@ - - - + + + From 7a2de63a446b16f35dffa7d8b4028544de803f03 Mon Sep 17 00:00:00 2001 From: trojanobelix Date: Fri, 28 Nov 2025 07:39:28 +0100 Subject: [PATCH 16/17] 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 17/17] 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)) {