using ModuleTech;
using ModuleTech.Gen2;
using Newtonsoft.Json;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using static ModuleTech.IntegratedReader;
using static System.Collections.Specialized.BitVector32;
using static System.Windows.Forms.VisualStyles.VisualStyleElement;

namespace ControlSystem
{
    public class CRfidHelper
    {
        public static Reader rdr;
        public static List<string> tags = new List<string>();
        /// <summary>
        /// 初始化打开
        /// </summary>
        public static bool OpenReader()
        {
            if (rdr != null)
            {
                rdr.Disconnect();
                rdr = null;
            }

            /*
             * 当使用设备的串口进行连接的时候，Create函数的第一个参数也可能是串口号
             * （例如com1）当设备仅有一个天线端口时（例如一体机或者发卡器），Create
             * 函数的第三个参数也可能为1,读写器出厂默认IP为192.168.1.100 
             * */
            int antnum = 16;
            try
            {
                //rdr = Reader.Create(ReadUrl, ModuleTech.Region.PRC, antnum); //频段不同 根据现场情况切换
                rdr = Reader.Create("192.168.1.100", ModuleTech.Region.NA, antnum);
            }
            catch (Exception ex)
            {
                return false;
            }

            #region 必须要设置的参数

            #region 设置读写器的发射功率
            //获取读写器最大发射功率
            //int a= ()rdr.ParamGet("RfPowerMax");
            ushort maxp = Convert.ToUInt16(rdr.ParamGet("RfPowerMax"));// rdr.ParamGet("RfPowerMax");
            AntPower[] pwrs = new AntPower[antnum];
            for (int i = 0; i < antnum; ++i)
            {
                pwrs[i].AntId = (byte)(i + 1);//天线id
                pwrs[i].ReadPower = 3300;//天线频率
                pwrs[i].WritePower = maxp;
            }
            //设置读写器发射功率,本例设置为最大发射功率，可根据实际情况调整,
            //一般来说，功率越大则识别距离越远
            rdr.ParamSet("AntPowerConf", pwrs);
            #endregion

            #region 设置盘存标签使用的天线
            //如果要使用其它天线可以在数组useants中放置其它多个天线编号，本例中是使用天线1
            int[] useants = new int[] { 5 };
            //int[] useants = new int[] { 1, 2, 3, 4, 5, 6, 7, 8 };
            rdr.ParamSet("ReadPlan", new SimpleReadPlan(TagProtocol.GEN2, useants));
            #endregion

            #region 设置盘存操作的其它细节选项
            BackReadOption bro = new BackReadOption();
            BackReadOption.FastReadTagMetaData frtmdata = new BackReadOption.FastReadTagMetaData();
            /*是否采用高速模式（目前只有slr11xx和slr12xx系列读写器才支持）,对于
            *一般标签数量不大，速度不快的应用没有必要使用高速模式,本例没有设置
            *使用高速模式
            * */
            bro.IsFastRead = true;
            #region 选择使用高速模式才起作用的选项
            //参照如下设置即可,如果使能高速模式，则只需取消以下被注释的代码即可

            //标签信息是否携带识别天线的编号
            frtmdata.IsAntennaID = true;
            //标签信息是否携带标签识别次数
            frtmdata.IsReadCnt = false;
            //标签信息是否携带识别标签时的信号强度
            frtmdata.IsRSSI = false;
            //标签信息是否携带时间戳
            frtmdata.IsTimestamp = false;
            //标签信息是否携带识别标签时的工作频点
            frtmdata.IsFrequency = false;
            //标签信息是否携带识别标签时同时读取的其它bank数据信息,如果要获取在
            //盘存时同时读取其它bank的信息还必须设置EmbededCmdOfInventory参数,
            //（目前只有slr11xx和slr12xx系列读写器才支持）
            frtmdata.IsEmdData = false;
            //保留字段，可始终设置为false
            frtmdata.IsRFU = false;
            //高速模式下为取得最佳效果设置为0即可
            bro.FastReadDutyRation = 0;

            #endregion

            #region 非高速模式才起作用的选项
            /*
            //盘存周期,单位为ms，可根据实际使用的天线个数按照每个天线需要200ms
            //的方式计算得出,如果启用高速模式则此选项没有任何意义，可以设置为
            //任意值，或者干脆不设置
            bro.ReadDuration = (ushort)(200 * useants.Length);
            //盘存周期间的设备不工作时间,单位为ms,一般可设置为0，增加设备不工作
            //时间有利于节电和减少设备发热（针对某些使用电池供电或空间结构不利
            //于散热的情况会有帮助）
            bro.ReadInterval = 0;
            */
            #endregion

            bro.FRTMetadata = frtmdata;
            rdr.ParamSet("BackReadOption", bro);
            //SetParams();//启用普通快速模式 （需要先禁用EX10快速模式）
            //rdr.ParamSet("Ex10FastModeParams", null);//null 的情况下是不启用EX10 快速采集
            rdr.ParamSet("Ex10FastModeParams", new Ex10FastModeParams()); //这里是启用EX10 快速采集
            #endregion

            #endregion

            #region 必须要设置的事件处理函数
            //识别到标签事件的处理函数
            rdr.ReadException += OnReaderException;
            //读写器异常发生事件的处理函数
            rdr.TagsRead += OnTagsRead;
            #endregion

            #region 根据应用需求可能要设置的参数
            //
            #region 设置Gen2Session
            /*
            //标签数量比较大，且移动速度缓慢或静止不动,设置为Session1可取得更
            //好效果,反之标签数量较少移动速度较快应设置为Session0,读写器默认
            //为Session0
            rdr.ParamSet("Gen2Session", Session.Session1);
            */
            rdr.ParamSet("Gen2Session", Session.Session1);
            #endregion

            #endregion
            return true;
        }
        /// <summary>
        /// 启用普通快速模式 （需要先禁用EX10快速模式）
        /// </summary>
        public static void SetParams()
        {
            //rdr.ParamSet("Gen2Target", (ModuleTech.Gen2.Target)12);
            //rdr.ParamSet("Gen2Qvalue", 2);
            rdr.ParamSet("EmbededCmdOfInventory", null);
            rdr.ParamSet("AccessPassword", (uint)0);
            rdr.ParamSet("Gen2Session", (ModuleTech.Gen2.Session)0);
            //rdr.ParamSet("gen2tagEncoding", 111);
        }
        /// <summary>
        /// 读写器触发采集
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="tagsArgs"></param>
        static void  OnTagsRead(object sender, Reader.TagsReadEventArgs tagsArgs)
        {
            try
            {
                Reader rdrtmp = (Reader)sender;

                foreach (var item in tagsArgs.Tags)
                {
                    string barcode = item.EPCString.Replace(" ", "");
                    var tagInfo = tags.FirstOrDefault(t => t == barcode);

                    if (tagInfo == null)
                    {
                        tags.Add(barcode);
                        Console.WriteLine(barcode);
                    }
                }
            }
            catch (Exception ex)
            {

            }
        }
        /// <summary>
        /// 读写器异常发生事件的处理函数
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="expArgs"></param>
        static void OnReaderException(object sender, Reader.ReadExceptionEventArgs expArgs)
        {
            Reader rdrtmp = (Reader)sender;
            string aa = rdrtmp.Address + "--异常信息:" + expArgs.ReaderException.ToString();
            //如果需要可在此处记录异常日志
            Debug.WriteLine(aa);

            return;
        }
    }
}
