using System; using System.Collections; using System.Collections.Generic; using System.Drawing.Drawing2D; using System.IO; using System.Linq; using System.Reflection; using System.Security.Policy; using System.Text; using System.Threading; using System.Threading.Tasks; using System.Timers; using Advantech.Motion; using Automation.BDaq; using Newtonsoft.Json.Linq; using OpenCvSharp; namespace AssistClient.Device { public class IOCardDev : IDisposable { private Automation.BDaq.InstantDiCtrl instantDiCtrl1; private Automation.BDaq.InstantDoCtrl instantDoCtrl; public string DeviceNum { get; private set; } /// /// 读取输入端口数量 /// public int DIPortCount { get; private set; } /// /// 写入输出端口数量 /// public int DOPortCount { get; private set; } /// /// 读取到的输入值 /// public byte[] DIData { get; private set; } public byte[] DOData { get; private set; } /// /// Log输出 /// public Action WarningEvent; public Action INEvent; public Action OUTEvent; /// /// 是否打开设备成功 /// public bool IsInit { get; private set; } = false; private System.Timers.Timer timer = new System.Timers.Timer(); //频闪使用 private System.Timers.Timer timerStrobe = new System.Timers.Timer(); private List strobeList = new List(); public IOCardDev() { } public bool start(string deviceNum="") { try { instantDiCtrl1 = new Automation.BDaq.InstantDiCtrl(); instantDoCtrl = new Automation.BDaq.InstantDoCtrl(); strobeList=new List(); if (deviceNum != "") { instantDiCtrl1.SelectedDevice = new Automation.BDaq.DeviceInformation(deviceNum); instantDoCtrl.SelectedDevice = new DeviceInformation(deviceNum); } //根据加载的文件设置设备的所有配置 string cfgPath = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\DevCfg\\IOCard_1703.xml"; if (File.Exists(cfgPath)) { var result = instantDiCtrl1.LoadProfile(cfgPath);//Loads a profile to initialize the device. var result2 = instantDoCtrl.LoadProfile(cfgPath);//Loads a profile to initialize the device. if (BioFailed(result) && BioFailed(result2)) throw new Exception("CardIO Load Config Failed With Error Code: [" + result.ToString() + "]"); } DeviceNum = instantDiCtrl1.SelectedDevice.Description; DIPortCount = instantDiCtrl1.Features.PortCount; DIData = new byte[DIPortCount]; DOPortCount = instantDoCtrl.Features.PortCount; DOData = new byte[DOPortCount]; loadDOData(); IsInit = true; timer.Elapsed += Timer_Elapsed; timer.Interval = 100; timer.Start(); timerStrobe.Elapsed += timerStrobe_Elapsed; timerStrobe.Interval = 500; timerStrobe.Start(); return true; } catch (Exception ex) { WarningEvent?.Invoke(WarningEnum.High, ex.Message); return false; } } public void stop() { if (!IsInit) return; IsInit = false; strobeList.Clear();//闪烁状态清空 timer.Stop(); timerStrobe.Stop(); //instantDiCtrl1.Cleanup(); instantDiCtrl1.Dispose(); //instantDoCtrl.Cleanup(); instantDoCtrl.Dispose(); } private void loadDOData(int portIndex=-1) { for (int i = 0; i < DOPortCount; ++i) { if (i == portIndex || portIndex < 0) { byte data; var reuslt = instantDoCtrl.Read(i, out data); if (reuslt != Automation.BDaq.ErrorCode.Success) throw new Exception("加载CardIO输出状态失败!"); if (DOData[i] != data) { DOData[i] = data; //Config.HeightDevIOState = compareIOHeightDev(); //WarningEvent(WarningEnum.Normal, "厚度气缸状态:" + Config.HeightDevIOState.ToString()); OUTEvent?.Invoke(i, DOData[i]); } } } } /// /// 复位,全置0 /// /// public bool reset() { strobeList.Clear();//闪烁状态清空 byte[] data=new byte[DOPortCount]; for(int i = 0;i < data.Length; ++i) data[i]=0; var reuslt = instantDoCtrl.Write(0, data.Length, data); if (BioFailed(reuslt)) return false; loadDOData(); return true; } /// /// 闪烁状态会清空 /// /// /// /// public bool writeData(int startPort, byte[] data) { strobeList.Clear();//闪烁状态清空 var reuslt = instantDoCtrl.Write(startPort, data.Length, data); if (BioFailed(reuslt)) return false; loadDOData(data.Length == 1 ? startPort : -1); return true; } /// /// /// /// /// /// /// 频闪 /// public bool writeBitState(int portIndex, int bitIndex, bool state, bool isStrobe = false) { //byte bit = (byte)(DOData[portIndex] & (byte)(0x01< 0 && state) return true; //if (bit == 0 && !state) return true; //byte data = DOData[portIndex]; //data &= (byte)(~(0x1 << bitIndex)); //data |= (byte)((state ? 1 : 0) << bitIndex); //var reuslt = instantDoCtrl.Write(startPort, len, data); var reuslt = instantDoCtrl.WriteBit(portIndex, bitIndex, (byte)(state ? 1 : 0));// (byte)((state ? 1 : 0) << bitIndex)); if (BioFailed(reuslt)) return false; loadDOData(portIndex); string key = portIndex + "|" + bitIndex; if (state && isStrobe) strobeList.Add(key); else if(strobeList.Contains(key)) strobeList.Remove(key); return true; } public bool getDIBitState(int portIndex, int bitIndex) { byte data = 0x01; data=(byte)(data << bitIndex); return (DIData[portIndex] & data) > 0; } public bool getDOBitState(int portIndex, int bitIndex) { byte data = 0x01; data = (byte)(data << bitIndex); return (DOData[portIndex] & data) > 0; } private bool strobeState = true; private void timerStrobe_Elapsed(object sender, ElapsedEventArgs e) { if (!IsInit) return; string[] key; for(int i = 0;i< strobeList.Count; i++) { key=strobeList[i].Split('|'); instantDoCtrl.WriteBit(Convert.ToInt16(key[0]), Convert.ToInt16(key[1]), (byte)(strobeState ? 1 : 0)); } strobeState =!strobeState; } private void Timer_Elapsed(object sender, ElapsedEventArgs e) { if (!IsInit) return; timer.Stop(); //byte data = 0;//data is used to the API ReadBit. //int bit = 0;//bit is used to the API ReadBit. Automation.BDaq.ErrorCode result; int startPort = 0; byte[] datas = new byte[DIPortCount]; do { result = instantDiCtrl1.Read(startPort, DIPortCount, datas); //errorCode = instantDiCtrl.ReadBit(startPort, bit, out data); if (BioFailed(result)) { INEvent?.Invoke(999, 0xff); //throw new Exception(); continue; } for (int i = 0; i < datas.Length; i++) { if (DIData[i] != datas[i]) { DIData[i]= datas[i]; INEvent?.Invoke(i, DIData[i]); } } Thread.Sleep(100); } while (IsInit); } private static bool BioFailed(Automation.BDaq.ErrorCode err) { return err < Automation.BDaq.ErrorCode.Success && err >= Automation.BDaq.ErrorCode.ErrorHandleNotValid; } public void Dispose() { stop(); } } }