Serialization.cs 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103
  1. using System;
  2. using System.Collections.Generic;
  3. using S7.Net.Types;
  4. namespace S7.Net.Protocol
  5. {
  6. internal static class Serialization
  7. {
  8. public static ushort GetWordAt(IList<byte> buf, int index)
  9. {
  10. return (ushort)((buf[index] << 8) + buf[index]);
  11. }
  12. public static byte[] SerializeDataItem(DataItem dataItem)
  13. {
  14. if (dataItem.Value == null)
  15. {
  16. throw new Exception($"DataItem.Value is null, cannot serialize. StartAddr={dataItem.StartByteAdr} VarType={dataItem.VarType}");
  17. }
  18. if (dataItem.Value is string s)
  19. return dataItem.VarType switch
  20. {
  21. VarType.S7String => S7String.ToByteArray(s, dataItem.Count),
  22. VarType.S7WString => S7WString.ToByteArray(s, dataItem.Count),
  23. _ => Types.String.ToByteArray(s, dataItem.Count)
  24. };
  25. if (dataItem.VarType == VarType.Date)
  26. {
  27. return Date.ToByteArray((System.DateTime)dataItem.Value);
  28. }
  29. return SerializeValue(dataItem.Value);
  30. }
  31. public static byte[] SerializeValue(object value)
  32. {
  33. switch (value.GetType().Name)
  34. {
  35. case "Boolean":
  36. return new[] { (byte)((bool)value ? 1 : 0) };
  37. case "Byte":
  38. return Types.Byte.ToByteArray((byte)value);
  39. case "Int16":
  40. return Types.Int.ToByteArray((Int16)value);
  41. case "UInt16":
  42. return Types.Word.ToByteArray((UInt16)value);
  43. case "Int32":
  44. return Types.DInt.ToByteArray((Int32)value);
  45. case "UInt32":
  46. return Types.DWord.ToByteArray((UInt32)value);
  47. case "Single":
  48. return Types.Real.ToByteArray((float)value);
  49. case "Double":
  50. return Types.LReal.ToByteArray((double)value);
  51. case "DateTime":
  52. return Types.DateTime.ToByteArray((System.DateTime)value);
  53. case "Byte[]":
  54. return (byte[])value;
  55. case "Int16[]":
  56. return Types.Int.ToByteArray((Int16[])value);
  57. case "UInt16[]":
  58. return Types.Word.ToByteArray((UInt16[])value);
  59. case "Int32[]":
  60. return Types.DInt.ToByteArray((Int32[])value);
  61. case "UInt32[]":
  62. return Types.DWord.ToByteArray((UInt32[])value);
  63. case "Single[]":
  64. return Types.Real.ToByteArray((float[])value);
  65. case "Double[]":
  66. return Types.LReal.ToByteArray((double[])value);
  67. case "String":
  68. // Hack: This is backwards compatible with the old code, but functionally it's broken
  69. // if the consumer does not pay attention to string length.
  70. var stringVal = (string)value;
  71. return Types.String.ToByteArray(stringVal, stringVal.Length);
  72. case "DateTime[]":
  73. return Types.DateTime.ToByteArray((System.DateTime[])value);
  74. case "DateTimeLong[]":
  75. return Types.DateTimeLong.ToByteArray((System.DateTime[])value);
  76. default:
  77. throw new InvalidVariableTypeException();
  78. }
  79. }
  80. public static void SetAddressAt(ByteArray buffer, int index, int startByte, byte bitNumber)
  81. {
  82. var start = startByte * 8 + bitNumber;
  83. buffer[index + 2] = (byte)start;
  84. start >>= 8;
  85. buffer[index + 1] = (byte)start;
  86. start >>= 8;
  87. buffer[index] = (byte)start;
  88. }
  89. public static void SetWordAt(ByteArray buffer, int index, ushort value)
  90. {
  91. buffer[index] = (byte)(value >> 8);
  92. buffer[index + 1] = (byte)value;
  93. }
  94. }
  95. }