Skip to content

Commit

Permalink
Merge pull request #51 from ChrisPulman/AddPLCtypes
Browse files Browse the repository at this point in the history
Update and Add PLC Types
  • Loading branch information
ChrisPulman authored Feb 2, 2024
2 parents 53daf09 + 2ad0f1c commit e7d773d
Show file tree
Hide file tree
Showing 23 changed files with 1,708 additions and 450 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -18,24 +18,38 @@ internal static class Conversion
public static int BinStringToInt32(this string txt)
{
var ret = 0;
for (var cnt = txt.Length - 1; cnt >= 0; cnt += -1)

for (var i = 0; i < txt.Length; i++)
{
if (int.Parse(txt.Substring(cnt, 1)) == 1)
{
ret += (int)Math.Pow(2, txt.Length - 1 - cnt);
}
ret = (ret << 1) | ((txt[i] == '1') ? 1 : 0);
}

return ret;
}

/// <summary>
/// Converts a binary string to a byte. Can return null.
/// </summary>
/// <param name="txt">The text.</param>
/// <returns>
/// A byte.
/// </returns>
public static byte? BinStringToByte(this string txt) => txt.Length == 8 ? (byte)BinStringToInt32(txt) : null;

/// <summary>
/// Converts from DWord (DBD) to double.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A double.</returns>
public static double ConvertToDouble(this uint input) => LReal.FromByteArray(DWord.ToByteArray(input));

/// <summary>
/// Converts from DWord (DBD) to float.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A float.</returns>
public static float ConvertToFloat(this uint input) => Real.FromByteArray(DWord.ToByteArray(input));

/// <summary>
/// Converts from uint value to int value; it's used to retrieve negative values from DBDs.
/// </summary>
Expand All @@ -57,6 +71,13 @@ public static int BinStringToInt32(this string txt)
/// <returns>A uint.</returns>
public static uint ConvertToUInt(this float input) => DWord.FromByteArray(LReal.ToByteArray(input));

/// <summary>
/// Converts from Int32 value to UInt32 value; it's used to pass negative values to DBDs.
/// </summary>
/// <param name="input">The input.</param>
/// <returns>A uint.</returns>
public static uint ConvertToUInt(this int input) => uint.Parse(input.ToString("X"), NumberStyles.HexNumber);

/// <summary>
/// Converts from short value to ushort value; it's used to pass negative values to DWs.
/// </summary>
Expand All @@ -79,6 +100,39 @@ public static bool SelectBit(this byte data, int bitPosition)
return result != 0;
}

/// <summary>
/// Helper to set a bit value to the given byte at the bit index.
/// <br/>
/// <example>
/// Set the bit at index 4:
/// <code>
/// byte data = 0;
/// data.SetBit(4, true);
/// </code>
/// </example>
/// </summary>
/// <param name="data">The data to be modified.</param>
/// <param name="index">The zero-based index of the bit to set.</param>
/// <param name="value">The Boolean value to assign to the bit.</param>
public static void SetBit(this ref byte data, int index, bool value)
{
if ((uint)index > 7)
{
return;
}

if (value)
{
var mask = (byte)(1 << index);
data |= mask;
}
else
{
var mask = (byte)~(1 << index);
data &= mask;
}
}

/// <summary>
/// Converts the value to a binary string.
/// </summary>
Expand Down
2 changes: 2 additions & 0 deletions src/S7PlcRx/Core/S7SocketRx.cs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@
using System.Reactive.Subjects;
using S7PlcRx.Enums;
using S7PlcRx.PlcTypes;
using DateTime = System.DateTime;
using TimeSpan = System.TimeSpan;

namespace S7PlcRx.Core;

Expand Down
File renamed without changes.
20 changes: 20 additions & 0 deletions src/S7PlcRx/Enums/S7StringType.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace S7PlcRx.Enums;

