NiRenIO.cs 9.3 KB
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using TSA_V.DeviceLibrary;

class NiRenIO: IOBase
{
    byte station = 1;
    public string IP;
    TcpClient tcpClient = new TcpClient();
    Thread iomonitorThread;
    ushort seq = 0;
    /// <summary>
    /// 
    /// </summary>
    /// <param name="changindex">变化的io列表</param>
    /// <param name="sta">所有IO状态</param>
    public delegate void IO_Changed(List<int> changindex, bool[] sta);
    public event IO_Changed DI_Changed_Event;
    public event IO_Changed DO_Changed_Event;
    /// <summary>
    /// 连接状态变化, 手动连接不触发
    /// </summary>
    public event EventHandler<bool> ConnectionState_Event;
    public NiRenIO()
    {
        //this.IP = ip;

        //DOdata[0] = 0x00;
        //DOdata[1] = 0x00;
        iomonitorThread = new Thread(new ThreadStart(iomonitor));
    }
    ~NiRenIO()
    {
        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, 12345);
                if (connectResult.Wait(1000))
                {
                    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;
            }
        }

    }
    /// <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;
    }

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

    /// <summary>
    /// 写io
    /// </summary>
    /// <param name="donum">地址</param>
    /// <param name="state">On/Off</param>
    /// <returns></returns>
    public bool WriteDO(int donum, bool state)
    {

        const string CMD_WriteDI = "AT+OCCH{0}={1}\r\n";

        var CMDSEND = string.Format(CMD_WriteDI, donum + 1, state ? "1": "0");
        var sendbyte = Encoding.ASCII.GetBytes(CMDSEND);
        lock (tcpClient)
        {
            try
            {
                tcpClient.Client.Send(sendbyte);
                Thread.Sleep(1);
                byte[] result = new byte[100];
                var ulength = tcpClient.Client.Receive(result);
                if (ulength > 0) {
                    var recive = Encoding.ASCII.GetString(result, 0, ulength);
                    if (recive.StartsWith("OK"))
                        return true;
                }

            }
            catch
            {
                return false;
            }
        }


        return false;
    }
    /// <summary>
    /// 所有DI状态
    /// </summary>
    public bool[] DIstate = new bool[64];
    /// <summary>
    /// 所有DO状态
    /// </summary>
    public bool[] DOstate = new bool[64];
    bool[] lastDIstate = new bool[64];
    bool[] lastDOstate = new bool[64];
    /// <summary>
    /// 读全部IO
    /// </summary>
    void ReadDO()
    {

        const string CMD_ReadDI = "AT+OCCH0=?\r\n";
        const string CMD_ReadD0 = "AT+STACH0=?\r\n";
        const string CMD_ReadALL = CMD_ReadDI + CMD_ReadD0;

        var sendbyte = Encoding.ASCII.GetBytes(CMD_ReadALL);
        var resultbuffer = new byte[2048];
        int ulength = 0;
        lock (tcpClient)
        {
            try
            {
                tcpClient.Client.Send(sendbyte);
                Thread.Sleep(1);
                ulength = tcpClient.Client.Receive(resultbuffer);

            }
            catch (SocketException se)
            {
                throw se;
            }
        }
        if (ulength == 0) {
            return;        
        }

        var recive = Encoding.ASCII.GetString(resultbuffer, 0, ulength);

        var datas = recive.Split(new char[] { '\r', '\n' });
        /*
            +STACH1:0,100000
            +STACH2:0,100000
            +OCCH1:0
            +OCCH2:0
         */
        foreach (var data in datas) {
            if (!data.StartsWith("+"))
                continue;

            if (data.StartsWith("+STACH"))
            {
                var ds = data.Split(':');
                var d = ds[0].Substring(6);
                if (!int.TryParse(d, out int doindex))
                    continue;
                doindex = doindex - 1;
                var sta = ds[1].StartsWith("1") ? true : false;
                DOstate[doindex] = sta;
            }
            else if (data.StartsWith("+OCCH"))
            {
                var ds = data.Split(':');
                var d = ds[0].Substring(5);
                if (!int.TryParse(d, out int doindex))
                    continue;
                doindex = doindex - 1;
                var sta = ds[1].StartsWith("1") ? true : false;
                DIstate[doindex] = sta;
            }

        }

        for (int i = 0; i < 64; i++)
        {
            List<int> dichgindex = new List<int>();
            List<int> dochgindex = new List<int>();
            if (lastDIstate[i] != DIstate[i])
            {
                dichgindex.Add(i);
                lastDIstate[i] = DIstate[i];
            }
            if (lastDOstate[i] != DOstate[i])
            {
                dochgindex.Add(i);
                lastDOstate[i] = DOstate[i];
            }
            if (dichgindex.Count > 0)
                DI_Changed_Event?.BeginInvoke(dichgindex, DIstate, null, null);
            if (dochgindex.Count > 0)
                DO_Changed_Event?.BeginInvoke(dochgindex, DOstate, null, null);
        }

    }

    void seqadd()
    {
        seq++;
        if (seq >= ushort.MaxValue - 10)
            seq = 0;
    }

    public override void ConnectionKND(List<string> dIODeviceNameList)
    {
    }

    public override void ReadAllDI(string deviceName, byte slaveId)
    {
        ReadDO();
    }

    public override void ReadAllDO(string deviceName, byte slaveId)
    {
        ReadDO();
    }

    public override void ConnectionIP(string kNDIP, ushort kNDPort)
    {
        this.IP = kNDIP;
        Open();
        //iomonitorThread = new Thread(new ThreadStart(iomonitor));
    }

    public override void WriteSingleDO(string deviceName, byte slaveId, ushort index, IO_VALUE value, int time)
    {
        WriteDO(index, value == IO_VALUE.HIGH);
    }

    public override bool IsConnection(string kNDIP)
    {
        return IsConn;
    }

    public override void WriteSingleDO(string deviceName, byte slaveId, ushort index, IO_VALUE value)
    {
        WriteDO(index, value == IO_VALUE.HIGH);
    }

    public override IO_VALUE GetDIValue(string deviceName, byte slaveID, ushort v)
    {
        if (v < DIstate.Length)
            return DIstate[v] ? IO_VALUE.HIGH : IO_VALUE.LOW;
        else
            return IO_VALUE.LOW;
    }

    public override IO_VALUE GetDOValue(string deviceName, byte slaveID, ushort v)
    {
        if (v < DOstate.Length)
            return DOstate[v] ? IO_VALUE.HIGH : IO_VALUE.LOW;
        else
            return IO_VALUE.LOW;
    }

    public override IO_VALUE GetIOValue(ConfigIO configIO)
    {
        if (configIO.ProType.Equals(ConfigItemType.DI))
        {
            if (configIO.IOIndex< DIstate.Length)
                return DIstate[configIO.IOIndex] ? IO_VALUE.HIGH : IO_VALUE.LOW;
            else
                return IO_VALUE.LOW;
        }
        else
        {
            if (configIO.IOIndex < DOstate.Length)
                return DOstate[configIO.IOIndex] ? IO_VALUE.HIGH : IO_VALUE.LOW;
            else
                return IO_VALUE.LOW;
        }


    }

    public override void CloseAllDO()
    {
        for (int i = 0; i < 32; i++)
        {
            WriteDO(i, false);
        }
    }

    public override void CloseAllConnection()
    {
        Close();
    }
}