From a2059eaa7c6c2346f3a1a03ab214a6cd8dfc8b38 Mon Sep 17 00:00:00 2001
From: lixiaojun <1287241240@qq.com>
Date: 星期一, 18 十一月 2024 13:39:40 +0800
Subject: [PATCH] 增加 szjt api数据对接

---
 IStation.DataDockingApi.JTMeter/00-core/LastCollectHelper.cs                            |   29 +
 IStation.DataDockingApi.JTMeter/03-handle/HandleHelper.cs                               |  180 ++++++++++++
 IStation.DataDocking.Api.sln                                                            |   37 ++
 IStation.DataDocking.Api/IStation.DataDocking.Api.csproj.user                           |    6 
 IStation.TopShelf.DataDocking4Mqtt/IStation.TopShelf.DataDocking4Mqtt.csproj.user       |    6 
 IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml.user  |   10 
 IStation.TopShelf.DataDocking4Mqtt/Properties/PublishProfiles/FolderProfile.pubxml.user |    2 
 IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.csproj.user         |    6 
 IStation.DataDocking.Api/IStation.DataDocking.Api.csproj                                |   25 +
 IStation.DataDockingApi.JTMeter/02-model/Result_Login.cs                                |   48 +++
 IStation.DataDockingApi.JTMeter/02-model/Exception.cs                                   |   21 +
 IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml.user           |    9 
 IStation.DataDockingApi.JTMeter/01-paras/AppParasHelper.cs                              |   39 ++
 IStation.DataDockingApi.JTMeter/IStation.DataDockingApi.JTMeter.csproj                  |   23 +
 IStation.DataDocking.Api/GlobalUsings.cs                                                |    5 
 IStation.DataDockingApi.JTMeter/paras_datadocking_api_jtmeter.json                      |   12 
 IStation.DataDocking.Api/Program.cs                                                     |   15 +
 IStation.DataDockingApi.JTMeter/GlobalUsings.cs                                         |   11 
 IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml                |   12 
 IStation.DataDockingApi.JTMeter/02-model/Result_History.cs                              |  119 +++++++
 IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.csproj              |   21 +
 IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml       |   12 
 IStation.TopShelf.DataDocking4Api/Program.cs                                            |   17 +
 IStation.DataDockingApi.JTMeter/00-core/TokenHelper.cs                                  |   69 ++++
 IStation.DataDockingApi.JTMeter/00-core/HttpRequestHelper.cs                            |   66 ++++
 IStation.TopShelf.DataDocking4Api/Service.cs                                            |   33 ++
 IStation.DataDockingApi.JTMeter/01-paras/AppParas.cs                                    |   50 +++
 27 files changed, 882 insertions(+), 1 deletions(-)

