using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;
using System.Threading;
using System.IO;
using System.Windows.Forms;

namespace GateBrakeSdk
{
    public class GateBrake
    {
        public class ROADGATE_INFO_STRUCT
        {
            public String ip; //设备 IP 地址。
	        public bool isManual; //是否遥控开杆， true-是， false-否。
	        public int Counter;//计数器， 统计未过车辆数。
	        public int reserve1;//预留字段 1。
	        public int reserve2; //预留字段 2。
	        public String reserve3; //预留字段 3。
	        public String reserve4; //预留字段 4。
	        public String reserve5; //预留字段 5。

        }
        public class ROADGATE_NETCONFIG_STRUCT
        {
            public String deviceName;//设备名称。
	        public String srcIp; //设备原来的 IP 地址。
	        public String destIp;//设备需要设置的 IP 地址。
	        public int port;//端口号。
	        public String mac;//设备 MAC 地址。
	        public int reserve1; //预留字段 1。
	        public int reserve2;//预留字段 2。
	        public String gate;//网关。
	        public String mask;//子网掩码。
	        public String reserve5;//预留字段 5。

        }
        public delegate void OnDataArrivedEventHandler(ROADGATE_INFO_STRUCT info);
        public static event OnDataArrivedEventHandler OnDataArrivedEvent;
        public delegate void StateChangedEventHandler(String ip, bool state);
        public static event StateChangedEventHandler OnDeviceStateChangedEvent;

        /**
         * state闸状态 0 正在开闸 1 已经关闸 2 开完闸 3 中间停止状态
         * isPressed地感是否被压， true被压 false未被压
         * **/
        public delegate void DeviceMonitorEventHandler(String ip, int state, bool isPressed);
        public static event DeviceMonitorEventHandler OnDeviceMonitorEvent;

        public delegate void LogerEventHandler(String msg);
        public static event LogerEventHandler OnLogerEvent;

        public delegate void UpdateInfoEventHandler(String ip, String status, Dictionary<String,String> param);
        public static event UpdateInfoEventHandler OnUpdateInfoEvent;

       

        private static List<ConnectInfo> connectInfoList = new List<ConnectInfo>();

        private class ConnectInfo
        {
            public String ip;
            public int port;
            public String model;//产品型号
            public String hdver  = "1.0";//固件版本
            public String date;//生产日期
            public String sn;//序列号
            public String mac = null;
            public String gate = null;
            public String mask = null;
            public String userName;
            public String password;
            public TcpClient client;
            public String preorder = null;
        }
        private static ConnectInfo getConnectInfoByIp(String ip)
        {
            if (ip == null)
            {
                return null;
            }
            for (int i = 0; i < connectInfoList.Count; i++)
            {
                String srcip = connectInfoList[i].ip;
                if (srcip.Equals(ip))
                {
                    return connectInfoList[i];
                }
            }
            return null;
        }

        public static void RemoveAllDevices()
        {
            for (int i = 0; i < connectInfoList.Count; i++)
            {
                if (connectInfoList[i].client != null)
                {
                    try
                    {
                        connectInfoList[i].client.Client.Close();
                        connectInfoList[i].client.Close();
                        connectInfoList[i].client = null;
                    }
                    catch (Exception) { }
                }
            }
            connectInfoList.Clear();
        }

