diff --git a/Tests/EDSMappingTests.cs b/Tests/EDSMappingTests.cs new file mode 100644 index 0000000..e03f3df --- /dev/null +++ b/Tests/EDSMappingTests.cs @@ -0,0 +1,618 @@ +using Google.Protobuf.WellKnownTypes; +using LibCanOpen; +using libEDSsharp; +using System; +using System.Globalization; +using Xunit; + +namespace Tests +{ + public class EDSMappingTests + { + [Fact] + public void Test_ToProtobufferAssertConfig() + { + var eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + var od = new ODentry + { + objecttype = ObjectType.VAR, + parameter_name = "Test REC", + Index = 0x2000 + }; + + var sub = new ODentry + { + parameter_name = "some value", + datatype = DataType.UNSIGNED8, + parent = od, + accesstype = EDSsharp.AccessType.ro, + defaultvalue = "1", + PDOtype = PDOMappingType.no, + objecttype = ObjectType.VAR + }; + + od.subobjects.Add(0x00, sub); + eds.ods.Add(0x2000, od); + + //Assert is called inside the map function + MappingEDS.MapToProtobuffer(eds); + } + [Fact] + public void Test_ToProtobufferFileInfo() + { + var eds = new EDSsharp + { + fi = new FileInfo + { + CreatedBy = "CreatedBy", + CreationDate = "01-20-2000", + CreationTime = "12:20am", + Description = "Description", + FileRevision = (byte)'A', + FileVersion = "1.0.0", + ModificationDate = "02-10-1000", + ModificationTime = "12:20pm", + ModifiedBy = "ModifiedBy" + } + }; + + var creationDateTime = DateTime.ParseExact($"{eds.fi.CreationTime} {eds.fi.CreationDate}", "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + var modificationDateTime = DateTime.ParseExact($"{eds.fi.ModificationTime} {eds.fi.ModificationDate}", "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + var creationTimestamp = Timestamp.FromDateTime(creationDateTime.ToUniversalTime()); + var modificationTimestamp = Timestamp.FromDateTime(modificationDateTime.ToUniversalTime()); + + var tmp = MappingEDS.MapToProtobuffer(eds); + Assert.Equal(eds.fi.CreatedBy, tmp.FileInfo.CreatedBy); + Assert.Equal(creationTimestamp, tmp.FileInfo.CreationTime); + Assert.Equal(eds.fi.Description, tmp.FileInfo.Description); + Assert.Equal(eds.fi.FileVersion, tmp.FileInfo.FileVersion); + Assert.Equal(eds.fi.ModifiedBy, tmp.FileInfo.ModifiedBy); + Assert.Equal(modificationTimestamp, tmp.FileInfo.ModificationTime); + } + [Fact] + public void Test_ToProtobufferDeviceInfo() + { + var eds = new EDSsharp + { + di = new DeviceInfo + { + BaudRate_10 = true, + BaudRate_20 = false, + BaudRate_50 = true, + BaudRate_125 = false, + BaudRate_250 = true, + BaudRate_500 = false, + BaudRate_800 = true, + BaudRate_1000 = false, + BaudRate_auto = true, + LSS_Master = false, + LSS_Supported = true, + VendorName = "VendorName", + ProductName = "ProductName" + } + }; + + var tmp = MappingEDS.MapToProtobuffer(eds); + Assert.Equal(eds.di.BaudRate_10, tmp.DeviceInfo.BaudRate10); + Assert.Equal(eds.di.BaudRate_20, tmp.DeviceInfo.BaudRate20); + Assert.Equal(eds.di.BaudRate_50, tmp.DeviceInfo.BaudRate50); + Assert.Equal(eds.di.BaudRate_125, tmp.DeviceInfo.BaudRate125); + Assert.Equal(eds.di.BaudRate_250, tmp.DeviceInfo.BaudRate250); + Assert.Equal(eds.di.BaudRate_500, tmp.DeviceInfo.BaudRate500); + Assert.Equal(eds.di.BaudRate_800, tmp.DeviceInfo.BaudRate800); + Assert.Equal(eds.di.BaudRate_1000, tmp.DeviceInfo.BaudRate1000); + Assert.Equal(eds.di.BaudRate_auto, tmp.DeviceInfo.BaudRateAuto); + Assert.Equal(eds.di.LSS_Master, tmp.DeviceInfo.LssMaster); + Assert.Equal(eds.di.LSS_Supported, tmp.DeviceInfo.LssSlave); + Assert.Equal(eds.di.VendorName, tmp.DeviceInfo.VendorName); + Assert.Equal(eds.di.ProductName, tmp.DeviceInfo.ProductName); + } + [Fact] + public void Test_ToProtobufferDeviceCommissioning() + { + var eds = new EDSsharp + { + dc = new DeviceCommissioning + { + NodeID = 123, + NodeName = "NodeName", + Baudrate = 456, + } + }; + + var tmp = MappingEDS.MapToProtobuffer(eds); + Assert.Equal(eds.dc.NodeID, tmp.DeviceCommissioning.NodeId); + Assert.Equal(eds.dc.NodeName, tmp.DeviceCommissioning.NodeName); + Assert.Equal(eds.dc.Baudrate, tmp.DeviceCommissioning.Baudrate); + } + [Theory] + [InlineData(OdObject.Types.ObjectType.Array, ObjectType.ARRAY)] + [InlineData(OdObject.Types.ObjectType.Record, ObjectType.RECORD)] + [InlineData(OdObject.Types.ObjectType.Var, ObjectType.VAR)] + [InlineData(OdObject.Types.ObjectType.Unspecified, ObjectType.DEFSTRUCT)] + [InlineData(OdObject.Types.ObjectType.Unspecified, ObjectType.DEFTYPE)] + [InlineData(OdObject.Types.ObjectType.Unspecified, ObjectType.DOMAIN)] + [InlineData(OdObject.Types.ObjectType.Unspecified, ObjectType.NULL)] + [InlineData(OdObject.Types.ObjectType.Unspecified, ObjectType.UNKNOWN)] + public void Test_ToProtobufferODObject(OdObject.Types.ObjectType objTypeProto, ObjectType objTypeEDS) + { + var eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + var od = new ODentry + { + objecttype = objTypeEDS, + parameter_name = "parameter name", + Index = 0x2000 + }; + eds.ods.Add(od.Index, od); + var tmp = MappingEDS.MapToProtobuffer(eds); + Assert.Equal(objTypeProto, tmp.Objects[od.Index.ToString()].ObjectType); + } + + [Theory] + [InlineData(OdSubObject.Types.DataType.Unspecified, DataType.UNKNOWN)] + [InlineData(OdSubObject.Types.DataType.Boolean, DataType.BOOLEAN)] + [InlineData(OdSubObject.Types.DataType.Integer8, DataType.INTEGER8)] + [InlineData(OdSubObject.Types.DataType.Integer16, DataType.INTEGER16)] + [InlineData(OdSubObject.Types.DataType.Integer32, DataType.INTEGER32)] + [InlineData(OdSubObject.Types.DataType.Unsigned8, DataType.UNSIGNED8)] + [InlineData(OdSubObject.Types.DataType.Unsigned16, DataType.UNSIGNED16)] + [InlineData(OdSubObject.Types.DataType.Unsigned32, DataType.UNSIGNED32)] + [InlineData(OdSubObject.Types.DataType.Real32, DataType.REAL32)] + [InlineData(OdSubObject.Types.DataType.VisibleString, DataType.VISIBLE_STRING)] + [InlineData(OdSubObject.Types.DataType.OctetString, DataType.OCTET_STRING)] + [InlineData(OdSubObject.Types.DataType.UnicodeString, DataType.UNICODE_STRING)] + [InlineData(OdSubObject.Types.DataType.TimeOfDay, DataType.TIME_OF_DAY)] + [InlineData(OdSubObject.Types.DataType.TimeDifference, DataType.TIME_DIFFERENCE)] + [InlineData(OdSubObject.Types.DataType.Domain, DataType.DOMAIN)] + [InlineData(OdSubObject.Types.DataType.Integer24, DataType.INTEGER24)] + [InlineData(OdSubObject.Types.DataType.Real64, DataType.REAL64)] + [InlineData(OdSubObject.Types.DataType.Integer40, DataType.INTEGER40)] + [InlineData(OdSubObject.Types.DataType.Integer48, DataType.INTEGER48)] + [InlineData(OdSubObject.Types.DataType.Integer56, DataType.INTEGER56)] + [InlineData(OdSubObject.Types.DataType.Integer64, DataType.INTEGER64)] + [InlineData(OdSubObject.Types.DataType.Unsigned24, DataType.UNSIGNED24)] + [InlineData(OdSubObject.Types.DataType.Unsigned40, DataType.UNSIGNED40)] + [InlineData(OdSubObject.Types.DataType.Unsigned48, DataType.UNSIGNED48)] + [InlineData(OdSubObject.Types.DataType.Unsigned56, DataType.UNSIGNED56)] + [InlineData(OdSubObject.Types.DataType.Unsigned64, DataType.UNSIGNED64)] + public void Test_ToProtobufferSubODObjectDatatype(OdSubObject.Types.DataType datatypeProto, DataType datatypeEDS) + { + var eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + var od = new ODentry + { + objecttype = ObjectType.RECORD, + Index = 0x2000 + }; + var sub = new ODentry + { + datatype = datatypeEDS, + parent = od, + }; + + od.subobjects.Add(0x00, sub); + eds.ods.Add(od.Index, od); + var tmp = MappingEDS.MapToProtobuffer(eds); + Assert.Equal(datatypeProto, tmp.Objects[od.Index.ToString()].SubObjects["0"].DataType); + } + + [Theory] + [InlineData(OdSubObject.Types.AccessPDO.Tr, OdSubObject.Types.AccessSDO.Rw, EDSsharp.AccessType.rw)] + [InlineData(OdSubObject.Types.AccessPDO.No, OdSubObject.Types.AccessSDO.Ro, EDSsharp.AccessType.ro)] + [InlineData(OdSubObject.Types.AccessPDO.No, OdSubObject.Types.AccessSDO.Wo, EDSsharp.AccessType.wo)] + [InlineData(OdSubObject.Types.AccessPDO.T, OdSubObject.Types.AccessSDO.Rw, EDSsharp.AccessType.rwr)] + [InlineData(OdSubObject.Types.AccessPDO.R, OdSubObject.Types.AccessSDO.Rw, EDSsharp.AccessType.rww)] + [InlineData(OdSubObject.Types.AccessPDO.R, OdSubObject.Types.AccessSDO.Ro, EDSsharp.AccessType.@const)] + [InlineData(OdSubObject.Types.AccessPDO.No, OdSubObject.Types.AccessSDO.No, EDSsharp.AccessType.UNKNOWN)] + public void Test_ToProtobufferSubODObjectAccesstype(OdSubObject.Types.AccessPDO accessPDOProto, OdSubObject.Types.AccessSDO accessSDOProto, EDSsharp.AccessType datatypeEDS) + { + var eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + var od = new ODentry + { + objecttype = ObjectType.RECORD, + Index = 0x2000 + }; + var sub = new ODentry + { + parent = od, + accesstype = datatypeEDS, + PDOtype = PDOMappingType.no, + }; + + od.subobjects.Add(0x00, sub); + eds.ods.Add(od.Index, od); + var tmp = MappingEDS.MapToProtobuffer(eds); + Assert.Equal(accessPDOProto, tmp.Objects[od.Index.ToString()].SubObjects["0"].Pdo); + Assert.Equal(accessSDOProto, tmp.Objects[od.Index.ToString()].SubObjects["0"].Sdo); + } + [Fact] + public void Test_ToProtobufferSubODObjectMembers() + { + var eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + var od = new ODentry + { + objecttype = ObjectType.RECORD, + Index = 0x2000 + }; + var sub = new ODentry + { + parent = od, + actualvalue = "123", + parameter_name = "parameter_name", + HighLimit = "HighLimit", + LowLimit = "LowLimit", + defaultvalue = "defaultvalue", + }; + + od.subobjects.Add(0x00, sub); + eds.ods.Add(od.Index, od); + var tmp = MappingEDS.MapToProtobuffer(eds); + Assert.Equal(sub.actualvalue, tmp.Objects[od.Index.ToString()].SubObjects["0"].ActualValue); + Assert.Equal(sub.parameter_name, tmp.Objects[od.Index.ToString()].SubObjects["0"].Name); + Assert.Equal(sub.HighLimit, tmp.Objects[od.Index.ToString()].SubObjects["0"].HighLimit); + Assert.Equal(sub.LowLimit, tmp.Objects[od.Index.ToString()].SubObjects["0"].LowLimit); + Assert.Equal(sub.defaultvalue, tmp.Objects[od.Index.ToString()].SubObjects["0"].DefaultValue); + } + [Fact] + public void Test_ToProtobufferODObject_CustomProperties() + { + var eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + var od = new ODentry + { + objecttype = ObjectType.RECORD, + Index = 0x2000, + }; + od.prop.CO_disabled = true; + od.prop.CO_countLabel = "CO_countLabel"; + od.prop.CO_storageGroup = "CO_storageGroup"; + + eds.ods.Add(od.Index, od); + var tmp = MappingEDS.MapToProtobuffer(eds); + + Assert.Equal(od.prop.CO_disabled, tmp.Objects[od.Index.ToString()].Disabled); + Assert.Equal(od.prop.CO_countLabel, tmp.Objects[od.Index.ToString()].CountLabel); + Assert.Equal(od.prop.CO_storageGroup, tmp.Objects[od.Index.ToString()].StorageGroup); + } + [Theory] + [InlineData(OdSubObject.Types.AccessSRDO.No, AccessSRDO.no)] + [InlineData(OdSubObject.Types.AccessSRDO.Rx, AccessSRDO.rx)] + [InlineData(OdSubObject.Types.AccessSRDO.Trx, AccessSRDO.trx)] + [InlineData(OdSubObject.Types.AccessSRDO.Tx, AccessSRDO.tx)] + public void Test_ToProtobufferSubODObject_CustomProperties(OdSubObject.Types.AccessSRDO accessSRDO, AccessSRDO co_prop) + { + var eds = new EDSsharp + { + ods = new System.Collections.Generic.SortedDictionary() + }; + var od = new ODentry + { + objecttype = ObjectType.RECORD, + Index = 0x2000 + }; + var sub = new ODentry + { + parent = od, + }; + sub.prop.CO_accessSRDO = co_prop; + sub.prop.CO_stringLengthMin = 123; + + od.subobjects.Add(0x00, sub); + eds.ods.Add(od.Index, od); + var tmp = MappingEDS.MapToProtobuffer(eds); + + Assert.Equal(accessSRDO, tmp.Objects[od.Index.ToString()].SubObjects["0"].Srdo); + Assert.Equal(sub.prop.CO_stringLengthMin, tmp.Objects[od.Index.ToString()].SubObjects["0"].StringLengthMin); + } + + [Fact] + public void Test_FromProtobufferAssertConfig() + { + var d = new CanOpenDevice { }; + + var od = new OdObject + { + ObjectType = OdObject.Types.ObjectType.Var, + Name = "Test VAR", + }; + + var sub = new OdSubObject + { + Name = "some value", + DataType = OdSubObject.Types.DataType.Unsigned8, + Pdo = OdSubObject.Types.AccessPDO.T, + Sdo = OdSubObject.Types.AccessSDO.Ro, + DefaultValue = "1", + }; + od.SubObjects.Add("0", sub); + d.Objects.Add("0x2000", od); + + //Assert is called inside the map function + MappingEDS.MapFromProtobuffer(d); + } + [Fact] + public void Test_FromProtobufferFileInfo() + { + var d = new CanOpenDevice + { + FileInfo = new CanOpen_FileInfo() + }; + var CreationTime = DateTime.ParseExact($"11:22AM 11-22-1234", "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + var ModificationTime = DateTime.ParseExact($"11:22AM 11-22-1234", "h:mmtt MM-dd-yyyy", CultureInfo.InvariantCulture); + + d.FileInfo.FileVersion = "FileVersion"; + d.FileInfo.Description = "Description"; + d.FileInfo.CreationTime = Timestamp.FromDateTime(CreationTime.ToUniversalTime()); + d.FileInfo.ModificationTime = Timestamp.FromDateTime(ModificationTime.ToUniversalTime()); + d.FileInfo.ModifiedBy = "ModifiedBy"; + + var tmp = MappingEDS.MapFromProtobuffer(d); + Assert.Equal(d.FileInfo.CreatedBy, tmp.fi.CreatedBy); + Assert.Equal(d.FileInfo.CreationTime.ToDateTime().ToString("h:mmtt"), tmp.fi.CreationTime); + Assert.Equal(d.FileInfo.CreationTime.ToDateTime().ToString("MM-dd-yyyy"), tmp.fi.CreationDate); + Assert.Equal(d.FileInfo.Description, tmp.fi.Description); + Assert.Equal(d.FileInfo.FileVersion, tmp.fi.FileVersion); + Assert.Equal(d.FileInfo.ModifiedBy, tmp.fi.ModifiedBy); + Assert.Equal(d.FileInfo.ModificationTime.ToDateTime().ToString("h:mmtt"), tmp.fi.ModificationTime); + Assert.Equal(d.FileInfo.ModificationTime.ToDateTime().ToString("MM-dd-yyyy"), tmp.fi.ModificationDate); + + //Assert is called inside the map function + MappingEDS.MapFromProtobuffer(d); + } + [Fact] + public void Test_FromProtobufferDeviceInfo() + { + var d = new CanOpenDevice + { + DeviceInfo = new CanOpen_DeviceInfo() + { + BaudRate10 = true, + BaudRate20 = false, + BaudRate50 = true, + BaudRate125 = false, + BaudRate250 = true, + BaudRate500 = false, + BaudRate800 = true, + BaudRate1000 = false, + BaudRateAuto = true, + LssMaster = false, + LssSlave = true, + VendorName = "VendorName", + ProductName = "ProductName" + } + }; + + var tmp = MappingEDS.MapFromProtobuffer(d); + Assert.Equal(d.DeviceInfo.BaudRate10, tmp.di.BaudRate_10); + Assert.Equal(d.DeviceInfo.BaudRate20, tmp.di.BaudRate_20); + Assert.Equal(d.DeviceInfo.BaudRate50, tmp.di.BaudRate_50); + Assert.Equal(d.DeviceInfo.BaudRate125, tmp.di.BaudRate_125); + Assert.Equal(d.DeviceInfo.BaudRate250, tmp.di.BaudRate_250); + Assert.Equal(d.DeviceInfo.BaudRate500, tmp.di.BaudRate_500); + Assert.Equal(d.DeviceInfo.BaudRate800, tmp.di.BaudRate_800); + Assert.Equal(d.DeviceInfo.BaudRate1000, tmp.di.BaudRate_1000); + Assert.Equal(d.DeviceInfo.BaudRateAuto, tmp.di.BaudRate_auto); + Assert.Equal(d.DeviceInfo.LssMaster, tmp.di.LSS_Master); + Assert.Equal(d.DeviceInfo.LssSlave, tmp.di.LSS_Supported); + Assert.Equal(d.DeviceInfo.VendorName, tmp.di.VendorName); + Assert.Equal(d.DeviceInfo.ProductName, tmp.di.ProductName); + } + + [Fact] + public void Test_FromProtobufferDeviceCommissioning() + { + var d = new CanOpenDevice + { + DeviceCommissioning = new CanOpen_DeviceCommissioning + { + Baudrate = 456, + NodeId = 123, + NodeName = "NodeName" + + } + }; + + var tmp = MappingEDS.MapFromProtobuffer(d); + Assert.Equal(d.DeviceCommissioning.NodeId, tmp.dc.NodeID); + Assert.Equal(d.DeviceCommissioning.NodeName, tmp.dc.NodeName); + Assert.Equal(d.DeviceCommissioning.Baudrate, tmp.dc.Baudrate); + } + + [Theory] + [InlineData(OdObject.Types.ObjectType.Array, ObjectType.ARRAY)] + [InlineData(OdObject.Types.ObjectType.Record, ObjectType.RECORD)] + [InlineData(OdObject.Types.ObjectType.Var, ObjectType.VAR)] + [InlineData(OdObject.Types.ObjectType.Unspecified, ObjectType.UNKNOWN)] + public void Test_FromProtobufferODObject(OdObject.Types.ObjectType objTypeProto, ObjectType objTypeEDS) + { + ushort index = 0x2000; + var d = new CanOpenDevice(); + var od = new OdObject + { + ObjectType = objTypeProto, + Name = "Name" + }; + d.Objects.Add(index.ToString(), od); + var tmp = MappingEDS.MapFromProtobuffer(d); + Assert.Equal(index, tmp.ods[index].Index); + Assert.Equal(objTypeEDS, tmp.ods[index].objecttype); + Assert.Equal(od.Name, tmp.ods[index].parameter_name); + } + + [Theory] + [InlineData(OdSubObject.Types.DataType.Unspecified, DataType.UNKNOWN)] + [InlineData(OdSubObject.Types.DataType.Boolean, DataType.BOOLEAN)] + [InlineData(OdSubObject.Types.DataType.Integer8, DataType.INTEGER8)] + [InlineData(OdSubObject.Types.DataType.Integer16, DataType.INTEGER16)] + [InlineData(OdSubObject.Types.DataType.Integer32, DataType.INTEGER32)] + [InlineData(OdSubObject.Types.DataType.Unsigned8, DataType.UNSIGNED8)] + [InlineData(OdSubObject.Types.DataType.Unsigned16, DataType.UNSIGNED16)] + [InlineData(OdSubObject.Types.DataType.Unsigned32, DataType.UNSIGNED32)] + [InlineData(OdSubObject.Types.DataType.Real32, DataType.REAL32)] + [InlineData(OdSubObject.Types.DataType.VisibleString, DataType.VISIBLE_STRING)] + [InlineData(OdSubObject.Types.DataType.OctetString, DataType.OCTET_STRING)] + [InlineData(OdSubObject.Types.DataType.UnicodeString, DataType.UNICODE_STRING)] + [InlineData(OdSubObject.Types.DataType.TimeOfDay, DataType.TIME_OF_DAY)] + [InlineData(OdSubObject.Types.DataType.TimeDifference, DataType.TIME_DIFFERENCE)] + [InlineData(OdSubObject.Types.DataType.Domain, DataType.DOMAIN)] + [InlineData(OdSubObject.Types.DataType.Integer24, DataType.INTEGER24)] + [InlineData(OdSubObject.Types.DataType.Real64, DataType.REAL64)] + [InlineData(OdSubObject.Types.DataType.Integer40, DataType.INTEGER40)] + [InlineData(OdSubObject.Types.DataType.Integer48, DataType.INTEGER48)] + [InlineData(OdSubObject.Types.DataType.Integer56, DataType.INTEGER56)] + [InlineData(OdSubObject.Types.DataType.Integer64, DataType.INTEGER64)] + [InlineData(OdSubObject.Types.DataType.Unsigned24, DataType.UNSIGNED24)] + [InlineData(OdSubObject.Types.DataType.Unsigned40, DataType.UNSIGNED40)] + [InlineData(OdSubObject.Types.DataType.Unsigned48, DataType.UNSIGNED48)] + [InlineData(OdSubObject.Types.DataType.Unsigned56, DataType.UNSIGNED56)] + [InlineData(OdSubObject.Types.DataType.Unsigned64, DataType.UNSIGNED64)] + public void Test_FromProtobufferSubODObjectDatatype(OdSubObject.Types.DataType datatypeProto, DataType datatypeEDS) + { + ushort index = 0x2000; + ushort subindex = 0x1; + var d = new CanOpenDevice(); + var od = new OdObject + { + ObjectType = OdObject.Types.ObjectType.Record + }; + var sub = new OdSubObject + { + DataType = datatypeProto, + }; + + od.SubObjects.Add(subindex.ToString(), sub); + d.Objects.Add(index.ToString(), od); + + var tmp = MappingEDS.MapFromProtobuffer(d); + + Assert.Equal(datatypeEDS, tmp.ods[index].subobjects[subindex].datatype); + } + + [Theory] + [InlineData(OdSubObject.Types.AccessPDO.Tr, OdSubObject.Types.AccessSDO.Rw, EDSsharp.AccessType.rw)] + [InlineData(OdSubObject.Types.AccessPDO.No, OdSubObject.Types.AccessSDO.Ro, EDSsharp.AccessType.ro)] + [InlineData(OdSubObject.Types.AccessPDO.No, OdSubObject.Types.AccessSDO.Wo, EDSsharp.AccessType.wo)] + [InlineData(OdSubObject.Types.AccessPDO.T, OdSubObject.Types.AccessSDO.Rw, EDSsharp.AccessType.rwr)] + [InlineData(OdSubObject.Types.AccessPDO.R, OdSubObject.Types.AccessSDO.Rw, EDSsharp.AccessType.rww)] + [InlineData(OdSubObject.Types.AccessPDO.R, OdSubObject.Types.AccessSDO.Ro, EDSsharp.AccessType.@const)] + [InlineData(OdSubObject.Types.AccessPDO.No, OdSubObject.Types.AccessSDO.No, EDSsharp.AccessType.UNKNOWN)] + public void Test_FromProtobufferSubODObjectAccesstype(OdSubObject.Types.AccessPDO accessPDOProto, OdSubObject.Types.AccessSDO accessSDOProto, EDSsharp.AccessType datatypeEDS) + { + ushort index = 0x2000; + ushort subindex = 0x1; + var d = new CanOpenDevice(); + var od = new OdObject + { + ObjectType = OdObject.Types.ObjectType.Record + }; + var sub = new OdSubObject + { + Sdo = accessSDOProto, + Pdo = accessPDOProto, + }; + + od.SubObjects.Add(subindex.ToString(), sub); + d.Objects.Add(index.ToString(), od); + + var tmp = MappingEDS.MapFromProtobuffer(d); + + Assert.Equal(datatypeEDS, tmp.ods[index].subobjects[subindex].accesstype); + } + + [Fact] + public void Test_FromProtobufferSubODObjectMembers() + { + ushort index = 0x2000; + ushort subindex = 0x1; + var d = new CanOpenDevice(); + var od = new OdObject + { + ObjectType = OdObject.Types.ObjectType.Record + }; + var sub = new OdSubObject + { + ActualValue = "123", + Name = "some value", + HighLimit = "HighLimit", + LowLimit = "LowLimit", + DefaultValue = "defaultvalue", + }; + + od.SubObjects.Add(subindex.ToString(), sub); + d.Objects.Add(index.ToString(), od); + var tmp = MappingEDS.MapFromProtobuffer(d); + + Assert.Equal(sub.ActualValue, tmp.ods[index].subobjects[subindex].actualvalue); + Assert.Equal(sub.Name, tmp.ods[index].subobjects[subindex].parameter_name); + Assert.Equal(sub.HighLimit, tmp.ods[index].subobjects[subindex].HighLimit); + Assert.Equal(sub.LowLimit, tmp.ods[index].subobjects[subindex].LowLimit); + Assert.Equal(sub.DefaultValue, tmp.ods[index].subobjects[subindex].defaultvalue); + Assert.Equal(index, tmp.ods[index].subobjects[subindex].Index); + Assert.Equal(subindex, tmp.ods[index].subobjects[subindex].Subindex); + } + [Fact] + public void Test_FromProtobufferODObject_CustomProperties() + { + ushort index = 0x2000; + var d = new CanOpenDevice(); + var od = new OdObject + { + ObjectType = OdObject.Types.ObjectType.Record, + Disabled = true, + CountLabel = "CountLabel", + StorageGroup = "StorageGroup" + }; + + d.Objects.Add(index.ToString(), od); + var tmp = MappingEDS.MapFromProtobuffer(d); + + Assert.Equal(od.Disabled, tmp.ods[index].prop.CO_disabled); + Assert.Equal(od.CountLabel, tmp.ods[index].prop.CO_countLabel); + Assert.Equal(od.StorageGroup, tmp.ods[index].prop.CO_storageGroup); + } + [Theory] + [InlineData(OdSubObject.Types.AccessSRDO.No, AccessSRDO.no)] + [InlineData(OdSubObject.Types.AccessSRDO.Rx, AccessSRDO.rx)] + [InlineData(OdSubObject.Types.AccessSRDO.Trx, AccessSRDO.trx)] + [InlineData(OdSubObject.Types.AccessSRDO.Tx, AccessSRDO.tx)] + public void Test_FromProtobufferSubODObject_CustomProperties(OdSubObject.Types.AccessSRDO accessSRDO, AccessSRDO co_prop) + { + ushort index = 0x2000; + ushort subindex = 0x1; + var d = new CanOpenDevice(); + var od = new OdObject + { + ObjectType = OdObject.Types.ObjectType.Record + }; + var sub = new OdSubObject + { + Srdo = accessSRDO, + StringLengthMin = 123, + }; + + od.SubObjects.Add(subindex.ToString(), sub); + d.Objects.Add(index.ToString(), od); + var tmp = MappingEDS.MapFromProtobuffer(d); + + Assert.Equal(co_prop, tmp.ods[index].subobjects[subindex].prop.CO_accessSRDO); + //Assert.Equal(sub.ActualValue, tmp.ods[index].subobjects[subindex].prop.CO_flagsPDO); + Assert.Equal(sub.StringLengthMin, tmp.ods[index].subobjects[subindex].prop.CO_stringLengthMin); + } + } +} diff --git a/libEDSsharp/CanOpenEDSMapping.cs b/libEDSsharp/CanOpenEDSMapping.cs new file mode 100644 index 0000000..6468f27 --- /dev/null +++ b/libEDSsharp/CanOpenEDSMapping.cs @@ -0,0 +1,467 @@ +/* + 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) 2024 Lars E. Susaas +*/ + +using AutoMapper; +using Google.Protobuf.WellKnownTypes; +using LibCanOpen; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.Linq; + +namespace libEDSsharp +{ + /// + /// Conversion class to/from EDS to protobuffer + /// + public class MappingEDS + { + /// + /// Converts from protobuffer to EDS + /// + /// protobuffer device + /// new EDS device containing data from protobuffer device + public static EDSsharp MapFromProtobuffer(CanOpenDevice source) + { + var config = new MapperConfiguration(cfg => + { + // workaround for https://github.com/AutoMapper/AutoMapper/issues/2959 + // Cant update untill after .net framwork is gone + cfg.ShouldMapMethod = (m => m.Name == "ARandomStringThatDoesNotMatchAnyFunctionName"); + cfg.CreateMap().ConvertUsing(); + cfg.CreateMap() + .ForMember(dest => dest.Dirty, opt => opt.Ignore()) + .ForMember(dest => dest.xddfilename_1_1, opt => opt.Ignore()) + .ForMember(dest => dest.xddfilenameStripped, opt => opt.Ignore()) + .ForMember(dest => dest.edsfilename, opt => opt.Ignore()) + .ForMember(dest => dest.dcffilename, opt => opt.Ignore()) + .ForMember(dest => dest.ODfilename, opt => opt.Ignore()) + .ForMember(dest => dest.ODfileVersion, opt => opt.Ignore()) + .ForMember(dest => dest.mdfilename, opt => opt.Ignore()) + .ForMember(dest => dest.xmlfilename, opt => opt.Ignore()) + .ForMember(dest => dest.xddfilename_1_0, opt => opt.Ignore()) + .ForMember(dest => dest.xddTemplate, opt => opt.Ignore()) + .ForMember(dest => dest.dummy_ods, opt => opt.Ignore()) + .ForMember(dest => dest.CO_storageGroups, opt => opt.Ignore()) + .ForMember(dest => dest.md, opt => opt.Ignore()) + .ForMember(dest => dest.oo, opt => opt.Ignore()) + .ForMember(dest => dest.mo, opt => opt.Ignore()) + .ForMember(dest => dest.c, opt => opt.Ignore()) + .ForMember(dest => dest.du, opt => opt.Ignore()) + .ForMember(dest => dest.td, opt => opt.Ignore()) + .ForMember(dest => dest.sm, opt => opt.Ignore()) + .ForMember(dest => dest.cm, opt => opt.Ignore()) + .ForMember(dest => dest.modules, opt => opt.Ignore()) + .ForMember(dest => dest.NodeID, opt => opt.Ignore()) + .ForMember(dest => dest.projectFilename, opt => opt.MapFrom(src => src.DeviceInfo.ProductName)) + .ForMember(dest => dest.NodeID, opt => opt.MapFrom(src => src.DeviceCommissioning.NodeId)) + .ForMember(dest => dest.fi, opt => opt.MapFrom(src => src.FileInfo)) + .ForMember(dest => dest.di, opt => opt.MapFrom(src => src.DeviceInfo)) + .ForMember(dest => dest.dc, opt => opt.MapFrom(src => src.DeviceCommissioning)) + .ForMember(dest => dest.ods, opt => opt.MapFrom(src => src.Objects)); + cfg.CreateMap() + .ForMember(dest => dest.FileName, opt => opt.Ignore()) + .ForMember(dest => dest.LastEDS, opt => opt.Ignore()) + .ForMember(dest => dest.EDSVersionMajor, opt => opt.Ignore()) + .ForMember(dest => dest.EDSVersionMinor, opt => opt.Ignore()) + .ForMember(dest => dest.EDSVersion, opt => opt.Ignore()) + .ForMember(dest => dest.exportFolder, opt => opt.Ignore()) + .ForMember(dest => dest.FileRevision, opt => opt.MapFrom(src => (byte)src.FileVersion.ElementAtOrDefault(0))) + .ForMember(dest => dest.CreationDateTime, opt => opt.MapFrom(src => src.CreationTime.ToDateTime())) + .ForMember(dest => dest.CreationDate, opt => opt.MapFrom(src => src.CreationTime.ToDateTime().ToString("MM-dd-yyyy"))) + .ForMember(dest => dest.CreationTime, opt => opt.MapFrom(src => src.CreationTime.ToDateTime().ToString("h:mmtt"))) + .ForMember(dest => dest.ModificationDateTime, opt => opt.MapFrom(src => src.ModificationTime.ToDateTime())) + .ForMember(dest => dest.ModificationDate, opt => opt.MapFrom(src => src.ModificationTime.ToDateTime().ToString("MM-dd-yyyy"))) + .ForMember(dest => dest.ModificationTime, opt => opt.MapFrom(src => src.ModificationTime.ToDateTime().ToString("h:mmtt"))); + cfg.CreateMap() + .ForMember(dest => dest.VendorNumber, opt => opt.Ignore()) + .ForMember(dest => dest.ProductNumber, opt => opt.Ignore()) + .ForMember(dest => dest.RevisionNumber, opt => opt.Ignore()) + .ForMember(dest => dest.SimpleBootUpMaster, opt => opt.Ignore()) + .ForMember(dest => dest.SimpleBootUpSlave, opt => opt.Ignore()) + .ForMember(dest => dest.Granularity, opt => opt.Ignore()) + .ForMember(dest => dest.DynamicChannelsSupported, opt => opt.Ignore()) + .ForMember(dest => dest.CompactPDO, opt => opt.Ignore()) + .ForMember(dest => dest.GroupMessaging, opt => opt.Ignore()) + .ForMember(dest => dest.NrOfRXPDO, opt => opt.Ignore()) // TODO Calculate this + .ForMember(dest => dest.NrOfTXPDO, opt => opt.Ignore()) // TODO Calculate this + .ForMember(dest => dest.LSS_Supported, opt => opt.MapFrom(src => src.LssSlave)) + .ForMember(dest => dest.LSS_Master, opt => opt.MapFrom(src => src.LssMaster)) + .ForMember(dest => dest.NG_Slave, opt => opt.Ignore()) + .ForMember(dest => dest.NG_Master, opt => opt.Ignore()) + .ForMember(dest => dest.NrOfNG_MonitoredNodes, opt => opt.Ignore()); + cfg.CreateMap() + .ForMember(dest => dest.NetNumber, opt => opt.Ignore()) + .ForMember(dest => dest.NetworkName, opt => opt.Ignore()) + .ForMember(dest => dest.CANopenManager, opt => opt.Ignore()) + .ForMember(dest => dest.LSS_SerialNumber, opt => opt.Ignore()); + cfg.CreateMap() + .ForMember(dest => dest.CO_accessSRDO, opt => opt.Ignore()) + .ForMember(dest => dest.CO_stringLengthMin, opt => opt.Ignore()); + cfg.CreateMap().ConvertUsing(); + cfg.CreateMap() + .ForMember(dest => dest.Index, opt => opt.Ignore()) + .ForMember(dest => dest.parameter_name, opt => opt.MapFrom(src => src.Name)) + .ForMember(dest => dest.denotation, opt => opt.Ignore()) + .ForMember(dest => dest.datatype, opt => opt.Ignore()) + .ForMember(dest => dest.accesstype, opt => opt.Ignore()) + .ForMember(dest => dest.defaultvalue, opt => opt.Ignore()) + .ForMember(dest => dest.LowLimit, opt => opt.Ignore()) + .ForMember(dest => dest.HighLimit, opt => opt.Ignore()) + .ForMember(dest => dest.actualvalue, opt => opt.Ignore()) + .ForMember(dest => dest.ObjFlags, opt => opt.Ignore()) + .ForMember(dest => dest.CompactSubObj, opt => opt.Ignore()) + .ForMember(dest => dest.count, opt => opt.Ignore()) + .ForMember(dest => dest.ObjExtend, opt => opt.Ignore()) + .ForMember(dest => dest.PDOtype, opt => opt.Ignore()) + .ForMember(dest => dest.Label, opt => opt.Ignore()) + .ForMember(dest => dest.parent, opt => opt.Ignore()) + .ForMember(dest => dest.prop, opt => opt.MapFrom(src => src)) + .ForMember(dest => dest.uniqueID, opt => opt.Ignore()); + cfg.CreateMap().ConvertUsing(); + cfg.CreateMap() + .ForMember(dest => dest.parameter_name, opt => opt.MapFrom(src => src.Name)) + .ForMember(dest => dest.Index, opt => opt.Ignore()) + .ForMember(dest => dest.denotation, opt => opt.Ignore()) + .ForMember(dest => dest.accesstype, opt => opt.MapFrom(src => src)) + .ForMember(dest => dest.ObjFlags, opt => opt.Ignore()) + .ForMember(dest => dest.CompactSubObj, opt => opt.Ignore()) + .ForMember(dest => dest.count, opt => opt.Ignore()) + .ForMember(dest => dest.ObjExtend, opt => opt.Ignore()) + .ForMember(dest => dest.PDOtype, opt => opt.Ignore()) + .ForMember(dest => dest.Label, opt => opt.Ignore()) + .ForMember(dest => dest.parent, opt => opt.Ignore()) + .ForMember(dest => dest.prop, opt => opt.Ignore()) + .ForPath(dest => dest.prop.CO_accessSRDO, opt => opt.MapFrom(src => src.Srdo)) + .ForPath(dest => dest.prop.CO_stringLengthMin, opt => opt.MapFrom(src => src.StringLengthMin)) + .ForMember(dest => dest.uniqueID, opt => opt.Ignore()) + .ForMember(dest => dest.objecttype, opt => opt.Ignore()) + .ForMember(dest => dest.Description, opt => opt.Ignore()) + .ForMember(dest => dest.subobjects, opt => opt.Ignore()); + }); + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + + var result = mapper.Map(source); + + //Post processing, add index / subindex + foreach (KeyValuePair obj in result.ods) + { + obj.Value.Index = obj.Key; + foreach (KeyValuePair subObj in obj.Value.subobjects) + { + subObj.Value.parent = obj.Value; + } + } + return result; + } + /// + /// Converts from EDS to protobuffer + /// + /// EDS device + /// protobuffer device containing data from EDS + public static CanOpenDevice MapToProtobuffer(EDSsharp source) + { + var config = new MapperConfiguration(cfg => + { + // workaround for https://github.com/AutoMapper/AutoMapper/issues/2959 + // Cant update untill after .net framwork is gone + cfg.ShouldMapMethod = (m => m.Name == "ARandomStringThatDoesNotMatchAnyFunctionName"); + cfg.CreateMap() + .ForMember(dest => dest.FileInfo, opt => opt.MapFrom(src => src.fi)) + .ForMember(dest => dest.DeviceInfo, opt => opt.MapFrom(src => src.di)) + .ForMember(dest => dest.DeviceCommissioning, opt => opt.MapFrom(src => src.dc)) + .ForMember(dest => dest.Objects, opt => opt.MapFrom(src => src.ods)); + cfg.CreateMap() + .ForMember(dest => dest.CreationTime, opt => opt.MapFrom(new EDSDateAndTimeResolver("creation"))) + .ForMember(dest => dest.ModificationTime, opt => opt.MapFrom(new EDSDateAndTimeResolver("modification"))); + cfg.CreateMap() + .ForMember(dest => dest.BaudRate10, opt => opt.MapFrom(src => src.BaudRate_10)) + .ForMember(dest => dest.BaudRate20, opt => opt.MapFrom(src => src.BaudRate_20)) + .ForMember(dest => dest.BaudRate50, opt => opt.MapFrom(src => src.BaudRate_50)) + .ForMember(dest => dest.BaudRate125, opt => opt.MapFrom(src => src.BaudRate_125)) + .ForMember(dest => dest.BaudRate250, opt => opt.MapFrom(src => src.BaudRate_250)) + .ForMember(dest => dest.BaudRate500, opt => opt.MapFrom(src => src.BaudRate_500)) + .ForMember(dest => dest.BaudRate800, opt => opt.MapFrom(src => src.BaudRate_800)) + .ForMember(dest => dest.BaudRate1000, opt => opt.MapFrom(src => src.BaudRate_1000)) + .ForMember(dest => dest.BaudRateAuto, opt => opt.MapFrom(src => src.BaudRate_auto)) + .ForMember(dest => dest.LssSlave, opt => opt.MapFrom(src => src.LSS_Supported)) + .ForMember(dest => dest.LssMaster, opt => opt.MapFrom(src => src.LSS_Master)); + cfg.CreateMap(); + cfg.CreateMap() + .ForMember(dest => dest.Disabled, opt => opt.MapFrom(src => src.prop.CO_disabled)) + .ForMember(dest => dest.Alias, opt => opt.Ignore()) + .ForMember(dest => dest.StorageGroup, opt => opt.MapFrom(src => src.prop.CO_storageGroup)) + .ForMember(dest => dest.FlagsPDO, opt => opt.Ignore()) + .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.parameter_name)) + .ForMember(dest => dest.ObjectType, opt => opt.MapFrom(src => src.objecttype)) + .ForMember(dest => dest.CountLabel, opt => opt.MapFrom(src => src.prop.CO_countLabel)); + cfg.CreateMap().ConvertUsing(); + cfg.CreateMap().ConvertUsing(); + cfg.CreateMap().ConvertUsing(); + cfg.CreateMap() + .ForMember(dest => dest.Name, opt => opt.MapFrom(src => src.parameter_name)) + .ForMember(dest => dest.Alias, opt => opt.Ignore()) + .ForMember(dest => dest.DataType, opt => opt.MapFrom(src => src.datatype)) + .ForMember(dest => dest.Sdo, opt => opt.MapFrom(src => src.accesstype)) + .ForMember(dest => dest.Pdo, opt => opt.MapFrom(src => src.accesstype)) + .ForMember(dest => dest.Srdo, opt => opt.MapFrom(src => src.prop.CO_accessSRDO)) + .ForMember(dest => dest.StringLengthMin, opt => opt.MapFrom(src => src.prop.CO_stringLengthMin)); + }); + + config.AssertConfigurationIsValid(); + var mapper = config.CreateMapper(); + return mapper.Map(source); + } + } + + /// + /// Helper class to convert EDS date and time into datetime used in the protobuffer timestand (datetime) + /// + public class EDSDateAndTimeResolver : IValueResolver + { + private readonly string _type; + public EDSDateAndTimeResolver(string type) + { + _type = type; + } + /// + /// Resolver to convert eds date and time into protobuffer timestamp (datetime) + /// + /// source EDS fileinfo object + /// protobuffer fileinfo object + /// result object + /// resolve context + /// result + public Timestamp Resolve(FileInfo source, CanOpen_FileInfo destination, Timestamp member, ResolutionContext context) + { + string strTime; + string strDate; + if (_type == "creation") + { + strDate = source.CreationDate; + strTime = source.CreationTime; + } + else + { + strDate = source.ModificationDate; + strTime = source.ModificationTime; + } + + var time = new DateTime(0); + var date = new DateTime(0); + + try + { + time = DateTime.ParseExact(strTime, "h:mmtt", CultureInfo.InvariantCulture); + } + catch (Exception e) + { + if (e is FormatException) + { + //Silently ignore + } + } + + try + { + date = DateTime.ParseExact(strDate, "MM-dd-yyyy", CultureInfo.InvariantCulture); + } + catch (Exception e) + { + if (e is FormatException) + { + //Silently ignore + } + } + + var datetime = date.AddTicks(time.TimeOfDay.Ticks); + return Timestamp.FromDateTime(datetime.ToUniversalTime()); + } + } + + /// + /// Helper class to convert object type enum + /// + /// Checkout AutoMapper.Extensions.EnumMapping when .net framework is gone + public class ODTypeResolver : ITypeConverter, ITypeConverter + { + /// + /// Resolver to convert object types + /// + /// EDS object type object + /// protobuffer object type + /// result object + /// resolve context + /// result + public OdObject.Types.ObjectType Convert(ObjectType source, OdObject.Types.ObjectType destination, ResolutionContext context) + { + switch (source) + { + case ObjectType.VAR: + return OdObject.Types.ObjectType.Var; + case ObjectType.ARRAY: + return OdObject.Types.ObjectType.Array; + case ObjectType.RECORD: + return OdObject.Types.ObjectType.Record; + case ObjectType.UNKNOWN: + case ObjectType.NULL: + case ObjectType.DOMAIN: + case ObjectType.DEFTYPE: + case ObjectType.DEFSTRUCT: + default: + return OdObject.Types.ObjectType.Unspecified; + } + } + /// + /// Resolver to convert object types + /// + /// EDS object type object + /// protobuffer object type + /// result object + /// resolve context + /// result + public ObjectType Convert(OdObject.Types.ObjectType source, ObjectType destination, ResolutionContext context) + { + switch (source) + { + case OdObject.Types.ObjectType.Unspecified: + return ObjectType.UNKNOWN; + case OdObject.Types.ObjectType.Var: + return ObjectType.VAR; + case OdObject.Types.ObjectType.Array: + return ObjectType.ARRAY; + case OdObject.Types.ObjectType.Record: + return ObjectType.RECORD; + default: + return ObjectType.UNKNOWN; + } + } + } + /// + /// Helper class to convert Access types + /// + /// Checkout AutoMapper.Extensions.EnumMapping when .net framework is gone + public class ODAccessTypeResolver : ITypeConverter, + ITypeConverter, + ITypeConverter + { + /// + /// Resolver to convert eds access into SDO access type + /// + /// EDS accesstype + /// protobuffer sdo access type + /// result object + /// resolve context + /// result + public OdSubObject.Types.AccessSDO Convert(EDSsharp.AccessType source, OdSubObject.Types.AccessSDO destination, ResolutionContext context) + { + switch (source) + { + case EDSsharp.AccessType.rw: + case EDSsharp.AccessType.rwr: + case EDSsharp.AccessType.rww: + return OdSubObject.Types.AccessSDO.Rw; + case EDSsharp.AccessType.ro: + case EDSsharp.AccessType.@const: + return OdSubObject.Types.AccessSDO.Ro; + case EDSsharp.AccessType.wo: + return OdSubObject.Types.AccessSDO.Wo; + case EDSsharp.AccessType.UNKNOWN: + default: + return OdSubObject.Types.AccessSDO.No; + } + } + /// + /// Resolver to convert eds access into PDO access type + /// + /// 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) + { + switch (source) + { + case EDSsharp.AccessType.rw: + return OdSubObject.Types.AccessPDO.Tr; + case EDSsharp.AccessType.rwr: + return OdSubObject.Types.AccessPDO.T; + case EDSsharp.AccessType.rww: + case EDSsharp.AccessType.@const: + return OdSubObject.Types.AccessPDO.R; + case EDSsharp.AccessType.ro: + case EDSsharp.AccessType.wo: + case EDSsharp.AccessType.UNKNOWN: + default: + return OdSubObject.Types.AccessPDO.No; + } + } + /// + /// Resolver to convert SDO access type into eds access into + /// + /// protobuffer sdo access type + /// EDS accesstype + /// result object + /// resolve context + /// result + public EDSsharp.AccessType Convert(OdSubObject source, EDSsharp.AccessType destination, ResolutionContext context) + { + if (source.Pdo == OdSubObject.Types.AccessPDO.Tr && source.Sdo == OdSubObject.Types.AccessSDO.Rw) + return EDSsharp.AccessType.rw; + else if (source.Pdo == OdSubObject.Types.AccessPDO.No && source.Sdo == OdSubObject.Types.AccessSDO.Ro) + return EDSsharp.AccessType.ro; + else if (source.Pdo == OdSubObject.Types.AccessPDO.No && source.Sdo == OdSubObject.Types.AccessSDO.Wo) + return EDSsharp.AccessType.wo; + else if (source.Pdo == OdSubObject.Types.AccessPDO.T && source.Sdo == OdSubObject.Types.AccessSDO.Rw) + return EDSsharp.AccessType.rwr; + else if (source.Pdo == OdSubObject.Types.AccessPDO.R && source.Sdo == OdSubObject.Types.AccessSDO.Rw) + return EDSsharp.AccessType.rww; + else if (source.Pdo == OdSubObject.Types.AccessPDO.R && source.Sdo == OdSubObject.Types.AccessSDO.Ro) + return EDSsharp.AccessType.@const; + else + return EDSsharp.AccessType.UNKNOWN; + } + } + + public class ODStringToShortTypeResolver : ITypeConverter + { + /// + /// Resolver to convert index & subindex string into short, will try hex, then descimal + /// + /// string containing index or subindex + /// short int interpreted from the string + /// result object + /// resolve context + /// result + public UInt16 Convert(string source, UInt16 destination, ResolutionContext context) + { + if (source.StartsWith("0x")) + { + var hex = source.Substring(2); + return System.Convert.ToUInt16(hex, 16); + } + else + { + return System.Convert.ToUInt16(source); + } + } + } +} diff --git a/libEDSsharp/libEDSsharp.csproj b/libEDSsharp/libEDSsharp.csproj index 9d9c6f3..2c71b47 100644 --- a/libEDSsharp/libEDSsharp.csproj +++ b/libEDSsharp/libEDSsharp.csproj @@ -47,6 +47,7 @@ +