Selaa lähdekoodia

1. 自定义订阅修改
2. 版本更新
3. 修改对象比对

Shun 2 vuotta sitten
vanhempi
commit
a45b14f504

+ 1 - 1
src/YSAI.DAQ/YSAI.Can/YSAI.Can.csproj

@@ -17,7 +17,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 
   <ItemGroup>

+ 2 - 2
src/YSAI.DAQ/YSAI.Core/YSAI.Core.csproj

@@ -5,7 +5,7 @@
     <ImplicitUsings>enable</ImplicitUsings>
     <Nullable>enable</Nullable>
     <GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-    <Version>1.0.0.50</Version>
+    <Version>1.0.0.54</Version>
     <Authors>Shun</Authors>
     <Company>YSAI</Company>
     <Product>SCADA</Product>
@@ -17,7 +17,7 @@
 		<PackageReference Include="Microsoft.ClearScript" Version="7.4.3" />
 		<PackageReference Include="System.IO.Ports" Version="7.0.0" />
 		<PackageReference Include="YSAI.Log" Version="1.0.0.9" />
-		<PackageReference Include="YSAI.Unility" Version="1.0.0.16" />
+		<PackageReference Include="YSAI.Unility" Version="1.0.0.17" />
 	</ItemGroup>
 
 </Project>

+ 2 - 2
src/YSAI.DAQ/YSAI.Core/data/AddressValue.cs

@@ -22,7 +22,7 @@ namespace YSAI.Core.data
         /// <summary>
         /// 获取或更新的时间
         /// </summary>
-        public DateTime Time { get; set; } = DateTime.Now.GetDateDetails();
+        public DateTime Time { get; set; } = DateTime.Now;
 
         /// <summary>
         /// 设置父类的参数
@@ -51,7 +51,7 @@ namespace YSAI.Core.data
         /// <returns></returns>
         public override bool Equals(object o)
         {
-            return this.Comparer(o as AddressValue).result;
+            return this.Comparer(o as AddressValue, new string[] { "Time" }).result;
         }
     }
 }

+ 190 - 191
src/YSAI.DAQ/YSAI.Core/subscribe/SubscribeOperate.cs

@@ -1,5 +1,7 @@
 using System.Collections.Concurrent;
+using System.Runtime.CompilerServices;
 using YSAI.Core.data;
+using YSAI.Core.@enum;
 using YSAI.Core.@interface;
 using YSAI.Unility;
 
@@ -73,120 +75,6 @@ namespace YSAI.Core.subscription
         /// </summary>
         CancellationTokenSource MonitorSwitch;
 
-        /// <summary>
-        /// 轮询任务处理
-        /// </summary>
-        Task PollTaskHandle;
-
-        /// <summary>
-        /// 别的操作进来是否继续轮询
-        /// </summary>
-        bool GoOn = true;
-
-        /// <summary>
-        /// 上一次的数据
-        /// </summary>
-        ConcurrentDictionary<string, AddressValue> UpParam;
-        /// <summary>
-        /// 上一次的数据
-        /// </summary>
-        List<ConcurrentDictionary<string, AddressValue>> UpParamArray;
-
-
-
-
-        /// <summary>
-        /// 现场安全字典比对,是否一致
-        /// </summary>
-        /// <param name="Param1"></param>
-        /// <param name="Param2"></param>
-        /// <returns></returns>
-        bool ConcurrentDictionaryEquals(ConcurrentDictionary<string, AddressValue> Param1, ConcurrentDictionary<string, AddressValue> Param2)
-        {
-            bool equal = false;
-            if (Param1.Count == Param2.Count)
-            {
-                equal = true;
-                foreach (var pair in Param1)
-                {
-                    AddressValue value;
-                    if (Param2.TryGetValue(pair.Key, out value))
-                    {
-                        if (!value.Equals(pair.Value))
-                        {
-                            equal = false;
-                            break;
-                        }
-                    }
-                    else
-                    {
-                        equal = false;
-                        break;
-                    }
-                }
-            }
-            return equal;
-        }
-
-        /// <summary>
-        /// 现场安全字典比对,是否一致
-        /// </summary>
-        /// <param name="Param1"></param>
-        /// <param name="Param2"></param>
-        /// <returns></returns>
-        bool ConcurrentDictionaryEquals(List<ConcurrentDictionary<string, AddressValue>> Param1, List<ConcurrentDictionary<string, AddressValue>> Param2)
-        {
-            foreach (ConcurrentDictionary<string, AddressValue> a in Param2)
-            {
-                if (!Param1.Exists(b => ConcurrentDictionaryEquals(a, b)))
-                {
-                    return false;
-                }
-            }
-            return true;
-        }
-
-        /// <summary>
-        /// 执行轮询
-        /// </summary>
-        Task Polling(CancellationTokenSource token)
-        {
-            //起个新线程处理
-            return Task.Factory.StartNew(() =>
-            {
-                while (!token.IsCancellationRequested)
-                {
-                    try
-                    {
-                        if (!GoOn) continue;
-                        lock (basics.Address)  //锁住不让其他操作
-                        {
-                            //数据必须大于0才进行
-                            if (basics.Address.AddressArray.Count > 0)
-                            {
-                                //执行委托
-                                OperateResult value = basics.Function?.Invoke(basics.Address);
-                                //判断一下
-                                if (!token.IsCancellationRequested)
-                                {
-                                    //数据入列
-                                    DataQueue.Enqueue(new QueueData() { value = value });
-                                }
-                                else
-                                {
-                                    return;
-                                }
-                            }
-                        }
-                    }
-                    catch (Exception ex)
-                    {
-                        OnEventHandler(this, new EventResult(false, $"自定义订阅轮询异常:{ex.Message}"));
-                    }
-                    Thread.Sleep(basics.HandleInterval);
-                }
-            }, token.Token);
-        }
         /// <summary>
         /// 释放
         /// </summary>