diff --git a/IStation.DataDocking.Api.sln b/IStation.DataDocking.Api.sln
new file mode 100644
index 0000000..15081bb
--- /dev/null
+++ b/IStation.DataDocking.Api.sln
@@ -0,0 +1,37 @@
+锘�
+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio Version 17
+VisualStudioVersion = 17.1.32328.378
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.DataDocking.Api", "IStation.DataDocking.Api\IStation.DataDocking.Api.csproj", "{0C528556-BB5A-477F-806E-2A441531D3D5}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.DataDockingApi.JTMeter", "IStation.DataDockingApi.JTMeter\IStation.DataDockingApi.JTMeter.csproj", "{64744652-C278-4439-8343-3872F07FFB45}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IStation.TopShelf.DataDocking4Api", "IStation.TopShelf.DataDocking4Api\IStation.TopShelf.DataDocking4Api.csproj", "{F77F77DE-C9C0-4F1A-8934-D3A435182C91}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{0C528556-BB5A-477F-806E-2A441531D3D5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{0C528556-BB5A-477F-806E-2A441531D3D5}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{0C528556-BB5A-477F-806E-2A441531D3D5}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{0C528556-BB5A-477F-806E-2A441531D3D5}.Release|Any CPU.Build.0 = Release|Any CPU
+		{64744652-C278-4439-8343-3872F07FFB45}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{64744652-C278-4439-8343-3872F07FFB45}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{64744652-C278-4439-8343-3872F07FFB45}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{64744652-C278-4439-8343-3872F07FFB45}.Release|Any CPU.Build.0 = Release|Any CPU
+		{F77F77DE-C9C0-4F1A-8934-D3A435182C91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{F77F77DE-C9C0-4F1A-8934-D3A435182C91}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{F77F77DE-C9C0-4F1A-8934-D3A435182C91}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{F77F77DE-C9C0-4F1A-8934-D3A435182C91}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {E02989A8-9B6F-43E5-AACA-790328215089}
+	EndGlobalSection
+EndGlobal
diff --git a/IStation.DataDocking.Api/GlobalUsings.cs b/IStation.DataDocking.Api/GlobalUsings.cs
new file mode 100644
index 0000000..4f80944
--- /dev/null
+++ b/IStation.DataDocking.Api/GlobalUsings.cs
@@ -0,0 +1,5 @@
+锘縢lobal using Yw;
+global using Yw.Untity;
+global using Yw.Service;
+global using Yw.Server;
+global using Quartz;
diff --git a/IStation.DataDocking.Api/IStation.DataDocking.Api.csproj b/IStation.DataDocking.Api/IStation.DataDocking.Api.csproj
new file mode 100644
index 0000000..633cab4
--- /dev/null
+++ b/IStation.DataDocking.Api/IStation.DataDocking.Api.csproj
@@ -0,0 +1,25 @@
+锘�<Project Sdk="Microsoft.NET.Sdk">
+
+	<PropertyGroup>
+		<OutputType>Exe</OutputType>
+		<TargetFramework>net6.0</TargetFramework>
+		<ImplicitUsings>enable</ImplicitUsings>
+		<Nullable>disable</Nullable>
+		<AssemblyName>IStation.DataDocking.Api</AssemblyName>
+		<RootNamespace>IStation.DataDocking</RootNamespace>
+		<GenerateDocumentationFile>True</GenerateDocumentationFile>
+	</PropertyGroup>
+
+	<ItemGroup>
+		<Folder Include="Properties\" />
+	</ItemGroup>
+
+	<ItemGroup>
+	  <PackageReference Include="Yw.DataDocking.Api.Core" Version="3.0.2" />
+	</ItemGroup>
+
+	<ItemGroup>
+	  <ProjectReference Include="..\IStation.DataDockingApi.JTMeter\IStation.DataDockingApi.JTMeter.csproj" />
+	</ItemGroup>
+
+</Project>
diff --git a/IStation.DataDocking.Api/IStation.DataDocking.Api.csproj.user b/IStation.DataDocking.Api/IStation.DataDocking.Api.csproj.user
new file mode 100644
index 0000000..58756b8
--- /dev/null
+++ b/IStation.DataDocking.Api/IStation.DataDocking.Api.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\webapi\v4.2\Service.V4.2\Server\IStation.DataDocking.Api\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/IStation.DataDocking.Api/Program.cs b/IStation.DataDocking.Api/Program.cs
new file mode 100644
index 0000000..cd0f099
--- /dev/null
+++ b/IStation.DataDocking.Api/Program.cs
@@ -0,0 +1,15 @@
+锘�// See https://aka.ms/new-console-template for more information
+
+
+LogHelper.Info("API鏁版嵁瀵规帴鏈嶅姟姝e湪鍚姩...");
+
+var jobHelper = new ApiJobHelper();
+await jobHelper.StartJob();
+AppDomain.CurrentDomain.ProcessExit += async (sender, e) =>
+{
+    await jobHelper.CancelJob();
+};
+
+LogHelper.Info("API鏁版嵁瀵规帴鏈嶅姟鍚姩鎴愬姛锛�");
+
+Console.ReadLine();
\ No newline at end of file
diff --git a/IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml b/IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 0000000..639934f
--- /dev/null
+++ b/IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,12 @@
+锘�<?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\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml.user b/IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml.user
new file mode 100644
index 0000000..f3bd97c
--- /dev/null
+++ b/IStation.DataDocking.Api/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -0,0 +1,9 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <History>True|2023-07-15T07:00:50.8280821Z;True|2023-07-15T14:14:42.0826207+08:00;True|2023-07-14T22:12:25.7041577+08:00;True|2023-07-12T10:19:32.0353122+08:00;True|2023-07-12T09:58:24.0623166+08:00;True|2023-07-12T09:48:23.4447126+08:00;True|2023-06-13T16:22:32.7349659+08:00;True|2023-06-13T15:04:34.9832999+08:00;</History>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/IStation.DataDockingApi.JTMeter/00-core/HttpRequestHelper.cs b/IStation.DataDockingApi.JTMeter/00-core/HttpRequestHelper.cs
new file mode 100644
index 0000000..977419a
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/00-core/HttpRequestHelper.cs
@@ -0,0 +1,66 @@
+锘縩amespace IStation.DataDockingApi
+{
+    internal class HttpRequestHelper
+    {
+
+        /// <summary>
+        /// 鐧诲綍
+        /// </summary>
+        public static Result_Login Login()
+        {
+            var appParas = AppParasHelper.Get();
+            var data = JsonHelper.Object2Json(appParas.account);
+            using (var httpClient = new HttpClient())
+            using (var request = new HttpRequestMessage(HttpMethod.Post, appParas.url.token))
+            {
+                request.Headers.Add("KeepAlive", "false");
+                request.Headers.Add("X-Requested-With", "XMLHttpRequest");
+                request.Content = new StringContent(data, Encoding.UTF8, "application/json");
+                var response = httpClient.SendAsync(request).Result;
+                response.EnsureSuccessStatusCode();
+                var responsetext = response.Content.ReadAsStringAsync().Result;
+                return JsonHelper.Json2Object<Result_Login>(responsetext);
+            }
+        }
+
+        /// <summary>
+        /// 鍘嗗彶
+        /// </summary>
+        public static Result_History History(string url, string token)
+        {
+            using (var httpClient = new HttpClient())
+            using (var request = new HttpRequestMessage(HttpMethod.Post, url))
+            {
+                request.Headers.Add("KeepAlive", "false");
+                if (!string.IsNullOrEmpty(token))
+                {
+                    request.Headers.Add("Access-Token", token);
+                }
+                var response = httpClient.SendAsync(request).Result;
+                response.EnsureSuccessStatusCode();
+                var responsetext = response.Content.ReadAsStringAsync().Result;
+                return JsonHelper.Json2Object<Result_History>(responsetext);
+            }
+        }
+
+        /// <summary>
+        /// Get
+        /// </summary>
+        public static string Get(string url)
+        {
+            using (var httpClient = new HttpClient())
+            using (var request = new HttpRequestMessage(HttpMethod.Get, url))
+            {
+                request.Headers.Add("KeepAlive", "false");
+                var response = httpClient.SendAsync(request).Result;
+                response.EnsureSuccessStatusCode();
+                var responsetext = response.Content.ReadAsStringAsync().Result;
+                return responsetext;
+            }
+        }
+
+
+
+    }
+
+}
diff --git a/IStation.DataDockingApi.JTMeter/00-core/LastCollectHelper.cs b/IStation.DataDockingApi.JTMeter/00-core/LastCollectHelper.cs
new file mode 100644
index 0000000..e5bf453
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/00-core/LastCollectHelper.cs
@@ -0,0 +1,29 @@
+锘縩amespace IStation.DataDockingApi
+{
+    internal class LastCollectHelper
+    {
+        private static Dictionary<string, DateTime> _dict = new Dictionary<string, DateTime>();
+
+        /// <summary>
+        /// 璁剧疆鏈�杩戞椂闂�
+        /// </summary>
+        public static bool SetLastTime(string code, DateTime time)
+        {
+            if (!_dict.ContainsKey(code))
+            {
+                _dict.Add(code, time);
+                return true;
+            }
+            if (time <= _dict[code])
+            {
+                return false;
+            }
+            _dict[code] = time;
+            return true;
+        }
+
+
+
+
+    }
+}
diff --git a/IStation.DataDockingApi.JTMeter/00-core/TokenHelper.cs b/IStation.DataDockingApi.JTMeter/00-core/TokenHelper.cs
new file mode 100644
index 0000000..d17e8b0
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/00-core/TokenHelper.cs
@@ -0,0 +1,69 @@
+锘縩amespace IStation.DataDockingApi
+{
+    /// <summary>
+    /// Token
+    /// </summary>
+    public class TokenHelper
+    {
+        private static DateTime _lastTokenTime;
+        private static string _token = null;
+
+        //鑾峰彇Token
+        private static string GetToken()
+        {
+            var result = HttpRequestHelper.Login();
+            if (result == null)
+            {
+                return default;
+            }
+            if (result.status != "SUCCESS")
+            {
+                var json = JsonHelper.Object2Json(result);
+                LogHelper.Info(json);
+                return default;
+            }
+            return result.content.token;
+        }
+
+        //楠岃瘉杩囨湡鏃堕棿
+        private static bool Verify()
+        {
+            var appParas = AppParasHelper.Get();
+            if (_lastTokenTime.AddHours(appParas.expire) < DateTime.Now)
+            {
+                return false;
+            }
+            return true;
+        }
+
+        /// <summary>
+        /// 鑾峰彇 (楠岃瘉杩囨湡鏃堕棿锛屼娇鐢ㄧ紦瀛榯oken)
+        /// </summary>
+        public static string Get()
+        {
+            if (string.IsNullOrEmpty(_token))
+            {
+                _token = GetToken();
+                _lastTokenTime = DateTime.Now;
+            }
+            if (!Verify())
+            {
+                _token = GetToken();
+                _lastTokenTime = DateTime.Now;
+            }
+            return _token;
+        }
+
+        /// <summary>
+        /// 閲嶆柊鑾峰彇 (涓嶅仛浠讳綍楠岃瘉锛岄噸鏂拌幏鍙杢oken,涔嬪悗鏇存柊缂撳瓨)
+        /// </summary>
+        public static string GetAgain()
+        {
+            _token = GetToken();
+            _lastTokenTime = DateTime.Now;
+            return _token;
+        }
+
+
+    }
+}
diff --git a/IStation.DataDockingApi.JTMeter/01-paras/AppParas.cs b/IStation.DataDockingApi.JTMeter/01-paras/AppParas.cs
new file mode 100644
index 0000000..c5e9b45
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/01-paras/AppParas.cs
@@ -0,0 +1,50 @@
+锘縩amespace IStation.DataDockingApi
+{
+    /// <summary>
+    /// app鍙傛暟锛堝彲閰嶅埗锛�
+    /// </summary>
+    internal class AppParas
+    {
+        /// <summary>
+        /// 杩囨湡鏃堕棿 锛堝皬鏃讹級
+        /// </summary>
+        public int expire { get; set; }
+
+        /// <summary>
+        /// url
+        /// </summary>
+        public Url url { get; set; }
+
+        /// <summary>
+        /// 璐︽埛
+        /// </summary>
+        public Account account { get; set; }
+
+        /// <summary>
+        /// 浠〃
+        /// </summary>
+        public List<string> meters { get; set; }
+
+
+    }
+
+    internal class Url
+    {
+        /// <summary>
+        /// token url
+        /// </summary>
+        public string token { get; set; }
+
+        /// <summary>
+        /// 鍘嗗彶鏁版嵁url
+        /// </summary>
+        public string history { get; set; }
+    }
+
+    internal class Account
+    {
+        public string username { get; set; }
+        public string password { get; set; }
+    }
+
+}
diff --git a/IStation.DataDockingApi.JTMeter/01-paras/AppParasHelper.cs b/IStation.DataDockingApi.JTMeter/01-paras/AppParasHelper.cs
new file mode 100644
index 0000000..a0f35b5
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/01-paras/AppParasHelper.cs
@@ -0,0 +1,39 @@
+锘縩amespace IStation.DataDockingApi
+{
+    /// <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_api_jtmeter.json");
+                }
+                return _jsonFileName;
+            }
+        }
+        private static string _jsonFileName = null;
+
+        /// <summary>
+        /// 鑾峰彇
+        /// </summary>
+        /// <returns></returns>
+        public static AppParas Get()
+        {
+            if (_appparas == null)
+            {
+                _appparas = JsonHelper.Json2Object<AppParas>(File.ReadAllText(JsonFileName));
+            }
+            return _appparas;
+        }
+        private static AppParas _appparas = null;
+    }
+
+}
diff --git a/IStation.DataDockingApi.JTMeter/02-model/Exception.cs b/IStation.DataDockingApi.JTMeter/02-model/Exception.cs
new file mode 100644
index 0000000..f58fc21
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/02-model/Exception.cs
@@ -0,0 +1,21 @@
+锘縩amespace IStation.DataDockingApi.JTMeter
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class Exception : System.Exception
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public Exception() : base() { }
+        /// <summary>
+        /// 
+        /// </summary>
+        public Exception(string message) : base(message) { }
+        /// <summary>
+        /// 
+        /// </summary>
+        public Exception(string message, System.Exception innerException) : base(message, innerException) { }
+    }
+}
diff --git a/IStation.DataDockingApi.JTMeter/02-model/Result_History.cs b/IStation.DataDockingApi.JTMeter/02-model/Result_History.cs
new file mode 100644
index 0000000..feae574
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/02-model/Result_History.cs
@@ -0,0 +1,119 @@
+锘縩amespace IStation.DataDockingApi.JTMeter
+{
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public class Result_History
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public string status { get; set; }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public HistoryResultMessage message { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public HistoryResultContent content { get; set; }
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    public class HistoryResultMessage
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public string notice { get; set; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public class HistoryResultContent
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public HistoryResultContentItem[] result { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public int count { get; set; }
+    }
+    /// <summary>
+    /// 
+    /// </summary>
+    public class HistoryResultContentItem
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public string meterCode { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string meterType { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? flowSpeed { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? instantFlow { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? cumulativeFlow { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? positiveCumulativeFlow { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? negativeCumulativeFlow { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? pressure { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string alarmDetail { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public DateTime collectedTime { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public DateTime reportTime { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? signalStrength { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? voltage { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? cumulativeWorkTime { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? positiveCumulativeWorkTime { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public double? negativeCumulativeWorkTime { get; set; }
+    }
+
+}
diff --git a/IStation.DataDockingApi.JTMeter/02-model/Result_Login.cs b/IStation.DataDockingApi.JTMeter/02-model/Result_Login.cs
new file mode 100644
index 0000000..fc4c172
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/02-model/Result_Login.cs
@@ -0,0 +1,48 @@
+锘縩amespace IStation.DataDockingApi.JTMeter
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class Result_Login
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public LoginResultContent content { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public LoginResultMessage message { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public string status { get; set; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public class LoginResultContent
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public string token { get; set; }
+    }
+
+    /// <summary>
+    /// 
+    /// </summary>
+    public class LoginResultMessage
+    {
+        /// <summary>
+        /// 
+        /// </summary>
+        public object notice { get; set; }
+        /// <summary>
+        /// 
+        /// </summary>
+        public object cause { get; set; }
+    }
+
+}
diff --git a/IStation.DataDockingApi.JTMeter/03-handle/HandleHelper.cs b/IStation.DataDockingApi.JTMeter/03-handle/HandleHelper.cs
new file mode 100644
index 0000000..a34ccec
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/03-handle/HandleHelper.cs
@@ -0,0 +1,180 @@
+锘縩amespace IStation.DataDockingApi
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class HandleHelper : IHandleHelper
+    {
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public void HandleData(List<Yw.Model.DataDockingConfigureItemExSubList> items, Action<List<Yw.Model.MonitorHandleRecord>> receive)
+        {
+            if (items == null || items.Count < 1)
+            {
+                return;
+            }
+            var app_paras = AppParasHelper.Get();
+            if (app_paras == null)
+            {
+                LogHelper.Error("鑻忓窞閲戝涵浠〃 Api 鏁版嵁瀵规帴涓紝缂哄皯瀵规帴閰嶇疆鏂囦欢");
+            }
+            var token = TokenHelper.Get();
+            if (string.IsNullOrEmpty(token))
+            {
+                LogHelper.Error("鑻忓窞閲戝涵浠〃 Api 鏁版嵁瀵规帴涓紝鑾峰彇Token澶辫触");
+                return;
+            }
+
+            var history_url = app_paras.url.history;
+            history_url = $"{history_url}?pageNumber=1&startTime={DateTime.Now.AddDays(-1).ToString("yyyy-MM-dd")}&endTime={DateTime.Now.AddDays(1).ToString("yyyy-MM-dd")}";
+
+            var history_result = HttpRequestHelper.History(history_url, token);
+            if (history_result == null)
+            {
+                LogHelper.Info("鑻忓窞閲戝涵浠〃 Api 鏁版嵁瀵规帴涓紝鑾峰彇瀹炴椂鏁版嵁澶辫触");
+                return;
+            }
+
+            if (history_result.status != "SUCCESS")
+            {
+                LogHelper.Info("鑻忓窞閲戝涵浠〃 Api 鏁版嵁瀵规帴涓紝鑾峰彇瀹炴椂鏁版嵁澶辫触锛坰tatus!= SUCCESS锛�,鍙兘鏄痶oken琚叾浠栫▼搴忔洿鏂帮紝姝e湪閲嶆柊鑾峰彇");
+                token = TokenHelper.GetAgain();
+                history_result = HttpRequestHelper.History(history_url, token);
+                if (history_result == null)
+                {
+                    LogHelper.Info("鑻忓窞閲戝涵浠〃 Api 鏁版嵁瀵规帴涓紝鑾峰彇瀹炴椂鏁版嵁澶辫触");
+                    return;
+                }
+                if (history_result.status != "SUCCESS")
+                {
+                    LogHelper.Info("鑻忓窞閲戝涵浠〃 Api 鏁版嵁瀵规帴涓紝鑾峰彇瀹炴椂鏁版嵁澶辫触锛坰tatus!= SUCCESS锛�,閲嶆柊鑾峰彇渚濇棫澶辫触锛岃妫�鏌ョ▼搴忥紒");
+                    return;
+                }
+            }
+
+            if (history_result.content.result == null || history_result.content.result.Length < 1)
+            {
+                LogHelper.Info("鑻忓窞閲戝涵浠〃 Api 鏁版嵁瀵规帴涓紝鑾峰彇瀹炴椂鏁版嵁澶辫触(鏁版嵁涓虹┖)");
+                return;
+            }
+
+            var result_group_list = history_result.content.result.OrderBy(x => x.collectedTime).GroupBy(x => x.collectedTime).ToList();
+            foreach (var result_group in result_group_list)
+            {
+                var receive_list = new List<Yw.Model.MonitorHandleRecord>();
+                var code_list = result_group.Select(x => x.meterCode).Distinct().ToList();
+                foreach (var code in code_list)
+                {
+                    var record = result_group.FirstOrDefault(x => x.meterCode == code);
+                    if (LastCollectHelper.SetLastTime(code, record.collectedTime))
+                    {
+                        if (record.instantFlow != null)
+                        {
+                            var signId = $"{code}_q";
+                            var item_list = items.Where(x => x.TransferId == signId).ToList();
+                            if (item_list != null && item_list.Count > 0)
+                            {
+                                foreach (var item in item_list)
+                                {
+                                    var item_sub = item.SubList.First();
+
+                                    var receiveRecord = new Yw.Model.MonitorHandleRecord();
+                                    receiveRecord.DataTime = record.collectedTime;
+                                    receiveRecord.MonitorPointID = item.MonitorPointID;
+
+                                    var srcValue = record.instantFlow.Value;
+                                    var dataStatus = new List<string>();
+                                    var dataValue = item_sub.Docking(srcValue.ToString(), ref dataStatus);
+
+                                    var receiveSubRecord = new Yw.Model.MonitorHandleSubRecord();
+                                    receiveSubRecord.SignalID = item_sub.SignalID;
+                                    receiveSubRecord.SrcValue = srcValue.ToString();
+                                    receiveSubRecord.DataValue = dataValue;
+
+                                    receiveRecord.SubList.Add(receiveSubRecord);
+
+                                    if (item.IsMeet(receiveRecord))
+                                    {
+                                        receive_list.Add(receiveRecord);
+                                    }
+                                }
+                            }
+                        }
+                        if (record.cumulativeFlow != null)
+                        {
+                            var signId = $"{code}_ql";
+                            var item_list = items.Where(x => x.TransferId == signId).ToList();
+                            if (item_list != null && item_list.Count > 0)
+                            {
+                                foreach (var item in item_list)
+                                {
+                                    var item_sub = item.SubList.First();
+
+                                    var receiveRecord = new Yw.Model.MonitorHandleRecord();
+                                    receiveRecord.DataTime = record.collectedTime;
+                                    receiveRecord.MonitorPointID = item.MonitorPointID;
+
+                                    var srcValue = record.cumulativeFlow.Value;
+                                    var dataStatus = new List<string>();
+                                    var dataValue = item_sub.Docking(srcValue.ToString(), ref dataStatus);
+
+                                    var receiveSubRecord = new Yw.Model.MonitorHandleSubRecord();
+                                    receiveSubRecord.SignalID = item_sub.SignalID;
+                                    receiveSubRecord.SrcValue = srcValue.ToString();
+                                    receiveSubRecord.DataValue = dataValue;
+
+                                    receiveRecord.SubList.Add(receiveSubRecord);
+                                    if (item.IsMeet(receiveRecord))
+                                    {
+                                        receive_list.Add(receiveRecord);
+                                    }
+                                }
+                            }
+                        }
+                        if (record.pressure != null)
+                        {
+                            var signId = $"{code}_pr";
+                            var item_list = items.Where(x => x.TransferId == signId).ToList();
+                            if (item_list != null && item_list.Count > 0)
+                            {
+                                foreach (var item in item_list)
+                                {
+                                    var item_sub = item.SubList.First();
+
+                                    var receiveRecord = new Yw.Model.MonitorHandleRecord();
+                                    receiveRecord.DataTime = record.collectedTime;
+                                    receiveRecord.MonitorPointID = item.MonitorPointID;
+
+                                    var srcValue = record.pressure.Value;
+                                    var dataStatus = new List<string>();
+                                    var dataValue = item_sub.Docking(srcValue.ToString(), ref dataStatus);
+
+                                    var receiveSubRecord = new Yw.Model.MonitorHandleSubRecord();
+                                    receiveSubRecord.SignalID = item_sub.SignalID;
+                                    receiveSubRecord.SrcValue = srcValue.ToString();
+                                    receiveSubRecord.DataValue = dataValue;
+
+                                    receiveRecord.SubList.Add(receiveSubRecord);
+                                    if (item.IsMeet(receiveRecord))
+                                    {
+                                        receive_list.Add(receiveRecord);
+                                    }
+                                }
+                            }
+                        }
+                    }
+                }
+                if (receive_list.Count > 0)
+                {
+                    receive(receive_list);
+                }
+
+            }
+
+
+        }
+    }
+
+}
diff --git a/IStation.DataDockingApi.JTMeter/GlobalUsings.cs b/IStation.DataDockingApi.JTMeter/GlobalUsings.cs
new file mode 100644
index 0000000..4efbcdc
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/GlobalUsings.cs
@@ -0,0 +1,11 @@
+锘縢lobal using Yw;
+global using Yw.Untity;
+global using Yw.Service;
+global using IStation.DataDockingApi.JTMeter;
+global using System.Text;
+global using Yw.Service.Monitor;
+global using Yw.DataDockingApi;
+global using System;
+global using System.Collections.Generic;
+global using System.Linq;
+global using System.Net.Http;
\ No newline at end of file
diff --git a/IStation.DataDockingApi.JTMeter/IStation.DataDockingApi.JTMeter.csproj b/IStation.DataDockingApi.JTMeter/IStation.DataDockingApi.JTMeter.csproj
new file mode 100644
index 0000000..3886bcc
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/IStation.DataDockingApi.JTMeter.csproj
@@ -0,0 +1,23 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>disable</Nullable>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <None Remove="paras_datadocking_api_jtmeter.json" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <Content Include="paras_datadocking_api_jtmeter.json">
+      <CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
+    </Content>
+  </ItemGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Yw.IDataDockingApi.Core" Version="3.0.3" />
+  </ItemGroup>
+
+</Project>
diff --git a/IStation.DataDockingApi.JTMeter/paras_datadocking_api_jtmeter.json b/IStation.DataDockingApi.JTMeter/paras_datadocking_api_jtmeter.json
new file mode 100644
index 0000000..f62b20e
--- /dev/null
+++ b/IStation.DataDockingApi.JTMeter/paras_datadocking_api_jtmeter.json
@@ -0,0 +1,12 @@
+{
+  "expire": 24,
+  "url": {
+    "token": "http://39.106.98.144:8100/hzybbase/auth/login",
+    "history": "http://39.106.98.144:8100/hzybbase/api/info/history/batch"
+  },
+  "account": {
+    "username": "wzjtzlsmg",
+    "password": "29e5b0b6a11ef700e158b79fa94e4397"
+  },
+  "meters": [ "3211312510799", "6321313403374", "6321313403444", "3211314313774", "3211324121890" ] //鏆傛椂涓嶇敤
+}
diff --git a/IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.csproj b/IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.csproj
new file mode 100644
index 0000000..1fe6dab
--- /dev/null
+++ b/IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.csproj
@@ -0,0 +1,21 @@
+<Project Sdk="Microsoft.NET.Sdk">
+
+  <PropertyGroup>
+    <OutputType>Exe</OutputType>
+    <TargetFramework>net6.0</TargetFramework>
+    <ImplicitUsings>enable</ImplicitUsings>
+    <Nullable>disable</Nullable>
+    <AssemblyName>IStation.TopShelf.DataDocking4Api</AssemblyName>
+    <RootNamespace>IStation.TopShelf</RootNamespace>
+    <GenerateDocumentationFile>True</GenerateDocumentationFile>
+  </PropertyGroup>
+
+  <ItemGroup>
+    <PackageReference Include="Yw.TopShelf" Version="3.0.0" />
+  </ItemGroup>
+
+  <ItemGroup>
+    <ProjectReference Include="..\IStation.DataDocking.Api\IStation.DataDocking.Api.csproj" />
+  </ItemGroup>
+
+</Project>
diff --git a/IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.csproj.user b/IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.csproj.user
new file mode 100644
index 0000000..aa5d674
--- /dev/null
+++ b/IStation.TopShelf.DataDocking4Api/IStation.TopShelf.DataDocking4Api.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.DataDocking4Api\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/IStation.TopShelf.DataDocking4Api/Program.cs b/IStation.TopShelf.DataDocking4Api/Program.cs
new file mode 100644
index 0000000..ab3227c
--- /dev/null
+++ b/IStation.TopShelf.DataDocking4Api/Program.cs
@@ -0,0 +1,17 @@
+锘�// See https://aka.ms/new-console-template for more information
+
+using IStation.TopShelf;
+using Topshelf;
+
+///SZJT
+HostFactory.Run(x =>
+{
+    x.Service<Service>();
+    x.RunAsLocalSystem();
+    x.SetDescription("鏅烘収娉电珯Core鐗圓PI鏁版嵁瀵规帴绋嬪簭(SZJT)");
+    x.SetDisplayName("IStation.Core.DataDocking.Api.SZJT");
+    x.SetServiceName("IStation.Core.DataDocking.Api.SZJT");
+    x.EnableServiceRecovery(r => r.RestartService(TimeSpan.FromSeconds(120)));
+    x.StartAutomatically();
+});
+
diff --git a/IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml b/IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml
new file mode 100644
index 0000000..639934f
--- /dev/null
+++ b/IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml
@@ -0,0 +1,12 @@
+锘�<?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\</PublishDir>
+    <PublishProtocol>FileSystem</PublishProtocol>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml.user b/IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml.user
new file mode 100644
index 0000000..a167748
--- /dev/null
+++ b/IStation.TopShelf.DataDocking4Api/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -0,0 +1,10 @@
+锘�<?xml version="1.0" encoding="utf-8"?>
+<!--
+https://go.microsoft.com/fwlink/?LinkID=208121.
+-->
+<Project>
+  <PropertyGroup>
+    <History>True|2024-11-18T05:37:07.7626653Z;True|2024-11-11T16:23:28.6469381+08:00;True|2024-05-16T12:39:54.9946569+08:00;True|2024-05-16T12:39:29.3584802+08:00;True|2024-05-09T17:14:37.5350192+08:00;True|2024-04-04T11:43:31.7040256+08:00;True|2024-03-02T10:23:38.5098941+08:00;True|2024-03-02T09:59:51.2850262+08:00;True|2023-12-26T12:07:27.4247222+08:00;True|2023-12-11T15:15:41.1462691+08:00;False|2023-12-11T15:14:59.4869740+08:00;True|2022-09-22T10:27:20.9740415+08:00;True|2022-07-01T20:14:42.0373390+08:00;True|2022-07-01T14:01:54.3765684+08:00;True|2022-07-01T13:55:51.6239735+08:00;True|2022-07-01T13:48:27.2176427+08:00;True|2022-06-06T13:37:14.3901330+08:00;True|2022-06-06T11:49:16.9822820+08:00;True|2022-06-02T09:29:24.8316905+08:00;</History>
+    <LastFailureDetails />
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/IStation.TopShelf.DataDocking4Api/Service.cs b/IStation.TopShelf.DataDocking4Api/Service.cs
new file mode 100644
index 0000000..572878c
--- /dev/null
+++ b/IStation.TopShelf.DataDocking4Api/Service.cs
@@ -0,0 +1,33 @@
+锘縰sing Yw.Server;
+using Topshelf;
+
+namespace IStation.TopShelf
+{
+    /// <summary>
+    /// 
+    /// </summary>
+    public class Service : ServiceControl
+    {
+        private readonly ApiJobHelper _jobHelper = new ApiJobHelper();
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public bool Start(HostControl hostControl)
+        {
+            _ = _jobHelper.StartJob();
+            return true;
+        }
+
+        /// <summary>
+        /// 
+        /// </summary>
+        public bool Stop(HostControl hostControl)
+        {
+            _ = _jobHelper.CancelJob();
+            return true;
+        }
+
+
+    }
+}
diff --git a/IStation.TopShelf.DataDocking4Mqtt/IStation.TopShelf.DataDocking4Mqtt.csproj.user b/IStation.TopShelf.DataDocking4Mqtt/IStation.TopShelf.DataDocking4Mqtt.csproj.user
new file mode 100644
index 0000000..9d33e4b
--- /dev/null
+++ b/IStation.TopShelf.DataDocking4Mqtt/IStation.TopShelf.DataDocking4Mqtt.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.DataDocking4Mqtt\Properties\PublishProfiles\FolderProfile.pubxml</_LastSelectedProfileId>
+  </PropertyGroup>
+</Project>
\ No newline at end of file
diff --git a/IStation.TopShelf.DataDocking4Mqtt/Properties/PublishProfiles/FolderProfile.pubxml.user b/IStation.TopShelf.DataDocking4Mqtt/Properties/PublishProfiles/FolderProfile.pubxml.user
index 5091dcd..6da1873 100644
--- a/IStation.TopShelf.DataDocking4Mqtt/Properties/PublishProfiles/FolderProfile.pubxml.user
+++ b/IStation.TopShelf.DataDocking4Mqtt/Properties/PublishProfiles/FolderProfile.pubxml.user
@@ -4,7 +4,7 @@
 -->
 <Project>
   <PropertyGroup>
-    <History>True|2024-05-20T06:54:10.8142650Z;True|2024-05-20T14:53:11.9407797+08:00;True|2024-05-16T11:27:44.8720373+08:00;True|2024-05-16T11:21:56.7846755+08:00;True|2024-02-22T16:25:43.4558929+08:00;True|2024-02-22T16:24:45.8722568+08:00;True|2024-02-22T12:01:45.6247638+08:00;True|2023-10-31T16:04:40.5948906+08:00;True|2023-10-19T13:26:35.6019347+08:00;True|2023-10-19T13:26:00.5198778+08:00;False|2023-10-19T13:24:00.4780702+08:00;True|2023-09-26T13:59:27.5337530+08:00;False|2023-09-26T13:58:50.7519102+08:00;False|2023-09-26T13:58:20.1466908+08:00;True|2022-09-22T10:27:20.9740415+08:00;True|2022-07-01T20:14:42.0373390+08:00;True|2022-07-01T14:01:54.3765684+08:00;True|2022-07-01T13:55:51.6239735+08:00;True|2022-07-01T13:48:27.2176427+08:00;True|2022-06-06T13:37:14.3901330+08:00;True|2022-06-06T11:49:16.9822820+08:00;True|2022-06-02T09:29:24.8316905+08:00;</History>
+    <History>True|2024-11-18T05:05:19.5471687Z;True|2024-05-20T14:54:10.8142650+08:00;True|2024-05-20T14:53:11.9407797+08:00;True|2024-05-16T11:27:44.8720373+08:00;True|2024-05-16T11:21:56.7846755+08:00;True|2024-02-22T16:25:43.4558929+08:00;True|2024-02-22T16:24:45.8722568+08:00;True|2024-02-22T12:01:45.6247638+08:00;True|2023-10-31T16:04:40.5948906+08:00;True|2023-10-19T13:26:35.6019347+08:00;True|2023-10-19T13:26:00.5198778+08:00;False|2023-10-19T13:24:00.4780702+08:00;True|2023-09-26T13:59:27.5337530+08:00;False|2023-09-26T13:58:50.7519102+08:00;False|2023-09-26T13:58:20.1466908+08:00;True|2022-09-22T10:27:20.9740415+08:00;True|2022-07-01T20:14:42.0373390+08:00;True|2022-07-01T14:01:54.3765684+08:00;True|2022-07-01T13:55:51.6239735+08:00;True|2022-07-01T13:48:27.2176427+08:00;True|2022-06-06T13:37:14.3901330+08:00;True|2022-06-06T11:49:16.9822820+08:00;True|2022-06-02T09:29:24.8316905+08:00;</History>
     <LastFailureDetails />
   </PropertyGroup>
 </Project>
\ No newline at end of file

--
Gitblit v1.9.3