PuYueRFID_C2S.cs 9.4 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

public class PuYueRFID_C2S
{
    byte station = 1;
    public string IP;
    TcpClient tcpClient = new TcpClient();
    Thread iomonitorThread;
    ushort seq = 0;

    public event EventHandler<string> ID_Changed_Event;
    /// <summary>
    /// 连接状态变化, 手动连接不触发
    /// </summary>
    public event EventHandler<bool> ConnectionState_Event;
    public PuYueRFID_C2S(string ip)
    {
        this.IP = ip;

        //DOdata[0] = 0x00;
        //DOdata[1] = 0x00;
        iomonitorThread = new Thread(new ThreadStart(iomonitor));
    }
    ~PuYueRFID_C2S()
    {
        iomonitorrun = false;
        Close();
    }
    bool systemrun = false;
    /// <summary>
    /// 打开IO
    /// </summary>
    /// <returns></returns>
    public bool Open()
    {

        tcpClient.Dispose();
        tcpClient = new TcpClient();
        tcpClient.ReceiveTimeout = 50;
        tcpClient.SendTimeout = 50;
        lock (tcpClient)
        {
            try
            {
                var connectResult = tcpClient.ConnectAsync(IP, 502);
                if (connectResult.Wait(1000))
                {
                    Init();
                    systemrun = true;
                    iomonitorrun = true;
                    iomonitorThread = new Thread(new ThreadStart(iomonitor));
                    iomonitorThread.Start();
                    ConnectionState_Event?.Invoke(this, true);
                    return true;
                }
                else
                {

                    tcpClient.EndConnect(connectResult);
                    tcpClient.Close();
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }

    }

    void Init()
    {
        //0设备地址,1波特率,2蜂鸣器状态,4天线盘存次数,6工作模式,7操作标签模式,8盘存标签超时时间,9自动触发间隔时间,10配置自动输出格式,11ASCII数据帧帧头,12标签记录保存时间
        short[] value = new short[] { 1, 2, 1, 0, 1, 0, 1, 2, 20, 20, 0x81, 0x1234, 20 };
        //设备地址1,波特率,禁止AFI,盘点超时时间(100*5ms),命令触发,操作模式,寄存器地址,寄存器数量,触发时间(10*5ms),输出格式,数据帧枕头,记录保持时间(9*5ms)
        short[] address = new short[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12};
        //short[] value = new short[] { 1, 2, 0, 100, 1, 1, 0x20, 4, 20, 1, 0x1234, 19 };
        for (int i = 0; i < address.Length; i++)
        {
            WriteDO(address[i], value[i]);
        }
    }
    /// <summary>
    /// 设置天线功率dBm
    /// </summary>
    public short AntennaPower
    {
        set{
            if (this.IsConn)
                WriteDO(0x0100, value);
        }
    }
    /// <summary>
    /// 关闭IO
    /// </summary>
    public void Close()
    {
        try
        {
            systemrun = false;
            iomonitorrun = false;
            if (tcpClient.Connected)
                tcpClient.Close();
        }
        catch { }
    }
    /// <summary>
    /// 连接状态
    /// </summary>
    public bool IsConn
    {
        get => iomonitorrun && systemrun && tcpClient.Connected;
    }

    bool iomonitorrun = false;
    /// <summary>
    /// 循环读全部IO
    /// </summary>
    void iomonitor()
    {
        iomonitorrun = true;
        while (iomonitorrun && systemrun)
        {
            
            try
            {
                if (ConnectionState_Event != null)
                    ReadDO();
                else
                    Thread.Sleep(1000);
            }
            catch (SocketException)
            {
                if (tcpClient.Connected)
                    tcpClient.Close();
                ConnectionState_Event?.Invoke(this, false);
                iomonitorrun = false;
            }
        }
        if (systemrun)
        {
            do
            {
                Thread.Sleep(1000);
            } while (systemrun && !Open());
        }
    }

    /// <summary>
    /// 写寄存器
    /// </summary>
    /// <param name="address"></param>
    /// <param name="value"></param>
    /// <returns></returns>
    public bool WriteDO(short address, short value)
    {
        byte funCode = 0x10;
        byte[] startAddress = BitConverter.GetBytes(address);  //寄存器起始地址;
        byte[] data = BitConverter.GetBytes(value);  //寄存器起始地址;
        byte startLength = 1;
        var seqhead = BitConverter.GetBytes(seq);
        byte[] by = new byte[]
        {
                //事物标识符
                seqhead[0],
                seqhead[1],
                //协议标识符 固定值
                0x00,
                0x00,
                //长度
                0x00,
                0x06,
                //从站地址
                station,
                //功能码
                funCode,
                startAddress[1],//起始地址高位
                startAddress[0], //起始地址低位
                0x00,
                startLength, //读个数
                0x02,
                data[1],
                data[0]
        };
        by[5] = (byte)(by.Length - 6);
        bool check = true;
        lock (tcpClient)
        {
            try
            {
                seqadd();
                tcpClient.Client.Send(by);
                byte[] result = new byte[100];
                var ulength = tcpClient.Client.Receive(result);
                var newResult = result.ToList().Take(ulength).ToArray();
                if (newResult[0] == seqhead[0] && newResult[1] == seqhead[1])
                {
                    check = true;
                }
                else
                {
                    return false;
                }
            }
            catch
            {
                return false;
            }
        }


        /*
        var newResult = result.ToList().Take(ulength).ToArray();
        //输出报文
        var output = string.Join(" ", newResult.Select(x => x.ToString("X2")));

        */
        return check;
    }

    string currentID = "";
    bool hasID = false;
    DateTime currentIDdate = DateTime.MinValue;
    string lastID = "";
    /// <summary>
    /// 读全部IO
    /// </summary>
    void ReadDO()
    {
        byte funCode = 0x03;//批量写圈
        byte[] startAddress = BitConverter.GetBytes((short)0x0255);
        byte startLength = 2;
        var seqhead = BitConverter.GetBytes(seq);
        byte[] by = new byte[]
        {
                //事物标识符
                seqhead[0],
                seqhead[1],
                //协议标识符 固定值
                0x00,
                0x00,
                //长度
                0x00,
                0x06,
                //从站地址
                station,
                //功能码
                funCode,
                startAddress[1],
                startAddress[0], //起始地址
                0x00,
                startLength, //读个数
        };
        by[5] = (byte)(by.Length - 6);
        byte[] result = new byte[100];
        int ulength = 0;

        lock (tcpClient)
        {
            try
            {
                seqadd();
                tcpClient.Client.Send(by);
                Thread.Sleep(5);
                ulength = tcpClient.Client.Receive(result);

            }
            catch (SocketException se)
            {
                throw se;
            }
            finally {
                Thread.Sleep(20);
            }
        }
        var newResult = result;//.ToList().Take(ulength).ToArray();
                               //aa = BitConverter.ToString(newResult);
                               //Console.WriteLine(aa);
        if (newResult[0] == seqhead[0] && newResult[1] == seqhead[1])
        {
            if (newResult[7] == 0x03)
            {
                hasID = true;
                currentID = (char)newResult[10] + newResult[11].ToString();
                currentIDdate = DateTime.Now;
                if (currentID != lastID)
                {
                    ID_Changed_Event?.Invoke(this, currentID);
                    lastID = currentID;
                }
            }else if (newResult[7] == 0x83)
            {
                hasID = false;
            }
        }
        else
        {
            Thread.Sleep(20);
            if (tcpClient.Client.Available>0)
                _ = tcpClient.Client.Receive(result);
            
        }
        //输出报文
        //var output = string.Join(" ", newResult.Select(x => x.ToString("X2")));

    }
    /// <summary>
    /// 读取rfid 
    /// </summary>
    /// <param name="id">读取到的id</param>
    /// <param name="ms">最后读到的时间ms</param>
    /// <returns>读取成功状态-1读取失败,0没有读到,1读取成功</returns>
    public int TryRead(out string id,out double ms) {
        id = "";
        ms = 0;
        try
        {
            ReadDO();
            id = lastID;
            ms = (DateTime.Now - currentIDdate).TotalMilliseconds;
            if (hasID)
                return 1;
            else
                return 0;
        }
        catch
        {
            return -1;
        }
    }
    void seqadd()
    {
        seq++;
        if (seq >= ushort.MaxValue - 10)
            seq = 0;
    }
}