@@ -284,7 +172,7 @@ namespace YSAI.Core.subscription
                     //当队列为空,初始化队列
                     if (DataQueue == null)
                     {
-                        DataQueue = new ConcurrentQueue<QueueData>();
+                        DataQueue = new ConcurrentQueue<AddressValue>();
                     }
 
                     //任务为空创建任务
@@ -368,17 +256,6 @@ namespace YSAI.Core.subscription
         }
 
 
-
-        /// <summary>
-        /// 队列数据
-        /// </summary>
-        private class QueueData
-        {
-            /// <summary>
-            /// 操作结果
-            /// </summary>
-            public OperateResult value { get; set; }
-        }
         /// <summary>
         /// 任务集合
         /// </summary>
@@ -386,101 +263,170 @@ namespace YSAI.Core.subscription
         /// <summary>
         /// 数据队列
         /// </summary>
-        private ConcurrentQueue<QueueData> DataQueue;
+        private ConcurrentQueue<AddressValue> DataQueue;
+        /// <summary>
+        /// 轮询任务处理
+        /// </summary>
+        Task PollTaskHandle;
 
         /// <summary>
-        /// 任务处理
+        /// 别的操作进来是否继续轮询
         /// </summary>
-        /// <param name="token">任务令牌</param>
-        /// <returns>任务</returns>
-        private Task TaskHandle(CancellationTokenSource token)
+        bool GoOn = true;
+
+        /// <summary>
+        /// 数据缓存池
+        /// </summary>
+        ConcurrentDictionary<string, AddressValue> DataCachePool = new ConcurrentDictionary<string, AddressValue>();
+        /// <summary>
+        /// 多组数据缓存池
+        /// </summary>
+        List<ConcurrentDictionary<string, AddressValue>> DataCachePoolArray = new List<ConcurrentDictionary<string, AddressValue>>();
+
+        /// <summary>
+        /// 执行轮询
+        /// </summary>
+        Task Polling(CancellationTokenSource token)
         {
             //起个新线程处理
             return Task.Factory.StartNew(() =>
             {
                 while (!token.IsCancellationRequested)
                 {
-                    //队列数据
-                    QueueData? queueData;
-                    while (DataQueue.TryDequeue(out queueData))
+                    try
                     {
-                        if (queueData != null && !token.IsCancellationRequested)
+                        if (!GoOn) continue;
+                        lock (basics.Address)  //锁住不让其他操作
                         {
-                            //状态判断
-                            if (queueData.value.State)
+                            //数据必须大于0才进行
+                            if (basics.Address.AddressArray.Count > 0)
                             {
-                                //判断数据类型
-                                switch (queueData.value.RType)
+                                //执行委托
+                                OperateResult value = basics.Function?.Invoke(basics.Address);
+                                if (value.State)
                                 {
-                                    case @enum.ResultType.KeyValue:
-                                        ConcurrentDictionary<string, AddressValue>? RData = queueData.value.RData as ConcurrentDictionary<string, AddressValue>;
-                                        //做流程处理
-                                        if (basics.ChangeOut)
+                                    //判断一下
+                                    if (!token.IsCancellationRequested)
+                                    {
+                                        switch (value.RType)
                                         {
-                                            //实例化对象
-                                            if (UpParam == null)
-                                            {
-                                                UpParam = new ConcurrentDictionary<string, AddressValue>();
-                                            }
-                                            //空数据不做处理
-                                            if (RData != null && RData.Count > 0)
-                                            {
-                                                //获取到第一次数据,准备节点检测数据是否变化
-                                                if (!ConcurrentDictionaryEquals(UpParam, RData))
+                                            case ResultType.KeyValue:
+
+                                                ConcurrentDictionary<string, AddressValue> resultData = value.RData as ConcurrentDictionary<string, AddressValue>;
+                                                //空数据不做处理
+                                                if (resultData != null && resultData.Count > 0)
                                                 {
-                                                    //当节点数据变化,有一项数据未变化,也把这未变项与变化项一同抛出,在特殊用途中,确保此批点位数据都存在
-                                                    if (basics.AllOut)
+                                                    if (basics.ChangeOut)
                                                     {
-                                                        //抛出差异数据
-                                                        OnEventHandler(this, new EventResult(true, "存在变化数据", RData, queueData.value.RType));
+                                                        if (!ConcurrentDictionaryEquals(DataCachePool, resultData))
+                                                        {
+                                                            if (basics.AllOut)
+                                                            {
+                                                                //抛出差异数据
+                                                                OnEventHandler(this, new EventResult(true, "存在变化数据", resultData, ResultType.KeyValue));
+                                                            }
+                                                            else
+                                                            {
+                                                                //数据入列
+                                                                foreach (var item in resultData)
+                                                                {
+                                                                    DataQueue.Enqueue(item.Value);
+                                                                }
+                                                            }
+                                                        }
+                                                        DataCachePool = resultData;
                                                     }
                                                     else
                                                     {
-                                                        //如果不一致,就找寻里面不一样的 键、值
-                                                        ConcurrentDictionary<string, AddressValue> data = new ConcurrentDictionary<string, AddressValue>(RData.Except(UpParam).ToDictionary(x => x.Key, x => x.Value));
                                                         //抛出差异数据
-                                                        OnEventHandler(this, new EventResult(true, "变化数据", data, queueData.value.RType));
+                                                        OnEventHandler(this, new EventResult(true, "实时数据", resultData, ResultType.KeyValue));
                                                     }
-                                                    //把这次新数据 赋值到历史数据中
-                                                    UpParam = RData;
                                                 }
-                                            }
-                                        }
-                                        else
-                                        {
-                                            OnEventHandler(this, new EventResult(true, "实时数据", queueData.value.RData, queueData.value.RType));
-                                        }
-                                        break;
-                                    case @enum.ResultType.KeyValueArray:
-                                        List<ConcurrentDictionary<string, AddressValue>>? RDataArray = queueData.value.RData as List<ConcurrentDictionary<string, AddressValue>>;
-                                        //实例化对象
-                                        if (UpParamArray == null)
-                                        {
-                                            UpParamArray = new List<ConcurrentDictionary<string, AddressValue>>();
-                                        }
-                                        //空数据不做处理
-                                        if (RDataArray != null && RDataArray.Count > 0)
-                                        {
-                                            //获取到第一次数据,准备节点检测数据是否变化
-                                            if (!ConcurrentDictionaryEquals(UpParamArray, RDataArray))
-                                            {
-                                                foreach (var item in RDataArray)
+                                                break;
+                                            case ResultType.KeyValueArray:
+                                                List<ConcurrentDictionary<string, AddressValue>>? resultDataArray = value.RData as List<ConcurrentDictionary<string, AddressValue>>;
+                                                //空数据不做处理
+                                                if (resultDataArray != null && resultDataArray.Count > 0)
                                                 {
-                                                    //抛出差异数据
-                                                    OnEventHandler(this, new EventResult(true, "存在变化数据", RDataArray, queueData.value.RType));
+                                                    if (basics.ChangeOut)
+                                                    {
+                                                        if (!ConcurrentDictionaryEquals(DataCachePoolArray, resultDataArray))
+                                                        {
+                                                            //抛出差异数据
+                                                            OnEventHandler(this, new EventResult(true, "存在变化数据", resultDataArray, ResultType.KeyValueArray));
+                                                        }
+                                                        DataCachePoolArray = resultDataArray;
+                                                    }
+                                                    else
+                                                    {
+                                                        //抛出差异数据
+                                                        OnEventHandler(this, new EventResult(true, "实时数据", resultDataArray, ResultType.KeyValueArray));
+                                                    }
                                                 }
-                                                //把这次新数据 赋值到历史数据中
-                                                UpParamArray = RDataArray;
-                                            }
+                                                break;
                                         }
-                                        break;
+                                    }
+                                    else
+                                    {
+                                        return;
+                                    }
+                                }
+                                else
+                                {
+                                    //当状态为false 说明读取失败,写入日志
+                                    OnEventHandler(this, new EventResult(false, $"自定义订阅轮询异常:{value.Message}"));
+                                }
+                            }
+                        }
+                    }
+                    catch (Exception ex)
+                    {
+                        OnEventHandler(this, new EventResult(false, $"自定义订阅轮询异常:{ex.Message}"));
+                    }
+                    Thread.Sleep(basics.HandleInterval);
+                }
+            }, token.Token);
+        }
+
+        /// <summary>
+        /// 数据缓存
+        /// </summary>
+        ConcurrentDictionary<string, AddressValue> DataCache = new ConcurrentDictionary<string, AddressValue>();
+
+
+
+        /// <summary>
+        /// 任务处理
+        /// </summary>
+        /// <param name="token">任务令牌</param>
+        /// <returns>任务</returns>
+        private Task TaskHandle(CancellationTokenSource token)
+        {
+            //起个新线程处理
+            return Task.Factory.StartNew(() =>
+            {
+                while (!token.IsCancellationRequested)
+                {
+                    //队列数据
+                    AddressValue? queueData;
+                    while (DataQueue.TryDequeue(out queueData))
+                    {
+                        if (queueData != null && !token.IsCancellationRequested)
+                        {
+                            if (DataCache.ContainsKey(queueData.AddressName))
+                            {
+                                if (!DataCache[queueData.AddressName].Equals(queueData))
+                                {
+                                    //抛出差异数据
+                                    OnEventHandler(this, new EventResult(true, "变化数据", new ConcurrentDictionary<string, AddressValue> { [queueData.AddressName] = queueData }, RType: ResultType.KeyValue));
                                 }
                             }
                             else
                             {
-                                //当状态为false 说明读取失败,写入日志
-                                OnEventHandler(this, new EventResult(false, $"自定义订阅轮询异常:{queueData.value.Message}"));
+                                //抛出差异数据
+                                OnEventHandler(this, new EventResult(true, "变化数据", new ConcurrentDictionary<string, AddressValue> { [queueData.AddressName] = queueData }, RType: ResultType.KeyValue));
                             }
+                            DataCachePool.AddOrUpdate(queueData.AddressName, queueData, (k, v) => queueData);
                         }
                     }
                     //队列里面的数据处理完休息一下
@@ -488,5 +434,58 @@ namespace YSAI.Core.subscription
                 }
             }, token.Token);
         }
