lixiaojun
2024-11-19 a5b6334ae09f2be1a5c073169458b55df68b0b2e
新增一个水质仪对接
已修改3个文件
已添加25个文件
1104 ■■■■■ 文件已修改
IStation.DataDocking.Socket.sln 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDocking.Socket/IStation.DataDocking.Socket.csproj 1 ●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/GlobalUsings.cs 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/HandleHelper.cs 137 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/IStation.DataDockingSocket.SZJT_SZY1.csproj 24 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/Middle/MiddleRecord.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewResult.cs 38 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewStandardModel.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewStandardRecord.cs 25 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewStandardSubRecord.cs 26 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldResult.cs 23 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldStandardModel.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldStandardRecord.cs 30 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldStandardSubRecord.cs 21 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/helper/ConfigHelper.cs 45 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/helper/DebugHelper.cs 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/helper/HandleDataHelper.cs 92 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/helper/OldTransferHelper.cs 41 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/helper/SessionHelper.cs 13 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/helper/SrcHelper.cs 22 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/instruction/SendInstructionJob.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/instruction/SendInstructionJobHelper.cs 100 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/instruction/SendInstructionJobNameHelper.cs 40 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/paras/AppParas.cs 176 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/paras/AppParasHelper.cs 39 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDockingSocket.SZJT_SZY1/paras_datadocking_socket_szjt_szy1.json 42 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.TopShelf.DataDocking4Socket/IStation.TopShelf.DataDocking4Socket.csproj.user 6 ●●●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.TopShelf.DataDocking4Socket/Properties/PublishProfiles/FolderProfile.pubxml.user 2 ●●● 补丁 | 查看 | 原始文档 | blame | 历史
IStation.DataDocking.Socket.sln
@@ -29,6 +29,8 @@
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.DataDockingSocket.SZJT_XJD", "IStation.DataDockingSocket.SZJT_XJD\IStation.DataDockingSocket.SZJT_XJD.csproj", "{A553EA76-C543-4C56-94C2-5594ABFFE6DD}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IStation.DataDockingSocket.SZJT_SZY1", "IStation.DataDockingSocket.SZJT_SZY1\IStation.DataDockingSocket.SZJT_SZY1.csproj", "{53CDD119-7F16-4E12-9134-EF497E833270}"
EndProject
Global
    GlobalSection(SolutionConfigurationPlatforms) = preSolution
        Debug|Any CPU = Debug|Any CPU
@@ -87,6 +89,10 @@
        {A553EA76-C543-4C56-94C2-5594ABFFE6DD}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {A553EA76-C543-4C56-94C2-5594ABFFE6DD}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {A553EA76-C543-4C56-94C2-5594ABFFE6DD}.Release|Any CPU.Build.0 = Release|Any CPU
        {53CDD119-7F16-4E12-9134-EF497E833270}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
        {53CDD119-7F16-4E12-9134-EF497E833270}.Debug|Any CPU.Build.0 = Debug|Any CPU
        {53CDD119-7F16-4E12-9134-EF497E833270}.Release|Any CPU.ActiveCfg = Release|Any CPU
        {53CDD119-7F16-4E12-9134-EF497E833270}.Release|Any CPU.Build.0 = Release|Any CPU
    EndGlobalSection
    GlobalSection(SolutionProperties) = preSolution
        HideSolutionNode = FALSE
IStation.DataDocking.Socket/IStation.DataDocking.Socket.csproj
@@ -21,6 +21,7 @@
    <ProjectReference Include="..\IStation.DataDockingSocket.SZJT_PST\IStation.DataDockingSocket.SZJT_PST.csproj" />
    <ProjectReference Include="..\IStation.DataDockingSocket.SZJT_QFT\IStation.DataDockingSocket.SZJT_QFT.csproj" />
    <ProjectReference Include="..\IStation.DataDockingSocket.SZJT_SYW\IStation.DataDockingSocket.SZJT_SYW.csproj" />
    <ProjectReference Include="..\IStation.DataDockingSocket.SZJT_SZY1\IStation.DataDockingSocket.SZJT_SZY1.csproj" />
    <ProjectReference Include="..\IStation.DataDockingSocket.SZJT_WTW\IStation.DataDockingSocket.SZJT_WTW.csproj" />
    <ProjectReference Include="..\IStation.DataDockingSocket.SZJT_XJD\IStation.DataDockingSocket.SZJT_XJD.csproj" />
  </ItemGroup>
