lixun vor 2 Jahren
Ursprung
Commit
df603f24b7
30 geänderte Dateien mit 1030 neuen und 488 gelöschten Zeilen
  1. 0 19
      src/YSAI.DAQ/YSAI.Can/Properties/PublishProfiles/FolderProfile.pubxml
  2. 4 0
      src/YSAI.DAQ/YSAI.Can/YSAI.Can.csproj
  3. 1 0
      src/YSAI.DAQ/YSAI.Core/interface/only/IS7.cs
  4. 3 13
      src/YSAI.DAQ/YSAI.Core/virtualAddress/VirtualAddressManage.cs
  5. 1 0
      src/YSAI.DAQ/YSAI.Manage.Core/ManageOperate.cs
  6. 59 59
      src/YSAI.DAQ/YSAI.Manage.Core/base/ManageBaseOperate.cs
  7. 11 0
      src/YSAI.DAQ/YSAI.Manage/Controllers/DaqLibOperateController.cs
  8. 0 6
      src/YSAI.DAQ/YSAI.Manage/Properties/PublishProfiles/FolderProfile.pubxml
  9. 1 1
      src/YSAI.DAQ/YSAI.Manage/Properties/launchSettings.json
  10. 2 4
      src/YSAI.DAQ/YSAI.Opc/da/client/OpcDaClientOperate.cs
  11. 3 0
      src/YSAI.DAQ/YSAI.S7/client/S7ClientData.cs
  12. 19 1
      src/YSAI.DAQ/YSAI.S7/client/S7ClientOperate.cs
  13. 224 0
      src/YSAI.DAQ/YSAI.S7/client/S7Unility.cs
  14. 2 0
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/COTP.cs
  15. 6 1
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Enums.cs
  16. 101 13
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/PLCHelpers.cs
  17. 15 1
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/PlcAsynchronous.cs
  18. 14 3
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/PlcSynchronous.cs
  19. 1 0
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/StreamExtensions.cs
  20. 1 0
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/TPKT.cs
  21. 26 11
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/Class.cs
  22. 1 1
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/DateTime.cs
  23. 1 1
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/S7String.cs
  24. 1 1
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/S7WString.cs
  25. 6 4
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/String.cs
  26. 39 12
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/Struct.cs
  27. 97 0
      src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/TimeSpan.cs
  28. 347 0
      src/YSAI.DAQ/YSAI.Test/TestAll.cs
  29. 43 337
      src/YSAI.DAQ/YSAI.TestConsole/Program.cs
  30. 1 0
      src/YSAI.DAQ/YSAI.Unility/ExtensionTool.cs

+ 0 - 19
src/YSAI.DAQ/YSAI.Can/Properties/PublishProfiles/FolderProfile.pubxml

@@ -1,19 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<!--
-https://go.microsoft.com/fwlink/?LinkID=208121.
--->
-<Project>
-  <PropertyGroup>
-    <Configuration>Release</Configuration>
-    <Platform>Any CPU</Platform>
-    <PublishDir>bin\Release\net6.0\publish\win-x86\</PublishDir>
-    <PublishProtocol>FileSystem</PublishProtocol>
-    <_TargetId>Folder</_TargetId>
-    <TargetFramework>net6.0</TargetFramework>
-    <RuntimeIdentifier>win-x86</RuntimeIdentifier>
-    <SelfContained>true</SelfContained>
-    <PublishSingleFile>true</PublishSingleFile>
-    <PublishReadyToRun>false</PublishReadyToRun>
-    <PublishTrimmed>false</PublishTrimmed>
-  </PropertyGroup>
-</Project>

+ 4 - 0
src/YSAI.DAQ/YSAI.Can/YSAI.Can.csproj

@@ -16,4 +16,8 @@
     </Reference>
   </ItemGroup>
 
+  <ItemGroup>
+    <Folder Include="Properties\" />
+  </ItemGroup>
+
 </Project>

+ 1 - 0
src/YSAI.DAQ/YSAI.Core/interface/only/IS7.cs

@@ -3,6 +3,7 @@ using System.Collections.Generic;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using YSAI.Core.data;
 using YSAI.Core.@interface.unify;
 
 namespace YSAI.Core.@interface.only

+ 3 - 13
src/YSAI.DAQ/YSAI.Core/virtualAddress/VirtualAddressManage.cs

@@ -30,7 +30,7 @@ namespace YSAI.Core.virtualAddress
         /// <summary>
         /// 虚拟地址的容器
         /// </summary>
-        private ConcurrentDictionary<string, VirtualAddress> VirtualAddressIocContainer;
+        private ConcurrentDictionary<string, VirtualAddress>? VirtualAddressIocContainer = new ConcurrentDictionary<string, VirtualAddress>();
 
         /// <summary>
         /// 设置虚拟地址,存在则不做操作,不存在则添加
@@ -39,21 +39,11 @@ namespace YSAI.Core.virtualAddress
         /// <returns></returns>
         private void SetVirtualAddress(VirtualAddressData virtualAddressData)
         {
-            //实例化
-            if (VirtualAddressIocContainer == null)
+            //判断是否存在
+            if (!VirtualAddressIocContainer.ContainsKey(virtualAddressData.AddressName))
             {
-                VirtualAddressIocContainer = new ConcurrentDictionary<string, VirtualAddress>();
-
                 add(virtualAddressData);
             }
-            else
-            {
-                //判断是否存在
-                if (!VirtualAddressIocContainer.ContainsKey(virtualAddressData.AddressName))
-                {
-                    add(virtualAddressData);
-                }
-            }
         }
 
         /// <summary>

+ 1 - 0
src/YSAI.DAQ/YSAI.Manage.Core/ManageOperate.cs

@@ -309,6 +309,7 @@ namespace YSAI.Manage.Core
         public void Dispose()
         {
             baseOperate?.Dispose();
+            baseOperate = null;
         }
 
         public OperateResult InitSucceedArray()

+ 59 - 59
src/YSAI.DAQ/YSAI.Manage.Core/base/ManageBaseOperate.cs

@@ -169,7 +169,7 @@ namespace YSAI.Manage.Core.@base
                                 {
                                     if (DBDaqObjArray.ContainsKey(dBData.SN))
                                     {
-                                        FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {dBData.SN} ] 已存在实例对象");
+                                        FaliMessage.Add($"[ {manage.DType} ] [ {dBData.SN} ] 已存在实例对象");
                                     }
                                     else
                                     {
@@ -199,7 +199,7 @@ namespace YSAI.Manage.Core.@base
                                 }
                                 else
                                 {
-                                    FaliMessage.Add($"[ {manage.DType.ToString()} ] 采集实例参数为空");
+                                    FaliMessage.Add($"[ {manage.DType} ] 采集实例参数为空");
                                 }
 
                                 break;
@@ -210,7 +210,7 @@ namespace YSAI.Manage.Core.@base
                                 {
                                     if (ModbusDaqObjArray.ContainsKey(modbusClientData.SN))
                                     {
-                                        FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {modbusClientData.SN} ] 已存在实例对象");
+                                        FaliMessage.Add($"[ {manage.DType} ] [ {modbusClientData.SN} ] 已存在实例对象");
                                     }
                                     else
                                     {
@@ -244,13 +244,13 @@ namespace YSAI.Manage.Core.@base
                                         }
                                         else
                                         {
-                                            FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {modbusClientData.SN} ] {operateResult.Message}");
+                                            FaliMessage.Add($"[ {manage.DType} ] [ {modbusClientData.SN} ] {operateResult.Message}");
                                         }
                                     }
                                 }
                                 else
                                 {
-                                    FaliMessage.Add($"[ {manage.DType.ToString()} ] 采集实例参数为空");
+                                    FaliMessage.Add($"[ {manage.DType} ] 采集实例参数为空");
                                 }
 
                                 break;
@@ -261,7 +261,7 @@ namespace YSAI.Manage.Core.@base
                                 {
                                     if (OpcUaDaqObjArray.ContainsKey(opcUaClientData.SN))
                                     {
-                                        FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcUaClientData.SN} ] 已存在实例对象");
+                                        FaliMessage.Add($"[ {manage.DType} ] [ {opcUaClientData.SN} ] 已存在实例对象");
                                     }
                                     else
                                     {
@@ -272,7 +272,7 @@ namespace YSAI.Manage.Core.@base
                                         operateResult = opcUaClientOperate.Init();
                                         if (!operateResult.State)
                                         {
-                                            FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcUaClientData.SN} ] {operateResult.Message}");
+                                            FaliMessage.Add($"[ {manage.DType} ] [ {opcUaClientData.SN} ] {operateResult.Message}");
                                         }
                                         else
                                         {
@@ -292,7 +292,7 @@ namespace YSAI.Manage.Core.@base
                                             }
                                             else
                                             {
-                                                FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcUaClientData.SN} ] {operateResult.Message}");
+                                                FaliMessage.Add($"[ {manage.DType} ] [ {opcUaClientData.SN} ] {operateResult.Message}");
                                             }
 
                                         }
@@ -300,7 +300,7 @@ namespace YSAI.Manage.Core.@base
                                 }
                                 else
                                 {
-                                    FaliMessage.Add($"[ {manage.DType.ToString()} ] 采集实例参数为空");
+                                    FaliMessage.Add($"[ {manage.DType} ] 采集实例参数为空");
                                 }
 
                                 break;
@@ -312,7 +312,7 @@ namespace YSAI.Manage.Core.@base
                                 {
                                     if (OpcDaDaqObjArray.ContainsKey(opcDaClientData.SN))
                                     {
-                                        FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcDaClientData.SN} ] 已存在实例对象");
+                                        FaliMessage.Add($"[ {manage.DType} ] [ {opcDaClientData.SN} ] 已存在实例对象");
                                     }
                                     else
                                     {
@@ -334,7 +334,7 @@ namespace YSAI.Manage.Core.@base
                                                 operateResult = opcDaClientOperate.AddNode(manage, opcDaClientData.SN, true);
                                                 if (!operateResult.State)
                                                 {
-                                                    FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcDaClientData.SN} ] {operateResult.Message}");
+                                                    FaliMessage.Add($"[ {manage.DType} ] [ {opcDaClientData.SN} ] {operateResult.Message}");
                                                 }
                                                 else
                                                 {
@@ -344,18 +344,18 @@ namespace YSAI.Manage.Core.@base
                                             }
                                             else
                                             {
-                                                FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcDaClientData.SN} ] {operateResult.Message}");
+                                                FaliMessage.Add($"[ {manage.DType} ] [ {opcDaClientData.SN} ] {operateResult.Message}");
                                             }
                                         }
                                         else
                                         {
-                                            FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcDaClientData.SN} ] {operateResult.Message}");
+                                            FaliMessage.Add($"[ {manage.DType} ] [ {opcDaClientData.SN} ] {operateResult.Message}");
                                         }
                                     }
                                 }
                                 else
                                 {
-                                    FaliMessage.Add($"[ {manage.DType.ToString()} ] 采集实例参数为空");
+                                    FaliMessage.Add($"[ {manage.DType} ] 采集实例参数为空");
                                 }
 
                                 break;
@@ -366,7 +366,7 @@ namespace YSAI.Manage.Core.@base
                                 {
                                     if (OpcDaHttpDaqObjArray.ContainsKey(opcDaHttpData.SN))
                                     {
-                                        FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {opcDaHttpData.SN} ] 已存在实例对象");
+                                        FaliMessage.Add($"[ {manage.DType} ] [ {opcDaHttpData.SN} ] 已存在实例对象");
                                     }
                                     else
                                     {
@@ -396,7 +396,7 @@ namespace YSAI.Manage.Core.@base
                                 }
                                 else
                                 {
-                                    FaliMessage.Add($"[ {manage.DType.ToString()} ] 采集实例参数为空");
+                                    FaliMessage.Add($"[ {manage.DType} ] 采集实例参数为空");
                                 }
 
                                 break;