/// <summary>
/// String type.
/// </summary>
public enum S7StringType
{
/// <summary>
/// ASCII string.
/// </summary>
S7String = VarType.S7String,

/// <summary>
/// Unicode string.
/// </summary>
S7WString = VarType.S7WString
}
30 changes: 30 additions & 0 deletions src/S7PlcRx/Enums/VarType.cs
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,16 @@ internal enum VarType
/// </summary>
String,

/// <summary>
/// S7 String variable type (variable).
/// </summary>
S7String,

/// <summary>
/// S7 WString variable type (variable).
/// </summary>
S7WString,

/// <summary>
/// The timer.
/// </summary>
Expand All @@ -62,4 +72,24 @@ internal enum VarType
/// The counter.
/// </summary>
Counter,

/// <summary>
/// DateTIme variable type.
/// </summary>
DateTime,

/// <summary>
/// IEC date (legacy) variable type.
/// </summary>
Date,

/// <summary>
/// DateTimeLong variable type.
/// </summary>
DateTimeLong,

/// <summary>
/// S7 TIME variable type - serialized as S7 DInt and deserialized as C# TimeSpan.
/// </summary>
Time
}
19 changes: 9 additions & 10 deletions src/S7PlcRx/ITag.cs
Original file line number Diff line number Diff line change
@@ -1,17 +1,16 @@
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace S7PlcRx
namespace S7PlcRx;

/// <summary>
/// ITag.
/// </summary>
public interface ITag
{
/// <summary>
/// ITag.
/// Sets the do not poll.
/// </summary>
public interface ITag
{
/// <summary>
/// Sets the do not poll.
/// </summary>
/// <param name="value">if set to <c>true</c> [value].</param>
void SetDoNotPoll(bool value);
}
/// <param name="value">if set to <c>true</c> [value].</param>
void SetDoNotPoll(bool value);
}
59 changes: 59 additions & 0 deletions src/S7PlcRx/PlcException.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using S7PlcRx.Enums;

namespace S7PlcRx;

/// <summary>
/// PlcException.
/// </summary>
/// <seealso cref="System.Exception" />
[Serializable]
[System.Diagnostics.CodeAnalysis.SuppressMessage("Roslynator", "RCS1194:Implement exception constructors", Justification = "Not desired in this instance.")]
public class PlcException : Exception
{
/// <summary>
/// Initializes a new instance of the <see cref="PlcException"/> class.
/// </summary>
/// <param name="errorCode">The error code.</param>
public PlcException(ErrorCode errorCode)
: this(errorCode, $"PLC communication failed with error '{errorCode}'.")
{
}

/// <summary>
/// Initializes a new instance of the <see cref="PlcException"/> class.
/// </summary>
/// <param name="errorCode">The error code.</param>
/// <param name="innerException">The inner exception.</param>
public PlcException(ErrorCode errorCode, Exception? innerException)
: this(errorCode, innerException?.Message, innerException)
{
}

/// <summary>
/// Initializes a new instance of the <see cref="PlcException"/> class.
/// </summary>
/// <param name="errorCode">The error code.</param>
/// <param name="message">The message.</param>
public PlcException(ErrorCode errorCode, string? message)
: base(message) => ErrorCode = errorCode;

/// <summary>
/// Initializes a new instance of the <see cref="PlcException"/> class.
/// </summary>
/// <param name="errorCode">The error code.</param>
/// <param name="message">The message.</param>
/// <param name="inner">The inner.</param>
public PlcException(ErrorCode errorCode, string? message, Exception? inner)
: base(message, inner) => ErrorCode = errorCode;

/// <summary>
/// Gets the error code.
/// </summary>
/// <value>
/// The error code.
/// </value>
public ErrorCode ErrorCode { get; }
}
64 changes: 64 additions & 0 deletions src/S7PlcRx/PlcTypes/Bit.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

using System.Collections;

namespace S7PlcRx.PlcTypes;

