mirror of
https://github.com/OpenLogics/MewtocolNet.git
synced 2025-12-06 03:01:24 +00:00
Changed boolean register usage and attributes
This commit is contained in:
@@ -7,7 +7,7 @@ namespace Examples {
|
|||||||
public class TestRegisters : RegisterCollectionBase {
|
public class TestRegisters : RegisterCollectionBase {
|
||||||
|
|
||||||
//corresponds to a R100 boolean register in the PLC
|
//corresponds to a R100 boolean register in the PLC
|
||||||
[Register(1000, RegisterType.R)]
|
[Register(IOType.R, 1000)]
|
||||||
public bool TestBool1 { get; private set; }
|
public bool TestBool1 { get; private set; }
|
||||||
|
|
||||||
private int testDuplicate;
|
private int testDuplicate;
|
||||||
@@ -19,7 +19,7 @@ namespace Examples {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//corresponds to a XD input of the PLC
|
//corresponds to a XD input of the PLC
|
||||||
[Register(RegisterType.X, SpecialAddress.D)]
|
[Register(IOType.X, (byte)0xD)]
|
||||||
public bool TestBoolInputXD { get; private set; }
|
public bool TestBoolInputXD { get; private set; }
|
||||||
|
|
||||||
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
|
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
|
||||||
|
|||||||
@@ -9,7 +9,7 @@ namespace Examples {
|
|||||||
|
|
||||||
private bool startCyclePLC;
|
private bool startCyclePLC;
|
||||||
|
|
||||||
[Register(50, RegisterType.R)]
|
[Register(IOType.R, 50)]
|
||||||
public bool StartCyclePLC {
|
public bool StartCyclePLC {
|
||||||
get => startCyclePLC;
|
get => startCyclePLC;
|
||||||
set => AutoSetter(value, ref startCyclePLC);
|
set => AutoSetter(value, ref startCyclePLC);
|
||||||
|
|||||||
@@ -3,9 +3,9 @@ using System.Collections.Generic;
|
|||||||
|
|
||||||
namespace MewtocolNet.Links {
|
namespace MewtocolNet.Links {
|
||||||
|
|
||||||
internal class LinkedData {
|
internal class CodeDescriptions {
|
||||||
|
|
||||||
internal static Dictionary<int, string> ErrorCodes = new Dictionary<int, string> {
|
internal static Dictionary<int, string> Error = new Dictionary<int, string> {
|
||||||
|
|
||||||
{21, "NACK error"},
|
{21, "NACK error"},
|
||||||
{22, "WACK error"},
|
{22, "WACK error"},
|
||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Data;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
@@ -205,167 +206,6 @@ namespace MewtocolNet {
|
|||||||
|
|
||||||
#region Register Adding
|
#region Register Adding
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a PLC memory register to the watchlist <para/>
|
|
||||||
/// The registers can be read back by attaching <see cref="WithPoller"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="_address">The address of the register in the PLCs memory</param>
|
|
||||||
/// <param name="_type">
|
|
||||||
/// The memory area type
|
|
||||||
/// <para>X = Physical input area (bool)</para>
|
|
||||||
/// <para>Y = Physical input area (bool)</para>
|
|
||||||
/// <para>R = Internal relay area (bool)</para>
|
|
||||||
/// <para>DT = Internal data area (short/ushort)</para>
|
|
||||||
/// <para>DDT = Internal relay area (int/uint)</para>
|
|
||||||
/// </param>
|
|
||||||
/// <param name="_name">A naming definition for QOL, doesn't effect PLC and is optional</param>
|
|
||||||
public void AddRegister (int _address, RegisterType _type, string _name = null) {
|
|
||||||
|
|
||||||
IRegister toAdd = null;
|
|
||||||
|
|
||||||
//as number registers
|
|
||||||
if (_type == RegisterType.DT_short) {
|
|
||||||
toAdd = new NRegister<short>(_address, _name);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DT_ushort) {
|
|
||||||
toAdd = new NRegister<ushort>(_address, _name);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DDT_int) {
|
|
||||||
toAdd = new NRegister<int>(_address, _name);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DDT_uint) {
|
|
||||||
toAdd = new NRegister<uint>(_address, _name);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DDT_float) {
|
|
||||||
toAdd = new NRegister<float>(_address, _name);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(toAdd == null) {
|
|
||||||
toAdd = new BRegister(_address, _type, _name);
|
|
||||||
}
|
|
||||||
|
|
||||||
Registers.Add(toAdd);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddRegister (Type _colType, int _address, RegisterType _type, string _name = null) {
|
|
||||||
|
|
||||||
IRegister toAdd = null;
|
|
||||||
|
|
||||||
//as number registers
|
|
||||||
if (_type == RegisterType.DT_short) {
|
|
||||||
toAdd = new NRegister<short>(_address, _name).WithCollectionType(_colType);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DT_ushort) {
|
|
||||||
toAdd = new NRegister<ushort>(_address, _name).WithCollectionType(_colType);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DDT_int) {
|
|
||||||
toAdd = new NRegister<int>(_address, _name).WithCollectionType(_colType);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DDT_uint) {
|
|
||||||
toAdd = new NRegister<uint>(_address, _name).WithCollectionType(_colType);
|
|
||||||
}
|
|
||||||
if (_type == RegisterType.DDT_float) {
|
|
||||||
toAdd = new NRegister<float>(_address, _name).WithCollectionType(_colType);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (toAdd == null) {
|
|
||||||
toAdd = new BRegister(_address, _type, _name).WithCollectionType(_colType);
|
|
||||||
}
|
|
||||||
|
|
||||||
Registers.Add(toAdd);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a PLC memory register to the watchlist <para/>
|
|
||||||
/// The registers can be read back by attaching <see cref="WithPoller"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="_spAddress">The special address of the register in the PLCs memory</param>
|
|
||||||
/// <param name="_type">
|
|
||||||
/// The memory area type
|
|
||||||
/// <para>X = Physical input area (bool)</para>
|
|
||||||
/// <para>Y = Physical input area (bool)</para>
|
|
||||||
/// <para>R = Internal relay area (bool)</para>
|
|
||||||
/// <para>DT = Internal data area (short/ushort)</para>
|
|
||||||
/// <para>DDT = Internal relay area (int/uint)</para>
|
|
||||||
/// </param>
|
|
||||||
/// <param name="_name">A naming definition for QOL, doesn't effect PLC and is optional</param>
|
|
||||||
public void AddRegister (SpecialAddress _spAddress, RegisterType _type, string _name = null) {
|
|
||||||
|
|
||||||
//as bool registers
|
|
||||||
Registers.Add(new BRegister(_spAddress, _type, _name));
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
internal void AddRegister (Type _colType, SpecialAddress _spAddress, RegisterType _type, string _name = null) {
|
|
||||||
|
|
||||||
var reg = new BRegister(_spAddress, _type, _name);
|
|
||||||
|
|
||||||
reg.collectionType = _colType;
|
|
||||||
|
|
||||||
//as bool registers
|
|
||||||
Registers.Add(reg);
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adds a PLC memory register to the watchlist <para/>
|
|
||||||
/// The registers can be read back by attaching <see cref="WithPoller"/>
|
|
||||||
/// </summary>
|
|
||||||
/// <typeparam name="T">
|
|
||||||
/// The type of the register translated from C# to IEC 61131-3 types
|
|
||||||
/// <para>C# ------ IEC</para>
|
|
||||||
/// <para>short => INT/WORD</para>
|
|
||||||
/// <para>ushort => UINT</para>
|
|
||||||
/// <para>int => DOUBLE</para>
|
|
||||||
/// <para>uint => UDOUBLE</para>
|
|
||||||
/// <para>float => REAL</para>
|
|
||||||
/// <para>string => STRING</para>
|
|
||||||
/// </typeparam>
|
|
||||||
/// <param name="_name">A naming definition for QOL, doesn't effect PLC and is optional</param>
|
|
||||||
/// <param name="_address">The address of the register in the PLCs memory</param>
|
|
||||||
/// <param name="_length">The length of the string (Can be ignored for other types)</param>
|
|
||||||
public void AddRegister<T>(int _address, int _length = 1, string _name = null) {
|
|
||||||
|
|
||||||
Type regType = typeof(T);
|
|
||||||
|
|
||||||
if (regType != typeof(string) && _length != 1) {
|
|
||||||
throw new NotSupportedException($"_lenght parameter only allowed for register of type string");
|
|
||||||
}
|
|
||||||
|
|
||||||
IRegister toAdd;
|
|
||||||
|
|
||||||
if (regType == typeof(short)) {
|
|
||||||
toAdd = new NRegister<short>(_address, _name);
|
|
||||||
} else if (regType == typeof(ushort)) {
|
|
||||||
toAdd = new NRegister<ushort>(_address, _name);
|
|
||||||
} else if (regType == typeof(int)) {
|
|
||||||
toAdd = new NRegister<int>(_address, _name);
|
|
||||||
} else if (regType == typeof(uint)) {
|
|
||||||
toAdd = new NRegister<uint>(_address, _name);
|
|
||||||
} else if (regType == typeof(float)) {
|
|
||||||
toAdd = new NRegister<float>(_address, _name);
|
|
||||||
} else if (regType == typeof(string)) {
|
|
||||||
toAdd = new SRegister(_address, _length, _name);
|
|
||||||
} else if (regType == typeof(TimeSpan)) {
|
|
||||||
toAdd = new NRegister<TimeSpan>(_address, _name);
|
|
||||||
} else if (regType == typeof(bool)) {
|
|
||||||
toAdd = new BRegister(_address, RegisterType.R, _name);
|
|
||||||
} else {
|
|
||||||
throw new NotSupportedException($"The type {regType} is not allowed for Registers \n" +
|
|
||||||
$"Allowed are: short, ushort, int, uint, float and string");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (Registers.Any(x => x.GetRegisterPLCName() == toAdd.GetRegisterPLCName())) {
|
|
||||||
throw new NotSupportedException($"Cannot add a register multiple times, " +
|
|
||||||
$"make sure that all register attributes or AddRegister assignments have different adresses.");
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//Internal register adding for auto register collection building
|
//Internal register adding for auto register collection building
|
||||||
internal void AddRegister<T> (Type _colType, int _address, PropertyInfo boundProp, int _length = 1, bool _isBitwise = false, Type _enumType = null) {
|
internal void AddRegister<T> (Type _colType, int _address, PropertyInfo boundProp, int _length = 1, bool _isBitwise = false, Type _enumType = null) {
|
||||||
|
|
||||||
@@ -405,7 +245,7 @@ namespace MewtocolNet {
|
|||||||
} else if (regType == typeof(TimeSpan)) {
|
} else if (regType == typeof(TimeSpan)) {
|
||||||
reg = new NRegister<TimeSpan>(_address, propName).WithCollectionType(_colType);
|
reg = new NRegister<TimeSpan>(_address, propName).WithCollectionType(_colType);
|
||||||
} else if (regType == typeof(bool)) {
|
} else if (regType == typeof(bool)) {
|
||||||
reg = new BRegister(_address, RegisterType.R, propName).WithCollectionType(_colType);
|
reg = new BRegister(IOType.R, 0x0, _address,propName).WithCollectionType(_colType);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (reg == null) {
|
if (reg == null) {
|
||||||
|
|||||||
@@ -239,6 +239,24 @@ namespace MewtocolNet {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the register type is non numeric
|
||||||
|
/// </summary>
|
||||||
|
internal static bool IsBoolean (this RegisterType type) {
|
||||||
|
|
||||||
|
return type == RegisterType.X || type == RegisterType.Y || type == RegisterType.R;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Checks if the register type is an physical in or output of the plc
|
||||||
|
/// </summary>
|
||||||
|
internal static bool IsPhysicalInOutType (this RegisterType type) {
|
||||||
|
|
||||||
|
return type == RegisterType.X || type == RegisterType.Y;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -17,6 +17,8 @@ using System.Threading;
|
|||||||
using MewtocolNet.Queue;
|
using MewtocolNet.Queue;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Timers;
|
using System.Timers;
|
||||||
|
using System.Data;
|
||||||
|
using System.Xml.Linq;
|
||||||
|
|
||||||
namespace MewtocolNet
|
namespace MewtocolNet
|
||||||
{
|
{
|
||||||
@@ -437,11 +439,10 @@ namespace MewtocolNet
|
|||||||
if (attr is RegisterAttribute cAttribute) {
|
if (attr is RegisterAttribute cAttribute) {
|
||||||
|
|
||||||
if (prop.PropertyType == typeof(bool) && cAttribute.AssignedBitIndex == -1) {
|
if (prop.PropertyType == typeof(bool) && cAttribute.AssignedBitIndex == -1) {
|
||||||
if (cAttribute.SpecialAddress == SpecialAddress.None) {
|
|
||||||
AddRegister(collection.GetType(), cAttribute.MemoryArea, cAttribute.RegisterType, _name: propName);
|
//add bool register non bit assgined
|
||||||
} else {
|
Registers.Add(new BRegister((IOType)(int)cAttribute.RegisterType, cAttribute.SpecialAddress, cAttribute.MemoryArea, _name: propName).WithCollectionType(collection.GetType()));
|
||||||
AddRegister(collection.GetType(), cAttribute.SpecialAddress, cAttribute.RegisterType, _name: propName);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (prop.PropertyType == typeof(short)) {
|
if (prop.PropertyType == typeof(short)) {
|
||||||
@@ -738,7 +739,7 @@ namespace MewtocolNet
|
|||||||
Match m = errorcheck.Match(response.ToString());
|
Match m = errorcheck.Match(response.ToString());
|
||||||
if (m.Success) {
|
if (m.Success) {
|
||||||
string eCode = m.Groups[1].Value;
|
string eCode = m.Groups[1].Value;
|
||||||
string eDes = Links.LinkedData.ErrorCodes[Convert.ToInt32(eCode)];
|
string eDes = Links.CodeDescriptions.Error[Convert.ToInt32(eCode)];
|
||||||
Console.ForegroundColor = ConsoleColor.Red;
|
Console.ForegroundColor = ConsoleColor.Red;
|
||||||
Console.WriteLine($"Response is: {response}");
|
Console.WriteLine($"Response is: {response}");
|
||||||
Logger.Log($"Error on command {_msg.Replace("\r", "")} the PLC returned error code: {eCode}, {eDes}", LogLevel.Error);
|
Logger.Log($"Error on command {_msg.Replace("\r", "")} the PLC returned error code: {eCode}, {eDes}", LogLevel.Error);
|
||||||
|
|||||||
@@ -23,17 +23,16 @@ namespace MewtocolNet.RegisterAttributes {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines the behavior of a register property
|
/// Defines the behavior of a register property
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[AttributeUsage(AttributeTargets.Property)]
|
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
|
||||||
public class RegisterAttribute : Attribute {
|
public class RegisterAttribute : Attribute {
|
||||||
|
|
||||||
internal int MemoryArea;
|
internal int MemoryArea;
|
||||||
internal int StringLength;
|
internal int StringLength;
|
||||||
internal RegisterType RegisterType;
|
internal RegisterType RegisterType;
|
||||||
internal SpecialAddress SpecialAddress = SpecialAddress.None;
|
internal byte SpecialAddress = 0x0;
|
||||||
internal BitCount BitCount;
|
internal BitCount BitCount;
|
||||||
internal int AssignedBitIndex = -1;
|
internal int AssignedBitIndex = -1;
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attribute for string type or numeric registers
|
/// Attribute for string type or numeric registers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -49,30 +48,21 @@ namespace MewtocolNet.RegisterAttributes {
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attribute for boolean registers
|
/// Attribute for boolean registers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="memoryArea">The area in the plcs memory</param>
|
public RegisterAttribute(IOType type, byte spAdress = 0x0) {
|
||||||
/// <param name="type">The type of boolean register</param>
|
|
||||||
public RegisterAttribute (int memoryArea, RegisterType type) {
|
|
||||||
|
|
||||||
if (type.ToString().StartsWith("DT"))
|
MemoryArea = 0;
|
||||||
throw new NotSupportedException("DT types are not supported for attribute register setups because the number type is casted automatically");
|
RegisterType = (RegisterType)(int)type;
|
||||||
|
SpecialAddress = spAdress;
|
||||||
MemoryArea = memoryArea;
|
|
||||||
RegisterType = type;
|
|
||||||
SpecialAddress = SpecialAddress.None;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Attribute for boolean registers
|
/// Attribute for boolean registers
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="spAdress">The special area in the plcs memory</param>
|
public RegisterAttribute (IOType type, int memoryArea, byte spAdress = 0x0) {
|
||||||
/// <param name="type">The type of boolean register</param>
|
|
||||||
public RegisterAttribute (RegisterType type, SpecialAddress spAdress) {
|
|
||||||
|
|
||||||
if (type.ToString().StartsWith("DT"))
|
MemoryArea = memoryArea;
|
||||||
throw new NotSupportedException("DT types are not supported for attribute register setups because the number type is casted automatically");
|
RegisterType = (RegisterType)(int)type;
|
||||||
|
|
||||||
RegisterType = type;
|
|
||||||
SpecialAddress = spAdress;
|
SpecialAddress = spAdress;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
26
MewtocolNet/Mewtocol/RegisterBuilder.cs
Normal file
26
MewtocolNet/Mewtocol/RegisterBuilder.cs
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace MewtocolNet.Mewtocol {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains useful tools for register creation
|
||||||
|
/// </summary>
|
||||||
|
public static class RegisterBuilder {
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parses a register from its PLC name
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="name">The name, fe. DT100</param>
|
||||||
|
/// <param name="reg">An <see cref="IRegister"/> or null if </param>
|
||||||
|
/// <returns>True if successfully parsed</returns>
|
||||||
|
//public static bool TryBuildFromName (string name, out IRegister reg) {
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
//}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@@ -7,64 +7,62 @@ using System.Threading.Tasks;
|
|||||||
namespace MewtocolNet {
|
namespace MewtocolNet {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The special register type
|
/// The register prefixed type
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum RegisterType {
|
public enum RegisterType {
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Physical input as a bool (Relay)
|
/// Physical input as a bool (Relay)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
X,
|
X = 0,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Physical output as a bool (Relay)
|
/// Physical output as a bool (Relay)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Y,
|
Y = 1,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Internal as a bool (Relay)
|
/// Internal as a bool (Relay)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
R,
|
R = 2,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data area as a short (Register)
|
/// Data area as a short (Register)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DT_short,
|
DT_short = 3,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Data area as an unsigned short (Register)
|
/// Data area as an unsigned short (Register)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DT_ushort,
|
DT_ushort = 4,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Double data area as an integer (Register)
|
/// Double data area as an integer (Register)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DDT_int,
|
DDT_int = 5,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Double data area as an unsigned integer (Register)
|
/// Double data area as an unsigned integer (Register)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DDT_uint,
|
DDT_uint = 6,
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Double data area as an floating point number (Register)
|
/// Double data area as an floating point number (Register)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DDT_float,
|
DDT_float = 7,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The special input / output channel address
|
/// The type of an input/output register
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum SpecialAddress {
|
public enum IOType {
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// No defined
|
/// Physical input as a bool (Relay)
|
||||||
/// </summary>
|
/// </summary>
|
||||||
None,
|
X = 0,
|
||||||
A = -10,
|
/// <summary>
|
||||||
B = -11,
|
/// Physical output as a bool (Relay)
|
||||||
C = -12,
|
/// </summary>
|
||||||
D = -13,
|
Y = 1,
|
||||||
E = -14,
|
/// <summary>
|
||||||
F = -15,
|
/// Internal relay
|
||||||
|
/// </summary>
|
||||||
#pragma warning restore
|
R = 2,
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Data;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using MewtocolNet;
|
using MewtocolNet;
|
||||||
|
|
||||||
@@ -22,8 +23,6 @@ namespace MewtocolNet.Registers {
|
|||||||
|
|
||||||
internal RegisterType RegType { get; private set; }
|
internal RegisterType RegType { get; private set; }
|
||||||
|
|
||||||
internal SpecialAddress SpecialAddress { get; private set; }
|
|
||||||
|
|
||||||
internal Type collectionType;
|
internal Type collectionType;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -44,50 +43,46 @@ namespace MewtocolNet.Registers {
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name => name;
|
public string Name => name;
|
||||||
|
|
||||||
internal int memoryAdress;
|
internal int memoryAddress;
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The registers memory adress if not a special register
|
/// The registers memory adress if not a special register
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int MemoryAddress => memoryAdress;
|
public int MemoryAddress => memoryAddress;
|
||||||
|
|
||||||
|
internal byte specialAddress;
|
||||||
|
/// <summary>
|
||||||
|
/// The registers memory adress if not a special register
|
||||||
|
/// </summary>
|
||||||
|
public byte SpecialAddress => specialAddress;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Defines a register containing a number
|
/// Creates a new boolean register
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="_address">Memory start adress max 99999</param>
|
/// <param name="_io">The io type prefix</param>
|
||||||
/// <param name="_type">Type of boolean register</param>
|
/// <param name="_spAddress">The special address</param>
|
||||||
/// <param name="_name">Name of the register</param>
|
/// <param name="_areaAdress">The area special address</param>
|
||||||
public BRegister (int _address, RegisterType _type = RegisterType.R, string _name = null) {
|
/// <param name="_name">The custom name</param>
|
||||||
|
/// <exception cref="NotSupportedException"></exception>
|
||||||
|
/// <exception cref="Exception"></exception>
|
||||||
|
public BRegister (IOType _io, byte _spAddress = 0x0, int _areaAdress = 0, string _name = null) {
|
||||||
|
|
||||||
if (_address > 99999) throw new NotSupportedException("Memory addresses cant be greater than 99999");
|
if (_areaAdress < 0)
|
||||||
|
throw new NotSupportedException("The area address cant be negative");
|
||||||
|
|
||||||
if (_type != RegisterType.X && _type != RegisterType.Y && _type != RegisterType.R)
|
if(_io == IOType.R && _areaAdress >= 512)
|
||||||
throw new NotSupportedException("The register type cant be numeric, use X, Y or R");
|
throw new NotSupportedException("R area addresses cant be greater than 511");
|
||||||
|
|
||||||
memoryAdress = _address;
|
if ((_io == IOType.X || _io == IOType.Y) && _areaAdress >= 110)
|
||||||
|
throw new NotSupportedException("XY area addresses cant be greater than 110");
|
||||||
|
|
||||||
|
if (_spAddress > 0xF)
|
||||||
|
throw new NotSupportedException("Special address cant be greater 15 or 0xF");
|
||||||
|
|
||||||
|
memoryAddress = (int)_areaAdress;
|
||||||
|
specialAddress = _spAddress;
|
||||||
name = _name;
|
name = _name;
|
||||||
|
|
||||||
RegType = _type;
|
RegType = (RegisterType)(int)_io;
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Defines a register containing a number
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="_address">Memory start adress max 99999</param>
|
|
||||||
/// <param name="_type">Type of boolean register</param>
|
|
||||||
/// <param name="_name">Name of the register</param>
|
|
||||||
public BRegister (SpecialAddress _address, RegisterType _type = RegisterType.R, string _name = null) {
|
|
||||||
|
|
||||||
if (_address == SpecialAddress.None)
|
|
||||||
throw new NotSupportedException("Special address cant be none");
|
|
||||||
|
|
||||||
if (_type != RegisterType.X && _type != RegisterType.Y && _type != RegisterType.R)
|
|
||||||
throw new NotSupportedException("The register type cant be numeric, use X, Y or R");
|
|
||||||
|
|
||||||
SpecialAddress = _address;
|
|
||||||
name = _name;
|
|
||||||
|
|
||||||
RegType = _type;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -105,11 +100,12 @@ namespace MewtocolNet.Registers {
|
|||||||
|
|
||||||
//build area code from register type
|
//build area code from register type
|
||||||
StringBuilder asciistring = new StringBuilder(RegType.ToString());
|
StringBuilder asciistring = new StringBuilder(RegType.ToString());
|
||||||
if(SpecialAddress == SpecialAddress.None) {
|
|
||||||
asciistring.Append(MemoryAddress.ToString().PadLeft(4, '0'));
|
string memPadded = MemoryAddress.ToString().PadLeft(4, '0');
|
||||||
} else {
|
string sp = SpecialAddress.ToString("X1");
|
||||||
asciistring.Append(SpecialAddress.ToString().PadLeft(4, '0'));
|
|
||||||
}
|
asciistring.Append(memPadded);
|
||||||
|
asciistring.Append(sp);
|
||||||
|
|
||||||
return asciistring.ToString();
|
return asciistring.ToString();
|
||||||
|
|
||||||
@@ -125,9 +121,6 @@ namespace MewtocolNet.Registers {
|
|||||||
|
|
||||||
public string GetStartingMemoryArea() {
|
public string GetStartingMemoryArea() {
|
||||||
|
|
||||||
if (SpecialAddress != SpecialAddress.None)
|
|
||||||
return SpecialAddress.ToString();
|
|
||||||
|
|
||||||
return MemoryAddress.ToString();
|
return MemoryAddress.ToString();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -148,8 +141,18 @@ namespace MewtocolNet.Registers {
|
|||||||
|
|
||||||
public string GetRegisterPLCName() {
|
public string GetRegisterPLCName() {
|
||||||
|
|
||||||
if (SpecialAddress != SpecialAddress.None) {
|
var spAdressEnd = SpecialAddress.ToString("X1");
|
||||||
return $"{GetRegisterString()}{SpecialAddress}";
|
|
||||||
|
if (MemoryAddress == 0) {
|
||||||
|
|
||||||
|
return $"{GetRegisterString()}{spAdressEnd}";
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if(MemoryAddress > 0 && SpecialAddress != 0) {
|
||||||
|
|
||||||
|
return $"{GetRegisterString()}{MemoryAddress}{spAdressEnd}";
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return $"{GetRegisterString()}{MemoryAddress}";
|
return $"{GetRegisterString()}{MemoryAddress}";
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>netstandard2.0</TargetFramework>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<PackageId>Mewtocol.NET</PackageId>
|
<PackageId>Mewtocol.NET</PackageId>
|
||||||
<Version>0.7.0</Version>
|
<Version>0.7.1</Version>
|
||||||
<Authors>Felix Weiss</Authors>
|
<Authors>Felix Weiss</Authors>
|
||||||
<Company>Womed</Company>
|
<Company>Womed</Company>
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
|||||||
@@ -21,11 +21,12 @@ namespace MewtocolTests {
|
|||||||
public class TestRegisterCollection : RegisterCollectionBase {
|
public class TestRegisterCollection : RegisterCollectionBase {
|
||||||
|
|
||||||
//corresponds to a R100 boolean register in the PLC
|
//corresponds to a R100 boolean register in the PLC
|
||||||
[Register(1000, RegisterType.R)]
|
//can also be written as R1000 because the last one is a special address
|
||||||
|
[Register(IOType.R, 100, spAdress: 0)]
|
||||||
public bool TestBool1 { get; private set; }
|
public bool TestBool1 { get; private set; }
|
||||||
|
|
||||||
//corresponds to a XD input of the PLC
|
//corresponds to a XD input of the PLC
|
||||||
[Register(RegisterType.X, SpecialAddress.D)]
|
[Register(IOType.X, (byte)0xD)]
|
||||||
public bool TestBoolInputXD { get; private set; }
|
public bool TestBoolInputXD { get; private set; }
|
||||||
|
|
||||||
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
|
//corresponds to a DT1101 - DT1104 string register in the PLC with (STRING[4])
|
||||||
@@ -117,7 +118,7 @@ namespace MewtocolTests {
|
|||||||
var register = interf.GetRegister(nameof(TestRegisterCollection.TestBool1));
|
var register = interf.GetRegister(nameof(TestRegisterCollection.TestBool1));
|
||||||
|
|
||||||
//test generic properties
|
//test generic properties
|
||||||
TestBasicGeneration(register, nameof(TestRegisterCollection.TestBool1), false, 1000, "R1000");
|
TestBasicGeneration(register, nameof(TestRegisterCollection.TestBool1), false, 100, "R100");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ namespace MewtocolTests {
|
|||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
Assert.Equal(expectedData, LinkedData.ErrorCodes);
|
Assert.Equal(expectedData, CodeDescriptions.Error);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ namespace MewtocolTests {
|
|||||||
new NRegister<TimeSpan>(50, _name : null),
|
new NRegister<TimeSpan>(50, _name : null),
|
||||||
};
|
};
|
||||||
|
|
||||||
List<string> expcectedIdents = new List<string> {
|
List<string> expectedIdents = new List<string> {
|
||||||
"D0005000050", //single word register
|
"D0005000050", //single word register
|
||||||
"D0005000050", //single word register
|
"D0005000050", //single word register
|
||||||
"D0005000051", //double word register
|
"D0005000051", //double word register
|
||||||
@@ -39,7 +39,7 @@ namespace MewtocolTests {
|
|||||||
for (int i = 0; i < registers.Count; i++) {
|
for (int i = 0; i < registers.Count; i++) {
|
||||||
|
|
||||||
IRegister? reg = registers[i];
|
IRegister? reg = registers[i];
|
||||||
string expect = expcectedIdents[i];
|
string expect = expectedIdents[i];
|
||||||
|
|
||||||
Assert.Equal(expect, reg.BuildMewtocolQuery());
|
Assert.Equal(expect, reg.BuildMewtocolQuery());
|
||||||
|
|
||||||
@@ -58,25 +58,38 @@ namespace MewtocolTests {
|
|||||||
new NRegister<uint>(80, _name : null),
|
new NRegister<uint>(80, _name : null),
|
||||||
new NRegister<float>(90, _name : null),
|
new NRegister<float>(90, _name : null),
|
||||||
new NRegister<TimeSpan>(100, _name : null),
|
new NRegister<TimeSpan>(100, _name : null),
|
||||||
|
|
||||||
//boolean
|
//boolean
|
||||||
new BRegister(100),
|
new BRegister(IOType.R, 0, 100),
|
||||||
new BRegister(5, RegisterType.X),
|
new BRegister(IOType.X, 5),
|
||||||
new BRegister(SpecialAddress.A, RegisterType.X),
|
new BRegister(IOType.X, 0xA),
|
||||||
|
new BRegister(IOType.X, 0xF, 109),
|
||||||
|
new BRegister(IOType.Y, 0xC, 75),
|
||||||
|
|
||||||
//string
|
//string
|
||||||
new SRegister(999, 5),
|
new SRegister(999, 5),
|
||||||
};
|
};
|
||||||
|
|
||||||
List<string> expcectedIdents = new List<string> {
|
List<string> expcectedIdents = new List<string> {
|
||||||
|
|
||||||
|
//numeric ones
|
||||||
"DT50",
|
"DT50",
|
||||||
"DT60",
|
"DT60",
|
||||||
"DDT70",
|
"DDT70",
|
||||||
"DDT80",
|
"DDT80",
|
||||||
"DDT90",
|
"DDT90",
|
||||||
"DDT100",
|
"DDT100",
|
||||||
|
|
||||||
|
//boolean
|
||||||
"R100",
|
"R100",
|
||||||
"X5",
|
"X5",
|
||||||
"XA",
|
"XA",
|
||||||
|
"X109F",
|
||||||
|
"Y75C",
|
||||||
|
|
||||||
|
//string
|
||||||
"DT999"
|
"DT999"
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//test mewtocol idents
|
//test mewtocol idents
|
||||||
@@ -104,7 +117,7 @@ namespace MewtocolTests {
|
|||||||
|
|
||||||
var ex1 = Assert.Throws<NotSupportedException>(() => {
|
var ex1 = Assert.Throws<NotSupportedException>(() => {
|
||||||
|
|
||||||
new BRegister(100000);
|
new BRegister(IOType.R, _areaAdress: 512);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -112,12 +125,20 @@ namespace MewtocolTests {
|
|||||||
|
|
||||||
var ex2 = Assert.Throws<NotSupportedException>(() => {
|
var ex2 = Assert.Throws<NotSupportedException>(() => {
|
||||||
|
|
||||||
new SRegister(100000, 5);
|
new BRegister(IOType.X, _areaAdress: 110);
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
output.WriteLine(ex2.Message.ToString());
|
output.WriteLine(ex2.Message.ToString());
|
||||||
|
|
||||||
|
var ex3 = Assert.Throws<NotSupportedException>(() => {
|
||||||
|
|
||||||
|
new SRegister(100000, 5);
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
output.WriteLine(ex3.Message.ToString());
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(DisplayName = "Non allowed (Wrong data type)")]
|
[Fact(DisplayName = "Non allowed (Wrong data type)")]
|
||||||
@@ -133,32 +154,6 @@ namespace MewtocolTests {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[Fact(DisplayName = "Non allowed (Wrong bool type address)")]
|
|
||||||
public void WrongDataTypeRegisterBool1 () {
|
|
||||||
|
|
||||||
var ex = Assert.Throws<NotSupportedException>(() => {
|
|
||||||
|
|
||||||
new BRegister(100, RegisterType.DDT_int);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
output.WriteLine(ex.Message.ToString());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
[Fact(DisplayName = "Non allowed (Wrong bool special address)")]
|
|
||||||
public void WrongDataTypeRegisterBool2 () {
|
|
||||||
|
|
||||||
var ex = Assert.Throws<NotSupportedException>(() => {
|
|
||||||
|
|
||||||
new BRegister(SpecialAddress.None, RegisterType.X);
|
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
output.WriteLine(ex.Message.ToString());
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
84
MewtocolTests/TestRegisterParsing.cs
Normal file
84
MewtocolTests/TestRegisterParsing.cs
Normal file
@@ -0,0 +1,84 @@
|
|||||||
|
using MewtocolNet;
|
||||||
|
using MewtocolNet.Mewtocol;
|
||||||
|
using MewtocolNet.Registers;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Xunit;
|
||||||
|
using Xunit.Abstractions;
|
||||||
|
|
||||||
|
namespace MewtocolTests;
|
||||||
|
|
||||||
|
public class TestRegisterParsing {
|
||||||
|
|
||||||
|
private readonly ITestOutputHelper output;
|
||||||
|
|
||||||
|
public TestRegisterParsing (ITestOutputHelper output) {
|
||||||
|
this.output = output;
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(DisplayName = "Parsing as BRegister (Phyiscal Outputs)")]
|
||||||
|
public void TestParsingBRegisterY () {
|
||||||
|
|
||||||
|
var tests = new Dictionary<string, IRegister>() {
|
||||||
|
|
||||||
|
{"Y0", new BRegister(IOType.Y)},
|
||||||
|
{"Y1", new BRegister(IOType.Y, 0x1)},
|
||||||
|
{"Y2", new BRegister(IOType.Y, 0x2)},
|
||||||
|
{"Y3", new BRegister(IOType.Y, 0x3)},
|
||||||
|
{"Y4", new BRegister(IOType.Y, 0x4)},
|
||||||
|
{"Y5", new BRegister(IOType.Y, 0x5)},
|
||||||
|
{"Y6", new BRegister(IOType.Y, 0x6)},
|
||||||
|
{"Y7", new BRegister(IOType.Y, 0x7)},
|
||||||
|
{"Y8", new BRegister(IOType.Y, 0x8)},
|
||||||
|
{"Y9", new BRegister(IOType.Y, 0x9)},
|
||||||
|
|
||||||
|
{"YA", new BRegister(IOType.Y, 0xA)},
|
||||||
|
{"YB", new BRegister(IOType.Y, 0xB)},
|
||||||
|
{"YC", new BRegister(IOType.Y, 0xC)},
|
||||||
|
{"YD", new BRegister(IOType.Y, 0xD)},
|
||||||
|
{"YE", new BRegister(IOType.Y, 0xE)},
|
||||||
|
{"YF", new BRegister(IOType.Y, 0xF)},
|
||||||
|
|
||||||
|
{"Y1A", new BRegister(IOType.Y, 0xA, 1)},
|
||||||
|
{"Y10B", new BRegister(IOType.Y, 0xB, 10)},
|
||||||
|
{"Y109C", new BRegister(IOType.Y, 0xC, 109)},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact(DisplayName = "Parsing as BRegister (Phyiscal Inputs)")]
|
||||||
|
public void TestParsingBRegisterX () {
|
||||||
|
|
||||||
|
var tests = new Dictionary<string, IRegister>() {
|
||||||
|
|
||||||
|
{"X0", new BRegister(IOType.X)},
|
||||||
|
{"X1", new BRegister(IOType.X, 0x1)},
|
||||||
|
{"X2", new BRegister(IOType.X, 0x2)},
|
||||||
|
{"X3", new BRegister(IOType.X, 0x3)},
|
||||||
|
{"X4", new BRegister(IOType.X, 0x4)},
|
||||||
|
{"X5", new BRegister(IOType.X, 0x5)},
|
||||||
|
{"X6", new BRegister(IOType.X, 0x6)},
|
||||||
|
{"X7", new BRegister(IOType.X, 0x7)},
|
||||||
|
{"X8", new BRegister(IOType.X, 0x8)},
|
||||||
|
{"X9", new BRegister(IOType.X, 0x9)},
|
||||||
|
|
||||||
|
{"XA", new BRegister(IOType.X, 0xA)},
|
||||||
|
{"XB", new BRegister(IOType.X, 0xB)},
|
||||||
|
{"XC", new BRegister(IOType.X, 0xC)},
|
||||||
|
{"XD", new BRegister(IOType.X, 0xD)},
|
||||||
|
{"XE", new BRegister(IOType.X, 0xE)},
|
||||||
|
{"XF", new BRegister(IOType.X, 0xF)},
|
||||||
|
|
||||||
|
{"X1A", new BRegister(IOType.X, 0xA, 1)},
|
||||||
|
{"X10B", new BRegister(IOType.X, 0xB, 10)},
|
||||||
|
{"X109C", new BRegister(IOType.X, 0xC, 109)},
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user