Newer
Older
SensorHub / SensorHub.Dig / Dig.cs
root on 17 Sep 2021 16 KB first commit
using MathWorks.MATLAB.NET.Arrays;
using mExcaMonitor;
using Newtonsoft.Json;
using SensorHub.Config;
using SensorHub.Servers;
using SensorHub.Servers.Commands.CASICCommands;
using SensorHub.Servers.JsonFormat;
using SensorHub.Utility;
using SuperSocket.SocketBase.Command;
using SuperSocket.SocketBase.Protocol;
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace SensorHub.Dig
{
    public class Dig : CommandBase<CasicSession, StringRequestInfo>
    {
        private static Dictionary<string, float[]> digDataValueMap = new Dictionary<string, float[]>();
        private static Dictionary<string, List<Object[]>> calResult = new Dictionary<string, List<Object[]>>();//计算结果

        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 devType = "开挖监测仪";
            String operType = Common.getOpeTypeByPdu(pduType);
            session.Logger.Info("AD接收数据:" + requestInfo.Body);
            session.Logger.Info("设备类型:" + devType);
            session.Logger.Info("操作类型:" + operType);
            session.Logger.Info("序号:" + seq);
            session.Logger.Info("会话:" + session.HubAddr + "," + session.SessionID);

            //判断是返回的设置确认数据帧, 回复第三方
            if (operType == "SetResponse")
            {
                Common.sendSetResponse(session, devCode, "Dig");
                return;
            }

            if (session.HubAddr == null)//新连接到来
            {
                if (DigServer.digWithSessionIdMap.ContainsKey(devCode))
                {
                    String sessionID = DigServer.digWithSessionIdMap[devCode];
                    CasicSession s = session.AppServer.GetSessionByID(sessionID);

                    if (s != null && s.Connected)
                    {
                        s.HubAddr = null;
                        s.Close();
                    }

                    DigServer.digWithSessionIdMap[devCode] = session.SessionID;

                    //该设备之前已连接,更新会话,断开旧连接
                    //byte[] btPdu = new byte[2];
                    //btPdu[0] = Common.getRespOperType(operType, true);
                    //btPdu[1] = 0x92;
                    //Common.sender433Config(session, devCode, btPdu, 0x03);
                    //return;
                }
                else
                {
                    DigServer.digWithSessionIdMap.Add(devCode, session.SessionID);

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

                    String logtime = now.ToString("yyyy") + now.ToString("MM") + now.ToString("dd")
                        + now.ToString("HH") + now.ToString("mm") + now.ToString("ss");

                    String message = JsonConvert.SerializeObject(new Json("Event", "Dig", devCode,
                        new DataJson("DigOnline", -1, null, logtime), timeStamp));

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

                session.HubAddr = devCode;
            }

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

            //具体业务处理
            String collectDate = "";
            List<String> eventList = new List<String>();
            List<DatasJson> datasList = new List<DatasJson>();
            String timestamp = "";//16进制形式

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

                    //非业务处理10000051,时间戳
                    if (tag != null && tag is SystemTimeTag)
                    {
                        SystemTimeTag systemTimeTag = (SystemTimeTag)tag;
                        timestamp = systemTimeTag.SysTime;
                        continue;
                    }


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

                        if (state == 0) continue;

                        redis.Publish("DigAlarm", devCode);//主动发布消息

                        eventList.Add(getDigAlarm(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;

                        eventList.Add(getDigAlarm(2));//DigLowBatteryAlarm:20

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

                }
                else
                {
                    //业务处理 
                    UploadTag uploadTag = tag as UploadTag;
                    switch (uploadTag.BizType)
                    {
                        case 20:
                            //速度
                            TagHandler speedHandler = new SpeedTagHandler();
                            speedHandler.resolve(tag, session);

                            int Seq = Convert.ToInt32(seq, 16) - 1;

                            if (speedHandler.Data != null)
                            {
                                if (!digDataValueMap.ContainsKey(devCode))
                                {
                                    digDataValueMap.Add(devCode, new float[3750 * 10]); //7500
                                }

                                if (Seq < 10)//只接收10s的数据
                                {
                                    (speedHandler.Data as float[]).CopyTo(digDataValueMap[devCode], 3750 * Seq);
                                }
                            }
                            break;

                        case 6:
                            session.Logger.Info("开挖监测仪心跳");
                            break;

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

            Common.sendMessage(session, "Dig", devCode, -1, eventList, datasList, null);

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

            byte oper = Common.getRespOperType(operType, true);//PDUType
            if (oper == 0xFF)//未知操作类型,不返回下发
                return;

            config[13] = oper;//操作类型
            config[10] = 0x03;//通信方式
            config[14] = 0x92;
            config[15] = 0x01;//Seq

            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);

            if (seq == "0A")//10s数据接收完毕
            {
                if (DigServer.digDataFinishMap.ContainsKey(devCode))
                {
                    DigServer.digDataFinishMap[devCode] = true;
                }
                else
                {
                    session.Logger.Info("设备[" + devCode + "]未在当前唤醒组中!");
                    return;
                }


                if (DigServer.digGroupDevcodeMap.ContainsKey(timestamp))
                {
                    foreach (var devcode in DigServer.digGroupDevcodeMap[timestamp])
                    {
                        if (DigServer.digDataFinishMap.ContainsKey(devcode) && DigServer.digDataFinishMap[devcode])
                        {
                            continue;
                        }
                        else
                        {
                            return;//数据未接收完成,不满足计算条件,直接退出
                        }
                    }


                    //调用算法进行计算
                    calculate(session, timestamp);
                }

                return;
            }


            //判断如果是心跳,检查是否需要下发参数
            if (operType == "OnlineRequest")
            {
                RedisHelper redis = new RedisHelper(0);
                String configItem = redis.StringGet(devCode);

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

                Thread.Sleep(5000);//延迟5s下发

                config = ConfigBuild.buildConfigFrame(devCode, configItem);
                config[10] = 0x03;
                config[13] = 0x03;
                config[14] = 0x92;

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

                session.Logger.Info("主动下发配置信息:" + BitConverter.ToString(config).Replace("-", ""));
                session.Send(Common.CRC(config), 0, config.Length + 2);
            }
        }


        private void calculate(CasicSession session, String timestamp)
        {
            String[] devCodes = DigServer.digGroupDevcodeMap[timestamp];

            if (devCodes.Length != 5)
            {
                session.Logger.Info("错误,不是5个设备编号,不满足计算条件");
                return;
            }

            session.Logger.Info("将数据存入文件!");

            string decTimestamp = StringUtil.Hex2DecTime(timestamp);//转换为直观的10进制时间戳
            foreach (var devcode in devCodes)
            {
                writeFile(devcode, decTimestamp);
            }

            session.Logger.Info("开始调用算法!");

            String devcodes = devCodes[0] + "," + devCodes[1] + "," + devCodes[2] + "," + devCodes[3] + "," + devCodes[4];//关键字

            try
            {

                mExcaMonitor.excavationMonitoring exc = new mExcaMonitor.excavationMonitoring();
                Object[] outList = exc.mExcaMonitor(3, (MWNumericArray)digDataValueMap[devCodes[0]], (MWNumericArray)digDataValueMap[devCodes[1]],
                    (MWNumericArray)digDataValueMap[devCodes[2]], (MWNumericArray)digDataValueMap[devCodes[3]], (MWNumericArray)digDataValueMap[devCodes[4]]);


                session.Logger.Info("调用算法计算结果:" + outList[0] + "," + outList[1] + "," + outList[2]);

                //String devcodes = devCodes[0] + "," + devCodes[1] + "," + devCodes[2] + "," + devCodes[3] + "," + devCodes[4];//关键字
                if (!calResult.ContainsKey(devcodes))
                {
                    calResult.Add(devcodes, new List<Object[]>());
                }

                calResult[devcodes].Add(outList);
            }
            catch (Exception ex)
            {
                throw ex;
            }

            foreach (var devcode in devCodes)
            {
                digDataValueMap.Remove(devcode);
                DigServer.digDataFinishMap.Remove(devcode);
            }
            DigServer.digGroupDevcodeMap.Remove(timestamp);//初始化,清除状态

            session.Logger.Info("计算结果组数:" + calResult[devcodes].Count);

            //calResult.Remove(devcodes);//暂时
            if (calResult[devcodes].Count >= 5)
            {
                session.Logger.Info("计算结果大于等于5组,开始分析!");

                int mark = 0;
                double distance = 0.0;   //开挖距离
                double angle = 0.0;      //开挖角度

                double manuallyDistance = 0.0;   //人工开挖距离
                double manuallyAngle = 0.0;      //人工开挖角度

                double mechanicallyDistance = 0.0;   //机械开挖距离
                double mechanicallyAngle = 0.0;      //机械开挖角度

                int no = 0;
                int manually = 0;
                int mechanically = 0;
                foreach (Object[] v in calResult[devcodes])
                {
                    session.Logger.Info("转换开始!");

                    int _mark = int.Parse(v[0].ToString());
                    double _distance = double.Parse(v[1].ToString());
                    double _angle = double.Parse(v[2].ToString());

                    session.Logger.Info("转换结果:" + _mark + "," + _distance + "," + _angle);

                    if (_mark == 0)
                    {
                        no++;
                    }
                    else if (_mark == 1)
                    {
                        manually++;
                        manuallyDistance = _distance;
                        manuallyAngle = _angle;
                    }
                    else if (_mark == 2)
                    {
                        mechanically++;
                        mechanicallyDistance = _distance;
                        mechanicallyAngle = _angle;
                    }
                }


                if (no > manually + mechanically)
                {
                    //无开挖
                    mark = 0;
                }
                else if (manually > mechanically)
                {
                    //人工开挖
                    mark = 1;
                    distance = manuallyDistance;
                    angle = manuallyAngle;
                }
                else
                {
                    //机械开挖
                    mark = 2;
                    distance = mechanicallyDistance;
                    angle = mechanicallyAngle;
                }

                //往第三方发送json字符串
                List<DatasJson> datasList = new List<DatasJson>();
                datasList.Add(new DigDatasJson(mark, distance, angle));
                Common.sendMessage(session, "Dig", devCodes[0], -1, null, datasList, null);

                calResult.Remove(devcodes);
                session.Logger.Info("开挖类型mark:" + mark + ",距离distance:" + distance + ",角度angle:" + angle);
            }
            else
            {
                session.Logger.Info("计算结果不足5次,继续下发唤醒点名指令:" + devcodes);
                redis.Publish("DigGroup", devcodes);
            }

        }

        private void writeFile(string devcode, string timestamp)
        {
            StringBuilder sb = new StringBuilder();
            foreach (double data in digDataValueMap[devcode])
            {
                sb.Append(data + " ");
            }

            String path = AppDomain.CurrentDomain.BaseDirectory + "File\\";
            String filename = devcode + "_" + timestamp + ".txt";
            File.AppendAllText(path + filename, sb.ToString());
        }

        private String getDigAlarm(int state)
        {
            switch (state)
            {
                case 0:
                    return "DigNormal";//正常
                case 1:
                    return "DigAlarm"; //报警
                case 2:
                    return "DigLowBatteryAlarm"; //低电量报警
                default:
                    return "DigUnknown"; //未知异常
            }
        }
    }
}