+        
+
+        /// <summary>
+        /// 线程安全字典比对,是否一致
+        /// </summary>
+        /// <param name="Param1"></param>
+        /// <param name="Param2"></param>
+        /// <returns></returns>
+        bool ConcurrentDictionaryEquals(ConcurrentDictionary<string, AddressValue> Param1, ConcurrentDictionary<string, AddressValue> Param2)
+        {
+            bool equal = false;
+            if (Param1.Count == Param2.Count)
+            {
+                equal = true;
+                foreach (var pair in Param1)
+                {
+                    AddressValue value;
+                    if (Param2.TryGetValue(pair.Key, out value))
+                    {
+                        if (!value.Equals(pair.Value))
+                        {
+                            equal = false;
+                            break;
+                        }
+                    }
+                    else
+                    {
+                        equal = false;
+                        break;
+                    }
+                }
+            }
+            return equal;
+        }
+
+        /// <summary>
+        /// 线程安全字典比对,是否一致
+        /// </summary>
+        /// <param name="Param1"></param>
+        /// <param name="Param2"></param>
+        /// <returns></returns>
+        bool ConcurrentDictionaryEquals(List<ConcurrentDictionary<string, AddressValue>> Param1, List<ConcurrentDictionary<string, AddressValue>> Param2)
+        {
+            foreach (ConcurrentDictionary<string, AddressValue> a in Param2)
+            {
+                if (!Param1.Exists(b => ConcurrentDictionaryEquals(a, b)))
+                {
+                    return false;
+                }
+            }
+            return true;
+        }
+
     }
 }

