diff --git a/HKCard.sln b/HKCard.sln
index db7f129..f4c1b26 100644
--- a/HKCard.sln
+++ b/HKCard.sln
@@ -7,7 +7,11 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HKCardIN", "HKCardIN\HKCard
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HKCardOUT", "HKCardOUT\HKCardOUT.csproj", "{A03F8002-B946-4FD6-BEE7-54EFC199FE4E}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HKLog", "HKLog\HKLog.csproj", "{617E076F-D422-44B7-8455-006AA34ECD45}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HKLog", "HKLog\HKLog.csproj", "{617E076F-D422-44B7-8455-006AA34ECD45}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HKControl", "HKControl\HKControl.csproj", "{C82945B1-3D74-40E3-A16C-213BCED377E1}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HKHelper", "HKHelper\HKHelper.csproj", "{CFA68AF9-1C11-41A3-8A73-34E004660CFC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -27,6 +31,14 @@ Global
{617E076F-D422-44B7-8455-006AA34ECD45}.Debug|Any CPU.Build.0 = Debug|Any CPU
{617E076F-D422-44B7-8455-006AA34ECD45}.Release|Any CPU.ActiveCfg = Release|Any CPU
{617E076F-D422-44B7-8455-006AA34ECD45}.Release|Any CPU.Build.0 = Release|Any CPU
+ {C82945B1-3D74-40E3-A16C-213BCED377E1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {C82945B1-3D74-40E3-A16C-213BCED377E1}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {C82945B1-3D74-40E3-A16C-213BCED377E1}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {C82945B1-3D74-40E3-A16C-213BCED377E1}.Release|Any CPU.Build.0 = Release|Any CPU
+ {CFA68AF9-1C11-41A3-8A73-34E004660CFC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {CFA68AF9-1C11-41A3-8A73-34E004660CFC}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {CFA68AF9-1C11-41A3-8A73-34E004660CFC}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {CFA68AF9-1C11-41A3-8A73-34E004660CFC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
diff --git a/HKControl/CommunicationBase.cs b/HKControl/CommunicationBase.cs
new file mode 100644
index 0000000..d27f266
--- /dev/null
+++ b/HKControl/CommunicationBase.cs
@@ -0,0 +1,32 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HKControl
+{
+ internal class CommunicationBase
+ {
+ ///
+ /// 连接成功
+ ///
+ public Action ConnectOk { get; set; }
+
+ ///
+ /// 连接失败
+ ///
+ public Action ConnectFail { get; set; }
+
+ ///
+ /// 断开连接
+ ///
+ public Action Disconnect { get; set; }
+
+ ///
+ /// 设置是否重连
+ /// true=启用重连,false=禁用重连
+ ///
+ public bool IsReconnect { get; set; } = true;
+ }
+}
diff --git a/HKControl/CommunicationPar.cs b/HKControl/CommunicationPar.cs
new file mode 100644
index 0000000..c044f00
--- /dev/null
+++ b/HKControl/CommunicationPar.cs
@@ -0,0 +1,22 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HKControl
+{
+ public class CommunicationPar
+ {
+ public List CommunicationModels { get; set; } = new List();
+ }
+
+ public class CommunicationModel
+ {
+ public string IpAddress { get; set; }
+
+ public int Port { get; set; } = 102;
+
+ public int DeviceNum { get; set; }
+ }
+}
diff --git a/HKControl/DataModel.cs b/HKControl/DataModel.cs
new file mode 100644
index 0000000..aede8bf
--- /dev/null
+++ b/HKControl/DataModel.cs
@@ -0,0 +1,37 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HKControl
+{
+ internal class DataModel
+ {
+ public WindowDataModel LeftWindowData { get; set; } = new WindowDataModel();
+ public WindowDataModel RightWindowData { get; set; } = new WindowDataModel();
+ }
+
+ public class WindowDataModel
+ {
+ ///
+ /// 是否允许刷卡
+ ///
+ public bool IsSwipe { get; set; }
+
+ ///
+ /// 开始配餐
+ ///
+ public bool Start { get; set; }
+
+ ///
+ /// 配餐完成状态
+ ///
+ public bool Complete { get; set; }
+
+ ///
+ /// 刷卡机编号
+ ///
+ public string CarNum { get; set; }
+ }
+}
diff --git a/HKControl/HKControl.csproj b/HKControl/HKControl.csproj
new file mode 100644
index 0000000..c6c2689
--- /dev/null
+++ b/HKControl/HKControl.csproj
@@ -0,0 +1,17 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
+
+
+
+
diff --git a/HKControl/Main.cs b/HKControl/Main.cs
new file mode 100644
index 0000000..bbd634a
--- /dev/null
+++ b/HKControl/Main.cs
@@ -0,0 +1,78 @@
+using System.Collections.Concurrent;
+using HKHelper;
+using S7.Net;
+
+namespace HKControl
+{
+ public class Main
+ {
+
+ private volatile static Main _Instance;
+ public static Main GetInstance => _Instance ?? (_Instance = new Main());
+ private Main() { }
+
+ ConcurrentDictionary SiemensDicitonary = new ConcurrentDictionary();
+ ConcurrentDictionary DataModels = new ConcurrentDictionary();
+
+
+ public bool GetIsSwipe(int CarNum)
+ {
+ var left = DataModels.Values.FirstOrDefault(p => p.LeftWindowData.CarNum == CarNum.ToString());
+ var right = DataModels.Values.FirstOrDefault(p => p.RightWindowData.CarNum == CarNum.ToString());
+ return false;
+ }
+
+ public void Init()
+ {
+ DataInit();
+ Json.Data.CommunicationModels.ToList()?.ForEach(item =>
+ {
+ if (!DataModels.ContainsKey(item.DeviceNum)) { DataModels.TryAdd(item.DeviceNum, new DataModel()); };
+ if (!SiemensDicitonary.ContainsKey(item.DeviceNum)) { SiemensDicitonary.TryAdd(item.DeviceNum, new Siemens()); }
+ ThreadManage.GetInstance().Start(new Action(() =>
+ {
+ SiemensDicitonary[item.DeviceNum].Connect(CpuType.S71200, item.IpAddress);
+ SiemensDicitonary[item.DeviceNum].ConnectOk = new Action(() =>
+ {
+ ThreadManage.GetInstance().StartLong(new Action(() =>
+ {
+ var vattable = DataModels[item.DeviceNum];
+ DataModels[item.DeviceNum] = SiemensDicitonary[item.DeviceNum].ReadClass(0, 1);
+ Thread.Sleep(100);
+ }), $"{item.DeviceNum} 号设备监听");
+ });
+ }), $"{item.DeviceNum} 号设备连接初始化");
+
+ });
+ }
+
+ private void DataInit()
+ {
+ Json.Read();
+ if (Json.Data.CommunicationModels.Count < 3)
+ {
+ Json.Data.CommunicationModels.Clear();
+
+ Json.Data.CommunicationModels.Add(new CommunicationModel()
+ {
+ IpAddress = "192.168.0.1",
+ DeviceNum = 1
+ });
+
+ Json.Data.CommunicationModels.Add(new CommunicationModel()
+ {
+ IpAddress = "192.168.0.2",
+ DeviceNum = 2
+ });
+
+ Json.Data.CommunicationModels.Add(new CommunicationModel()
+ {
+ IpAddress = "192.168.0.3",
+ DeviceNum = 3
+ });
+
+ Json.Save();
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/HKControl/Siemens.cs b/HKControl/Siemens.cs
new file mode 100644
index 0000000..67969dc
--- /dev/null
+++ b/HKControl/Siemens.cs
@@ -0,0 +1,106 @@
+using S7.Net;
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HKControl
+{
+ internal class Siemens : CommunicationBase
+ {
+ Plc myPlc;
+ public bool IsConnected => myPlc is null ? false : myPlc.IsConnected;
+
+ ///
+ /// 打开连接
+ ///
+ /// PLC CPU 类型
+ /// plc ip 地址
+ /// plc 端口号
+ /// PLC 机架号
+ /// PLC 插槽号
+ public void Connect(CpuType cpuType, string ip, int port = 102, short rack = 0, short solt = 0)
+ {
+ myPlc = new Plc(cpuType, ip, port, rack, solt);
+ myPlc.Open();
+ }
+
+ ///
+ /// 断开和PLC的连接
+ ///
+ public void Disconnect()
+ {
+ myPlc?.Close();
+ }
+
+ public object Read(string address)
+ {
+ if (!IsConnected) return default;
+ return myPlc?.Read(address);
+ }
+
+ public bool[] ReadBools(int address, int count)
+ {
+ if (!IsConnected) return default;
+ var res = Read(DataType.Memory, 0, address, VarType.Bit, count);
+ if (res != null && res is bool[] bools) return bools;
+ return default;
+ }
+
+ public ushort[] ReadMW(int address, int count)
+ {
+ if (!IsConnected) return default;
+ var res = Read(DataType.Memory, 0, address, VarType.Word, count);
+ if (res != null && res is ushort[] ReturnValue) return ReturnValue;
+ return default;
+ }
+
+ public float[] ReadMD(int address, int count)
+ {
+ if (!IsConnected) return default;
+ var res = Read(DataType.Memory, 0, address, VarType.Real, count);
+ if (res != null && res is float[] ReturnValue) return ReturnValue;
+ return default;
+ }
+
+ private object Read(DataType dataType, int db, int address, VarType varType, int count)
+ {
+ if (!IsConnected) return default;
+ return myPlc?.Read(dataType, db, address, varType, count);
+ }
+
+ public void Write(string address, object value)
+ {
+ myPlc?.Write(address, value);
+ }
+
+ public ReadT ReadStruct(int db, int startAddress = 0)
+ {
+ if (!IsConnected) return default;
+ return (ReadT)myPlc.ReadStruct(typeof(ReadT), db, startAddress);
+ }
+
+ public void WriteStruct(object structValue, int db, int startAddress = 0)
+ {
+ myPlc?.WriteStruct(structValue, db, startAddress);
+ }
+
+ public int ReadClass(object sourceClass, int db, int startAddress = 0)
+ {
+ if (!IsConnected) return -1;
+ return myPlc.ReadClass(sourceClass, db, startAddress);
+ }
+
+ public TResult ReadClass(int db, int startAddress = 0) where TResult : class
+ {
+ if (!IsConnected) return default;
+ return myPlc.ReadClass(db, startAddress);
+ }
+
+ public void WriteClass(object sourceClass, int db, int startAddress = 0)
+ {
+ myPlc?.WriteClass(sourceClass, db, startAddress);
+ }
+ }
+}
diff --git a/HKControl/WindowEnum.cs b/HKControl/WindowEnum.cs
new file mode 100644
index 0000000..4b9633a
--- /dev/null
+++ b/HKControl/WindowEnum.cs
@@ -0,0 +1,17 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace HKControl
+{
+ ///
+ /// 窗口枚举
+ ///
+ public enum WindowEnum : int
+ {
+ WindewLeft = 1,
+ WindewRight = 2,
+ }
+}
diff --git a/HKHelper/HKHelper.cs b/HKHelper/HKHelper.cs
new file mode 100644
index 0000000..294c8df
--- /dev/null
+++ b/HKHelper/HKHelper.cs
@@ -0,0 +1,31 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Runtime.InteropServices;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace HKHelper
+{
+ public class HKHelper : Singleton
+ {
+ ///
+ /// 判断网络状况的方法,返回值true为连接,false为未连接
+ ///
+ ///
+ ///
+ ///
+ [DllImport("wininet")]
+ public extern static bool InternetGetConnectedState(out int conState, int reder);
+ ///
+ /// 获取当前网络连接状态
+ ///
+ /// 成功连接网络返回 true,未连接返回 false
+ public bool GetNetworkState()
+ {
+ return InternetGetConnectedState(out int i, 0);
+ }
+
+ }
+}
diff --git a/HKHelper/HKHelper.csproj b/HKHelper/HKHelper.csproj
new file mode 100644
index 0000000..933c8b2
--- /dev/null
+++ b/HKHelper/HKHelper.csproj
@@ -0,0 +1,13 @@
+
+
+
+ net6.0
+ enable
+ enable
+
+
+
+
+
+
+
diff --git a/HKHelper/Json.cs b/HKHelper/Json.cs
new file mode 100644
index 0000000..70e9d23
--- /dev/null
+++ b/HKHelper/Json.cs
@@ -0,0 +1,81 @@
+using Newtonsoft.Json;
+using System;
+using System.IO;
+using System.Collections.Concurrent;
+using System.Reflection;
+
+namespace HKHelper
+{
+ ///
+ /// Json参数服务类
+ ///
+ public class Json where T : class, new()
+ {
+ static string path
+ {
+ get
+ {
+ Directory.CreateDirectory(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, $"AccessFile\\JSON"));
+ return $"{AppDomain.CurrentDomain.BaseDirectory}AccessFile\\JSON\\{typeof(T).Name}.json";
+ }
+ }
+
+ public static T Data { get; set; } = new T();
+
+ ///
+ /// 保存数据
+ ///
+ public static void Save()
+ {
+ string outjson = JsonConvert.SerializeObject(Data);
+ File.WriteAllText(path, outjson);
+ }
+
+ ///
+ /// 获取保存的数据
+ ///
+ public static void Read()
+ {
+ if (File.Exists(path))
+ {
+ string JsonString = File.ReadAllText(path);
+ var result = JsonConvert.DeserializeObject(JsonString);
+ if (result != null) { Data = result; }
+ }
+ }
+
+ ///
+ /// 保存带接口的对象
+ ///
+ public static void SaveInterface()
+ {
+ var settings = new JsonSerializerSettings();
+ settings.TypeNameHandling = TypeNameHandling.Objects;
+ string outjson = JsonConvert.SerializeObject(Data, Formatting.Indented, settings);
+ File.WriteAllText(path, outjson);
+ }
+
+ ///
+ /// 获取带接口对象的字符串
+ ///
+ public static void ReadInterface()
+ {
+ if (File.Exists(path))
+ {
+ var settings = new JsonSerializerSettings();
+ settings.TypeNameHandling = TypeNameHandling.Objects;
+ string JsonString = File.ReadAllText(path);
+ var result = JsonConvert.DeserializeObject(JsonString, settings);
+ if (result != null) { Data = result; }
+ }
+ }
+
+ /*
+ 使用反序列化接口对象的方法
+ 一、使用 SaveInterface 方法保存成字符串,使用 ReadInterface 方法获取对象
+ 二、在接口属性上加一个特性 [JsonProperty(TypeNameHandling = TypeNameHandling.Auto)]
+ */
+
+
+ }
+}
diff --git a/HKHelper/ThreadManage.cs b/HKHelper/ThreadManage.cs
new file mode 100644
index 0000000..423c0f0
--- /dev/null
+++ b/HKHelper/ThreadManage.cs
@@ -0,0 +1,445 @@
+using System;
+using System.Collections.Concurrent;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading;
+using System.Threading.Tasks;
+
+namespace HKHelper
+{
+ public class Singleton where T : new()
+ {
+ private static object _async = new object();
+
+ private static T _instance;
+
+ static readonly Lazy instance = new();
+ ///
+ /// 获取实例
+ ///
+ ///
+ public static T GetInstance()
+ {
+ return instance.Value;
+ }
+ }
+ public class ThreadManage : Singleton
+ {
+ string guid = "871d7e28-c413-4675-8d28-64e4dca4c2d3-";
+ private static readonly object _lock = new object();
+ StringBuilder callbackKey = new StringBuilder();
+ List keys = new List();
+ ConcurrentDictionary Threads = new ConcurrentDictionary();
+ ConcurrentDictionary CancellationTokenSources = new ConcurrentDictionary();
+
+ ///
+ /// 停止指定任务
+ ///
+ /// 任务名
+ /// 任务结束的回调
+ public void StopTask(string key, Action ExitCallback = null)
+ {
+ if (CancellationTokenSources.ContainsKey(guid + key))
+ {
+ CancellationTokenSources[guid + key]?.Cancel();
+ ActionManage.GetInstance.Register(ExitCallback, guid + key);
+ }
+ else
+ {
+ if (ExitCallback != null) ExitCallback();
+ }
+ }
+
+ ///
+ /// 长任务,带 while true 的循环
+ ///
+ ///
+ ///
+ public void StartLong(Action action, string key, bool IsRestart = false, Action RunComplete = null)
+ {
+ CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
+ bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
+ {
+ Thread.CurrentThread.Name = key;
+ ReStart:
+ try
+ {
+ while (!CancellationTokenSources[guid + key].IsCancellationRequested)
+ {
+ if (action != null) action();
+ }
+ }
+ catch (Exception ex)
+ {
+ if (IsRestart)
+ {
+ Thread.Sleep(2000);
+ goto ReStart;
+ }
+ else
+ {
+ CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource temp);
+ Threads.TryRemove(guid + key, out Task temp1);
+ }
+ }
+ }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action((t, o) =>
+ {
+ ThreadStatus(t, o.ToString());
+ if (RunComplete != null) RunComplete();
+ }), guid + key));
+ }
+
+
+ ///
+ /// 不带 while true 的循环任务
+ ///
+ ///
+ ///
+ public void Start(Action action, string key, bool isRestart = false)
+ {
+ CancellationTokenSources.TryAdd(guid + key, new CancellationTokenSource());
+ bool result = Threads.TryAdd(guid + key, Task.Factory.StartNew(new Action(() =>
+ {
+ Thread.CurrentThread.Name = key;
+ try
+ {
+ if (action != null) action();
+ }
+ catch (Exception ex)
+ {
+ if (isRestart)
+ {
+ CancellationTokenSources.TryRemove(guid + key, out CancellationTokenSource item1);
+ Threads.TryRemove(guid + key, out Task item2);
+ Start(action, key, isRestart);
+ }
+ else
+ {
+ }
+ }
+ }), CancellationTokenSources[guid + key].Token).ContinueWith(new Action((t, o) =>
+ {
+ ThreadStatus(t, o.ToString());
+ }), guid + key));
+ }
+
+ private void ThreadStatus(Task task, string key)
+ {
+ bool IsRemove = false;
+ string name = key.Substring(key.LastIndexOf('-') + 1);
+ switch (task.Status)
+ {
+ case TaskStatus.RanToCompletion:
+ IsRemove = true;
+ break;
+ case TaskStatus.Faulted:
+ IsRemove = true;
+ break;
+ case TaskStatus.Canceled:
+ IsRemove = true;
+ break;
+ default:
+ break;
+ }
+
+ if (IsRemove)
+ {
+ if (Threads.ContainsKey(key))
+ Threads.TryRemove(key, out Task t);
+ if (CancellationTokenSources.ContainsKey(key))
+ CancellationTokenSources.TryRemove(key, out CancellationTokenSource cts);
+ ActionManage.GetInstance.Send(key);
+ }
+ }
+
+ ///
+ /// 释放所有线程资源
+ ///
+ public void Dispose()
+ {
+ for (int i = 0; i < CancellationTokenSources.Count; i++)
+ {
+ CancellationTokenSources.ElementAt(i).Value.Cancel();
+ }
+ }
+
+ ///
+ /// 判断指定线程是否完成
+ ///
+ ///
+ ///
+ public bool IsComplete(string key)
+ {
+ if (Threads.ContainsKey(guid + key)) return Threads[guid + key].IsCompleted;
+ return false;
+ }
+
+ }
+ internal class Delegation
+ {
+ ///
+ /// 带参数的委托
+ ///
+ public Action