| | |
| | | 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 |
| | |
| | | {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 |
| | |
| | | <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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | global using Yw; |
| | | global using Yw.Untity; |
| | | global using Yw.Service; |
| | | global using System.ComponentModel.DataAnnotations; |
| | | global using Quartz; |
| | | global using Yw.DataDockingSocket; |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <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> |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace IStation.DataDockingSocket |
| | | { |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public class NewStandardModel |
| | | { |
| | | |
| | | /// <summary> |
| | | /// 注åç |
| | | /// </summary> |
| | | public string RegisterCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è®°å½å表 |
| | | /// </summary> |
| | | public List<NewStandardRecord> RecordList { get; set; } |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; } |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; } |
| | | |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace IStation.DataDockingSocket |
| | | { |
| | | /// <summary> |
| | | /// |
| | | /// </summary> |
| | | public class OldStandardModel |
| | | { |
| | | |
| | | /// <summary> |
| | | /// 注åç |
| | | /// </summary> |
| | | public string RegisterCode { get; set; } |
| | | |
| | | /// <summary> |
| | | /// è®°å½å表 |
| | | /// </summary> |
| | | public List<OldStandardRecord> Records { get; set; } |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; } |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace IStation.DataDockingSocket |
| | | { |
| | | /// <summary> |
| | | /// æ°æ®æ å对æ¥åè®°å½dto |
| | | /// </summary> |
| | | public class OldStandardSubRecord |
| | | { |
| | | |
| | | /// <summary> |
| | | /// åè®°å½id |
| | | /// </summary> |
| | | public string RecordId { get; set; } |
| | | |
| | | /// <summary> |
| | | /// åè®°å½å¼ |
| | | /// </summary> |
| | | public string RecordValue { get; set; } |
| | | |
| | | } |
| | | |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | | } |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | namespace IStation.DataDockingSocket |
| | | { |
| | | /// <summary> |
| | | /// ä¼è¯è¾
å©ç±» |
| | | /// </summary> |
| | | public class SessionHelper |
| | | { |
| | | /// <summary> |
| | | /// ç¼å |
| | | /// </summary> |
| | | public static Yw.Model.IMonitorDataDockingSession Cache { get; set; } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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); |
| | | } |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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} 主å¨è¯·æ±æ°æ®ä»»å¡ä¸åå¨"); |
| | | } |
| | | } |
| | | |
| | | |
| | | |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; } |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | 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; |
| | | } |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | { |
| | | "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 |
| | | } |
¶Ô±ÈÐÂÎļþ |
| | |
| | | <?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> |
| | |
| | | --> |
| | | <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> |