using Casic.Birmm.RbFreqStandMeasure.Properties; using Casic.Birmm.RbFreqStandMeasure.R_DataBase.Model; using Casic.Birmm.RbFreqStandMeasure.R_DataBase.Service; using Casic.Birmm.RbFreqStandMeasure.R_DataBase.Service.Impl; using Casic.Birmm.RbFreqStandMeasure.Tools; using System; using System.Collections.Generic; using System.Drawing; using System.Drawing.Drawing2D; using System.IO.Ports; using System.Linq; using System.Reflection; using System.Text; using System.Threading; using System.Windows.Forms; namespace Casic.Birmm.RbFreqStandMeasure.tools { public class DetectionHelper { private readonly object obj = new object(); private bool isUsing = false; private System.Threading.Timer timerAccuracy; delegate void TimerDelegate(string text); private long devIdAccuracy = -1; private SerialPort portAccuracy; private System.Threading.Timer timerStability; private long devIdStability = -1; private SerialPort portStability; private List<string> resultStability = new List<string>(); private System.Threading.Timer timerBootFeature; private long devIdBootFeature = -1; private SerialPort portBootFeature; private List<string> resultBootFeature = new List<string>(); private System.Threading.Timer timerAgeRate; private long devIdAgeRate = -1; private SerialPort portAgeRate; private List<string> resultAgeRate = new List<string>(); private DetectionService detectionService = new DetectionServiceImpl(); private DetectionItemService detectionItemService = new DetectionItemServiceImpl(); private DeviceService deviceService = new DeviceServiceImpl(); private System.Threading.Timer timerClock; private static System.Threading.Timer timerSatellite; //1-STABILITY,2-ACCURACY,3-BOOT_FEATURE,4-AGE_RATE public DetectionHelper() { } #region 检测 #region 准确度 public void detecAccuracy(long deviceId, SerialPort port, DateTime endTime, bool isStartNow) { portAccuracy = port; devIdAccuracy = deviceId; int delay = 0; if (!isStartNow) { TimeSpan secondSpan = new TimeSpan(endTime.Ticks - DateTime.Now.Ticks); delay = secondSpan.Milliseconds; } timerAccuracy = new System.Threading.Timer(exeAccuracy, null, delay + 200 ,60000); } private void exeAccuracy(Object State) { while (true) { lock (obj) { if (!isUsing) { isUsing = true; string result = ""; double sum = 0.0; for (int i = 0; i < 3; i++) { string fre = getFrequencyData(portAccuracy); if (fre.Equals("")) { MessageBox.Show("从" + portAccuracy.PortName + "获取数据失败!"); return; } sum = sum + Convert.ToDouble(fre); detectionService.add(devIdAccuracy, fre, "2"); Thread.Sleep(1000); } result = sum / 3 + ""; detectionItemService.updateDetecStatus(devIdAccuracy, "", result, "", "", ""); deviceService.updateStatus(devIdAccuracy, "3", ""); timerAccuracy.Dispose(); isUsing = false; break; } } } } #endregion #region 稳定度 public void detecStability(long deviceId, DateTime startTime, string interval, SerialPort port, bool isStartNow) { portStability = port; devIdStability = deviceId; int delay = 0; if (!isStartNow) { TimeSpan secondSpan = new TimeSpan(startTime.Ticks - DateTime.Now.Ticks); delay = secondSpan.Milliseconds; } timerStability = new System.Threading.Timer(exeStability, null, delay + 100, Convert.ToInt32(interval)*1000); } private void exeStability(Object State) { while (true) { lock (obj) { if (!isUsing) { isUsing = true; LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "开始检测稳定度"); string result = ""; string fre = getFrequencyData(portStability); if (fre.Equals("")) { MessageBox.Show("从" + portStability.PortName + "获取数据失败!"); return; } resultStability.Add(fre); detectionService.add(devIdStability, fre, "1"); if (resultStability.Count == 101) { result = FreMath.Stable(resultStability) + ""; LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "稳定度检测结果:" + result); detectionItemService.updateDetecStatus(devIdStability, result, "", "", "", ""); List<DetectionItem> detectionItemList = detectionItemService.search(devIdStability, true); if (detectionItemList != null && detectionItemList.Count > 0) { DetectionItem detectionItem = detectionItemList[0]; if (!detectionItem.Stability.Equals("-1") && !detectionItem.Accuracy.Equals("-1") && !detectionItem.AgeRate.Equals("-1") && !detectionItem.BootFeature.Equals("-1")) { deviceService.updateStatus(devIdStability, "3", ""); } } timerStability.Dispose(); resultStability.Clear(); } isUsing = false; break; } } } } #endregion #region 开机特性 public void detecBootFeature(long deviceId, DateTime startTime, SerialPort port, bool isStartNow) { portBootFeature = port; devIdBootFeature = deviceId; int delay = 0; if (!isStartNow) { TimeSpan secondSpan = new TimeSpan(startTime.Ticks - DateTime.Now.Ticks); delay = secondSpan.Milliseconds; } timerBootFeature = new System.Threading.Timer(exeBootFeature, null, delay + 100, 60*60*1000); } private void exeBootFeature(Object State) { while (true) { lock (obj) { if (!isUsing) { LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "开始检测开机特性"); isUsing = true; string result = ""; double sum = 0.0; for (int i = 0; i < 3; i++) { string fre = getFrequencyData(portBootFeature); if (fre.Equals("")) { MessageBox.Show("从" + portBootFeature.PortName + "获取数据失败!"); return; } detectionService.add(devIdStability, fre, "3"); sum = sum + Convert.ToDouble(fre); } resultBootFeature.Add(sum / 3 + ""); if (resultBootFeature.Count == 8) { string max = "0.0"; string min = "0.0"; foreach (string fre in resultBootFeature) { if (Convert.ToDouble(fre) > Convert.ToDouble(max)) max = fre; if (Convert.ToDouble(fre) < Convert.ToDouble(min) || min.Equals("0.0")) min = fre; } result = (Convert.ToDouble(max) - Convert.ToDouble(min)) + ""; detectionItemService.updateDetecStatus(devIdBootFeature, "", "", result, "", ""); List<DetectionItem> detectionItemList = detectionItemService.search(devIdBootFeature, true); if (detectionItemList != null && detectionItemList.Count > 0) { DetectionItem detectionItem = detectionItemList[0]; if (!detectionItem.Stability.Equals("-1") && !detectionItem.Accuracy.Equals("-1") && !detectionItem.AgeRate.Equals("-1") && !detectionItem.BootFeature.Equals("-1")) { deviceService.updateStatus(devIdBootFeature, "3", ""); } } timerBootFeature.Dispose(); resultBootFeature.Clear(); } isUsing = false; break; } } } } #endregion #region 日老化率 public void detecAgeRate(long deviceId, DateTime startTime, SerialPort port, bool isStartNow) { portAgeRate = port; devIdAgeRate = deviceId; int delay = 0; if (!isStartNow) { TimeSpan secondSpan = new TimeSpan(startTime.Ticks - DateTime.Now.Ticks); delay = secondSpan.Milliseconds; } timerAgeRate = new System.Threading.Timer(exeAgeRate, null, delay + 100, 12 * 60 * 60 * 1000); } private void exeAgeRate(Object State) { while (true) { lock (obj) { if (!isUsing) { isUsing = true; LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "开始检测日老化率"); string result = ""; double sum = 0.0; for (int i = 0; i < 3; i++) { string fre = getFrequencyData(portAgeRate); if (fre.Equals("")) { MessageBox.Show("从" + portAgeRate.PortName + "获取数据失败!"); return; } detectionService.add(devIdStability, fre, "4"); sum = sum + Convert.ToDouble(fre); } resultAgeRate.Add(sum / 3 + ""); if (resultAgeRate.Count == 15) { double r = 0.0; double k = FreMath.DriftRate(resultAgeRate, out r); result = k + "," + r; LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "日老化率检测结果:" + result); detectionItemService.updateDetecStatus(devIdAgeRate, "", "", "", result, ""); List<DetectionItem> detectionItemList = detectionItemService.search(devIdAgeRate, true); if (detectionItemList != null && detectionItemList.Count > 0) { DetectionItem detectionItem = detectionItemList[0]; if (!detectionItem.Stability.Equals("-1") && !detectionItem.Accuracy.Equals("-1") && !detectionItem.AgeRate.Equals("-1") && !detectionItem.BootFeature.Equals("-1")) { deviceService.updateStatus(devIdAgeRate, "3", ""); } } timerAgeRate.Dispose(); resultAgeRate.Clear(); } isUsing = false; break; } } } } #endregion #endregion public SerialPort portOpen(string portName, int bandRate) { try { LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, portName + " " + bandRate); SerialPort port = new SerialPort(); // 搜索串口 string[] names = SerialPort.GetPortNames(); if (names.Length == 0 || Array.IndexOf(names, portName) == -1) { return null; } // 设置串口参数 port.PortName = portName; port.BaudRate = bandRate; port.Parity = Parity.None; port.DataBits = 8; port.StopBits = StopBits.One; port.Handshake = Handshake.None; port.ReadTimeout = -1; port.WriteTimeout = 3000; // 打开串口 if (!port.IsOpen) { port.Open(); } if (port.IsOpen) { LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "打开串口成功!"); return port; } return null; } catch (Exception ex) { LogHelper.WriteInfoLog(MethodBase.GetCurrentMethod().DeclaringType, "打开串口失败!" + ex.Message); return null; } } // 获取检测数据 public string getFrequencyData(SerialPort port) { //lock(obj) //isUsing = true; try { if(port.IsOpen)LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "portname:"+port.PortName); else LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "port closed"); string received = ""; if (ConfigHelper.GetAppConfig("deviceType").ToString().Equals("1")) { int count = 0; while (count < 5) { int readLen = port.BytesToRead; if (readLen > 0) { byte[] buffer = new byte[readLen]; port.Read(buffer, 0, readLen);// 接收数据到buffer里面 string data = Encoding.ASCII.GetString(buffer); string[] dataArray = data.Split(' '); if (data.StartsWith("$") && dataArray.Length == 2 && data.LastIndexOf('$') == 0) { received = dataArray[0].Replace("$", "") + "." + data.Split(' ')[1].Replace(".", "").TrimEnd('0'); break; } } count++; } } else { LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "开始获取测量值2"); int count = 0; while (count < 10000) { int readLen = port.BytesToRead; LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "readLen=" + readLen); if (readLen > 0) { byte[] buffer = new byte[readLen]; port.Read(buffer, 0, readLen);// 接收数据到buffer里面 string data = Encoding.ASCII.GetString(buffer); string[] dataArray = data.Split(' '); if (dataArray.Length >= 3) { foreach (string sss in dataArray) { if (sss.Contains("E")) { received = sss; //received = float.Parse(received)+""; LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "获取测量值2:" + received + ":" + data); break; } } if (!received.Equals("")) break; } } count++; } } //isUsing = false; return received; } catch (Exception ex) { LogHelper.WriteErrorLog(MethodBase.GetCurrentMethod().DeclaringType, "错误:" + ex.Message); return ""; } } // 获取铷钟数据 public void startClockFresh() { timerClock = new System.Threading.Timer(exeClock, null, 50, 60 * 1000); } public void exeClock(Object State) { string portName = ConfigHelper.GetAppConfig("clock").Split(' ')[0]; int bandRate = Convert.ToInt32(ConfigHelper.GetAppConfig("clock").Split(' ')[1]); SerialPort port = portOpen(portName, bandRate); if (port == null) { MessageBox.Show("无法打开串口"+portName+",原子钟状态获取失败!"); return; } int count = 0; string clockStatus = ""; while (count < 5) { int Readlen = port.BytesToRead; // 接收到数据 if (Readlen > 0) { byte[] buffer = new byte[Readlen]; port.Read(buffer, 0, Readlen);// 接收数据到buffer里面 string data = Encoding.ASCII.GetString(buffer); if (data.StartsWith("$") && data.Contains("*")) { string clockStatusCode = data.Split(',')[9]; switch (clockStatusCode) { case "1": clockStatus = "预热"; break; case "2": clockStatus = "自由运动"; break; case "3": clockStatus = "捕获"; break; case "4": clockStatus = "快锁"; break; case "5": clockStatus = "慢锁"; break; case "7": clockStatus = "保持"; break; default: break; } break; } } count++; } HomeCtrlForm.homeCtrlForm.label_clockStatus.Text = clockStatus; StatusCtrlForm.statusCtrlForm.label_clockStatus.Text = clockStatus; } // 获取卫星RMC数据 public void startSatelliteFresh() { timerSatellite = new System.Threading.Timer(exeSatellite, null, 50, 60 * 1000); } public void exeSatellite(Object State) { List<string> gpList = new List<string>(); List<string> bdList = new List<string>(); // RMC string portName = ConfigHelper.GetAppConfig("satellite").Split(' ')[0]; int bandRate = Convert.ToInt32(ConfigHelper.GetAppConfig("clock").Split(' ')[1]); SerialPort port = portOpen(portName, bandRate); if (port == null) { MessageBox.Show("无法打开串口" + portName + ",卫星数据获取失败!"); return; } int count = 0; while (count < 5) { int Readlen = port.BytesToRead; if (Readlen > 0) { byte[] buffer = new byte[Readlen]; port.Read(buffer, 0, Readlen);// 接收数据到buffer里面 string data = Encoding.ASCII.GetString(buffer); string[] dataArray = data.Split('$'); if (dataArray.Length > 0) { foreach (string sss in dataArray) { if (sss.Contains("GPGGA") && sss.Contains("*")) { string[] resultArray = sss.Split(','); string lat = resultArray[2].Replace(".", "").Insert(2, ".") + resultArray[3]; string lng = resultArray[4].Replace(".", "").Insert(2, ".") + resultArray[5]; string x = parseGGA(sss).Split(',')[0]; string y = parseGGA(sss).Split(',')[1]; string z = parseGGA(sss).Split(',')[2]; new Thread(() => { StatusCtrlForm.statusCtrlForm.label_lat.Text = lat; StatusCtrlForm.statusCtrlForm.label_lng.Text = lng; StatusCtrlForm.statusCtrlForm.label_x.Text = x; StatusCtrlForm.statusCtrlForm.label_y.Text = y; StatusCtrlForm.statusCtrlForm.label_z.Text = z; }).Start(); } if (sss.Contains("GNRMC") && sss.Contains("*")) { string[] resultArray = sss.Split(','); string date = resultArray[9]; date = date.Substring(4, 2) + "-" + date.Substring(2, 2) + "-" + date.Substring(0, 2); string mjd = getMJD(date.Substring(4, 2), date.Substring(2, 2), date.Substring(0, 2)); string time = resultArray[1]; time = time.Substring(0, 2) + ":" + time.Substring(2, 2) + ":" + time.Substring(4); string status = resultArray[2] == "A" ? "定位有效" : "警告"; new Thread(() => { StatusCtrlForm.statusCtrlForm.label_date.Text = date; StatusCtrlForm.statusCtrlForm.label_time.Text = time; StatusCtrlForm.statusCtrlForm.label_receiverStatus.Text = status; StatusCtrlForm.statusCtrlForm.label_mjd.Text = mjd; HomeCtrlForm.homeCtrlForm.label_receiverStatus.Text = status; }).Start(); } if (sss.Contains("GPGSV") || sss.Contains("BDGSV")) { if (sss.Split(',')[2].Equals("1")) { int totalGP = 0; int totalBD = 0; if (sss.Contains("GPGSV")) { gpList.Add(sss); totalGP = Convert.ToInt32(sss.Split(',')[1]); } else { bdList.Add(sss); totalBD = Convert.ToInt32(sss.Split(',')[1]); } for (int i = 2; i <= (totalGP==0? totalBD: totalGP); i++) { Thread.Sleep(1000); int count2 = 0; while (count2 < 5) { Readlen = port.BytesToRead; if (Readlen > 0) { buffer = new byte[Readlen]; port.Read(buffer, 0, Readlen);// 接收数据到buffer里面 data = Encoding.ASCII.GetString(buffer); dataArray = data.Split('$'); if (dataArray.Length > 0) { foreach (string s in dataArray) { if (s.Contains("GPGSV")) { if (sss.Split(',')[2].Equals(i + "")) { if (sss.Contains("GPGSV")) { gpList.Add(sss); if (gpList.Count == totalGP) { new Thread(() => { StatusCtrlForm.statusCtrlForm.label_usaTotal.Text = totalGP + ""; draw(gpList, "USA"); }).Start(); } } else { bdList.Add(sss); if (bdList.Count == totalBD) { new Thread(() => { StatusCtrlForm.statusCtrlForm.label_chnTotal.Text = totalBD + ""; draw(bdList, "CHN"); }).Start(); } } break; } } } } } count2++; } } } } } } break; } count++; } } private string getMJD(string ys, string ms, string ds) { int y = Convert.ToInt32(ys) - 1900; int m = Convert.ToInt32(ms); int d = Convert.ToInt32(ds); int L = 0; if (m == 1 || m == 2) L = 1; int njdINT = 14956 + d +(int)((y-L)*365.25)+(int)((m+1+L*12)*30.6001); return njdINT+""; } private string parseGGA(string ggaStr) { double f = 1 / 298.257223563; /*基准椭球体的极扁率*/ double a = 6378137.0; /*基准椭球体的长半径*/ double b = 6356752.314; /*基准椭球体的短半径*/ double e2 = f * (2 - f); /*基准椭球体的偏心率*/ double pi_180 = Math.PI / 180; //$GPGGA,081918.00,3954.7889938,N,11615.5667600,E,1,28,0.68,78.6748,M,-9.7970,M,02,*7D var arr = ggaStr.Split(','); string m_pBs = parseCoord(arr[2], arr[3]); string m_pLs = parseCoord(arr[4], arr[5]); string m_pHs = Convert.ToDouble(arr[9]) + Convert.ToDouble(arr[11]) + "";// add 大地水准面高度 纠正误差 // objBLH.b = util.parseCoord(arr[2],arr[3]); // objBLH.l = util.parseCoord(arr[4],arr[5]); // objBLH.h = parseFloat(arr[9]); string X = "", Y = "", Z = ""; double m_pB = Convert.ToDouble(m_pBs); double m_pL = Convert.ToDouble(m_pLs); double m_pH = Convert.ToDouble(m_pHs); double N = a / Math.Sqrt(1 - e2 * Math.Sin(m_pB * pi_180) * Math.Sin(m_pB * Math.PI)); X = (N + m_pH) * Math.Cos(m_pB * pi_180) * Math.Cos(m_pL * Math.PI) + ""; Y = (N + m_pH) * Math.Cos(m_pB * pi_180) * Math.Sin(m_pL * Math.PI) + ""; Z = (N * (1 - e2) + m_pH) * Math.Sin(m_pB * pi_180) + ""; return X + "," + Y + "," + Z; } private string parseCoord (string coord, string dir) { //$GPGGA,081918.00,3954.7889938,N,11615.5667600,E,1,28,0.68,78.6748,M,-9.7970,M,02,*7D if ( coord.Equals("")) return null; int n=1, sgn = 1; switch (dir) { case "S": sgn = -1; break; case "N": n = 2;break; case "W": sgn = -1; break; case "E": n = 3; break; default: break; } return sgn * (Convert.ToDouble(coord.Substring(0, n)) + Convert.ToDouble(coord.Substring(n)) / 60) + ""; } private string BLH2XYX (string objectBLH) { // var objectBLH ={l:116.259446,b:39.91314989666667,h:78.6748};//for test // var N = a / Math.sqrt(1 - e2 * Math.sin(objectBLH.b * pi_180) * Math.sin(objectBLH.b * pi_180)); // var X = (N + objectBLH.h) * Math.cos(objectBLH.b * pi_180) * Math.cos(objectBLH.l * pi_180); // var Y = (N + objectBLH.h) * Math.cos(objectBLH.b * pi_180) * Math.sin(objectBLH.l * pi_180); // var Z = [N * (1 - e2 ) + objectBLH.h] * Math.sin(objectBLH.b * pi_180); // var objectXYZ = {}; // objectXYZ.X = X; // objectXYZ.Y = Y; // objectXYZ.Z = Z; string X="", Y="", Z = ""; double m_pB = Convert.ToDouble(objectBLH.Split(',')[0]); double m_pL = Convert.ToDouble(objectBLH.Split(',')[1]); double m_pH = Convert.ToDouble(objectBLH.Split(',')[2]); //double N = a / Math.Sqrt(1 - e2 * Math.Sin(m_pB * pi_180) * Math.Sin(m_pB * Math.PI)); //X = (N + m_pH) * Math.Cos(m_pB * pi_180) * Math.Cos(m_pL * Math.PI); //Y = (N + m_pH) * Math.Cos(m_pB * pi_180) * Math.Sin(m_pL * Math.PI); //Z = [N * (1 - e2) + m_pH] * Math.Sin(m_pB * pi_180); return X+","+Y+","+Z; } private void draw(List<string> gsvList, string type) { foreach (string gsv in gsvList) { string[] arr = gsv.Split(','); int length = arr.Count(); for (int i = 4; i < arr.Length; i=i+3) { if ((i + 3) < arr.Length) { int Elevation = Convert.ToInt32(arr[i + 1]); int azimuth = Convert.ToInt32(arr[i + 2]); double cosLen = Math.Cos(Elevation * Math.PI / 180) * (585 / 2); double xCor = Math.Cos(azimuth * Math.PI / 180) * cosLen; double yCor = Math.Sin(azimuth * Math.PI / 180) * cosLen; int x = (int)Math.Floor(610 / 2 + xCor); int y = (int)Math.Floor(610 / 2 - yCor); Graphics gp = StatusCtrlForm.coo.CreateGraphics(); gp.SmoothingMode = SmoothingMode.HighQuality; gp.DrawImage((Bitmap)Resources.ResourceManager.GetObject(type), x, y); } } } } } }