using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Sharp7;
using HTCoreServiceApp.DriverInterface;
using HTCoreServiceApp.Models;
using System.Threading;
using HTCoreServiceApp.Common;
using System.Collections;
using System.Text.RegularExpressions;
using HTCoreServiceApp.DataHandle;
using System.Timers;
using Newtonsoft.Json.Linq;
using System.Net;
using static System.Runtime.InteropServices.JavaScript.JSType;
using Pipelines.Sockets.Unofficial.Arenas;
using System.Numerics;
using Microsoft.AspNetCore.Http;
using Newtonsoft.Json;
using Dm;

namespace HTCoreServiceApp.Communicate.DriverSiemensS7
{
    public class DisperseS7ClientExample : IDriverEntity
    {

        public string DeviceId { get; set; }

        private string DriverName { get; set; }
        private List<MetaSystem> Systems { get; set; }

        public bool IsConnected { get; set; }

        public int Timeout { get; set; }

        public bool isScan { get; set; }

        public System.Timers.Timer ScanTimer { get ; set; }

		System.Timers.Timer timerCheck = new System.Timers.Timer();

		public string Address = "127.0.0.1";
        private int Rack = 0;
        private int Slot = 0;

        private string PLCType = "";

        public S7Client Client;
        //private byte[] Buffer = new byte[65536];
        //private byte[] DB_A = new byte[1024];
        //private byte[] DB_B = new byte[1024];
        //private byte[] DB_C = new byte[1024];
        private readonly object _lock = new();


        private List<MetaGroup> MetaGroups;
        private List<MetaTag> MetaTags;


        private List<ScanTagsPara> SetupParameterTagsPara;
        //private bool BSetupParameter = false;
        //List<Argument> argument, List<MetaGroup> metaGroups,List<MetaTag> metaTags
        public DisperseS7ClientExample(TagGroup tagGroup) 
        {
            Client = new S7Client();

            Address =tagGroup.Arguments.Where(x => x.PropertyName == "ServerName").First().PropertyValue;
            Rack = int.Parse(tagGroup.Arguments.Where(x => x.PropertyName == "Rack").First().PropertyValue);
            Slot = int.Parse(tagGroup.Arguments.Where(x => x.PropertyName == "Slot").First().PropertyValue);
            PLCType = tagGroup.Arguments.Where(x => x.PropertyName == "PLCType").First().PropertyValue;
            Timeout = int.Parse(tagGroup.Arguments.Where(x => x.PropertyName == "TimeOut").First().PropertyValue);
            MetaGroups =tagGroup.Groups;
            MetaTags = tagGroup.Tags;//只有一组
            DriverName = tagGroup.DriverName;
            Systems = tagGroup.Systems;

            SetupParameterTagsPara = new List<ScanTagsPara>();

            Client.SetConnectionType(0x3);
            Client.ConnTimeout= Timeout;
            Client.RecvTimeout = 200;



			//Connect();
			timerCheck.Interval = 2000;
			StartConnectCheck();

            StartScan();
        }

        public void StartScan()
        {
            var groups = MetaGroups.GroupBy(x => new { x.GroupId });

            var scanTagsParas = new List<ScanTagsPara>();
            
            foreach (var metaGroup in groups)
            {
                var groupType = metaGroup.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList().First().GroupType;
                

                ScanTagsPara scanTagsPara = new ScanTagsPara();
                scanTagsPara.GroupName = MetaGroups.Where(x=>x.GroupId == metaGroup.Key.GroupId).ToList().First().GroupName;
                scanTagsPara.UpdateRate = MetaGroups.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList().First().UpdateRate;
                scanTagsPara.IsConsecutive = (bool)MetaGroups.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList().First().IsActive;
                scanTagsPara.IsActive = MetaGroups.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList().First().IsActive;
                //scanTagsPara.IsActive = false;
                scanTagsPara.ScanTags  = MetaTags.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList();
                if (scanTagsPara.ScanTags.Count < 1)
                {
                    continue;
                }
                short driverID = (short)MetaGroups.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList().First().DriverId;
                scanTagsPara.DriverName = DriverName;
                var groupSysId = MetaGroups.Where(x => x.GroupId == metaGroup.Key.GroupId).ToList().First().SystemId;
                scanTagsPara.SystemName = Systems.Where(x => x.SystemId == groupSysId).ToList().First().SystemName;
                scanTagsPara.AddressArg = PLCHelper.GetAddressArg(scanTagsPara.ScanTags);

                var pBools = scanTagsPara.ScanTags.Where(x => x.DataType == (short)DataType.PBOOL).ToList();
                var pBoolCount = pBools.Count;
                if (pBoolCount > 0)
                {
                    scanTagsPara.IncludeBChaned = true;
                    scanTagsPara.BChangedAddress = pBools.First().Address;
                }
                else
                {
                    scanTagsPara.IncludeBChaned= false;
                }
                if (groupType == 0 || groupType == null)
                {
                    scanTagsParas.Add(scanTagsPara);
                }
                else if (groupType == 1)
                {
                    SetupParameterTagsPara.Add(scanTagsPara);
                }
                    
            }

            //if 添加连续或单变量读取标记
            //if (scanTagsPara.IsConsecutive == true)
            //{
            //    if (scanTagsPara.IsActive == true && scanTagsPara.ScanTags.Count > 0)
            //        Task.Run(() =>
            //        {
            //            ScanConsecutive(scanTagsPara);
            //        }) ;
            //}
            //else
            //{
            //    if (scanTagsPara.IsActive == true && scanTagsPara.ScanTags.Count > 0)
            //        Task.Run(() =>
            //        {
            //            Scan(scanTagsPara);
            //        });

            //}
            ScanConsecutive(scanTagsParas);
        }