+ 1 - 1
src/YSAI.DAQ/YSAI.DB/YSAI.DB.csproj

@@ -18,7 +18,7 @@
 		<PackageReference Include="System.Data.OracleClient" Version="1.0.8" />
 		<PackageReference Include="System.Data.SqlClient" Version="4.8.5" />
 		<PackageReference Include="System.Data.SQLite" Version="1.0.118" />
-		<PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+		<PackageReference Include="YSAI.Core" Version="1.0.0.53" />
 	</ItemGroup>
 	<!--<ItemGroup>
 		<ProjectReference Include="..\YSAI.Core\YSAI.Core.csproj" />

+ 1 - 1
src/YSAI.DAQ/YSAI.DaqManage/YSAI.DaqManage.csproj

@@ -7,7 +7,7 @@
   </PropertyGroup>
 	<ItemGroup>
 		<FrameworkReference Include="Microsoft.AspNetCore.App" />
-		<PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+		<PackageReference Include="YSAI.Core" Version="1.0.0.53" />
 	</ItemGroup>
 
 	<!--<ItemGroup>

+ 1 - 1
src/YSAI.DAQ/YSAI.Kafka/YSAI.Kafka.csproj

@@ -14,7 +14,7 @@
 
   <ItemGroup>
     <PackageReference Include="Confluent.Kafka" Version="2.2.0" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 	
 	<!--<ItemGroup>

