Newer
Older
SensorHub-NoiseCorr / SensorHub.Servers / Common.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using SensorHub.Servers.Commands.CASICCommands;
using SensorHub.Utility;
using Newtonsoft.Json;
using SensorHub.Servers.JsonFormat;
using SuperSocket.SocketBase.Protocol;
using SensorHub.Config;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Configuration;
using Microsoft.Win32;
using System.Threading;
using SensorHub.Servers.SM4;
using Newtonsoft.Json.Linq;
using AepSdk.Apis;

namespace SensorHub.Servers
{
    public static class Common
    {
        public static Dictionary<String, String> concentratorWithSessionIdMap = new Dictionary<String, String>();

        public static Dictionary<String, int> concentratorWithHeartbeatMap = new Dictionary<String, int>();

        public static String getOpeTypeByPdu(String pduType)
        {
            Int16 btpduType = Int16.Parse(pduType, System.Globalization.NumberStyles.HexNumber);

            int opearType = (btpduType >> 8) & 0xFF;
            String result = "";
            switch (opearType)
            {
                case 1:
                    result = "GetRequest";
                    break;
                case 2:
                    result = "GetResponse";
                    break;
                case 3:
                    result = "SetRequest";
                    break;
                case 4:
                    result = "TrapRequest";
                    break;
                case 5:
                    result = "TrapResponse";
                    break;
                case 6:
                    result = "OnlineRequest";
                    break;
                case 7:
                    result = "OnlineResponse";
                    break;
                case 8:
                    result = "StartupRequest";
                    break;
                case 9:
                    result = "StartupResponse";
                    break;
                case 10:
                    result = "WakeupRequest";
                    break;
                case 11:
                    result = "WakeupResponse";
                    break;
                case 13:
                    result = "ClientRequest";
                    break;
                case 12:
                    result = "SetResponse";
                    break;
                default:
                    result = "undefined";
                    break;
            }
            return result;
        }

        public static String getDeviceTypeByPdu(String pduType)
        {
            Int16 btpduType = Int16.Parse(pduType, System.Globalization.NumberStyles.HexNumber);
            int deviceType = btpduType & 0x7F;

            String devType = System.Configuration.ConfigurationManager.AppSettings["devType" + deviceType];

            return devType;
        }

        public static void senderGPRSConfig(CasicSession session, string devCode, byte[] btPdu, string source)
        {
            sendGPRSConfig(session, devCode, btPdu, source, "TEA");
        }

        public static void senderSM4Config(CasicSession session, string devCode, byte[] btPdu, string source)
        {
            sendGPRSConfig(session, devCode, btPdu, source, "SM4");
        }

        public static byte[] BuildConfigBytes(string devCode)
        {
            RedisHelper redis = new RedisHelper(0);

            string configItem = null;
            if (redis.Conn != null)
            {
                configItem = redis.StringGet(devCode);
            }

            return ConfigBuild.getConfigTag(configItem);
        }

        public static void sendGPRSConfig(CasicSession session, string devCode, byte[] btPdu, string source, string mode)
        {
            RedisHelper redis = new RedisHelper(0);

            String configItem = null;
            if (redis.Conn != null)
            {
                configItem = redis.StringGet(devCode);
            }

            session.Logger.Info("收到Redis中的待下发配置:" + configItem);

            byte[] config = ConfigBuild.buildConfigFrame(devCode, configItem);
            config[10] = 0x03;
            config[13] = btPdu[0];
            config[14] = btPdu[1];
            if (mode == "SM4")
            {
                config[10] = 0xC3;
            }

            SystemTimeConfig sysTimeConfig = new SystemTimeConfig(null);
            byte[] btConfig = sysTimeConfig.getConfig(new byte[0]);
            btConfig.CopyTo(config, 16);

            session.Logger.Info("下发回复配置信息:" + BitConverter.ToString(config).Replace("-", ""));

            if (source == "4G")
            {
                session.Send(CRC(config), 0, config.Length + 2);
                return;
            }


            byte[] tag = new byte[config.Length - 16];
            byte[] enTag;

            Array.Copy(config, 16, tag, 0, config.Length - 16);

            if (mode == "TEA")
            {
                int a = tag.Length % 8;
                if (a != 0)
                {
                    enTag = new byte[tag.Length + 8 - a];
                    tag.CopyTo(enTag, 0);
                    for (int i = 0; i < 8 - a; i++)
                    {
                        enTag[tag.Length + i] = 0;
                    }
                }
                else
                {
                    enTag = new byte[tag.Length];
                    tag.CopyTo(enTag, 0);
                }

                TEA.encrypt(ref enTag, enTag.Length);
            }
            else
            {
                enTag = SM4Utils.sm4Encrypt(tag, devCode);//"77656E7169616E674149797565797565"
            }

            byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length];
            Array.Copy(config, result, 16);
            enTag.CopyTo(result, 16);

            byte[] afcrc = CRC(result);