        /// <summary>
        /// 启动连续读取
        /// </summary>
        /// <param name="scanTagsParas"></param>
        public void ScanConsecutive(List<ScanTagsPara> scanTagsParas)
        {
            foreach (var scanTagsPara in scanTagsParas)
            {
                ScanTimer timerScan = new ScanTimer();
                if (scanTagsPara.UpdateRate > 0)
                {
                    timerScan.Interval = (double)scanTagsPara.UpdateRate;
                }
                else
                {
                    timerScan.Interval = 1000;
                }
                timerScan.ScanTagsPara = scanTagsPara;

                //timerScan.AddressArg = PLCHelper.GetAddressArg(scanTagsParas.ScanTags);

                timerScan.Elapsed += new System.Timers.ElapsedEventHandler(TimerScanConsecutive_Elapsed);
                timerScan.Enabled = true;
            }
        }
        /// <summary>
        /// 连续读取timer事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimerScanConsecutive_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            long hdatetime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
            ScanTimer timerScan = (ScanTimer)sender;
            ScanTagsPara scanTagsPara = timerScan.ScanTagsPara;
            //AddressArg addressArg = timerScan.AddressArg;
            
            if (scanTagsPara.IsActive == false)
                return;
            if (Client.Connected)
            {

                var addressArg = scanTagsPara.AddressArg;

                //object _lock = new();

                Task task = Task.Run(() =>
                {
                    lock (_lock)
                    {
                        try
                        {
                            var tcollstart = DateTime.Now;
                            //CodingTools.StartTime = DateTime.Now.Millisecond;//de
                            //scanTagsPara.ScanTags.Min(x => x.Address);
                            //scanTagsPara.ScanTags.Min(x => x.Address);提高速度应放在timer事件前，测试后更改
                            int startAdress = addressArg.Start;
                            int Area = 132;
                            int DBNumber = 0;
                            if (scanTagsPara.GroupName.Contains("DB"))
                            {
                                DBNumber = int.Parse(Regex.Replace(scanTagsPara.GroupName, "[a-z]", "", RegexOptions.IgnoreCase));
                            }
                            else
                            {
                                DBNumber = int.Parse(scanTagsPara.GroupName);
                            }
                            int amount = addressArg.Length;
                            int WordLen = 2;
                            byte[] buffer = new byte[amount];
                            int pdu = PLCHelper.GetSiemensPDU(PLCType) * 2 - 18;
                            int Result = 0;


                            //byte[] bufferr = new byte[amount];
                            Result = ReadArea(Area, DBNumber, startAdress, amount, WordLen, ref buffer);


                            //if (amount <= pdu)
                            //{
                            //    Result = ReadArea(Area, DBNumber, startAdress, amount, WordLen, ref buffer);
                            //}
                            //else
                            //{
                            //    //int additional = amount- pdu;
                            //    int forCount = (int)Math.Ceiling(float.Parse(((float)amount / (float)pdu).ToString()));
                            //    List<byte[]> bytes= new List<byte[]>();
                            //    for (int i = 0; i < forCount; i++)
                            //    {
                            //        if ((amount - (i * pdu)) > pdu)
                            //        {
                            //            int start = startAdress + i * pdu;
                            //            byte[] bytes1 = new byte[pdu];
                            //            Result = ReadArea(Area, DBNumber, start, pdu, WordLen, ref bytes1);
                            //            bytes.Add(bytes1);
                            //        }
                            //        else
                            //        {
                            //            int start = startAdress + i * pdu;
                            //            byte[] bytes1 = new byte[amount - (i * pdu)];
                            //            Result = ReadArea(Area, DBNumber, start, amount - (i * pdu), WordLen, ref bytes1);
                            //            bytes.Add(bytes1);
                            //        }
                            //        Thread.Sleep(3);
                            //    }
                            //    var byetstemp = Array.Empty<byte>();
                            //    foreach (var buff in bytes)
                            //    {
                            //        byetstemp = byetstemp.Concat(buff).ToArray();
                            //    }
                            //    buffer = byetstemp;
                            //}


                            var tcollend = DateTime.Now;
                            var timecolldiff =  tcollend - tcollstart;
                            Console.WriteLine($"S7读取耗时：{timecolldiff},设备:{DriverName}变量组:{scanTagsPara.GroupName}");
                            //CodingTools.EndTime = DateTime.Now.Millisecond;//de
                            //var timess = (CodingTools.EndTime - CodingTools.StartTime).ToString();
                            //Console.WriteLine($"读取耗时：{timess}");
                            if (Result == 0)
                            {
                                var t1 = DateTime.Now;
                                Console.WriteLine(string.Join(",", buffer) + "S7读取完成：DB" + DBNumber.ToString() + ",字节数：" + amount.ToString());
                                //Task<int> saveResult = DataExtract.DataExtractCAsync(scanTagsPara.ScanTags, scanTagsPara.GroupName, scanTagsPara.DriverName, buffer, addressArg);
                                var ss = new DataExtract();
                                
                                Task.Run(()=>

                                    ss.DataExtractCAsync(scanTagsPara.ScanTags, scanTagsPara.SystemName, scanTagsPara.GroupName, scanTagsPara.DriverName, buffer, addressArg, hdatetime)
                                );
                                var t2 = DateTime.Now;
                                var timediff = t2- t1;
                                Console.WriteLine($"S7缓存和储存耗时：{timediff}");
                                {
                                    //if (saveResult.Result == 0)
                                    //{
                                    //    //logger
                                    //}
                                    //else
                                    //{
                                    //    //logger
                                    //}

                                }
                                if(scanTagsPara.IncludeBChaned)
                                {
                                    var BChanged = GetVlaue((short)DataType.BOOL, scanTagsPara.BChangedAddress, buffer, addressArg);
                                    if(BChanged == "True")
                                    {
                                        var ReadSetResult = StartReadSetupParameter();
                                        if (ReadSetResult == 0)
                                        {
                                            SetDeviceData(scanTagsPara.GroupName, "BChanged", "0");
                                        }
                                    }
                                }
                            }
                            else if (Result != 0)
                            {
                                Console.WriteLine("S7读取失败：DB" + DBNumber.ToString() + ",ERRORCODE：" + Result.ToString());
								LogHelper.LogWrite("S7读取失败：DB" + DBNumber.ToString() + ",ERRORCODE：" + Result.ToString());
								//Close();
								//Thread.Sleep(50);
								//Connect();
						    }

                        }
                        catch (Exception ex)
                        {
                            LogHelper.LogWrite($"{DriverName}读取失败，S7错误信息{ex}");
                        }
                    }

                });
            }
            else
            {
				LogHelper.LogWrite($"{DriverName}读取失败，S7未连接");
				//Connect();
			}
            Thread.Sleep(50);
            
        }

