Newer
Older
SensorHub / SensorHub.MultiLeak / MultiLeak.cs
root on 17 Sep 2021 23 KB first commit
using Newtonsoft.Json;
using SensorHub.Config;
using SensorHub.Servers;
using SensorHub.Servers.Commands.CASICCommands;
using SensorHub.Servers.JsonFormat;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Caching;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SensorHub.MultiLeak
{
    public class MultiLeak : CommandBase<CasicSession, StringRequestInfo>
    {
        private static MemoryCache memoryCache = new MemoryCache("MultiLeak");
        private readonly object SyncObj = new object();

        private RedisHelper redis = new RedisHelper(0);

        public override void ExecuteCommand(CasicSession session, StringRequestInfo requestInfo)
        {
            //TODO: construct the receving casic data
            String preamble = requestInfo.Parameters[0];
            String version = requestInfo.Parameters[1];
            String leng = requestInfo.Parameters[2];
            String devCode = requestInfo.Parameters[3];
            String routeFlag = requestInfo.Parameters[4];
            String dstNodeAddr = requestInfo.Parameters[5];
            String pduType = requestInfo.Parameters[6];
            String seq = requestInfo.Parameters[7];
            String settings = requestInfo.Parameters[8];
            String source = requestInfo.Parameters[9];

            String devName = "MultiLeak";

            if (source.Contains("-"))
            {
                session.Send("HTTP/1.1 200 OK\r\n\r\n\r\n");
                session.Close();
            }

            //print the receving data
            String devType = "多功能漏损监测仪";
            String operType = Common.getOpeTypeByPdu(pduType);
            session.Logger.Info("AD接收数据:" + requestInfo.Body);
            session.Logger.Info("设备类型:" + devType);
            session.Logger.Info("操作类型:" + operType);
            session.Logger.Info("会话:" + session.HubAddr + "," + session.SessionID);

            //判断是返回的设置确认数据帧, 回复第三方
            if (operType == "SetResponse")
            {
                for (int type = 1; type < 4; type++)
                {
                    if (string.IsNullOrEmpty(redis.StringGet(devCode + "-" + type)))
                    {
                        continue;
                    }

                    Common.sendSetResponse(session, devCode + "-" + type, devName);

                    if (source != "433")
                    {
                        for (int t = type + 1; t < 4; t++)
                        {
                            if (!string.IsNullOrEmpty(redis.StringGet(devCode + "-" + t)))
                            {
                                Thread.Sleep(5000);
                                senderGPRSConfig(session, devCode, new byte[2] { 0x03, 0x81 }, source);
                                break;
                            }
                        }
                    }

                    return;     
                }
                return;
            }

            if (!isfinishe(pduType) || seq != "01")//不分包不缓存
            {
                //多功能分包传输,对各个数据分包进行缓存
                var item = memoryCache.Get(devCode);
                if (item != null && (((int)item >> (Convert.ToInt32(seq, 16) - 1)) & 0x01) == 1)
                {
                    session.Logger.Info("已缓存数据序列号:" + Convert.ToString((int)item, 2));
                    session.Logger.Info("该数据已缓存!");
                    return;
                }
                else
                {
                    lock (this.SyncObj)//锁定
                    {
                        item = memoryCache.Get(devCode);

                        if (item != null)
                        {
                            session.Logger.Info("已缓存数据序列号:" + Convert.ToString((int)item, 2));

                            if ((((int)item >> (Convert.ToInt32(seq, 16) - 1)) & 0x01) == 1)
                            {
                                session.Logger.Info("该数据已缓存!");
                                return;
                            }
                            else
                            {
                                var cachePolicy = new CacheItemPolicy();
                                cachePolicy.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(1);

                                int Seq = (int)item;
                                Seq |= (1 << (Convert.ToInt32(seq, 16) - 1));
                                memoryCache.Set(devCode, Seq, cachePolicy);
                                session.Logger.Info("设置已经接收数据序列号:" + Convert.ToString(Seq, 2));
                            }
                        }
                        else
                        {
                            var cachePolicy = new CacheItemPolicy();
                            cachePolicy.AbsoluteExpiration = DateTimeOffset.Now.AddMinutes(1);

                            int Seq = 0;
                            Seq |= (1 << (Convert.ToInt32(seq, 16) - 1));
                            memoryCache.Set(devCode, Seq, cachePolicy);
                            session.Logger.Info("设置已经接收数据序列号:" + Convert.ToString(Seq, 2));
                        }

                    }
                }
            }

            List<Tag> tags = Common.getTags(settings, session);

            //具体业务处理
            String collectDate = "";
            String uptime = "";

            int? pci = null;
            int? rsrp = null;
            int? snr = null;

            String softwareVersion = "";
            uint offset = 0;
            uint size = 0;

            List<String> eventList = new List<String>();
            List<DatasJson> datasList = new List<DatasJson>();

            foreach (Tag tag in tags)
            {
                if (!(tag is UploadTag))
                {
                    if (tag != null && tag is PCITag)
                    {
                        PCITag pciTag = (PCITag)tag;
                        pci = pciTag.PCI;
                        continue;
                    }

                    if (tag != null && tag is RSRPTag)
                    {
                        RSRPTag rsrpTag = (RSRPTag)tag;
                        rsrp = rsrpTag.RSRP;
                        continue;
                    }

                    if (tag != null && tag is SNRTag)
                    {
                        SNRTag snrTag = (SNRTag)tag;
                        snr = snrTag.SNR;
                        continue;
                    }

                    if (tag != null && tag is CellTag)  //多功能电量单独发送
                    {
                        CellTag cellTag = tag as CellTag;

                        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
                        {
                            String message = JsonConvert.SerializeObject(new Json("Data", devName, devCode,
                                  new DataJson("MultiLeakCellData", cellTag.Cell, null, logtime), timeStamp));

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

                        break;
                    }

                    //非业务处理
                    if (tag != null && tag is SystemDateTag)
                    {
                        SystemDateTag systemDateTag = tag as SystemDateTag;
                        collectDate = systemDateTag.CollectDate;
                        continue;
                    }

                    if (tag != null && tag is SensorException0Tag)
                    {
                        SensorException0Tag sensorException0 = tag as SensorException0Tag;
                        int state = sensorException0.state;

                        if (state == 0) continue;

                        eventList.Add(getMultiLeakAlarm(state));

                        session.Logger.Info("通道一发送容错信息:oid:" + tag.Oid + ";value:" + state);
                        continue;
                    }

                    if (tag != null && tag is SensorException1Tag)
                    {
                        SensorException1Tag sensorException1 = tag as SensorException1Tag;
                        int state = sensorException1.state;

                        if (state == 0) continue;

                        eventList.Add(getMultiLeakAlarm(state + 3));

                        session.Logger.Info("通道二发送容错信息:oid:" + tag.Oid + ";value:" + state);
                        continue;
                    }

                    if (tag != null && tag is SensorException2Tag)
                    {
                        SensorException2Tag sensorException2 = tag as SensorException2Tag;
                        int state = sensorException2.state;

                        if (state == 0) continue;

                        eventList.Add(getMultiLeakAlarm(state + 6));

                        session.Logger.Info("通道三发送容错信息:oid:" + tag.Oid + ";value:" + state);
                        continue;
                    }

                    //非业务处理
                    if (tag != null && tag is SoftwareVersionTag)
                    {
                        SoftwareVersionTag versionTag = (SoftwareVersionTag)tag;
                        softwareVersion = versionTag.Version;
                        continue;
                    }

                    if (tag != null && tag is OffsetTag)
                    {
                        OffsetTag offsetTag = (OffsetTag)tag;
                        offset = offsetTag.Offset;
                        continue;
                    }

                    if (tag != null && tag is SizeTag)
                    {
                        SizeTag sizeTag = (SizeTag)tag;
                        size = sizeTag.Size;
                        continue;
                    }

                }
                else
                {
                    //业务处理 
                    UploadTag uploadTag = tag as UploadTag;

                    switch (uploadTag.BizType)
                    {
                        case 1:
                            //流量
                            TagHandler flowHandler = new FlowTagHandler();
                            flowHandler.resolve(tag, session);

                            DateTime baseTime1 = Convert.ToDateTime(collectDate + " " + flowHandler.CollecTime);

                            datasList.Clear();
                            for (int i = 0; i < flowHandler.DataList.Count / 3; i++)
                            {
                                DateTime upTime = baseTime1.AddMinutes(i * flowHandler.Interval);
                                uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd")
                                    + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss");

                                datasList.Add(new MultiLeakFlowDatasJson(uptime, (float)flowHandler.DataList[i * 3],
                                    (float)flowHandler.DataList[i * 3 + 1], (float)flowHandler.DataList[i * 3 + 2]));
                            }
                            sendMessage(session, "MultiLeakFlow", devCode, -1, pci, rsrp, snr, null, datasList, null);

                            break;
                        case 2:
                            //压力
                            TagHandler pressHandler = new PressTagHandler();
                            pressHandler.resolve(tag, session);

                            DateTime baseTime2 = Convert.ToDateTime(collectDate + " " + pressHandler.CollecTime);

                            datasList.Clear();
                            for (int i = 0; i < pressHandler.DataList.Count; i++)
                            {
                                DateTime upTime = baseTime2.AddMinutes(i * pressHandler.Interval);
                                uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd")
                                    + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss");

                                datasList.Add(new MultiLeakPressureDatasJson(uptime, (float)pressHandler.DataList[i]));
                            }
                            sendMessage(session, "MultiLeakPressure", devCode, -1, pci, rsrp, snr, null, datasList, null);

                            break;
                        case 4:
                            //噪声
                            TagHandler noiseHandler = new NoiseTagHandler();
                            noiseHandler.resolve(tag, session);

                            DateTime baseTime3 = Convert.ToDateTime(collectDate + " " + noiseHandler.CollecTime);

                            datasList.Clear();
                            for (int i = 0; i < noiseHandler.DataList.Count; i++)
                            {
                                DateTime upTime = baseTime3.AddMinutes(i * noiseHandler.Interval);
                                uptime = upTime.ToString("yyyy") + upTime.ToString("MM") + upTime.ToString("dd")
                                    + upTime.ToString("HH") + upTime.ToString("mm") + upTime.ToString("ss");

                                datasList.Add(new MultiLeakNoiseDatasJson(uptime, (double)noiseHandler.DataList[i]));
                            }
                            sendMessage(session, "MultiLeakNoise", devCode, -1, pci, rsrp, snr, null, datasList, null);

                            break;
                        default:
                            session.Logger.Info("未知业务类型!");
                            break;
                    }

                }
            }

            byte[] btPdu = new byte[2]; //2个字节
            btPdu[0] = Common.getRespOperType(operType, source == "433" ? true : false);
            btPdu[1] = 0x81;

            if (btPdu[0] == 0xFF)//未知操作类型
            {
                return;
            }

            if (softwareVersion != "" || size != 0 || offset != 0)//进入远程升级流程
            {
                Common.remoteUpgrade(session, operType, devName, devCode, btPdu, softwareVersion, size, offset, source);
                return;
            }


            sendMessage(session, devName, devCode, -1, pci, rsrp, snr, eventList, null, null);

            if (isfinishe(pduType))
            {
                try
                {
                    if (routeFlag == "03") //GPRS,3G网络,电信平台
                    {
                        memoryCache.Remove(devCode);
                        senderGPRSConfig(session, devCode, btPdu, source);
                    }
                    else //433
                    {
                        sender433Config(session, devCode, btPdu, 0x01);
                    }
                }
                catch (Exception e)
                {
                    session.Logger.Error(e.ToString());
                }
            }
        }

        private 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("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", "MultiLeak", 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);
            }

        }

        private void sender433Config(CasicSession session, string devCode, byte[] btPdu, byte routeflag)
        {
            CasicSender sender = new CasicSender(null);
            byte[] config = sender.build433RspConfigFrame(devCode);

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

            btPdu.CopyTo(config, 13);

            var item = memoryCache.Get(devCode);
            if (item != null)
            {
                byte[] value = BitConverter.GetBytes((int)item);
                config[34] = value[1];
                config[35] = value[0];
            }
  
            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(Common.CRC(config), 0, config.Length + 2);

            memoryCache.Remove(devCode);//移除上一次缓存的分包状态
        }

        private void senderGPRSConfig(CasicSession session, string devCode, byte[] btPdu, string source)
        {
            for (int type = 1; type <= 4; type++)
            {
                String configItem = null;
                if (redis.Conn != null)
                {
                    configItem = redis.StringGet(devCode + "-" + type);
                }

                if (string.IsNullOrEmpty(configItem) && type < 4)
                {
                    continue;
                }

                byte[] config = ConfigBuild.buildConfigFrame(devCode, configItem);
                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("-", ""));

                if (source == "4G")
                {
                    session.Send(Common.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);

                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 = Common.CRC(result);

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

                break;
            }
           
        }


        private bool isfinishe(String pduType)
        {
            Int16 btpduType = Int16.Parse(pduType, System.Globalization.NumberStyles.HexNumber);
            int flag = btpduType & 0x80;
            return flag == 128 ? true : false;
        }

        private String getMultiLeakAlarm(int state)
        {
            switch (state)
            {
                case 0:
                    return "MultiLeakFlowNormal";//流量探头正常
                case 1:
                    return "MultiLeakFlowFail"; //流量探头采集失败
                case 2:
                    return "MultiLeakFlowError"; //流量探头数据异常
                case 3:
                    return "MultiLeakPressureNormal";//压力探头正常
                case 4:
                    return "MultiLeakPressureFail"; //压力探头采集失败
                case 5:
                    return "MultiLeakPressureError"; //压力探头数据异常
                case 6:
                    return "MultiLeakNoiseNormal";//噪声探头正常
                case 7:
                    return "MultiLeakNoiseFail"; //噪声探头采集失败
                case 8:
                    return "MultiLeakNoiseError"; //噪声探头数据异常
                default:
                    return "MultiLeakUnknown"; //未知异常

            }
        }
    }
}