S7String.cs 3.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980
  1. using System;
  2. using System.Text;
  3. namespace S7.Net.Types
  4. {
  5. /// <summary>
  6. /// Contains the methods to convert from S7 strings to C# strings
  7. /// An S7 String has a preceeding 2 byte header containing its capacity and length
  8. /// </summary>
  9. public static class S7String
  10. {
  11. private static Encoding stringEncoding = Encoding.ASCII;
  12. /// <summary>
  13. /// The Encoding used when serializing and deserializing S7String (Encoding.ASCII by default)
  14. /// </summary>
  15. /// <exception cref="ArgumentNullException">StringEncoding must not be null</exception>
  16. public static Encoding StringEncoding
  17. {
  18. get => stringEncoding;
  19. set => stringEncoding = value ?? throw new ArgumentNullException(nameof(StringEncoding));
  20. }
  21. /// <summary>
  22. /// Converts S7 bytes to a string
  23. /// </summary>
  24. /// <param name="bytes"></param>
  25. /// <returns></returns>
  26. public static string FromByteArray(byte[] bytes)
  27. {
  28. if (bytes.Length < 2)
  29. {
  30. throw new PlcException(ErrorCode.ReadData, "Malformed S7 String / too short");
  31. }
  32. int size = bytes[0];
  33. int length = bytes[1];
  34. if (length > size)
  35. {
  36. throw new PlcException(ErrorCode.ReadData, "Malformed S7 String / length larger than capacity");
  37. }
  38. try
  39. {
  40. return StringEncoding.GetString(bytes, 2, length);
  41. }
  42. catch (Exception e)
  43. {
  44. throw new PlcException(ErrorCode.ReadData,
  45. $"Failed to parse {VarType.S7String} from data. Following fields were read: size: '{size}', actual length: '{length}', total number of bytes (including header): '{bytes.Length}'.",
  46. e);
  47. }
  48. }
  49. /// <summary>
  50. /// Converts a <see cref="T:string"/> to S7 string with 2-byte header.
  51. /// </summary>
  52. /// <param name="value">The string to convert to byte array.</param>
  53. /// <param name="reservedLength">The length (in characters) allocated in PLC for the string.</param>
  54. /// <returns>A <see cref="T:byte[]" /> containing the string header and string value with a maximum length of <paramref name="reservedLength"/> + 2.</returns>
  55. public static byte[] ToByteArray(string? value, int reservedLength)
  56. {
  57. if (value is null)
  58. {
  59. throw new ArgumentNullException(nameof(value));
  60. }
  61. if (reservedLength > 254) throw new ArgumentException($"The maximum string length supported is 254.");
  62. var bytes = StringEncoding.GetBytes(value);
  63. if (bytes.Length > reservedLength) throw new ArgumentException($"The provided string length ({bytes.Length} is larger than the specified reserved length ({reservedLength}).");
  64. var buffer = new byte[2 + reservedLength];
  65. Array.Copy(bytes, 0, buffer, 2, bytes.Length);
  66. buffer[0] = (byte)reservedLength;
  67. buffer[1] = (byte)bytes.Length;
  68. return buffer;
  69. }
  70. }
  71. }