From d010731c85e2c4453683f9f1d976fb1b4cec8575 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A6=82=E6=84=8F=20=E5=BD=AD?= <2417589739@qq.com> Date: Tue, 13 Sep 2022 14:57:51 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E8=AE=BE=E5=A4=87=E6=8E=A7?= =?UTF-8?q?=E5=88=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- HKCard.sln | 14 +- HKControl/CommunicationBase.cs | 32 +++ HKControl/CommunicationPar.cs | 22 ++ HKControl/DataModel.cs | 37 +++ HKControl/HKControl.csproj | 17 ++ HKControl/Main.cs | 78 ++++++ HKControl/Siemens.cs | 106 ++++++++ HKControl/WindowEnum.cs | 17 ++ HKHelper/HKHelper.cs | 31 +++ HKHelper/HKHelper.csproj | 13 + HKHelper/Json.cs | 81 ++++++ HKHelper/ThreadManage.cs | 445 +++++++++++++++++++++++++++++++++ 12 files changed, 892 insertions(+), 1 deletion(-) create mode 100644 HKControl/CommunicationBase.cs create mode 100644 HKControl/CommunicationPar.cs create mode 100644 HKControl/DataModel.cs create mode 100644 HKControl/HKControl.csproj create mode 100644 HKControl/Main.cs create mode 100644 HKControl/Siemens.cs create mode 100644 HKControl/WindowEnum.cs create mode 100644 HKHelper/HKHelper.cs create mode 100644 HKHelper/HKHelper.csproj create mode 100644 HKHelper/Json.cs create mode 100644 HKHelper/ThreadManage.cs 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 ActionPar { get; set; } + /// + /// 带参数的委托 + /// + public Action ActionPars { get; set; } + /// + /// 无参数的委托 + /// + public Action ActionBus { get; set; } + /// + /// 有返回值的委托 + /// + public Func FuncObj { get; set; } + /// + /// 有返回值,有参数的委托 + /// + public Func FuncPar { get; set; } + } + public class ActionManage + { + + private volatile static ActionManage _Instance; + public static ActionManage GetInstance => _Instance ?? (_Instance = new ActionManage()); + private ActionManage() { } + + //private static ConcurrentDictionary actions = new ConcurrentDictionary(); + private static ConcurrentDictionary actions = new ConcurrentDictionary(); + + static readonly object SendLock = new object(); + static readonly object SendParLock = new object(); + static readonly object RegisterLock = new object(); + + /// + /// 注销委托 + /// + /// + public void CancelRegister(string key) + { + if (actions.ContainsKey(key)) + actions.TryRemove(key, out Delegation t); + } + + /// + /// 执行注册过的委托 + /// + /// 注册委托的key + /// 委托参数 + /// 委托回调 + public void Send(string key, object par, Action Callback = null) + { + lock (SendLock) + if (actions.ContainsKey(key)) actions[key].ActionPar.Invoke(par, Callback); + } + + /// + /// 执行注册过的委托 + /// + /// 注册委托的key + /// 委托参数 + /// 委托回调 + public void Send(string key, object[] par, Action Callback = null) + { + lock (SendLock) + if (actions.ContainsKey(key)) actions[key].ActionPars.Invokes(par, Callback); + } + + /// + /// 执行注册过的委托 + /// + /// 注册委托的key + /// 委托回调 + public void Send(string key, Action Callback = null) + { + lock (SendLock) + if (actions.ContainsKey(key)) actions[key].ActionBus?.Invoke(Callback); + } + + public object SendResult(string key, object par = null) + { + lock (SendLock) + if (actions.ContainsKey(key)) + if (par == null) + { + return actions[key].FuncObj?.Invoke(); + } + else + { + return actions[key].FuncPar?.Invoke(par); + } + return default; + } + + public void Register(T action, string key) + { + lock (RegisterLock) + { + if (action != null) + { + if (!actions.ContainsKey(key)) + { + if (action is Action actionBus) + actions.TryAdd(key, new Delegation() { ActionBus = actionBus }); + + if (action is Action actionObj) + actions.TryAdd(key, new Delegation() { ActionPar = actionObj }); + + if (action is Action actionObjs) + actions.TryAdd(key, new Delegation() { ActionPars = actionObjs }); + + if (action is Func funcObj) + actions.TryAdd(key, new Delegation() { FuncObj = funcObj }); + + if (action is Func puncPar) + actions.TryAdd(key, new Delegation() { FuncPar = puncPar }); + } + } + } + + } + + } + public static class ExpandMethod + { + /// + /// 获取布尔数组指定值得索引 + /// + /// 要获取索引的数组 + /// 要获取索引的值 + /// + public static int GetIndex(this bool[] obj, bool value) + { + if (obj == null) return -1; + return Array.FindIndex(obj, p => p == value); + } + + /// + /// 获取字符串数组指定值得索引 + /// + /// 要获取索引的数组 + /// 要获取索引的值 + /// + public static int GetIndex(this string[] obj, string value) + { + if (obj == null || value == null) return -1; + return Array.FindIndex(obj, p => p == value && p.Length > 0); + } + + /// + /// 委托回调 + /// + /// 要执行的委托 + /// 委托回调 + public static void Invoke(this Action action, Action callback) + { + action?.Invoke(); + callback?.Invoke(); + } + + /// + /// 委托回调 + /// + /// 要执行的委托 + /// 要执行的委托的参数 + /// 委托回调 + public static void Invoke(this Action action, object par, Action callback) + { + action?.Invoke(par); + callback?.Invoke(); + } + + public static void Invokes(this Action action, object[] par, Action callback) + { + action?.Invoke(par); + callback?.Invoke(); + } + + + /// + /// 字节数组转换成32位整数 + /// + /// + /// + public static int BytesToInt(this byte[] bytes) + { + if (bytes.Length > 4) return -1; + int ReturnVlaue = 0; + for (int i = 0; i < bytes.Length; i++) + { + ReturnVlaue += (int)(bytes[i] << (i * 8)); + } + return ReturnVlaue; + } + + /// + /// 字节数组转换成 ushort 数组 + /// + /// 要转换的字节数组 + /// 字节高度顺序控制 + /// + public static ushort[] BytesToUshorts(this byte[] bytes, bool reverse = false) + { + int len = bytes.Length; + + byte[] srcPlus = new byte[len + 1]; + bytes.CopyTo(srcPlus, 0); + int count = len >> 1; + + if (len % 2 != 0) + { + count += 1; + } + + ushort[] dest = new ushort[count]; + if (reverse) + { + for (int i = 0; i < count; i++) + { + dest[i] = (ushort)(srcPlus[i * 2] << 8 | srcPlus[2 * i + 1] & 0xff); + } + } + else + { + for (int i = 0; i < count; i++) + { + dest[i] = (ushort)(srcPlus[i * 2] & 0xff | srcPlus[2 * i + 1] << 8); + } + } + + return dest; + } + + /// + /// ushort 数组转换成字节数组 + /// + /// 需要转换的 ushort数组 + /// 高低字节的设置 + /// + public static byte[] UshortsToBytes(this ushort[] src, bool reverse = false) + { + + int count = src.Length; + byte[] dest = new byte[count << 1]; + if (reverse) + { + for (int i = 0; i < count; i++) + { + dest[i * 2] = (byte)(src[i] >> 8); + dest[i * 2 + 1] = (byte)(src[i] >> 0); + } + } + else + { + for (int i = 0; i < count; i++) + { + dest[i * 2] = (byte)(src[i] >> 0); + dest[i * 2 + 1] = (byte)(src[i] >> 8); + } + } + return dest; + } + } +}