@@ -407,7 +407,7 @@ namespace YSAI.Manage.Core.@base
                                 {
                                     if (S7DaqObjArray.ContainsKey(s7ClientData.SN))
                                     {
-                                        FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {s7ClientData.SN} ] 已存在实例对象");
+                                        FaliMessage.Add($"[ {manage.DType} ] [ {s7ClientData.SN} ] 已存在实例对象");
                                     }
                                     else
                                     {
@@ -440,13 +440,13 @@ namespace YSAI.Manage.Core.@base
                                         }
                                         else
                                         {
-                                            FaliMessage.Add($"[ {manage.DType.ToString()} ] [ {s7ClientData.SN} ] {operateResult.Message}");
+                                            FaliMessage.Add($"[ {manage.DType} ] [ {s7ClientData.SN} ] {operateResult.Message}");
                                         }
                                     }
                                 }
                                 else
                                 {
-                                    FaliMessage.Add($"[ {manage.DType.ToString()} ] 采集实例参数为空");
+                                    FaliMessage.Add($"[ {manage.DType} ] 采集实例参数为空");
                                 }
 
                                 break;
@@ -482,21 +482,21 @@ namespace YSAI.Manage.Core.@base
                     operateResult = OpcUaDaqObjArray[SN].Write(data);
                     if (!operateResult.State)
                     {
-                        return Break("Write", false, $"[ {DType.ToString} ] {operateResult.Message}");
+                        return Break("Write", false, $"[ {DType} ] {operateResult.Message}");
                     }
                     break;
                 case DaqType.OpcDa:
                     operateResult = OpcDaDaqObjArray[SN].Write(data);
                     if (!operateResult.State)
                     {
-                        return Break("Write", false, $"[ {DType.ToString} ] {operateResult.Message}");
+                        return Break("Write", false, $"[ {DType} ] {operateResult.Message}");
                     }
                     break;
                 case DaqType.S7:
                     operateResult = S7DaqObjArray[SN].Write(data);
                     if (!operateResult.State)
                     {
-                        return Break("Write", false, $"[ {DType.ToString} ] {operateResult.Message}");
+                        return Break("Write", false, $"[ {DType} ] {operateResult.Message}");
                     }
                     break;
             }
@@ -595,7 +595,7 @@ namespace YSAI.Manage.Core.@base
 
                         if (addressManage == null)
                         {
-                            return Break("On", false, $"[ {DType.ToString()} ] 地址管理数据为空");
+                            return Break("On", false, $"[ {DType} ] 地址管理数据为空");
                         }
 
                         switch (DType)
@@ -604,7 +604,7 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.Modbus:
@@ -612,7 +612,7 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
 
                                 break;
@@ -620,28 +620,28 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!OpcUaDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.OpcDa:
                                 //判断是否有此实例
                                 if (!OpcDaDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.OpcDaHttp:
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.S7:
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                         }
@@ -662,7 +662,7 @@ namespace YSAI.Manage.Core.@base
                                 operateResult = OpcDaDaqObjArray[SN].UpdateGroupSubscribedState(SN, true);
                                 if (!operateResult.State)
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] {operateResult.Message}");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] {operateResult.Message}");
                                 }
                                 break;
                             case DaqType.DB:
@@ -675,12 +675,12 @@ namespace YSAI.Manage.Core.@base
                                     operateResult = SubscribeObjArray[SN].On();
                                     if (!operateResult.State)
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] {operateResult.Message}");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] {operateResult.Message}");
                                     }
                                 }
                                 else
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 订阅不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 订阅不存在");
                                 }
                                 break;
                         }
@@ -731,42 +731,42 @@ namespace YSAI.Manage.Core.@base
                                     //判断是否有此实例
                                     if (!DBDaqObjArray.ContainsKey(SN))
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                     }
                                     break;
                                 case DaqType.Modbus:
                                     //判断是否有此实例
                                     if (!ModbusDaqObjArray.ContainsKey(SN))
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                     }
                                     break;
                                 case DaqType.OpcUa:
                                     //判断是否有此实例
                                     if (!OpcUaDaqObjArray.ContainsKey(SN))
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                     }
                                     break;
                                 case DaqType.OpcDa:
                                     //判断是否有此实例
                                     if (!OpcDaDaqObjArray.ContainsKey(SN))
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                     }
                                     break;
                                 case DaqType.OpcDaHttp:
                                     //判断是否有此实例
                                     if (!OpcDaHttpDaqObjArray.ContainsKey(SN))
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                     }
                                     break;
                                 case DaqType.S7:
                                     //判断是否有此实例
                                     if (!S7DaqObjArray.ContainsKey(SN))
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                     }
                                     break;
                             }
@@ -797,12 +797,12 @@ namespace YSAI.Manage.Core.@base
                                         operateResult = SubscribeObjArray[SN].Off();
                                         if (!operateResult.State)
                                         {
-                                            return Break("Off", false, $"[ {DType.ToString} ] [ {SN} ] {operateResult.Message}");
+                                            return Break("Off", false, $"[ {DType} ] [ {SN} ] {operateResult.Message}");
                                         }
                                     }
                                     else
                                     {
-                                        return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 订阅不存在");
+                                        return Break("On", false, $"[ {DType} ] [ {SN} ] 订阅不存在");
                                     }
                                     break;
                             }
@@ -853,12 +853,12 @@ namespace YSAI.Manage.Core.@base
                         AddressManage? addressManage = basics.AManages.FirstOrDefault(c => c.DType.Equals(DType) && c.SN.Equals(SN));
                         if (addressManage == null)
                         {
-                            return Break("Read", false, $"[ {DType.ToString()} ] 地址管理数据为空");
+                            return Break("Read", false, $"[ {DType} ] 地址管理数据为空");
                         }
                         AddressDetails? details = addressManage.AddressArray.FirstOrDefault(c => c.AddressName.Equals(AddressName));
                         if (details == null)
                         {
-                            return Break("Read", false, $"[ {DType.ToString()} ] 未查询到({AddressName})地址配置数据");
+                            return Break("Read", false, $"[ {DType} ] 未查询到({AddressName})地址配置数据");
                         }
 
                         switch (DType)
@@ -867,7 +867,7 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.Modbus:
@@ -875,7 +875,7 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
 
                                 break;
@@ -883,28 +883,28 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!OpcUaDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.OpcDa:
                                 //判断是否有此实例
                                 if (!OpcDaDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.OpcDaHttp:
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.S7:
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                         }
@@ -955,7 +955,7 @@ namespace YSAI.Manage.Core.@base
                                 break;
                         }
 
-                        return Break("Read", false, $"[ {DType.ToString()} ] [ {AddressName} ] {operateResult.Message}");
+                        return Break("Read", false, $"[ {DType} ] [ {AddressName} ] {operateResult.Message}");
                     }
                     else
                     {
@@ -993,12 +993,12 @@ namespace YSAI.Manage.Core.@base
                         AddressManage? addressManage = basics.AManages.FirstOrDefault(c => c.DType.Equals(DType) && c.SN.Equals(SN));
                         if (addressManage == null)
                         {
-                            return Break("Write", false, $"[ {DType.ToString()} ] 地址管理数据为空");
+                            return Break("Write", false, $"[ {DType} ] 地址管理数据为空");
                         }
                         AddressDetails? details = addressManage.AddressArray.FirstOrDefault(c => c.AddressName.Equals(AddressName));
                         if (details == null)
                         {
-                            return Break("Write", false, $"[ {DType.ToString()} ] 未查询到({AddressName})地址配置数据");
+                            return Break("Write", false, $"[ {DType} ] 未查询到({AddressName})地址配置数据");
                         }
 
                         switch (DType)
@@ -1007,7 +1007,7 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.Modbus:
@@ -1015,7 +1015,7 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
 
                                 break;
@@ -1023,28 +1023,28 @@ namespace YSAI.Manage.Core.@base
                                 //判断是否有此实例
                                 if (!OpcUaDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.OpcDa:
                                 //判断是否有此实例
                                 if (!OpcDaDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.OpcDaHttp:
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                             case DaqType.S7:
                                 //判断是否有此实例
                                 if (!DBDaqObjArray.ContainsKey(SN))
                                 {
-                                    return Break("On", false, $"[ {DType.ToString} ] [ {SN} ] 实例不存在");
+                                    return Break("On", false, $"[ {DType} ] [ {SN} ] 实例不存在");
                                 }
                                 break;
                         }
@@ -1053,7 +1053,7 @@ namespace YSAI.Manage.Core.@base
                         {
                             case DaqType.OpcDaHttp:
                             case DaqType.DB:
-                                return Break("Write", false, $"[ {DType.ToString} ] 目前不支持写入功能");
+                                return Break("Write", false, $"[ {DType} ] 目前不支持写入功能");
                             case DaqType.Modbus:
                                 ConcurrentDictionary<ushort, object> pairs = new ConcurrentDictionary<ushort, object>();
                                 try
@@ -1083,7 +1083,7 @@ namespace YSAI.Manage.Core.@base
                                 operateResult = ModbusDaqObjArray[SN].Write(pairs);
                                 if (!operateResult.State)
                                 {
-                                    return Break("Write", false, $"[ {DType.ToString} ] {operateResult.Message}");
+                                    return Break("Write", false, $"[ {DType} ] {operateResult.Message}");
                                 }
                                 break;
                             default:

+ 11 - 0
src/YSAI.DAQ/YSAI.Manage/Controllers/DaqLibOperateController.cs

@@ -97,6 +97,17 @@ namespace YSAI.Manage.Controllers
         {
             return manageOperate.Init();
         }
+
+        /// <summary>
+        /// 释放所有已初始化的实例
+        /// </summary>
+        /// <returns></returns>
+        [HttpPost]
+        public IActionResult InitDispose()
+        {
+            manageOperate.Dispose();
+            return Ok();
+        }
         /// <summary>
         /// 打开
         /// </summary>

+ 0 - 6
src/YSAI.DAQ/YSAI.Manage/Properties/PublishProfiles/FolderProfile.pubxml

@@ -13,11 +13,5 @@ https://go.microsoft.com/fwlink/?LinkID=208121.
     <PublishUrl>bin\Release\net6.0\publish\</PublishUrl>
     <WebPublishMethod>FileSystem</WebPublishMethod>
     <_TargetId>Folder</_TargetId>
-    <SiteUrlToLaunchAfterPublish />
-    <TargetFramework>net6.0</TargetFramework>
-    <RuntimeIdentifier>win-x86</RuntimeIdentifier>
-    <PublishSingleFile>true</PublishSingleFile>
-    <ProjectGuid>6e9667c0-303c-472d-949b-60f812e6c659</ProjectGuid>
-    <SelfContained>true</SelfContained>
   </PropertyGroup>
 </Project>

+ 1 - 1
src/YSAI.DAQ/YSAI.Manage/Properties/launchSettings.json

@@ -14,7 +14,7 @@
       "dotnetRunMessages": true,
       "launchBrowser": true,
       "launchUrl": "swagger",
-      "applicationUrl": "https://192.168.2.38:19876;http://192.168.2.38:19875",
+      "applicationUrl": "https://0.0.0.0:19876;http://0.0.0.0:19875",
       "environmentVariables": {
         "ASPNETCORE_ENVIRONMENT": "Development"
       }

+ 2 - 4
src/YSAI.DAQ/YSAI.Opc/da/client/OpcDaClientOperate.cs

@@ -600,20 +600,19 @@ namespace YSAI.Opc.da.client
             {
                 if (opcDaClient != null && opcDaClient.IsConnected)
                 {
-                    opcDaClient.Disconnect();
                     opcDaClient.Dispose();
                     opcDaClient = null;
                 }
                 else
                 {
-                    return Break("On", false, "未连接");
+                    return Break("Off", false, "未连接");
                 }
             }
             catch (Exception ex)
             {
                 return Break("Off", false, ex.Message);
             }
-            return Break("On", false, "关闭失败");
+            return Break("Off", false, "关闭失败");
         }
 
         public Task<OperateResult> ReadAsync(Address address)
@@ -696,7 +695,6 @@ namespace YSAI.Opc.da.client
             {
                 return Break("Read", false, ex.Message);
             }
-            return Break("Read", false, "读取失败");
         }
 
         public Task<OperateResult> WriteAsync<V>(ConcurrentDictionary<string, V> Values)

+ 3 - 0
src/YSAI.DAQ/YSAI.S7/client/S7ClientData.cs

@@ -7,6 +7,7 @@ using System.ComponentModel;
 using System.Linq;
 using System.Text;
 using System.Threading.Tasks;
+using YSAI.Core.@enum;
 
 namespace YSAI.S7.client
 {
@@ -77,5 +78,7 @@ namespace YSAI.S7.client
                 }
             }
         }