+ 1 - 1
src/YSAI.DAQ/YSAI.Modbus/YSAI.Modbus.csproj

@@ -15,7 +15,7 @@
 	<ItemGroup>
     <PackageReference Include="NModbus" Version="3.0.80" />
     <PackageReference Include="NModbus.Serial" Version="3.0.80" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 
 	<!--<ItemGroup>

+ 1 - 1
src/YSAI.DAQ/YSAI.Mqtt/YSAI.Mqtt.csproj

@@ -15,7 +15,7 @@
   <ItemGroup>
     <PackageReference Include="MQTTnet" Version="4.3.1.873" />
     <PackageReference Include="MQTTnet.AspNetCore" Version="4.3.1.873" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 
 	<!--<ItemGroup>

+ 1 - 1
src/YSAI.DAQ/YSAI.Opc/YSAI.Opc.csproj

@@ -13,7 +13,7 @@
   </PropertyGroup>
   <ItemGroup>
     <PackageReference Include="OPCFoundation.NetStandard.Opc.Ua" Version="1.4.372.56" />
-	<PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+	<PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 
 

+ 1 - 1
src/YSAI.DAQ/YSAI.RabbitMQ/YSAI.RabbitMQ.csproj

@@ -14,7 +14,7 @@
 
   <ItemGroup>
     <PackageReference Include="RabbitMQ.Client" Version="6.6.0" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 
   <ItemGroup>

+ 1 - 1
src/YSAI.DAQ/YSAI.RelayManage/YSAI.RelayManage.csproj

@@ -9,7 +9,7 @@
 	<ItemGroup>
 		<PackageReference Include="RabbitMQ.Client" Version="6.6.0" />
 		<PackageReference Include="Confluent.Kafka" Version="2.2.0" />
-		<PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+		<PackageReference Include="YSAI.Core" Version="1.0.0.53" />
 		<FrameworkReference Include="Microsoft.AspNetCore.App" />
 	</ItemGroup>
 

+ 1 - 1
src/YSAI.DAQ/YSAI.S7/YSAI.S7.csproj

@@ -14,7 +14,7 @@
 
 	<ItemGroup>
     <PackageReference Include="S7netplus" Version="0.20.0" />
-    <PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+    <PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 
 	<!--<ItemGroup>

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

@@ -1,226 +0,0 @@
-using S7.Net.Types;
-using System.Globalization;
-
-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;
-        }
-
-
-
-    }
-}

+ 280 - 127
src/YSAI.DAQ/YSAI.Test.All/Program.cs

@@ -1,159 +1,310 @@
-
-
-
+using S7.Net;
 using System.Collections.Concurrent;
 using YSAI.Core.data;
