using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Security.Cryptography.X509Certificates;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Net.Security;
using Newtonsoft.Json.Linq;
using AGI.Foundation;
using AGI.Foundation.Access;
using AGI.Foundation.Access.Constraints;
using AGI.Foundation.Celestial;
using AGI.Foundation.Coordinates;
using AGI.Foundation.Geometry;
using AGI.Foundation.Propagators;
using AGI.Foundation.Time;
using Basic_Astrodynamics;
using System.Xml;
using System.Net;
using uPLibrary.Networking.M2Mqtt;
using uPLibrary.Networking.M2Mqtt.Messages;
using System.Net.Sockets;
using Satllite.Protobuf.Agi;
using Google.Protobuf;
using Google.Protobuf.Collections;
using Google.Protobuf.WellKnownTypes;
using System.Threading;
using System.Runtime.InteropServices;
namespace Mqtt_AGI
{

    class Program
    {
        

        //[DllImport("kernel32")]
        //private static extern long WritePrivateProfileString(string section, string key, string value, string filePath);\
        //win32 API 获取ini文件内容
        [DllImport("kernel32")]
        private static extern long GetPrivateProfileString(string section, string key, string defa, StringBuilder buffer, int size, string filePath);
        static MqttClient client = null; //主机为IP时  
        //static string clientId = Guid.NewGuid().ToString();
        static string ip, port;
        static int count = 0;
        static string LevelUid, LevelTopic,clientId;
        //获取配置信息中的站点等级信息 生成LevelUid
        static void Level_Topic_Uid_init()
        {
            try
            {
                string IniPath = System.Windows.Forms.Application.StartupPath + "\\config.ini";
                StringBuilder level1 = new StringBuilder(16);
                StringBuilder level2 = new StringBuilder(16);
                StringBuilder level3 = new StringBuilder(16);
                GetPrivateProfileString("role", "level1", "0", level1, 16, IniPath);
                GetPrivateProfileString("role", "level2", "0", level2, 16, IniPath);
                GetPrivateProfileString("role", "level3", "0", level3, 16, IniPath);
                //Console.WriteLine(SerializeUid.SerilizeString(Convert.ToUInt32(level1.ToString()), Convert.ToUInt32(level2.ToString()), Convert.ToUInt32(level3.ToString())));
                LevelTopic = SerializeUid.Serilize_Init_Level_Topic(Convert.ToUInt32(level1.ToString()), Convert.ToUInt32(level2.ToString()), Convert.ToUInt32(level3.ToString()));
                LevelUid = SerializeUid.Serilize_Init_Level_Uid(Convert.ToUInt32(level1.ToString()), Convert.ToUInt32(level2.ToString()), Convert.ToUInt32(level3.ToString()));
                clientId = SerializeUid.SerilizeUid(LevelUid, systemID.AGI);
                Console.WriteLine("MqttclientId:" + clientId);
                //Console.WriteLine(Convert.ToString(subTopic,2).PadLeft(32,'0'));//32位  前面补0
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        static void heart_thread() {

            //初始化包配置
            try
            {
                while (true)
                {
                    Heartbeat heartbeat = new Heartbeat();
                    heartbeat.Suid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.AGI), 2);
                    heartbeat.IidList.Add(IID.AgiReport);
                    heartbeat.IidList.Add(IID.AgiReportRespond);
                    heartbeat.IidList.Add(IID.AgiTle);
                    heartbeat.IidList.Add(IID.AgiTleRespond);
                    TDSCmd MessageHeart = new TDSCmd();
                    MessageHeart.InterfaceId = IID.OamHeartBeatRx;
                    MessageHeart.DstSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.OAM), 2);
                    MessageHeart.SrcSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.AGI), 2);
                    MessageHeart.ForwardFlag = 0;//不需要转发
                    MessageHeart.Ts = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow);
                    //加载数据段
                    Any Parameter = Any.Pack(heartbeat);
                    MessageHeart.Parameters.Add(Parameter);
                    client.Publish(SerializeUid.SerilizeTopic(LevelTopic, systemID.OAM), MessageHeart.ToByteArray());
                    Thread.Sleep(1000 * 10);
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.Message);
            }
        }
        static void client_MqttMsgPublishReceived(object sender, MqttMsgPublishEventArgs e)
        {

            //处理接收到的消息 protobuf协议
            try
            {
                TDSCmd datastruct = TDSCmd.Parser.ParseFrom(e.Message);
                Console.WriteLine("收到消息 反序列化:" + datastruct + "\r\n");

                Any Parameter;
                for (int messageNum = 0; messageNum < datastruct.Parameters.Count; ++messageNum)
                {
                    Parameter = datastruct.Parameters[messageNum];
                    if (datastruct.InterfaceId == IID.AgiReport)
                    {
                        CalcReportReq CalcReport = Parameter.Unpack<CalcReportReq>();
                        string[] args = { CalcReport.StartDateTime,CalcReport.EndDateTime,
                    CalcReport.Latitude.ToString(),CalcReport.Longitude.ToString(),
                    CalcReport.Altitude.ToString(),CalcReport.Slice.ToString(),
                    CalcReport.MinAzi.ToString(),CalcReport.MaxAzi.ToString(),
                    CalcReport.MinEle.ToString(),CalcReport.MaxEle.ToString(),
                    CalcReport.MinDist.ToString(),CalcReport.MaxDist.ToString(),
                    CalcReport.PointSlice.ToString(),CalcReport.PointCollect.ToString(),
                    CalcReport.Line0,CalcReport.Line1,CalcReport.Line2};
                        calc_report(args);//轨道预报
                    }
                    else if (datastruct.InterfaceId == IID.AgiTle)
                    {
                        CalcTleReq CalcTle = Parameter.Unpack<CalcTleReq>();
                        string[] args = { CalcTle.NoradID.ToString(), CalcTle.NoradName,
                    CalcTle.Year.ToString(),CalcTle.Month.ToString(),CalcTle.Day.ToString(),
                    CalcTle.Hour.ToString(),CalcTle.Minute.ToString(),CalcTle.Second.ToString(),
                    CalcTle.A.ToString(),CalcTle.Ee.ToString(),CalcTle.I.ToString(),
                    CalcTle.Raan.ToString(),CalcTle.Arc.ToString(),CalcTle.M.ToString() };
                        calc_tle(args);  //精轨转TLE
                    }

                }
            }
            catch (Exception ex) {
                Console.WriteLine(ex.Message);
            }
            //轨道预报
            //处理接收到的消息  
            //string msg = System.Text.Encoding.Default.GetString(e.Message);

            //Console.WriteLine("收到消息:" + msg + "\r\n");
            //string[] args = msg.Split(new char[] { ',' });
            //Console.WriteLine(e.Topic);
            ////Console.WriteLine(args);
            //if (e.Topic == SerializeUid.SerilizeString(LevelUid, systemID.AGI, Module.CACL_TLE))
            //    calc_tle(args);  //精轨转TLE
            //else if (e.Topic == "xyz_topic_parameter")
            //    calc_xyz(args);  //综合飞行弹道
            //else if (e.Topic == SerializeUid.SerilizeString(LevelUid, systemID.AGI, Module.CACL_REPORT))
            //    calc_report(args);  //轨道预报
        }
        static void client_MqttConnectionClosed(object sender, EventArgs e)
        {
            try
            {
                while (client == null || client.IsConnected == false)
                {
                    Console.WriteLine("断线重连...");
                    Thread.Sleep(5 * 1000);//5秒尝试重连一次
                    MqttConnect(ref client);
                }
            }
            catch (Exception ex)
            {
                // continue;
                Console.WriteLine(ex.Message);
                Console.WriteLine("client_MqttConnectionClosed异常");
                return;
            }

        }
        //配置ip port
        static void MqttConnect(ref MqttClient client) {
            try
            {
                client.Connect(clientId, "", "", false, 30);
                //level1/level2/level3/system
                Console.WriteLine("Subscribe:" + SerializeUid.SerilizeTopic(LevelTopic, systemID.AGI));
                client.Subscribe(new string[] { SerializeUid.SerilizeTopic(LevelTopic, systemID.AGI) }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });

                //client.Subscribe(new string[] { SerializeUid.SerilizeString(LevelUid, systemID.AGI) }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
                client.Subscribe(new string[] { "xyz_topic_parameter" }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
                //client.Subscribe(new string[] { SerializeUid.SerilizeString(LevelUid, systemID.AGI) }, new byte[] { MqttMsgBase.QOS_LEVEL_EXACTLY_ONCE });
                Console.WriteLine("Connect state:" + client.IsConnected);
            }
            catch (Exception ex)
            {
                // continue;
                Console.WriteLine(ex.Message);
                Console.WriteLine("MqttConnect异常");
                return;
            }
        }
        static void Main(string[] args)
        {


            // Application.EnableVisualStyles();
            //  Application.SetCompatibleTextRenderingDefault(false);
            //  Application.Run(new Form1());
            try
                {
                Level_Topic_Uid_init();
                //从配置文件获取ip port
                StringBuilder ip_build = new StringBuilder(32);
                StringBuilder port_build = new StringBuilder(32);
                string IniPath = System.Windows.Forms.Application.StartupPath + "\\config.ini";
                GetPrivateProfileString("mqtt-local", "server", "0", ip_build, 32, IniPath);
                GetPrivateProfileString("mqtt-local", "port", "0", port_build, 32, IniPath);
                ip = ip_build.ToString();port = port_build.ToString();
                Console.WriteLine(ip+" "+port);

               client = new MqttClient(ip, int.Parse(port), false, null, null, MqttSslProtocols.None);
                    MqttConnect(ref client);
                    // 注册消息接收处理事件，还可以注册消息订阅成功、取消订阅成功、与服务器断开等事件处理函数  
                    client.MqttMsgPublishReceived += client_MqttMsgPublishReceived;
                    //断线重连
                    client.ConnectionClosed += client_MqttConnectionClosed;
                Thread thread = new Thread(heart_thread);
                thread.Start();
                Console.WriteLine("Heart thread start");
            }
                catch (Exception ex)
                {
                    // continue;
                    Console.WriteLine(ex.Message);
                Console.WriteLine("Main 异常");

                return;
                }

        }

        static void calc_tle(string [] args) //精轨转TLE
        {
            if (args.Count() < 14) { Console.WriteLine("args<14"); return; } //参数不够13个，无法计算
            string noradid = "00000";
            System.Text.RegularExpressions.Regex rex = new System.Text.RegularExpressions.Regex(@"^\d+$"); //纯数字
            if (rex.IsMatch(args[0]))  //修改卫星双行根数中的卫星编号，卫星编号必须是五位为纯数字，否则无法做预报
            {
               noradid = Convert.ToInt32(args[0]).ToString("00000");
            }
            if (noradid.Length > 5) noradid = noradid.Substring(noradid.Length - 5);//超过5位，只取后五位作为卫星编号
            string line0 =args[1];
            if (line0 == "") line0 = noradid;  //传入卫星名称line0空字符串，默认让它就是卫星编号
            string line1 = null;
            string line2 = null;
            double[] kepler = new double[12];
        //    string dir = System.AppDomain.CurrentDomain.BaseDirectory;
 
            for (int i = 2; i < args.Count(); i++)
            {
                    kepler[i -2] = Convert.ToDouble(args[i]);
            }
          
            double Mjd = Time.YMD2ModifiedJulianDate((int)kepler[0], (int)kepler[1], (int)kepler[2], (int)kepler[3], (int)kepler[4], kepler[5]); //日期时间
            double a = kepler[6];  //轨道半轴长
            double ee = kepler[7];  //偏心率
            double I = kepler[8];    //轨道倾角
            double raan = kepler[9];  //升交点赤经
            double arc = kepler[10];  //近地点幅角
            double m = kepler[11];  //平近点角
            double tr = 0;
            double[] Kepler_J2000 = new double[] { Mjd, a, ee, I, raan, arc, tr, m };

            TLE_Computer.Kepler_J20002TLE(Kepler_J2000, ref line1, ref line2);     //生成对应的双行根数
             /*特别说明，本方法生成的TLE双行根数中默认卫星编号都是“00000”，多个这样的TLE预报时将视为同一颗卫星圈次*/
                line1=line1.Remove(2, 5);
                line1=line1.Insert(2, noradid);
                line2=line2.Remove(2, 5);
                line2=line2.Insert(2, noradid);

            // protobuf格式化操作 
            CalcTleRet calctleret =new CalcTleRet();
            calctleret.Line0 = line0;
            calctleret.Line1 = line1;
            calctleret.Line2 = line2;
            
            //初始化包配置
            TDSCmd MessageSend =new TDSCmd();
            MessageSend.InterfaceId = IID.AgiTleRespond;
            MessageSend.DstSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.SERVER),2);
            MessageSend.SrcSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.AGI),2);
            MessageSend.ForwardFlag = 0;//不需要转发
            //加载数据段
            Any Parameter = Any.Pack(calctleret);
            MessageSend.Parameters.Add(Parameter);

            
            client.Publish(SerializeUid.SerilizeTopic(LevelTopic, systemID.SERVER), MessageSend.ToByteArray());
            Console.WriteLine("Tle send topic:"+ SerializeUid.SerilizeTopic(LevelTopic, systemID.SERVER));
            Console.WriteLine("pacakge length:" + MessageSend.ToByteArray().Length);
            Console.WriteLine("Sucess send count:" + (++count));
            Console.WriteLine("Content:" + MessageSend);
            //Console.WriteLine(line0);
            //Console.WriteLine(line1);
            //Console.WriteLine(line2);
            

            //client.Publish("server/response/agi/tle", System.Text.Encoding.Default.GetBytes(line0+";"+line1+";"+line2));
            

        }

        static void calc_xyz(string[] args) //综合飞行弹道
        {
            if (args.Count() < 11) return;
            double[] xyz = new double[11];
            for (int i = 0; i < args.Count(); i++)
            {
                xyz[i] = Convert.ToDouble(args[i]);
            }
            double[] AER = new double[3];
            double[] lla = new double[3];
            double[] xx = new double[7];
            for (int i = 0; i < 7; i++)  //T,X,Y,Z,VX,VY,VZ;
                xx[i] = xyz[i];
            lla[0] = xyz[7] * Math.PI / 180;  //纬度，角度转弧度
            lla[1] = xyz[8] * Math.PI / 180;  //经度，角度转弧度
            lla[2] = xyz[9];  //高度
            double deta = xyz[10];

            Forecast.Xyz2Aer(xx, lla, deta, ref AER);
            AER[0] = AER[0] * MathematicalConstant.Rad2Deg;             //方位角
            AER[1] = AER[1] * MathematicalConstant.Rad2Deg;              //俯仰角
            AER[2] = AER[2];                                                //距离

            string aer = AER[0] + ";" + AER[1] + ";" + AER[2];
         //    Console.WriteLine(aer);
            client.Publish("xyz_topic_response", System.Text.Encoding.Default.GetBytes(aer));


        }

        static void calc_report(string[] args)  //轨道预报
        {

            if (args.Count() < 17) { Console.WriteLine("args<17");return; } //不能小于17个参数
            for (int count=0;count<args.Length;count++) { if (args[count].Length == 0) { Console.WriteLine("calc_report args["+count+"] is empty"); return; } }//参数不能为空
            /*按顺序解析MQTT传过来的参数*/
            DateTime dt1 = DateTime.ParseExact(args[0],"yyyy-MM-dd HH:mm:ss",null);                                   //预报起始时间 世界时间
            DateTime dt2 = DateTime.ParseExact(args[1],"yyyy-MM-dd HH:mm:ss",null);                                   //预报结束时间 世界时间=北京时间-8小时
            double start_mjd_utcg = Time.DateTime2ModifiedJulianDate(dt1);
            
            double Stop_mjd_utcg = Time.DateTime2ModifiedJulianDate(dt2);
            double site_wd = Convert.ToDouble(args[2]); //站点纬度
            double site_jd = Convert.ToDouble(args[3]); //站点经度
            double site_gd = Convert.ToDouble(args[4]);  //高度
            double step = Convert.ToDouble(args[5]);//预报间隔,对应原来AGI时的Constraints[9]
            //Console.WriteLine("step:"+step.ToString("f3"));
            int slice = Convert.ToInt32(step * 1000.0);
            Double[] Constraints = new Double[6];  //最小方位，最大方位，最小俯仰，最大俯仰，最小距离，最大距离
            for (int i = 0; i < 6; i++)
                Constraints[i] = Convert.ToDouble(args[i + 6]);
            double xxdjsjg = Convert.ToDouble(args[12]); //星下点计算间隔,对应原来AGI时的Constraints[10]   //仅计算星下点有用
             double xxdcjjg = Convert.ToDouble(args[13]);  //星下点采集间隔,对应原来AGI时的Constraints[11]  //仅计算星下点有用
            string line0, line1, line2;
            line0 = args[14];
            line1 = args[15];
            line2 = args[16];
            //    client.Publish("agi_topic_response", System.Text.Encoding.Default.GetBytes(string.Join(" ",args)));
            
            //开始做预报

            BindingList<TLE> Tles_0 = new BindingList<TLE>();                                                    //轨道根数泛型  TLE
            List<Aer_List_Facility_Arc> List_Forecast_Dots_Aer_Facility_0 = new List<Aer_List_Facility_Arc>();//双行根数点位预报
            Facility facility = new Facility(site_wd * Math.PI / 180.0, site_jd * Math.PI / 180.0, site_gd);   //测站维度经度高度（单位是弧度 米）


            try
            {

                var sgp4 = new Sgp4Propagator(new TwoLineElementSet(line1 + "\n" + line2));
                PropagatorPoint satPoint = sgp4.CreatePoint();
                TLE Tles = new TLE(line0, line1, line2);
                JulianDate start = new JulianDate(dt1);
                JulianDate Stop = new JulianDate(dt2);
                AGI.Foundation.Time.Duration step_Duration = new AGI.Foundation.Time.Duration(0,step);//间隔1s
                //Console.WriteLine("start time:" + start.ToDateTime().ToString("HH:mm:ss.fff"));
                //Console.WriteLine("end time:" + Stop);
                Forecast_AGI yb = new Forecast_AGI(facility, Tles, Constraints, start, Stop, step_Duration); //初始化预报参数
                try
                {
                    
                    yb.Forecast_AGI_Aer(); //计算俯仰角
                    //Console.WriteLine(yb.Count_TIC);
                    if (yb.Count_TIC > 0)
                    {
                        List_Forecast_Dots_Aer_Facility_0.AddRange(yb.Detail_Dot);
                    }
                }
                catch (Exception ex)
                {
                    // continue;
                    Console.WriteLine(ex.Message);
                    return;
                }
                int circle = 1;

                //protobuf CalcReportRet 回复包
                CalcReportRet CalcReport = new CalcReportRet();

                //JObject CalcRetJson = new JObject();//最后返回的预报信息 包含xxd data report
                //JArray ReportArray = new JArray();//生成report json对象
                Console.WriteLine("产生圈次任务总数："+List_Forecast_Dots_Aer_Facility_0.Count);
                for (int i = 0; i < List_Forecast_Dots_Aer_Facility_0.Count; i++)  //解析预报点位，并计算圈次
                {
                    
                    Aer_List_Facility_Arc aa = new Aer_List_Facility_Arc();
                    aa = List_Forecast_Dots_Aer_Facility_0[i];
                    System.DateTime currentTime = System.DateTime.Now;
                    if (i > 0 && aa.Satellite_Catalog_Number == List_Forecast_Dots_Aer_Facility_0[i - 1].Satellite_Catalog_Number)  //如果是1个任务，应该
                        circle++;
                    else circle = 1;
                    /*解析当前圈次,生成任务相关的消息*/
                    int count = aa.Aer_List.Count;
                    string nid = aa.Satellite_Catalog_Number.ToString("00000");
                    string sdate = aa.Aer_List[0].DateTime_UTCG.ToLocalTime().Date.ToString("yyyyMMdd");
                    string stime = aa.Aer_List[0].DateTime_UTCG.ToLocalTime().ToString("HHmmss.fff");
                    string edate = aa.Aer_List[count - 1].DateTime_UTCG.ToLocalTime().Date.ToString("yyyyMMdd");
                    string etime = aa.Aer_List[count - 1].DateTime_UTCG.ToLocalTime().ToString("HHmmss.fff");
                    double startAr = aa.Aer_List[0].Azimuth_Rad * MathematicalConstant.Rad2Deg;
                    double endAr = aa.Aer_List[count - 1].Azimuth_Rad * MathematicalConstant.Rad2Deg;
                    double startEr = aa.Aer_List[0].Elevation_Rad * MathematicalConstant.Rad2Deg;
                    double maxEr = startEr;
                    double minDist = aa.Aer_List[0].Range_Metre;
                    double maxDist = minDist;
                    //json 返回时间格式 "yyyy-MM-dd HH:mm:ss"
                    string start_json = aa.Aer_List[0].DateTime_UTCG.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");
                    string end_json= aa.Aer_List[count - 1].DateTime_UTCG.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");

                    string sdt = aa.Aer_List[0].DateTime_UTCG.ToLocalTime().ToString("yyyyMMddHHmm");
                    string ReportFileName = nid + sdt + ".txt";/*任务信息文件名，为卫星号+起始日期和起始时间,与任务编号同*/
                    string report_Message = ReportFileName + ";"; //任务信息消息
                    string DataFileName = nid + sdt + ".dat";/*任务dat文件名，为卫星号+起始日期和起始时间,与任务编号同*/
                    string data_Message = DataFileName + ";";  //预报点位消息
                    string XxdFileName = nid + dt1.ToLocalTime().ToString("_yyyyMMddHHmm") + dt2.ToLocalTime().ToString("_yyyyMMddHHmm") + ".txt";/*任务星下点文件名，为卫星号+起始日期和起始时间,与任务编号同*/
                    string xxd_Message = XxdFileName + ";";  //星下点消息
                    /*记录本圈次任务信息,出入境时间,出入境角度，最高仰角，最大最小距离等任务关键信息*/
                    int index = 0;
                    
                    for (int j = 1; j < count; j++) //记录最大最小仰角及行索引
                    {
                        // if (maxAr < aa.Aer_List[j].Azimuth_Rad * Const.Rad2Deg) maxAr = aa.Aer_List[j].Azimuth_Rad * Const.Rad2Deg;
                        if (maxEr < aa.Aer_List[j].Elevation_Rad * MathematicalConstant.Rad2Deg) { maxEr = aa.Aer_List[j].Elevation_Rad * MathematicalConstant.Rad2Deg; index = j; }
                        //  if (minAr > aa.Aer_List[j].Azimuth_Rad * Const.Rad2Deg) minAr = aa.Aer_List[j].Azimuth_Rad * Const.Rad2Deg;
                        // if (minEr > aa.Aer_List[j].Elevation_Rad * Const.Rad2Deg) { minEr = aa.Aer_List[j].Elevation_Rad * Const.Rad2Deg; }
                        if (minDist > aa.Aer_List[j].Range_Metre) minDist = aa.Aer_List[j].Range_Metre;
                        if (maxDist < aa.Aer_List[j].Range_Metre) maxDist = aa.Aer_List[j].Range_Metre;
                    }
                    //protobuf task package begin

                    Satllite.Protobuf.Agi.Task task = new Satllite.Protobuf.Agi.Task();//单个task包
                    task.Start = start_json;
                    task.End = end_json;
                    task.StartAzi = startAr;
                    task.EndAzi = endAr;
                    task.StartEle = startEr;
                    task.MaxEle = maxEr;
                    task.MinDist = minDist;
                    task.MaxDist = maxDist;
                    
                    //end

                    //string report;
                    

                    //report = nid + "  " + sdate + "  " + stime + " " + edate + "  " + etime + "  " + startAr + " " + endAr + "  " + startEr + "  " + maxEr + "  " + index + "  " + minDist + "  " + maxDist + "  " + slice + "  " + circle + "   " + XxdFileName + "  " + "\r\n";
                    //report_Message += report;
                    //Console.WriteLine(report_Message);
                    //client.Publish("server/response/agi/report", System.Text.Encoding.Default.GetBytes(report_Message));  //将本圈次任务信息发布出去

                    /*本圈次任务点位信息*/

                    
                    //string linedata;
                    //JArray DataArray = new JArray();//生成data json对象
                    
                    for (int j = 0; j < count; j++)
                    {
                        //JObject DataObj = new JObject();//每个俯仰角是一个json对象
                        string data_time ;
                        double azi = aa.Aer_List[j].Azimuth_Rad * MathematicalConstant.Rad2Deg;
                        double ele = aa.Aer_List[j].Elevation_Rad * MathematicalConstant.Rad2Deg;
                        double range = aa.Aer_List[j].Range_Metre;
                        string azistring, elestring;
                        azistring = azi.ToString("000.0000");
                        elestring = ele.ToString("00.0000");
                        int Milltime = aa.Aer_List[j].DateTime_UTCG.Millisecond;
                        //Console.WriteLine(aa.Aer_List[j].DateTime_UTCG.ToString("HH:mm:ss.ffff"));
                        //Console.WriteLine(aa.Aer_List[j].DateTime_UTCG.Millisecond);


                        //判断一下毫秒  四舍五入 
                        if (Milltime>=500)
                            data_time = aa.Aer_List[j].DateTime_UTCG.ToLocalTime().AddSeconds(1).ToString("yyyy-MM-dd HH:mm:ss");//Data.dat文件格式，空格不能错 azi方位角 ele仰角
                        else
                            data_time = aa.Aer_List[j].DateTime_UTCG.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");//Data.dat文件格式，空格不能错 azi方位角 ele仰角

                        //linedata = aa.Aer_List[j].DateTime_UTCG.ToLocalTime().Date.ToString("yyyy M d") + " " + aa.Aer_List[j].DateTime_UTCG.ToLocalTime().ToString("H m s") + "   " + azistring + "  " + elestring + ";";//Data.dat文件格式，空格不能错 azi方位角 ele仰角
                        //data_Message += linedata;

                        //protobuf obs begin
                        
                        Obs obs = new Obs();
                        obs.Dt = data_time;
                        obs.Azi = azi;
                        obs.Ele = ele;
                        obs.Range = range / 1000.0;
                        task.Obss.Add(obs);
                        
                        //protobuf obs end


                        //DataObj.Add("dt", data_time);
                        //DataObj.Add("azi", azi);
                        //DataObj.Add("ele", ele);
                        //DataObj.Add("range", range/1000.0);
                        //DataArray.Add(DataObj);//加入data数组
                        //输出方位角 俯仰角和距离
                    }
                    //Console.WriteLine(data_Message);
                    
                    //client.Publish("server/response/agi/data", System.Text.Encoding.Default.GetBytes(data_Message));  //将本圈次任务点位信息发布出去
                    
                    
                    
                    
                    /*生成星下点，一个卫星的所有圈次共享一个星下点预报，故仅第一圈时生成该任务的星下点*/
                    if (circle == 1)
                    {

                        AGI.Foundation.Time.Duration prog_Duration = new AGI.Foundation.Time.Duration(0, xxdjsjg);  //星下点计算间隔设置
                        Propagator_AGI pyb = new Propagator_AGI(Tles, start, Stop, prog_Duration);  //计算星下点

                        try
                        {
                            pyb.Propagator_Fixed();
                            int nn = pyb.Detail_Dot_Fixed.Count;
                        }
                        catch (Exception ex)
                        {
                            Console.WriteLine(ex.Message);
                            continue;
                        }



                        int xxd_step = Convert.ToInt32(xxdcjjg);  //星下点采集间隔设置
                        //string xxd_line;
                        //JArray XxdArray = new JArray();//生成xxd json对象
                        for (int j = 0; j < pyb.Detail_Dot_Fixed.Count; j = j +xxd_step)
                        {

                            double mjd_utcg_1 = pyb.Detail_Dot_Fixed.Xyz_List[j].Mjd_UTCG;
                            double x_1 = pyb.Detail_Dot_Fixed.Xyz_List[j].X_Metre;
                            double y_1 = pyb.Detail_Dot_Fixed.Xyz_List[j].Y_Metre;
                            double z_1 = pyb.Detail_Dot_Fixed.Xyz_List[j].Z_Metre;
                            Cartesian_LLA laa = new Cartesian_LLA(mjd_utcg_1, x_1, y_1, z_1);
                            string xxd_date = laa.DateTime_UTCG.ToLocalTime().ToString("yyyy-MM-dd HH:mm:ss");
                            double lattitude = laa.Latitude_Rad * MathematicalConstant.Rad2Deg;
                            double longtitude = laa.Longitude_Rad * MathematicalConstant.Rad2Deg;
                            double altitude = laa.Altitude_Metre;
                            string latstring, longstring;
                            latstring = lattitude.ToString("0.00");
                            longstring = longtitude.ToString("0.00");
                            //xxd_line = laa.DateTime_UTCG.ToString("yyyyMMdd   HH:mm:ss.fff") + "   " + laa.X_Metre.ToString("0.00") + "   " + laa.Y_Metre.ToString("0.00") + "   " + laa.Z_Metre.ToString("0.00") + "     " +latstring + "   " +longstring + "   " + laa.Altitude_Metre.ToString("0.00") + "   \r\n";
                            //xxd_line = laa.DateTime_UTCG.ToLocalTime().ToString("yyyyMMdd HH:mm:ss.fff") + " " + 0 + " " + 0 + " " + 0 + " " + latstring + " " + longstring + " " + 0 + ";";
                            //xxd_Message += xxd_line;
                            
                            //protobuf xxd begin
                            
                             /* 测试先不发送xxd*/
                            Xxd xxd = new Xxd();
                            xxd.Dt = xxd_date;
                            xxd.Lon = longtitude;
                            xxd.Lat = lattitude;
                            xxd.Height = altitude / 1000.0;
                            CalcReport.Xxds.Add(xxd);
                            
                            
                            //end

                            //JObject XxdObject = new JObject();
                            //XxdObject.Add("dt", xxd_date) ;
                            //XxdObject.Add("lon",longtitude);
                            //XxdObject.Add("lat",lattitude);
                            //XxdObject.Add("height",altitude/1000.0);
                            //XxdArray.Add(XxdObject);

                        }
                        //CalcRetJson.Add("xxd",XxdArray);
                        //Console.WriteLine(xxd_Message);
                        //client.Publish("server/response/agi/xxd", System.Text.Encoding.Default.GetBytes(xxd_Message));  //将任务星下点信息发布出去

                    }
                    CalcReport.Tasks.Add(task);//每一圈产生一个task
                    
                   // JObject ReportObj = new JObject();
                    //ReportObj.Add("start", start_json); ReportObj.Add("end", end_json);
                    //ReportObj.Add("startAzi", startAr); ReportObj.Add("endAzi", endAr);
                    //ReportObj.Add("startEle", startEr); ReportObj.Add("maxEle", maxEr);
                    //ReportObj.Add("minDist", minDist / 1000.0); ReportObj.Add("maxDist", maxDist / 1000.0);
                    //ReportObj.Add("obs", DataArray);
                    //ReportArray.Add(ReportObj);

                }
                //protobuf begin
                //初始化包配置
                TDSCmd MessageReport = new TDSCmd();
                MessageReport.InterfaceId = IID.AgiReportRespond;
                MessageReport.DstSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.SERVER),2);
                MessageReport.SrcSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.AGI),2);
                MessageReport.ForwardFlag = 0;//不需要转发
                MessageReport.Ts = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow);
                //加载数据段
                Any Parameter = Any.Pack(CalcReport);
                MessageReport.Parameters.Add(Parameter);
                

                client.Publish(SerializeUid.SerilizeTopic(LevelTopic, systemID.SERVER), MessageReport.ToByteArray());

                Console.WriteLine("Report send topic:" + SerializeUid.SerilizeTopic(LevelTopic, systemID.SERVER));

                Console.WriteLine("Report pacakge length:" + MessageReport.ToByteArray().Length);
                //client.Publish("server/response/agi/json", System.Text.Encoding.Default.GetBytes(CalcRetJson.ToString()));  //将任务星下点信息发布出去
                Console.WriteLine("Sucess send count:" + (++count));
                Console.WriteLine("Content:" + MessageReport);
                //Console.WriteLine(CalcRetJson.ToString());

                //日志包
                TDSCmd MessageLog = new TDSCmd();
                Log log = new Log();
                log.StationID = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.AGI), 2);
                log.LogInfoCHN = line0;
                log.LogInfoENG = line0;
                log.Loglevel = LogLevel.Normal;
                log.Manipunator = "system";
                log.ReportTime = Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow);
                MessageLog.InterfaceId = IID.OamLogRx;
                MessageLog.DstSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.OAM), 2);
                MessageLog.SrcSuid = Convert.ToUInt32(SerializeUid.SerilizeUid(LevelUid, systemID.AGI), 2);
                MessageLog.Ts= Google.Protobuf.WellKnownTypes.Timestamp.FromDateTime(DateTime.UtcNow);
                Any Logs = Any.Pack(log);
                MessageLog.Parameters.Add(Logs);
                client.Publish(SerializeUid.SerilizeTopic(LevelTopic, systemID.OAM), MessageLog.ToByteArray());
                //protobuf end
                Console.WriteLine("Log send topic:" + SerializeUid.SerilizeTopic(LevelTopic, systemID.OAM));

                Console.WriteLine("Log pacakge length:" + MessageLog.ToByteArray().Length);
                //client.Publish("server/response/agi/json", System.Text.Encoding.Default.GetBytes(CalcRetJson.ToString()));  //将任务星下点信息发布出去
                Console.WriteLine("Content:" + MessageLog);
                //Console.WriteLine(CalcRetJson.ToString());

            }
            catch (Exception e)
            {
               Console.WriteLine(e.Message);
                return;
            }


        }

    }
}