        public static bool Initialize(string ip, int port, string userName, string passWord)
        {
            if (ip == null)
            {
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info != null)
            {
                info.port = port;
                info.userName = userName;
                info.password = passWord;

                return true;
            }
            ConnectInfo newinfo = new ConnectInfo();
            newinfo.ip = ip;
            newinfo.port = port;
            newinfo.userName = userName;
            newinfo.password = passWord;
            connectInfoList.Add(newinfo);
            log("call Initialize ip:" + ip + " port:" + port);

            //MessageBox.Show(null, "测试版本,请使用正式版本，谢谢", "测试版本", MessageBoxButtons.OK, MessageBoxIcon.Warning);

            return true;
        }
        public static bool UnInitialize(string ip)
        {
            if (ip == null)
            {
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null)
            {
                return false;
            }
            TcpClient client = info.client;
            if (client != null)
            {
                client.Client.Close();
                client.Close();
                client = null;
            }
            connectInfoList.Remove(info);
            log("call UnInitialize ip:" + ip);
            return true;
        }
        public static bool Connect(string ip)
        {
            if (ip == null)
            {
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null || info.port == 0)
            {
                return false;
            }
            if (info.client != null)
            {
                return false;
            }
            info.client = new TcpClient();
            try
            {
                log("begin connect to " + ip + " port:" + info.port);
                info.client.Connect(IPAddress.Parse(ip), info.port);
                log("connect to " + ip + " success");
                ReadMac(ip);
                Thread.Sleep(100);
                GetDeviceInfo(ip);//连接闸道成功后，获取基本信息
                log("statechange true");
                if (OnDeviceStateChangedEvent != null)
                {
                    //设备在线了
                    OnDeviceStateChangedEvent(info.ip, true);
                }
                Thread t = new Thread(new ParameterizedThreadStart(run));
                t.Start(info);
                return true;
            }
            catch (Exception)
            {
                info.client = null;
            }
            return false;
        }
        private static void log(String msg)
        {
            if (OnLogerEvent != null)
            {
                OnLogerEvent("" + msg);
            }
        }
        private static void updateinfo(String ip, String status, Dictionary<String,String> param)
        {
            if (OnUpdateInfoEvent != null)
            {
                OnUpdateInfoEvent(ip, status, param);
            }
        }
        private static void dealcmd(ConnectInfo connectInfo, String ip, String data, byte[] bytes)
        {

            int orglen = 0;
            while (data.Length > 0 && bytes != null && bytes.Length > 0)
            {
                if (orglen == bytes.Length)
                {
                    break;
                }
                orglen = bytes.Length;

                if (data.StartsWith("BIP"))
                {
                    //修改网络返回
                    if (bytes.Length >= 15)
                    {
                        connectInfo.preorder = null;
                        //子网掩码
                        String mask = (int)bytes[3] + "." + (int)bytes[4] + "." + (int)bytes[5] + "." + (int)bytes[6];
                        //网关
                        String gate = (int)bytes[7] + "." + (int)bytes[8] + "." + (int)bytes[9] + "." + (int)bytes[10];
                        //String iplast = "" + (int)bytes[10];
                        //String fullip = (int)(bytes[2] & bytes[6]) + "." + (int)(bytes[3] & bytes[7]) + "." + (int)(bytes[4] & bytes[8]) + "." + (int)(bytes[5] | bytes[10]);
                        String fullip = (int)bytes[11] + "." + (int)bytes[12] + "." + (int)bytes[13] + "." + (int)bytes[14];
                        log("set ip mask:" + mask + "gate:" + gate + " IP:" + fullip);
                        Dictionary<String, String> param = new Dictionary<string, string>();
                        param.Add("mask", mask);
                        param.Add("gate", gate);
                        param.Add("ip", fullip);
                        updateinfo(ip, "IP", param);

                        byte[] tmp = new byte[bytes.Length - 11];
                        System.Array.Copy(bytes, 11, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);

                    }
                    else
                    {
                        connectInfo.preorder = "BIP";
                        byte[] tmp = new byte[bytes.Length - 3];
                        System.Array.Copy(bytes, 3, tmp, 0, tmp.Length);
                        bytes = tmp;
                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("RMAC"))
                {
                    if (bytes.Length >= 10)
                    {
                        connectInfo.preorder = null;
                        String mac = bytes[4].ToString("x2") + ":" + bytes[5].ToString("x2") + ":" + bytes[6].ToString("x2") + ":" + bytes[7].ToString("x2") + ":" + bytes[8].ToString("x2") + ":" + bytes[9].ToString("x2");
                        log("rmac " + mac + " datalen = " + bytes.Length);

                        ConnectInfo info = getConnectInfoByIp(ip);
                        if (info != null)
                        {
                            info.mac = mac;
                        }
                        Dictionary<String, String> param = new Dictionary<string, string>();
                        param.Add("mac", mac);
                        updateinfo(ip, "RMAC", param);

                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                    else
                    {
                        connectInfo.preorder = "RMAC";
                        byte[] tmp = new byte[bytes.Length - 4];
                        System.Array.Copy(bytes, 4, tmp, 0, tmp.Length);
                        bytes = tmp;
                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("SMAC"))
                {
                    if (bytes.Length >= 10)
                    {
                        connectInfo.preorder = null;
                        String mac = bytes[4].ToString("x2") + ":" + bytes[5].ToString("x2") + ":" + bytes[6].ToString("x2") + ":" + bytes[7].ToString("x2") + ":" + bytes[8].ToString("x2") + ":" + bytes[9].ToString("x2");
                        log("smac " + mac);

                        ConnectInfo info = getConnectInfoByIp(ip);
                        if (info != null)
                        {
                            info.mac = mac;
                        }
                        Dictionary<String, String> param = new Dictionary<string, string>();
                        param.Add("mac", mac);
                        updateinfo(ip, "SMAC", param);

                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                    else
                    {
                        connectInfo.preorder = "SMAC";
                        byte[] tmp = new byte[bytes.Length - 4];
                        System.Array.Copy(bytes, 4, tmp, 0, tmp.Length);
                        bytes = tmp;
                        data = Encoding.ASCII.GetString(bytes);
                    }

                }
                else if (data.StartsWith("locked"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("locked");
                        updateinfo(ip, "locked", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("lock"))
                {
                    if (bytes.Length >= 4)
                    {
                        log("lock");
                        updateinfo(ip, "lock", null);

                        byte[] tmp = new byte[bytes.Length - 4];
                        System.Array.Copy(bytes, 4, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("unlock"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("unlock");
                        updateinfo(ip, "unlock", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstLM_up1"))
                {
                    if (bytes.Length >= 9)
                    {
                        log("起到位地感被压cstLM_up1");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 2, true);
                        }
                        updateinfo(ip, "cstLM_up1", null);

                        byte[] tmp = new byte[bytes.Length - 9];
                        System.Array.Copy(bytes, 9, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstLM_up"))
                {
                    if (bytes.Length >= 8)
                    {
                        log("起到位地感没有被压cstLM_up");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 2, false);
                        }
                        updateinfo(ip, "cstLM_up", null);

                        byte[] tmp = new byte[bytes.Length - 8];
                        System.Array.Copy(bytes, 8, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstLM_down1"))
                {
                    if (bytes.Length >= 11)
                    {
                        log("落到位地感被压cstLM_down1");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 1, true);
                        }
                        updateinfo(ip, "cstLM_down1", null);
                        byte[] tmp = new byte[bytes.Length - 11];
                        System.Array.Copy(bytes, 11, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstLM_down"))
                {
                    if (bytes.Length >= 10)
                    {
                        log("落到位地感没有被压cstLM_down");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 1, false);
                        }
                        updateinfo(ip, "cstLM_down", null);
                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstOpening1"))
                {
                    if (bytes.Length >= 11)
                    {
                        log("开闸过程地感被压cstOpening1");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 0, true);
                        }
                        updateinfo(ip, "cstOpening1", null);

                        byte[] tmp = new byte[bytes.Length - 11];
                        System.Array.Copy(bytes, 11, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstOpening"))
                {
                    if (bytes.Length >= 10)
                    {
                        log("开闸过程地感没有被压cstOpening");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 0, false);
                        }
                        updateinfo(ip, "cstOpening", null);

                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstMD_stop1"))
                {
                    if (bytes.Length >= 11)
                    {
                        log("中间停止状态地感被压 文档定义的是cstMD_stop1");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 3, true);
                        }
                        updateinfo(ip, "cstMD_stop1", null);

                        byte[] tmp = new byte[bytes.Length - 11];
                        System.Array.Copy(bytes, 11, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstMD_stop"))
                {
                    if (bytes.Length >= 10)
                    {
                        log("中间停止状态地感没有被压");
                        if (OnDeviceMonitorEvent != null)
                        {
                            OnDeviceMonitorEvent(ip, 3, false);
                        }
                        updateinfo(ip, "cstMD_stop", null);

                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cstClosing"))
                {
                    if (bytes.Length >= 10)
                    {
                        log("关闸过程");
                        updateinfo(ip, "cstClosing", null);

                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("cst"))
                {
                    if (bytes.Length < 4)
                    {
                        connectInfo.preorder = "cst";
                        byte[] tmp = new byte[bytes.Length - 3];
                        System.Array.Copy(bytes, 3, tmp, 0, tmp.Length);
                        bytes = tmp;
                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("Small"))
                {
                    if (bytes.Length >= 5)
                    {
                        log("地感模块线圈电感量偏小");
                        updateinfo(ip, "Small", null);

                        byte[] tmp = new byte[bytes.Length - 5];
                        System.Array.Copy(bytes, 5, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("Large"))
                {
                    if (bytes.Length >= 5)
                    {
                        log("地感模块线圈电感量偏大");
                        updateinfo(ip, "Large", null);

                        byte[] tmp = new byte[bytes.Length - 5];
                        System.Array.Copy(bytes, 5, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("Disconnect"))
                {
                    if (bytes.Length >= 10)
                    {
                        log("地感模块线圈断开");
                        updateinfo(ip, "Disconnect", null);

                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("Not closed"))
                {
                    if (bytes.Length >= 10)
                    {
                        log("非关闸状态");
                        updateinfo(ip, "Not closed", null);

                        byte[] tmp = new byte[bytes.Length - 10];
                        System.Array.Copy(bytes, 10, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("Rconf"))
                {
                    if (bytes.Length >= 13)
                    {
                        connectInfo.preorder = null;
                        log("查询控制器功能和设置信息");
                        Dictionary<String, String> param = new Dictionary<string, string>();
                        param.Add("ip", ip);
                        param.Add("angle", "" + bytes[5]);
                        param.Add("autoclose", "" + bytes[6]);
                        param.Add("digangsign", "" + bytes[7]);
                        param.Add("yuzu", "" + bytes[8]);
                        param.Add("count", "" + bytes[9]);
                        param.Add("vangle", "" + bytes[10]);
                        param.Add("hangle", "" + bytes[11]);
                        param.Add("speed", "" + bytes[12]);
                        updateinfo(ip, "Rconf", param);

                        byte[] tmp = new byte[bytes.Length - 13];
                        System.Array.Copy(bytes, 13, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                    else
                    {
                        connectInfo.preorder = "Rconf";
                        byte[] tmp = new byte[bytes.Length - 5];
                        System.Array.Copy(bytes, 5, tmp, 0, tmp.Length);
                        bytes = tmp;
                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("Sconf"))
                {
                    if (bytes.Length >= 13)
                    {
                        connectInfo.preorder = null;
                        log("控制器功能和设置信息");
                        Dictionary<String, String> param = new Dictionary<string, string>();
                        param.Add("angle", "" + bytes[5]);
                        param.Add("autoclose", "" + bytes[6]);
                        param.Add("digangsign", "" + bytes[7]);
                        param.Add("yuzu", "" + bytes[8]);
                        param.Add("count", "" + bytes[9]);
                        param.Add("vangle", "" + bytes[10]);
                        param.Add("hangle", "" + bytes[11]);
                        param.Add("speed", "" + bytes[12]);
                        updateinfo(ip, "Sconf", param);

                        byte[] tmp = new byte[bytes.Length - 13];
                        System.Array.Copy(bytes, 13, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                    else
                    {
                        connectInfo.preorder = "Sconf";
                        byte[] tmp = new byte[bytes.Length - 5];
                        System.Array.Copy(bytes, 5, tmp, 0, tmp.Length);
                        bytes = tmp;
                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("Rsn"))
                {
                    if (bytes.Length >= 14)
                    {
                        connectInfo.preorder = null;

                        String model = data.Substring(3, 3);
                        String date = data.Substring(6, 4);
                        String sn = data.Substring(10, 4);
                        ConnectInfo info = getConnectInfoByIp(ip);
                        if (info != null)
                        {
                            info.model = model;
                            info.date = date;
                            info.sn = sn;
                        }
                        log("读道闸主板序列号 产品型号为" + model + " 生产日期为" + date + " 序列号为" + sn);
                        Dictionary<String, String> param = new Dictionary<string, string>();
                        param.Add("model", model);
                        param.Add("date", date);
                        param.Add("sn", sn);
                        updateinfo(ip, "Rsn", param);

                        byte[] tmp = new byte[bytes.Length - 14];
                        System.Array.Copy(bytes, 14, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                    else
                    {
                        connectInfo.preorder = "Rsn";
                        byte[] tmp = new byte[bytes.Length - 3];
                        System.Array.Copy(bytes, 3, tmp, 0, tmp.Length);
                        bytes = tmp;
                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("LM_up"))
                {
                    if (bytes.Length >= 5)
                    {
                        log("起杆到位状态");
                        if (OnDataArrivedEvent != null)
                        {
                            ROADGATE_INFO_STRUCT info = new ROADGATE_INFO_STRUCT();
                            info.Counter = 0;
                            info.isManual = false;
                            info.ip = ip;
                            OnDataArrivedEvent(info);
                        }
                        updateinfo(ip, "LM_up", null);

                        byte[] tmp = new byte[bytes.Length - 5];
                        System.Array.Copy(bytes, 5, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("LM_down"))
                {
                    if (bytes.Length >= 7)
                    {
                        log("落杆到位状态");
                        updateinfo(ip, "LM_down", null);
                        byte[] tmp = new byte[bytes.Length - 7];
                        System.Array.Copy(bytes, 7, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("MD_stop"))
                {
                    if (bytes.Length >= 7)
                    {
                        log("中间停止状态");
                        updateinfo(ip, "MD_stop", null);
                        byte[] tmp = new byte[bytes.Length - 7];
                        System.Array.Copy(bytes, 7, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("openXK"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("线控开闸");
                        updateinfo(ip, "openXK", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("openYK"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("遥控开闸");
                        updateinfo(ip, "openYK", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("openDG"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("地感防砸开闸");
                        updateinfo(ip, "openDG", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("openIR"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("红外对射防砸开闸");
                        updateinfo(ip, "openIR", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("closeDG"))
                {
                    if (bytes.Length >= 7)
                    {
                        log("车过地感自动关闸");
                        updateinfo(ip, "closeDG", null);

                        byte[] tmp = new byte[bytes.Length - 7];
                        System.Array.Copy(bytes, 7, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("closeXK"))
                {
                    if (bytes.Length >= 7)
                    {
                        log("线控关闸");
                        updateinfo(ip, "closeXK", null);

                        byte[] tmp = new byte[bytes.Length - 7];
                        System.Array.Copy(bytes, 7, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("closeYK"))
                {
                    if (bytes.Length >= 7)
                    {
                        log("遥控关闸");
                        updateinfo(ip, "closeYK", null);

                        byte[] tmp = new byte[bytes.Length - 7];
                        System.Array.Copy(bytes, 7, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("closeDL"))
                {
                    if (bytes.Length >= 7)
                    {
                        log("延时自动关闸");
                        updateinfo(ip, "closeDL", null);

                        byte[] tmp = new byte[bytes.Length - 7];
                        System.Array.Copy(bytes, 7, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("stopXK"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("线控停止");
                        updateinfo(ip, "stopXK", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("stopYK"))
                {
                    if (bytes.Length >= 6)
                    {
                        log("遥控停止");
                        updateinfo(ip, "stopYK", null);

                        byte[] tmp = new byte[bytes.Length - 6];
                        System.Array.Copy(bytes, 6, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }//命令前缀有重复，需要关注一下
                else if (data.StartsWith("open"))
                {
                    if (bytes.Length >= 4)
                    {
                        log("开闸回复");
                        updateinfo(ip, "open", null);

                        byte[] tmp = new byte[bytes.Length - 4];
                        System.Array.Copy(bytes, 4, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("close"))
                {
                    if (bytes.Length >= 5)
                    {
                        log("关闸回复");
                        updateinfo(ip, "close", null);

                        byte[] tmp = new byte[bytes.Length - 5];
                        System.Array.Copy(bytes, 5, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else if (data.StartsWith("stop"))
                {
                    if (bytes.Length >= 4)
                    {
                        log("停止回复");
                        updateinfo(ip, "stop", null);

                        byte[] tmp = new byte[bytes.Length - 4];
                        System.Array.Copy(bytes, 4, tmp, 0, tmp.Length);
                        bytes = tmp;

                        data = Encoding.ASCII.GetString(bytes);
                    }
                }
                else
                {
                    log("收到非法数据" + data);
                    //无效的指令
                    connectInfo.preorder = null;
                    break;
                }
            }
        }
        private static void ReceiveCallback(IAsyncResult ar)
        {
            try
            {
                StateObject state = ar.AsyncState as StateObject;
                ConnectInfo info = state.info;

                int length = info.client.Client.EndReceive(ar);

                if (length > 0)
                {
                    IPEndPoint ipendpoint = info.client.Client.RemoteEndPoint as IPEndPoint;

                    String data = "";
                    byte[] tmp = null;
                    
                    if (info.preorder != null)
                    {
                        data = info.preorder + Encoding.Default.GetString(state.bytes, 0, length);
                        byte[] head = Encoding.Default.GetBytes(info.preorder);
                        tmp = new byte[length + info.preorder.Length];
                        System.Array.Copy(head, 0, tmp, 0, head.Length);
                        System.Array.Copy(state.bytes, 0, tmp, head.Length, length);
                        info.preorder = null;
                    }
                    else
                    {
                        data = Encoding.Default.GetString(state.bytes, 0, length);
                        tmp = new byte[length];
                        System.Array.Copy(state.bytes, 0, tmp, 0, length);
                    }
                    
                    
                    String msg = String.Format("接收数据(from {0}:{1})：{2}", ipendpoint.Address, ipendpoint.Port, data);
                    log(msg);
                    dealcmd(info, ipendpoint.Address.ToString(), data, tmp);
                }
            }
            catch (Exception) { }
        }
        class StateObject
        {
            public ConnectInfo info;
            public byte[] bytes;
        }
        private static void run(object obj)
        {
            ConnectInfo info = obj as ConnectInfo;
            TcpClient tcpClient = info.client;

            IPEndPoint ipendpoint = tcpClient.Client.RemoteEndPoint as IPEndPoint;

            NetworkStream ns = tcpClient.GetStream();
           // ns.ReadTimeout = 5000;
            int wait = 0;
            while (info.client != null)
            {
                try
                {
                    if (ns.CanRead)
                    {
                        StateObject state = new StateObject();
                        state.info = info;
                        state.bytes = new byte[1024];


                        ns.BeginRead(state.bytes, 0, state.bytes.Length, new AsyncCallback(ReceiveCallback), state);

                        //30秒检测一次状态
                        if (wait++ < 300)
                        {
                            Thread.Sleep(100);
                        }
                        else
                        {
                            wait = 0;
                            GetDeviceInfo(info.ip);
                            /*String[] tmp = GetDeviceInfo(info.ip);
                            if (tmp == null)
                            {
                                info.client = null;
                                //通信异常了
                                if (OnDeviceStateChangedEvent != null)
                                {
                                    //设备断线了
                                    OnDeviceStateChangedEvent(info.ip, false);
                                }
                                break;
                            }
                             * */
                        }

                        /*
                        int length = ns.Read(bytes, 0, bytes.Length);
                        if (length > 0)
                        {
                            String data = Encoding.Default.GetString(bytes, 0, length);
                            byte[] tmp = new byte[length];
                            System.Array.Copy(bytes, 0, tmp, 0, length);
                            Console.WriteLine("{0:HH:mm:ss}->接收数据(from {1}:{2})：{3}", DateTime.Now, ipendpoint.Address, ipendpoint.Port, data);
                            dealcmd(ipendpoint.Address.ToString(), data, tmp);
                            //这里需要放入一个队列里，然后解析
                        }
                        else
                        {
                            continue;
                        }
                         * */
                    }
                    else
                    {
                        throw new Exception();
                    }
                    
                }
                catch (Exception)
                {
                    info.client = null;
                    //通信异常了
                    if (OnDeviceStateChangedEvent != null)
                    {
                        //设备断线了
                        OnDeviceStateChangedEvent(info.ip, false);
                    }
                }
            }
        }
        public static bool DisConnect(string ip)
        {
            if (ip == null)
            {
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null)
            {
                return false;
            }
            try
            {
                UnInitialize(ip);
                return true;
            }
            catch (Exception)
            {
                info.client = null;
            }
            return false;
        }
        /**
         * 
         * 
         * commond 0关闸 1开闸 2停止 3加锁 4解锁 5查询状态
         * */
        public static bool SendCommand(string ip, int command)
        {
            if (ip == null)
            {
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null)
            {
                return false;
            }
            if (info.client == null)
            {
                return false;
            }
            String str = "";
            if (command == 0)
            {
                str = "close";
            }
            else if (command == 1)
            {
                str = "open";
            }
            else if (command == 2)
            {
                str = "stop";
            }
            else if (command == 3)
            {
                str = "lock";
            }
            else if (command == 4)
            {
                str = "unlock";
            }
            else if (command == 5)
            {
                str = "cst";
            }
            if (str.Length == 0)
            {
                return false;
            }
            log("SendCommand " + str);
            byte[] datas = Encoding.ASCII.GetBytes(str);
            try
            {
                NetworkStream ns = info.client.GetStream();
                ns.Write(datas, 0, datas.Length);
                ns.Flush();
                return true;
            }
            catch (Exception)
            {
            }
            return false;
        }

        /**
         * 查看控制器功能，查询结果将通过事件OnUpdateInfoEvent返回,详细信息在param中传递
         * OnUpdateInfoEvent(ip,"Rconf", param)
         * param 中依次为 angle 起杆角度 autoclose 延时自动关闸 digangsign 地感信号消失延时关闸 yuzhu 遇阻 count 计数 vangle 垂直调整 hangle 水平调整 speed 起落速度
         * */
        public static bool QuerryController(String ip)
        {
            if (ip == null)
            {
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null)
            {
                return false;
            }
            if (info.client == null)
            {
                return false;
            }
            String str = "Rconf";
            byte[] datas = Encoding.ASCII.GetBytes(str);
            log("QuerryController");
            try
            {
                NetworkStream ns = info.client.GetStream();
                ns.Write(datas, 0, datas.Length);
                ns.Flush();
                return true;
            }
            catch (Exception)
            {
            }
            return false;
        }
        /**
         * 设置控制器功能 起杆角度 延时自动关闸 地感信号消失延时关闸 遇阻 计数 垂直调整 水平调整 起落速度
         * angle:取值只能为50 55 60 65 70 75 80 85 90
         * autoclose:0为关闭 3-60秒
         * digangsign:0为关闭1-30秒
         * yuzu:遇阻00为遇阻停止 01遇阻转起杆力度轻 02遇阻转起杆力度中
         * vangle:0-10
         * hangle:0-20
         * speed:    0: 3、6秒双速起慢落慢      1：3、6秒双速起快落慢      2：3、6秒双速起快落快 
         *          16：1、2秒双速起慢落慢     17：1、2秒双速起快落慢      18：1、2秒双速起快落快
         * */
        public static bool ConfigController(String ip, int angle, int autoclose, int digangsign,int yuzu,bool count, int vangle, int hangle,int speed)
        {
            if (ip == null)
            {
                return false;
            }
            if (angle != 50 && angle != 55 && angle != 60 && angle != 65 && angle != 70 && angle != 75 && angle != 80 && angle != 85 && angle != 90)
            {
                log("起杆角度不能为" + angle);
                return false;
            }
            if (!(autoclose == 0 || (autoclose >= 3 && autoclose <= 60)))
            {
                log("延时自动关闸 参数非法，只能为0或大于3并且小于60的整数");
                return false;
            }
            if (!(digangsign >= 0 && digangsign <= 30))
            {
                log("感信号消失延时关闸 参数非法，只能为大于等于0并且小于30的整数");
                return false;
            }
            if (yuzu != 0 && yuzu != 1 && yuzu != 2)
            {
                log("遇阻参数只能为0  1  2");
                return false;
            }
            if (!(vangle >= 0 && vangle <= 10))
            {
                log("垂直调整参数非法，只能为0-10之间");
                return false;
            }
            if (!(hangle >= 0 && hangle <= 20))
            {
                log("水平调整参数非法，只能为0-20之间");
                return false;
            }
            if (speed != 0 && speed != 1 && speed != 2 && speed != 16 && speed != 17 && speed != 18)
            {
                log("起落速度参数非法，只能为 0: 3、6秒双速起慢落慢      1：3、6秒双速起快落慢      2：3、6秒双速起快落快 16：1、2秒双速起慢落慢     17：1、2秒双速起快落慢      18：1、2秒双速起快落快");
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null)
            {
                return false;
            }
            if (info.client == null)
            {
                return false;
            }
            byte[] datas = new byte[13];
            datas[0] = 0x53;
            datas[1] = 0x63;
            datas[2] = 0x6f;
            datas[3] = 0x6e;
            datas[4] = 0x66;
            datas[5] = (byte)angle;
            datas[6] = (byte)autoclose;
            datas[7] = (byte)digangsign;
            datas[8] = (byte)yuzu;
            datas[9] = (byte)(count ? 0x01 : 0x00);
            datas[10] = (byte)vangle;
            datas[11] = (byte)hangle;
            datas[12] = (byte)speed;

            try
            {
                NetworkStream ns = info.client.GetStream();
                ns.Write(datas, 0, datas.Length);
                ns.Flush();
                return true;
            }
            catch (Exception)
            {
            }
            return false;
        }

        public static String[] GetDeviceInfo(String ip)
        {
            if (ip == null)
            {
                return null;
            }
            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null)
            {
                return null;
            }
            if (info.client == null)
            {
                return null;
            }
            String[] ret = new String[12];

            String str = "Rsn";
            byte[] datas = Encoding.ASCII.GetBytes(str);
            log("GetDeviceInfo");
            try
            {
                NetworkStream ns = info.client.GetStream();
                ns.Write(datas, 0, datas.Length);
                ns.Flush();
                //取缓存或者等待返回数据

                
                ret[0] = info.model;
                ret[1] = info.hdver;
                ret[2] = info.mac;
                ret[10] = info.date;
                ret[11] = info.sn;
     
                return ret;
            }
            catch (Exception)
            {
                return null;
            }
            return ret;
        }


        public static bool SetDeviceInfo(ROADGATE_NETCONFIG_STRUCT param)
        {
            if (param == null || param.srcIp == null)
            {
                return false;
            }
            ConnectInfo info = getConnectInfoByIp(param.srcIp);
            if (info == null)
            {
                return false;
            }
            if (info.client == null)
            {
                return false;
            }
            if (param.destIp != null && !param.srcIp.Equals(param.destIp))
            {
                //需要设置ip
                byte[] datas = new byte[15];
                datas[0] = 0x42;
                datas[1] = 0x49;
                datas[2] = 0x50;
                //子网掩码定死为255.255.255.0先
                if (param.mask != null)
                {
                    byte[] bytes = IpString2Bytes(param.mask);
                    datas[3] = bytes[0];
                    datas[4] = bytes[1];
                    datas[5] = bytes[2];
                    datas[6] = bytes[3];
                }
                else
                {
                    //若未传值，直接赋为255.255.255.0
                    datas[3] = 0xff;
                    datas[4] = 0xff;
                    datas[5] = 0xff;
                    datas[6] = 0x00;
                }
                //根据destIp计算出网关
                if (param.gate != null)
                {
                    byte[] bytes = IpString2Bytes(param.gate);
                    datas[7] = bytes[0];
                    datas[8] = bytes[1];
                    datas[9] = bytes[2];
                    datas[10] = bytes[3];
                    //bytes = IpString2Bytes(param.destIp);
                    // datas[10] = bytes[3];
                }
                else
                {
                    byte[] bytes = IpString2Bytes(param.destIp);
                    datas[7] = bytes[0];
                    datas[8] = bytes[1];
                    datas[9] = bytes[2];
                    datas[10] = 1; //强制设置为1

                    // datas[10] = bytes[3];
                }
                {
                    byte[]  bytes = IpString2Bytes(param.destIp);
                    datas[11] = bytes[0];
                    datas[12] = bytes[1];
                    datas[13] = bytes[2];
                    datas[14] = bytes[3];
                }

                log("set ip");

                try
                {
                    NetworkStream ns = info.client.GetStream();
                    ns.Write(datas, 0, datas.Length);
                    ns.Flush();
                }
                catch (Exception)
                {
                    return false;
                }
            }
            if (param.mac != null && !param.mac.Equals(info.mac))
            {

                if (param.destIp != null && !param.srcIp.Equals(param.destIp))
                {
                    Thread.Sleep(100);
                }
                //需要修改mac
                byte[] datas = new byte[10];
                datas[0] = 0x53;
                datas[1] = 0x4d;
                datas[2] = 0x41;
                datas[3] = 0x43;

                byte[] macbytes = MacStrign2Bytes(param.mac);
                datas[4] = macbytes[0];
                datas[5] = macbytes[1];
                datas[6] = macbytes[2];
                datas[7] = macbytes[3];
                datas[8] = macbytes[4];
                datas[9] = macbytes[5];
                log("set mac");
                try
                {
                    NetworkStream ns = info.client.GetStream();
                    ns.Write(datas, 0, datas.Length);
                    ns.Flush();
                }
                catch (Exception)
                {
                    return false;
                }
            }
          

            return true;
        }

        private static bool ReadMac(String ip)
        {
            byte[] datas = new byte[4];
            datas[0] = 0x52;
            datas[1] = 0x4d;
            datas[2] = 0x41;
            datas[3] = 0x43;

            ConnectInfo info = getConnectInfoByIp(ip);
            if (info == null)
            {
                return false;
            }
            if (info.client == null)
            {
                return false;
            }

            try
            {
                NetworkStream ns = info.client.GetStream();
                ns.Write(datas, 0, datas.Length);
                ns.Flush();
            }
            catch (Exception)
            {
                return false;
            }

            return true;
        }

        private static byte[] MacStrign2Bytes(String mac)
        {
            byte[] ret = new byte[6];
            String[] items = mac.Split(':');
            if (items.Length != 6)
            {
                return ret;
            }
            for (int i = 0; i < items.Length; i++)
            {
                String str = items[i];
                try
                {
                    byte b = Byte.Parse(str, System.Globalization.NumberStyles.HexNumber);
                    ret[i] = b;
                }
                catch (Exception) { }

            }
            return ret;
        }
        private static byte[] IpString2Bytes(String ip)
        {
            byte[] ret = new byte[4];
            String[] items = ip.Split('.');
            if (items.Length != 4)
            {
                return ret;
            }
            for (int i = 0; i < items.Length; i++)
            {
                String str = items[i];
                try
                {
                    byte b = Byte.Parse(str);
                    ret[i] = b;
                }
                catch (Exception) { }

            }
            return ret;
        }
    }
}