+
+       
     }
 }

+ 19 - 1
src/YSAI.DAQ/YSAI.S7/client/S7ClientOperate.cs

@@ -1,5 +1,6 @@
 
 using S7.Net;
+using StackExchange.Redis;
 using System.Collections.Concurrent;
 using System.Net.Sockets;
 using YSAI.Core.data;
@@ -177,7 +178,24 @@ namespace YSAI.S7.client
                         }
                         else
                         {
-                            Value = PlcS7?.Read(item.AddressName).ToString();
+                            switch (item.AddressDataType)
+                            {
+                                case Core.@enum.DataType.Bool:
+                                    Value = ((byte)PlcS7?.Read(item.AddressName)).SelectBit(0).ToString();
+                                    break;
+                                case Core.@enum.DataType.String:
+                                    Value = PlcS7?.Read(item.AddressName).ValToBinString();
+                                    break;
+                                case Core.@enum.DataType.Float:
+                                    Value = ((uint)PlcS7?.Read(item.AddressName)).ConvertToFloat().ToString();
+                                    break;
+                                case Core.@enum.DataType.Int:
+                                    Value = ((uint)PlcS7?.Read(item.AddressName)).ConvertToInt().ToString();
+                                    break;
+                                default:
+                                    Value = "不支持此类型读取";
+                                    break;
+                            }
                         }
 
                         //数据处理

+ 224 - 0
src/YSAI.DAQ/YSAI.S7/client/S7Unility.cs