        /// <summary>
        /// 
        /// </summary>
        public int StartReadSetupParameter()
        {


            //AddressArg addressArg = timerScan.AddressArg;
            int recode = 0;
            foreach (var scanTagsPara in SetupParameterTagsPara)
            {
                if (scanTagsPara.IsActive == false)
                    break;
                if (Client.Connected)
                {

                    var addressArg = scanTagsPara.AddressArg;

                    //object _lock = new();

                    Task task = Task.Factory.StartNew(() =>
                    {
                        lock (_lock)
                        {
                            try
                            {
                                var tcollstart = DateTime.Now;
                                //CodingTools.StartTime = DateTime.Now.Millisecond;//de
                                //scanTagsPara.ScanTags.Min(x => x.Address);
                                //scanTagsPara.ScanTags.Min(x => x.Address);提高速度应放在timer事件前，测试后更改
                                int startAdress = addressArg.Start;
                                int Area = 132;
                                int DBNumber = 0;
                                if (scanTagsPara.GroupName.Contains("DB"))
                                {
                                    DBNumber = int.Parse(Regex.Replace(scanTagsPara.GroupName, "[a-z]", "", RegexOptions.IgnoreCase));
                                }
                                else
                                {
                                    DBNumber = int.Parse(scanTagsPara.GroupName);
                                }
                                int amount = addressArg.Length;
                                int WordLen = 2;
                                byte[] buffer = new byte[amount];
                                int pdu = PLCHelper.GetSiemensPDU(PLCType) * 2 - 18;
                                int Result = 0;
                                if (amount <= pdu)
                                {
                                    Result = ReadArea(Area, DBNumber, startAdress, amount, WordLen, ref buffer);
                                }
                                else
                                {
                                    //int additional = amount- pdu;
                                    int forCount = (int)Math.Ceiling(float.Parse(((float)amount / (float)pdu).ToString()));
                                    List<byte[]> bytes = new List<byte[]>();
                                    for (int i = 0; i < forCount; i++)
                                    {
                                        if ((amount - (i * pdu)) > pdu)
                                        {
                                            int start = startAdress + i * pdu;
                                            byte[] bytes1 = new byte[pdu];
                                            Result = ReadArea(Area, DBNumber, start, pdu, WordLen, ref bytes1);
                                            bytes.Add(bytes1);
                                        }
                                        else
                                        {
                                            int start = startAdress + i * pdu;
                                            byte[] bytes1 = new byte[amount - (i * pdu)];
                                            Result = ReadArea(Area, DBNumber, start, amount - (i * pdu), WordLen, ref bytes1);
                                            bytes.Add(bytes1);
                                        }
                                        Thread.Sleep(3);
                                    }
                                    var byetstemp = Array.Empty<byte>();
                                    foreach (var buff in bytes)
                                    {
                                        byetstemp = byetstemp.Concat(buff).ToArray();
                                    }
                                    buffer = byetstemp;
                                }
                                recode = recode + Result;
                                var tcollend = DateTime.Now;
                                var timecolldiff = tcollend - tcollstart;
                                Console.WriteLine($"S7<工艺设定参数>读取耗时：{timecolldiff},设备:{DriverName}");
                                //CodingTools.EndTime = DateTime.Now.Millisecond;//de
                                //var timess = (CodingTools.EndTime - CodingTools.StartTime).ToString();
                                //Console.WriteLine($"读取耗时：{timess}");
                                if (Result == 0)
                                {
                                    var t1 = DateTime.Now;
                                    Console.WriteLine(string.Join(",", buffer) + "S7<工艺设定参数>读取完成：DB" + DBNumber.ToString() + ",字节数：" + amount.ToString());
                                    //Task<int> saveResult = DataExtract.DataExtractCAsync(scanTagsPara.ScanTags, scanTagsPara.GroupName, scanTagsPara.DriverName, buffer, addressArg);
                                    var ss = new DataExtract();
                                    long hdatetime = new DateTimeOffset(DateTime.UtcNow).ToUnixTimeMilliseconds();
                                    ss.DataExtractCAsync(scanTagsPara.ScanTags, scanTagsPara.SystemName, scanTagsPara.GroupName, scanTagsPara.DriverName, buffer, addressArg, hdatetime);
                                    var t2 = DateTime.Now;
                                    var timediff = t2 - t1;
                                    Console.WriteLine($"S7<工艺设定参数>缓存和储存耗时：{timediff}");
                                    {
                                        //if (saveResult.Result == 0)
                                        //{
                                        //    //logger
                                        //}
                                        //else
                                        //{
                                        //    //logger
                                        //}

                                    }
                                    //if (scanTagsPara.IncludeBChaned)
                                    //{
                                    //    var BChanged = GetVlaue((short)DataType.BOOL, scanTagsPara.BChangedAddress, buffer, addressArg);
                                    //    if (BChanged == "True")
                                    //    {
                                    //        StartReadSetupParameter();
                                    //        SetDeviceData(scanTagsPara.GroupName, "BChanged", "0");
                                    //    }
                                    //}
                                }
                                else if (Result != 0)
                                {
                                    Console.WriteLine("S7工艺设定参数读取失败：DB" + DBNumber.ToString() + ",ERRORCODE：" + Result.ToString());
                                    LogHelper.LogWrite("S7工艺设定参数读取失败：DB" + DBNumber.ToString() + ",ERRORCODE：" + Result.ToString());
                                    //Close();
                                    //Thread.Sleep(50);
                                    //Connect();
                                }

                            }
                            catch (Exception ex)
                            {
                                LogHelper.LogWrite($"{DriverName}读取失败，S7错误信息{ex}");
                                recode = recode + 1;
                            }
                        }

                    });
                }
                else
                {
                    LogHelper.LogWrite($"{DriverName}读取失败，S7未连接");
                    //Connect();
                    return -1;
                }
                Thread.Sleep(10);
            }
            return recode;

        }

