/// <summary>
        /// 选择网卡,调用底层C++函数,这一步会导致其中变量ifbuf赋值为网卡名。
        /// </summary>
        /// <param name="id">此ID与网卡扫描顺序有关</param>
        /// <returns>成功返回100,失败返回-1</returns>
        public OperationResult SetAdapter(string id)
        {
            StringBuilder sb = new StringBuilder("\\Device\\NPF_" + id);

            HtEcConnector.SetAdapter(sb);   //返回-1表示赋值失败
            return(new OperationResult());
        }
        /// <summary>
        /// 获取本机网卡列表,调用底层C++函数。
        /// 由于无法实现传递string数组,因此基本原理是首先获取网络适配器数量adapterNum;
        /// 然后获取每一个adapter的Name,用StringBuilder来传递。
        /// </summary>
        public Adapter[] GetAdapter()
        {
            int adapterNum = HtEcConnector.getAdapterNum();    //Get adapter number first.

            Adapter[] adapters = new Adapter[adapterNum];

            StringBuilder tmpAdapterName = new StringBuilder();
            StringBuilder tmpAdapterDesc = new StringBuilder();

            tmpAdapterName.Capacity = 128;
            tmpAdapterDesc.Capacity = 128;
            for (int i = 0; i < adapterNum; i++)    //Get adapter name one-by-one.
            {
                int err = HtEcConnector.getAdapterName(tmpAdapterName, tmpAdapterDesc, i);
                if (err <= 0)              //有错误
                {
                    throw new Exception(); //一般来讲是这个错误
                }
                adapters[i]      = new Adapter();
                adapters[i].Name = tmpAdapterName.ToString();
                adapters[i].Desc = tmpAdapterDesc.ToString();
                tmpAdapterName.Clear();
                tmpAdapterDesc.Clear();
            }
            ConnectionContext.adapters = adapters;
            return(adapters);
        }
 public void InitAutoReadConfig()
 {
     callback = (slave, channel, value) =>
     {
         AutoDataChanged(null, new DataChangedEventArgs(slave, channel, value));
     };
     //binding callback.
     HtEcConnector.doWork(callback);
 }
        public void HighFreqRead(int deviceId, int channel, int freq, HighCallback call)
        {
            HighFreqReadCallback callback = (ans) =>
            {
                call(ans);
            };

            highCallbacks.Add(callback);
            HtEcConnector.HighFreqRead(deviceId, channel, freq, callback);
        }
        public bool ReadBoolean(int deviceId, int channel)
        {
            int tmpValue = HtEcConnector.getDigitalValue(deviceId, channel);

            if (tmpValue == 0)
            {
                return(false);
            }
            else if (tmpValue == 1)
            {
                return(true);
            }
            else
            {
                //throw new Exception("读取bool值错误,请检查:"+typeof(EtherCAT));
                return(false);
            }
        }
        // 建立连接状态,包括:初始化网卡,选择网卡,初始化从站
        private void BuildConnection()
        {
            if (isLoadedDriver)
            {
                return;
            }

            try
            {
                SetAdapter(ConnectionContext.adapterId);

                //this.GetDevice();
                ConnectionContext.deviceNum = HtEcConnector.initSlaveConfig();

                isLoadedDriver = true;
            }
            catch (Exception ex)
            {
                //log.Error(ex.Message + "\n" + ex.StackTrace);
            }
        }
 /// <summary>
 /// 主要作用是停止硬件运行,对于EtherCAT来说是恢复Init状态。
 /// </summary>
 /// <returns>应该返回操作结果</returns>
 public OperationResult Disconnect()
 {
     HtEcConnector.stopRunning();
     return(new OperationResult());
 }
 public int WriteBoolean(int deviceId, int channel, byte value)
 {
     return(HtEcConnector.setDigitalValue(deviceId, channel, value));
 }
 public int WriteAnalog(int deviceId, int channel, int value)
 {
     return(HtEcConnector.setAnalogValue(deviceId, channel, value));
 }
 public void StartAutoRead()
 {
     HtEcConnector.readStart();
 }
 public void HighFreqReadStop(int deviceId, int channelId)
 {
     HtEcConnector.HighFreqReadStop(deviceId, channelId);
     Thread.Sleep(1000); //等待回传最后一组数据
     //highCallbacks.Remove(XXX);highcallbacks应该作一个dictionary,以便通过键值获取并释放委托内存
 }
        /* 这里的两个函数表示我们的原生读函数,由于功能需要我们依旧保留这个方法,但是在更新数据缓冲池、
         * 控件显示等方面我们还是采用redis读取的方式。
         * Redis读取的好处也是明显的,无需依赖C#中极其不准确的Timer来触发读取,可以保证缓冲池中数据时
         * 钟保持最新;不足之处在于,由于控制逻辑依旧是在C#中实现,一些周期循环控制可能还是不尽如人意。
         * 值得一提的是,我们在编写控制逻辑的时候,可以绑定OnDataRefresh等事件,事件触发之时我们再执行
         * 对应的控制算法。
         */

        public int ReadAnalog(int deviceId, int channel)
        {
            int tmpValue = HtEcConnector.getAnalogValue(deviceId, channel);

            return(tmpValue);
        }
        /// <summary>
        /// 获取设备列表
        /// </summary>
        public List <List <IOdevice> > GetDevice()
        {
            BuildConnection();
            int slaveNum = ConnectionContext.deviceNum;

            List <List <IOdevice> > deviceContiner = new List <List <IOdevice> >(); //全部device
            List <IOdevice>         devGroup       = null;                          //一个device组
            IOdevice tmpDevice = null;

            for (int i = 1; i < slaveNum + 2; i++)
            {
                HtEcEntity    tmpSlave     = new HtEcEntity();
                StringBuilder tmpSlaveName = new StringBuilder();
                tmpSlaveName.Capacity = 128;

                int err = HtEcConnector.getSlaveInfo(tmpSlaveName, ref tmpSlave, i);

                if (tmpSlave.type == 10 || tmpSlave.type == 20) //耦合器或驱动器
                {
                    if (devGroup != null)
                    {
                        deviceContiner.Add(devGroup);
                    }
                    devGroup = new List <IOdevice>();
                }

                tmpDevice = new IOdevice(tmpSlave.id, DeviceType.NULL, tmpSlaveName.ToString(), tmpSlave.channelNum);
                //type
                switch (tmpSlave.type)
                {
                case 1:
                    tmpDevice.type = DeviceType.DI;
                    break;

                case 2:
                    tmpDevice.type = DeviceType.DO;
                    break;

                case 3:
                    tmpDevice.type = DeviceType.AI;
                    break;

                case 4:
                    tmpDevice.type = DeviceType.AO;
                    break;

                case 10:
                    tmpDevice.type = DeviceType.COUPLER;
                    break;

                case 20:
                    tmpDevice.type = DeviceType.SOLVER;
                    break;

                default:
                    break;
                }

                devGroup.Add(tmpDevice);
                tmpSlaveName.Clear();
            }
            deviceContiner.Add(devGroup);
            return(deviceContiner);
        }
 public int InitDevice()
 {
     return(HtEcConnector.initSlaveConfig());
 }