            //TODO:发送数据
            if (source == "OTHER")
            {
                session.Send(afcrc, 0, afcrc.Length);
            }
            else
            {
                String strBase64Value = Convert.ToBase64String(afcrc);
                int ret = SendAEPCommand(session, strBase64Value, source);
                if (ret != 0)
                {
                    session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret);
                }
                else
                {
                    session.Logger.Info("电信平台下发配置信息成功!");
                }
            }
        }

        public static void senderNBConfig(CasicSession session, string devCode, byte[] btPdu, string source)
        {
            byte[] config = ConfigBuild.buildConfigFrame(devCode, null);
            config[10] = 0x03;
            config[13] = btPdu[0];
            config[14] = btPdu[1];

            SystemTimeConfig sysTimeConfig = new SystemTimeConfig(null);
            byte[] btConfig = sysTimeConfig.getConfig(new byte[0]);
            btConfig.CopyTo(config, 16);

            session.Logger.Info("下发回复配置信息:" + BitConverter.ToString(config).Replace("-", ""));


            byte[] tag = new byte[config.Length - 16];
            byte[] enTag;

            Array.Copy(config, 16, tag, 0, config.Length - 16);

            int a = tag.Length % 8;
            if (a != 0)
            {
                enTag = new byte[tag.Length + 8 - a];
                tag.CopyTo(enTag, 0);
                for (int i = 0; i < 8 - a; i++)
                {
                    enTag[tag.Length + i] = 0;
                }
            }
            else
            {
                enTag = new byte[tag.Length];
                tag.CopyTo(enTag, 0);
            }

            TEA.encrypt(ref enTag, enTag.Length);

            byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length];
            Array.Copy(config, result, 16);
            enTag.CopyTo(result, 16);

            byte[] afcrc = CRC(result);
            //session.Send(afcrc, 0, afcrc.Length);

            String strBase64Value = Convert.ToBase64String(afcrc);
            int ret = SendNACommand(session, strBase64Value, source);
            if (ret != 201)
            {
                session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret);
            }
            else
            {
                session.Logger.Info("电信平台下发配置信息成功!");
            }
        }


        public static byte[] CRC(byte[] befcrc)
        {
            //增加CRC校验
            String strCrc = StringUtil.To16HexString(String.Format("{0:X}", (int)CodeUtils.CRC16_AD(befcrc)));
            byte[] btcrc = { CodeUtils.String2Byte(strCrc.Substring(0, 2)), CodeUtils.String2Byte(strCrc.Substring(2, 2)) };
            byte[] afcrc = new byte[befcrc.Length + 2];
            befcrc.CopyTo(afcrc, 0);
            btcrc.CopyTo(afcrc, befcrc.Length);
            return afcrc;
        }

        public static byte[] getCRC(byte[] befcrc)
        {
            //增加CRC校验
            String strCrc = StringUtil.To16HexString(String.Format("{0:X}", (int)CodeUtils.CRC16_AD(befcrc)));
            byte[] btcrc = { CodeUtils.String2Byte(strCrc.Substring(0, 2)), CodeUtils.String2Byte(strCrc.Substring(2, 2)) };
            return btcrc;
        }

        public static int SendNACommand(CasicSession session, String strValue, String deviceId_Telecom)
        {
            NASDK currsdk = new NASDK();
            TokenResult token = currsdk.getToken();
            if (token == null)
            {
                session.Logger.Error("获取Token失败!");
                return 0;
            }
            string strToken = token.accessToken;
            session.Logger.Info("获取Token成功:" + strToken);

            CommandPara cp = new CommandPara();
            cp.paraName = "Value";
            cp.paraValue = strValue;

            int result = currsdk.sendCommand(strToken, deviceId_Telecom, null, "Config", "Config", cp, session);
            return result;
        }

        public static int SendAEPCommand(CasicSession session, string strValue, string deviceId)
        {
            string operatorId = ConfigurationManager.AppSettings["operatorId"];
            Int32 productId = Int32.Parse(ConfigurationManager.AppSettings["productId"]);

            JObject body = new JObject();
            JObject command = new JObject();
            JObject paras = new JObject();

            paras.Add("Value", strValue);
            command.Add("paras", paras);
            command.Add("serviceId", "Config");
            command.Add("method", "Config");

            body.Add("command", command);
            body.Add("deviceId", deviceId);
            body.Add("operator", operatorId);
            body.Add("productId", productId);

            string ret = AepDeviceCommand.CreateCommandLwm2mProfile(JsonConvert.SerializeObject(body));
            session.Logger.Info(ret);
            return Int32.Parse(JObject.Parse(ret)["code"].ToString());
        }

        public static void sender433Config(CasicSession session, string devCode, byte[] btPdu, byte routeflag)
        {
            if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发
            {
                return;
            }

            CasicSender sender = new CasicSender(null);
            byte[] config = sender.build433RspConfigFrame(devCode);

            config[10] = routeflag;//通信方式

            if (routeflag == 0x00)//是集中器
            {
                config[11] = 0x01;
                config[12] = 0x01;
            }

            btPdu.CopyTo(config, 13);

            SystemTimeConfig sysTimeConfig = new SystemTimeConfig(null);
            byte[] btConfig = sysTimeConfig.getConfig(new byte[0]);
            btConfig.CopyTo(config, 16);

            session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", ""));
            session.Send(CRC(config), 0, config.Length + 2);
        }

        //远程升级组帧
        public static void sender433UpdateConfig(CasicSession session, string devCode, byte[] btPdu, byte routeflag, uint size, byte[] crc)
        {
            if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发
            {
                return;
            }

            CasicSender sender = new CasicSender(null);
            byte[] config = sender.build433RspConfigFrame(devCode);

            config[10] = routeflag;//通信方式

            if (routeflag == 0x00)//是集中器
            {
                config[11] = 0x01;
                config[12] = 0x01;
            }

            btPdu.CopyTo(config, 13);

            SystemTimeConfig sysTimeConfig = new SystemTimeConfig(null);
            byte[] btConfig = sysTimeConfig.getConfig(new byte[0]);
            btConfig.CopyTo(config, 16);

            if (size > 0)//需要升级
            {
                config[config.Length - 1] = 0x01;

                byte[] updateConfig = new byte[config.Length + 10 + 8];
                config.CopyTo(updateConfig, 0);

                //升级包大小(Byte)
                byte[] sizeTag = { 0x60, 0x00, 0x06, 0x02, 
                                 0x00, 0x04, 
                                 0x00, 0x00, 0x00, 0x00 };

                byte[] sizeByte = BitConverter.GetBytes(size);
                Array.Reverse(sizeByte);
                sizeByte.CopyTo(sizeTag, 6);

                //CRC校验值
                byte[] crcTag = { 0x60, 0x00, 0x06, 0x03, 
                                 0x00, 0x02, 
                                 0x00, 0x00 };

                crc.CopyTo(crcTag, 6);

                sizeTag.CopyTo(updateConfig, config.Length);
                crcTag.CopyTo(updateConfig, config.Length + 10);

                updateConfig[3] = 0x39;//固定长度 57字节

                session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(updateConfig).Replace("-", ""));
                session.Send(CRC(updateConfig), 0, updateConfig.Length + 2);
                return;
            }

            session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", ""));
            session.Send(CRC(config), 0, config.Length + 2);
        }

        //远程升级数据包组帧
        public static void sender433UpdateDataConfig(CasicSession session, string devCode, byte[] btPdu, byte routeflag, byte[] data)
        {
            if (routeflag == 0xFF || btPdu[0] == 0xFF)//通信方式为FF时表示不存在,不下发
            {
                return;
            }

            CasicSender sender = new CasicSender(null);
            byte[] config = sender.buildHeaderFrame(devCode);

            config[10] = routeflag;//通信方式

            if (routeflag == 0x00)//是集中器
            {
                config[11] = 0x01;
                config[12] = 0x01;
            }

            btPdu.CopyTo(config, 13);

            byte[] dataTag = new byte[6 + data.Length];
            byte[] oid = { 0x60, 0x00, 0x06, 0x01 };
            oid.CopyTo(dataTag, 0);
            byte[] dataLengthByte = BitConverter.GetBytes((ushort)data.Length);

            dataTag[4] = dataLengthByte[1];
            dataTag[5] = dataLengthByte[0];

            data.CopyTo(dataTag, 6);

            byte[] dataConfig = new byte[config.Length + dataTag.Length];
            config.CopyTo(dataConfig, 0);
            dataTag.CopyTo(dataConfig, config.Length);

            byte[] lengthByte = BitConverter.GetBytes((ushort)(config.Length + dataTag.Length - 4));
            dataConfig[2] = lengthByte[1];
            dataConfig[3] = lengthByte[0];

            session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(dataConfig).Replace("-", ""));
            session.Send(CRC(dataConfig), 0, dataConfig.Length + 2);
        }

        public static List<Tag> getTags(String strTags, CasicSession session)
        {
            List<Tag> tags = new List<Tag>();
            try
            {
                int i = 0;
                while (i < strTags.Length)
                {
                    //get each tag from strTag and construct tag list; 
                    String oid = strTags.Substring(i, 8);

                    int len = Int16.Parse(strTags.Substring(i + 8, 4), System.Globalization.NumberStyles.HexNumber);
                    String value = strTags.Substring(i + 12, len * 2);
                    i = i + 12 + 2 * len;
                    //TODO LIST:Construct a tag according to oid
                    Tag tag = TagFactory.create(oid, len, value);
                    tags.Add(tag);
                }
            }
            catch (Exception e)
            {
                session.Logger.Error("设备上传协议出错:" + e.Message);
            }
            return tags;
        }

        //public static void sendMessage(CasicSession session, String devName, String devCode, int cell, List<String> eventList, List<DatasJson> datasList, List<String> startupList)
        //{
        //    DateTime now = DateTime.Now;
        //    String logtime = now.ToString("yyyy") + now.ToString("MM") + now.ToString("dd")
        //                    + now.ToString("HH") + now.ToString("mm") + now.ToString("ss");

        //    DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //当地时区
        //    long timeStamp = (long)(now - startTime).TotalMilliseconds; //相差毫秒数

        //    try
        //    {
        //        //往第三方发送数据
        //        if (datasList != null && datasList.Count > 0)
        //        {
        //            String message = JsonConvert.SerializeObject(new Json("Data", devName, devCode,
        //                  new DataJson(devName + "Data", cell, datasList, logtime), timeStamp));

        //            Client client = new Client();
        //            if (client.InitClient())
        //            {
        //                session.Logger.Info("往第三方发送数据:" + message);
        //                client.SendMessage(message);
        //            }
        //            else
        //            {
        //                session.Logger.Info("Client初始化失败,未连接上第三方服务器");
        //            }
        //        }

        //        if (eventList != null && eventList.Count > 0)
        //        {
        //            String message = JsonConvert.SerializeObject(new Json("Event", devName, devCode,
        //             new EventJson(devName + "Event", eventList, logtime), timeStamp));

        //            Client client = new Client();
        //            if (client.InitClient())
        //            {
        //                session.Logger.Info("往第三方发送数据:" + message);
        //                client.SendMessage(message);
        //            }
        //            else
        //            {
        //                session.Logger.Info("Client初始化失败,未连接上第三方服务器");
        //            }
        //        }

        //        if (startupList != null && startupList.Count == 2)
        //        {
        //            String message = JsonConvert.SerializeObject(new Json("StartupRequest", devName, devCode,
        //             new StartupJson(devName + "Data", startupList[0], startupList[1]), timeStamp));

        //            Client client = new Client();
        //            if (client.InitClient())
        //            {
        //                session.Logger.Info("往第三方发送数据:" + message);
        //                client.SendMessage(message);
        //            }
        //            else
        //            {
        //                session.Logger.Info("Client初始化失败,未连接上第三方服务器");
        //            }
        //        }
        //    }
        //    catch (Exception ex)
        //    {
        //        session.Logger.Error("往第三方发送数据出错:" + ex.Message);
        //    }

        //}

        public static void kafkaProduce(CasicSession session, String devName, String devCode, int cell,
            int? pci, int? rsrp, int? snr, List<String> eventList, List<DatasJson> datasList, List<String> startupList)
        {
            kafkaProduce(session, devName, devCode, cell, pci, rsrp, snr, eventList, datasList, startupList, null);
        }

        public static void kafkaProduce(CasicSession session, String devName, String devCode, int cell,
            int? pci, int? rsrp, int? snr, List<String> eventList, List<DatasJson> datasList, List<String> startupList, List<State> loopStates)
        {
            DateTime now = DateTime.Now;
            String logtime = now.ToString("yyyy") + now.ToString("MM") + now.ToString("dd")
                            + now.ToString("HH") + now.ToString("mm") + now.ToString("ss");

            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //当地时区
            long timeStamp = (long)(now - startTime).TotalMilliseconds; //相差毫秒数

            try
            {
                //往第三方发送数据
                if (datasList != null && datasList.Count > 0)
                {
                    var jsonSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
                    String message = JsonConvert.SerializeObject(new Json("Data", devName, devCode,
                          new DataJson(devName + "Data", cell, pci, rsrp, snr, datasList, logtime, loopStates), timeStamp));

                    KafkaUtils.produce(KafkaUtils.TOPIC, message);

                    session.Logger.Info("往kafka写入数据:" + message);
                }

                if (eventList != null && eventList.Count > 0)
                {
                    String message = JsonConvert.SerializeObject(new Json("Event", devName, devCode,
                     new EventJson(devName + "Event", eventList, logtime), timeStamp));

                    KafkaUtils.produce(KafkaUtils.TOPIC, message);

                    session.Logger.Info("往kafka写入数据:" + message);
                }

                if (startupList != null && startupList.Count == 2)
                {
                    String message = JsonConvert.SerializeObject(new Json("StartupRequest", devName, devCode,
                     new StartupJson(devName + "Data", startupList[0], startupList[1]), timeStamp));

                    KafkaUtils.produce(KafkaUtils.TOPIC, message);

                    session.Logger.Info("往kafka写入数据:" + message);
                }
            }
            catch (Exception ex)
            {
                session.Logger.Error("往kafka写入数据出错:" + ex.Message);
            }

        }

        public static void CorrKafkaProduce(CasicSession session, String devName, String devCode, int cell,
            int? pci, int? rsrp, int? snr,  List<DatasJson> datasList)
        {
            DateTime now = DateTime.Now;
            String logtime = now.ToString("yyyyMMddHHmmss");

            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //当地时区
            long timeStamp = (long)(now - startTime).TotalMilliseconds; //相差毫秒数

            string brokers = ConfigurationManager.AppSettings["corrKafkaBrokers"];
            string topic = ConfigurationManager.AppSettings["corrKafkaTopic"];

            try
            {
                //往第三方发送数据
                if (datasList != null && datasList.Count > 0)
                {
                    var jsonSetting = new JsonSerializerSettings { NullValueHandling = NullValueHandling.Ignore };
                    string message = JsonConvert.SerializeObject(new Json("Data", devName, devCode, new DataJson(devName + "Data", cell, pci, rsrp, snr, datasList, logtime, null), timeStamp));

                    KafkaUtils.produce(brokers, topic, message);

                    session.Logger.Info("往kafka写入数据:" + message);
                }
            }
            catch (Exception ex)
            {
                session.Logger.Error("往kafka写入数据出错:" + ex.Message);
            }

        }

        public static void kafkaSetResponseProduce(CasicSession session, String devCode, String devName)
        {
            String message = JsonConvert.SerializeObject(new Json("SetResponse", devName, devCode,
             new JsonBody(devName + "ConfigSuccess"), getTimeStamp()));

            KafkaUtils.produce(KafkaUtils.TOPIC, message);

            session.Logger.Info("往kafka写入数据:" + message);
        }

        public static void kafkaProduceVersinData(CasicSession session, String devName, String devCode, String version)
        {
            String message = "{\"mType\":\"Data\",\"devType\":\"" + devName + "\",\"devCode\":\""
               + devCode + "\",\"version\":\"" + version + "\"}";

            KafkaUtils.produce(KafkaUtils.TOPIC, message);

            session.Logger.Info("往kafka写入数据:" + message);
        }


        public static void sendMessage(CasicSession session, String devName, String devCode, int cell, List<String> eventList, List<DatasJson> datasList, List<String> startupList)
        {
            DateTime now = DateTime.Now;
            String logtime = now.ToString("yyyy") + now.ToString("MM") + now.ToString("dd")
                            + now.ToString("HH") + now.ToString("mm") + now.ToString("ss");

            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //当地时区
            long timeStamp = (long)(now - startTime).TotalMilliseconds; //相差毫秒数

            try
            {
                //往第三方发送数据
                if (datasList != null && datasList.Count > 0)
                {
                    String message = JsonConvert.SerializeObject(new Json("Data", devName, devCode,
                          new DataJson(devName + "Data", cell, datasList, logtime), timeStamp));

                    if (Common.SendMessage(message))
                    {
                        session.Logger.Info("往第三方发送数据:" + message);
                    }
                    else
                    {
                        session.Logger.Info("未连接上第三方服务器");
                    }
                }

                if (eventList != null && eventList.Count > 0)
                {
                    String message = JsonConvert.SerializeObject(new Json("Event", devName, devCode,
                     new EventJson(devName + "Event", eventList, logtime), timeStamp));

                    if (Common.SendMessage(message))
                    {
                        session.Logger.Info("往第三方发送数据:" + message);
                    }
                    else
                    {
                        session.Logger.Info("未连接上第三方服务器");
                    }
                }

                if (startupList != null && startupList.Count == 2)
                {
                    String message = JsonConvert.SerializeObject(new Json("StartupRequest", devName, devCode,
                     new StartupJson(devName + "Data", startupList[0], startupList[1]), timeStamp));

                    if (Common.SendMessage(message))
                    {
                        session.Logger.Info("往第三方发送数据:" + message);
                    }
                    else
                    {
                        session.Logger.Info("未连接上第三方服务器");
                    }
                }
            }
            catch (Exception ex)
            {
                session.Logger.Error("往第三方发送数据出错:" + ex.Message);
            }
        }


        public static void sendMessage(CasicSession session, String devName, String devCode, int cell, int? pci, int? rsrp, int? snr,
            List<String> eventList, List<DatasJson> datasList, List<String> startupList)
        {
            DateTime now = DateTime.Now;
            String logtime = now.ToString("yyyyMMddHHmmss");

            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //当地时区
            long timeStamp = (long)(now - startTime).TotalMilliseconds; //相差毫秒数

            try
            {
                //往第三方发送数据
                if (datasList != null && datasList.Count > 0)
                {
                    String message = JsonConvert.SerializeObject(new Json("Data", devName, devCode,
                          new DataJson(devName + "Data", cell, pci, rsrp, snr, datasList, logtime), timeStamp));

                    if (Common.SendMessage(message))
                    {
                        session.Logger.Info("往第三方发送数据:" + message);
                    }
                    else
                    {
                        session.Logger.Info("未连接上第三方服务器");
                    }
                }

                if (eventList != null && eventList.Count > 0)
                {
                    String message = JsonConvert.SerializeObject(new Json("Event", devName, devCode,
                     new EventJson(devName + "Event", eventList, logtime), timeStamp));

                    if (Common.SendMessage(message))
                    {
                        session.Logger.Info("往第三方发送事件:" + message);
                    }
                    else
                    {
                        session.Logger.Info("未连接上第三方服务器");
                    }
                }

                if (startupList != null && startupList.Count == 2)
                {
                    String message = JsonConvert.SerializeObject(new Json("StartupRequest", devName, devCode,
                     new StartupJson(devName + "Data", startupList[0], startupList[1]), timeStamp));

                    if (Common.SendMessage(message))
                    {
                        session.Logger.Info("往第三方发送数据:" + message);
                    }
                    else
                    {
                        session.Logger.Info("未连接上第三方服务器");
                    }
                }
            }
            catch (Exception ex)
            {
                session.Logger.Error("往第三方发送数据出错:" + ex.Message);
            }

        }

        public static byte getRespOperType(String operType, bool is433)
        {
            byte ret = 0x00;
            if (operType == "TrapRequest")//A版回复TrapResponse,N版回复SetRequest,井盖除外
            {
                if (is433)
                {
                    ret = 0x05;
                }
                else
                {
                    ret = 0x03;
                }

            }
            else if (operType == "OnlineRequest")
            {
                ret = 0x07;
            }
            else if (operType == "SetRequest")
            {
                ret = 0x0C;
            }
            else if (operType == "GetRequest")
            {
                ret = 0x02;
            }
            else if (operType == "WakeupRequest")
            {
                ret = 0x0B;
            }
            else if (operType == "StartupRequest")
            {
                ret = 0x09;
            }
            else
            {
                ret = 0xFF;//未知操作类型
            }

            return ret;
        }

        public static void sendSetResponse(CasicSession session, String devCode, String devName)
        {
            RedisHelper redis = new RedisHelper(0);

            String configItem = null;
            if (redis.Conn != null)
            {
                configItem = redis.StringGet(devCode);
                if (!String.IsNullOrEmpty(configItem))
                {
                    ConfigItems configItems = JsonConvert.DeserializeObject<ConfigItems>(configItem);
                    if (configItems.sm4Key != null)
                    {
                        //更新数据库设备密钥
                        SM4Utils.updateSecretKeyByDevcode(devCode, configItems.sm4Key);
                    }
                    redis.KeyDelete(devCode);
                }
            }

            String message = JsonConvert.SerializeObject(new Json("SetResponse", devName, devCode,
             new JsonBody(devName + "ConfigSuccess"), getTimeStamp()));

            if (Common.SendMessage(message))
            {
                session.Logger.Info("往第三方发送数据:" + message);
            }
            else
            {
                session.Logger.Info("未连接上第三方服务器");
            }
        }

        //public static void sendSetResponse(CasicSession session, String devCode, String devName)
        //{
        //    RedisHelper redis = new RedisHelper(0);
        //    redis.KeyDelete(devCode);

        //    String message = JsonConvert.SerializeObject(new Json("SetResponse", devName, devCode,
        //     new JsonBody(devName + "ConfigSuccess"), getTimeStamp()));

        //    Client client = new Client();
        //    if (client.InitClient())
        //    {
        //        session.Logger.Info("往第三方发送数据:" + message);
        //        client.SendMessage(message);
        //    }
        //    else
        //    {
        //        session.Logger.Info("Client初始化失败,未连接上第三方服务器");
        //    }
        //}

        public static byte[] getIpPortTag(String ip, int port)
        {
            //修改ip 0x10000022
            byte[] ipOid = { 0x10, 0x00, 0x00, 0x22 };
            byte[] ipValue = System.Text.Encoding.Default.GetBytes(ip);
            byte[] ipLen = BitConverter.GetBytes((short)ipValue.Length);
            Array.Reverse(ipLen);

            //修改port 0x10000023
            byte[] portOid = { 0x10, 0x00, 0x00, 0x23 };
            byte[] portValue = System.Text.Encoding.Default.GetBytes(port.ToString());
            byte[] portLen = BitConverter.GetBytes((short)portValue.Length);
            Array.Reverse(portLen);

            byte[] tag = new byte[4 + 2 + ipValue.Length + 4 + 2 + portValue.Length];

            ipOid.CopyTo(tag, 0);
            ipLen.CopyTo(tag, 4);
            ipValue.CopyTo(tag, 6);

            portOid.CopyTo(tag, 6 + ipValue.Length);
            portLen.CopyTo(tag, 10 + ipValue.Length);
            portValue.CopyTo(tag, 12 + ipValue.Length);

            return tag;
        }

        public static long getTimeStamp()
        {
            DateTime startTime = TimeZone.CurrentTimeZone.ToLocalTime(new System.DateTime(1970, 1, 1)); //当地时区
            long timeStamp = (long)(DateTime.Now - startTime).TotalMilliseconds; //相差毫秒数

            return timeStamp;
        }

        public static void sendConfig(CasicSession session, String devCode, String routeFlag, String source, byte[] btPdu)
        {
            if (btPdu[0] == 0xFF)//未知操作类型
            {
                return;
            }

            try
            {
                if (routeFlag == "03") //GPRS,3G网络,电信平台
                {
                    senderSM4Config(session, devCode, btPdu, source);
                }
                else if (routeFlag == "01") //433
                {
                    sender433Config(session, devCode, btPdu, 0x01);
                }
                else //sm4加密
                {
                    senderSM4Config(session, devCode, btPdu, source);
                }
            }
            catch (Exception e)
            {
                session.Logger.Error(e.ToString());
            }
        }

        public static void dispatchConfigMessage(ThirdpartySession session, String devName, String devCode, int netType,
            String concentratorCode, byte[] btPdu, byte[] configTag)
        {
            byte routeflag = 0x00;
            switch (netType)
            {
                case 1://433,所有的长连接
                    routeflag = 01;
                    break;
                case 2://其他
                case 3://电信NB
                case 4://4G
                    routeflag = 03;
                    break;
                default:
                    break;
            }

            //下发配置组帧
            CasicSender casicSender = new CasicSender(null);

            byte[] frame = casicSender.buildConfigFrame(devCode);

            int length = frame.Length + configTag.Length;
            byte[] config = new byte[length];
            frame.CopyTo(config, 0);
            configTag.CopyTo(config, frame.Length);

            config[10] = routeflag;//通信方式
            config[15] = 0x01;//Seq

            btPdu.CopyTo(config, 13);

            byte[] btLens = new byte[2];//数据帧长度
            byte[] btlens0 = BitConverter.GetBytes(length - 4);
            btLens[0] = btlens0[1];
            btLens[1] = btlens0[0];
            btLens.CopyTo(config, 2);

            ThirdpartyServer thirdparty = session.AppServer as ThirdpartyServer;//数据转发
            thirdparty.DispatchMessage(netType, devCode, concentratorCode, config);

            String message = JsonConvert.SerializeObject(new Json("SetRequest", devName, devCode,
                      new JsonBody(devName + "ConfigGot"), getTimeStamp()));

            session.Send(message + "\r\n");
        }


        public static void dispatchQueryMessage(ThirdpartySession session, String devName, String devCode, String concentratorCode, byte[] btPdu)
        {
            //下发配置组帧
            CasicSender casicSender = new CasicSender(null);

            byte[] config = casicSender.buildQueryFrame(devCode);
            btPdu.CopyTo(config, 13);

            ThirdpartyServer thirdparty = session.AppServer as ThirdpartyServer;//数据转发
            thirdparty.DispatchMessage(1, devCode, concentratorCode, config);

            String message = JsonConvert.SerializeObject(new Json("GetRequest", devName, devCode,
                      new JsonBody("Query" + devName + "Got"), getTimeStamp()));

            session.Send(message + "\r\n");
        }

        public static bool SendMessage(string message)
        {
            String thirdpartyIP = ConfigurationManager.AppSettings["ThirdpartyIP"];
            int thirdpartyPORT = Convert.ToInt32(ConfigurationManager.AppSettings["ThirdpartyPORT"]);

            bool ret = false;
            TcpClient client = new TcpClient();
            try
            {
                client.Connect(IPAddress.Parse(thirdpartyIP), thirdpartyPORT);

                NetworkStream stream = client.GetStream();
                StreamWriter sw = new StreamWriter(stream);

                if (client.Connected)
                {
                    sw.WriteLine(message);
                    sw.Flush();

                    ret = true;
                }
            }
            catch (Exception e)
            {
                //throw e;
            }
            finally
            {
                Thread.Sleep(500);
                client.Close();
            }

            return ret;
        }

        public static void remoteUpgrade(CasicSession session, String operType, String devName, String devCode, byte[] btPdu, String softwareVersion, uint size, uint offset, String source)
        {

            if (!String.IsNullOrEmpty(softwareVersion))//有上传版本号,进行升级回复
            {
                //读取文件
                //String path = Directory.GetCurrentDirectory();
                String path = Common.GetWindowsServiceInstallPath(ConfigurationManager.AppSettings["ServiceName"]);
                path += "\\Update\\" + devName;
                String lastestFilePath = String.Empty;

                var files = Directory.GetFiles(path);
                foreach (var file in files)
                {
                    if (String.IsNullOrEmpty(lastestFilePath))
                    {
                        lastestFilePath = file;
                        continue;
                    }

                    if (lastestFilePath.CompareTo(file) < 0)
                    {
                        lastestFilePath = file;
                    }
                }

                if (string.IsNullOrEmpty(lastestFilePath))
                {
                    return;
                }

                int index = lastestFilePath.LastIndexOf('_');
                String lastestVersion = lastestFilePath.Substring(index + 2);
                if (softwareVersion.CompareTo(lastestVersion) < 0)//判断是否需要升级
                {
                    //读取二进制文件
                    BinaryReader br = null;
                    try
                    {
                        br = new BinaryReader(new FileStream(lastestFilePath, FileMode.Open, FileAccess.Read, FileShare.Read));
                        long length = br.BaseStream.Length;
                        byte[] data = br.ReadBytes((int)length);
                        byte[] crc = getCRC(data);

                        senderUpgradeConfig(session, devCode, btPdu, (uint)br.BaseStream.Length, crc, source);
                    }
                    catch (IOException e)
                    {
                        session.Logger.Error(e.Message + "\n Cannot read from file.");
                        senderUpgradeConfig(session, devCode, btPdu, 0, null, source);//回复不升级
                    }
                    br.Close();
                    return;
                }
                else
                {
                    senderUpgradeConfig(session, devCode, btPdu, 0, null, source);//回复不升级
                    return;
                }
            }
            else if (operType == "GetRequest" && size > 0)//下发升级数据包
            {
                //String path = Directory.GetCurrentDirectory();
                String path = Common.GetWindowsServiceInstallPath(ConfigurationManager.AppSettings["ServiceName"]);
                path += "\\Update\\" + devName;
                String lastestFilePath = String.Empty;

                var files = Directory.GetFiles(path);
                foreach (var file in files)
                {
                    if (String.IsNullOrEmpty(lastestFilePath))
                    {
                        lastestFilePath = file;
                        continue;
                    }

                    if (lastestFilePath.CompareTo(file) < 0)
                    {
                        lastestFilePath = file;
                    }
                }

                //读取二进制文件
                BinaryReader br = null;
                try
                {
                    br = new BinaryReader(new FileStream(lastestFilePath, FileMode.Open, FileAccess.Read, FileShare.Read));

                    byte[] data;
                    int left = (int)br.BaseStream.Length - (int)offset;
                    if (left >= size)
                    {
                        data = new byte[size];
                        br.BaseStream.Position = offset;
                        br.Read(data, 0, (int)size);
                    }
                    else
                    {
                        data = new byte[left];
                        br.BaseStream.Position = offset;
                        br.Read(data, 0, left);
                    }

                    Common.senderUpgradeDataConfig(session, devCode, btPdu, offset, data, source);
                }
                catch (IOException e)
                {
                    session.Logger.Error(e.Message + "\n Cannot read from file.");
                }
                br.Close();
                return;
            }
        }

        //nb远程升级组帧
        public static void senderUpgradeConfig(CasicSession session, string devCode, byte[] btPdu, uint size, byte[] crc, String source)
        {
            CasicSender sender = new CasicSender(null);
            byte[] config = sender.buildUpgradeConfigFrame(devCode);

            config[10] = 0x03;//通信方式,nb

            btPdu.CopyTo(config, 13);

            if (size > 0)//需要升级
            {
                config[config.Length - 1] = 0x01;

                byte[] updateConfig = new byte[config.Length + 10 + 8];
                config.CopyTo(updateConfig, 0);

                // 升级包大小(Byte)
                byte[] sizeTag = { 0x60, 0x00, 0x06, 0x02, 
                                 0x00, 0x04, 
                                 0x00, 0x00, 0x00, 0x00 };

                byte[] sizeByte = BitConverter.GetBytes(size);
                Array.Reverse(sizeByte);
                sizeByte.CopyTo(sizeTag, 6);

                //CRC校验值
                byte[] crcTag = { 0x60, 0x00, 0x06, 0x03, 
                                 0x00, 0x02, 
                                 0x00, 0x00 };
                crc.CopyTo(crcTag, 6);

                sizeTag.CopyTo(updateConfig, config.Length);
                crcTag.CopyTo(updateConfig, config.Length + 10);

                int length = config.Length + 10 + 8 - 4;
                byte[] lengthByte = BitConverter.GetBytes((ushort)length);
                updateConfig[2] = lengthByte[1];
                updateConfig[3] = lengthByte[0];

                session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(updateConfig).Replace("-", ""));

                byte[] result = FrameSM4Encrypt(updateConfig);
                byte[] afcrc = CRC(result);

                //TODO:发送数据
                string strBase64Value = Convert.ToBase64String(afcrc);
                int ret = SendAEPCommand(session, strBase64Value, source); // AEP平台下发指令
                if (ret != 0)
                {
                    session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret);
                }
                else
                {
                    session.Logger.Info("电信平台下发配置信息成功!");
                }
            }
            else
            {
                // 不需要升级
                session.Logger.Info("下发回复信息:" + BitConverter.ToString(config).Replace("-", ""));

                byte[] result = FrameSM4Encrypt(config);
                byte[] afcrc = CRC(result);

                // 发送到电信AEP平台上 先转成base64
                string strBase64Value = Convert.ToBase64String(afcrc);
                int ret = SendAEPCommand(session, strBase64Value, source); // AEP平台下发指令
                if (ret != 0)
                {
                    session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret);
                }
                else
                {
                    session.Logger.Info("电信平台下发配置信息成功!");
                }
            }

        }

        //nb远程升级数据包组帧
        public static void senderUpgradeDataConfig(CasicSession session, string devCode, byte[] btPdu, uint offset, byte[] data, String source)
        {
            CasicSender sender = new CasicSender(null);
            byte[] config = sender.buildHeaderFrame(devCode);

            config[10] = 0x03;//通信方式,nb

            btPdu.CopyTo(config, 13);

            byte[] offsetTag = { 0x20, 0x00, 0x01, 0x02, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, };
            byte[] value = BitConverter.GetBytes(offset);
            value.CopyTo(offsetTag, 6);


            byte[] dataTag = new byte[6 + data.Length];
            byte[] oid = { 0x60, 0x00, 0x06, 0x01 };
            oid.CopyTo(dataTag, 0);
            byte[] dataLengthByte = BitConverter.GetBytes((ushort)data.Length);

            dataTag[4] = dataLengthByte[1];
            dataTag[5] = dataLengthByte[0];

            data.CopyTo(dataTag, 6);

            byte[] dataConfig = new byte[config.Length + offsetTag.Length + dataTag.Length];
            config.CopyTo(dataConfig, 0);
            offsetTag.CopyTo(dataConfig, config.Length);
            dataTag.CopyTo(dataConfig, config.Length + offsetTag.Length);

            byte[] lengthByte = BitConverter.GetBytes((ushort)(dataConfig.Length - 4));
            dataConfig[2] = lengthByte[1];
            dataConfig[3] = lengthByte[0];

            session.Logger.Info("下发升级数据包回复信息:" + BitConverter.ToString(dataConfig).Replace("-", ""));

            byte[] result = FrameSM4Encrypt(dataConfig);
            byte[] afcrc = CRC(result);

            //TODO:发送数据
            string strBase64Value = Convert.ToBase64String(afcrc);
            int ret = SendAEPCommand(session, strBase64Value, source);
            if (ret != 0)
            {
                session.Logger.Info("电信平台下发配置信息失败,返回的Http状态码:" + ret);
            }
            else
            {
                session.Logger.Info("电信平台下发配置信息成功!");
            }

        }

        public static void sendVersinData(CasicSession session, String devName, String devCode, String version)
        {
            String message = "{\"mType\":\"Data\",\"devType\":\"" + devName + "\",\"devCode\":\""
                + devCode + "\",\"version\":\"" + version + "\"}";

            if (Common.SendMessage(message))
            {
                session.Logger.Info("往第三方发送数据:" + message);
            }
            else
            {
                session.Logger.Info("未连接上第三方服务器");
            }
        }

        //数据帧TEA加密
        private static byte[] frameEncrypt(byte[] frame)
        {
            byte[] tag = new byte[frame.Length - 16];
            byte[] enTag;

            Array.Copy(frame, 16, tag, 0, frame.Length - 16);

            int a = tag.Length % 8;
            if (a != 0)
            {
                enTag = new byte[tag.Length + 8 - a];
                tag.CopyTo(enTag, 0);
                for (int i = 0; i < 8 - a; i++)
                {
                    enTag[tag.Length + i] = 0;
                }
            }
            else
            {
                enTag = new byte[tag.Length];
                tag.CopyTo(enTag, 0);
            }

            TEA.encrypt(ref enTag, enTag.Length);

            byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length];
            Array.Copy(frame, result, 16);
            enTag.CopyTo(result, 16);

            return result;
        }

        // 数据帧TEA加密
        private static byte[] FrameSM4Encrypt(byte[] frame)
        {
            byte[] tag = new byte[frame.Length - 16];
            byte[] enTag;

            Array.Copy(frame, 16, tag, 0, frame.Length - 16);
            enTag = SM4Utils.sm4Encrypt(tag);

            byte[] result = new byte[1 + 1 + 2 + 6 + 1 + 2 + 2 + 1 + enTag.Length];
            Array.Copy(frame, result, 16);
            enTag.CopyTo(result, 16);

            return result;
        }


        /// <summary>
        /// 获取服务安装路径
        /// </summary>
        /// <param name="ServiceName"></param>
        /// <returns></returns>
        public static string GetWindowsServiceInstallPath(string ServiceName)
        {
            string key = @"SYSTEM\CurrentControlSet\Services\" + ServiceName;
            string path = Registry.LocalMachine.OpenSubKey(key).GetValue("ImagePath").ToString();
            //替换掉双引号   
            path = path.Replace("\"", string.Empty);

            FileInfo fi = new FileInfo(path);
            return fi.Directory.ToString();
        }
    }
}