        private static string GetVlaue(short dataType, string address, byte[] bytes, AddressArg addressArg)
        {
            string val = "";

            string startaddress = Regex.Replace(address, "[a-z]", "", RegexOptions.IgnoreCase);
            int address_dem = 0;
            int address_int = 0;
            if (startaddress.Contains(".") && startaddress.Length > 2)
            {
                try
                {
                    string[] address_arr = startaddress.Split('.');
                    address_int = int.Parse(address_arr[0]) - addressArg.AddressOffset;
                    address_dem = int.Parse(address_arr[1]);
                }
                catch (Exception exp)
                {
                    //logger
                }
            }
            else
            {
                address_int = int.Parse(startaddress) - addressArg.AddressOffset;
            }

            switch (dataType)
            {
                case (short)DataType.FLOAT:
                    return S7.GetRealAt(bytes, address_int).ToString();
                case (short)DataType.BOOL:
                    return S7.GetBitAt(bytes, address_int, address_dem).ToString();
                case (short)DataType.INT:
                    return S7.GetIntAt(bytes, address_int).ToString();
                case (short)DataType.WORD:
                    return S7.GetWordAt(bytes, address_int).ToString();
            }
            return val;
        }
        /*
        /// <summary>
        /// 启动单个变量读取
        /// </summary>
        /// <param name="scanTagsPara"></param>
        public void Scan(ScanTagsPara scanTagsPara)
        {
            ScanTimer timerScan = new ScanTimer();
            if (scanTagsPara.UpdateRate > 0)
            {
                timerScan.Interval = (double)scanTagsPara.UpdateRate;
            }
            else
            {
                timerScan.Interval = 1000;
            }
            timerScan.ScanTagsPara = scanTagsPara;
            timerScan.Elapsed += new System.Timers.ElapsedEventHandler(TimerScan_Elapsed);
            timerScan.Enabled = true;
        }

        /// <summary>
        /// 单个变量读取timer事件
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void TimerScan_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
            ScanTimer timerScan = (ScanTimer)sender;
            ScanTagsPara scanTagsPara = timerScan.ScanTagsPara;
            AddressArg addressArg = timerScan.AddressArg;
            if (IsConnected = true)
            {
                object _lock = new();

                Task task = Task.Run(() =>
                {
                    lock (_lock)
                    {
                        try
                        {
                            //CodingTools.StartTime = DateTime.Now.Millisecond;//de
                            //scanTagsPara.ScanTags.Min(x => x.Address);
                            //scanTagsPara.ScanTags.Min(x => x.Address);提高速度应放在timer事件前，测试后更改
                            int startAdress = addressArg.Start;
                            int Area = 132;
                            int DBNumber = 0;
                            if (scanTagsPara.GroupName.Contains("DB"))
                            {
                                DBNumber = int.Parse(Regex.Replace(scanTagsPara.GroupName, "[a-z]", "", RegexOptions.IgnoreCase));
                            }
                            else
                            {
                                DBNumber = int.Parse(scanTagsPara.GroupName);
                            }
                            int amount = addressArg.Length;
                            int WordLen = 2;
                            byte[] buffer = new byte[amount];
                            int Result = ReadArea(Area, DBNumber, startAdress, amount, WordLen, ref buffer);
                            //CodingTools.EndTime = DateTime.Now.Millisecond;//de
                            //var timess = (CodingTools.EndTime - CodingTools.StartTime).ToString();
                            //Console.WriteLine($"读取耗时：{timess}");
                            if (Result == 0)
                            {
                                //Console.WriteLine(string.Join(",", buffer) + "读取完成：DB" + DBNumber.ToString() + ",字节数：" + amount.ToString());
                                int saveResult = DataExtract.DataExtractConsecutive(timerScan.ScanTagsPara.ScanTags, scanTagsPara.GroupName, timerScan.ScanTagsPara.DriverName, buffer, addressArg);
                                {
                                    if (saveResult == 0)
                                    {
                                        //logger
                                    }
                                    else
                                    {
                                        //logger
                                    }

                                }
                            }
                            else if (Result != 0)
                            {
                                Console.WriteLine("读取失败：DB" + DBNumber.ToString() + ",ERRORCODE：" + Result.ToString());
                                Close();
                                Thread.Sleep(200);
                                Connect();
                            }

                        }
                        catch (Exception ex)
                        {

                        }
                    }

                });
            }
            else
            {
                Connect();
            }
        }
        */
        public int ReadArea(int Area, int DBNumber, int start, int Amount, int WordLen, ref byte[] buffer)
        {
            object _lock = new();
            lock (_lock)
            {
                int reval = 0;
                int SizeRead = 0;
                int Result;
                //buffer = new byte[65536];
                return Result = Client.ReadArea(Area, DBNumber, start, Amount, WordLen, buffer, ref SizeRead);
            }
        }