/// <summary>
/// Contains the conversion methods to convert Bit from S7 plc to C#.
/// </summary>
public static class Bit
{
/// <summary>
/// Converts a Bit to bool.
/// </summary>
/// <param name="v">The v.</param>
/// <param name="bitAdr">The bit adr.</param>
/// <returns>
/// A bool.
/// </returns>
public static bool FromByte(byte v, byte bitAdr) => (v & (1 << bitAdr)) != 0;

/// <summary>
/// Converts an array of bytes to a BitArray.
/// </summary>
/// <param name="bytes">The bytes to convert.</param>
/// <returns>
/// A BitArray with the same number of bits and equal values as <paramref name="bytes" />.
/// </returns>
public static BitArray ToBitArray(byte[] bytes) => ToBitArray(bytes, bytes?.Length * 8);

/// <summary>
/// Converts an array of bytes to a BitArray.
/// </summary>
/// <param name="bytes">The bytes to convert.</param>
/// <param name="length">The number of bits to return.</param>
/// <returns>A BitArray with <paramref name="length"/> bits.</returns>
public static BitArray ToBitArray(byte[] bytes, int? length)
{
if (length == null)
{
throw new ArgumentNullException(nameof(length));
}

if (bytes == null)
{
throw new ArgumentNullException(nameof(bytes));
}

if (length > bytes?.Length * 8)
{
throw new ArgumentException($"Not enough data in bytes to return {length} bits.", nameof(bytes));
}

var bitArr = new BitArray(bytes!);
var bools = new bool[length.Value];
for (var i = 0; i < length; i++)
{
bools[i] = bitArr[i];
}

return new BitArray(bools);
}
}
60 changes: 60 additions & 0 deletions src/S7PlcRx/PlcTypes/Boolean.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
// Copyright (c) Chris Pulman. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.

namespace S7PlcRx.PlcTypes;

/// <summary>
/// Contains the methods to read, set and reset bits inside bytes.
/// </summary>
public static class Boolean
{
/// <summary>
/// Returns the value of a bit in a bit, given the address of the bit.
/// </summary>
/// <param name="value">The value.</param>
/// <param name="bit">The bit.</param>
/// <returns>A bool.</returns>
public static bool GetValue(byte value, int bit) => (value & (1 << bit)) != 0;

/// <summary>
/// Sets the value of a bit to 1 (true), given the address of the bit. Returns
/// a copy of the value with the bit set.
/// </summary>
/// <param name="value">The input value to modify.</param>
/// <param name="bit">The index (zero based) of the bit to set.</param>
/// <returns>The modified value with the bit at index set.</returns>
public static byte SetBit(byte value, int bit)
{
SetBit(ref value, bit);

return value;
}

/// <summary>
/// Sets the value of a bit to 1 (true), given the address of the bit.
/// </summary>
/// <param name="value">The value to modify.</param>
/// <param name="bit">The index (zero based) of the bit to set.</param>
public static void SetBit(ref byte value, int bit) => value = (byte)((value | (1 << bit)) & 0xFF);

/// <summary>
/// Resets the value of a bit to 0 (false), given the address of the bit. Returns
/// a copy of the value with the bit cleared.
/// </summary>
/// <param name="value">The input value to modify.</param>
/// <param name="bit">The index (zero based) of the bit to clear.</param>
/// <returns>The modified value with the bit at index cleared.</returns>
public static byte ClearBit(byte value, int bit)
{
ClearBit(ref value, bit);

return value;
}

/// <summary>
/// Resets the value of a bit to 0 (false), given the address of the bit.
/// </summary>
/// <param name="value">The input value to modify.</param>
/// <param name="bit">The index (zero based) of the bit to clear.</param>
public static void ClearBit(ref byte value, int bit) => value = (byte)(value & ~(1 << bit) & 0xFF);
}
Loading

0 comments on commit e7d773d

Please sign in to comment.