-using YSAI.Core.@interface;
-
+using YSAI.Core.@enum;
+using YSAI.Log;
+using YSAI.S7.client;
+using YSAI.Unility;
 
 
-for (var i = 0; i < 101; i++)
+S7ClientOperate s7ClientOperate = S7ClientOperate.Instance(new S7ClientData.Basics()
+{
+    Ip = "192.168.2.20",
+    Port = 102,
+    Rack = 0,
+    Slot = 1,
+    S7CpuType = CpuType.S71200,
+    ChangeOut = true,
+    HandleInterval = 1,
+    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()
+{
+    AddressName = "DB71.DBD4",
+    AddressDataType = YSAI.Core.@enum.DataType.String,
+    AddressType = AddressType.Reality
+});
+
+//读取
+operateResult = s7ClientOperate.Read(address);
+Console.WriteLine(operateResult.Message);
+if (operateResult.State)
 {
-    test.Instance(new testData.Basics());
+    foreach (var item in operateResult.RData as ConcurrentDictionary<string, AddressValue>)
+    {
+        Console.WriteLine(item.Key);
+        Console.WriteLine(item.Value.Value);
+    }
 }
 
+//订阅
+s7ClientOperate.OnEvent += S7ClientOperate_OnEvent;
+s7ClientOperate.Subscribe(address);
 
-public class testData
+while (true)
 {
-    /// <summary>
-    /// 基础数据
-    /// </summary>
-    public class Basics 
-    {
-       
-    }
+    string value = Console.ReadLine();
+    //写入
+    ConcurrentDictionary<string, string> keyValuePairs = new ConcurrentDictionary<string, string>();
+    keyValuePairs.TryAdd("DB71.DBD4", value);
+    operateResult = s7ClientOperate.Write(keyValuePairs);
+    Console.WriteLine(operateResult.Message);
 }
-public class test : IBaseAbstract, IDaq
+
+void S7ClientOperate_OnEvent(object? sender, EventResult e)
 {
+    Console.WriteLine(e.ToJson());
+}
 
-    protected override string TAG => "S7ClientOperate";
-    /// <summary>
-    /// 单例锁
-    /// </summary>
-    protected static readonly object Lock = new object();
-    /// <summary>
-    /// 自身对象集合
-    /// </summary>
-    private static List<test> ThisObjList = new List<test>();
-    /// <summary>
-    /// 单例模式
-    /// </summary>
-    /// <returns></returns>
-    public static test Instance(testData.Basics basics)
-    {
-        if (ThisObjList.Count >= MaxInstanceCount)
-        {
-            throw new Exception(ExceedMaxInstanceCountTips);
-        }
-        test? exp = ThisObjList.FirstOrDefault(c=> c.basics.Equals(basics));
-        if (exp == null)
-        {
-            lock (Lock)
-            {
-                if (ThisObjList.Count(c => c.basics.Equals(basics)) > 0)
-                {
-                    return ThisObjList.First(c => c.basics.Equals(basics));
-                }
-                else
-                {
-                    test exp2 = new test(basics);
-                    ThisObjList.Add(exp2);
-                    return exp2;
-                }
-            }
-        }
-        return exp;
-    }
 
-    /// <summary>
-    /// 构造函数
-    /// </summary>
-    /// <param name="basics"></param>
-    public test(testData.Basics basics)
-    {
-        this.basics = basics;
-    }
 
-    /// <summary>
-    /// 基础数据
-    /// </summary>
-    private testData.Basics basics { get; set; }
 
-    public void Dispose()
-    {
-        throw new NotImplementedException();
-    }
 
-    public OperateResult GetStatus()
-    {
-        throw new NotImplementedException();
-    }
 
-    public Task<OperateResult> GetStatusAsync()
-    {
-        throw new NotImplementedException();
-    }
+//S7ClientOperate s7ClientOperate = S7ClientOperate.Instance(new S7ClientData.Basics()
+//{
+//    Ip = "172.16.21.79",
+//    Port = 102,
+//    Rack = 0,
+//    Slot = 2,
+//    S7CpuType = CpuType.S7300,
+//    ChangeOut = true,
+//    HandleInterval = 1,
+//    SN = Guid.NewGuid().ToString()
+//}); ;
 
-    public OperateResult Off()
-    {
-        throw new NotImplementedException();
-    }
+////打开
+//OperateResult operateResult = s7ClientOperate.On();
+//LogHelper.Verbose(operateResult.Message);
 
-    public Task<OperateResult> OffAsync()
-    {
-        throw new NotImplementedException();
-    }
+////点位地址
+//Address address = new Address();
+//address.SN = Guid.NewGuid().ToString();
+//address.CreationTime = DateTime.Now.GetDateDetails(); ;
+//address.AddressArray = new List<AddressDetails>();
 
-    public OperateResult On()
-    {
-        throw new NotImplementedException();
-    }
 
-    public Task<OperateResult> OnAsync()
-    {
-        throw new NotImplementedException();
-    }
+//List<string> addresss = new List<string>
+//{
+//  "DB71.DBD636",
+//  "DB71.DBDL450",
+//  "DB71.DBD546",
+//  "DB602.DBD450",
+//  "DB71.DBD550"
+//  };
 
-    public OperateResult Read(Address address)
-    {
-        throw new NotImplementedException();
-    }
+//List<string> msgs = new List<string>
+//{
+//  "ZS4.ZS4.LRD3_3238_OutputTem 三千滚筒烘丝出口物料温度",
+//  "ZS4.ZS4.LRD3_KL3236_BucketTemp2 三千滚筒烘丝2区筒壁温度",
+//  "ZS4.ZS4.LRD3_KL3236_BacCoverPrePV   三千滚筒烘丝罩压力",
+//  "ZS4.ZS4.LRD3_KL3236_ZKLD_HT_OUTTEMP 三千烘丝入口温度",
+//  "ZS4.ZS4.LRD3_KL3236_MoisRemovalVal  三千滚筒烘丝排潮风门"
+//};
 
-    public Task<OperateResult> ReadAsync(Address address)
-    {
-        throw new NotImplementedException();
-    }
+//for (int i = 0; i < addresss.Count; i++)
+//{
+//    address.AddressArray.Add(new AddressDetails()
+//    {
+//        AddressName = addresss[i].Trim(),
+//        AddressDataType = YSAI.Core.@enum.DataType.Float,
+//        AddressDescribe = msgs[i],
+//        AddressType = AddressType.Reality
+//    });
+//}
 
-    public OperateResult Subscribe(Address address)
-    {
-        throw new NotImplementedException();
-    }
 
-    public Task<OperateResult> SubscribeAsync(Address address)
-    {
-        throw new NotImplementedException();
-    }
 
-    public OperateResult UnSubscribe(Address address)
-    {
-        throw new NotImplementedException();
-    }
 
-    public Task<OperateResult> UnSubscribeAsync(Address address)
-    {
-        throw new NotImplementedException();
-    }
+////读取
+//operateResult = s7ClientOperate.Read(address);
+//LogHelper.Verbose(operateResult.Message);
+//if (operateResult.State)
+//{
+//    foreach (var item in operateResult.RData as ConcurrentDictionary<string, AddressValue>)
+//    {
+//        LogHelper.Verbose(item.Key);
+//        LogHelper.Verbose(item.Value.Value);
+//    }
+//}
 
-    public OperateResult Write<V>(ConcurrentDictionary<string, V> Values)
-    {
-        throw new NotImplementedException();
-    }
+////订阅
+//s7ClientOperate.OnEvent += S7ClientOperate_OnEvent;
+//s7ClientOperate.Subscribe(address);
 
-    public Task<OperateResult> WriteAsync<V>(ConcurrentDictionary<string, V> Values)
-    {
-        throw new NotImplementedException();
-    }
-}
+//while (true)
+//{
+//    Console.ReadLine();
+//}
+
+//void S7ClientOperate_OnEvent(object? sender, EventResult e)
+//{
+//    LogHelper.Verbose(e.ToJson());
+//}
+
+
+//using System.Collections.Concurrent;
+//using YSAI.Core.data;
+//using YSAI.Core.@interface;
+
+
+
+//for (var i = 0; i < 101; i++)
+//{
+//    test.Instance(new testData.Basics());
+//}
+
+
+//public class testData
+//{
+//    /// <summary>
+//    /// 基础数据
+//    /// </summary>
+//    public class Basics 
+//    {
+
+//    }
+//}
+//public class test : IBaseAbstract, IDaq
+//{
+
+//    protected override string TAG => "S7ClientOperate";
+//    /// <summary>
+//    /// 单例锁
+//    /// </summary>
+//    protected static readonly object Lock = new object();
+//    /// <summary>
+//    /// 自身对象集合
+//    /// </summary>
+//    private static List<test> ThisObjList = new List<test>();
+//    /// <summary>
+//    /// 单例模式
+//    /// </summary>
+//    /// <returns></returns>
+//    public static test Instance(testData.Basics basics)
+//    {
+//        if (ThisObjList.Count >= MaxInstanceCount)
+//        {
+//            throw new Exception(ExceedMaxInstanceCountTips);
+//        }
+//        test? exp = ThisObjList.FirstOrDefault(c=> c.basics.Equals(basics));
+//        if (exp == null)
+//        {
+//            lock (Lock)
+//            {
+//                if (ThisObjList.Count(c => c.basics.Equals(basics)) > 0)
+//                {
+//                    return ThisObjList.First(c => c.basics.Equals(basics));
+//                }
+//                else
+//                {
+//                    test exp2 = new test(basics);
+//                    ThisObjList.Add(exp2);
+//                    return exp2;
+//                }
+//            }
+//        }
+//        return exp;
+//    }
+
+//    /// <summary>
+//    /// 构造函数
+//    /// </summary>
+//    /// <param name="basics"></param>
+//    public test(testData.Basics basics)
+//    {
+//        this.basics = basics;
+//    }
+
+//    /// <summary>
+//    /// 基础数据
+//    /// </summary>
+//    private testData.Basics basics { get; set; }
+
+//    public void Dispose()
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public OperateResult GetStatus()
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public Task<OperateResult> GetStatusAsync()
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public OperateResult Off()
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public Task<OperateResult> OffAsync()
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public OperateResult On()
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public Task<OperateResult> OnAsync()
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public OperateResult Read(Address address)
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public Task<OperateResult> ReadAsync(Address address)
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public OperateResult Subscribe(Address address)
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public Task<OperateResult> SubscribeAsync(Address address)
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public OperateResult UnSubscribe(Address address)
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public Task<OperateResult> UnSubscribeAsync(Address address)
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public OperateResult Write<V>(ConcurrentDictionary<string, V> Values)
+//    {
+//        throw new NotImplementedException();
+//    }
+
+//    public Task<OperateResult> WriteAsync<V>(ConcurrentDictionary<string, V> Values)
+//    {
+//        throw new NotImplementedException();
+//    }
+//}
 
 
 //using YSAI.Unility;