		public void StartConnectCheck()
		{
			
			timerCheck.Elapsed += new System.Timers.ElapsedEventHandler(TimerCheckConnect_Elapsed);
			timerCheck.Enabled = true;
		}

        private void TimerCheckConnect_Elapsed(object? sender, System.Timers.ElapsedEventArgs e)
        {
			timerCheck.Enabled = false;
			if (Client.Connected)
            {
				timerCheck.Enabled = true;
				return;
            }
            else
            {
                Connect();
			}
        }


		public bool Connect()
        {
            int Result;
            Result = Client.ConnectTo(Address, Rack, Slot);
            if (Result == 0&& Client.Connected)
            {
                IsConnected = true;
				//log
				LogHelper.LogWrite($"S7连接成功，返回值:{Result}");
				timerCheck.Enabled = true;
				return true;
            }
            else
            {
                IsConnected = false;
                //log
                LogHelper.LogWrite($"S7连接失败，返回值:{Result}");
				timerCheck.Enabled = true;
				return false;
            }
        }

        public bool Close()
        {
            int Result;
            Result = Client.Disconnect();
            if (Result == 0)
            {
                IsConnected = false;
				//log
				LogHelper.LogWrite($"S7关闭连接成功，返回值:{Result}");
				return true;
            }
            else
            {
                IsConnected = false;
				LogHelper.LogWrite($"S7关闭连接失败，返回值:{Result}");
				//log
				return false;
            }
        }