IStation.DataDockingSocket.SZJT_SZY1/GlobalUsings.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
global using Yw;
global using Yw.Untity;
global using Yw.Service;
global using System.ComponentModel.DataAnnotations;
global using Quartz;
global using Yw.DataDockingSocket;
IStation.DataDockingSocket.SZJT_SZY1/HandleHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,137 @@
namespace IStation.DataDockingSocket
{
    public class HandleHelper : IHandleHelper
    {
        /// <summary>
        /// å¤„理注册码
        /// </summary>
        public void HandleRegisterCode(Yw.Model.IMonitorDataDockingSession session)
        {
            if (session == null)
                return;
            if (!session.IsConnected)
                return;
            if (SessionHelper.Cache != null)
            {
                if (SessionHelper.Cache != session)
                {
                    if (SessionHelper.Cache.IsConnected)
                    {
                        SessionHelper.Cache.Close($"{session.SessionName} ä¸­ï¼Œäº§ç”Ÿæ–°çš„会话!");
                    }
                }
            }
            SessionHelper.Cache = session;
            var appParas = AppParasHelper.Get();
            if (appParas == null)
            {
                LogHelper.Error("Socket æ•°æ®å¯¹æŽ¥ä¸­ï¼ŒSZY1 ç¼ºå°‘数据对接配置文件");
                return;
            }
            foreach (var item in appParas.InstructionItems)
            {
                SendInstructionJobHelper.StartJob(session, item);
                Thread.Sleep(appParas.InstructionSendSpace * 1000);
            }
        }
        /// <summary>
        /// å¤„理心跳包
        /// </summary>
        public void HandleHeartbeat(Yw.Model.IMonitorDataDockingSession session)
        {
        }
        /// <summary>
        /// å¤„理数据
        /// </summary>
        public void HandleData
            (
                Yw.Model.IMonitorDataDockingSession session,
                byte[] bytes,
                List<Yw.Model.DataDockingConfigureItemExSubList> mappers,
                Action<List<Yw.Model.MonitorHandleRecord>> receive
            )
        {
            if (session == null)
                return;
            if (!session.IsConnected)
                return;
            if (bytes == null)
                return;
            if (!AppParas.Verify(bytes))
            {
                return;
            }
            if (mappers == null || mappers.Count < 1)
            {
                return;
            }
            var appParas = AppParasHelper.Get();
            if (appParas == null)
            {
                LogHelper.Error("Socket æ•°æ®å¯¹æŽ¥ä¸­ï¼ŒSZY1 ç¼ºå°‘数据对接配置文件");
                return;
            }
            var item = appParas.InstructionItems.Find(x => x.Verify(bytes));
            if (item == null)
                return;
            var middleList = HandleDataHelper.HandleData(item, bytes);
            if (middleList != null && middleList.Count > 0)
            {
                var recordList = new List<Yw.Model.MonitorHandleRecord>();
                foreach (var mapper in mappers)
                {
                    if (mapper.SubList == null || mapper.SubList.Count < 1)
                    {
                        continue;
                    }
                    var mapper_sub = mapper.SubList.First();
                    var middle = middleList.Find(x => x.SignId == mapper.TransferId);
                    if (middle != null)
                    {
                        var record = new Yw.Model.MonitorHandleRecord
                        {
                            MonitorPointID = mapper.MonitorPointID,
                            DataTime = middle.DataTime
                        };
                        var dataStatus = new List<string>();
                        var record_sub = new Yw.Model.MonitorHandleSubRecord();
                        record_sub.SignalID = mapper_sub.SignalID;
                        record_sub.SrcValue = middle.DataValue;
                        record_sub.DataValue = mapper_sub.Docking(middle.DataValue, ref dataStatus);
                        record_sub.DataStatus = dataStatus;
                        record.SubList.Add(record_sub);
                        recordList.Add(record);
                    }
                }
                receive(recordList);
            }
            if (ConfigHelper.SupportOld)
            {
                OldTransferHelper.Transfer(middleList);
            }
            if (appParas.Src)
            {
                SrcHelper.Src(bytes);
            }
            if (appParas.Debug)
            {
                DebugHelper.Debug(middleList);
            }
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/IStation.DataDockingSocket.SZJT_SZY1.csproj
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">
  <PropertyGroup>
    <TargetFramework>net6.0</TargetFramework>
    <ImplicitUsings>enable</ImplicitUsings>
    <Nullable>disable</Nullable>
  </PropertyGroup>
  <ItemGroup>
    <None Remove="paras_datadocking_socket_szjt_szy1.json" />
  </ItemGroup>
  <ItemGroup>
    <Content Include="paras_datadocking_socket_szjt_szy1.json">
      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
    </Content>
  </ItemGroup>
  <ItemGroup>
    <PackageReference Include="Yw.IDataDockingSocket.Core" Version="3.0.1" />
    <PackageReference Include="Yw.Quartz.Core" Version="3.0.0" />
  </ItemGroup>
</Project>
IStation.DataDockingSocket.SZJT_SZY1/Model/Middle/MiddleRecord.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    ///
    /// </summary>
    internal class MiddleRecord
    {
        /// <summary>
        /// æ ‡å¿—id
        /// </summary>
        public string SignId { get; set; }
        /// <summary>
        /// æ•°æ®æ—¶é—´
        /// </summary>
        public DateTime DataTime { get; set; }
        /// <summary>
        /// æ•°æ®å€¼
        /// </summary>
        public string DataValue { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewResult.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,38 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    ///
    /// </summary>
    public class NewResult
    {
        /// <summary>
        /// çŠ¶æ€ç 
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// é”™è¯¯ç 
        /// </summary>
        public object Error { get; set; }
        /// <summary>
        /// é”™è¯¯ä¿¡æ¯
        /// </summary>
        public object Message { get; set; }
        /// <summary>
        /// æ•°æ®
        /// </summary>
        public bool Data { get; set; }
        /// <summary>
        /// é™„加数据
        /// </summary>
        public object Extras { get; set; }
        /// <summary>
        /// æ—¶é—´æˆ³
        /// </summary>
        public DateTime Timestamp { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewStandardModel.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    ///
    /// </summary>
    public class NewStandardModel
    {
        /// <summary>
        /// æ³¨å†Œç 
        /// </summary>
        public string RegisterCode { get; set; }
        /// <summary>
        /// è®°å½•列表
        /// </summary>
        public List<NewStandardRecord> RecordList { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewStandardRecord.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,25 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// æ•°æ®å¯¹æŽ¥æ ‡å‡†è®°å½•dto
    /// </summary>
    public class NewStandardRecord
    {
        /// <summary>
        /// ä¼ è¾“id
        /// </summary>
        public string TransferId { get; set; }
        /// <summary>
        /// åŽŸå§‹æ—¶é—´
        /// </summary>
        public DateTime SrcTime { get; set; }
        /// <summary>
        /// å­é¡¹åˆ—表
        /// </summary>
        public List<NewStandardSubRecord> SubList { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/New/NewStandardSubRecord.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,26 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// æ•°æ®æ ‡å‡†å¯¹æŽ¥å­è®°å½•dto
    /// </summary>
    public class NewStandardSubRecord
    {
        /// <summary>
        /// ä¼ è¾“id
        /// </summary>
        public string TransferId { get; set; }
        /// <summary>
        /// åŽŸå§‹å€¼
        /// </summary>
        public string SrcValue { get; set; }
        /// <summary>
        /// æ•°æ®çŠ¶æ€
        /// </summary>
        public List<string> DataStatus { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldResult.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,23 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    ///
    /// </summary>
    public class OldResult
    {
        /// <summary>
        /// çŠ¶æ€ä¿¡æ¯
        /// </summary>
        public int Code { get; set; }
        /// <summary>
        /// æç¤ºä¿¡æ¯
        /// </summary>
        public string Message { get; set; }
        /// <summary>
        ///
        /// </summary>
        public bool Data { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldStandardModel.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    ///
    /// </summary>
    public class OldStandardModel
    {
        /// <summary>
        /// æ³¨å†Œç 
        /// </summary>
        public string RegisterCode { get; set; }
        /// <summary>
        /// è®°å½•列表
        /// </summary>
        public List<OldStandardRecord> Records { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldStandardRecord.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,30 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// æ•°æ®å¯¹æŽ¥æ ‡å‡†è®°å½•dto
    /// </summary>
    public class OldStandardRecord
    {
        /// <summary>
        /// è®°å½•标识
        /// </summary>
        public string RecordId { get; set; }
        /// <summary>
        /// è®°å½•类型
        /// </summary>
        public int RecordType { get; set; }
        /// <summary>
        /// è®°å½•æ—¶é—´
        /// </summary>
        public DateTime RecordTime { get; set; }
        /// <summary>
        /// è®°å½•值
        /// </summary>
        public string RecordValue { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/Model/Old/OldStandardSubRecord.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,21 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// æ•°æ®æ ‡å‡†å¯¹æŽ¥å­è®°å½•dto
    /// </summary>
    public class OldStandardSubRecord
    {
        /// <summary>
        /// å­è®°å½•id
        /// </summary>
        public string RecordId { get; set; }
        /// <summary>
        /// å­è®°å½•值
        /// </summary>
        public string RecordValue { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/helper/ConfigHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,45 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// é…ç½®æ–‡ä»¶è¾…助类
    /// </summary>
    internal class ConfigHelper
    {
        /// <summary>
        /// æ—§æ³¨å†Œç 
        /// </summary>
        public static string OldRegisterCode
        {
            get
            {
                return AppParasHelper.Get().OldTransfer.RegisterCode;
            }
        }
        /// <summary>
        /// æ—§ä¼ è¾“Url
        /// </summary>
        public static string OldTransferUrl
        {
            get
            {
                return AppParasHelper.Get().OldTransfer.TransferUrl;
            }
        }
        /// <summary>
        /// æ˜¯å¦æ”¯æŒ
        /// </summary>
        public static bool SupportOld
        {
            get
            {
                return AppParasHelper.Get().SupportOld;
            }
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/helper/DebugHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// ç”Ÿæˆè°ƒè¯•信息辅助类
    /// </summary>
    internal class DebugHelper
    {
        private const string _logName = "socket-szjt-szy1-debug";
        /// <summary>
        /// ç”Ÿæˆ
        /// </summary>
        public static void Debug(List<MiddleRecord> list)
        {
            if (list == null || list.Count < 1)
            {
                return;
            }
            var debug_list = new List<Yw.Model.MonitorDataDockingDebugRecord>();
            foreach (var record in list)
            {
                var debug_item = new Yw.Model.MonitorDataDockingDebugRecord();
                debug_item.TransferId = record.SignId;
                debug_item.SrcTime = record.DataTime.ToString("yyyy-MM-dd HH:mm:ss");
                debug_item.SubList.Add(new Yw.Model.MonitorDataDockingDebugSubRecord()
                {
                    TransferId = "",
                    SrcValue = record.DataValue
                });
                debug_list.Add(debug_item);
            }
            if (debug_list != null && debug_list.Count > 0)
            {
                var json = JsonHelper.Object2Json(debug_list);
                LogHelper.Custom(_logName, json);
            }
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/helper/HandleDataHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,92 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// å¤„理数据辅助类
    /// </summary>
    internal class HandleDataHelper
    {
        /// <summary>
        /// å¤„理数据
        /// </summary>
        public static List<MiddleRecord> HandleData
            (
                InstructionItem item,
                byte[] bts
            )
        {
            var list = new List<MiddleRecord>();
            //将指令转化为字节数组
            var instrution_bts = BitTransfer.FromString(item.Instruction);
            //请求数据的索引器位置 ä»Ž0开始
            var startIndex = instrution_bts[2] * 16 * 16 + instrution_bts[3];
            foreach (var x in item.RuleItems)
            {
                var record = new MiddleRecord();
                record.SignId = x.SignId;
                record.DataTime = DateTime.Now;
                record.DataValue = null;
                var skip = 3 + (x.Index - startIndex - 1) * 2;
                switch (x.Rule)
                {
                    case eRule.Float:
                        {
                            var btValue = bts.Skip(skip).Take(2 * 2).ToArray();
                            var value = CalcuFloat(btValue) * x.Ratio;
                            record.DataValue = value.ToString();
                        }
                        break;
                    case eRule.Short:
                        {
                            var btValue = bts.Skip(skip).Take(2).ToArray();
                            var value = CalcuShort(btValue) * x.Ratio;
                            record.DataValue = value.ToString();
                        }
                        break;
                    case eRule.Int:
                        {
                            var btValue = bts.Skip(skip).Take(2 * 2).ToArray();
                            var value = CalcuInt(btValue) * x.Ratio;
                            record.DataValue = value.ToString();
                        }
                        break;
                    default: break;
                }
                list.Add(record);
            }
            return list;
        }
        //计算Float
        private static float CalcuFloat(byte[] bts)
        {
            if (bts.Length != 4)
                return default;
            var rbts = bts.Reverse().ToArray();
            return BitConverter.ToSingle(rbts, 0);
        }
        //计算Short
        private static short CalcuShort(byte[] bts)
        {
            if (bts.Length != 2)
                return default;
            var rbts = bts.Reverse().ToArray();
            return BitConverter.ToInt16(rbts, 0);
        }
        //计算Int
        private static int CalcuInt(byte[] bts)
        {
            if (bts.Length != 4)
                return default;
            var rbts = bts.Reverse().ToArray();
            return BitConverter.ToInt32(rbts, 0);
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/helper/OldTransferHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,41 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    ///
    /// </summary>
    internal class OldTransferHelper
    {
        /// <summary>
        /// ä¼ è¾“
        /// </summary>
        /// <param name="middleList"></param>
        /// <returns></returns>
        public static bool Transfer(List<MiddleRecord> middleList)
        {
            try
            {
                if (middleList == null || middleList.Count < 1)
                {
                    return false;
                }
                var recordList = middleList.Select(x => new OldStandardRecord() { RecordId = x.SignId, RecordType = 0, RecordTime = x.DataTime, RecordValue = x.DataValue }).ToList();
                var model = new OldStandardModel() { RegisterCode = ConfigHelper.OldRegisterCode, Records = recordList };
                var data = JsonHelper.Object2Json(model);
                var responseText = HttpRequestHelper.Post(ConfigHelper.OldTransferUrl, data);
                var result = JsonHelper.Json2Object<OldResult>(responseText);
                if (result.Code != 0)
                {
                    throw new Exception(result.Message);
                }
                return result.Data;
            }
            catch (Exception ex)
            {
                LogHelper.Error(ex.Message);
                return false;
            }
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/helper/SessionHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,13 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// ä¼šè¯è¾…助类
    /// </summary>
    public class SessionHelper
    {
        /// <summary>
        /// ç¼“å­˜
        /// </summary>
        public static Yw.Model.IMonitorDataDockingSession Cache { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/helper/SrcHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,22 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// ç”ŸæˆåŽŸå§‹ä¿¡æ¯è¾…åŠ©ç±»
    /// </summary>
    internal class SrcHelper
    {
        private const string _logName = "socket-szjt-szy1-src";
        /// <summary>
        /// ç”Ÿæˆ
        /// </summary>
        public static void Src(byte[] bts)
        {
            if (bts == null || bts.Length < 1)
                return;
            var message = BitTransfer.ToString(bts);
            LogHelper.Custom(_logName, message);
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/instruction/SendInstructionJob.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// å‘送指令任务
    /// </summary>
    [DisallowConcurrentExecution]//此特性标识 å¿…须等待这次任务执行完成后,才能执行下次任务
    public class SendInstructionJob : IJob
    {
        internal const string Session = "Session";//会话字符
        internal const string Instruction = "Instruction";//指令字符
        public async Task Execute(IJobExecutionContext context)
        {
            try
            {
                await Task.Run(() =>
                {
                    var dataMap = context.MergedJobDataMap;
                    var bytes = (byte[])dataMap[Instruction];
                    if (bytes == null)
                        return;
                    var session = (Yw.Model.IMonitorDataDockingSession)dataMap[Session];
                    if (session == null)
                        return;
                    if (session.IsConnected)
                    {
                        SessionHelper.Cache.Send(bytes, 0, bytes.Length);
                        LogHelper.Info(session.SessionName + ":" + BitConverter.ToString(bytes) + ", å‘送一条请求数据指令");
                    }
                });
            }
            catch (Exception ex)
            {
                var e = new JobExecutionException(ex);
                throw e;
            }
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/instruction/SendInstructionJobHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,100 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// Modbus辅助类
    /// </summary>
    public class SendInstructionJobHelper
    {
        private static IScheduler _sched;//调度器
        /// <summary>
        /// å¼€å§‹ä»»åŠ¡
        /// </summary>
        public static async void StartJob(Yw.Model.IMonitorDataDockingSession session, InstructionItem item)
        {
            if (session == null)
                return;
            if (!session.IsConnected)
                return;
            if (item == null)
                return;
            if (string.IsNullOrEmpty(item.Instruction))
                return;
            if (item.RuleItems == null || item.RuleItems.Count < 1)
                return;
            LogHelper.Info($"{session.SessionName} å¼€å§‹å¤„理发送指令任务,指令:{item.Instruction} !");
            var jobName = SendInstructionJobNameHelper.GetJobName(session, item.Instruction);
            var jobGroupName = SendInstructionJobNameHelper.GetJobGroupName(session, item.Instruction);
            var triggerName = SendInstructionJobNameHelper.GetTriggerName(session, item.Instruction);
            //判断是否存在
            if (_sched != null)
            {
                var triggerKey = new TriggerKey(triggerName, jobGroupName);
                if (await _sched.CheckExists(triggerKey))
                {
                    LogHelper.Info($"{session.SessionName} ä¸­ï¼ŒæŒ‡ä»¤ï¼š{item.Instruction} çš„主动请求数据任务已经开启,无需重复开启!");
                    return;
                }
            }
            //判断是否开启调取器
            if (_sched == null)
            {
                // 1.创建scheduler的引用
                var fac = new Quartz.Impl.StdSchedulerFactory();
                _sched = await fac.GetScheduler();
                //2.启动 scheduler
                await _sched.Start();
            }
            //3.创建任务
            var job = JobBuilder.Create<SendInstructionJob>()
             .WithIdentity(jobName, jobGroupName)
             .Build();
            job.JobDataMap.Put(SendInstructionJob.Session, session);
            job.JobDataMap.Put(SendInstructionJob.Instruction, BitTransfer.FromString(item.Instruction));
            //4.创建Trigger
            var trigger = TriggerBuilder.Create()
            .WithIdentity(triggerName, jobGroupName)
            .WithSimpleSchedule(x => x.WithIntervalInSeconds(item.Frequency).RepeatForever()
            .WithMisfireHandlingInstructionNextWithRemainingCount())
            .Build();
            //5.加入调度管理器
            await _sched.ScheduleJob(job, trigger);
            session.SessionClosedEvent += () => CancelJob(session, item.Instruction);
            LogHelper.Info($"{session.SessionName} ä¸­ï¼ŒæŒ‡ä»¤:{item.Instruction}  çš„主动请求数据线程开启成功!");
        }
        /// <summary>
        /// å–消任务
        /// </summary>
        private static async void CancelJob(Yw.Model.IMonitorDataDockingSession session, string instruction)
        {
            if (_sched == null)
                return;
            LogHelper.Info($"{session.SessionName}  æ­£æ‰“算终止主动请求数据任务");
            var triggerName = SendInstructionJobNameHelper.GetTriggerName(session, instruction);
            var jobGroupName = SendInstructionJobNameHelper.GetJobGroupName(session, instruction);
            var triggerKey = new TriggerKey(triggerName, jobGroupName);
            if (await _sched.CheckExists(triggerKey))
            {
                await _sched.UnscheduleJob(triggerKey);
                LogHelper.Info($"{session.SessionName},指令:{instruction}  ä¸»åŠ¨è¯·æ±‚æ•°æ®ä»»åŠ¡ç»ˆæ­¢æˆåŠŸ");
            }
            else
            {
                LogHelper.Info($"{session.SessionName},指令:{instruction}  ä¸»åŠ¨è¯·æ±‚æ•°æ®ä»»åŠ¡ä¸å­˜åœ¨");
            }
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/instruction/SendInstructionJobNameHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,40 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// å‘送指令任务名称辅助类
    /// </summary>
    public class SendInstructionJobNameHelper
    {
        private const string _jobNameHeader = "SZJT_TenSendInstructionJob";
        private const string _jobGroupHeader = "SZJT_TenSendInstructionJobGroup";
        private const string _triggerNameHeader = "SZJT_TenSendInstructionJobTrigger";
        /// <summary>
        /// èŽ·å–ä»»åŠ¡åç§°
        /// </summary>
        public static string GetJobName(Yw.Model.IMonitorDataDockingSession session, string instructioon)
        {
            var jobName = $"{_jobNameHeader}_{session.RegisterCode}_{session.SessionID}_{instructioon}";
            return jobName;
        }
        /// <summary>
        /// èŽ·å–ä»»åŠ¡ç»„åç§°
        /// </summary>
        public static string GetJobGroupName(Yw.Model.IMonitorDataDockingSession session, string instructioon)
        {
            var jobGroup = $"{_jobGroupHeader}_{session.RegisterCode}_{session.SessionID}_{instructioon}";
            return jobGroup;
        }
        /// <summary>
        /// èŽ·å–è§¦å‘å™¨åç§°
        /// </summary>
        public static string GetTriggerName(Yw.Model.IMonitorDataDockingSession session, string instructioon)
        {
            var triggerName = $"{_triggerNameHeader}_{session.RegisterCode}_{session.SessionID}_{instructioon}";
            return triggerName;
        }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/paras/AppParas.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,176 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// app参数(可配制)
    /// </summary>
    public class AppParas
    {
        /// <summary>
        /// æŒ‡ä»¤å‘送间隔
        /// </summary>
        public int InstructionSendSpace { get; set; }
        /// <summary>
        /// æŒ‡ä»¤é¡¹åˆ—表
        /// </summary>
        public List<InstructionItem> InstructionItems { get; set; }
        /// <summary>
        /// æ—§ä¼ è¾“
        /// </summary>
        public Transfer OldTransfer { get; set; }
        /// <summary>
        /// æ”¯æŒæ—§
        /// </summary>
        public bool SupportOld { get; set; }
        /// <summary>
        /// æ˜¯å¦ä¿å­˜åŽŸå§‹
        /// </summary>
        public bool Src { get; set; }
        /// <summary>
        /// æ˜¯å¦è°ƒè¯•
        /// </summary>
        public bool Debug { get; set; }
        /// <summary>
        /// éªŒè¯ModbusRtu åè®®
        /// </summary>
        public static bool Verify(byte[] bts)
        {
            if (bts == null)
                return default;
            if (bts.Length < 6)
                return false;
            if (bts.Length - 5 != bts[2])
                return false;
            if (!ModBusRtuHelper.CheckReceivedMessage(bts))
                return false;
            return true;
        }
    }
    /// <summary>
    /// è§£æžè§„则枚举
    /// </summary>
    public enum eRule
    {
        /// <summary>
        /// ä¸¤ä¸ªå­—节为一组,两组表示一个数据,通过得到的四个字节反转后,BitConvert.Single()获取值
        /// </summary>
        [Display(Name = "双字解析为浮点数", Description = "双字解析为浮点数 ")]
        Float = 1,
        /// <summary>
        /// ä¸¤ä¸ªå­—节表示一个整数值,通过得到的2个字节反转后,BitConvert.ToInt16()获取值
        /// </summary>
        [Display(Name = "单字解析为整数", Description = "单字表示一个整数值")]
        Short = 2,
        /// <summary>
        /// ä¸¤ä¸ªå­—节为一组,两组表示一个数据,通过得到的四个字节反转后,BitConverter.ToInt32();获取值
        /// </summary>
        [Display(Name = "双字解析为整数", Description = "双字表示一个整数值")]
        Int = 3,
    }
    /// <summary>
    /// è§£æžé¡¹
    /// </summary>
    public class RuleItem
    {
        /// <summary>
        /// æ ‡è®°æ ‡è¯†
        /// </summary>
        public string SignId { get; set; }
        /// <summary>
        /// ç´¢å¼• ä»Ž1开始
        /// </summary>
        public int Index { get; set; }
        /// <summary>
        /// ç³»æ•°
        /// </summary>
        public double Ratio { get; set; }
        /// <summary>
        /// è§£æžè§„则
        /// </summary>
        public eRule Rule { get; set; }
    }
    /// <summary>
    /// æŒ‡ä»¤é¡¹
    /// </summary>
    public class InstructionItem
    {
        /// <summary>
        /// æŒ‡ä»¤
        /// </summary>
        public string Instruction { get; set; }
        /// <summary>
        /// æŒ‡ä»¤å‘送频率 ç§’
        /// </summary>
        public int Frequency { get; set; }
        /// <summary>
        /// è§£æžé¡¹
        /// </summary>
        public List<RuleItem> RuleItems { get; set; }
        /// <summary>
        /// éªŒè¯
        /// </summary>
        public bool Verify(byte[] bts)
        {
            if (bts == null)
                return default;
            if (bts.Length < 6)
                return false;
            if (bts.Length - 5 != bts[2])
                return false;
            if (string.IsNullOrEmpty(this.Instruction))
                return default;
            var instruction = BitTransfer.FromString(this.Instruction);
            if (bts[0] == instruction[0])
            {
                if (bts[1] == instruction[1])
                {
                    //请求的数据字节数量
                    var requestDataCount = BitConverter.ToInt16(instruction.Skip(4).Take(2).Reverse().ToArray(), 0) * 2;
                    if (requestDataCount == bts[2])
                    {
                        return true;
                    }
                }
            }
            return default;
        }
    }
    /// <summary>
    /// ä¼ è¾“
    /// </summary>
    public class Transfer
    {
        /// <summary>
        /// æ³¨å†Œç 
        /// </summary>
        public string RegisterCode { get; set; }
        /// <summary>
        /// ä¼ è¾“Url
        /// </summary>
        public string TransferUrl { get; set; }
    }
}
IStation.DataDockingSocket.SZJT_SZY1/paras/AppParasHelper.cs
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,39 @@
namespace IStation.DataDockingSocket
{
    /// <summary>
    /// app å‚数辅助类
    /// </summary>
    internal class AppParasHelper
    {
        /// <summary>
        /// json文件名称
        /// </summary>
        public static string JsonFileName
        {
            get
            {
                if (string.IsNullOrEmpty(_jsonFileName))
                {
                    _jsonFileName = System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "paras_datadocking_socket_szjt_szy1.json");
                }
                return _jsonFileName;
            }
        }
        private static string _jsonFileName = null;
        /// <summary>
        /// èŽ·å–
        /// </summary>
        /// <returns></returns>
        public static AppParas Get()
        {
            if (_appparas == null)
            {
                var json = File.ReadAllText(JsonFileName);
                _appparas = JsonHelper.Json2Object<AppParas>(json);
            }
            return _appparas;
        }
        private static AppParas _appparas = null;
    }
}
IStation.DataDockingSocket.SZJT_SZY1/paras_datadocking_socket_szjt_szy1.json
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,42 @@
{
  "InstructionSendSpace": 10,
  "InstructionItems": [
    {
      "Instruction": "01-03-01-82-00-08-E5-D8",
      "Frequency": 60,
      "RuleItems": [
        {
          "SignId": "szy1_387",
          "Index": 387,
          "Ratio": 1,
          "Rule": 1
        },
        {
          "SignId": "szy1_389",
          "Index": 389,
          "Ratio": 1,
          "Rule": 1
        },
        {
          "SignId": "szy1_391",
          "Index": 391,
          "Ratio": 1,
          "Rule": 1
        },
        {
          "SignId": "szy1_393",
          "Index": 393,
          "Ratio": 1,
          "Rule": 1
        }
      ]
    }
  ],
  "OldTransfer": {
    "RegisterCode": "@@@863293051622816",
    "TransferUrl": "http://172.19.69.11:9019/Run/DataDocking/Standard/Insert@V1.0"
  },
  "SupportOld": true,
  "Debug": true,
  "Src": true
}
IStation.TopShelf.DataDocking4Socket/IStation.TopShelf.DataDocking4Socket.csproj.user
¶Ô±ÈÐÂÎļþ
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  <PropertyGroup>
    <_LastSelectedProfileId>D:\WorkData\git\istation\szjt\IStation.TopShelf.DataDocking4Socket\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
  </PropertyGroup>
</Project>
IStation.TopShelf.DataDocking4Socket/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -4,7 +4,7 @@
-->
<Project>
  <PropertyGroup>
    <History>True|2024-11-11T08:07:57.2232009Z;True|2024-05-16T13:56:47.8204382+08:00;True|2024-05-09T16:59:48.1703915+08:00;False|2024-05-09T16:54:48.1914196+08:00;True|2024-04-04T11:53:15.6689438+08:00;False|2024-04-04T11:52:41.3417899+08:00;False|2024-04-04T11:50:18.0958240+08:00;True|2023-12-26T12:15:34.2479140+08:00;True|2023-12-26T12:15:13.2347981+08:00;True|2023-12-12T20:07:12.6576370+08:00;True|2022-12-01T15:20:13.0180741+08:00;True|2022-12-01T13:30:29.6610607+08:00;True|2022-12-01T13:10:00.6718954+08:00;True|2022-11-30T16:12:46.0669167+08:00;True|2022-11-30T16:11:46.8013058+08:00;True|2022-11-18T17:16:08.2357388+08:00;True|2022-11-18T17:10:16.7111998+08:00;True|2022-11-18T17:04:10.5678845+08:00;True|2022-11-18T17:01:48.4283015+08:00;True|2022-11-18T16:52:07.1424550+08:00;True|2022-11-07T14:19:02.7595787+08:00;True|2022-11-07T14:16:18.9629209+08:00;True|2022-11-07T14:10:58.7927593+08:00;True|2022-11-07T13:40:15.7710087+08:00;True|2022-11-04T10:51:31.2128411+08:00;True|2022-11-04T10:50:48.9390883+08:00;False|2022-11-04T10:45:25.5349335+08:00;False|2022-11-04T10:38:09.7881861+08:00;False|2022-11-04T10:32:57.3163779+08:00;True|2022-10-31T13:50:19.2799744+08:00;True|2022-10-28T18:12:41.9095520+08:00;True|2022-10-28T15:43:16.2950292+08:00;True|2022-10-28T15:41:52.2233941+08:00;True|2022-10-28T15:30:14.2215199+08:00;True|2022-10-28T11:51:16.0785196+08:00;True|2022-10-28T11:44:51.8315664+08:00;True|2022-10-28T10:33:52.2698494+08:00;True|2022-10-28T09:35:47.1875028+08:00;True|2022-10-28T09:10:26.0008427+08:00;True|2022-10-27T18:39:24.9534804+08:00;True|2022-10-27T18:33:34.4681116+08:00;True|2022-10-27T18:13:21.7875951+08:00;True|2022-10-27T18:12:44.3890244+08:00;True|2022-10-27T18:07:26.1755739+08:00;True|2022-10-27T17:57:58.0347320+08:00;True|2022-10-27T17:34:58.8259465+08:00;True|2022-10-27T17:22:06.3154634+08:00;False|2022-10-27T17:20:19.9004059+08:00;True|2022-10-27T17:18:10.4716763+08:00;True|2022-10-27T17:05:00.4099257+08:00;True|2022-10-27T16:54:07.3727699+08:00;True|2022-10-27T16:42:08.7868428+08:00;True|2022-10-27T16:20:40.9187590+08:00;True|2022-10-27T16:15:48.8887876+08:00;True|2022-10-27T15:32:23.6326778+08:00;True|2022-10-27T15:31:21.2898598+08:00;True|2022-10-27T15:31:06.9752171+08:00;True|2022-10-27T15:30:12.3351290+08:00;True|2022-10-27T15:16:06.6376480+08:00;True|2022-10-27T15:04:16.6181644+08:00;True|2022-10-27T14:56:07.3371453+08:00;True|2022-10-27T14:55:40.9994920+08:00;True|2022-10-26T14:21:13.7358061+08:00;True|2022-10-26T13:58:17.8518712+08:00;True|2022-10-26T10:50:57.8305616+08:00;True|2022-10-26T10:41:24.0512951+08:00;True|2022-10-26T10:36:18.9669938+08:00;True|2022-10-26T10:23:42.5700603+08:00;True|2022-10-26T09:49:18.1242267+08:00;True|2022-10-24T17:44:25.5039390+08:00;True|2022-07-02T00:06:16.6338790+08:00;True|2022-07-02T00:02:49.1000053+08:00;True|2022-07-01T23:23:53.1924783+08:00;True|2022-07-01T14:02:38.1190102+08:00;True|2022-07-01T13:55:33.4591108+08:00;</History>
    <History>True|2024-11-19T02:44:43.1147974Z;True|2024-11-11T16:07:57.2232009+08:00;True|2024-05-16T13:56:47.8204382+08:00;True|2024-05-09T16:59:48.1703915+08:00;False|2024-05-09T16:54:48.1914196+08:00;True|2024-04-04T11:53:15.6689438+08:00;False|2024-04-04T11:52:41.3417899+08:00;False|2024-04-04T11:50:18.0958240+08:00;True|2023-12-26T12:15:34.2479140+08:00;True|2023-12-26T12:15:13.2347981+08:00;True|2023-12-12T20:07:12.6576370+08:00;True|2022-12-01T15:20:13.0180741+08:00;True|2022-12-01T13:30:29.6610607+08:00;True|2022-12-01T13:10:00.6718954+08:00;True|2022-11-30T16:12:46.0669167+08:00;True|2022-11-30T16:11:46.8013058+08:00;True|2022-11-18T17:16:08.2357388+08:00;True|2022-11-18T17:10:16.7111998+08:00;True|2022-11-18T17:04:10.5678845+08:00;True|2022-11-18T17:01:48.4283015+08:00;True|2022-11-18T16:52:07.1424550+08:00;True|2022-11-07T14:19:02.7595787+08:00;True|2022-11-07T14:16:18.9629209+08:00;True|2022-11-07T14:10:58.7927593+08:00;True|2022-11-07T13:40:15.7710087+08:00;True|2022-11-04T10:51:31.2128411+08:00;True|2022-11-04T10:50:48.9390883+08:00;False|2022-11-04T10:45:25.5349335+08:00;False|2022-11-04T10:38:09.7881861+08:00;False|2022-11-04T10:32:57.3163779+08:00;True|2022-10-31T13:50:19.2799744+08:00;True|2022-10-28T18:12:41.9095520+08:00;True|2022-10-28T15:43:16.2950292+08:00;True|2022-10-28T15:41:52.2233941+08:00;True|2022-10-28T15:30:14.2215199+08:00;True|2022-10-28T11:51:16.0785196+08:00;True|2022-10-28T11:44:51.8315664+08:00;True|2022-10-28T10:33:52.2698494+08:00;True|2022-10-28T09:35:47.1875028+08:00;True|2022-10-28T09:10:26.0008427+08:00;True|2022-10-27T18:39:24.9534804+08:00;True|2022-10-27T18:33:34.4681116+08:00;True|2022-10-27T18:13:21.7875951+08:00;True|2022-10-27T18:12:44.3890244+08:00;True|2022-10-27T18:07:26.1755739+08:00;True|2022-10-27T17:57:58.0347320+08:00;True|2022-10-27T17:34:58.8259465+08:00;True|2022-10-27T17:22:06.3154634+08:00;False|2022-10-27T17:20:19.9004059+08:00;True|2022-10-27T17:18:10.4716763+08:00;True|2022-10-27T17:05:00.4099257+08:00;True|2022-10-27T16:54:07.3727699+08:00;True|2022-10-27T16:42:08.7868428+08:00;True|2022-10-27T16:20:40.9187590+08:00;True|2022-10-27T16:15:48.8887876+08:00;True|2022-10-27T15:32:23.6326778+08:00;True|2022-10-27T15:31:21.2898598+08:00;True|2022-10-27T15:31:06.9752171+08:00;True|2022-10-27T15:30:12.3351290+08:00;True|2022-10-27T15:16:06.6376480+08:00;True|2022-10-27T15:04:16.6181644+08:00;True|2022-10-27T14:56:07.3371453+08:00;True|2022-10-27T14:55:40.9994920+08:00;True|2022-10-26T14:21:13.7358061+08:00;True|2022-10-26T13:58:17.8518712+08:00;True|2022-10-26T10:50:57.8305616+08:00;True|2022-10-26T10:41:24.0512951+08:00;True|2022-10-26T10:36:18.9669938+08:00;True|2022-10-26T10:23:42.5700603+08:00;True|2022-10-26T09:49:18.1242267+08:00;True|2022-10-24T17:44:25.5039390+08:00;True|2022-07-02T00:06:16.6338790+08:00;True|2022-07-02T00:02:49.1000053+08:00;True|2022-07-01T23:23:53.1924783+08:00;True|2022-07-01T14:02:38.1190102+08:00;True|2022-07-01T13:55:33.4591108+08:00;</History>
    <LastFailureDetails />
  </PropertyGroup>
</Project>