@@ -162,9 +313,11 @@ public class test : IBaseAbstract, IDaq
 
 //A a = new A();
 //a.Id = 1;
+//a.Name = "A";
 
 //A b = new A();
 //b.Id = 1;
+//b.Name = "B";
 
 
 

+ 18 - 0
src/YSAI.DAQ/YSAI.Test.All/Properties/PublishProfiles/FolderProfile.pubxml

@@ -0,0 +1,18 @@
+<?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\linux-x64\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+    <_TargetId>Folder</_TargetId>
+    <TargetFramework>net6.0</TargetFramework>
+    <RuntimeIdentifier>linux-x64</RuntimeIdentifier>
+    <SelfContained>true</SelfContained>
+    <PublishSingleFile>false</PublishSingleFile>
+    <PublishTrimmed>false</PublishTrimmed>
+  </PropertyGroup>
+</Project>

+ 1 - 1
src/YSAI.DAQ/YSAI.Test.All/YSAI.Test.All.csproj

@@ -13,7 +13,7 @@
   </ItemGroup>
 
   <ItemGroup>
-    <ProjectReference Include="..\YSAI.Core\YSAI.Core.csproj" />
+    <ProjectReference Include="..\YSAI.S7\YSAI.S7.csproj" />
   </ItemGroup>
 
 