        public void Dispose()
        {
            try
            {
                int Result = Client.Disconnect();
                //log
            }
            catch (Exception ex)
            {
                //log
            }
            
        }
        /// <summary>
        /// 写入方法
        /// </summary>
        /// <param name="writePara"></param>
        /// <returns></returns>
		public int Write(WritePara writePara)
		{
            //var t1 = DateTime.Now;
            int reCode = 0;
            //JObject valueJson = JObject.Parse(writePara);
            var srcValue = writePara.Value; //valueJson[propertyName: "Value"].ToString();
            var writeAddress = writePara.WriteAddress;//valueJson[propertyName: "WriteAddress"].ToString();
            var dataType = writePara.DataType;//short.Parse(valueJson[propertyName: "DataType"].ToString());
            var groupName = writePara.GroupName; //valueJson[propertyName: "GroupName"].ToString();
            var windex = writeAddress.IndexOf(".");
            writeAddress = writeAddress.Remove(windex, 1).Insert(windex, ",");
            var array = writeAddress.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            var DBNum_string = array[0].ToString();
            var DBNum = int.Parse(Regex.Replace(DBNum_string, "[a-z]", "", RegexOptions.IgnoreCase));
			
            var address = array[1].ToString();
			string startaddress = Regex.Replace(address, "[a-z]", "", RegexOptions.IgnoreCase);
			int address_dem = 0;
			int address_int = 0;
			if (startaddress.Contains(".") && startaddress.Length > 2)
			{
				try
				{
					string[] address_arr = startaddress.Split('.');
					address_int = int.Parse(address_arr[0]);
					address_dem = int.Parse(address_arr[1]);
				}
				catch (Exception exp)
				{
					//logger
				}
			}
			else
			{
				address_int = int.Parse(startaddress);
			}

			byte[] revbuffer_w;// = new byte[maxreg + 2];
			decimal value = decimal.Parse(srcValue);
            lock (_lock)
            {
			    if (dataType == (short)DataType.BOOL)
			    {
                    var boolbyte = new byte[1];
				    int rebooltempread = ReadArea(132, DBNum, address_int, 1, 2, ref boolbyte);
                    Thread.Sleep(50);
                    Console.WriteLine(rebooltempread);
                    var temval = (float)value;
				    bool bl = temval > 0.0f ? true : false;
				    //var rtbyte = revbuffer_w[address_int];
				    //var rtbuff = Sharp7.S7. rtbyte
				    Sharp7.S7.SetBitAt(ref boolbyte, 0, address_dem, bl);
				    reCode = Client.WriteArea(132, DBNum, address_int, 1, 2, boolbyte);
			    }
			    else if (dataType == (short)DataType.FLOAT)
			    {
                    revbuffer_w = new byte[4];
				    Sharp7.S7.SetRealAt(revbuffer_w, 0, (float)value);
				    reCode = Client.WriteArea(132, DBNum, address_int, 4, 2, revbuffer_w);
			    }
                else if (dataType == (short)DataType.IFLOAT)
                {
                    revbuffer_w = new byte[2];

                    Sharp7.S7.SetIntAt(revbuffer_w, 0, (short)value);
                    reCode = Client.WriteArea(132, DBNum, address_int, 2, 2, revbuffer_w);
                }
                else if (dataType == (short)DataType.INT)
                {
                    revbuffer_w = new byte[2];
                    Sharp7.S7.SetIntAt(revbuffer_w, 0, (short)value);
                    reCode = Client.WriteArea(132, DBNum, address_int, 2, 2, revbuffer_w);
                }
                else if (dataType == (short)DataType.WORD)
			    {
				    revbuffer_w = new byte[2];
				    Sharp7.S7.SetWordAt(revbuffer_w, 0, (ushort)value);
				    reCode = Client.WriteArea(132, DBNum, address_int, 2, 2, revbuffer_w);
			    }
			    else if (dataType == (short)DataType.BYTE)
			    {
				    revbuffer_w = new byte[1];
				    Sharp7.S7.SetByteAt(revbuffer_w, 0, (byte)value);
				    reCode = Client.WriteArea(132, DBNum, address_int, 1, 2, revbuffer_w);
			    }
                else if (dataType == (short)DataType.PBOOL)
                {
                    var boolbyte = new byte[1];
                    int rebooltempread = ReadArea(132, DBNum, address_int, 1, 2, ref boolbyte);
                    Thread.Sleep(50);
                    Console.WriteLine(rebooltempread);
                    var temval = (float)value;
                    bool bl = temval > 0.0f ? true : false;
                    //var rtbyte = revbuffer_w[address_int];
                    //var rtbuff = Sharp7.S7. rtbyte
                    Sharp7.S7.SetBitAt(ref boolbyte, 0, address_dem, bl);
                    reCode = Client.WriteArea(132, DBNum, address_int, 1, 2, boolbyte);
                }
                else
                {

                }
			}
			Console.WriteLine(writePara);
            //var t2 = DateTime.Now;
            //var timediff = t2 - t1;
            //Console.WriteLine($"S7写入耗时：{timediff}");
            return reCode;
		}