@@ -0,0 +1,224 @@
+using System.Globalization;
+using S7.Net;
+using S7.Net.Types;
+
+namespace YSAI.S7.client
+{
+    public static class S7Unility
+    {
+        /// <summary>
+        /// 将二进制字符串转换为Int32值
+        /// </summary>
+        /// <param name="txt"></param>
+        /// <returns></returns>
+        public static int BinStringToInt32(this string txt)
+        {
+            int ret = 0;
+
+            for (int i = 0; i < txt.Length; i++)
+            {
+                ret = (ret << 1) | ((txt[i] == '1') ? 1 : 0);
+            }
+            return ret;
+        }
+
+        /// <summary>
+        /// 将二进制字符串转换为字节。可以返回null。
+        /// </summary>
+        /// <param name="txt"></param>
+        /// <returns></returns>
+        public static byte? BinStringToByte(this string txt)
+        {
+            if (txt.Length == 8) return (byte)BinStringToInt32(txt);
+            return null;
+        }
+
+        /// <summary>
+        /// 将值转换为二进制字符串
+        /// </summary>
+        /// <param name="value"></param>
+        /// <returns></returns>
+        public static string ValToBinString(this object value)
+        {
+            int cnt = 0;
+            int cnt2 = 0;
+            int x = 0;
+            string txt = "";
+            long longValue = 0;
+
+            try
+            {
+                if (value.GetType().Name.IndexOf("[]") < 0)
+                {
+                    // ist nur ein Wert
+                    switch (value.GetType().Name)
+                    {
+                        case "Byte":
+                            x = 7;
+                            longValue = (long)((byte)value);
+                            break;
+                        case "Int16":
+                            x = 15;
+                            longValue = (long)((Int16)value);
+                            break;
+                        case "Int32":
+                            x = 31;
+                            longValue = (long)((Int32)value);
+                            break;
+                        case "Int64":
+                            x = 63;
+                            longValue = (long)((Int64)value);
+                            break;
+                        default:
+                            throw new Exception();
+                    }
+
+                    for (cnt = x; cnt >= 0; cnt += -1)
+                    {
+                        if (((Int64)longValue & (Int64)Math.Pow(2, cnt)) > 0)
+                            txt += "1";
+                        else
+                            txt += "0";
+                    }
+                }
+                else
+                {
+                    // ist ein Array
+                    switch (value.GetType().Name)
+                    {
+                        case "Byte[]":
+                            x = 7;
+                            byte[] ByteArr = (byte[])value;
+                            for (cnt2 = 0; cnt2 <= ByteArr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((ByteArr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        case "Int16[]":
+                            x = 15;
+                            Int16[] Int16Arr = (Int16[])value;
+                            for (cnt2 = 0; cnt2 <= Int16Arr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((Int16Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        case "Int32[]":
+                            x = 31;
+                            Int32[] Int32Arr = (Int32[])value;
+                            for (cnt2 = 0; cnt2 <= Int32Arr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((Int32Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        case "Int64[]":
+                            x = 63;
+                            byte[] Int64Arr = (byte[])value;
+                            for (cnt2 = 0; cnt2 <= Int64Arr.Length - 1; cnt2++)
+                            {
+                                for (cnt = x; cnt >= 0; cnt += -1)
+                                    if ((Int64Arr[cnt2] & (byte)Math.Pow(2, cnt)) > 0) txt += "1"; else txt += "0";
+                            }
+                            break;
+                        default:
+                            throw new Exception();
+                    }
+                }
+                return txt;
+            }
+            catch
+            {
+                return "";
+            }
+        }
+
+        /// <summary>
+        /// 帮助器获取给定字节和位索引的位值。
+        /// Example: DB1.DBX0.5 -> var bytes = ReadBytes(DB1.DBW0); bool bit = bytes[0].SelectBit(5); 
+        /// </summary>
+        /// <param name="data"></param>
+        /// <param name="bitPosition"></param>
+        /// <returns></returns>
+        public static bool SelectBit(this byte data, int bitPosition)
+        {
+            int mask = 1 << bitPosition;
+            int result = data & mask;
+
+            return (result != 0);
+        }
+
+        /// <summary>
+        /// 从短值转换为短值;它用于从单词中检索负值
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static short ConvertToShort(this ushort input)
+        {
+            short output;
+            output = short.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// 从短值转换为短值;它被用来传递负值给dw
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static ushort ConvertToUshort(this short input)
+        {
+            ushort output;
+            output = ushort.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// 将UInt32值转换为Int32值;它用于从dbd中检索负值
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static Int32 ConvertToInt(this uint input)
+        {
+            int output;
+            output = int.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// 将Int32值转换为UInt32值;它用于向dbd传递负值
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static UInt32 ConvertToUInt(this int input)
+        {
+            uint output;
+            output = uint.Parse(input.ToString("X"), NumberStyles.HexNumber);
+            return output;
+        }
+
+        /// <summary>
+        /// 从float转换为DWord (DBD)
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static UInt32 ConvertToUInt(this float input)
+        {
+            uint output;
+            output = DWord.FromByteArray(Real.ToByteArray(input));
+            return output;
+        }
+
+        /// <summary>
+        /// 从DWord (DBD)转换为float
+        /// </summary>
+        /// <param name="input"></param>
+        /// <returns></returns>
+        public static float ConvertToFloat(this uint input)
+        {
+            float output;
+            output = Real.FromByteArray(DWord.ToByteArray(input));
+            return output;
+        }
+    }
+}

+ 2 - 0
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/COTP.cs

@@ -55,6 +55,7 @@ namespace S7.Net
             /// See: https://tools.ietf.org/html/rfc905
             /// </summary>
             /// <param name="stream">The socket to read from</param>
+            /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
             /// <returns>COTP DPDU instance</returns>
             public static async Task<TPDU> ReadAsync(Stream stream, CancellationToken cancellationToken)
             {
@@ -89,6 +90,7 @@ namespace S7.Net
             /// See: https://tools.ietf.org/html/rfc905
             /// </summary>
             /// <param name="stream">The stream to read from</param>
+            /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
             /// <returns>Data in TSDU</returns>
             public static async Task<byte[]> ReadAsync(Stream stream, CancellationToken cancellationToken)
             {

+ 6 - 1
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Enums.cs

@@ -206,6 +206,11 @@
         /// <summary>
         /// DateTimeLong variable type
         /// </summary>
-        DateTimeLong
+        DateTimeLong,
+        
+        /// <summary>
+        /// S7 TIME variable type - serialized as S7 DInt and deserialized as C# TimeSpan 
+        /// </summary>
+        Time
     }
 }

+ 101 - 13
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/PLCHelpers.cs

@@ -10,29 +10,97 @@ namespace S7.Net
 {
     public partial class Plc
     {
+        private static void WriteTpktHeader(System.IO.MemoryStream stream, int length)
+        {
+            stream.Write(new byte[] { 0x03, 0x00 });
+            stream.Write(Word.ToByteArray((ushort) length));
+        }
+
+        private static void WriteDataHeader(System.IO.MemoryStream stream)
+        {
+            stream.Write(new byte[] { 0x02, 0xf0, 0x80 });
+        }
+
+        private static void WriteS7Header(System.IO.MemoryStream stream, byte messageType, int parameterLength, int dataLength)
+        {
+            stream.WriteByte(0x32); // S7 protocol ID
+            stream.WriteByte(messageType); // Message type
+            stream.Write(new byte[] { 0x00, 0x00 }); // Reserved
+            stream.Write(new byte[] { 0x00, 0x00 }); // PDU ref
+            stream.Write(Word.ToByteArray((ushort) parameterLength));
+            stream.Write(Word.ToByteArray((ushort) dataLength));
+        }
+
         /// <summary>
-        /// Creates the header to read bytes from the PLC
+        /// Creates the header to read bytes from the PLC.
         /// </summary>
-        /// <param name="amount"></param>
-        /// <returns></returns>
-        private static void BuildHeaderPackage(System.IO.MemoryStream stream, int amount = 1)
+        /// <param name="stream">The stream to write to.</param>
+        /// <param name="amount">The number of items to read.</param>
+        private static void WriteReadHeader(System.IO.MemoryStream stream, int amount = 1)
         {
-            //header size = 19 bytes
-            stream.Write(new byte[] { 0x03, 0x00 });
-            //complete package size
-            stream.Write(Int.ToByteArray((short)(19 + (12 * amount))));
-            stream.Write(new byte[] { 0x02, 0xf0, 0x80, 0x32, 0x01, 0x00, 0x00, 0x00, 0x00 });
-            //data part size
-            stream.Write(Word.ToByteArray((ushort)(2 + (amount * 12))));
-            stream.Write(new byte[] { 0x00, 0x00, 0x04 });
+            // Header size 19, 12 bytes per item
+            WriteTpktHeader(stream, 19 + 12 * amount);
+            WriteDataHeader(stream);
+            WriteS7Header(stream, 0x01, 2 + 12 * amount, 0);
+            // Function code: read request
+            stream.WriteByte(0x04);
             //amount of requests
             stream.WriteByte((byte)amount);
         }
 
+        private static void WriteUserDataHeader(System.IO.MemoryStream stream, int parameterLength, int dataLength)
+        {
+            const byte s7MessageTypeUserData = 0x07;
+
+            WriteTpktHeader(stream, 17 + parameterLength + dataLength);
+            WriteDataHeader(stream);
+            WriteS7Header(stream, s7MessageTypeUserData, parameterLength, dataLength);
+        }
+
+        private static void WriteSzlReadRequest(System.IO.MemoryStream stream, ushort szlId, ushort szlIndex)
+        {
+            WriteUserDataHeader(stream, 8, 8);
+
+            // Parameter
+            const byte szlMethodRequest = 0x11;
+            const byte szlTypeRequest = 0b100;
+            const byte szlFunctionGroupCpuFunctions = 0b100;
+            const byte subFunctionReadSzl = 0x01;
+
+            // Parameter head
+            stream.Write(new byte[] { 0x00, 0x01, 0x12 });
+            // Parameter length
+            stream.WriteByte(0x04);
+            // Method
+            stream.WriteByte(szlMethodRequest);
+            // Type / function group
+            stream.WriteByte(szlTypeRequest << 4 | szlFunctionGroupCpuFunctions);
+            // Subfunction
+            stream.WriteByte(subFunctionReadSzl);
+            // Sequence number
+            stream.WriteByte(0);
+
+            // Data
+            const byte success = 0xff;
+            const byte transportSizeOctetString = 0x09;
+
+            // Return code
+            stream.WriteByte(success);
+            // Transport size
+            stream.WriteByte(transportSizeOctetString);
+            // Length
+            stream.Write(Word.ToByteArray(4));
+            // SZL-ID
+            stream.Write(Word.ToByteArray(szlId));
+            // SZL-Index
+            stream.Write(Word.ToByteArray(szlIndex));
+        }
+
         /// <summary>
         /// Create the bytes-package to request data from the PLC. You have to specify the memory type (dataType),
         /// the address of the memory, the address of the byte and the bytes count.
         /// </summary>
+        /// <param name="stream">The stream to write the read data request to.</param>
         /// <param name="dataType">MemoryType (DB, Timer, Counter, etc.)</param>
         /// <param name="db">Address of the memory to be read</param>
         /// <param name="startByteAdr">Start address of the byte</param>
@@ -168,6 +236,15 @@ namespace S7.Net
                     {
                         return DateTimeLong.ToArray(bytes);
                     }
+                case VarType.Time:
+                    if (varCount == 1)
+                    {
+                        return Types.TimeSpan.FromByteArray(bytes);
+                    }
+                    else
+                    {
+                        return Types.TimeSpan.ToArray(bytes);
+                    }
                 default:
                     return null;
             }
@@ -201,6 +278,7 @@ namespace S7.Net
                 case VarType.DWord:
                 case VarType.DInt:
                 case VarType.Real:
+                case VarType.Time:
                     return varCount * 4;
                 case VarType.LReal:
                 case VarType.DateTime:
@@ -253,7 +331,7 @@ namespace S7.Net
             int packageSize = 19 + (dataItems.Count * 12);
             var package = new System.IO.MemoryStream(packageSize);
 
-            BuildHeaderPackage(package, dataItems.Count);
+            WriteReadHeader(package, dataItems.Count);
 
             foreach (var dataItem in dataItems)
             {
@@ -262,5 +340,15 @@ namespace S7.Net
 
             return package.ToArray();
         }
+
+        private static byte[] BuildSzlReadRequestPackage(ushort szlId, ushort szlIndex)
+        {
+            var stream = new System.IO.MemoryStream();
+            
+            WriteSzlReadRequest(stream, szlId, szlIndex);
+            stream.SetLength(stream.Position);
+
+            return stream.ToArray();
+        }
     }
 }

+ 15 - 1
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/PlcAsynchronous.cs

@@ -312,6 +312,20 @@ namespace S7.Net
             return dataItems;
         }
 
+        /// <summary>
+        /// Read the current status from the PLC. A value of 0x08 indicates the PLC is in run status, regardless of the PLC type.
+        /// </summary>
+        /// <param name="cancellationToken">The token to monitor for cancellation requests. The default value is None.
+        /// Please note that cancellation is advisory/cooperative and will not lead to immediate cancellation in all cases.</param>
+        /// <returns>A task that represents the asynchronous operation, with it's result set to the current PLC status on completion.</returns>
+        public async Task<byte> ReadStatusAsync(CancellationToken cancellationToken = default)
+        {
+            var dataToSend = BuildSzlReadRequestPackage(0x0424, 0);
+            var s7data = await RequestTsduAsync(dataToSend, cancellationToken);
+
+            return (byte) (s7data[37] & 0x0f);
+        }
+
         /// <summary>
         /// Write a number of bytes from a DB starting from a specified index. This handles more than 200 bytes with multiple requests.
         /// If the write was not successful, check LastErrorCode or LastErrorString.
@@ -428,7 +442,6 @@ namespace S7.Net
 
         /// <summary>
         /// Writes a single variable from the PLC, takes in input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.
-        /// If the write was not successful, check <see cref="LastErrorCode"/> or <see cref="LastErrorString"/>.
         /// </summary>
         /// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param>
         /// <param name="value">Value to be written to the PLC</param>
@@ -507,6 +520,7 @@ namespace S7.Net
         /// <param name="db">Address of the memory area (if you want to read DB1, this is set to 1). This must be set also for other memory area types: counters, timers,etc.</param>
         /// <param name="startByteAdr">Start byte address. If you want to read DB1.DBW200, this is 200.</param>
         /// <param name="value">Bytes to write. The lenght of this parameter can't be higher than 200. If you need more, use recursion.</param>
+        /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
         /// <returns>A task that represents the asynchronous write operation.</returns>
         private async Task WriteBytesWithASingleRequestAsync(DataType dataType, int db, int startByteAdr, ReadOnlyMemory<byte> value, CancellationToken cancellationToken)
         {

+ 14 - 3
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/PlcSynchronous.cs

@@ -289,7 +289,6 @@ namespace S7.Net
 
         /// <summary>
         /// Writes a single variable from the PLC, takes in input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.
-        /// If the write was not successful, check <see cref="LastErrorCode"/> or <see cref="LastErrorString"/>.
         /// </summary>
         /// <param name="variable">Input strings like "DB1.DBX0.0", "DB20.DBD200", "MB20", "T45", etc.</param>
         /// <param name="value">Value to be written to the PLC</param>
@@ -329,7 +328,7 @@ namespace S7.Net
                 const int packageSize = 19 + 12; // 19 header + 12 for 1 request
                 var dataToSend = new byte[packageSize];
                 var package = new MemoryStream(dataToSend);
-                BuildHeaderPackage(package);
+                WriteReadHeader(package);
                 // package.Add(0x02);  // datenart
                 BuildReadDataRequestPackage(package, dataType, db, startByteAdr, buffer.Length);
 
@@ -474,7 +473,7 @@ namespace S7.Net
                 int packageSize = 19 + (dataItems.Count * 12);
                 var dataToSend = new byte[packageSize];
                 var package = new MemoryStream(dataToSend);
-                BuildHeaderPackage(package, dataItems.Count);
+                WriteReadHeader(package, dataItems.Count);
                 // package.Add(0x02);  // datenart
                 foreach (var dataItem in dataItems)
                 {
@@ -493,6 +492,18 @@ namespace S7.Net
             }
         }
 
+        /// <summary>
+        /// Read the current status from the PLC. A value of 0x08 indicates the PLC is in run status, regardless of the PLC type.
+        /// </summary>
+        /// <returns>The current PLC status.</returns>
+        public byte ReadStatus()
+        {
+            var dataToSend = BuildSzlReadRequestPackage(0x0424, 0);
+            var s7data = RequestTsdu(dataToSend);
+
+            return (byte) (s7data[37] & 0x0f);
+        }
+
         private byte[] RequestTsdu(byte[] requestData) => RequestTsdu(requestData, 0, requestData.Length);
 
         private byte[] RequestTsdu(byte[] requestData, int offset, int length)

+ 1 - 0
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/StreamExtensions.cs

@@ -39,6 +39,7 @@ namespace S7.Net
         /// <param name="buffer">the buffer to read into</param>
         /// <param name="offset">the offset in the buffer to read into</param>
         /// <param name="count">the amount of bytes to read into the buffer</param>
+        /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
         /// <returns>returns the amount of read bytes</returns>
         public static async Task<int> ReadExactAsync(this Stream stream, byte[] buffer, int offset, int count, CancellationToken cancellationToken)
         {

+ 1 - 0
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/TPKT.cs

@@ -29,6 +29,7 @@ namespace S7.Net
         /// Reads a TPKT from the socket Async
         /// </summary>
         /// <param name="stream">The stream to read from</param>
+        /// <param name="cancellationToken">A cancellation token that can be used to cancel the asynchronous operation.</param>
         /// <returns>Task TPKT Instace</returns>
         public static async Task<TPKT> ReadAsync(Stream stream, CancellationToken cancellationToken)
         {

+ 26 - 11
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/Class.cs

@@ -64,7 +64,8 @@ namespace S7.Net.Types
                     numBytes += attribute.ReservedLengthInBytes;
                     break;
                 default:
-                    var propertyClass = Activator.CreateInstance(type);
+                    var propertyClass = Activator.CreateInstance(type) ??
+                        throw new ArgumentException($"Failed to create instance of type {type}.", nameof(type));
                     numBytes = GetClassSize(propertyClass, numBytes, true);
                     break;
             }
@@ -76,6 +77,8 @@ namespace S7.Net.Types
         /// Gets the size of the class in bytes.
         /// </summary>
         /// <param name="instance">An instance of the class</param>
+        /// <param name="numBytes">The offset of the current field.</param>
+        /// <param name="isInnerProperty"><see langword="true" /> if this property belongs to a class being serialized as member of the class requested for serialization; otherwise, <see langword="false" />.</param>
         /// <returns>the number of bytes</returns>
         public static double GetClassSize(object instance, double numBytes = 0.0, bool isInnerProperty = false)
         {
@@ -84,8 +87,10 @@ namespace S7.Net.Types
             {
                 if (property.PropertyType.IsArray)
                 {
-                    Type elementType = property.PropertyType.GetElementType();
-                    Array array = (Array)property.GetValue(instance, null);
+                    Type elementType = property.PropertyType.GetElementType()!;
+                    Array array = (Array?) property.GetValue(instance, null) ??
+                        throw new ArgumentException($"Property {property.Name} on {instance} must have a non-null value to get it's size.", nameof(instance));
+
                     if (array.Length <= 0)
                     {
                         throw new Exception("Cannot determine size of class, because an array is defined which has no fixed size greater than zero.");
@@ -199,7 +204,9 @@ namespace S7.Net.Types
                     numBytes += sData.Length;
                     break;
                 default:
-                    var propClass = Activator.CreateInstance(propertyType);
+                    var propClass = Activator.CreateInstance(propertyType) ??
+                        throw new ArgumentException($"Failed to create instance of type {propertyType}.", nameof(propertyType));
+
                     numBytes = FromBytes(propClass, bytes, numBytes);
                     value = propClass;
                     break;
@@ -213,6 +220,8 @@ namespace S7.Net.Types
         /// </summary>
         /// <param name="sourceClass">The object to fill in the given array of bytes</param>
         /// <param name="bytes">The array of bytes</param>
+        /// <param name="numBytes">The offset for the current field.</param>
+        /// <param name="isInnerClass"><see langword="true" /> if this class is the type of a member of the class to be serialized; otherwise, <see langword="false" />.</param>
         public static double FromBytes(object sourceClass, byte[] bytes, double numBytes = 0, bool isInnerClass = false)
         {
             if (bytes == null)
@@ -223,9 +232,11 @@ namespace S7.Net.Types
             {
                 if (property.PropertyType.IsArray)
                 {
-                    Array array = (Array)property.GetValue(sourceClass, null);
+                    Array array = (Array?) property.GetValue(sourceClass, null) ??
+                        throw new ArgumentException($"Property {property.Name} on sourceClass must be an array instance.", nameof(sourceClass));
+
                     IncrementToEven(ref numBytes);
-                    Type elementType = property.PropertyType.GetElementType();
+                    Type elementType = property.PropertyType.GetElementType()!;
                     for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
                     {
                         array.SetValue(
@@ -320,26 +331,30 @@ namespace S7.Net.Types
         /// <summary>
         /// Creates a byte array depending on the struct type.
         /// </summary>
-        /// <param name="sourceClass">The struct object</param>
+        /// <param name="sourceClass">The struct object.</param>
+        /// <param name="bytes">The target byte array.</param>
+        /// <param name="numBytes">The offset for the current field.</param>
         /// <returns>A byte array or null if fails.</returns>
         public static double ToBytes(object sourceClass, byte[] bytes, double numBytes = 0.0)
         {
             var properties = GetAccessableProperties(sourceClass.GetType());
             foreach (var property in properties)
             {
+                var value = property.GetValue(sourceClass, null) ??
+                    throw new ArgumentException($"Property {property.Name} on sourceClass can't be null.", nameof(sourceClass));
+
                 if (property.PropertyType.IsArray)
                 {
-                    Array array = (Array)property.GetValue(sourceClass, null);
+                    Array array = (Array) value;
                     IncrementToEven(ref numBytes);
-                    Type elementType = property.PropertyType.GetElementType();
                     for (int i = 0; i < array.Length && numBytes < bytes.Length; i++)
                     {
-                        numBytes = SetBytesFromProperty(array.GetValue(i), property, bytes, numBytes);
+                        numBytes = SetBytesFromProperty(array.GetValue(i)!, property, bytes, numBytes);
                     }
                 }
                 else
                 {
-                    numBytes = SetBytesFromProperty(property.GetValue(sourceClass, null), property, bytes, numBytes);
+                    numBytes = SetBytesFromProperty(value, property, bytes, numBytes);
                 }
             }
             return numBytes;

+ 1 - 1
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/DateTime.cs

@@ -141,7 +141,7 @@ namespace S7.Net.Types
         /// Converts an array of <see cref="T:System.DateTime"/> values to a byte array.
         /// </summary>
         /// <param name="dateTimes">The DateTime values to convert.</param>
-        /// <returns>A byte array containing the S7 date time representations of <paramref name="dateTime"/>.</returns>
+        /// <returns>A byte array containing the S7 date time representations of <paramref name="dateTimes"/>.</returns>
         /// <exception cref="ArgumentOutOfRangeException">Thrown when any value of
         ///   <paramref name="dateTimes"/> is before <see cref="P:SpecMinimumDateTime"/>
         ///   or after <see cref="P:SpecMaximumDateTime"/>.</exception>

+ 1 - 1
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/S7String.cs

@@ -58,7 +58,7 @@ namespace S7.Net.Types
         /// <param name="value">The string to convert to byte array.</param>
         /// <param name="reservedLength">The length (in characters) allocated in PLC for the string.</param>
         /// <returns>A <see cref="T:byte[]" /> containing the string header and string value with a maximum length of <paramref name="reservedLength"/> + 2.</returns>
-        public static byte[] ToByteArray(string value, int reservedLength)
+        public static byte[] ToByteArray(string? value, int reservedLength)
         {
             if (value is null)
             {

+ 1 - 1
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/S7WString.cs

@@ -48,7 +48,7 @@ namespace S7.Net.Types
         /// <param name="value">The string to convert to byte array.</param>
         /// <param name="reservedLength">The length (in characters) allocated in PLC for the string.</param>
         /// <returns>A <see cref="T:byte[]" /> containing the string header and string value with a maximum length of <paramref name="reservedLength"/> + 4.</returns>
-        public static byte[] ToByteArray(string value, int reservedLength)
+        public static byte[] ToByteArray(string? value, int reservedLength)
         {
             if (value is null)
             {

+ 6 - 4
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/String.cs

@@ -12,13 +12,15 @@
         /// <param name="reservedLength">The amount of bytes reserved for the <paramref name="value"/> in the PLC.</param>
         public static byte[] ToByteArray(string value, int reservedLength)
         {
-            var length = value?.Length;
-            if (length > reservedLength) length = reservedLength;
             var bytes = new byte[reservedLength];
+            if (value == null) return bytes;
+
+            var length = value.Length;
+            if (length == 0) return bytes;
 
-            if (length == null || length == 0) return bytes;
+            if (length > reservedLength) length = reservedLength;
 
-            System.Text.Encoding.ASCII.GetBytes(value, 0, length.Value, bytes, 0);
+            System.Text.Encoding.ASCII.GetBytes(value, 0, length, bytes, 0);
 
             return bytes;
         }

+ 39 - 12
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/Struct.cs

@@ -45,6 +45,7 @@ namespace S7.Net.Types
                         break;
                     case "Int32":
                     case "UInt32":
+                    case "TimeSpan":
                         numBytes = Math.Ceiling(numBytes);
                         if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
                             numBytes++;
@@ -98,8 +99,8 @@ namespace S7.Net.Types
             int bytePos = 0;
             int bitPos = 0;
             double numBytes = 0.0;
-            object structValue = Activator.CreateInstance(structType);
-
+            object structValue = Activator.CreateInstance(structType) ??
+                throw new ArgumentException($"Failed to create an instance of the type {structType}.", nameof(structType));
 
             var infos = structValue.GetType()
 #if NETSTANDARD1_3
@@ -215,6 +216,21 @@ namespace S7.Net.Types
 
                         numBytes += sData.Length;
                         break;
+                    case "TimeSpan":
+                        numBytes = Math.Ceiling(numBytes);
+                        if ((numBytes / 2 - Math.Floor(numBytes / 2.0)) > 0)
+                            numBytes++;
+                        
+                        // get the value
+                        info.SetValue(structValue, TimeSpan.FromByteArray(new[] 
+                        {
+                            bytes[(int)numBytes + 0],
+                            bytes[(int)numBytes + 1],
+                            bytes[(int)numBytes + 2],
+                            bytes[(int)numBytes + 3]
+                        }));
+                        numBytes += 4;
+                        break;
                     default:
                         var buffer = new byte[GetStructSize(info.FieldType)];
                         if (buffer.Length == 0)
@@ -254,6 +270,14 @@ namespace S7.Net.Types
 
             foreach (var info in infos)
             {
+                static TValue GetValueOrThrow<TValue>(FieldInfo fi, object structValue) where TValue : struct
+                {
+                    var value = fi.GetValue(structValue) as TValue? ??
+                        throw new ArgumentException($"Failed to convert value of field {fi.Name} of {structValue} to type {typeof(TValue)}");
+
+                    return value;
+                }
+
                 bytes2 = null;
                 switch (info.FieldType.Name)
                 {
@@ -261,7 +285,7 @@ namespace S7.Net.Types
                         // get the value
                         bytePos = (int)Math.Floor(numBytes);
                         bitPos = (int)((numBytes - (double)bytePos) / 0.125);
-                        if ((bool)info.GetValue(structValue))
+                        if (GetValueOrThrow<bool>(info, structValue))
                             bytes[bytePos] |= (byte)Math.Pow(2, bitPos);            // is true
                         else
                             bytes[bytePos] &= (byte)(~(byte)Math.Pow(2, bitPos));   // is false
@@ -270,26 +294,26 @@ namespace S7.Net.Types
                     case "Byte":
                         numBytes = (int)Math.Ceiling(numBytes);
                         bytePos = (int)numBytes;
-                        bytes[bytePos] = (byte)info.GetValue(structValue);
+                        bytes[bytePos] = GetValueOrThrow<byte>(info, structValue);
                         numBytes++;
                         break;
                     case "Int16":
-                        bytes2 = Int.ToByteArray((Int16)info.GetValue(structValue));
+                        bytes2 = Int.ToByteArray(GetValueOrThrow<short>(info, structValue));
                         break;
                     case "UInt16":
-                        bytes2 = Word.ToByteArray((UInt16)info.GetValue(structValue));
+                        bytes2 = Word.ToByteArray(GetValueOrThrow<ushort>(info, structValue));
                         break;
                     case "Int32":
-                        bytes2 = DInt.ToByteArray((Int32)info.GetValue(structValue));
+                        bytes2 = DInt.ToByteArray(GetValueOrThrow<int>(info, structValue));
                         break;
                     case "UInt32":
-                        bytes2 = DWord.ToByteArray((UInt32)info.GetValue(structValue));
+                        bytes2 = DWord.ToByteArray(GetValueOrThrow<uint>(info, structValue));
                         break;
                     case "Single":
-                        bytes2 = Real.ToByteArray((float)info.GetValue(structValue));
+                        bytes2 = Real.ToByteArray(GetValueOrThrow<float>(info, structValue));
                         break;
                     case "Double":
-                        bytes2 = LReal.ToByteArray((double)info.GetValue(structValue));
+                        bytes2 = LReal.ToByteArray(GetValueOrThrow<double>(info, structValue));
                         break;
                     case "String":
                         S7StringAttribute? attribute = info.GetCustomAttributes<S7StringAttribute>().SingleOrDefault();
@@ -298,11 +322,14 @@ namespace S7.Net.Types
 
                         bytes2 = attribute.Type switch
                         {
-                            S7StringType.S7String => S7String.ToByteArray((string)info.GetValue(structValue), attribute.ReservedLength),
-                            S7StringType.S7WString => S7WString.ToByteArray((string)info.GetValue(structValue), attribute.ReservedLength),
+                            S7StringType.S7String => S7String.ToByteArray((string?)info.GetValue(structValue), attribute.ReservedLength),
+                            S7StringType.S7WString => S7WString.ToByteArray((string?)info.GetValue(structValue), attribute.ReservedLength),
                             _ => throw new ArgumentException("Please use a valid string type for the S7StringAttribute")
                         };
                         break;
+                    case "TimeSpan":
+                        bytes2 = TimeSpan.ToByteArray((System.TimeSpan)info.GetValue(structValue));
+                        break;
                 }
                 if (bytes2 != null)
                 {

+ 97 - 0
src/YSAI.DAQ/YSAI.S7/client/lib/S7.Net/Types/TimeSpan.cs

@@ -0,0 +1,97 @@
+using System;
+using System.Collections.Generic;
+
+namespace S7.Net.Types
+{
+    /// <summary>
+    /// Contains the methods to convert between <see cref="T:System.TimeSpan"/> and S7 representation of TIME values.
+    /// </summary>
+    public static class TimeSpan
+    {
+        /// <summary>
+        /// The minimum <see cref="T:System.TimeSpan"/> value supported by the specification.
+        /// </summary>
+        public static readonly System.TimeSpan SpecMinimumTimeSpan = System.TimeSpan.FromMilliseconds(int.MinValue);
+
+        /// <summary>
+        /// The maximum <see cref="T:System.TimeSpan"/> value supported by the specification.
+        /// </summary>
+        public static readonly System.TimeSpan SpecMaximumTimeSpan = System.TimeSpan.FromMilliseconds(int.MaxValue);
+
+        /// <summary>
+        /// Parses a <see cref="T:System.TimeSpan"/> value from bytes.
+        /// </summary>
+        /// <param name="bytes">Input bytes read from PLC.</param>
+        /// <returns>A <see cref="T:System.TimeSpan"/> object representing the value read from PLC.</returns>
+        /// <exception cref="ArgumentOutOfRangeException">Thrown when the length of
+        ///   <paramref name="bytes"/> is not 4 or any value in <paramref name="bytes"/>
+        ///   is outside the valid range of values.</exception>
+        public static System.TimeSpan FromByteArray(byte[] bytes)
+        {
+            var milliseconds = DInt.FromByteArray(bytes);
+            return System.TimeSpan.FromMilliseconds(milliseconds);
+        }
+
+        /// <summary>
+        /// Parses an array of <see cref="T:System.TimeSpan"/> values from bytes.
+        /// </summary>
+        /// <param name="bytes">Input bytes read from PLC.</param>
+        /// <returns>An array of <see cref="T:System.TimeSpan"/> objects representing the values read from PLC.</returns>
+        /// <exception cref="ArgumentOutOfRangeException">Thrown when the length of
+        ///   <paramref name="bytes"/> is not a multiple of 4 or any value in
+        ///   <paramref name="bytes"/> is outside the valid range of values.</exception>
+        public static System.TimeSpan[] ToArray(byte[] bytes)
+        {
+            const int singleTimeSpanLength = 4;
+            
+            if (bytes.Length % singleTimeSpanLength != 0)
+                throw new ArgumentOutOfRangeException(nameof(bytes), bytes.Length,
+                    $"Parsing an array of {nameof(System.TimeSpan)} requires a multiple of {singleTimeSpanLength} bytes of input data, input data is '{bytes.Length}' long.");
+
+            var result = new System.TimeSpan[bytes.Length / singleTimeSpanLength];
+
+            var milliseconds = DInt.ToArray(bytes);
+            for (var i = 0; i < milliseconds.Length; i++)
+                result[i] = System.TimeSpan.FromMilliseconds(milliseconds[i]);
+
+            return result;
+        }
+
+        /// <summary>
+        /// Converts a <see cref="T:System.TimeSpan"/> value to a byte array.
+        /// </summary>
+        /// <param name="timeSpan">The TimeSpan value to convert.</param>
+        /// <returns>A byte array containing the S7 date time representation of <paramref name="timeSpan"/>.</returns>
+        /// <exception cref="ArgumentOutOfRangeException">Thrown when the value of
+        ///   <paramref name="timeSpan"/> is before <see cref="P:SpecMinimumTimeSpan"/>
+        ///   or after <see cref="P:SpecMaximumTimeSpan"/>.</exception>
+        public static byte[] ToByteArray(System.TimeSpan timeSpan)
+        {
+            if (timeSpan < SpecMinimumTimeSpan)
+                throw new ArgumentOutOfRangeException(nameof(timeSpan), timeSpan,
+                    $"Time span '{timeSpan}' is before the minimum '{SpecMinimumTimeSpan}' supported in S7 time representation.");
+
+            if (timeSpan > SpecMaximumTimeSpan)
+                throw new ArgumentOutOfRangeException(nameof(timeSpan), timeSpan,
+                    $"Time span '{timeSpan}' is after the maximum '{SpecMaximumTimeSpan}' supported in S7 time representation.");
+
+            return DInt.ToByteArray(Convert.ToInt32(timeSpan.TotalMilliseconds));
+        }
+
+        /// <summary>
+        /// Converts an array of <see cref="T:System.TimeSpan"/> values to a byte array.
+        /// </summary>
+        /// <param name="timeSpans">The TimeSpan values to convert.</param>
+        /// <returns>A byte array containing the S7 date time representations of <paramref name="timeSpans"/>.</returns>
+        /// <exception cref="ArgumentOutOfRangeException">Thrown when any value of
+        ///   <paramref name="timeSpans"/> is before <see cref="P:SpecMinimumTimeSpan"/>
+        ///   or after <see cref="P:SpecMaximumTimeSpan"/>.</exception>
+        public static byte[] ToByteArray(System.TimeSpan[] timeSpans)
+        {
+            var bytes = new List<byte>(timeSpans.Length * 4);
+            foreach (var timeSpan in timeSpans) bytes.AddRange(ToByteArray(timeSpan));
+
+            return bytes.ToArray();
+        }
+    }
+}

+ 347 - 0
src/YSAI.DAQ/YSAI.Test/TestAll.cs

@@ -554,5 +554,352 @@ namespace YSAI.Test
 
             FileTool.StringToFile(ReflectionOperate.ConfigFile, JsonTool.JsonEntityToString(basics).JsonFormatting());
         }
+
+        [TestMethod]
+        public void 创建反射与地址配置()
+        {
+            //创建一个采集配置
+            List<AddressManage> addressManages = new List<AddressManage>();
+
+            AddressManage addressManage = new AddressManage();
+            addressManage.DType = Core.@enum.DaqType.OpcDa;
+            addressManage.SN = "OPCDA采集";
+            addressManage.InstanceParam = new OpcDaClientData.Basics() { SN = "OPCDA采集", ServiceName = "Knight.OPC.Server.Demo", SpecificationVer = Specification.COM_DA_20 };
+            addressManage.AddressArray = new List<AddressDetails>()
+            {
+                new AddressDetails()
+                {
+                    AddressName = "a.a.a",
+                    AddressDataType = Core.@enum.DataType.Bool,
+                    AddressDescribe = "一个动态的布尔类型",
+                    AddressAnotherName = "test",
+                    AddressPropertyName = "aaa",
+                    AddressType = Core.@enum.AddressType.Reality,
+                    MqttRelay = new AddressRelay.MqttRelayParam()
+                    {
+                        QoSLevel = 0,
+                        Retain = true,
+                        Topic = "Test/aaa",
+                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                    }
+                },
+                new AddressDetails()
+                {
+                    AddressName = "a.a.h",
+                    AddressDataType = Core.@enum.DataType.String,
+                    AddressDescribe = "一个动态的字符串类型",
+                    AddressAnotherName = "test",
+                    AddressPropertyName = "aah",
+                    AddressType = Core.@enum.AddressType.Reality,
+                    AddressParseParam = new AddressParse()
+                    {
+                        ParseType = Core.@enum.ParseType.ScriptAnalysis,
+                        Script = new Core.script.ScriptData.Basics()
+                        {
+                            ScriptCode = @"function Convert(value) 
+                                            {
+                                                return '这是脚本测试,传入的参数是:' + value;
+                                            }",
+                            ScriptFunction = "Convert",
+                            ScriptType = Core.script.ScriptData.ScriptType.JavaScript
+                        }
+                    },
+                    MqttRelay = new AddressRelay.MqttRelayParam()
+                    {
+                        QoSLevel = 0,
+                        Retain = true,
+                        Topic = "Test/aah",
+                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                    }
+                },
+                new AddressDetails()
+                 {
+                     AddressName = "a.a.g",
+                     AddressDataType = Core.@enum.DataType.Double,
+                     AddressDescribe = "一个动态的浮点类型",
+                     AddressAnotherName = "test",
+                     AddressPropertyName = "aag",
+                     AddressType = Core.@enum.AddressType.Reality,
+                     AddressParseParam = new AddressParse()
+                     {
+                         ParseType = Core.@enum.ParseType.ScriptAnalysis,
+                         Script = new Core.script.ScriptData.Basics()
+                         {
+                             ScriptCode = @"function Convert(value) 
+                                            {
+                                                return value*1000;
+                                            }",
+                             ScriptFunction = "Convert",
+                             ScriptType = Core.script.ScriptData.ScriptType.JavaScript
+                         }
+                     },
+                     MqttRelay = new AddressRelay.MqttRelayParam()
+                     {
+                         QoSLevel = 0,
+                         Retain = true,
+                         Topic = "Test/aag",
+                         ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                     }
+                 },
+                new AddressDetails()
+                 {
+                     AddressName = "OPCDA_VirtualAddress",
+                     AddressDataType = Core.@enum.DataType.String,
+                     AddressDescribe = "虚拟地址",
+                     AddressAnotherName = "test",
+                     AddressPropertyName = "OPCDA_VirtualAddress",
+                     AddressType = Core.@enum.AddressType.Virtual,
+                    MqttRelay = new AddressRelay.MqttRelayParam()
+                    {
+                        QoSLevel = 0,
+                        Retain = true,
+                        Topic = "Test/OPCDA_VirtualAddress",
+                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                    }
+                 },
+                new AddressDetails()
+                  {
+                      AddressName = "OPCDA_VirtualDynamicAddress",
+                      AddressDataType = Core.@enum.DataType.String,
+                      AddressDescribe = "虚拟动态地址",
+                      AddressAnotherName = "test",
+                      AddressPropertyName = "OPCDA_VirtualDynamicAddress",
+                      AddressType = Core.@enum.AddressType.VirtualDynamic,
+                        MqttRelay = new AddressRelay.MqttRelayParam()
+                        {
+                            QoSLevel = 0,
+                            Retain = true,
+                            Topic = "Test/OPCDA_VirtualDynamicAddress",
+                            ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                        }
+                  }
+            };
+
+            addressManages.Add(addressManage);
+
+            addressManage = new AddressManage();
+            addressManage.DType = Core.@enum.DaqType.OpcUa;
+            addressManage.SN = "OPCUA采集";
+            addressManage.InstanceParam = new OpcUaClientData.Basics() { SN = "OPCUA采集", Name = "TEST", Password = "ysai", UserName = "ysai", ServerUrl = "opc.tcp://192.168.2.38:8866/Opc.Ua.Service", SamplingInterval = 100 };
+            addressManage.AddressArray = new List<AddressDetails>()
+            {
+                new AddressDetails()
+                {
+                    AddressName = "ns=2;s=Boolean_Dynamic",
+                    AddressDataType = Core.@enum.DataType.Bool,
+                    AddressDescribe = "一个动态的布尔类型",
+                    AddressAnotherName = "test",
+                    AddressPropertyName = "Boolean_Dynamic",
+                    AddressType = Core.@enum.AddressType.Reality,
+                    MqttRelay = new AddressRelay.MqttRelayParam()
+                    {
+                        QoSLevel = 0,
+                        Retain = true,
+                        Topic = "Test/Boolean_Dynamic",
+                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                    }
+                },
+                new AddressDetails()
+                {
+                    AddressName = "ns=2;s=String_Dynamic",
+                    AddressDataType = Core.@enum.DataType.String,
+                    AddressDescribe = "一个动态的字符串类型",
+                    AddressAnotherName = "test",
+                    AddressPropertyName = "String_Dynamic",
+                    AddressType = Core.@enum.AddressType.Reality,
+                    AddressParseParam = new AddressParse()
+                    {
+                        ParseType = Core.@enum.ParseType.ScriptAnalysis,
+                        Script = new Core.script.ScriptData.Basics()
+                        {
+                            ScriptCode = @"function Convert(value) 
+                                            {
+                                                return '这是脚本测试,传入的参数是:' + value;
+                                            }",
+                            ScriptFunction = "Convert",
+                            ScriptType = Core.script.ScriptData.ScriptType.JavaScript
+                        }
+                    },
+                    MqttRelay = new AddressRelay.MqttRelayParam()
+                    {
+                        QoSLevel = 0,
+                        Retain = true,
+                        Topic = "Test/String_Dynamic",
+                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                    }
+                },
+                new AddressDetails()
+                 {
+                     AddressName = "ns=2;s=Double_Dynamic",
+                     AddressDataType = Core.@enum.DataType.Double,
+                     AddressDescribe = "一个动态的浮点类型",
+                     AddressAnotherName = "test",
+                     AddressPropertyName = "Double_Dynamic",
+                     AddressType = Core.@enum.AddressType.Reality,
+                     AddressParseParam = new AddressParse()
+                     {
+                         ParseType = Core.@enum.ParseType.ScriptAnalysis,
+                         Script = new Core.script.ScriptData.Basics()
+                         {
+                             ScriptCode = @"function Convert(value) 
+                                            {
+                                                return value*1000;
+                                            }",
+                             ScriptFunction = "Convert",
+                             ScriptType = Core.script.ScriptData.ScriptType.JavaScript
+                         }
+                     },
+                     MqttRelay = new AddressRelay.MqttRelayParam()
+                     {
+                         QoSLevel = 0,
+                         Retain = true,
+                         Topic = "Test/Double_Dynamic",
+                         ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                     }
+                 },
+                new AddressDetails()
+                 {
+                     AddressName = "OPCUA_VirtualAddress",
+                     AddressDataType = Core.@enum.DataType.String,
+                     AddressDescribe = "虚拟地址",
+                     AddressAnotherName = "test",
+                     AddressPropertyName = "OPCUA_VirtualAddress",
+                     AddressType = Core.@enum.AddressType.Virtual,
+                        MqttRelay = new AddressRelay.MqttRelayParam()
+                        {
+                            QoSLevel = 0,
+                            Retain = true,
+                            Topic = "Test/OPCUA_VirtualAddress",
+                            ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                        }
+                 },
+                new AddressDetails()
+                  {
+                      AddressName = "OPCUA_VirtualDynamicAddress",
+                      AddressDataType = Core.@enum.DataType.String,
+                      AddressDescribe = "虚拟动态地址",
+                      AddressAnotherName = "test",
+                      AddressPropertyName = "OPCUA_VirtualDynamicAddress",
+                      AddressType = Core.@enum.AddressType.VirtualDynamic,
+                        MqttRelay = new AddressRelay.MqttRelayParam()
+                        {
+                            QoSLevel = 0,
+                            Retain = true,
+                            Topic = "Test/OPCUA_VirtualDynamicAddress",
+                            ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
+                        }
+                  }
+            };
+
+            addressManages.Add(addressManage);
+
+            //生成文件
+            FileTool.StringToFile("config//DaqConfig.json", JsonTool.JsonEntityToString(addressManages).JsonFormatting());
+
+
+            List<AddressManage>? addresses = JsonTool.StringToJsonEntity<List<AddressManage>>(FileTool.FileToString("config//DaqConfig.json"));
+
+            OpcDaClientData.Basics? basics1 = JsonTool.StringToJsonEntity<OpcDaClientData.Basics>(addresses[0].InstanceParam.ToString());
+
+
+
+            //创建一个转发配置
+            ReflectionData.Basics basics = new ReflectionData.Basics()
+            {
+                DllDatas = new List<Basics.DllData>()
+                {
+                    new Basics.DllData()
+                    {
+                        DllPath="YSAI.Mqtt.dll",
+                        IsAbsolutePath=false,
+                        NamespaceDatas=new List<Basics.DllData.NamespaceData>()
+                        {
+                            new Basics.DllData.NamespaceData()
+                            {
+                                Namespace="YSAI.Mqtt.service.websocket",
+                                ClassDatas=new List<Basics.DllData.NamespaceData.ClassData>()
+                                {
+                                    new Basics.DllData.NamespaceData.ClassData()
+                                    {
+                                        ClassName="MqttWebSocketServiceOperate",
+                                        ConstructorParam=new object[]{ new MqttWebSocketServiceData.Basics { LoginID="ysai",LoginPassword="ysai",Port= 11819, HttpPort= 11820, Uri="NB_CLASS" } },
+                                        SN="YSAI.Mqtt.MqttWebSocketServiceOperate[Instance]",
+                                        MethodDatas=new List<Basics.DllData.NamespaceData.ClassData.MethodData>()
+                                        {
+                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
+                                            {
+                                                MethodName="On",
+                                                SN="[On]",
+                                                WhetherExecute=true
+                                            }
+                                        }
+                                    }
+                                }
+                            },
+                            new Basics.DllData.NamespaceData()
+                            {
+                                Namespace="YSAI.Mqtt.client",
+                                ClassDatas=new List<Basics.DllData.NamespaceData.ClassData>()
+                                {
+                                    new Basics.DllData.NamespaceData.ClassData()
+                                    {
+                                        ClassName="MqttClientOperate",
+                                        ConstructorParam=new object[]{ new MqttClientData.Basics { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce, ServerIPAddress = "127.0.0.1", ServerLoginID = "ysai", ServerLoginPassword = "ysai", ServerPort = 11819 } },
+                                        SN="YSAI.Mqtt.MqttClientOperate[Instance]",
+                                        MethodDatas=new List<Basics.DllData.NamespaceData.ClassData.MethodData>()
+                                        {
+                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
+                                            {
+                                                MethodName="Init",
+                                                SN="[Init]",
+                                                WhetherExecute=true
+                                            },
+                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
+                                            {
+                                                MethodName="On",
+                                                SN="[On]",
+                                                WhetherExecute=true
+                                            },
+                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
+                                            {
+                                                MethodName="Off",
+                                                SN="[Off]"
+                                            },
+                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
+                                            {
+                                                MethodName="PublishSubscribe",
+                                                SN="[PublishSubscribe]"
+                                            },
+                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
+                                            {
+                                                MethodName="AddSubscribe",
+                                                SN="[AddSubscribe]"
+                                            },
+                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
+                                            {
+                                                MethodName="RemoveSubscribe",
+                                                SN="[RemoveSubscribe]"
+                                            }
+                                        },
+                                        EventDatas=new List<ClassData.EventData>()
+                                        {
+                                            new ClassData.EventData()
+                                            {
+                                                EventName="OnEvent",
+                                                SN="[OnEvent]"
+                                            }
+                                        }
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+            };
+            //生成文件
+            FileTool.StringToFile(ReflectionOperate.ConfigFile, JsonTool.JsonEntityToString(basics).JsonFormatting());
+
+
+        }
     }
 }

+ 43 - 337
src/YSAI.DAQ/YSAI.TestConsole/Program.cs

@@ -16,358 +16,64 @@ using YSAI.Opc.da.client;
 using YSAI.Opc.ua.client;
 using YSAI.Opc.ua.service;
 using YSAI.RabbitMQ;
+using YSAI.S7.client;
+using S7.Net;
 using YSAI.Unility;
 using static YSAI.Core.reflection.ReflectionData;
 using static YSAI.Core.reflection.ReflectionData.Basics.DllData.NamespaceData;
+using YSAI.Core.@enum;
+
 namespace YSAI.TestConsole
 {
     internal class Program
     {
         static void Main(string[] args)
         {
-            //创建一个采集配置
-            List<AddressManage> addressManages = new List<AddressManage>();
-
-            AddressManage addressManage = new AddressManage();
-            addressManage.DType = Core.@enum.DaqType.OpcDa;
-            addressManage.SN = "OPCDA采集";
-            addressManage.InstanceParam = new OpcDaClientData.Basics() { SN = "OPCDA采集", ServiceName = "Knight.OPC.Server.Demo", SpecificationVer = Specification.COM_DA_20 };
-            addressManage.AddressArray = new List<AddressDetails>()
+            //对象实例
+            S7ClientOperate s7ClientOperate = S7ClientOperate.Instance(new S7ClientData.Basics()
             {
-                new AddressDetails()
-                {
-                    AddressName = "a.a.a",
-                    AddressDataType = Core.@enum.DataType.Bool,
-                    AddressDescribe = "一个动态的布尔类型",
-                    AddressAnotherName = "test",
-                    AddressPropertyName = "aaa",
-                    AddressType = Core.@enum.AddressType.Reality,
-                    MqttRelay = new AddressRelay.MqttRelayParam()
-                    {
-                        QoSLevel = 0,
-                        Retain = true,
-                        Topic = "Test/aaa",
-                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                    }
-                },
-                new AddressDetails()
-                {
-                    AddressName = "a.a.h",
-                    AddressDataType = Core.@enum.DataType.String,
-                    AddressDescribe = "一个动态的字符串类型",
-                    AddressAnotherName = "test",
-                    AddressPropertyName = "aah",
-                    AddressType = Core.@enum.AddressType.Reality,
-                    AddressParseParam = new AddressParse()
-                    {
-                        ParseType = Core.@enum.ParseType.ScriptAnalysis,
-                        Script = new Core.script.ScriptData.Basics()
-                        {
-                            ScriptCode = @"function Convert(value) 
-                                            {
-                                                return '这是脚本测试,传入的参数是:' + value;
-                                            }",
-                            ScriptFunction = "Convert",
-                            ScriptType = Core.script.ScriptData.ScriptType.JavaScript
-                        }
-                    },
-                    MqttRelay = new AddressRelay.MqttRelayParam()
-                    {
-                        QoSLevel = 0,
-                        Retain = true,
-                        Topic = "Test/aah",
-                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                    }
-                },
-                new AddressDetails()
-                 {
-                     AddressName = "a.a.g",
-                     AddressDataType = Core.@enum.DataType.Double,
-                     AddressDescribe = "一个动态的浮点类型",
-                     AddressAnotherName = "test",
-                     AddressPropertyName = "aag",
-                     AddressType = Core.@enum.AddressType.Reality,
-                     AddressParseParam = new AddressParse()
-                     {
-                         ParseType = Core.@enum.ParseType.ScriptAnalysis,
-                         Script = new Core.script.ScriptData.Basics()
-                         {
-                             ScriptCode = @"function Convert(value) 
-                                            {
-                                                return value*1000;
-                                            }",
-                             ScriptFunction = "Convert",
-                             ScriptType = Core.script.ScriptData.ScriptType.JavaScript
-                         }
-                     },
-                     MqttRelay = new AddressRelay.MqttRelayParam()
-                     {
-                         QoSLevel = 0,
-                         Retain = true,
-                         Topic = "Test/aag",
-                         ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                     }
-                 },
-                new AddressDetails()
-                 {
-                     AddressName = "OPCDA_VirtualAddress",
-                     AddressDataType = Core.@enum.DataType.String,
-                     AddressDescribe = "虚拟地址",
-                     AddressAnotherName = "test",
-                     AddressPropertyName = "OPCDA_VirtualAddress",
-                     AddressType = Core.@enum.AddressType.Virtual,
-                    MqttRelay = new AddressRelay.MqttRelayParam()
-                    {
-                        QoSLevel = 0,
-                        Retain = true,
-                        Topic = "Test/OPCDA_VirtualAddress",
-                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                    }
-                 },
-                new AddressDetails()
-                  {
-                      AddressName = "OPCDA_VirtualDynamicAddress",
-                      AddressDataType = Core.@enum.DataType.String,
-                      AddressDescribe = "虚拟动态地址",
-                      AddressAnotherName = "test",
-                      AddressPropertyName = "OPCDA_VirtualDynamicAddress",
-                      AddressType = Core.@enum.AddressType.VirtualDynamic,
-                        MqttRelay = new AddressRelay.MqttRelayParam()
-                        {
-                            QoSLevel = 0,
-                            Retain = true,
-                            Topic = "Test/OPCDA_VirtualDynamicAddress",
-                            ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                        }
-                  }
-            };
-
-            addressManages.Add(addressManage);
-
-            addressManage = new AddressManage();
-            addressManage.DType = Core.@enum.DaqType.OpcUa;
-            addressManage.SN = "OPCUA采集";
-            addressManage.InstanceParam = new OpcUaClientData.Basics() { SN = "OPCUA采集", Name = "TEST", Password = "ysai", UserName = "ysai", ServerUrl = "opc.tcp://192.168.2.38:8866/Opc.Ua.Service", SamplingInterval = 100 };
-            addressManage.AddressArray = new List<AddressDetails>()
+                Ip = "192.168.2.20",
+                Port = 102,
+                Rack = 0,
+                Slot = 1,
+                S7CpuType = CpuType.S71200,
+                SN = Guid.NewGuid().ToString()
+            });
+
+            //打开
+            OperateResult operateResult = s7ClientOperate.On();
+            Console.WriteLine(operateResult.Message);
+
+            //点位地址
+            Address address = new Address();
+            address.SN = Guid.NewGuid().ToString();
+            address.CreationTime = DateTime.Now.ToLocalTime();
+            address.AddressArray = new List<AddressDetails>();
+            address.AddressArray.Add(new AddressDetails()
             {
-                new AddressDetails()
-                {
-                    AddressName = "ns=2;s=Boolean_Dynamic",
-                    AddressDataType = Core.@enum.DataType.Bool,
-                    AddressDescribe = "一个动态的布尔类型",
-                    AddressAnotherName = "test",
-                    AddressPropertyName = "Boolean_Dynamic",
-                    AddressType = Core.@enum.AddressType.Reality,
-                    MqttRelay = new AddressRelay.MqttRelayParam()
-                    {
-                        QoSLevel = 0,
-                        Retain = true,
-                        Topic = "Test/Boolean_Dynamic",
-                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                    }
-                },
-                new AddressDetails()
-                {
-                    AddressName = "ns=2;s=String_Dynamic",
-                    AddressDataType = Core.@enum.DataType.String,
-                    AddressDescribe = "一个动态的字符串类型",
-                    AddressAnotherName = "test",
-                    AddressPropertyName = "String_Dynamic",
-                    AddressType = Core.@enum.AddressType.Reality,
-                    AddressParseParam = new AddressParse()
-                    {
-                        ParseType = Core.@enum.ParseType.ScriptAnalysis,
-                        Script = new Core.script.ScriptData.Basics()
-                        {
-                            ScriptCode = @"function Convert(value) 
-                                            {
-                                                return '这是脚本测试,传入的参数是:' + value;
-                                            }",
-                            ScriptFunction = "Convert",
-                            ScriptType = Core.script.ScriptData.ScriptType.JavaScript
-                        }
-                    },
-                    MqttRelay = new AddressRelay.MqttRelayParam()
-                    {
-                        QoSLevel = 0,
-                        Retain = true,
-                        Topic = "Test/String_Dynamic",
-                        ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                    }
-                },
-                new AddressDetails()
-                 {
-                     AddressName = "ns=2;s=Double_Dynamic",
-                     AddressDataType = Core.@enum.DataType.Double,
-                     AddressDescribe = "一个动态的浮点类型",
-                     AddressAnotherName = "test",
-                     AddressPropertyName = "Double_Dynamic",
-                     AddressType = Core.@enum.AddressType.Reality,
-                     AddressParseParam = new AddressParse()
-                     {
-                         ParseType = Core.@enum.ParseType.ScriptAnalysis,
-                         Script = new Core.script.ScriptData.Basics()
-                         {
-                             ScriptCode = @"function Convert(value) 
-                                            {
-                                                return value*1000;
-                                            }",
-                             ScriptFunction = "Convert",
-                             ScriptType = Core.script.ScriptData.ScriptType.JavaScript
-                         }
-                     },
-                     MqttRelay = new AddressRelay.MqttRelayParam()
-                     {
-                         QoSLevel = 0,
-                         Retain = true,
-                         Topic = "Test/Double_Dynamic",
-                         ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                     }
-                 },
-                new AddressDetails()
-                 {
-                     AddressName = "OPCUA_VirtualAddress",
-                     AddressDataType = Core.@enum.DataType.String,
-                     AddressDescribe = "虚拟地址",
-                     AddressAnotherName = "test",
-                     AddressPropertyName = "OPCUA_VirtualAddress",
-                     AddressType = Core.@enum.AddressType.Virtual,
-                        MqttRelay = new AddressRelay.MqttRelayParam()
-                        {
-                            QoSLevel = 0,
-                            Retain = true,
-                            Topic = "Test/OPCUA_VirtualAddress",
-                            ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                        }
-                 },
-                new AddressDetails()
-                  {
-                      AddressName = "OPCUA_VirtualDynamicAddress",
-                      AddressDataType = Core.@enum.DataType.String,
-                      AddressDescribe = "虚拟动态地址",
-                      AddressAnotherName = "test",
-                      AddressPropertyName = "OPCUA_VirtualDynamicAddress",
-                      AddressType = Core.@enum.AddressType.VirtualDynamic,
-                        MqttRelay = new AddressRelay.MqttRelayParam()
-                        {
-                            QoSLevel = 0,
-                            Retain = true,
-                            Topic = "Test/OPCUA_VirtualDynamicAddress",
-                            ReflectionSN = "YSAI.Mqtt.MqttClientOperate[Instance][PublishSubscribe]"
-                        }
-                  }
-            };
-
-            addressManages.Add(addressManage);
-
-            //生成文件
-            FileTool.StringToFile("config//DaqConfig.json", JsonTool.JsonEntityToString(addressManages).JsonFormatting());
-
-
-            List<AddressManage>? addresses = JsonTool.StringToJsonEntity<List<AddressManage>>(FileTool.FileToString("config//DaqConfig.json"));
-
-            OpcDaClientData.Basics? basics1=JsonTool.StringToJsonEntity<OpcDaClientData.Basics>(addresses[0].InstanceParam.ToString());
-
-
-
-            //创建一个转发配置
-            ReflectionData.Basics basics = new ReflectionData.Basics()
+                AddressName = "DB71.DBD4",
+                AddressDataType = Core.@enum.DataType.Float,
+                AddressType = AddressType.Reality
+            });
+
+            //读取
+            operateResult = s7ClientOperate.Read(address);
+            Console.WriteLine(operateResult.Message);
+            if (operateResult.State)
             {
-                DllDatas = new List<Basics.DllData>()
+                foreach (var item in operateResult.RData as ConcurrentDictionary<string, AddressValue>)
                 {
-                    new Basics.DllData()
-                    {
-                        DllPath="YSAI.Mqtt.dll",
-                        IsAbsolutePath=false,
-                        NamespaceDatas=new List<Basics.DllData.NamespaceData>()
-                        {
-                            new Basics.DllData.NamespaceData()
-                            {
-                                Namespace="YSAI.Mqtt.service.websocket",
-                                ClassDatas=new List<Basics.DllData.NamespaceData.ClassData>()
-                                {
-                                    new Basics.DllData.NamespaceData.ClassData()
-                                    {
-                                        ClassName="MqttWebSocketServiceOperate",
-                                        ConstructorParam=new object[]{ new MqttWebSocketServiceData.Basics { LoginID="ysai",LoginPassword="ysai",Port= 11819, HttpPort= 11820, Uri="NB_CLASS" } },
-                                        SN="YSAI.Mqtt.MqttWebSocketServiceOperate[Instance]",
-                                        MethodDatas=new List<Basics.DllData.NamespaceData.ClassData.MethodData>()
-                                        {
-                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
-                                            {
-                                                MethodName="On",
-                                                SN="[On]",
-                                                WhetherExecute=true
-                                            }
-                                        }
-                                    }
-                                }
-                            },
-                            new Basics.DllData.NamespaceData()
-                            {
-                                Namespace="YSAI.Mqtt.client",
-                                ClassDatas=new List<Basics.DllData.NamespaceData.ClassData>()
-                                {
-                                    new Basics.DllData.NamespaceData.ClassData()
-                                    {
-                                        ClassName="MqttClientOperate",
-                                        ConstructorParam=new object[]{ new MqttClientData.Basics { QualityOfServiceLevel = MQTTnet.Protocol.MqttQualityOfServiceLevel.AtMostOnce, ServerIPAddress = "127.0.0.1", ServerLoginID = "ysai", ServerLoginPassword = "ysai", ServerPort = 11819 } },
-                                        SN="YSAI.Mqtt.MqttClientOperate[Instance]",
-                                        MethodDatas=new List<Basics.DllData.NamespaceData.ClassData.MethodData>()
-                                        {
-                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
-                                            {
-                                                MethodName="Init",
-                                                SN="[Init]",
-                                                WhetherExecute=true
-                                            },
-                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
-                                            {
-                                                MethodName="On",
-                                                SN="[On]",
-                                                WhetherExecute=true
-                                            },
-                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
-                                            {
-                                                MethodName="Off",
-                                                SN="[Off]"
-                                            },
-                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
-                                            {
-                                                MethodName="PublishSubscribe",
-                                                SN="[PublishSubscribe]"
-                                            },
-                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
-                                            {
-                                                MethodName="AddSubscribe",
-                                                SN="[AddSubscribe]"
-                                            },
-                                            new Basics.DllData.NamespaceData.ClassData.MethodData()
-                                            {
-                                                MethodName="RemoveSubscribe",
-                                                SN="[RemoveSubscribe]"
-                                            }
-                                        },
-                                        EventDatas=new List<ClassData.EventData>()
-                                        {
-                                            new ClassData.EventData()
-                                            {
-                                                EventName="OnEvent",
-                                                SN="[OnEvent]"
-                                            }
-                                        }
-                                    }
-                                }
-                            }
-                        }
-                    }
+                    Console.WriteLine(item.Key);
+                    Console.WriteLine(item.Value.Value);
                 }
-            };
-            //生成文件
-            FileTool.StringToFile(ReflectionOperate.ConfigFile, JsonTool.JsonEntityToString(basics).JsonFormatting());
-
-
+            }
 
+            //写入
+            ConcurrentDictionary<string, float> keyValuePairs=new ConcurrentDictionary<string, float>();
+            keyValuePairs.TryAdd("DB71.DBD4", 1.6666f);
+            operateResult = s7ClientOperate.Write(keyValuePairs);
+            Console.WriteLine(operateResult.Message);
+            
 
 
 

+ 1 - 0
src/YSAI.DAQ/YSAI.Unility/ExtensionTool.cs

@@ -18,6 +18,7 @@ namespace YSAI.Unility
     /// </summary>
     public static class ExtensionTool
     {
+
         public static string UTF8ToBase64(this string data)
         {
             if (data.IsEmpty())