+ 1 - 1
src/YSAI.DAQ/YSAI.Test/YSAI.Test.csproj

@@ -17,7 +17,7 @@
       <PrivateAssets>all</PrivateAssets>
       <IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
     </PackageReference>
-	<PackageReference Include="YSAI.Core" Version="1.0.0.50" />
+	<PackageReference Include="YSAI.Core" Version="1.0.0.53" />
   </ItemGroup>
 
   <ItemGroup>

+ 17 - 7
src/YSAI.DAQ/YSAI.Unility/ExtensionTool.cs

@@ -17,18 +17,28 @@ namespace YSAI.Unility
         /// <typeparam name="T">泛型对象</typeparam>
         /// <param name="a">对象A</param>
         /// <param name="b">对象B</param>
+        /// <param name="ignoreMember">按名称忽略特定成员</param>
         /// <returns>(是否一致,不一致的原因)</returns>
-        public static (bool result, string message) Comparer<T>(this T a, T b)
+        public static (bool result, string message) Comparer<T>(this T a, T b, string[]? ignoreMember = null)
         {
-            (bool result, string message) rm = new(false, string.Empty);
-            var comparer = new objectsComparer.Comparer<T>();
+            //操作结果
+            (bool result, string message) OR = new(false, string.Empty);
+            objectsComparer.Comparer<T> comparer = new objectsComparer.Comparer<T>();
             IEnumerable<Difference> differences;
-            rm.result = comparer.Compare(a, b, out differences);
-            if (!rm.result)
+            //忽略比对成员
+            if (ignoreMember != null && ignoreMember.Length > 0)
             {
-                rm.message = string.Join(Environment.NewLine, differences);
+                for (int i = 0; i < ignoreMember.Length; i++)
+                {
+                    comparer.IgnoreMember(ignoreMember[i]);
+                }
+            }
+            OR.result = comparer.Compare(a, b, out differences);
+            if (!OR.result)
+            {
+                OR.message = string.Join(Environment.NewLine, differences);
             }
-            return rm;
+            return OR;
         }
         /// <summary>
         /// 判断为空GUID

+ 1 - 1
src/YSAI.DAQ/YSAI.Unility/YSAI.Unility.csproj

@@ -5,7 +5,7 @@
 		<ImplicitUsings>enable</ImplicitUsings>
 		<Nullable>enable</Nullable>
 		<GeneratePackageOnBuild>True</GeneratePackageOnBuild>
-		<Version>1.0.0.16</Version>
+		<Version>1.0.0.17</Version>
 		<Authors>Shun</Authors>
 		<Company>YSAI</Company>
 		<Product>SCADA</Product>