        public int WriteBlock(WriteBlockPara writePara)
        {
            //var t1 = DateTime.Now;
            int reCode = 0;
            //JObject valueJson = JObject.Parse(writePara);
            var srcValue = writePara.Value; //valueJson[propertyName: "Value"].ToString();
            var writeAddress = writePara.WriteAddress;//valueJson[propertyName: "WriteAddress"].ToString();
            var dataType = writePara.DataType;//short.Parse(valueJson[propertyName: "DataType"].ToString());
            var windex = writeAddress.IndexOf(".");
            writeAddress = writeAddress.Remove(windex, 1).Insert(windex, ",");
            var array = writeAddress.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            var DBNum_string = array[0].ToString();
            var DBNum = int.Parse(Regex.Replace(DBNum_string, "[a-z]", "", RegexOptions.IgnoreCase));

            var address = array[1].ToString();
            string startaddress = Regex.Replace(address, "[a-z]", "", RegexOptions.IgnoreCase);
            int address_dem = 0;
            int address_int = 0;
            if (startaddress.Contains(".") && startaddress.Length > 2)
            {
                try
                {
                    string[] address_arr = startaddress.Split('.');
                    address_int = int.Parse(address_arr[0]);
                    address_dem = int.Parse(address_arr[1]);
                }
                catch (Exception exp)
                {
                    //logger
                }
            }
            else
            {
                address_int = int.Parse(startaddress);
            }

            byte[] revbuffer_w;// = new byte[maxreg + 2];
            decimal value = decimal.Parse(srcValue);
            lock (_lock)
            {
                if (dataType == (short)DataType.BOOL)
                {
                    var boolbyte = new byte[1];
                    int rebooltempread = ReadArea(132, DBNum, address_int, 1, 2, ref boolbyte);
                    Thread.Sleep(50);
                    Console.WriteLine(rebooltempread);
                    var temval = (float)value;
                    bool bl = temval > 0.0f ? true : false;
                    //var rtbyte = revbuffer_w[address_int];
                    //var rtbuff = Sharp7.S7. rtbyte
                    Sharp7.S7.SetBitAt(ref boolbyte, 0, address_dem, bl);
                    reCode = Client.WriteArea(132, DBNum, address_int, 1, 2, boolbyte);
                }
                else if (dataType == (short)DataType.FLOAT)
                {
                    revbuffer_w = new byte[4];
                    Sharp7.S7.SetRealAt(revbuffer_w, 0, (float)value);
                    reCode = Client.WriteArea(132, DBNum, address_int, 4, 2, revbuffer_w);
                }
                else if (dataType == (short)DataType.IFLOAT)
                {
                    revbuffer_w = new byte[2];

                    Sharp7.S7.SetIntAt(revbuffer_w, 0, (short)value);
                    reCode = Client.WriteArea(132, DBNum, address_int, 2, 2, revbuffer_w);
                }
                else if (dataType == (short)DataType.INT)
                {
                    revbuffer_w = new byte[2];
                    Sharp7.S7.SetIntAt(revbuffer_w, 0, (short)value);
                    reCode = Client.WriteArea(132, DBNum, address_int, 2, 2, revbuffer_w);
                }
                else if (dataType == (short)DataType.WORD)
                {
                    revbuffer_w = new byte[2];
                    Sharp7.S7.SetWordAt(revbuffer_w, 0, (ushort)value);
                    reCode = Client.WriteArea(132, DBNum, address_int, 2, 2, revbuffer_w);
                }
                else if (dataType == (short)DataType.BYTE)
                {
                    revbuffer_w = new byte[1];
                    Sharp7.S7.SetByteAt(revbuffer_w, 0, (byte)value);
                    reCode = Client.WriteArea(132, DBNum, address_int, 1, 2, revbuffer_w);
                }
                else if (dataType == (short)DataType.PBOOL)
                {
                    var boolbyte = new byte[1];
                    int rebooltempread = ReadArea(132, DBNum, address_int, 1, 2, ref boolbyte);
                    Thread.Sleep(50);
                    Console.WriteLine(rebooltempread);
                    var temval = (float)value;
                    bool bl = temval > 0.0f ? true : false;
                    //var rtbyte = revbuffer_w[address_int];
                    //var rtbuff = Sharp7.S7. rtbyte
                    Sharp7.S7.SetBitAt(ref boolbyte, 0, address_dem, bl);
                    reCode = Client.WriteArea(132, DBNum, address_int, 1, 2, boolbyte);
                }
                else
                {

                }
            }
            Console.WriteLine(writePara);
            //var t2 = DateTime.Now;
            //var timediff = t2 - t1;
            //Console.WriteLine($"S7写入耗时：{timediff}");
            return reCode;
        }

        public int SetDeviceData(string groupName, string tagName, string value)
        {

            int reCode = 0;

            
            try
            {
                if (!string.IsNullOrEmpty(groupName) && !string.IsNullOrEmpty(groupName) && !string.IsNullOrEmpty(groupName))
                {
                    //var context = StaticLibrary.DBContext;
                    //return StaticLibrary.MemoryCacheHelper.GetString(groupName);
                    //var driverID = MetaGroups.Where(x => x.GroupName == groupName).FirstOrDefault().DriverId;
                    //var driverName = MetaDrivers.Where(x => x.DriverId == driverID).FirstOrDefault().DriverName;
                    var groupID = MetaGroups.Where(x => x.GroupName == groupName).FirstOrDefault().GroupId;
                    var dataType = MetaTags.Where(x => x.TagName == tagName && x.GroupId == groupID).First().DataType;
                    var writeAddress = MetaTags.Where(x => x.TagName == tagName && x.GroupId == groupID).First().WriteAddress;
                    if (writeAddress == "" || writeAddress == null)
                    {
                        reCode = 1;
                        return reCode;
                    }
                    var windex = writeAddress.IndexOf(".");
                    writeAddress = writeAddress.Remove(windex, 1).Insert(windex, ",");
                    //var valueHandle = 0;
                    if (dataType == (short)DataType.BOOL)
                    {
                        if (value.Equals("True") || value.Equals("true") || value.Equals("TRUE") || value.Equals("1"))
                        {
                            value = "1";
                        }
                        else if (value.Equals("False") || value.Equals("false") || value.Equals("FALSE") || value.Equals("0"))
                        {
                            value = "0";
                        }
                    }
                    var writePara = new WritePara
                    {
                        TagName = tagName,
                        GroupName = groupName,
                        WriteAddress = writeAddress,
                        DataType = dataType,
                        Value = value
                    };
                    //string serJson = JsonConvert.SerializeObject(writePara);

                    Write(writePara);
                    
                }
                else
                {
                    reCode = 1;
                }
            }
            catch (Exception ex)
            {
                reCode = 1;
            }
            return reCode;
        }

        
    }
}
