AirScout/AirScout/MapDlg.cs

7102 wiersze
329 KiB
C#
Czysty Wina Historia

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

// AirScout Aircraft Scatter Prediction
// Copyright (C) DL2ALF
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Drawing.Imaging;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Forms;
using System.Windows.Forms.VisualStyles;
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.WindowsForms;
using GMap.NET.WindowsForms.Markers;
using GMap.NET.WindowsForms.ToolTips;
using System.IO;
using System.IO.Ports;
using System.Net;
using System.Net.Sockets;
using System.Threading;
using Zeptomoby.OrbitTools;
using System.Globalization;
using System.Runtime.InteropServices;
using System.Reflection;
using System.Configuration;
using WinTest;
using Renci.SshNet;
using System.Diagnostics;
using AquaControls;
using AirScout.Core;
using AirScout.PlaneFeeds.Generic;
using AirScout.Aircrafts;
using NDde;
using NDde.Server;
using NDde.Client;
using ScoutBase;
using ScoutBase.Core;
using ScoutBase.Elevation;
using ScoutBase.Stations;
using ScoutBase.Propagation;
using SerializableGenerics;
using Ionic.Zip;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
using SQLiteDatabase;
using System.Xml;
using System.Xml.Serialization;
using System.Security.Cryptography;
using OxyPlot;
using OxyPlot.WindowsForms;
using OxyPlot.Series;
using OxyPlot.Axes;
using System.Data.SQLite;
using AirScout.AircraftPositions;
using AirScout.Signals;
namespace AirScout
{
public partial class MapDlg : Form
{
[CategoryAttribute("Directories")]
[DescriptionAttribute("Application Directory")]
public string AppDirectory
{
get
{
return Application.StartupPath.TrimEnd(Path.DirectorySeparatorChar).Replace('\\', Path.DirectorySeparatorChar);
}
}
[CategoryAttribute("Directories")]
[DescriptionAttribute("Local Application Data Directory")]
public string AppDataDirectory
{
get
{
return Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), Application.CompanyName, Application.ProductName).TrimEnd(Path.DirectorySeparatorChar);
}
}
[CategoryAttribute("Directories")]
[DescriptionAttribute("Logfile Directory")]
public string LogDirectory
{
get
{
// get Property
string logdir = Properties.Settings.Default.Log_Directory;
// replace Windows/Linux directory spearator chars
logdir = logdir.Replace('\\', Path.DirectorySeparatorChar);
logdir = logdir.Replace('/', Path.DirectorySeparatorChar);
// set to default value if empty
if (String.IsNullOrEmpty(logdir))
logdir = "Log";
// replace variables, if any
logdir = VC.ReplaceAllVars(logdir);
// remove directory separator chars at begin and end
logdir = logdir.TrimStart(Path.DirectorySeparatorChar);
logdir = logdir.TrimEnd(Path.DirectorySeparatorChar);
// fully qualify path
if (!logdir.Contains(Path.VolumeSeparatorChar))
logdir = Path.Combine(AppDataDirectory, logdir);
return logdir;
}
}
[CategoryAttribute("Directories")]
[DescriptionAttribute("Tempfile Directory")]
public string TmpDirectory
{
get
{
// get Property
string tmpdir = Properties.Settings.Default.Tmp_Directory;
// replace Windows/Linux directory spearator chars
tmpdir = tmpdir.Replace('\\', Path.DirectorySeparatorChar);
tmpdir = tmpdir.Replace('/', Path.DirectorySeparatorChar);
// set to default value if empty
if (String.IsNullOrEmpty(tmpdir))
tmpdir = "Tmp";
// replace variables, if any
tmpdir = VC.ReplaceAllVars(tmpdir);
// remove directory separator chars at begin and end
tmpdir = tmpdir.TrimStart(Path.DirectorySeparatorChar);
tmpdir = tmpdir.TrimEnd(Path.DirectorySeparatorChar);
// fully qualify path
if (!tmpdir.Contains(Path.VolumeSeparatorChar))
tmpdir = Path.Combine(AppDataDirectory, tmpdir);
return tmpdir;
}
}
[CategoryAttribute("Directories")]
[DescriptionAttribute("Database Directory")]
public string DatabaseDirectory
{
get
{
// get Property
string databasedir = Properties.Settings.Default.Database_Directory;
// replace Windows/Linux directory spearator chars
databasedir = databasedir.Replace('\\', Path.DirectorySeparatorChar);
databasedir = databasedir.Replace('/', Path.DirectorySeparatorChar);
// set to default value if empty
if (String.IsNullOrEmpty(databasedir))
databasedir = "Database";
// replace variables, if any
databasedir = VC.ReplaceAllVars(databasedir);
// remove directory separator chars at begin and end
databasedir = databasedir.TrimStart(Path.DirectorySeparatorChar);
databasedir = databasedir.TrimEnd(Path.DirectorySeparatorChar);
// fully qualify path
if (!databasedir.Contains(Path.VolumeSeparatorChar))
databasedir = Path.Combine(AppDataDirectory, databasedir);
return databasedir;
}
}
[CategoryAttribute("Directories")]
[DescriptionAttribute("Icon Directory")]
public string IconDirectory
{
get
{
// get Property
string icondir = Properties.Settings.Default.Icon_Directory;
// replace Windows/Linux directory spearator chars
icondir = icondir.Replace('\\', Path.DirectorySeparatorChar);
icondir = icondir.Replace('/', Path.DirectorySeparatorChar);
// set to default value if empty
if (String.IsNullOrEmpty(icondir))
icondir = "Icon";
// replace variables, if any
icondir = VC.ReplaceAllVars(icondir);
// remove directory separator chars at begin and end
icondir = icondir.TrimStart(Path.DirectorySeparatorChar);
icondir = icondir.TrimEnd(Path.DirectorySeparatorChar);
// fully qualify path
if (!icondir.Contains(Path.VolumeSeparatorChar))
icondir = Path.Combine(AppDataDirectory, icondir);
return icondir;
}
}
[CategoryAttribute("Directories")]
[DescriptionAttribute("Elevation Directory")]
public string ElevationDirectory
{
get
{
// get Property
string elevationdir = Properties.Settings.Default.Elevation_Directory;
// replace Windows/Linux directory spearator chars
elevationdir = elevationdir.Replace('\\', Path.DirectorySeparatorChar);
elevationdir = elevationdir.Replace('/', Path.DirectorySeparatorChar);
// set to default value if empty
if (String.IsNullOrEmpty(elevationdir))
elevationdir = "elevation";
// replace variables, if any
elevationdir = VC.ReplaceAllVars(elevationdir);
// remove directory separator chars at begin and end
elevationdir = elevationdir.TrimStart(Path.DirectorySeparatorChar);
elevationdir = elevationdir.TrimEnd(Path.DirectorySeparatorChar);
// fully qualify path
if (!elevationdir.Contains(Path.VolumeSeparatorChar))
elevationdir = Path.Combine(AppDataDirectory, elevationdir);
return elevationdir;
}
}
public static LogWriter Log;
public VarConverter VC = new VarConverter();
private int cntdn = 0;
DateTime CurrentTime = DateTime.UtcNow;
public bool ForceClose = false;
// FlightRadar
PlaneInfoCache Planes = new PlaneInfoCache();
SortedList<string, PlaneInfo> ActivePlanes = new SortedList<string, PlaneInfo>();
private DateTime History_OldestEntry = DateTime.MinValue;
private DateTime History_YoungestEntry = DateTime.MinValue;
private List<string> SelectedPlanes = new List<string>();
// Path
public List<ElevationPathDesignator> ElevationPaths = new List<ElevationPathDesignator>();
public List<PropagationPathDesignator> PropagationPaths = new List<PropagationPathDesignator>();
// Map
// Overlays
GMapOverlay gmo_Routes = new GMapOverlay("Routes");
GMapOverlay gmo_PropagationPaths = new GMapOverlay("PropagationPaths");
GMapOverlay gmo_Objects = new GMapOverlay("Objects");
GMapOverlay gmo_Planes = new GMapOverlay("Planes");
GMapOverlay gmo_Airports = new GMapOverlay("Airports");
GMapOverlay gmo_Callsigns = new GMapOverlay("Callsigns");
GMapOverlay gmo_NearestPaths = new GMapOverlay("PropagationPaths");
GMapOverlay gmo_NearestPlanes = new GMapOverlay("Planes");
// Routes
GMapRoute gmr_FullPath;
GMapRoute gmr_VisiblePpath;
GMapRoute gmr_NearestFull;
GMapRoute gmr_NearestVisible;
// Markers
GMapMarker gmm_MyLoc;
GMapMarker gmm_DXLoc;
GMapMarker gmm_CurrentMarker;
bool isDraggingMarker;
// Bitmap indices
private int bmindex_darkorange;
private int bmindex_lightgreen;
private int bmindex_red;
private int bmindex_gray;
private int bmindex_magenta;
// Tooltip font
public Font ToolTipFont;
// right control boxes
int gb_Map_Info_Width = 0;
int gb_Map_Info_MaximizedHeight = 0;
int gb_Map_Zoom_MaximizedHeight = 0;
int gb_Map_Filter_MaximizedHeigth = 0;
int gb_Map_Alarms_MaximizedHeight = 0;
int gb_Map_Info_MinimizedHeight = 0;
int gb_Map_Zoom_MinimizedHeight = 0;
int gb_Map_Filter_MinimizedHeigth = 0;
int gb_Map_Alarms_MinimizedHeight = 0;
int CurrentMapSplitterDistance = 0;
// Plane feeds
public ArrayList PlaneFeeds;
public PlaneFeed bw_PlaneFeed1;
public PlaneFeed bw_PlaneFeed2;
public PlaneFeed bw_PlaneFeed3;
// Startup
private bool FirstRun = true;
private bool CleanRun = false;
private Splash SplashDlg = new Splash();
// Background workers
public ElevationDatabaseUpdater bw_GLOBEUpdater = new ElevationDatabaseUpdater();
public ElevationDatabaseUpdater bw_SRTM3Updater = new ElevationDatabaseUpdater();
public ElevationDatabaseUpdater bw_SRTM1Updater = new ElevationDatabaseUpdater();
public StationDatabaseUpdater bw_StationDatabaseUpdater = new StationDatabaseUpdater();
public AircraftDatabaseUpdater bw_AircraftDatabaseUpdater = new AircraftDatabaseUpdater();
public AircraftPositionDatabaseMaintainer bw_AircraftDatabaseMaintainer = new AircraftPositionDatabaseMaintainer();
public PathCalculator bw_GLOBEPathCalculator = new PathCalculator(ELEVATIONMODEL.GLOBE);
public PathCalculator bw_SRTM3PathCalculator = new PathCalculator(ELEVATIONMODEL.SRTM3);
public PathCalculator bw_SRTM1PathCalculator = new PathCalculator(ELEVATIONMODEL.SRTM1);
// Modes
AIRSCOUTPATHMODE PathMode = AIRSCOUTPATHMODE.NONE;
AIRSCOUTLIFEMODE LifeMode = AIRSCOUTLIFEMODE.NONE;
AIRSCOUTPLAYMODE PlayMode = AIRSCOUTPLAYMODE.NONE;
private int Time_Offline_Interval = 0;
// charting
// path chart
PlotModel pm_Path = new PlotModel();
PlotView pv_Path = new PlotView();
LinearAxis Path_X = new LinearAxis();
LinearAxis Path_Y = new LinearAxis();
AreaSeries Path_Elevation = new AreaSeries();
LineSeries Min_H1 = new LineSeries();
LineSeries Min_H2 = new LineSeries();
LineSeries Max_H = new LineSeries();
AreaSeries Min_H = new AreaSeries();
LineSeries Planes_Hi = new LineSeries();
LineSeries Planes_Lo = new LineSeries();
// elevation chart
PlotModel pm_Elevation = new PlotModel();
PlotView pv_Elevation = new PlotView();
LinearAxis Elevation_X = new LinearAxis();
LinearAxis Elevation_Y = new LinearAxis();
AreaSeries Elevation = new AreaSeries();
LineSeries LOS = new LineSeries();
// spectrum chart
PlotModel pm_Spectrum = new PlotModel();
PlotView pv_Spectrum = new PlotView();
LinearAxis Spectrum_X = new LinearAxis();
LinearAxis Spectrum_Y = new LinearAxis();
LineSeries Spectrum = new LineSeries();
AreaSeries SpectrumRecord = new AreaSeries();
int SpectrumPointsCount = 0;
int SpectrumMaxPoints = 600;
// webbrowser
private System.Windows.Forms.WebBrowser wb_News = null;
CultureInfo LocalCulture;
// Watchlist control
private bool WatchlistUpdating = false;
private bool WatchlistAllCheckedChanging = false;
bool WatchlistAllChecked = false;
CheckBoxState WatchlistAllCheckedState = CheckBoxState.UncheckedNormal;
System.Drawing.Point WatchlistOldMousePos = new System.Drawing.Point(0, 0);
// Analysis
private List<DateTime> AllLastUpdated = new List<DateTime>();
private List<AircraftPositionDesignator> AllPositions = new List<AircraftPositionDesignator>();
private long AircraftPositionsCount = 0;
// nearest plane
private PlaneInfo NearestPlane = null;
// Airports
private List<AirportDesignator> Airports = new List<AirportDesignator>();
#region Startup & Initialization
public MapDlg()
{
// save current local LocalCulture
LocalCulture = Application.CurrentCulture;
// force culture invariant language for GUI
Application.CurrentCulture = CultureInfo.InvariantCulture;
InitializeComponent();
// do basic initialization
this.Text = "AirScout - Aircraft Scatter Prediction V" + Application.ProductVersion + " (c) 2013-2018 DL2ALF";
// create a new renderer wich is clipping the status text on overflow
ss_Main.Renderer = new ClippingToolStripRenderer();
// initialize settings
InitializeSettings();
// initialize charting
InitializeCharts();
// Initilialize Webbrowser
InitializeWebbrowser();
// check for command line args
string[] args = Environment.GetCommandLineArgs();
if ((args != null) && (args.Count() > 1))
{
// try to clean installation & database
if ((args[1].ToUpper() == "/CLEAN") ||
(args[1].ToUpper() == "-CLEAN"))
{
CleanupDlg Dlg = new CleanupDlg(this);
DialogResult result = Dlg.ShowDialog();
// exit immediately if user closes the form without pressing a button
if (result == DialogResult.Abort)
System.Environment.Exit(-1);
if (result == DialogResult.OK)
CleanRun = true;
}
}
// set elevation database update event handler
bw_GLOBEUpdater.ProgressChanged += new ProgressChangedEventHandler(bw_ElevationDatabaseUpdater_ProgressChanged);
bw_SRTM3Updater.ProgressChanged += new ProgressChangedEventHandler(bw_ElevationDatabaseUpdater_ProgressChanged);
bw_SRTM1Updater.ProgressChanged += new ProgressChangedEventHandler(bw_ElevationDatabaseUpdater_ProgressChanged);
// set station database updater event handler
bw_StationDatabaseUpdater.ProgressChanged += new ProgressChangedEventHandler(bw_StationDatabaseUpdater_ProgressChanged);
bw_StationDatabaseUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_StationDatabaseUpdater_RunWorkerCompleted);
// set aircraft database updater event handler
bw_AircraftDatabaseUpdater.ProgressChanged += new ProgressChangedEventHandler(bw_AircraftDatabaseUpdater_ProgressChanged);
bw_AircraftDatabaseUpdater.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_AircraftDatabaseUpdater_RunWorkerCompleted);
// set aircraft database maintainer event handler
bw_AircraftDatabaseMaintainer.ProgressChanged += new ProgressChangedEventHandler(bw_AircraftDatabaseMaintainer_ProgressChanged);
bw_AircraftDatabaseMaintainer.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bw_AircraftDatabaseMaintainer_RunWorkerCompleted);
// set elevation path calculator event handler
bw_GLOBEPathCalculator.ProgressChanged += new ProgressChangedEventHandler(bw_ElevationPathCalculator_ProgressChanged);
bw_SRTM3PathCalculator.ProgressChanged += new ProgressChangedEventHandler(bw_ElevationPathCalculator_ProgressChanged);
bw_SRTM1PathCalculator.ProgressChanged += new ProgressChangedEventHandler(bw_ElevationPathCalculator_ProgressChanged);
// save FirstRun property before trying to upgrade user settings
FirstRun = Properties.Settings.Default.FirstRun;
}
public void CheckDirectories()
{
// check if directories exist
if (!Directory.Exists(TmpDirectory))
Directory.CreateDirectory(TmpDirectory);
if (!Directory.Exists(LogDirectory))
Directory.CreateDirectory(LogDirectory);
if (!Directory.Exists(IconDirectory))
Directory.CreateDirectory(IconDirectory);
if (!Directory.Exists(DatabaseDirectory))
Directory.CreateDirectory(DatabaseDirectory);
if (!Directory.Exists(ElevationDirectory))
Directory.CreateDirectory(ElevationDirectory);
}
/// <summary>
/// Returns the default value of a property
/// </summary>
/// <param name="propertyname">The property name.</param>
/// <returns>The property value.</returns>
public static dynamic GetPropertyDefaultValue(string propertyname)
{
string p = (string)Properties.Settings.Default.Properties[propertyname].DefaultValue;
Type t = Properties.Settings.Default.Properties[propertyname].PropertyType;
return Convert.ChangeType(p, t);
}
private void InitializeSettings()
{
// check for invalid settings
// check if band is BNONE --> set to 1.2G
if (Properties.Settings.Default.Band == BAND.BNONE)
Properties.Settings.Default.Band = BAND.B1_2G;
// chekc if band settings are NULL --> set to default
if (Properties.Settings.Default.Path_Band_Settings == null)
Properties.Settings.Default.Path_Band_Settings = new BandSettings(true);
// check if watchlist in null --> create new
if (Properties.Settings.Default.Watchlist == null)
Properties.Settings.Default.Watchlist = new Watchlist();
string location = StationData.Database.GetDBLocation();
// check calls
if (String.IsNullOrEmpty(Properties.Settings.Default.MyCall))
Properties.Settings.Default.MyCall = GetPropertyDefaultValue(nameof(Properties.Settings.Default.MyCall));
if (String.IsNullOrEmpty(Properties.Settings.Default.DXCall))
Properties.Settings.Default.DXCall = GetPropertyDefaultValue(nameof(Properties.Settings.Default.DXCall));
// check lat/lon
if (!GeographicalPoint.Check(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon))
{
Properties.Settings.Default.MyLat = GetPropertyDefaultValue(nameof(Properties.Settings.Default.MyLat));
Properties.Settings.Default.MyLon = GetPropertyDefaultValue(nameof(Properties.Settings.Default.MyLon));
}
if (!GeographicalPoint.Check(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon))
{
Properties.Settings.Default.DXLat = GetPropertyDefaultValue(nameof(Properties.Settings.Default.DXLat));
Properties.Settings.Default.DXLon = GetPropertyDefaultValue(nameof(Properties.Settings.Default.DXLon));
}
// set current elevation model
SetElevationModel();
// set antenna height to 10m be default
Properties.Settings.Default.MyHeight = 10;
Properties.Settings.Default.DXHeight = 10;
}
private void CheckSettings()
{
Log.WriteMessage("Checking properties...");
// check for empty MyCalls list
if (Properties.Settings.Default.MyCalls == null)
{
Properties.Settings.Default.MyCalls = new List<string>();
Properties.Settings.Default.MyCalls.Add("DL2ALF");
}
if (Properties.Settings.Default.MyCalls.Count == 0)
Properties.Settings.Default.MyCalls.Add("DL2ALF");
// list all properties in log
foreach (SettingsPropertyValue p in Properties.Settings.Default.PropertyValues)
{
if ((p != null) && (p.Name != null))
{
string value = p.PropertyValue != null ? p.PropertyValue.ToString() : "[null]";
Log.WriteMessage("Checking property " + p.Name + " = " + value);
}
}
/*
// check URLs for trailing separator
if (!Properties.Settings.Default.Elevation_GLOBE_URL.EndsWith("/"))
Properties.Settings.Default.Elevation_GLOBE_URL = Properties.Settings.Default.Elevation_GLOBE_URL + "/";
if (!Properties.Settings.Default.Elevation_SRTM3_URL.EndsWith("/"))
Properties.Settings.Default.Elevation_SRTM3_URL = Properties.Settings.Default.Elevation_SRTM3_URL + "/";
if (!Properties.Settings.Default.Elevation_SRTM1_URL.EndsWith("/"))
Properties.Settings.Default.Elevation_SRTM1_URL = Properties.Settings.Default.Elevation_SRTM1_URL + "/";
if (!Properties.Settings.Default.StationDatabase_Update_URL.EndsWith("/"))
Properties.Settings.Default.StationDatabase_Update_URL = Properties.Settings.Default.StationDatabase_Update_URL + "/";
*/
Log.WriteMessage("Checking properties finished...");
}
private void CheckInternet()
{
// check internet connectivity
try
{
using (var client = new WebClient())
{
string url = Properties.Settings.Default.Connectivity_URL;
using (var stream = client.OpenRead(url))
{
}
}
}
catch
{
MessageBox.Show("Could not find an internet connection.\nThis is required on first run.\nAirScout will close.", "Internet connectivity");
this.Close();
}
}
private void InitializeLogfile()
{
// set directories and formats for logfile
ScoutBase.Core.Properties.Settings.Default.LogWriter_Directory = LogDirectory;
ScoutBase.Core.Properties.Settings.Default.LogWriter_FileFormat = "AirScout_{0:yyyy_MM_dd}.log";
ScoutBase.Core.Properties.Settings.Default.LogWriter_MessageFormat = "{0:u} {1}";
// gets an instance of a LogWriter
Log = LogWriter.Instance;
Log.WriteMessage("-------------------------------------------------------------------------------------");
Log.WriteMessage(Application.ProductName + " is starting up.", 0, false);
Log.WriteMessage("-------------------------------------------------------------------------------------");
Log.WriteMessage("Operating system : " + Environment.OSVersion.Platform);
Log.WriteMessage("Application directory : " + AppDirectory);
Log.WriteMessage("Application data directory: " + AppDataDirectory);
Log.WriteMessage("Log directory : " + LogDirectory);
Log.WriteMessage("Temp directory : " + TmpDirectory);
Log.WriteMessage("Database directory : " + DatabaseDirectory);
Log.WriteMessage("Elevation directory : " + ElevationDirectory);
Log.WriteMessage("Application settings file : " + AppDomain.CurrentDomain.SetupInformation.ConfigurationFile);
Log.WriteMessage("User settings file : " + GetUserSettingsPath());
Log.WriteMessage("Disk space available : " + SupportFunctions.GetDriveAvailableFreeSpace(Path.GetPathRoot(AppDataDirectory)) / 1024 / 1024 + " MB");
Log.WriteMessage("-------------------------------------------------------------------------------------");
}
private void InitializeDatabase()
{
Log.WriteMessage("Started.");
SetElevationModel();
// reset database status
Properties.Settings.Default.Elevation_GLOBE_DatabaseStatus = DATABASESTATUS.UNDEFINED;
Properties.Settings.Default.Elevation_SRTM3_DatabaseStatus = DATABASESTATUS.UNDEFINED;
Properties.Settings.Default.Elevation_SRTM1_DatabaseStatus = DATABASESTATUS.UNDEFINED;
// set nearfield suppression
PropagationData.Database.NearFieldSuppression = Properties.Settings.Default.Path_NearFieldSuppression;
Log.WriteMessage("Finished.");
}
private void MapDlg_Load(object sender, EventArgs e)
{
try
{
// Show splash screen
SplashDlg.Show();
// bring window to front
SplashDlg.BringToFront();
Application.DoEvents();
// Check directories, complete it and create, if not exist
SplashDlg.Status("Checking directories...");
CheckDirectories();
// start a log, specify format of logfile and entries
SplashDlg.Status("Initializing logfile...");
InitializeLogfile();
// Check properties
SplashDlg.Status("Checking settings...");
CheckSettings();
// get AirScout password phrase
InitializePassword();
// Initialize database
SplashDlg.Status("Initializing database...");
InitializeDatabase();
// initialize icons
SplashDlg.Status("Creating icons...");
InitializeIcons();
ToolTipFont = CreateFontFromString(Properties.Settings.Default.Map_ToolTipFont);
SplashDlg.Status("Loading Map...");
// initialize map
// setting User Agent to fix Open Street Map issue 2016-09-20
GMap.NET.MapProviders.GMapProvider.UserAgent = "AirScout";
// set initial settings for main map
gm_Main.MapProvider = GMapProviders.Find(Properties.Settings.Default.Map_Provider);
gm_Main.IgnoreMarkerOnMouseWheel = true;
gm_Main.MinZoom = 0;
gm_Main.MaxZoom = 20;
gm_Main.Zoom = 6;
gm_Main.DragButton = System.Windows.Forms.MouseButtons.Left;
gm_Main.CanDragMap = true;
gm_Main.ScalePen = new Pen(Color.Black, 3);
gm_Main.MapScaleInfoEnabled = true;
gm_Main.Overlays.Add(gmo_Airports);
gm_Main.Overlays.Add(gmo_Callsigns);
gm_Main.Overlays.Add(gmo_PropagationPaths);
gm_Main.Overlays.Add(gmo_Routes);
gm_Main.Overlays.Add(gmo_Objects);
gm_Main.Overlays.Add(gmo_Planes);
// setting User Agent to fix Open Street Map issue 2016-09-20
GMap.NET.MapProviders.GMapProvider.UserAgent = "AirScout";
// set initial settings for main map
gm_Nearest.MapProvider = GMapProviders.Find(Properties.Settings.Default.Map_Provider);
gm_Nearest.IgnoreMarkerOnMouseWheel = true;
gm_Nearest.MinZoom = 0;
gm_Nearest.MaxZoom = 20;
gm_Nearest.Zoom = 6;
gm_Nearest.DragButton = System.Windows.Forms.MouseButtons.Left;
gm_Nearest.CanDragMap = true;
gm_Nearest.ScalePen = new Pen(Color.Black, 3);
gm_Nearest.MapScaleInfoEnabled = true;
gm_Nearest.Overlays.Add(gmo_NearestPaths);
gm_Nearest.Overlays.Add(gmo_NearestPlanes);
gm_Nearest.Position = new PointLatLng(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
cntdn = Properties.Settings.Default.Planes_Update;
btn_Map_PlayPause.Select();
// intially fill dialog box elements and set band
string[] bands = Bands.GetStringValuesExceptNoneAndAll();
foreach (string b in bands)
cb_Band.Items.Add(b);
BAND band = Properties.Settings.Default.Band;
cb_Band.SelectedItem = Bands.GetStringValue(band);
string[] cats = PlaneCategories.GetStringValues();
foreach (string cat in cats)
cb_Planes_Filter_Min_Cat.Items.Add(cat);
// initialize gauge controls
ag_Azimuth.fromAngle = -90;
ag_Azimuth.toAngle = 270;
ag_Elevation.fromAngle = 180;
ag_Elevation.toAngle = 270;
// install additional mouse events
gb_Map_Info.MouseClick += new MouseEventHandler(this.gb_Map_Info_MouseClick);
gb_Map_Zoom.MouseClick += new MouseEventHandler(this.gb_Map_Zoom_MouseClick);
gb_Map_Filter.MouseClick += new MouseEventHandler(this.gb_Map_Filter_MouseClick);
gb_Map_Alarms.MouseClick += new MouseEventHandler(this.gb_Map_Alarms_MouseClick);
// get installed plane feeds
PlaneFeeds = new PlaneFeedEnumeration().EnumFeeds();
// set planefeed event handler
foreach (PlaneFeed feed in PlaneFeeds)
{
feed.ProgressChanged += new ProgressChangedEventHandler(bw_PlaneFeed_ProgressChanged);
}
// select feeds
foreach (PlaneFeed feed in PlaneFeeds)
{
if (Properties.Settings.Default.Planes_PlaneFeed1 == feed.Name)
bw_PlaneFeed1 = feed;
if (Properties.Settings.Default.Planes_PlaneFeed2 == feed.Name)
bw_PlaneFeed2 = feed;
if (Properties.Settings.Default.Planes_PlaneFeed3 == feed.Name)
bw_PlaneFeed3 = feed;
}
// update image list sizes
il_Planes_L.ImageSize = new System.Drawing.Size(Properties.Settings.Default.Planes_IconSize_L, Properties.Settings.Default.Planes_IconSize_L);
il_Planes_M.ImageSize = new System.Drawing.Size(Properties.Settings.Default.Planes_IconSize_M, Properties.Settings.Default.Planes_IconSize_M);
il_Planes_H.ImageSize = new System.Drawing.Size(Properties.Settings.Default.Planes_IconSize_H, Properties.Settings.Default.Planes_IconSize_H);
il_Planes_S.ImageSize = new System.Drawing.Size(Properties.Settings.Default.Planes_IconSize_S, Properties.Settings.Default.Planes_IconSize_S);
// try to upgrade user settings from prevoius version on first run
try
{
if (FirstRun)
{
Log.WriteMessage("Preparing for first run.");
// try to ugrade settings when not started with /CLEAN option
if (!CleanRun)
{
// Mono hack to assure that default values were initilaized
if (SupportFunctions.IsMono)
{
Properties.Settings.Default.Reset();
SaveUserSettings();
Properties.Settings.Default.Reload();
}
Log.WriteMessage("Upgrading settings.");
Properties.Settings.Default.Upgrade();
// handle skip to version 1.3.0.0
if (String.IsNullOrEmpty(Properties.Settings.Default.Version) || (String.Compare(Properties.Settings.Default.Version, "1.3.0.0") < 0))
{
/*
// reset elevation data url to new default values
Properties.Settings.Default.Elevation_GLOBE_URL = GetPropertyDefaultValue(nameof(Properties.Settings.Default.Elevation_GLOBE_URL));
Properties.Settings.Default.Elevation_SRTM3_URL = GetPropertyDefaultValue(nameof(Properties.Settings.Default.Elevation_SRTM3_URL));
Properties.Settings.Default.Elevation_SRTM1_URL = GetPropertyDefaultValue(nameof(Properties.Settings.Default.Elevation_SRTM1_URL));
// reset elevation data path to default values
Properties.Settings.Default.Elevation_GLOBE_DataPath = GetPropertyDefaultValue(nameof(Properties.Settings.Default.Elevation_GLOBE_DataPath));
Properties.Settings.Default.Elevation_SRTM3_DataPath = GetPropertyDefaultValue(nameof(Properties.Settings.Default.Elevation_SRTM3_DataPath));
Properties.Settings.Default.Elevation_SRTM1_DataPath = GetPropertyDefaultValue(nameof(Properties.Settings.Default.Elevation_SRTM1_DataPath));
// reset stations data url to its default value
Properties.Settings.Default.StationDatabase_Update_URL = GetPropertyDefaultValue(nameof(Properties.Settings.Default.StationDatabase_Update_URL));
*/
Properties.Settings.Default.Version = Application.ProductVersion;
SaveUserSettings();
}
AirScout.PlaneFeeds.Properties.Settings.Default.Upgrade();
}
CheckDirectories();
CheckSettings();
// get passphrase again
InitializePassword();
// reset topmost state
SplashDlg.TopMost = false;
// must have internet connection on FirstRun
CheckInternet();
/*
// run database updater once for basic information
bw_DatabaseUpdater.RunWorkerAsync(UPDATERSTARTOPTIONS.FIRSTRUN);
// wait till finished
while (bw_DatabaseUpdater.IsBusy)
Application.DoEvents();
*/
SplashDlg.Close();
// show FirstRunWizard
try
{
FirstRunWizard Dlg = new FirstRunWizard();
if (Dlg.ShowDialog() != System.Windows.Forms.DialogResult.OK)
{
Log.WriteMessage("Aborting FirstRunWizard.");
// flush the log and exit immediately
Log.FlushLog();
System.Environment.Exit(-1);
}
else
{
// reset FirstRun property
Properties.Settings.Default.FirstRun = false;
Properties.Settings.Default.FirstRun = Properties.Settings.Default.FirstRun;
// set privacy statements (for legacy)
Properties.Settings.Default.First_Agree = true;
Properties.Settings.Default.First_Disagree = false;
Properties.Settings.Default.First_Privacy = false;
// save settings
SaveUserSettings();
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
// flush the log and exit immediately
Log.FlushLog();
System.Environment.Exit(-1);
}
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
// refresh the Layout
OnSizeChanged(null);
// get initial width of boxes
gb_Map_Info_Width = gb_Map_Info.Width;
// get initial height of boxes
gb_Map_Info_MinimizedHeight = gb_Map_Info.Height - gb_Map_Info.DisplayRectangle.Height;
gb_Map_Zoom_MinimizedHeight = gb_Map_Zoom.Height - gb_Map_Zoom.DisplayRectangle.Height;
gb_Map_Filter_MinimizedHeigth = gb_Map_Filter.Height - gb_Map_Filter.DisplayRectangle.Height;
gb_Map_Alarms_MinimizedHeight = gb_Map_Alarms.Height - gb_Map_Alarms.DisplayRectangle.Height;
gb_Map_Info_MaximizedHeight = gb_Map_Info.Height;
gb_Map_Zoom_MaximizedHeight = gb_Map_Zoom.Height;
gb_Map_Filter_MaximizedHeigth = gb_Map_Filter.Height;
gb_Map_Alarms_MaximizedHeight = gb_Map_Alarms.Height;
// correct splitter values if default
if (Properties.Settings.Default.MainSplitter_Distance <= 0)
Properties.Settings.Default.MainSplitter_Distance = this.Width - gb_Map_Info_Width;
if (Properties.Settings.Default.MapSplitter_Distance <= 0)
Properties.Settings.Default.MapSplitter_Distance = this.Height - 300;
// check directories and settings for missing values
CheckDirectories();
CheckSettings();
// select plane feeds again
foreach (PlaneFeed feed in PlaneFeeds)
{
if (Properties.Settings.Default.Planes_PlaneFeed1 == feed.Name)
bw_PlaneFeed1 = feed;
if (Properties.Settings.Default.Planes_PlaneFeed2 == feed.Name)
bw_PlaneFeed2 = feed;
if (Properties.Settings.Default.Planes_PlaneFeed3 == feed.Name)
bw_PlaneFeed3 = feed;
}
// start permanent background workers
StartAllBackgroundWorkers();
// start main timer
ti_Progress.Start();
FirstRun = false;
// check if a vaild feed is on
if ((bw_PlaneFeed1 == null) && (bw_PlaneFeed2 == null) && (bw_PlaneFeed3 == null))
MessageBox.Show("Plane Feeds are disabled. \n\nYou can use the software anyway, but you will never see a plane on the map. \nIn order to get valid plane positions do the following:\n\n1. Go to the \"Options/Plane\" tab and activate at least one plane feed\n2. Go to the \"Options/General\" tab and adjust \"Planes Positions Range\" to a suitable area around your location", "Plane Feeds Disabled");
// invalidate tracking values
Properties.Settings.Default.Track_SetAz = double.NaN;
Properties.Settings.Default.Track_SetEl = double.NaN;
// set online mode by default
Properties.Settings.Default.Time_Mode_Online = true;
// install OnIdle event handler
// must be here at first!
Application.Idle += new EventHandler(OnIdle);
// move map to MyLoc
if (!double.IsNaN(Properties.Settings.Default.MyLat) && !double.IsNaN(Properties.Settings.Default.MyLon))
gm_Main.Position = new PointLatLng(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
// update status
UpdateStatus();
// show airports on map
UpdateAirports();
// show watchlist on map
UpdateWatchlistInMap();
// set special event handlers on locator combo boxes
// set callsign history and locs
cb_MyCall_TextChanged(this, null);
// set MyLoc and DXLoc combobox properties
cb_MyLoc.DisplayMember = nameof(LocatorDropDownItem.Locator);
cb_MyLoc.ValueMember = nameof(LocatorDropDownItem.GeoLocation);
cb_MyLoc.Precision = (int)Properties.Settings.Default.Locator_MaxLength / 2;
cb_MyLoc.SmallLettersForSubsquares = Properties.Settings.Default.Locator_SmallLettersForSubsquares;
cb_MyLoc.AutoLength = Properties.Settings.Default.Locator_AutoLength;
cb_DXLoc.DisplayMember = nameof(LocatorDropDownItem.Locator);
cb_DXLoc.ValueMember = nameof(LocatorDropDownItem.GeoLocation);
cb_DXLoc.Precision = (int)Properties.Settings.Default.Locator_MaxLength / 2;
cb_DXLoc.SmallLettersForSubsquares = Properties.Settings.Default.Locator_SmallLettersForSubsquares;
cb_DXLoc.AutoLength = Properties.Settings.Default.Locator_AutoLength;
// populate watchlist
RefreshWatchlistView();
// set players bounds
sb_Analysis_Play.Minimum = 0;
sb_Analysis_Play.Maximum = int.MaxValue;
// set path mode to single
PathMode = AIRSCOUTPATHMODE.SINGLE;
// set life mode to life
LifeMode = AIRSCOUTLIFEMODE.LIFE;
// set play mode to pause
PlayMode = AIRSCOUTPLAYMODE.PAUSE;
// maintain background calculations thread wait
Properties.Settings.Default.Background_Calculations_ThreadWait = 0;
Log.WriteMessage("Finished.");
// start timer to finish startup
ti_Startup.Start();
}
catch (Exception ex)
{
// close the application in case of any exception
Log.WriteMessage(ex.ToString());
// close the splash window
if (SplashDlg != null)
SplashDlg.Close();
MessageBox.Show("An error occured during startup: " + ex.ToString() + "\n\nPress >OK< to close the application.", "AirScout", MessageBoxButtons.OK);
this.Close();
}
}
private void FinishStartup()
{
// finish startup
// close splash window
// set window layout
if (SplashDlg != null)
SplashDlg.Close();
// restore window size, state and location
try
{
if (!SupportFunctions.IsMono)
{
this.Size = Properties.Settings.Default.General_WindowSize;
this.Location = Properties.Settings.Default.General_WindowLocation;
this.WindowState = Properties.Settings.Default.General_WindowState;
// set splitter positions
sc_Map.SplitterDistance = Properties.Settings.Default.MapSplitter_Distance;
sc_Main.SplitterDistance = Properties.Settings.Default.MainSplitter_Distance;
CurrentMapSplitterDistance = Properties.Settings.Default.MapSplitter_Distance;
// hide latest news tab
tp_News.Hide();
}
else
{
// ignore window settings under Linux/Mono
// start always maximized
this.WindowState = FormWindowState.Maximized;
sc_Map.SplitterDistance = this.Height - 220;
sc_Main.SplitterDistance = this.Width - gb_Map_Info_Width;
}
}
catch (Exception ex)
{
// do nothing if failed
Log.WriteMessage(ex.Message);
}
// make main window visible
this.Visible = true;
// set focus to map
this.btn_Map_Save.Focus();
// Linux/Mono compatibility
// simulate splitter click
this.sc_Map_SplitterMoved(this, null);
this.sc_Main_SplitterMoved(this, null);
}
private void StartAllBackgroundWorkers()
{
// start all background workers
// check if the thread is not NULL and not activated
Say("Starting background threads...");
if ((bw_AirportMapper != null) && !bw_AirportMapper.IsBusy)
bw_AirportMapper.RunWorkerAsync();
if ((bw_JSONWriter != null) && !bw_JSONWriter.IsBusy)
bw_JSONWriter.RunWorkerAsync();
if ((bw_NewsFeed != null) && !bw_NewsFeed.IsBusy)
bw_NewsFeed.RunWorkerAsync();
if ((bw_AircraftDatabaseMaintainer != null) && (!bw_AircraftDatabaseMaintainer.IsBusy))
{
AircraftPositionDatabaseMaintainerStartOptions startoptions = new AircraftPositionDatabaseMaintainerStartOptions();
startoptions.Name = "Aircrafts";
startoptions.Database_MaxCount = (long)Properties.Settings.Default.AircraftDatabase_MaxCount;
startoptions.Database_MaxSize = (double)Properties.Settings.Default.AircraftDatabase_MaxSize;
startoptions.Database_MaxDaysLifetime = (int)Properties.Settings.Default.AircraftDatabase_MaxDaysLifetime;
bw_AircraftDatabaseMaintainer.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Background_Update_OnStartup)
{
if ((bw_StationDatabaseUpdater != null) && !bw_StationDatabaseUpdater.IsBusy)
{
StationDatabaseUpdaterStartOptions startoptions = new StationDatabaseUpdaterStartOptions();
startoptions.Name = "Stations";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE;
bw_StationDatabaseUpdater.RunWorkerAsync(startoptions);
}
if ((bw_AircraftDatabaseUpdater != null) && !bw_AircraftDatabaseUpdater.IsBusy)
{
AircraftDatabaseUpdaterStartOptions startoptions = new AircraftDatabaseUpdaterStartOptions();
startoptions.Name = "Aircrafts";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE;
bw_AircraftDatabaseUpdater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_GLOBE_Enabled && (bw_GLOBEUpdater != null) && !bw_GLOBEUpdater.IsBusy)
{
ElevationDatabaseUpdaterStartOptions startoptions = new ElevationDatabaseUpdaterStartOptions();
startoptions.Name = "GLOBE";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE;
startoptions.Model = ELEVATIONMODEL.GLOBE;
startoptions.MinLat = Properties.Settings.Default.MinLat;
startoptions.MinLon = Properties.Settings.Default.MinLon;
startoptions.MaxLat = Properties.Settings.Default.MaxLat;
startoptions.MaxLon = Properties.Settings.Default.MaxLon;
startoptions.FileCacheEnabled = Properties.Settings.Default.Elevation_GLOBE_EnableCache;
bw_GLOBEUpdater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_SRTM3_Enabled && (bw_SRTM3Updater != null) && !bw_SRTM3Updater.IsBusy)
{
ElevationDatabaseUpdaterStartOptions startoptions = new ElevationDatabaseUpdaterStartOptions();
startoptions.Name = "SRTM3";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE;
startoptions.Model = ELEVATIONMODEL.SRTM3;
startoptions.MinLat = Properties.Settings.Default.MinLat;
startoptions.MinLon = Properties.Settings.Default.MinLon;
startoptions.MaxLat = Properties.Settings.Default.MaxLat;
startoptions.MaxLon = Properties.Settings.Default.MaxLon;
startoptions.FileCacheEnabled = Properties.Settings.Default.Elevation_SRTM3_EnableCache;
bw_SRTM3Updater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_SRTM1_Enabled && (bw_SRTM1Updater != null) && !bw_SRTM1Updater.IsBusy)
{
ElevationDatabaseUpdaterStartOptions startoptions = new ElevationDatabaseUpdaterStartOptions();
startoptions.Name = "SRTM1";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE;
startoptions.Model = ELEVATIONMODEL.SRTM1;
startoptions.MinLat = Properties.Settings.Default.MinLat;
startoptions.MinLon = Properties.Settings.Default.MinLon;
startoptions.MaxLat = Properties.Settings.Default.MaxLat;
startoptions.MaxLon = Properties.Settings.Default.MaxLon;
startoptions.FileCacheEnabled = Properties.Settings.Default.Elevation_SRTM1_EnableCache;
bw_SRTM1Updater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_GLOBE_Enabled && (bw_GLOBEPathCalculator != null) && !bw_GLOBEPathCalculator.IsBusy)
bw_GLOBEPathCalculator.RunWorkerAsync(BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE);
if (Properties.Settings.Default.Elevation_SRTM3_Enabled && (bw_SRTM3PathCalculator != null) && !bw_SRTM3PathCalculator.IsBusy)
bw_SRTM3PathCalculator.RunWorkerAsync(BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE);
if (Properties.Settings.Default.Elevation_SRTM1_Enabled && (bw_SRTM1PathCalculator != null) && !bw_SRTM1PathCalculator.IsBusy)
bw_SRTM1PathCalculator.RunWorkerAsync(BACKGROUNDUPDATERSTARTOPTIONS.RUNONCE);
}
else if (Properties.Settings.Default.Background_Update_Periodically)
{
if ((bw_StationDatabaseUpdater != null) && !bw_StationDatabaseUpdater.IsBusy)
{
StationDatabaseUpdaterStartOptions startoptions = new StationDatabaseUpdaterStartOptions();
startoptions.Name = "Stations";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY;
bw_StationDatabaseUpdater.RunWorkerAsync(startoptions);
}
if ((bw_AircraftDatabaseUpdater != null) && !bw_AircraftDatabaseUpdater.IsBusy)
{
AircraftDatabaseUpdaterStartOptions startoptions = new AircraftDatabaseUpdaterStartOptions();
startoptions.Name = "Aircrafts";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY;
bw_AircraftDatabaseUpdater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_GLOBE_Enabled && (bw_GLOBEUpdater != null) && !bw_GLOBEUpdater.IsBusy)
{
ElevationDatabaseUpdaterStartOptions startoptions = new ElevationDatabaseUpdaterStartOptions();
startoptions.Name = "GLOBE";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY;
startoptions.Model = ELEVATIONMODEL.GLOBE;
startoptions.MinLat = Properties.Settings.Default.MinLat;
startoptions.MinLon = Properties.Settings.Default.MinLon;
startoptions.MaxLat = Properties.Settings.Default.MaxLat;
startoptions.MaxLon = Properties.Settings.Default.MaxLon;
startoptions.FileCacheEnabled = Properties.Settings.Default.Elevation_GLOBE_EnableCache;
bw_GLOBEUpdater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_SRTM3_Enabled && (bw_SRTM3Updater != null) && !bw_SRTM3Updater.IsBusy)
{
ElevationDatabaseUpdaterStartOptions startoptions = new ElevationDatabaseUpdaterStartOptions();
startoptions.Name = "SRTM3";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY;
startoptions.Model = ELEVATIONMODEL.SRTM3;
startoptions.MinLat = Properties.Settings.Default.MinLat;
startoptions.MinLon = Properties.Settings.Default.MinLon;
startoptions.MaxLat = Properties.Settings.Default.MaxLat;
startoptions.MaxLon = Properties.Settings.Default.MaxLon;
startoptions.FileCacheEnabled = Properties.Settings.Default.Elevation_SRTM3_EnableCache;
bw_SRTM3Updater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_SRTM1_Enabled && (bw_SRTM1Updater != null) && !bw_SRTM1Updater.IsBusy)
{
ElevationDatabaseUpdaterStartOptions startoptions = new ElevationDatabaseUpdaterStartOptions();
startoptions.Name = "SRTM1";
startoptions.Options = BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY;
startoptions.Model = ELEVATIONMODEL.SRTM1;
startoptions.MinLat = Properties.Settings.Default.MinLat;
startoptions.MinLon = Properties.Settings.Default.MinLon;
startoptions.MaxLat = Properties.Settings.Default.MaxLat;
startoptions.MaxLon = Properties.Settings.Default.MaxLon;
startoptions.FileCacheEnabled = Properties.Settings.Default.Elevation_SRTM1_EnableCache;
bw_SRTM1Updater.RunWorkerAsync(startoptions);
}
if (Properties.Settings.Default.Elevation_GLOBE_Enabled && (bw_GLOBEPathCalculator != null) && !bw_GLOBEPathCalculator.IsBusy)
bw_GLOBEPathCalculator.RunWorkerAsync(BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY);
if (Properties.Settings.Default.Elevation_SRTM3_Enabled && (bw_SRTM3PathCalculator != null) && !bw_SRTM3PathCalculator.IsBusy)
bw_SRTM3PathCalculator.RunWorkerAsync(BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY);
if (Properties.Settings.Default.Elevation_SRTM1_Enabled && (bw_SRTM1PathCalculator != null) && !bw_SRTM1PathCalculator.IsBusy)
bw_SRTM1PathCalculator.RunWorkerAsync(BACKGROUNDUPDATERSTARTOPTIONS.RUNPERIODICALLY);
}
if ((bw_PlaneFeed1 != null) && (!bw_PlaneFeed1.IsBusy))
{
PlaneFeedWorkEventArgs feedargs = new PlaneFeedWorkEventArgs();
feedargs.AppDirectory = AppDirectory;
feedargs.AppDataDirectory = AppDataDirectory;
feedargs.LogDirectory = LogDirectory;
feedargs.TmpDirectory = TmpDirectory;
feedargs.DatabaseDirectory = DatabaseDirectory;
feedargs.MaxLat = Properties.Settings.Default.MaxLat;
feedargs.MinLon = Properties.Settings.Default.MinLon;
feedargs.MinLat = Properties.Settings.Default.MinLat;
feedargs.MaxLon = Properties.Settings.Default.MaxLon;
feedargs.MinAlt = Properties.Settings.Default.Planes_MinAlt;
feedargs.MaxAlt = Properties.Settings.Default.Planes_MaxAlt;
feedargs.MyLat = Properties.Settings.Default.MyLat;
feedargs.MyLon = Properties.Settings.Default.MyLon;
feedargs.DXLat = Properties.Settings.Default.DXLat;
feedargs.DXLon = Properties.Settings.Default.DXLon;
feedargs.KeepHistory = Properties.Settings.Default.Planes_KeepHistory;
bw_PlaneFeed1.RunWorkerAsync(feedargs);
}
if ((bw_PlaneFeed2 != null) && (!bw_PlaneFeed2.IsBusy))
{
PlaneFeedWorkEventArgs feedargs = new PlaneFeedWorkEventArgs();
feedargs.AppDirectory = AppDirectory;
feedargs.AppDataDirectory = AppDataDirectory;
feedargs.LogDirectory = LogDirectory;
feedargs.TmpDirectory = TmpDirectory;
feedargs.DatabaseDirectory = DatabaseDirectory;
feedargs.MaxLat = Properties.Settings.Default.MaxLat;
feedargs.MinLon = Properties.Settings.Default.MinLon;
feedargs.MinLat = Properties.Settings.Default.MinLat;
feedargs.MaxLon = Properties.Settings.Default.MaxLon;
feedargs.MinAlt = Properties.Settings.Default.Planes_MinAlt;
feedargs.MaxAlt = Properties.Settings.Default.Planes_MaxAlt;
feedargs.MyLat = Properties.Settings.Default.MyLat;
feedargs.MyLon = Properties.Settings.Default.MyLon;
feedargs.DXLat = Properties.Settings.Default.DXLat;
feedargs.DXLon = Properties.Settings.Default.DXLon;
feedargs.KeepHistory = Properties.Settings.Default.Planes_KeepHistory;
bw_PlaneFeed2.RunWorkerAsync(feedargs);
}
if ((bw_PlaneFeed3 != null) && (!bw_PlaneFeed3.IsBusy))
{
PlaneFeedWorkEventArgs feedargs = new PlaneFeedWorkEventArgs();
feedargs.AppDirectory = AppDirectory;
feedargs.AppDataDirectory = AppDataDirectory;
feedargs.LogDirectory = LogDirectory;
feedargs.TmpDirectory = TmpDirectory;
feedargs.DatabaseDirectory = DatabaseDirectory;
feedargs.MaxLat = Properties.Settings.Default.MaxLat;
feedargs.MinLon = Properties.Settings.Default.MinLon;
feedargs.MinLat = Properties.Settings.Default.MinLat;
feedargs.MaxLon = Properties.Settings.Default.MaxLon;
feedargs.MinAlt = Properties.Settings.Default.Planes_MinAlt;
feedargs.MaxAlt = Properties.Settings.Default.Planes_MaxAlt;
feedargs.MyLat = Properties.Settings.Default.MyLat;
feedargs.MyLon = Properties.Settings.Default.MyLon;
feedargs.DXLat = Properties.Settings.Default.DXLat;
feedargs.DXLon = Properties.Settings.Default.DXLon;
feedargs.KeepHistory = Properties.Settings.Default.Planes_KeepHistory;
bw_PlaneFeed3.RunWorkerAsync(feedargs);
}
if (Properties.Settings.Default.Server_Activate)
{
if ((bw_WinTestReceive != null) && (!bw_WinTestReceive.IsBusy))
bw_WinTestReceive.RunWorkerAsync();
if ((bw_Webserver != null) && (!bw_Webserver.IsBusy))
bw_Webserver.RunWorkerAsync();
}
if (Properties.Settings.Default.SpecLab_Enabled)
{
if ((bw_SpecLab_Receive != null) && (!bw_SpecLab_Receive.IsBusy))
bw_SpecLab_Receive.RunWorkerAsync();
}
if (Properties.Settings.Default.Track_Activate)
{
if ((bw_Track != null) && (!bw_Track.IsBusy))
bw_Track.RunWorkerAsync();
}
Say("Background threads started.");
}
private void StopBackgroundworker(BackgroundWorker worker, string name, int count, int total)
{
if (worker == null)
return;
if (!worker.IsBusy)
return;
worker.CancelAsync();
// waiting for background threads to finish
Stopwatch st = new Stopwatch();
st.Start();
Say("Stopping background thread " + count.ToString() + " of " + total.ToString() + " [" + name + "]...");
while ((worker != null) && worker.IsBusy)
Application.DoEvents();
st.Stop();
Log.WriteMessage("Stopping " + name + ", " + st.ElapsedMilliseconds.ToString() + " ms.");
}
private void StopAllBackgroundWorkers()
{
Say("Stopping background threads...");
// cancel permanent background workers, wait for finish
int bcount = 13;
int i = 1;
// cancel all threads
StopBackgroundworker(bw_WinTestReceive, nameof(bw_WinTestReceive), i, bcount); i++;
StopBackgroundworker(bw_SpecLab_Receive, nameof(bw_SpecLab_Receive), i, bcount); i++;
StopBackgroundworker(bw_Track, nameof(bw_Track), i, bcount); i++;
StopBackgroundworker(bw_JSONWriter, nameof(bw_JSONWriter), i, bcount); i++;
StopBackgroundworker(bw_NewsFeed, nameof(bw_NewsFeed), i, bcount); i++;
StopBackgroundworker(bw_PlaneFeed1, nameof(bw_PlaneFeed1), i, bcount); i++;
StopBackgroundworker(bw_PlaneFeed2, nameof(bw_PlaneFeed2), i, bcount); i++;
StopBackgroundworker(bw_PlaneFeed3, nameof(bw_PlaneFeed3), i, bcount); i++;
StopBackgroundworker(bw_GLOBEPathCalculator, nameof(bw_GLOBEPathCalculator), i, bcount); i++;
StopBackgroundworker(bw_SRTM3PathCalculator, nameof(bw_SRTM3PathCalculator), i, bcount); i++;
StopBackgroundworker(bw_SRTM1PathCalculator, nameof(bw_SRTM1PathCalculator), i, bcount); i++;
StopBackgroundworker(bw_AircraftDatabaseUpdater, nameof(bw_AircraftDatabaseUpdater), i, bcount); i++;
StopBackgroundworker(bw_StationDatabaseUpdater, nameof(bw_StationDatabaseUpdater), i, bcount); i++;
Say("Background threads stopped.");
}
private void CancelAllBackgroundWorkers()
{
// cancel all background workers, don't wait for finish
if (bw_AirportMapper != null)
bw_AirportMapper.CancelAsync();
if (bw_PlaneFeed1 != null)
bw_PlaneFeed1.CancelAsync();
if (bw_PlaneFeed2 != null)
bw_PlaneFeed2.CancelAsync();
if (bw_PlaneFeed3 != null)
bw_PlaneFeed3.CancelAsync();
if (bw_WinTestReceive != null)
bw_WinTestReceive.CancelAsync();
if (bw_SpecLab_Receive != null)
bw_SpecLab_Receive.CancelAsync();
if (bw_Track != null)
bw_Track.CancelAsync();
if (bw_JSONWriter != null)
bw_JSONWriter.CancelAsync();
if (bw_Webserver != null)
bw_Webserver.CancelAsync();
if (bw_NewsFeed != null)
bw_NewsFeed.CancelAsync();
if (bw_HistoryDownloader != null)
bw_HistoryDownloader.CancelAsync();
if (bw_StationDatabaseUpdater != null)
bw_StationDatabaseUpdater.CancelAsync();
if (bw_AircraftDatabaseMaintainer != null)
bw_AircraftDatabaseMaintainer.CancelAsync();
if (bw_AircraftDatabaseUpdater != null)
bw_AircraftDatabaseUpdater.CancelAsync();
if (bw_GLOBEPathCalculator != null)
bw_GLOBEUpdater.CancelAsync();
if (bw_SRTM3Updater != null)
bw_SRTM3Updater.CancelAsync();
if (bw_SRTM1Updater != null)
bw_SRTM1Updater.CancelAsync();
if (bw_GLOBEPathCalculator != null)
bw_GLOBEPathCalculator.CancelAsync();
if (bw_SRTM3PathCalculator != null)
bw_SRTM3PathCalculator.CancelAsync();
if (bw_SRTM1PathCalculator != null)
bw_SRTM1PathCalculator.CancelAsync();
}
private Bitmap CreatePlaneIcon(Color color)
{
// get the basic icon
Bitmap bm = new Bitmap(AppDirectory + Path.DirectorySeparatorChar + Properties.Settings.Default.Planes_IconFileName);
// read the content and change color of each pixel
for (int j = 0; j < bm.Width; j++)
{
for (int k = 0; k < bm.Height; k++)
{
// get the color of each pixel
Color c = bm.GetPixel(j, k);
// check if not transparent
if (c.A > 0)
{
// change color
bm.SetPixel(j, k, Color.FromArgb(c.A, color.R, color.G, color.B));
}
}
}
return bm;
}
public static Color ColorFromHSV(double hue, double saturation, double value)
{
int hi = Convert.ToInt32(Math.Floor(hue / 60)) % 6;
double f = hue / 60 - Math.Floor(hue / 60);
value = value * 255;
int v = Convert.ToInt32(value);
int p = Convert.ToInt32(value * (1 - saturation));
int q = Convert.ToInt32(value * (1 - f * saturation));
int t = Convert.ToInt32(value * (1 - (1 - f) * saturation));
if (hi == 0)
return Color.FromArgb(255, v, t, p);
else if (hi == 1)
return Color.FromArgb(255, q, v, p);
else if (hi == 2)
return Color.FromArgb(255, p, v, t);
else if (hi == 3)
return Color.FromArgb(255, p, q, v);
else if (hi == 4)
return Color.FromArgb(255, t, p, v);
else
return Color.FromArgb(255, v, p, q);
}
public Color GetColor(double power)
{
double H = power * 0.3; // Hue (note 0.4 = Green, see huge chart below)
double S = 0.95; // Saturation
double B = 0.95; // Brightness
return ColorFromHSV((float)H * 360, (float)S, (float)B);
}
private Bitmap CreateAirportIcon(int alpha)
{
// get the basic icon
Bitmap bm = new Bitmap(AppDirectory + Path.DirectorySeparatorChar + Properties.Settings.Default.Airports_IconFileName);
// read the content and change opacity of each pixel
for (int j = 0; j < bm.Width; j++)
{
for (int k = 0; k < bm.Height; k++)
{
// get the color of each pixel
Color c = bm.GetPixel(j, k);
// check if not transparent
if (c.A > 0)
{
// change color
bm.SetPixel(j, k, Color.FromArgb(alpha, c.R, c.G, c.B));
}
}
}
return bm;
}
private void InitializeIcons()
{
// create extra icons regular size
Log.WriteMessage("Started.");
try
{
// now generate 0% - 100% colored planes
for (int i = 0; i <= 100; i++)
{
Bitmap bm = CreatePlaneIcon(GetColor(1.0f - (float)i / 100.0f));
il_Planes_L.Images.Add(bm);
il_Planes_M.Images.Add(bm);
il_Planes_H.Images.Add(bm);
il_Planes_S.Images.Add(bm);
}
il_Planes_L.Images.Add(CreatePlaneIcon(Color.Gray));
il_Planes_M.Images.Add(CreatePlaneIcon(Color.Gray));
il_Planes_H.Images.Add(CreatePlaneIcon(Color.Gray));
il_Planes_S.Images.Add(CreatePlaneIcon(Color.Gray));
bmindex_gray = il_Planes_M.Images.Count - 1;
il_Planes_L.Images.Add(CreatePlaneIcon(Color.LightGreen));
il_Planes_M.Images.Add(CreatePlaneIcon(Color.LightGreen));
il_Planes_H.Images.Add(CreatePlaneIcon(Color.LightGreen));
il_Planes_S.Images.Add(CreatePlaneIcon(Color.LightGreen));
bmindex_lightgreen = il_Planes_M.Images.Count - 1;
il_Planes_L.Images.Add(CreatePlaneIcon(Color.DarkOrange));
il_Planes_M.Images.Add(CreatePlaneIcon(Color.DarkOrange));
il_Planes_H.Images.Add(CreatePlaneIcon(Color.DarkOrange));
il_Planes_S.Images.Add(CreatePlaneIcon(Color.DarkOrange));
bmindex_darkorange = il_Planes_M.Images.Count - 1;
il_Planes_L.Images.Add(CreatePlaneIcon(Color.Red));
il_Planes_M.Images.Add(CreatePlaneIcon(Color.Red));
il_Planes_H.Images.Add(CreatePlaneIcon(Color.Red));
il_Planes_S.Images.Add(CreatePlaneIcon(Color.Red));
bmindex_red = il_Planes_M.Images.Count - 1;
il_Planes_L.Images.Add(CreatePlaneIcon(Color.Magenta));
il_Planes_M.Images.Add(CreatePlaneIcon(Color.Magenta));
il_Planes_H.Images.Add(CreatePlaneIcon(Color.Magenta));
il_Planes_S.Images.Add(CreatePlaneIcon(Color.Magenta));
bmindex_magenta = il_Planes_M.Images.Count - 1;
il_Airports.Images.Add(CreateAirportIcon(255));
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
Log.WriteMessage("Finished.");
}
private void InitializeCharts()
{
// propagation path chart
pm_Path.Title = String.Empty;
pm_Path.DefaultFontSize = 6F;
pm_Path.IsLegendVisible = false;
pv_Path.BackColor = Color.White;
pv_Path.Model = pm_Path;
// add axes
pm_Path.Axes.Clear();
// add X-axis
Path_X.IsZoomEnabled = false;
Path_X.Maximum = 1000;
Path_X.Minimum = 0;
Path_X.MajorGridlineStyle = LineStyle.Solid;
Path_X.MinorGridlineStyle = LineStyle.Dot;
Path_X.Position = AxisPosition.Bottom;
this.pm_Path.Axes.Add(Path_X);
// add Y-axis
Path_Y.IsZoomEnabled = false;
Path_Y.Maximum = 20000;
Path_Y.Minimum = 0;
Path_Y.MajorGridlineStyle = LineStyle.Solid;
Path_Y.MinorGridlineStyle = LineStyle.Dot;
Path_Y.Position = AxisPosition.Left;
this.pm_Path.Axes.Add(Path_Y);
// add series
pm_Path.Series.Clear();
Path_Elevation.Title = "Elevation";
Min_H1.Title = "Min_H1";
Min_H1.StrokeThickness = 2;
Min_H1.LineStyle = LineStyle.Solid;
Min_H1.Color = OxyColors.Red;
Min_H2.Title = "Min_H2";
Min_H2.StrokeThickness = 2;
Min_H2.LineStyle = LineStyle.Solid;
Min_H2.Color = OxyColors.Gold;
Max_H.Title = "Max_H";
Max_H.StrokeThickness = 2;
Max_H.LineStyle = LineStyle.Dot;
Max_H.Color = OxyColors.DarkBlue;
Min_H.Title = "Min_H";
Min_H.StrokeThickness = 0;
Min_H.LineStyle = LineStyle.Solid;
Min_H.Color = OxyColors.Magenta.ChangeSaturation(0.4);
Planes_Hi.Title = "Planes_Hi";
Planes_Hi.Color = OxyColors.Transparent;
Planes_Hi.MarkerType = MarkerType.Square;
Planes_Hi.MarkerFill = OxyColors.Magenta;
Planes_Lo.Title = "Planes_Lo";
Planes_Lo.Color = OxyColors.Transparent;
Planes_Lo.MarkerType = MarkerType.Square;
Planes_Lo.MarkerFill = OxyColors.Gray;
pm_Path.Series.Add(Path_Elevation);
pm_Path.Series.Add(Min_H1);
pm_Path.Series.Add(Min_H2);
pm_Path.Series.Add(Max_H);
pm_Path.Series.Add(Min_H);
pm_Path.Series.Add(Planes_Hi);
pm_Path.Series.Add(Planes_Lo);
// add legend
pm_Path.LegendTitle = "";
pm_Path.LegendPosition = LegendPosition.TopRight;
pm_Path.LegendBackground = OxyColors.White;
pm_Path.LegendBorder = OxyColors.Black;
pm_Path.LegendBorderThickness = 1;
// add control
this.tp_Elevation.Controls.Add(pv_Path);
pv_Path.Paint += new PaintEventHandler(pv_Path_Paint);
// zoomed elevation chart
pm_Elevation.Title = String.Empty;
pm_Elevation.DefaultFontSize = 6F;
pm_Elevation.IsLegendVisible = false;
pv_Elevation.BackColor = Color.White;
pv_Elevation.Model = pm_Elevation;
// add series
pm_Elevation.Series.Clear();
Elevation.Title = "Elevation";
LOS.Title = "LOS";
LOS.StrokeThickness = 2;
LOS.Color = OxyColors.Black;
pm_Elevation.Series.Add(Elevation);
pm_Elevation.Series.Add(LOS);
// create axes
pm_Elevation.Axes.Clear();
// add X-axis
Elevation_X.IsZoomEnabled = false;
Elevation_X.Maximum = 1000;
Elevation_X.Minimum = 0;
Elevation_X.MajorGridlineStyle = LineStyle.Solid;
Elevation_X.MinorGridlineStyle = LineStyle.Dot;
Elevation_X.Position = AxisPosition.Bottom;
this.pm_Elevation.Axes.Add(Elevation_X);
// add Y-axis
Elevation_Y.IsZoomEnabled = false;
// auto size maximum
// Elevation_Y.Maximum = maxelv,
Elevation_Y.Minimum = 0;
Elevation_Y.MajorGridlineStyle = LineStyle.Solid;
Elevation_Y.MinorGridlineStyle = LineStyle.Dot;
Elevation_Y.Position = AxisPosition.Left;
this.pm_Elevation.Axes.Add(Elevation_Y);
// add legend
pm_Elevation.LegendTitle = "";
pm_Elevation.LegendPosition = LegendPosition.TopRight;
pm_Elevation.LegendBackground = OxyColors.White;
pm_Elevation.LegendBorder = OxyColors.Black;
pm_Elevation.LegendBorderThickness = 1;
// add control
this.tp_Elevation.Controls.Add(pv_Elevation);
// spectrum chart
pm_Spectrum.Title = String.Empty;
pm_Spectrum.DefaultFontSize = 6F;
pv_Spectrum.BackColor = Color.White;
pv_Spectrum.Model = pm_Spectrum;
// add Spectrum series
pm_Spectrum.Series.Clear();
// create axes
pm_Spectrum.Axes.Clear();
// add X-axis
Spectrum_X.IsZoomEnabled = false;
Spectrum_X.Maximum = SpectrumMaxPoints;
Spectrum_X.Minimum = 0;
Spectrum_X.MajorGridlineStyle = LineStyle.Solid;
Spectrum_X.MinorGridlineStyle = LineStyle.Dot;
Spectrum_X.Position = AxisPosition.Bottom;
this.pm_Spectrum.Axes.Add(Spectrum_X);
// add Y-axis
Spectrum_Y.IsZoomEnabled = false;
Spectrum_Y.Maximum = 0;
Spectrum_Y.Minimum = -120;
Spectrum_Y.MajorGridlineStyle = LineStyle.Solid;
Spectrum_Y.MinorGridlineStyle = LineStyle.Dot;
Spectrum_Y.Position = AxisPosition.Left;
this.pm_Spectrum.Axes.Add(Spectrum_Y);
// add series
SpectrumRecord.Color = OxyColors.Magenta;
pm_Spectrum.Series.Add(SpectrumRecord);
Spectrum.InterpolationAlgorithm = OxyPlot.InterpolationAlgorithms.CanonicalSpline;
Spectrum.StrokeThickness = 3;
Spectrum.Color = OxyColors.Goldenrod;
pm_Spectrum.Series.Add(Spectrum);
// add control
this.pv_Spectrum.Dock = DockStyle.Fill;
this.gb_Spectrum.Controls.Add(pv_Spectrum);
return;
}
private void InitializeWebbrowser()
{
// do not initialize webbrowser --> not working on all Linux systems
if (SupportFunctions.IsMono)
return;
// iniitialize webbrowser on Windows
this.wb_News = new System.Windows.Forms.WebBrowser();
//
// wb_News
//
this.wb_News.DataBindings.Add(new System.Windows.Forms.Binding("Url", global::AirScout.Properties.Settings.Default, "News_URL", true, System.Windows.Forms.DataSourceUpdateMode.OnPropertyChanged));
this.wb_News.Dock = System.Windows.Forms.DockStyle.Fill;
this.wb_News.Location = new System.Drawing.Point(0, 0);
this.wb_News.MinimumSize = new System.Drawing.Size(20, 20);
this.wb_News.Name = "wb_News";
this.wb_News.Size = new System.Drawing.Size(844, 197);
this.wb_News.TabIndex = 0;
this.wb_News.Url = global::AirScout.Properties.Settings.Default.News_URL;
this.tp_News.Controls.Add(this.wb_News);
}
private void InitializePassword()
{
// get current AirScout password phrase from website and store it in settings
try
{
// get upload info
WebRequest myWebRequest = WebRequest.Create(Properties.Settings.Default.SFTP_PwdURL);
WebResponse myWebResponse = myWebRequest.GetResponse();
Stream ReceiveStream = myWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader readStream = new StreamReader(ReceiveStream, encode);
string s = readStream.ReadToEnd();
Properties.Settings.Default.Password = s;
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void UpdateAirports()
{
if (!Properties.Settings.Default.Airports_Activate)
return;
if ((Airports == null) || (Airports.Count == 0))
return;
foreach (AirportDesignator airport in Airports)
{
try
{
GMarkerGoogle gm = new GMarkerGoogle(new PointLatLng(airport.Lat, airport.Lon), ToolTipFont, RotateImageByAngle(il_Airports.Images[0], 0));
gm.ToolTipText = airport.Airport + "\n" +
airport.IATA + "/" + airport.ICAO;
gm.ToolTipMode = MarkerTooltipMode.OnMouseOver;
gm.Tag = airport.IATA + "," + airport.ICAO;
gmo_Airports.Markers.Add(gm);
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
}
private void ti_Startup_Tick(object sender, EventArgs e)
{
FinishStartup();
ti_Startup.Stop();
}
#endregion
#region User Settings
private string GetUserSettingsPath()
{
if (!SupportFunctions.IsMono)
return ConfigurationManager.OpenExeConfiguration(ConfigurationUserLevel.PerUserRoamingAndLocal).FilePath;
// try to build a path to user specific settings under Linux/Mono
string usersettingspath = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
usersettingspath = Path.Combine(usersettingspath, Application.CompanyName, AppDomain.CurrentDomain.FriendlyName);
usersettingspath += "_Url_";
Assembly assembly = Assembly.GetEntryAssembly();
if (assembly == null)
{
assembly = Assembly.GetCallingAssembly();
}
byte[] pkt = assembly.GetName().GetPublicKeyToken();
byte[] hash = SHA1.Create().ComputeHash((pkt != null && pkt.Length > 0) ? pkt : Encoding.UTF8.GetBytes(assembly.EscapedCodeBase));
StringBuilder evidence_string = new StringBuilder();
byte[] array = hash;
for (int i = 0; i < array.Length; i++)
{
byte b = array[i];
evidence_string.AppendFormat("{0:x2}", b);
}
usersettingspath += evidence_string.ToString();
if (!Directory.Exists(usersettingspath))
{
Directory.CreateDirectory(usersettingspath);
}
usersettingspath = Path.Combine(usersettingspath, "user.config");
return usersettingspath;
}
private void SaveUserSettings()
{
Log.WriteMessage("Saving configuration...");
Properties.Settings.Default.Save();
if (!SupportFunctions.IsMono)
return;
Console.WriteLine("Creating XML document...");
XmlDocument doc = new XmlDocument();
XmlDeclaration xmlDeclaration = doc.CreateXmlDeclaration("1.0", "UTF-8", null);
XmlElement root = doc.DocumentElement;
doc.InsertBefore(xmlDeclaration, root);
XmlElement configuration = doc.CreateElement(string.Empty, "configuration", string.Empty);
doc.AppendChild(configuration);
XmlElement configsections = doc.CreateElement(string.Empty, "configSections", string.Empty);
configuration.AppendChild(configsections);
XmlElement usersettingsgroup = doc.CreateElement(string.Empty, "sectionGroup", string.Empty);
XmlAttribute usersettingsname = doc.CreateAttribute(string.Empty, "name", string.Empty);
usersettingsname.Value = "userSettings";
usersettingsgroup.Attributes.Append(usersettingsname);
XmlElement usersection = doc.CreateElement(string.Empty, "section", string.Empty);
XmlAttribute sectionname = doc.CreateAttribute(string.Empty, "name", string.Empty);
sectionname.Value = "AirScout.PlaneFeeds.Properties.Settings";
usersection.Attributes.Append(sectionname);
XmlAttribute sectiontype = doc.CreateAttribute(string.Empty, "type", string.Empty);
sectiontype.Value = "System.Configuration.ClientSettingsSection, System, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089";
usersection.Attributes.Append(sectiontype);
XmlAttribute sectionallowexedefinition = doc.CreateAttribute(string.Empty, "allowExeDefinition", string.Empty);
sectionallowexedefinition.Value = "MachineToLocalUser";
usersection.Attributes.Append(sectionallowexedefinition);
XmlAttribute sectionrequirepermission = doc.CreateAttribute(string.Empty, "requirePermission", string.Empty);
sectionrequirepermission.Value = "false";
usersection.Attributes.Append(sectionrequirepermission);
usersettingsgroup.AppendChild(usersection);
configsections.AppendChild(usersettingsgroup);
XmlElement usersettings = doc.CreateElement(string.Empty, "userSettings", string.Empty);
configuration.AppendChild(usersettings);
Console.WriteLine("Writing user settings...");
// append AirScout.PlaneFeeds properties
Console.WriteLine("Appending AirScout.PlaneFeeds.Properties.Settings.Default node...");
XmlElement planefeedproperties = doc.CreateElement(string.Empty, AirScout.PlaneFeeds.Properties.Settings.Default.ToString(), string.Empty);
usersettings.AppendChild(planefeedproperties);
foreach (SettingsPropertyValue p in AirScout.PlaneFeeds.Properties.Settings.Default.PropertyValues)
{
if ((p != null) && (p.Name != null) && (p.PropertyValue != null) && !p.UsingDefaultValue)
{
// Console.WriteLine("Appending " + p.Name + " = " + p.PropertyValue.ToString());
XmlElement setting = doc.CreateElement(string.Empty, "setting", string.Empty);
XmlAttribute name = doc.CreateAttribute(string.Empty, "name", string.Empty);
name.Value = p.Name.ToString();
setting.Attributes.Append(name);
XmlAttribute serializeas = doc.CreateAttribute(string.Empty, "serializeAs", string.Empty);
serializeas.Value = p.Property.SerializeAs.ToString();
setting.Attributes.Append(serializeas);
XmlElement value = doc.CreateElement(string.Empty, "value", string.Empty);
if (p.PropertyValue != null && p.Property.SerializeAs == SettingsSerializeAs.String)
{
XmlText text = doc.CreateTextNode(p.SerializedValue.ToString());
value.AppendChild(text);
}
else
{
if (p.PropertyValue != null && p.Property.SerializeAs == SettingsSerializeAs.Xml)
{
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms, new XmlWriterSettings
{
NewLineOnAttributes = true,
OmitXmlDeclaration = true
});
XmlSerializer serializer = new XmlSerializer(p.PropertyValue.GetType());
serializer.Serialize(writer, p.PropertyValue);
byte[] text2 = new byte[ms.ToArray().Length - 3];
Array.Copy(ms.ToArray(), 3, text2, 0, text2.Length);
XmlText xml = doc.CreateTextNode(Encoding.UTF8.GetString(text2.ToArray<byte>()));
value.AppendChild(xml);
value.InnerXml = WebUtility.HtmlDecode(value.InnerXml);
}
}
setting.AppendChild(value);
planefeedproperties.AppendChild(setting);
}
}
// append AirScout properties
Console.WriteLine("Appending AirScout.Properties.Settings.Default node...");
XmlElement properties = doc.CreateElement(string.Empty, Properties.Settings.Default.ToString(), string.Empty);
usersettings.AppendChild(properties);
foreach (SettingsPropertyValue p in Properties.Settings.Default.PropertyValues)
{
if ((p != null) && (p.Name != null) && (p.PropertyValue != null) && !p.UsingDefaultValue)
{
// Console.WriteLine("Appending " + p.Name + " = " + p.PropertyValue.ToString();
XmlElement setting = doc.CreateElement(string.Empty, "setting", string.Empty);
XmlAttribute name = doc.CreateAttribute(string.Empty, "name", string.Empty);
name.Value = p.Name.ToString();
setting.Attributes.Append(name);
XmlAttribute serializeas = doc.CreateAttribute(string.Empty, "serializeAs", string.Empty);
serializeas.Value = p.Property.SerializeAs.ToString();
setting.Attributes.Append(serializeas);
XmlElement value = doc.CreateElement(string.Empty, "value", string.Empty);
if (p.PropertyValue != null && p.Property.SerializeAs == SettingsSerializeAs.String)
{
XmlText text = doc.CreateTextNode(p.SerializedValue.ToString());
value.AppendChild(text);
}
else
{
if (p.PropertyValue != null && p.Property.SerializeAs == SettingsSerializeAs.Xml)
{
MemoryStream ms = new MemoryStream();
XmlWriter writer = XmlWriter.Create(ms, new XmlWriterSettings
{
NewLineOnAttributes = true,
OmitXmlDeclaration = true
});
XmlSerializer serializer = new XmlSerializer(p.PropertyValue.GetType());
serializer.Serialize(writer, p.PropertyValue);
byte[] text2 = new byte[ms.ToArray().Length - 3];
Array.Copy(ms.ToArray(), 3, text2, 0, text2.Length);
XmlText xml = doc.CreateTextNode(Encoding.UTF8.GetString(text2.ToArray<byte>()));
value.AppendChild(xml);
value.InnerXml = WebUtility.HtmlDecode(value.InnerXml);
}
}
setting.AppendChild(value);
properties.AppendChild(setting);
}
}
doc.Save(GetUserSettingsPath());
}
#endregion
#region Idle
private void OnIdle(object sender, EventArgs args)
{
// close window if disagreed
if (ForceClose)
{
Application.Exit();
}
/*
// show/hide group boxes
if (Properties.Settings.Default.Map_ShowInfoBox)
{
gb_Map_Info.ClientSize = new System.Drawing.Size(gb_Map_Info.ClientSize.Width, gb_Map_Info_MaximizedHeight);
if (gb_Map_Info.Text != "˄ Info")
gb_Map_Info.Text = "˄ Info";
}
else
{
gb_Map_Info.ClientSize = new System.Drawing.Size(gb_Map_Info.ClientSize.Width, gb_Map_Info_MinimizedHeight);
if (gb_Map_Info.Text != "˅ Info")
gb_Map_Info.Text = "˅ Info";
}
if (Properties.Settings.Default.Map_ShowZoomBox)
{
gb_Map_Zoom.ClientSize = new System.Drawing.Size(gb_Map_Zoom.ClientSize.Width, gb_Map_Zoom_MaximizedHeight);
if (gb_Map_Zoom.Text != "˄ Map Zoom")
gb_Map_Zoom.Text = "˄ Map Zoom";
}
else
{
gb_Map_Zoom.ClientSize = new System.Drawing.Size(gb_Map_Zoom.ClientSize.Width, gb_Map_Zoom_MinimizedHeight);
if (gb_Map_Zoom.Text != "˅ Map Zoom")
gb_Map_Zoom.Text = "˅ Map Zoom";
}
if (Properties.Settings.Default.Map_ShowFilterBox)
{
gb_Map_Filter.ClientSize = new System.Drawing.Size(gb_Map_Filter.ClientSize.Width, gb_Map_Filter_MaximizedHeigth);
if (gb_Map_Filter.Text != "˄ Planes Filter")
gb_Map_Filter.Text = "˄ Planes Filter";
}
else
{
gb_Map_Filter.ClientSize = new System.Drawing.Size(gb_Map_Filter.ClientSize.Width, gb_Map_Filter_MinimizedHeigth);
if (gb_Map_Filter.Text != "˅ Planes Filter")
gb_Map_Filter.Text = "˅ Planes Filter";
}
if (Properties.Settings.Default.Map_ShowAlarmBox)
{
gb_Map_Alarms.ClientSize = new System.Drawing.Size(gb_Map_Alarms.ClientSize.Width, gb_Map_Alarms_MaximizedHeight);
if (gb_Map_Alarms.Text != "˄ Alarms")
gb_Map_Alarms.Text = "˄ Alarms";
}
else
{
gb_Map_Alarms.ClientSize = new System.Drawing.Size(gb_Map_Alarms.ClientSize.Width, gb_Map_Alarms_MinimizedHeight);
if (gb_Map_Alarms.Text != "˅ Alarms")
gb_Map_Alarms.Text = "˅ Alarms";
}
// show/hide panes
gmo_Airports.IsVisibile = Properties.Settings.Default.Airports_Activate;
gmo_Callsigns.IsVisibile = Properties.Settings.Default.Watchlist_Activated;
pa_Map_Boxes.ClientSize = new System.Drawing.Size(pa_Map_Boxes.ClientSize.Width, ClientSize.Height - ss_Main.Height);
*/
// enable/disable watchlist button
if (btn_Control_Manage_Watchlist.Enabled == Properties.Settings.Default.Watchlist_SyncWithKST)
btn_Control_Manage_Watchlist.Enabled = !Properties.Settings.Default.Watchlist_SyncWithKST;
}
#endregion
#region Closing Down
private void MapDlg_FormClosing(object sender, FormClosingEventArgs e)
{
Log.WriteMessage(Application.ProductName + " is closing.");
// flush the Log for the first time to save all messages
Log.FlushLog();
//save window size, state and location
Properties.Settings.Default.General_WindowLocation = this.Location;
if (this.WindowState == FormWindowState.Normal)
Properties.Settings.Default.General_WindowSize = this.Size;
else
Properties.Settings.Default.General_WindowSize = this.RestoreBounds.Size;
Properties.Settings.Default.General_WindowState = this.WindowState;
Say("Waiting for background threads to close...");
// close background threads, save database and settings
try
{
// cancel background workers
CancelAllBackgroundWorkers();
// save splitter positions
Properties.Settings.Default.MainSplitter_Distance = sc_Main.SplitterDistance;
Properties.Settings.Default.MapSplitter_Distance = CurrentMapSplitterDistance;
// invalidate tracking values
Properties.Settings.Default.Track_SetAz = double.NaN;
Properties.Settings.Default.Track_SetEl = double.NaN;
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
finally
{
// save InMemory databases if any
if (StationData.Database.IsInMemory())
{
Stopwatch st = new Stopwatch();
st.Start();
SayDatabase("Saving station database...");
StationData.Database.BackupDatabase();
st.Stop();
Log.WriteMessage("Station database saved, " + st.ElapsedMilliseconds.ToString() + " ms.");
}
if (PropagationData.Database.IsInMemory(ELEVATIONMODEL.GLOBE))
{
Stopwatch st = new Stopwatch();
st.Start();
SayDatabase("Saving GLOBE database...");
PropagationData.Database.BackupDatabase(ELEVATIONMODEL.GLOBE);
st.Stop();
Log.WriteMessage("Propagation database GLOBE saved, " + st.ElapsedMilliseconds.ToString() + " ms.");
}
if (PropagationData.Database.IsInMemory(ELEVATIONMODEL.SRTM3))
{
Stopwatch st = new Stopwatch();
st.Start();
SayDatabase("Saving SRTM3 database...");
PropagationData.Database.BackupDatabase(ELEVATIONMODEL.SRTM3);
st.Stop();
Log.WriteMessage("Propagation database SRTM3 saved, " + st.ElapsedMilliseconds.ToString() + " ms.");
}
if (PropagationData.Database.IsInMemory(ELEVATIONMODEL.SRTM1))
{
Stopwatch st = new Stopwatch();
st.Start();
SayDatabase("Saving SRTM1 database...");
PropagationData.Database.BackupDatabase(ELEVATIONMODEL.SRTM1);
st.Stop();
Log.WriteMessage("Propagation database SRTM1 saved, " + st.ElapsedMilliseconds.ToString() + " ms.");
}
if (AircraftData.Database.IsInMemory())
{
Stopwatch st = new Stopwatch();
st.Start();
SayDatabase("Saving aircraft database...");
AircraftData.Database.BackupDatabase();
st.Stop();
Log.WriteMessage("Aircraft database saved, " + st.ElapsedMilliseconds.ToString() + " ms.");
}
// save properties to file
SaveUserSettings();
// flush the Log again in case of any exception to save all messages
Log.FlushLog();
}
}
private void MapDlg_FormClosed(object sender, FormClosedEventArgs e)
{
Log.WriteMessage(Application.ProductName + " is closed.");
// flush the Log for the first time to save all messages
Log.FlushLog();
}
#endregion
#region Service Functions
private void Say(string text)
{
if (String.Compare(tsl_Status.Text, text) == 0)
return;
tsl_Status.Text = text;
}
private void SayDatabase(string text)
{
if (String.Compare(tsl_Database.Text, text) == 0)
return;
tsl_Database.Text = text;
}
private void SayCalculations(string text)
{
if (String.Compare(tsl_Calculations.Text, text) == 0)
return;
tsl_Calculations.Text = text;
}
private void SayAnalysis(string text)
{
if (String.Compare(tb_Analysis_Status.Text, text) == 0)
return;
tb_Analysis_Status.Text = text;
tb_Analysis_Status.Refresh();
}
private void UpdateStatus()
{
// upddate TextBoxes
tb_UTC.Text = CurrentTime.ToString("yyyy-MM-dd HH:mm:ss");
if (Properties.Settings.Default.Time_Mode_Online)
tb_UTC.BackColor = Color.LightSalmon;
else
tb_UTC.BackColor = Color.Plum;
string call = Properties.Settings.Default.MyCall;
cb_MyCall.SilentText = Properties.Settings.Default.MyCall;
cb_MyLoc.SilentText = MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon,
Properties.Settings.Default.Locator_SmallLettersForSubsquares,
(int)Properties.Settings.Default.Locator_MaxLength / 2,
Properties.Settings.Default.Locator_AutoLength);
cb_DXCall.Text = Properties.Settings.Default.DXCall;
cb_DXLoc.SilentText = MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat,
Properties.Settings.Default.DXLon,
Properties.Settings.Default.Locator_SmallLettersForSubsquares,
(int)Properties.Settings.Default.Locator_MaxLength / 2,
Properties.Settings.Default.Locator_AutoLength);
if (MaidenheadLocator.Check(cb_MyLoc.Text) && MaidenheadLocator.Check(cb_DXLoc.Text))
{
tb_QTF.Text = Math.Round(LatLon.Bearing(Properties.Settings.Default.MyLat,
Properties.Settings.Default.MyLon,
Properties.Settings.Default.DXLat,
Properties.Settings.Default.DXLon)).ToString("F0");
tb_QRB.Text = Math.Round(LatLon.Distance(Properties.Settings.Default.MyLat,
Properties.Settings.Default.MyLon,
Properties.Settings.Default.DXLat,
Properties.Settings.Default.DXLon)).ToString("F0");
}
else
{
tb_QRB.Text = "0";
tb_QTF.Text = "0";
}
// colour Textbox if more precise lat/lon information is available
if (MaidenheadLocator.IsPrecise(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, 3))
{
cb_MyLoc.BackColor = Color.PaleGreen;
}
else
{
cb_MyLoc.BackColor = Color.FloralWhite;
}
// colour Textbox if more precise lat/lon information is available
if (MaidenheadLocator.IsPrecise(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, 3))
{
cb_DXLoc.BackColor = Color.PaleGreen;
}
else
{
cb_DXLoc.BackColor = Color.FloralWhite;
}
cb_Band.SelectedItem = Bands.GetStringValue(Properties.Settings.Default.Band);
}
private void Alarm(string msg)
{
if (Properties.Settings.Default.Alarm_Activate)
{
gb_Map_Alarms.BackColor = Color.Plum;
if (Properties.Settings.Default.Alarm_BringWindowToFront)
{
// try different methods to bring the window to front under WinXP and Win7
this.TopMost = true;
SetForegroundWindow(this.Handle);
// restore window size, state and location
try
{
this.WindowState = Properties.Settings.Default.General_WindowState;
this.Size = Properties.Settings.Default.General_WindowSize;
this.Location = Properties.Settings.Default.General_WindowLocation;
}
catch (Exception ex)
{
// do nothing if failed
Log.WriteMessage(ex.Message);
}
this.BringToFront();
this.Activate();
this.TopMost = false;
}
if (Properties.Settings.Default.Alarm_PlaySound)
System.Media.SystemSounds.Beep.Play();
}
}
private void MapSave()
{
Log.WriteMessage("Started.");
try
{
Bitmap bmp = new Bitmap(this.Width, this.Height);
this.DrawToBitmap(bmp, new System.Drawing.Rectangle(new System.Drawing.Point(0, 0), this.Size));
EncoderParameters encoderParameters = new EncoderParameters(1);
encoderParameters.Param[0] = new EncoderParameter(System.Drawing.Imaging.Encoder.Quality, 100L);
ImageCodecInfo[] codecs = ImageCodecInfo.GetImageDecoders();
foreach (ImageCodecInfo codec in codecs)
{
if (codec.FormatID == System.Drawing.Imaging.ImageFormat.Jpeg.Guid)
{
bmp.Save(TmpDirectory + Path.DirectorySeparatorChar + Properties.Settings.Default.Band + "_" + Properties.Settings.Default.MyCall.Replace("/", "_") + "_" + Properties.Settings.Default.DXCall.Replace("/", "_") + "_" + CurrentTime.ToString("yyyyMMdd") + "_" + CurrentTime.ToString("HHmmss") + ".jpg", codec, encoderParameters);
}
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
Log.WriteMessage("Finished.");
}
private void cb_Alarms_Activate_CheckedChanged(object sender, EventArgs e)
{
if (!cb_Alarms_Activate.Checked)
gb_Map_Alarms.BackColor = SystemColors.Control;
}
private void tb_UTC_MouseDoubleClick(object sender, MouseEventArgs e)
{
if (PlayMode != AIRSCOUTPLAYMODE.PAUSE)
return;
SetTimeDlg Dlg = new SetTimeDlg();
Dlg.cb_Time_Online.Checked = Properties.Settings.Default.Time_Mode_Online;
Dlg.dtp_SetTimeDlg_Start.Value = Properties.Settings.Default.Time_Offline;
if (Dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
Properties.Settings.Default.Time_Offline = Dlg.dtp_SetTimeDlg_Start.Value;
Properties.Settings.Default.Time_Mode_Online = Dlg.cb_Time_Online.Checked;
UpdateStatus();
}
}
private void UpdateLocation(string call, double lat, double lon, GEOSOURCE source)
{
// update callsign database with new lat/lon info
if (Callsign.Check(call))
StationData.Database.LocationInsertOrUpdateIfNewer(new LocationDesignator(call, lat, lon, source));
}
public LocationDesignator LocationFindOrCreate(string call, string loc)
{
// check all parameters
if (!Callsign.Check(call))
return null;
if (!MaidenheadLocator.Check(loc))
return null;
// get location info
LocationDesignator ld = StationData.Database.LocationFindOrCreate(call, loc);
// get elevation
ld.Elevation = GetElevation(ld.Lat, ld.Lon);
ld.BestCaseElevation = false;
// modify location in case of best case elevation is selected --> but do not store in database or settings!
if (Properties.Settings.Default.Path_BestCaseElevation)
{
if (!MaidenheadLocator.IsPrecise(ld.Lat, ld.Lon, 3))
{
ElvMinMaxInfo maxinfo = GetMinMaxElevationLoc(ld.Loc);
if (maxinfo != null)
{
ld.Lat = maxinfo.MaxLat;
ld.Lon = maxinfo.MaxLon;
ld.Elevation = maxinfo.MaxElv;
ld.BestCaseElevation = true;
}
}
}
return ld;
}
public LocationDesignator LocationFindOrUpdateOrCreate(string call, double lat, double lon)
{
// check all parameters
if (!Callsign.Check(call))
return null;
if (!GeographicalPoint.Check(lat, lon))
return null;
// get location info
LocationDesignator ld = StationData.Database.LocationFindOrUpdateOrCreate(call, lat, lon);
// get elevation
ld.Elevation = GetElevation(ld.Lat, ld.Lon);
ld.BestCaseElevation = false;
// modify location in case of best case elevation is selected --> but do not store in database or settings!
if (Properties.Settings.Default.Path_BestCaseElevation)
{
if (!MaidenheadLocator.IsPrecise(ld.Lat, ld.Lon, 3))
{
ElvMinMaxInfo maxinfo = GetMinMaxElevationLoc(ld.Loc);
if (maxinfo != null)
{
ld.Lat = maxinfo.MaxLat;
ld.Lon = maxinfo.MaxLon;
ld.Elevation = maxinfo.MaxElv;
ld.BestCaseElevation = true;
}
}
}
return ld;
}
public LocationDesignator LocationFind(string call, string loc = "")
{
// check all parameters
if (!Callsign.Check(call))
return null;
if (!String.IsNullOrEmpty(loc) && !MaidenheadLocator.Check(loc))
return null;
// get location info
LocationDesignator ld = (String.IsNullOrEmpty(loc)) ? StationData.Database.LocationFind(call) : StationData.Database.LocationFind(call, loc);
// return null if not found
if (ld == null)
return null;
// get elevation
ld.Elevation = GetElevation(ld.Lat, ld.Lon);
ld.BestCaseElevation = false;
// modify location in case of best case elevation is selected --> but do not store in database or settings!
if (Properties.Settings.Default.Path_BestCaseElevation)
{
if (!MaidenheadLocator.IsPrecise(ld.Lat, ld.Lon, 3))
{
ElvMinMaxInfo maxinfo = GetMinMaxElevationLoc(ld.Loc);
if (maxinfo != null)
{
ld.Lat = maxinfo.MaxLat;
ld.Lon = maxinfo.MaxLon;
ld.Elevation = maxinfo.MaxElv;
ld.BestCaseElevation = true;
}
}
}
return ld;
}
public short GetElevation(string loc)
{
return GetElevation(MaidenheadLocator.LatFromLoc(loc), MaidenheadLocator.LonFromLoc(loc));
}
public short GetElevation(double lat, double lon)
{
if (!GeographicalPoint.Check(lat, lon))
return 0;
short elv = ElevationData.Database.ElvMissingFlag;
// try to get elevation data from distinct elevation model
// start with detailed one
if (Properties.Settings.Default.Elevation_SRTM1_Enabled && (elv == ElevationData.Database.ElvMissingFlag))
elv = ElevationData.Database[lat, lon, ELEVATIONMODEL.SRTM1, false];
if (Properties.Settings.Default.Elevation_SRTM3_Enabled && (elv == ElevationData.Database.ElvMissingFlag))
elv = ElevationData.Database[lat, lon, ELEVATIONMODEL.SRTM3, false];
if (Properties.Settings.Default.Elevation_GLOBE_Enabled && (elv == ElevationData.Database.ElvMissingFlag))
elv = ElevationData.Database[lat, lon, ELEVATIONMODEL.GLOBE, false];
// set it to zero if still invalid
if (elv <= ElevationData.Database.TileMissingFlag)
elv = 0;
return elv;
}
public ElvMinMaxInfo GetMinMaxElevationLoc(string loc)
{
ElvMinMaxInfo elv = new ElvMinMaxInfo();
// try to get elevation data from distinct elevation model
// start with detailed one
if (Properties.Settings.Default.Elevation_SRTM1_Enabled && (elv.MaxElv == ElevationData.Database.ElvMissingFlag))
{
ElvMinMaxInfo info = ElevationData.Database.GetMaxElvLoc(loc, ELEVATIONMODEL.SRTM1, false);
if (info != null)
{
elv.MaxLat = info.MaxLat;
elv.MaxLon = info.MaxLon;
elv.MaxElv = info.MaxElv;
elv.MinLat = info.MinLat;
elv.MinLon = info.MinLon;
elv.MinElv = info.MinElv;
}
}
if (Properties.Settings.Default.Elevation_SRTM3_Enabled && (elv.MaxElv == ElevationData.Database.ElvMissingFlag))
{
ElvMinMaxInfo info = ElevationData.Database.GetMaxElvLoc(loc, ELEVATIONMODEL.SRTM3, false);
if (info != null)
{
elv.MaxLat = info.MaxLat;
elv.MaxLon = info.MaxLon;
elv.MaxElv = info.MaxElv;
elv.MinLat = info.MinLat;
elv.MinLon = info.MinLon;
elv.MinElv = info.MinElv;
}
}
if (Properties.Settings.Default.Elevation_GLOBE_Enabled && (elv.MaxElv == ElevationData.Database.ElvMissingFlag))
{
ElvMinMaxInfo info = ElevationData.Database.GetMaxElvLoc(loc, ELEVATIONMODEL.GLOBE, false);
if (info != null)
{
elv.MaxLat = info.MaxLat;
elv.MaxLon = info.MaxLon;
elv.MaxElv = info.MaxElv;
elv.MinLat = info.MinLat;
elv.MinLon = info.MinLon;
elv.MinElv = info.MinElv;
}
}
// set it to zero if still invalid
if (elv.MaxElv == ElevationData.Database.ElvMissingFlag)
elv.MaxElv = 0;
if (elv.MinElv == ElevationData.Database.ElvMissingFlag)
elv.MinElv = 0;
return elv;
}
public void SetElevationModel()
{
if (Properties.Settings.Default.Elevation_SRTM1_Enabled)
Properties.Settings.Default.ElevationModel = ELEVATIONMODEL.SRTM1;
else if (Properties.Settings.Default.Elevation_SRTM3_Enabled)
Properties.Settings.Default.ElevationModel = ELEVATIONMODEL.SRTM3;
else if (Properties.Settings.Default.Elevation_GLOBE_Enabled)
Properties.Settings.Default.ElevationModel = ELEVATIONMODEL.GLOBE;
else
Properties.Settings.Default.ElevationModel = ELEVATIONMODEL.NONE;
}
public static Font CreateFontFromString(string font)
{
try
{
string[] a = Properties.Settings.Default.Map_ToolTipFont.Split(';');
string fontfamily = a[0].Trim();
float emsize = 0;
float.TryParse(a[1].Trim(), NumberStyles.Float, CultureInfo.InvariantCulture, out emsize);
FontStyle fontstyle = 0;
// check if any additional font style is given
if (a.Length > 2)
{
if (a[2].ToUpper().IndexOf("BOLD") >= 0)
fontstyle = fontstyle | FontStyle.Bold;
if (a[2].ToUpper().IndexOf("ITALIC") >= 0)
fontstyle = fontstyle | FontStyle.Italic;
if (a[2].ToUpper().IndexOf("UNDERLINE") >= 0)
fontstyle = fontstyle | FontStyle.Underline;
if (a[2].ToUpper().IndexOf("STRIKEOUT") >= 0)
fontstyle = fontstyle | FontStyle.Strikeout;
}
else
{
fontstyle = FontStyle.Regular;
}
return new Font(fontfamily, emsize, fontstyle, GraphicsUnit.Point);
}
catch
{
}
return null;
}
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool ShowWindow(IntPtr hWnd, ShowWindowCommands nCmdShow);
[DllImport("user32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
static extern bool SetForegroundWindow(IntPtr hWnd);
enum ShowWindowCommands : int
{
/// <summary>
/// Hides the window and activates another window.
/// </summary>
Hide = 0,
/// <summary>
/// Activates and displays a window. If the window is minimized or
/// maximized, the system restores it to its original size and position.
/// An application should specify this flag when displaying the window
/// for the first time.
/// </summary>
Normal = 1,
/// <summary>
/// Activates the window and displays it as a minimized window.
/// </summary>
ShowMinimized = 2,
/// <summary>
/// Maximizes the specified window.
/// </summary>
Maximize = 3, // is this the right value?
/// <summary>
/// Activates the window and displays it as a maximized window.
/// </summary>
ShowMaximized = 3,
/// <summary>
/// Displays a window in its most recent size and position. This value
/// is similar to <see cref="Win32.ShowWindowCommand.Normal"/>, except
/// the window is not activated.
/// </summary>
ShowNoActivate = 4,
/// <summary>
/// Activates the window and displays it in its current size and position.
/// </summary>
Show = 5,
/// <summary>
/// Minimizes the specified window and activates the next top-level
/// window in the Z order.
/// </summary>
Minimize = 6,
/// <summary>
/// Displays the window as a minimized window. This value is similar to
/// <see cref="Win32.ShowWindowCommand.ShowMinimized"/>, except the
/// window is not activated.
/// </summary>
ShowMinNoActive = 7,
/// <summary>
/// Displays the window in its current size and position. This value is
/// similar to <see cref="Win32.ShowWindowCommand.Show"/>, except the
/// window is not activated.
/// </summary>
ShowNA = 8,
/// <summary>
/// Activates and displays the window. If the window is minimized or
/// maximized, the system restores it to its original size and position.
/// An application should specify this flag when restoring a minimized window.
/// </summary>
Restore = 9,
/// <summary>
/// Sets the show state based on the SW_* value specified in the
/// STARTUPINFO structure passed to the CreateProcess function by the
/// program that started the application.
/// </summary>
ShowDefault = 10,
/// <summary>
/// <b>Windows 2000/XP:</b> Minimizes a window, even if the thread
/// that owns the window is not responding. This flag should only be
/// used when minimizing windows from a different thread.
/// </summary>
ForceMinimize = 11
}
private void ShowOptionsDlg()
{
// stop background threads
Say("Waiting for background threads to close....");
StopAllBackgroundWorkers();
// save current settings
SaveUserSettings();
// show options dialog
OptionsDlg Dlg = new OptionsDlg(this);
Say("Options");
if (Dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
// clear paths cache assuming that new options were set
ElevationPaths.Clear();
PropagationPaths.Clear();
// update station infos
UpdateLocation(Properties.Settings.Default.MyCall,
Properties.Settings.Default.MyLat,
Properties.Settings.Default.MyLon,
MaidenheadLocator.IsPrecise(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, 3) ? GEOSOURCE.FROMUSER : GEOSOURCE.FROMLOC);
UpdateLocation(Properties.Settings.Default.DXCall,
Properties.Settings.Default.DXLat,
Properties.Settings.Default.DXLon,
MaidenheadLocator.IsPrecise(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, 3) ? GEOSOURCE.FROMUSER : GEOSOURCE.FROMLOC);
// update map provider
gm_Main.MapProvider = GMapProviders.Find(Properties.Settings.Default.Map_Provider);
// update ToolTipFont
ToolTipFont = CreateFontFromString(Properties.Settings.Default.Map_ToolTipFont);
// update planefeeds
bw_PlaneFeed1 = null;
bw_PlaneFeed2 = null;
bw_PlaneFeed3 = null;
foreach (PlaneFeed feed in PlaneFeeds)
{
if (Properties.Settings.Default.Planes_PlaneFeed1 == feed.Name)
bw_PlaneFeed1 = feed;
if (Properties.Settings.Default.Planes_PlaneFeed2 == feed.Name)
bw_PlaneFeed2 = feed;
if (Properties.Settings.Default.Planes_PlaneFeed3 == feed.Name)
bw_PlaneFeed3 = feed;
}
// update timer interval
ti_Progress.Interval = Properties.Settings.Default.Map_Update * 1000;
// update background update intervals
ScoutBase.Elevation.Properties.Settings.Default.Datatbase_BackgroundUpdate_Period = (int)Properties.Settings.Default.Background_Update_Period;
ScoutBase.Stations.Properties.Settings.Default.Database_BackgroundUpdate_Period = (int)Properties.Settings.Default.Background_Update_Period;
AirScout.Aircrafts.Properties.Settings.Default.Database_BackgroundUpdate_Period = (int)Properties.Settings.Default.Background_Update_Period;
// update database path path and elevation model
InitializeDatabase();
}
else
{
// nothing was changed
Properties.Settings.Default.Reload();
}
// start permanent background workers
StartAllBackgroundWorkers();
// update status window
UpdateStatus();
UpdateAirports();
UpdateWatchlistInMap();
RefreshWatchlistView();
}
#endregion
#region Play & Pause
private void Play()
{
PlayMode = AIRSCOUTPLAYMODE.FORWARD;
// switch tab control according to path mode
if (PathMode == AIRSCOUTPATHMODE.SINGLE)
tc_Control.SelectedTab = tp_Control_Single;
else if (PathMode == AIRSCOUTPATHMODE.MULTI)
tc_Control.SelectedTab = tp_Control_Multi;
// update tab control
tc_Control.Refresh();
// update all current paths
UpdatePaths();
// clear spectrum
try
{
Spectrum.Points.Clear();
SpectrumPointsCount = 0;
Spectrum_X.Reset();
SpectrumRecord.Points.Clear();
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
// change button image
btn_Map_PlayPause.Image = il_Main.Images[0];
// disable controls
cb_Band.Enabled = false;
btn_Options.Enabled = false;
cb_MyCall.Enabled = false;
cb_MyLoc.Enabled = false;
cb_DXCall.Enabled = false;
cb_DXLoc.Enabled = false;
tc_Control.Enabled = false;
pa_Planes_Filter.Enabled = false;
gb_Analysis_Controls.Enabled = false;
gb_Analysis_Database.Enabled = false;
gb_Analysis_Player.Enabled = false;
tc_Main.Enabled = false;
//referesh main window
this.Refresh();
}
private void Pause()
{
PlayMode = AIRSCOUTPLAYMODE.PAUSE;
// change button image
btn_Map_PlayPause.Image = il_Main.Images[1];
// update tab control
tc_Control.Refresh();
// enable controls
cb_Band.Enabled = true;
btn_Options.Enabled = true;
cb_MyCall.Enabled = true;
cb_MyLoc.Enabled = true;
cb_DXCall.Enabled = true;
cb_DXLoc.Enabled = true;
tc_Control.Enabled = true;
pa_Planes_Filter.Enabled = true;
gb_Analysis_Controls.Enabled = true;
gb_Analysis_Database.Enabled = true;
gb_Analysis_Player.Enabled = true;
tc_Main.Enabled = true;
// stop tracking
Properties.Settings.Default.Track_SetAz = double.NaN;
Properties.Settings.Default.Track_SetEl = double.NaN;
//referesh main window
this.Refresh();
}
#endregion
#region Paths
private double GetMinH(double max_alt, double H1, double H2)
{
double max = Math.Max(H1, H2);
if (max <= max_alt)
return max;
return max_alt;
}
private void ClearAllPathsInMap()
{
gmo_PropagationPaths.Clear();
}
private void DrawPath(PropagationPathDesignator ppath)
{
// draws a propagation path to map
PropagationPoint[] ppoints = new PropagationPoint[0];
try
{
// get infopoints for map
ppoints = ppath.GetInfoPoints();
// calculate midpoint
ScoutBase.Core.LatLon.GPoint midpoint = LatLon.MidPoint(ppath.Lat1, ppath.Lon1, ppath.Lat2, ppath.Lon2);
GMapMarker gmmid = new GMarkerGoogle(new PointLatLng(midpoint.Lat, midpoint.Lon), ToolTipFont, Properties.Settings.Default.Map_SmallMarkers ? GMarkerGoogleType.blue_small : GMarkerGoogleType.blue_dot);
gmmid.ToolTipText = ppath.Location1.Call + " <> " + ppath.Location2.Call;
gmmid.ToolTipMode = MarkerTooltipMode.OnMouseOver;
gmo_Objects.Markers.Add(gmmid);
// calculate dx end
gmm_DXLoc = new GMarkerGoogle(new PointLatLng(ppath.Lat2, ppath.Lon2), ToolTipFont, Properties.Settings.Default.Map_SmallMarkers ? GMarkerGoogleType.yellow_small : GMarkerGoogleType.yellow_dot);
gmm_DXLoc.ToolTipText = ppath.Location2.Call + "\n" +
ppath.Location2.Lat.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
ppath.Location2.Lon.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
ppath.Location2.Loc + "\n" +
GetElevation(ppath.Location2.Lat, ppath.Location2.Lon).ToString("F0") + "m";
if (Properties.Settings.Default.Track_Activate)
gmm_DXLoc.ToolTipText += "\nRight+Click to Turn Antenna";
gmm_DXLoc.ToolTipMode = MarkerTooltipMode.OnMouseOver;
gmm_DXLoc.Tag = ppath.Location2.Call;
gmo_Objects.Markers.Add(gmm_DXLoc);
// set three small points for hot path, if one
if (!Properties.Settings.Default.Map_SmallMarkers)
{
int i1 = -1;
int i3 = -1;
for (int i = 0; i < ppoints.Length; i++)
{
if (Math.Max(ppoints[i].H1, ppoints[i].H2) < Properties.Settings.Default.Planes_MaxAlt)
{
if (i1 == -1)
i1 = i;
else i3 = i;
}
}
if ((i1 >= 0) && (i3 >= 0))
{
GMapMarker gmi1 = new GMarkerGoogle(new PointLatLng(ppoints[i1].Lat, ppoints[i1].Lon), GMarkerGoogleType.red_small);
gmo_Objects.Markers.Add(gmi1);
LatLon.GPoint gp = LatLon.MidPoint(ppoints[i1].Lat, ppoints[i1].Lon, ppoints[i3].Lat, ppoints[i3].Lon);
GMapMarker gmi2 = new GMarkerGoogle(new PointLatLng(gp.Lat, gp.Lon), GMarkerGoogleType.blue_small);
gmo_Objects.Markers.Add(gmi2);
GMapMarker gmi3 = new GMarkerGoogle(new PointLatLng(ppoints[i3].Lat, ppoints[i3].Lon), GMarkerGoogleType.yellow_small);
gmo_Objects.Markers.Add(gmi3);
}
}
// draw propagation path according to path status
// valid: black
// invalid: red
gmr_FullPath = new GMapRoute("fullpath");
gmr_FullPath.Stroke = (ppath.Valid) ? new Pen(Color.Black, 3) : new Pen(Color.Red, 3);
gmo_PropagationPaths.Routes.Add(gmr_FullPath);
gmr_NearestFull = new GMapRoute("fullpath");
gmr_NearestFull.Stroke = (ppath.Valid) ? new Pen(Color.Black, 3) : new Pen(Color.Red, 3);
gmo_NearestPaths.Routes.Add(gmr_NearestFull);
foreach (PropagationPoint ppoint in ppoints)
{
gmr_FullPath.Points.Add(new PointLatLng(ppoint.Lat, ppoint.Lon));
gmr_NearestFull.Points.Add(new PointLatLng(ppoint.Lat, ppoint.Lon));
}
// draw mutual visible path
gmr_VisiblePpath = new GMapRoute("visiblepath");
gmr_VisiblePpath.Stroke = new Pen(Color.Magenta, 3);
gmr_NearestVisible = new GMapRoute("visiblepath");
gmr_NearestVisible.Stroke = new Pen(Color.Magenta, 3);
for (int i = 0; i < ppoints.Length; i++)
{
if ((Math.Max(ppoints[i].H1, ppoints[i].H2) > 0) && (Math.Max(ppoints[i].H1, ppoints[i].H2) < Properties.Settings.Default.Planes_MaxAlt))
{
PointLatLng p = new PointLatLng(ppoints[i].Lat, ppoints[i].Lon);
gmr_VisiblePpath.Points.Add(p);
gmr_NearestVisible.Points.Add(p);
}
}
gmo_PropagationPaths.Routes.Add(gmr_VisiblePpath);
gmo_NearestPaths.Routes.Add(gmr_NearestVisible);
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void UpdatePaths()
{
// updates all current path to calculate
Log.WriteMessage("UpdatePath started.");
Stopwatch st = new Stopwatch();
st.Start();
// check if there are a valid home settings
if (!Callsign.Check(Properties.Settings.Default.MyCall) ||
!GeographicalPoint.Check(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon))
return;
// OK valid, lets continue
// slow down background calculations
Properties.Settings.Default.Background_Calculations_ThreadWait = 1000;
//clear map overlays
gmo_PropagationPaths.Clear();
gmo_NearestPaths.Clear();
gmo_Objects.Clear();
// clear all planes and tooltips
gmo_Planes.Clear();
// clear paths
ElevationPaths.Clear();
PropagationPaths.Clear();
// clear charts
ClearCharts();
// put call on MyCalls last recent collection if not already in
if (Properties.Settings.Default.MyCalls.IndexOf(Properties.Settings.Default.MyCall) < 0)
{
Properties.Settings.Default.MyCalls.Insert(0, Properties.Settings.Default.MyCall);
}
// keep the MyCalls list small
while (Properties.Settings.Default.MyCalls.Count > 10)
{
Properties.Settings.Default.MyCalls.RemoveAt(Properties.Settings.Default.MyCalls.Count - 1);
}
// check and update station database
LocationDesignator myloc = LocationFindOrUpdateOrCreate(Properties.Settings.Default.MyCall, Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
Properties.Settings.Default.MyElevation = myloc.Elevation;
// get qrv info or create default
QRVDesignator myqrv = StationData.Database.QRVFindOrCreateDefault(myloc.Call, myloc.Loc, Properties.Settings.Default.Band);
// set qrv defaults if zero
if (myqrv.AntennaHeight == 0)
myqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band);
if (myqrv.AntennaGain == 0)
myqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band);
if (myqrv.Power == 0)
myqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band);
// draw my end on the map
gmm_MyLoc = new GMarkerGoogle(new PointLatLng(myloc.Lat, myloc.Lon), ToolTipFont, Properties.Settings.Default.Map_SmallMarkers ? GMarkerGoogleType.red_small : GMarkerGoogleType.red_dot);
gmm_MyLoc.ToolTipText = myloc.Call + "\n" +
myloc.Lat.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
myloc.Lon.ToString("F8", CultureInfo.InvariantCulture) + "\n" +
myloc.Loc + "\n" +
GetElevation(myloc.Lat, myloc.Lon).ToString("F0") + "m";
gmm_MyLoc.ToolTipMode = MarkerTooltipMode.OnMouseOver;
gmm_MyLoc.Tag = myloc.Call;
gmo_Objects.Markers.Add(gmm_MyLoc);
// do single path mode
if (PathMode == AIRSCOUTPATHMODE.SINGLE)
{
// check if there are a valid DX settings
if (!Callsign.Check(Properties.Settings.Default.DXCall) ||
!GeographicalPoint.Check(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon))
return;
// OK valid, lets continue
// check and update station database
LocationDesignator dxloc = LocationFindOrUpdateOrCreate(Properties.Settings.Default.DXCall, Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon);
Properties.Settings.Default.DXElevation = dxloc.Elevation;
// get qrv info or create default
QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxloc.Call, dxloc.Loc, Properties.Settings.Default.Band);
// set qrv defaults if zero
if (dxqrv.AntennaHeight == 0)
dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band);
if (dxqrv.AntennaGain == 0)
dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band);
if (dxqrv.Power == 0)
dxqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band);
// find local obstruction, if any
LocalObstructionDesignator o = ElevationData.Database.LocalObstructionFind(myloc.Lat, myloc.Lon, Properties.Settings.Default.ElevationModel);
double mybearing = LatLon.Bearing(myloc.Lat, myloc.Lon, dxloc.Lat, dxloc.Lon);
double myobstr = (o != null) ? o.GetObstruction(myqrv.AntennaHeight, mybearing) : double.MinValue;
// try to find elevation path in database or create new one and store
ElevationPathDesignator epath = ElevationData.Database.ElevationPathFindOrCreateFromLatLon(
null,
myloc.Lat,
myloc.Lon,
dxloc.Lat,
dxloc.Lon,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel);
// add additional info to ppath
epath.Location1 = myloc;
epath.Location2 = dxloc;
epath.QRV1 = myqrv;
epath.QRV2 = dxqrv;
// try to find propagation path in database or create new one and store
PropagationPathDesignator ppath = PropagationData.Database.PropagationPathFindOrCreateFromLatLon(
null,
myloc.Lat,
myloc.Lon,
GetElevation(myloc.Lat, myloc.Lon) + myqrv.AntennaHeight,
dxloc.Lat,
dxloc.Lon,
GetElevation(dxloc.Lat, dxloc.Lon) + dxqrv.AntennaHeight,
Bands.ToGHz(Properties.Settings.Default.Band),
LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].K_Factor,
Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].F1_Clearance,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel,
myobstr);
// add additional info to ppath
ppath.Location1 = myloc;
ppath.Location2 = dxloc;
ppath.QRV1 = myqrv;
ppath.QRV2 = dxqrv;
// add single path to paths list
ElevationPaths.Add(epath);
PropagationPaths.Add(ppath);
// put DXCall on the watchlist if not already in
if (Properties.Settings.Default.Watchlist.IndexOf(Properties.Settings.Default.DXCall, MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, false, 3)) < 0)
{
Properties.Settings.Default.Watchlist.Insert(0, new WatchlistItem(Properties.Settings.Default.DXCall, MaidenheadLocator.LocFromLatLon(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, false, 3), ppath.Distance > Properties.Settings.Default.Path_MaxLength));
}
// keep the watchlist small
while (Properties.Settings.Default.Watchlist.Count() > Properties.Settings.Default.Watchlist_MaxCount)
{
Properties.Settings.Default.Watchlist.RemoveAt(Properties.Settings.Default.Watchlist.Count() - 1);
}
}
else if (PathMode == AIRSCOUTPATHMODE.MULTI)
{
// iterate through watchlist and add selected
foreach (ListViewItem item in lv_Control_Watchlist.Items)
{
// use only selected items
if (!item.Checked)
continue;
string call = item.Text;
string loc = item.SubItems[1].Text;
// check if call & loc are valid
if (!Callsign.Check(call) || !MaidenheadLocator.Check(loc))
continue;
// check and update station database
LocationDesignator dxloc = LocationFindOrCreate(call, loc);
// get qrv info or create default
QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxloc.Call, dxloc.Loc, Properties.Settings.Default.Band);
// set qrv defaults if zero
if (dxqrv.AntennaHeight == 0)
dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band);
if (dxqrv.AntennaGain == 0)
dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band);
if (dxqrv.Power == 0)
dxqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band);
// find local obstruction, if any
LocalObstructionDesignator o = ElevationData.Database.LocalObstructionFind(myloc.Lat, myloc.Lon, Properties.Settings.Default.ElevationModel);
double mybearing = LatLon.Bearing(myloc.Lat, myloc.Lon, dxloc.Lat, dxloc.Lon);
double myobstr = (o != null) ? o.GetObstruction(myqrv.AntennaHeight, mybearing) : double.MinValue;
// try to find elevation path in database or create new one and store
ElevationPathDesignator epath = ElevationData.Database.ElevationPathFindOrCreateFromLatLon(
null,
myloc.Lat,
myloc.Lon,
dxloc.Lat,
dxloc.Lon,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel);
// try to find propagation path in database or create new one and store
PropagationPathDesignator ppath = PropagationData.Database.PropagationPathFindOrCreateFromLatLon(
null,
myloc.Lat,
myloc.Lon,
GetElevation(myloc.Lat, myloc.Lon) + myqrv.AntennaHeight,
dxloc.Lat,
dxloc.Lon,
GetElevation(dxloc.Lat, dxloc.Lon) + dxqrv.AntennaHeight,
Bands.ToGHz(Properties.Settings.Default.Band),
LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].K_Factor,
Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].F1_Clearance,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel,
myobstr);
// add additional info to ppath
ppath.Location1 = myloc;
ppath.Location2 = dxloc;
ppath.QRV1 = myqrv;
ppath.QRV2 = dxqrv;
// add path to paths list
ElevationPaths.Add(epath);
PropagationPaths.Add(ppath);
}
}
// calculate the area to show in map
// initially set to my location
double minlat = myloc.Lat;
double minlon = myloc.Lon;
double maxlat = myloc.Lat;
double maxlon = myloc.Lon;
double centerlat = myloc.Lat;
double centerlon = myloc.Lon;
// now do the drawing
foreach (PropagationPathDesignator ppath in PropagationPaths)
{
DrawPath(ppath);
// maintain Min/Max values
minlat = Math.Min(minlat, ppath.Lat2);
minlon = Math.Min(minlon, ppath.Lon2);
maxlat = Math.Max(maxlat, ppath.Lat2);
maxlon = Math.Max(maxlon, ppath.Lon2);
}
// show diagram when in SINGLE mode
if (PathMode == AIRSCOUTPATHMODE.SINGLE)
{
// both Elevationpaths & PropagationPaths should contain only one entry
if ((ElevationPaths.Count > 0) && (PropagationPaths.Count > 0))
UpdateCharts(ElevationPaths[ElevationPaths.Count - 1], PropagationPaths[PropagationPaths.Count - 1]);
}
// calculate center
centerlat = LatLon.MidPoint(minlat, minlon, maxlat, maxlon).Lat;
centerlon = LatLon.MidPoint(minlat, minlon, maxlat, maxlon).Lon;
// ensure that whole path is visible and optionally centered
gm_Main.SetZoomToFitRect(RectLatLng.FromLTRB(minlon, maxlat, maxlon, minlat));
if (Properties.Settings.Default.Map_AutoCenter)
gm_Main.Position = new PointLatLng(centerlat, centerlon);
// clear all selections
SelectedPlanes.Clear();
// update watchlist locations in map
UpdateWatchlistInMap();
// update status window
UpdateStatus();
// invalidate tracking
Properties.Settings.Default.Track_SetAz = double.NaN;
Properties.Settings.Default.Track_SetEl = double.NaN;
// speed up background calculations
Properties.Settings.Default.Background_Calculations_ThreadWait = 0;
st.Stop();
Log.WriteMessage("UpdatePath finished, " + st.ElapsedMilliseconds.ToString() + "ms.");
}
#endregion
#region Charts
private void UpdateCharts(ElevationPathDesignator epath, PropagationPathDesignator ppath)
{
// updates the diagram area
short[] epoints = new short[0];
PropagationPoint[] ppoints = new PropagationPoint[0];
try
{
ClearCharts();
// adjust diagram axes
Path_X.Maximum = ppath.Distance;
Elevation_X.Maximum = epath.Distance;
// get infopoints for charting
epoints = epath.GetInfoPoints();
ppoints = ppath.GetInfoPoints();
// calculate epsilon for LOS
double eps_los = Propagation.EpsilonFromHeights(GetElevation(ppath.Lat1, ppath.Lon1) + ppath.QRV1.AntennaHeight, ppath.Distance, GetElevation(ppath.Lat2, ppath.Lon2) + ppath.QRV2.AntennaHeight, LatLon.Earth.Radius);
// fill chart
short maxelv = short.MinValue;
double myelev = GetElevation(ppath.Lat1, ppath.Lon1);
for (int i = 0; i < epoints.Length; i++)
{
Path_Elevation.Points.Add(new OxyPlot.DataPoint(i, epoints[i]));
Min_H1.Points.Add(new OxyPlot.DataPoint(i, ppoints[i].H1));
Min_H2.Points.Add(new OxyPlot.DataPoint(i, ppoints[i].H2));
Max_H.Points.Add(new OxyPlot.DataPoint(i, Properties.Settings.Default.Planes_MaxAlt));
Min_H.Points.Add(new OxyPlot.DataPoint(i, Properties.Settings.Default.Planes_MaxAlt));
Min_H.Points2.Add(new OxyPlot.DataPoint(i, GetMinH(Properties.Settings.Default.Planes_MaxAlt, Min_H1.Points[i].Y, Min_H2.Points[i].Y)));
LOS.Points.Add(new OxyPlot.DataPoint(i, Propagation.HeightFromEpsilon(myelev + ppath.QRV1.AntennaHeight, i, eps_los, LatLon.Earth.Radius)));
Elevation.Points.Add(new OxyPlot.DataPoint(i, epoints[i]));
if (maxelv < epoints[i])
maxelv = epoints[i];
}
// adjust Y-axis --> max elv + 10%
Elevation_Y.Maximum = maxelv + maxelv * 0.1;
// invalidate plots
pm_Path.InvalidatePlot(true);
pm_Elevation.InvalidatePlot(true);
// show path legends
Charts_ShowLegends(5000);
// refresh path info
tp_Elevation.Text = "Pathinfo ";
if (Properties.Settings.Default.ElevationModel == ELEVATIONMODEL.SRTM1)
tp_Elevation.Text = tp_Elevation.Text + "[SRTM1]";
else if (Properties.Settings.Default.ElevationModel == ELEVATIONMODEL.SRTM3)
tp_Elevation.Text = tp_Elevation.Text + "[SRTM3]";
else if (Properties.Settings.Default.ElevationModel == ELEVATIONMODEL.GLOBE)
tp_Elevation.Text = tp_Elevation.Text + "[GLOBE]";
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void ClearCharts()
{
try
{
// clear all points
Path_Elevation.Points.Clear();
Min_H1.Points.Clear();
Min_H2.Points.Clear();
Max_H.Points.Clear();
Min_H.Points.Clear();
Min_H.Points2.Clear();
Planes_Hi.Points.Clear();
Planes_Lo.Points.Clear();
Elevation.Points.Clear();
LOS.Points.Clear();
// update view
pm_Path.InvalidatePlot(true);
pm_Elevation.InvalidatePlot(true);
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void Charts_ShowLegends(int ms)
{
// enable path legends for some seconds
pm_Path.IsLegendVisible = true;
pm_Path.InvalidatePlot(true);
pm_Elevation.IsLegendVisible = true;
pm_Elevation.InvalidatePlot(true);
ti_ShowLegends.Interval = ms;
ti_ShowLegends.Start();
}
private void ti_ShowLegends_Tick(object sender, EventArgs e)
{
pm_Path.IsLegendVisible = false;
pm_Path.InvalidatePlot(true);
pm_Elevation.IsLegendVisible = false;
pm_Elevation.InvalidatePlot(true);
ti_ShowLegends.Enabled = false;
}
private void pv_Path_Paint(object sender, PaintEventArgs e)
{
// draw calsign s on chart
string mycall = Properties.Settings.Default.MyCall;
string dxcall = Properties.Settings.Default.DXCall;
int top = pv_Path.Bottom - pv_Path.Height / 2;
int left = pv_Path.Left + 50;
int right = pv_Path.Width - 38;
Font font = new Font(FontFamily.GenericSansSerif, 8, FontStyle.Bold);
Graphics g = e.Graphics;
using (StringFormat format = new StringFormat(StringFormatFlags.DirectionVertical))
{
// measure text to emulate TextAlign.Middle
int mywidth = (int)g.MeasureString(mycall, font).Width;
int dxwidth = (int)g.MeasureString(dxcall, font).Width;
using (SolidBrush brush = new SolidBrush(Color.Black))
{
if (pv_Path.Height - 50 > mywidth)
g.DrawString(mycall, font, brush, left, top - mywidth / 2, format);
if (pv_Path.Height - 50 > dxwidth)
g.DrawString(dxcall, font, brush, right, top - dxwidth / 2, format);
/*
if (pv_Path.Height > 2 * mywidth + 50)
g.DrawString(mycall, font, brush, left, top, format);
if (pv_Path.Height > 2 * dxwdith + 50)
g.DrawString(dxcall, font, brush, right, top, format);
*/
}
}
}
#endregion
#region Planes
private static Bitmap RotateImageByAngle(System.Drawing.Image oldBitmap, float angle)
{
var newBitmap = new Bitmap(oldBitmap.Width, oldBitmap.Height);
var graphics = Graphics.FromImage(newBitmap);
graphics.TranslateTransform((float)oldBitmap.Width / 2, (float)oldBitmap.Height / 2);
graphics.RotateTransform(angle);
graphics.TranslateTransform(-(float)oldBitmap.Width / 2, -(float)oldBitmap.Height / 2);
graphics.DrawImage(oldBitmap, new System.Drawing.Point(0, 0));
return newBitmap;
}
private GMarkerGoogle CreatePlaneSimple(PlaneInfo info, bool selected)
{
// return on empty info
if (info == null)
return null;
// show flight info only
// get bitmap according to category
Bitmap bm;
int bmindex = bmindex_gray;
Brush brush = new SolidBrush(Color.FromArgb(180, Color.White));
if (info.Potential == 100)
{
bmindex = bmindex_magenta;
brush = new SolidBrush(Color.FromArgb(150, Color.Plum));
}
else if (info.Potential == 75)
{
bmindex = bmindex_red;
brush = new SolidBrush(Color.FromArgb(150, Color.Red));
}
else if (info.Potential == 50)
{
bmindex = bmindex_darkorange;
brush = new SolidBrush(Color.FromArgb(150, Color.DarkOrange));
}
if (info.Category == PLANECATEGORY.SUPERHEAVY)
bm = new Bitmap(il_Planes_S.Images[bmindex]);
else if (info.Category == PLANECATEGORY.HEAVY)
bm = new Bitmap(il_Planes_H.Images[bmindex]);
else if (info.Category == PLANECATEGORY.MEDIUM)
bm = new Bitmap(il_Planes_M.Images[bmindex]);
else if (info.Category == PLANECATEGORY.LIGHT)
bm = new Bitmap(il_Planes_L.Images[bmindex]);
else
bm = new Bitmap(il_Planes_M.Images[bmindex]);
GMarkerGoogle m = new GMarkerGoogle(new PointLatLng(info.Lat, info.Lon), ToolTipFont, RotateImageByAngle(bm, (float)info.Track));
m.Tag = info.Hex;
string lat = "";
if (info.Lat >= 0)
lat = Math.Abs(info.Lat).ToString("00.00") + "°N";
else
lat = Math.Abs(info.Lat).ToString("00.00") + "°S";
string lon = "";
if (info.Lon >= 0)
lon = Math.Abs(info.Lon).ToString("000.00") + "°E";
else
lon = Math.Abs(info.Lon).ToString("000.00") + "°W";
m.ToolTipText = info.Call + "\n--------------------";
if (Properties.Settings.Default.InfoWin_Position)
m.ToolTipText += "\nPos: " + lat + " , " + lon;
if (Properties.Settings.Default.InfoWin_Alt)
{
if (Properties.Settings.Default.InfoWin_Metric)
m.ToolTipText += "\nAlt: " + (int)info.Alt_m + "m";
else
m.ToolTipText += "\nAlt: " + (int)info.Alt + "ft";
}
if (Properties.Settings.Default.InfoWin_Track)
m.ToolTipText += "\nTrack: " + (int)info.Track + "°";
if (Properties.Settings.Default.InfoWin_Type)
m.ToolTipText += "\nType: " + info.Manufacturer + " " + info.Model + " [" + PlaneCategories.GetShortStringValue(info.Category) + "]";
// set tooltip on if hot
if (selected)
m.ToolTipMode = MarkerTooltipMode.Always;
else
m.ToolTipMode = MarkerTooltipMode.OnMouseOver;
if (m.ToolTip != null)
m.ToolTip.Fill = brush;
return m;
}
private GMarkerGoogle CreatePlaneDetailed(PlaneInfo info, bool selected)
{
// return on empty info
if (info == null)
return null;
// get bitmap according to category
Bitmap bm;
int bmindex = bmindex_gray;
Brush brush = new SolidBrush(Color.FromArgb(180, Color.White));
if (info.Potential == 100)
{
bmindex = bmindex_magenta;
brush = new SolidBrush(Color.FromArgb(150, Color.Plum));
}
else if (info.Potential == 75)
{
bmindex = bmindex_red;
brush = new SolidBrush(Color.FromArgb(150, Color.Red));
}
else if (info.Potential == 50)
{
bmindex = bmindex_darkorange;
brush = new SolidBrush(Color.FromArgb(150, Color.DarkOrange));
}
if (info.Category == PLANECATEGORY.SUPERHEAVY)
bm = new Bitmap(il_Planes_S.Images[bmindex]);
else if (info.Category == PLANECATEGORY.HEAVY)
bm = new Bitmap(il_Planes_H.Images[bmindex]);
else if (info.Category == PLANECATEGORY.MEDIUM)
bm = new Bitmap(il_Planes_M.Images[bmindex]);
else if (info.Category == PLANECATEGORY.LIGHT)
bm = new Bitmap(il_Planes_L.Images[bmindex]);
else
bm = new Bitmap(il_Planes_M.Images[bmindex]);
GMarkerGoogle m = new GMarkerGoogle(new PointLatLng(info.Lat, info.Lon), ToolTipFont, RotateImageByAngle(bm, (float)info.Track));
m.Tag = info.Hex;
string lat = "";
if (info.Lat >= 0)
lat = Math.Abs(info.Lat).ToString("00.00") + "°N";
else
lat = Math.Abs(info.Lat).ToString("00.00") + "°S";
string lon = "";
if (info.Lon >= 0)
lon = Math.Abs(info.Lon).ToString("000.00") + "°E";
else
lon = Math.Abs(info.Lon).ToString("000.00") + "°W";
int mins = 0;
if (info.Speed > 0)
mins = (int)(info.IntQRB / UnitConverter.kts_kmh(info.Speed) * 60.0);
// fill tooltip texts
m.ToolTipText = info.Call + "\n--------------------";
if (Properties.Settings.Default.InfoWin_Position)
m.ToolTipText += "\nPos: " + lat + " , " + lon;
if (Properties.Settings.Default.InfoWin_Alt)
{
if (Properties.Settings.Default.InfoWin_Metric)
m.ToolTipText += "\nAlt: " + (int)info.Alt_m + "m [" + info.AltDiff.ToString("+#;-#;0") + "m]";
else
m.ToolTipText += "\nAlt: " + (int)info.Alt + "ft [" + UnitConverter.m_ft(info.AltDiff).ToString("+#;-#;0") + "ft]";
}
if (Properties.Settings.Default.InfoWin_Track)
m.ToolTipText += "\nTrack: " + info.Track + "°";
if (Properties.Settings.Default.InfoWin_Speed)
{
if (Properties.Settings.Default.InfoWin_Metric)
m.ToolTipText += "\nSpeed: " + info.Speed_kmh.ToString("F0") + "km/h";
else
m.ToolTipText += "\nSpeed: " + info.Speed.ToString("F0") + "kts";
}
if (Properties.Settings.Default.InfoWin_Type)
m.ToolTipText += "\nType: " + info.Manufacturer + " " + info.Model + " [" + PlaneCategories.GetShortStringValue(info.Category) + "]";
if (Properties.Settings.Default.InfoWin_Dist)
{
if (Properties.Settings.Default.InfoWin_Metric)
m.ToolTipText += "\nDist: " + info.IntQRB.ToString("F0") + "km";
else
m.ToolTipText += "\nDist: " + UnitConverter.km_mi(info.IntQRB).ToString("F0") + "mi";
}
if (Properties.Settings.Default.InfoWin_Time)
m.ToolTipText += "\nTime: " + (CurrentTime + new TimeSpan(0, mins, 0)).ToString("HH:mm") + " [ " + mins.ToString("") + "min]";
if (Properties.Settings.Default.InfoWin_Angle)
m.ToolTipText += "\nAngle: " + (info.Angle / Math.PI * 180.0).ToString("F0") + "°";
if (Properties.Settings.Default.InfoWin_Epsilon)
m.ToolTipText += "\nEps: " + (info.Eps1 / Math.PI * 180.0).ToString("00.00") + "° <> " + (info.Eps2 / Math.PI * 180.0).ToString("00.00") + "°";
if (Properties.Settings.Default.InfoWin_Squint)
m.ToolTipText += "\nSquint: " + (info.Squint / Math.PI * 180).ToString("00.00") + "°";
if (selected)
{
m.ToolTipMode = MarkerTooltipMode.Always;
}
else
{
m.ToolTipMode = MarkerTooltipMode.OnMouseOver;
}
if (m.ToolTip != null)
m.ToolTip.Fill = brush;
return m;
}
private void DrawPlanes()
{
bool alarm = false;
bool isselected = false;
string alarm_msg = "";
List<PlaneInfo> pathplanes = new List<PlaneInfo>();
// check if any plane is on list --> return empty list
if ((ActivePlanes == null) || (ActivePlanes.Count == 0))
return;
// draw all planes
foreach (PlaneInfo plane in ActivePlanes.Values)
{
try
{
// show planes if it meets filter criteria
if ((plane.Alt_m >= Properties.Settings.Default.Planes_MinAlt) && (plane.Category >= Properties.Settings.Default.Planes_Filter_Min_Category))
{
// check selected state
isselected = SelectedPlanes.IndexOf(plane.Hex) >= 0;
// now, show plane according to potential
switch (plane.Potential)
{
case 100:
gmo_Planes.Markers.Add(CreatePlaneDetailed(plane, isselected));
// set alarm
if (plane.IntQRB < Properties.Settings.Default.Alarm_Distance)
{
alarm = true;
alarm_msg = plane.Call;
}
break;
case 75:
gmo_Planes.Markers.Add(CreatePlaneDetailed(plane, isselected));
// set alarm
if (plane.IntQRB < Properties.Settings.Default.Alarm_Distance)
{
alarm = true;
alarm_msg = plane.Call;
}
break;
case 50:
gmo_Planes.Markers.Add(CreatePlaneDetailed(plane, isselected));
break;
default:
gmo_Planes.Markers.Add(CreatePlaneSimple(plane, isselected));
break;
}
// count the planes drawed and update caption
gb_Map.Text = "Map [" + gmo_Planes.Markers.Count.ToString() + " plane(s)]";
// if selected: draw the thin path to crossing point if one
if (isselected)
{
if (plane.IntPoint != null)
{
GMapRoute intpath = new GMapRoute(plane.Call);
intpath.Stroke = new Pen(Color.Black, 1);
intpath.Points.Add(new PointLatLng(plane.Lat, plane.Lon));
intpath.Points.Add(new PointLatLng(plane.IntPoint.Lat, plane.IntPoint.Lon));
gmo_Routes.Routes.Add(intpath);
// Console.WriteLine(DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss") + ";" + info.IntQRB.ToString("F3"));
}
// track plane, if enabled
if (Properties.Settings.Default.Track_Activate)
{
double az = LatLon.Bearing(Properties.Settings.Default.MyLat,
Properties.Settings.Default.MyLon,
plane.Lat,
plane.Lon);
// calculate elevation
// TODO: adjust K-Factor to settings
double h = (GetElevation(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon) + Properties.Settings.Default.MyHeight) / 1000;
double H = plane.Alt_m / 1000.0;
double dist = LatLon.Distance(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, plane.Lat, plane.Lon);
double el = Propagation.EpsilonFromHeights(h, dist, H, (LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].K_Factor) / Math.PI * 180);
// set tracking values
Properties.Settings.Default.Track_SetAz = az;
Properties.Settings.Default.Track_SetEl = el;
}
}
// show planes on chart if in sigle path mode
if (PathMode == AIRSCOUTPATHMODE.SINGLE)
{
if ((plane.IntPoint != null) && (plane.IntQRB <= Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].MaxDistance))
{
// calculate distance from mylat/mylon
double dist = LatLon.Distance(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, plane.IntPoint.Lat, plane.IntPoint.Lon);
// add new data points
if (plane.AltDiff > 0)
{
Planes_Hi.Points.Add(new DataPoint(dist, plane.Alt_m));
}
else
{
Planes_Lo.Points.Add(new DataPoint(dist, plane.Alt_m));
}
}
}
}
// invalidate chart
pm_Path.InvalidatePlot(true);
// set alarm if one
if (alarm)
Alarm(alarm_msg);
// stop tracking if selected object is lost for any reason
if (!isselected)
{
Properties.Settings.Default.Track_SetAz = double.NaN;
Properties.Settings.Default.Track_SetEl = double.NaN;
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
}
private void UpdatePlanes()
{
// get current time
// update status
UpdateStatus();
// check for filter settings
// and color filter box
int planes_filter_minalt = 0;
planes_filter_minalt = Properties.Settings.Default.Planes_Filter_Min_Alt;
if (planes_filter_minalt < 0)
planes_filter_minalt = 0;
if ((planes_filter_minalt != 0) || (Properties.Settings.Default.Planes_Filter_Min_Category > PLANECATEGORY.LIGHT))
{
pa_Planes_Filter.BackColor = Color.Plum;
}
else
{
pa_Planes_Filter.BackColor = SystemColors.Control;
}
Stopwatch st = new Stopwatch();
st.Start();
List<PlaneInfo> allplanes = Planes.GetAll(CurrentTime, Properties.Settings.Default.Planes_Position_TTL);
// TODO: maintain selected status
st.Stop();
// Log.WriteMessage("Getting plane positions from database: " + allplanes.Count().ToString() + " plane(s), " + st.ElapsedMilliseconds.ToString() + " ms.");
// clear active planes
ActivePlanes.Clear();
foreach (PropagationPathDesignator ppath in PropagationPaths)
{
st.Reset();
st.Start();
NearestPlane = null;
// get nearest planes per path
List<PlaneInfo> nearestplanes = AircraftData.Database.GetNearestPlanes(DateTime.UtcNow, ppath, allplanes, Properties.Settings.Default.Planes_Filter_Max_Circumcircle, Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].MaxDistance, Properties.Settings.Default.Planes_MaxAlt);
foreach (PlaneInfo plane in nearestplanes)
{
// add or update plane in active planes list
PlaneInfo activeplane;
if (ActivePlanes.TryGetValue(plane.Hex, out activeplane))
{
// plane found --> update if necessary
bool update = false;
// plane has higher potential
if (plane.Potential > activeplane.Potential)
update = true;
// plane has same potetial but is nearer to path
else if ((plane.Potential == activeplane.Potential) && (plane.IntQRB < activeplane.IntQRB))
update = true;
// update if necessary
if (update)
{
ActivePlanes.Remove(activeplane.Hex);
ActivePlanes.Add(plane.Hex, plane);
}
}
else
{
// add plane to list if not foound
ActivePlanes.Add(plane.Hex, plane);
}
// maintain nearest plane info
// check if plane is within MaxDistance
if (plane.IntQRB < Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].MaxDistance)
{
if (NearestPlane == null)
{
// set first nearest plane info anyway
NearestPlane = plane;
}
// use higher potential anyway
if (plane.Potential > NearestPlane.Potential)
{
NearestPlane = plane;
}
else if (plane.Potential == NearestPlane.Potential)
{
// use nearer plane if same potential
if (plane.IntQRB < NearestPlane.IntQRB)
NearestPlane = plane;
}
}
}
st.Stop();
// Log.WriteMessage("Get nearest planes: " + ActivePlanes.Count.ToString() + " plane(s), " + st.ElapsedMilliseconds.ToString() + " ms.");
}
st.Start();
// clear planes overlay in map
gmo_Planes.Clear();
// clear all routes except paths
gmo_Routes.Clear();
// clear data points in chart
Planes_Hi.Points.Clear();
Planes_Lo.Points.Clear();
// draw planes
DrawPlanes();
st.Stop();
// Log.WriteMessage("Drawing planes: " + ActivePlanes.Count.ToString() + " plane(s), " + st.ElapsedMilliseconds.ToString() + " ms.");
}
#endregion
#region Watchlist
private void UpdateWatchlistInMap()
{
// show callsigns from watchlist
gmo_Callsigns.Clear();
if (!Properties.Settings.Default.Watchlist_Activated)
return;
// create new watchlist if null
if (Properties.Settings.Default.Watchlist == null)
Properties.Settings.Default.Watchlist = new Watchlist();
foreach (WatchlistItem item in Properties.Settings.Default.Watchlist)
{
// nasty!! Should never be null!
if (item == null)
continue;
LocationDesignator dxloc = LocationFindOrCreate(item.Call, item.Loc);
GMarkerGoogle gm = new GMarkerGoogle(new PointLatLng(dxloc.Lat, dxloc.Lon), ToolTipFont, (dxloc.Source == GEOSOURCE.FROMUSER) ? GMarkerGoogleType.green_small : GMarkerGoogleType.white_small);
gm.ToolTipText = dxloc.Call;
gm.ToolTipMode = MarkerTooltipMode.OnMouseOver;
gm.Tag = dxloc.Call;
gmo_Callsigns.Markers.Add(gm);
}
}
private void RefreshWatchlistView()
{
// set watchlistupdating flag
WatchlistUpdating = true;
// update listview
lv_Control_Watchlist.BeginUpdate();
lv_Control_Watchlist.Items.Clear();
foreach (WatchlistItem item in Properties.Settings.Default.Watchlist)
{
// nasty!! Should never be null!
if (item == null)
continue;
LocationDesignator dxcall = StationData.Database.LocationFindOrCreate(item.Call, item.Loc);
ListViewItem lvi = new ListViewItem(item.Call);
lvi.Name = "Call";
ListViewItem.ListViewSubItem lsi = new ListViewItem.ListViewSubItem(lvi, item.Loc);
lsi.Name = "Loc";
lvi.SubItems.Add(lsi);
lv_Control_Watchlist.Items.Add(lvi);
if (item.Checked)
lvi.Checked = true;
if (item.Selected)
lvi.Selected = true;
// tag item as "Out of Range"
if (item.OutOfRange)
{
lvi.Tag = "OOR";
lvi.ForeColor = Color.LightGray;
}
else
{
lvi.BackColor = (dxcall.Source == GEOSOURCE.FROMUSER) ? Color.PaleGreen : Color.White;
}
}
lv_Control_Watchlist.Sort();
lv_Control_Watchlist.EndUpdate();
// reset watchlistupdating flag
WatchlistUpdating = false;
}
#endregion
#region User Interface
private void MapDlg_SizeChanged(object sender, EventArgs e)
{
try
{
// ensure that the Info panel is fully visible
// set the splitter according to Info panel width
int dist = sc_Main.Width - gb_Map_Info_Width - 5;
if ((dist > 0) && (dist < sc_Main.Width))
sc_Main.SplitterDistance = dist;
// set the infowin height according to window size
// int height = sc_Main.Height - gb_CommonInfo.Height - gb_Map_Buttons.Height - 5;
// tc_ControlPanel.Height = height;
}
catch
{
// do nothing if window is minimized or otherwise invisible
}
}
private void MapDlg_Resize(object sender, EventArgs e)
{
}
private void ti_Progress_Tick(object sender, EventArgs e)
{
if (LifeMode == AIRSCOUTLIFEMODE.LIFE)
{
if (PlayMode == AIRSCOUTPLAYMODE.FORWARD)
{
// update current time
if (Properties.Settings.Default.Time_Mode_Online)
{
CurrentTime = DateTime.UtcNow;
UpdatePlanes();
}
}
}
else if (LifeMode == AIRSCOUTLIFEMODE.HISTORY)
{
if (PlayMode != AIRSCOUTPLAYMODE.PAUSE)
{
Properties.Settings.Default.Time_Offline = Properties.Settings.Default.Time_Offline.AddSeconds(Time_Offline_Interval);
if (Properties.Settings.Default.Time_Offline < dtp_Analysis_MinValue.Value)
Properties.Settings.Default.Time_Offline = dtp_Analysis_MinValue.Value;
if (Properties.Settings.Default.Time_Offline > dtp_Analysis_MaxValue.Value)
Properties.Settings.Default.Time_Offline = dtp_Analysis_MaxValue.Value;
CurrentTime = Properties.Settings.Default.Time_Offline;
tb_Analysis_Time.Text = CurrentTime.ToString("yyyy-MM-hh HH:mm:ss");
double span = (CurrentTime - dtp_Analysis_MinValue.Value).TotalSeconds;
if ((span > sb_Analysis_Play.Minimum) && (span < sb_Analysis_Play.Maximum))
sb_Analysis_Play.Value = (int)span;
UpdatePlanes();
}
}
}
private void sc_Main_SplitterMoved(object sender, SplitterEventArgs e)
{
}
private void sc_Map_SplitterMoved(object sender, SplitterEventArgs e)
{
}
#region Map
private void gm_Main_OnMapZoomChanged()
{
double midlat = LatLon.MidPoint(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon).Lat;
double midlon = LatLon.MidPoint(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon).Lon;
if ((PlayMode == AIRSCOUTPLAYMODE.FORWARD) && Properties.Settings.Default.Map_AutoCenter)
gm_Main.Position = new PointLatLng(midlat, midlon);
tb_Zoom.Text = gm_Main.Zoom.ToString();
}
private void gm_Main_OnMarkerClick(GMapMarker item, MouseEventArgs e)
{
try
{
if (e.Button == System.Windows.Forms.MouseButtons.Left)
{
// check if callsign clicked
if (item.Overlay == gmo_Callsigns)
{
string call = (string)item.Tag;
if (Callsign.Check(call) && (call != Properties.Settings.Default.MyCall))
{
if (PathMode == AIRSCOUTPATHMODE.MULTI)
{
// search call on watchlist
int index = Properties.Settings.Default.Watchlist.IndexOf(call);
if (index >= 0)
{
// toggle checked state
Properties.Settings.Default.Watchlist.ElementAt(index).Checked = !Properties.Settings.Default.Watchlist.ElementAt(index).Checked;
// refresh watchlist view
RefreshWatchlistView();
// update paths if running
if (PlayMode == AIRSCOUTPLAYMODE.FORWARD)
UpdatePaths();
}
}
}
}
// check if plane clicked
else if (item.Overlay == gmo_Planes)
{
// keep the selected state
int selectedindex = SelectedPlanes.IndexOf((string)item.Tag);
// clear all other selections if tracking is enabled
if (Properties.Settings.Default.Track_Activate)
{
SelectedPlanes.Clear();
}
// toogle selection of the selected plane
if (selectedindex >= 0)
{
// remove item from selected planes list
SelectedPlanes.RemoveAt(selectedindex);
// invalidate tracking
Properties.Settings.Default.Track_SetAz = double.NaN;
Properties.Settings.Default.Track_SetEl = double.NaN;
}
else
{
SelectedPlanes.Add((string)item.Tag);
}
}
// check if call clicked
else if (item.Overlay == gmo_Callsigns)
{
LocationDesignator ld = StationData.Database.LocationFind(item.Tag.ToString());
if (ld != null)
{
if (PlayMode != AIRSCOUTPLAYMODE.PAUSE)
this.Pause();
Properties.Settings.Default.DXCall = item.Tag.ToString();
Properties.Settings.Default.DXLat = ld.Lat;
Properties.Settings.Default.DXLon = ld.Lon;
UpdateStatus();
this.Play();
}
}
}
if (e.Button == System.Windows.Forms.MouseButtons.Right)
{
// new for tracking antenna
if ((string)item.Tag == Properties.Settings.Default.DXCall)
{
// Right click on DXCall needle --> set antenna position
// get antenna direction
double qtf = LatLon.Bearing(Properties.Settings.Default.MyLat,
Properties.Settings.Default.MyLon,
Properties.Settings.Default.DXLat,
Properties.Settings.Default.DXLon);
// store new QTF in properties
lock (Properties.Settings.Default)
{
Properties.Settings.Default.Track_SetAz = qtf;
Properties.Settings.Default.Track_SetEl = 0;
}
}
}
}
catch (Exception ex)
{
// do nothing if item not found in planes list
Log.WriteMessage(ex.Message);
}
}
private void gm_Main_OnMarkerEnter(GMapMarker item)
{
if (((item == gmm_MyLoc) || (item == gmm_DXLoc)) && !isDraggingMarker)
gmm_CurrentMarker = item;
}
private void gm_Main_OnMarkerLeave(GMapMarker item)
{
}
private void gm_Main_MouseDown(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Left && gmm_CurrentMarker != null && gmm_CurrentMarker.IsMouseOver)
isDraggingMarker = true;
}
private void gm_Main_MouseMove(object sender, MouseEventArgs e)
{
}
private void gm_Main_MouseUp(object sender, MouseEventArgs e)
{
if (isDraggingMarker)
{
isDraggingMarker = false;
}
}
private void gm_Main_Paint(object sender, PaintEventArgs e)
{
// paint gauges on top of the map if enabled
if (Properties.Settings.Default.Track_Activate &&
(Properties.Settings.Default.Track_SetAz >= 0) &&
(Properties.Settings.Default.Track_SetAz <= 360) &&
(Properties.Settings.Default.Track_SetEl >= 0) &&
(Properties.Settings.Default.Track_SetEl <= 90))
{
// update gauges
ag_Azimuth.Value = (float)Properties.Settings.Default.Track_SetAz;
ag_Elevation.Value = (float)Properties.Settings.Default.Track_SetEl;
// draw elements
int ofsX = ag_Azimuth.Left;
int ofsY = ag_Azimuth.Top;
ag_Azimuth.DrawDialText(e.Graphics, ofsX, ofsY);
ag_Azimuth.DisplayNumber(e.Graphics, ofsX, ofsY);
ag_Azimuth.DrawCalibration(e.Graphics, ofsX, ofsY);
ag_Azimuth.DrawCenterPoint(e.Graphics, ofsX, ofsY);
ag_Azimuth.DrawPointer(e.Graphics, ofsX, ofsY);
ofsX = ag_Elevation.Left;
ofsY = ag_Elevation.Top;
ag_Elevation.DrawDialText(e.Graphics, ofsX, ofsY);
ag_Elevation.DisplayNumber(e.Graphics, ofsX, ofsY);
ag_Elevation.DrawCalibration(e.Graphics, ofsX, ofsY);
ag_Elevation.DrawCenterPoint(e.Graphics, ofsX, ofsY);
ag_Elevation.DrawPointer(e.Graphics, ofsX, ofsY);
}
}
private void gm_Main_SizeChanged(object sender, EventArgs e)
{
// adjust position of gauges
ag_Azimuth.Left = gm_Main.Right - ag_Azimuth.Width - ag_Elevation.Width - 40;
ag_Azimuth.Top = gm_Main.Bottom - ag_Azimuth.Height - 20;
ag_Elevation.Left = gm_Main.Right - ag_Elevation.Width - 20;
ag_Elevation.Top = gm_Main.Bottom - ag_Elevation.Height - 20;
}
#endregion
#region Right Controls
private void cb_Band_SelectedIndexChanged(object sender, EventArgs e)
{
if (cb_Band.SelectedItem != null)
Properties.Settings.Default.Band = Bands.ParseStringValue((string)cb_Band.SelectedItem);
else Properties.Settings.Default.Band = BAND.BNONE;
SaveUserSettings();
Properties.Settings.Default.Reload();
}
#region Tab Control Control Panel
private void tc_Control_DrawItem(object sender, DrawItemEventArgs e)
{
// This event is called once for each tab button in your tab control
// First paint the background with a color based on the current tab
// e.Index is the index of the tab in the TabPages collection.
switch (e.Index)
{
case 0:
e.Graphics.FillRectangle(new SolidBrush(SystemColors.Control), e.Bounds);
break;
case 1:
e.Graphics.FillRectangle(new SolidBrush(SystemColors.Control), e.Bounds);
break;
case 2:
e.Graphics.FillRectangle(new SolidBrush((Properties.Settings.Default.Planes_Filter_Min_Category > PLANECATEGORY.LIGHT) ? Color.Plum : SystemColors.Control), e.Bounds);
break;
default:
break;
}
// Then draw the current tab button text
Rectangle paddedBounds = e.Bounds;
paddedBounds.Inflate(-2, -2);
e.Graphics.DrawString(tc_Control.TabPages[e.Index].Text, tc_Control.Font, (tc_Control.Enabled) ? SystemBrushes.ControlText : SystemBrushes.GrayText, paddedBounds);
}
#region Single Tab
private void tp_Control_Single_Enter(object sender, EventArgs e)
{
if (PathMode != AIRSCOUTPATHMODE.SINGLE)
{
PathMode = AIRSCOUTPATHMODE.SINGLE;
// restore splitter distance
sc_Map.SplitterDistance = CurrentMapSplitterDistance;
}
}
private void gb_Map_Info_MouseClick(object sender, MouseEventArgs e)
{
// get font size in pixels
double pixels;
using (Graphics g = this.CreateGraphics())
{
pixels = gb_Map_Info.Font.SizeInPoints * g.DpiX / 72;
}
if ((e.Y <= pixels) && (e.Button == MouseButtons.Left))
{
Properties.Settings.Default.Map_ShowInfoBox = !Properties.Settings.Default.Map_ShowInfoBox;
}
}
private void cb_MyCall_TextChanged(object sender, EventArgs e)
{
Console.WriteLine("cb_MyCall_TextChanged: " + cb_MyCall.Text);
int i = cb_MyCall.SelectionStart;
Properties.Settings.Default.MyCall = cb_MyCall.Text;
// clear locator entries
cb_MyLoc.Text = "";
cb_MyLoc.Items.Clear();
Properties.Settings.Default.MyLat = double.NaN;
Properties.Settings.Default.MyLon = double.NaN;
Properties.Settings.Default.MyElevation = 0;
if (Callsign.Check(cb_MyCall.Text))
{
// select last recent loc
LocationDesignator ld = StationData.Database.LocationFind(cb_MyCall.Text);
if (ld != null)
{
Properties.Settings.Default.MyLat = ld.Lat;
Properties.Settings.Default.MyLon = ld.Lon;
Properties.Settings.Default.MyElevation = GetElevation(ld.Lat, ld.Lon);
}
}
UpdateStatus();
cb_MyCall.Select(i, 0);
}
private void cb_MyCall_SelectedIndexChanged(object sender, EventArgs e)
{
if (cb_MyCall.SelectedItem != null)
{
cb_MyCall.Text = cb_MyCall.SelectedItem.ToString();
LocationDesignator ld = StationData.Database.LocationFind(cb_MyCall.Text);
if (Callsign.Check(cb_MyCall.Text) && (ld != null))
{
// update Settings
cb_MyLoc.Text = MaidenheadLocator.LocFromLatLon(ld.Lat, ld.Lon, Properties.Settings.Default.Locator_SmallLettersForSubsquares, (int)Properties.Settings.Default.Locator_MaxLength / 2, Properties.Settings.Default.Locator_AutoLength);
Properties.Settings.Default.MyCall = cb_MyCall.Text;
Properties.Settings.Default.MyLat = ld.Lat;
Properties.Settings.Default.MyLon = ld.Lon;
Properties.Settings.Default.MyElevation = GetElevation(ld.Lat, ld.Lon);
Properties.Settings.Default.MyHeight = 10;
}
else
{
Properties.Settings.Default.MyLat = double.NaN;
Properties.Settings.Default.MyLon = double.NaN;
Properties.Settings.Default.MyElevation = 0;
Properties.Settings.Default.MyHeight = 0;
}
UpdateStatus();
}
}
private void cb_MyCall_DropDown(object sender, EventArgs e)
{
// poulate from MyCalls last recent collection
// populate drop down list
cb_MyCall.Items.Clear();
foreach (string call in Properties.Settings.Default.MyCalls)
{
cb_MyCall.Items.Add(call);
}
}
private void cb_MyLoc_TextChanged(object sender, EventArgs e)
{
if (cb_MyLoc.Focused)
{
if (MaidenheadLocator.Check(cb_MyLoc.Text) && (cb_MyLoc.Text.Length >= 6))
{
Properties.Settings.Default.MyLat = cb_MyLoc.GeoLocation.Lat;
Properties.Settings.Default.MyLon = cb_MyLoc.GeoLocation.Lon;
Properties.Settings.Default.MyElevation = GetElevation(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
Properties.Settings.Default.MyHeight = 10;
// colour Textbox if more precise lat/lon information is available
if (MaidenheadLocator.IsPrecise(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, 3))
{
cb_MyLoc.BackColor = Color.PaleGreen;
}
UpdateStatus();
}
else
{
cb_MyLoc.BackColor = Color.FloralWhite;
}
}
}
private void cb_MyLoc_DropDown(object sender, EventArgs e)
{
// fill MyLoc combo box with all known locators
cb_MyLoc.BackColor = Color.FloralWhite;
cb_MyLoc.SilentText = "";
cb_MyLoc.Items.Clear();
List<LocationDesignator> lds = StationData.Database.LocationFindAll(cb_MyCall.Text);
if (lds != null)
{
// fill item list of locator box
foreach (LocationDesignator ld in lds)
{
LocatorDropDownItem ldd = new LocatorDropDownItem(MaidenheadLocator.LocFromLatLon(ld.Lat, ld.Lon, Properties.Settings.Default.Locator_SmallLettersForSubsquares, (int)Properties.Settings.Default.Locator_MaxLength / 2, Properties.Settings.Default.Locator_AutoLength), new LatLon.GPoint(ld.Lat, ld.Lon));
cb_MyLoc.Items.Add(ldd);
}
}
}
private void cb_MyLoc_SelectedIndexChanged(object sender, EventArgs e)
{
LocatorDropDownItem ldd = (LocatorDropDownItem)cb_MyLoc.SelectedItem;
if (ldd != null)
{
// update properties
cb_MyLoc.Precision = (int)Properties.Settings.Default.Locator_MaxLength / 2;
cb_MyLoc.SmallLettersForSubsquares = Properties.Settings.Default.Locator_SmallLettersForSubsquares;
cb_MyLoc.AutoLength = Properties.Settings.Default.Locator_AutoLength;
// set geolocation instead of text
cb_MyLoc.GeoLocation = ldd.GeoLocation;
}
}
private void cb_MyLoc_SelectionChangeCommittedWithNoUpdate(object sender, EventArgs e)
{
}
private void cb_DXCall_TextChanged(object sender, EventArgs e)
{
int i = cb_DXCall.SelectionStart;
Properties.Settings.Default.DXCall = cb_DXCall.Text;
// clear locator entries
cb_DXLoc.Text = "";
cb_DXLoc.Items.Clear();
Properties.Settings.Default.DXLat = double.NaN;
Properties.Settings.Default.DXLon = double.NaN;
Properties.Settings.Default.DXElevation = 0;
if (Callsign.Check(cb_DXCall.Text))
{
// select last recent loc
LocationDesignator ld = StationData.Database.LocationFind(cb_DXCall.Text);
if (ld != null)
{
Properties.Settings.Default.DXLat = ld.Lat;
Properties.Settings.Default.DXLon = ld.Lon;
Properties.Settings.Default.DXElevation = GetElevation(ld.Lat, ld.Lon);
}
}
UpdateStatus();
cb_DXCall.Select(i, 0);
}
private void cb_DXCall_SelectedIndexChanged(object sender, EventArgs e)
{
if (cb_DXCall.SelectedItem != null)
{
cb_DXCall.Text = cb_DXCall.SelectedItem.ToString();
LocationDesignator ld = StationData.Database.LocationFind(cb_DXCall.Text);
if (Callsign.Check(cb_DXCall.Text) && (ld != null))
{
// update Settings
cb_DXLoc.Text = MaidenheadLocator.LocFromLatLon(ld.Lat, ld.Lon, Properties.Settings.Default.Locator_SmallLettersForSubsquares, (int)Properties.Settings.Default.Locator_MaxLength / 2, Properties.Settings.Default.Locator_AutoLength);
Properties.Settings.Default.DXCall = cb_DXCall.Text;
Properties.Settings.Default.DXLat = ld.Lat;
Properties.Settings.Default.DXLon = ld.Lon;
Properties.Settings.Default.DXElevation = GetElevation(ld.Lat, ld.Lon);
Properties.Settings.Default.DXHeight = 10;
}
else
{
Properties.Settings.Default.DXLat = double.NaN;
Properties.Settings.Default.DXLon = double.NaN;
Properties.Settings.Default.DXElevation = 0;
Properties.Settings.Default.DXHeight = 0;
}
UpdateStatus();
}
}
private void cb_DXCall_DropDown(object sender, EventArgs e)
{
// populate from watchlist
// return on empty watchlist
if (Properties.Settings.Default.Watchlist == null)
return;
// populate drop down list
List<string> dxcalls = new List<string>();
foreach (WatchlistItem item in Properties.Settings.Default.Watchlist)
{
// nasty!! Should never be null!
if (item == null)
continue;
dxcalls.Add(item.Call);
}
dxcalls.Sort();
cb_DXCall.Items.Clear();
cb_DXCall.Items.AddRange(dxcalls.ToArray());
}
private void cb_DXLoc_TextChanged(object sender, EventArgs e)
{
if (cb_DXLoc.Focused)
{
if (MaidenheadLocator.Check(cb_DXLoc.Text) && (cb_DXLoc.Text.Length >= 6))
{
Properties.Settings.Default.DXLat = cb_DXLoc.GeoLocation.Lat;
Properties.Settings.Default.DXLon = cb_DXLoc.GeoLocation.Lon;
Properties.Settings.Default.DXElevation = GetElevation(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon);
Properties.Settings.Default.DXHeight = 10;
// colour Textbox if more precise lat/lon information is available
if (MaidenheadLocator.IsPrecise(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon, 3))
{
cb_DXLoc.BackColor = Color.PaleGreen;
}
UpdateStatus();
}
else
{
cb_DXLoc.BackColor = Color.FloralWhite;
}
}
}
private void cb_DXLoc_DropDown(object sender, EventArgs e)
{
// fill DXLoc combo box with all known locators
cb_DXLoc.BackColor = Color.FloralWhite;
cb_DXLoc.SilentText = "";
cb_DXLoc.Items.Clear();
List<LocationDesignator> lds = StationData.Database.LocationFindAll(cb_DXCall.Text);
if (lds != null)
{
// fill item list of locator box
foreach (LocationDesignator ld in lds)
{
LocatorDropDownItem ldd = new LocatorDropDownItem(MaidenheadLocator.LocFromLatLon(ld.Lat, ld.Lon, Properties.Settings.Default.Locator_SmallLettersForSubsquares, (int)Properties.Settings.Default.Locator_MaxLength / 2, Properties.Settings.Default.Locator_AutoLength), new LatLon.GPoint(ld.Lat, ld.Lon));
cb_DXLoc.Items.Add(ldd);
}
}
}
private void cb_DXLoc_SelectedIndexChanged(object sender, EventArgs e)
{
LocatorDropDownItem ldd = (LocatorDropDownItem)cb_DXLoc.SelectedItem;
if (ldd != null)
{
// update properties
cb_DXLoc.Precision = (int)Properties.Settings.Default.Locator_MaxLength / 2;
cb_DXLoc.SmallLettersForSubsquares = Properties.Settings.Default.Locator_SmallLettersForSubsquares;
cb_DXLoc.AutoLength = Properties.Settings.Default.Locator_AutoLength;
// set geolocation instead of text
cb_DXLoc.GeoLocation = ldd.GeoLocation;
}
}
private void cb_DXLoc_SelectionChangeCommittedWithNoUpdate(object sender, EventArgs e)
{
}
#endregion
#region Tab Multi
private void tp_Control_Multi_Enter(object sender, EventArgs e)
{
if (PathMode != AIRSCOUTPATHMODE.MULTI)
{
CurrentMapSplitterDistance = sc_Map.SplitterDistance;
PathMode = AIRSCOUTPATHMODE.MULTI;
sc_Map.SplitterDistance = gm_Main.Height + tc_Main.Height;
}
}
private void lv_Control_Watchlist_Resize(object sender, EventArgs e)
{
// list view resized
// resize locator column to fit the client size
lv_Control_Watchlist.Columns[1].Width = lv_Control_Watchlist.ClientSize.Width - lv_Control_Watchlist.Columns[0].Width;
}
private void lv_Control_Watchlist_ColumnWidthChanged(object sender, ColumnWidthChangedEventArgs e)
{
// adjust width of Locator column to list view width
if (e.ColumnIndex == 0)
{
// call sign column changed
// resize locator column to fit the client size
lv_Control_Watchlist.Columns[1].Width = lv_Control_Watchlist.ClientSize.Width - lv_Control_Watchlist.Columns[0].Width;
}
}
private void lv_Control_Watchlist_ItemChecked(object sender, ItemCheckedEventArgs e)
{
// ignore event while populating list view
if (WatchlistUpdating)
return;
// sync watchlist with list view
ListViewItem lvi = e.Item;
if (lvi == null)
return;
// search item in watchlist
int index = Properties.Settings.Default.Watchlist.IndexOf(lvi.Text, lvi.SubItems[1].Text);
if (index >= 0)
Properties.Settings.Default.Watchlist[index].Checked = lvi.Checked;
if (WatchlistAllCheckedChanging)
return;
// maintain AllChecked checkbox
foreach (ListViewItem item in lv_Control_Watchlist.Items)
{
// stop on first different checked state
if ((item != null) && (item.Checked != lvi.Checked))
{
WatchlistAllCheckedState = CheckBoxState.MixedNormal;
lv_Control_Watchlist.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.HeaderSize);
return;
}
}
// all items in the same state
WatchlistAllCheckedState = (lvi.Checked) ? CheckBoxState.CheckedNormal : CheckBoxState.UncheckedNormal;
lv_Control_Watchlist.AutoResizeColumn(0, ColumnHeaderAutoResizeStyle.HeaderSize);
}
private void lv_Control_Watchlist_ColumnClick(object sender, ColumnClickEventArgs e)
{
WatchlistAllCheckedChanging = true;
if (!WatchlistAllChecked)
{
WatchlistAllChecked = true;
WatchlistAllCheckedState = CheckBoxState.CheckedPressed;
foreach (ListViewItem item in lv_Control_Watchlist.Items)
{
// check all items within range
if ((item.Tag == null) || (item.Tag.ToString() != "OOR"))
item.Checked = true;
}
Invalidate();
}
else
{
WatchlistAllChecked = false;
WatchlistAllCheckedState = CheckBoxState.UncheckedNormal;
Invalidate();
foreach (ListViewItem item in lv_Control_Watchlist.Items)
{
item.Checked = false;
}
}
WatchlistAllCheckedChanging = false;
}
private void lv_Control_Watchlist_DrawColumnHeader(object sender, DrawListViewColumnHeaderEventArgs e)
{
TextFormatFlags flags = TextFormatFlags.LeftAndRightPadding;
e.DrawBackground();
CheckBoxRenderer.DrawCheckBox(e.Graphics, new System.Drawing.Point(ClientRectangle.Location.X + 4, ClientRectangle.Location.Y), WatchlistAllCheckedState);
e.DrawText(flags);
}
private void lv_Control_Watchlist_DrawItem(object sender, DrawListViewItemEventArgs e)
{
e.DrawDefault = true;
}
private void lv_Control_Watchlist_DrawSubItem(object sender, DrawListViewSubItemEventArgs e)
{
e.DrawDefault = true;
}
private void btn_Control_Manage_Watchlist_Click(object sender, EventArgs e)
{
WatchlistDlg Dlg = new WatchlistDlg();
if (Dlg.ShowDialog() == DialogResult.OK)
{
// sync watchlist
foreach (WatchlistItem item in Properties.Settings.Default.Watchlist)
{
// nasty!! Should never be null!
if (item == null)
continue;
item.Remove = true;
}
foreach (ListViewItem lvi in Dlg.lv_Watchlist_Selected.Items)
{
// search item in watchlist
int index = Properties.Settings.Default.Watchlist.IndexOf(lvi.Text);
// reset remove flag if found, create and add new entry if not
if (index >= 0)
Properties.Settings.Default.Watchlist[index].Remove = false;
else
{
// try to find last recent locator from database and add to watchlist
LocationDesignator dxcall = StationData.Database.LocationFindLastRecent(lvi.Text);
if (dxcall != null)
{
double qrb = LatLon.Distance(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, dxcall.Lat, dxcall.Lon);
Properties.Settings.Default.Watchlist.Add(new WatchlistItem(dxcall.Call, dxcall.Loc, qrb > Properties.Settings.Default.Path_MaxLength));
}
}
}
// remove the rest of items
Properties.Settings.Default.Watchlist.RemoveAll(item => item.Remove);
// refersh watchlist view
RefreshWatchlistView();
}
}
private void ShowToolTip(ToolTip tt, string text, Control control, System.Drawing.Point p, int ms = 5000)
{
if (String.IsNullOrEmpty(text))
return;
// int BorderWidth = this.Width – this.ClientSize.Width)/2;
// int TitlebarHeight = this.Height – this.ClientSize.Height – 2 * BorderWidth;
int BorderWith = (this.Width - this.ClientSize.Width) / 2;
int TitleBarHeight = this.Height - this.ClientSize.Height - 2 * BorderWith;
p = control.PointToScreen(p);
p = this.PointToClient(p);
p.X = p.X + BorderWith;
p.Y = p.Y + TitleBarHeight + Cursor.Size.Height;
tt.Show(text, this, p, ms);
}
private void lv_Control_Watchlist_ItemMouseHover(object sender, ListViewItemMouseHoverEventArgs e)
{
}
private void lv_Control_Watchlist_MouseMove(object sender, MouseEventArgs e)
{
try
{
System.Drawing.Point p = new System.Drawing.Point(e.X, e.Y);
ListViewHitTestInfo info = lv_Control_Watchlist.HitTest(p);
if ((WatchlistOldMousePos != p) && (info != null) && (info.SubItem != null))
{
WatchlistOldMousePos = p;
// check whether the column name is one of the following
if (info.SubItem.Name == "Call")
{
string dxcall = info.Item.SubItems[0].Text;
string dxloc = info.Item.SubItems[1].Text;
LocationDesignator ld = StationData.Database.LocationFind(dxcall, dxloc);
// location found --> show Tooltip with details
if (ld != null)
{
string qrb = LatLon.Distance(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, ld.Lat, ld.Lon).ToString("F0", CultureInfo.InvariantCulture);
string qtf = LatLon.Bearing(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, ld.Lat, ld.Lon).ToString("F0", CultureInfo.InvariantCulture);
ShowToolTip(tt_Control_Watchlist, dxcall + "\n" + dxloc + "\n" + qrb + " km\n" + qtf + "°", lv_Control_Watchlist, p);
}
}
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
#endregion
#region Tab Options
private void tp_Control_Options_Enter(object sender, EventArgs e)
{
// set plane filter
try
{
cb_Planes_Filter_Min_Cat.SelectedItem = PlaneCategories.GetStringValue(Properties.Settings.Default.Planes_Filter_Min_Category);
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void gb_Map_Zoom_MouseClick(object sender, MouseEventArgs e)
{
// get font size in pixels
double pixels;
using (Graphics g = this.CreateGraphics())
{
pixels = gb_Map_Zoom.Font.SizeInPoints * g.DpiX / 72;
}
if ((e.Y <= pixels) && (e.Button == MouseButtons.Left))
{
Properties.Settings.Default.Map_ShowZoomBox = !Properties.Settings.Default.Map_ShowZoomBox;
}
}
private void gb_Map_Filter_MouseClick(object sender, MouseEventArgs e)
{
// get font size in pixels
double pixels;
using (Graphics g = this.CreateGraphics())
{
pixels = gb_Map_Filter.Font.SizeInPoints * g.DpiX / 72;
}
if ((e.Y <= pixels) && (e.Button == MouseButtons.Left))
{
Properties.Settings.Default.Map_ShowFilterBox = !Properties.Settings.Default.Map_ShowFilterBox;
}
}
private void gb_Map_Alarms_MouseClick(object sender, MouseEventArgs e)
{
// get font size in pixels
double pixels;
using (Graphics g = this.CreateGraphics())
{
pixels = gb_Map_Alarms.Font.SizeInPoints * g.DpiX / 72;
}
if ((e.Y <= pixels) && (e.Button == MouseButtons.Left))
{
Properties.Settings.Default.Map_ShowAlarmBox = !Properties.Settings.Default.Map_ShowAlarmBox;
}
}
private void btn_Zoom_In_Click(object sender, EventArgs e)
{
if (gm_Main.Zoom < 20)
gm_Main.Zoom++;
}
private void btn_Zoom_Out_Click(object sender, EventArgs e)
{
if (gm_Main.Zoom > 0)
gm_Main.Zoom--;
}
private void cb_Planes_Filter_Min_Category_SelectedIndexChanged(object sender, EventArgs e)
{
try
{
Properties.Settings.Default.Planes_Filter_Min_Category = PlaneCategories.ParseStringValue((string)cb_Planes_Filter_Min_Cat.SelectedItem);
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
#endregion
#endregion
#region Buttons
private void btn_Options_Click(object sender, EventArgs e)
{
ShowOptionsDlg();
}
private void btn_Map_Save_Click(object sender, EventArgs e)
{
MapSave();
}
private void btn_Map_PlayPause_Click(object sender, EventArgs e)
{
if (PlayMode != AIRSCOUTPLAYMODE.FORWARD)
{
Play();
}
else
{
Pause();
}
}
#endregion
#endregion
#region Main Tab Control
private void tc_Main_SelectedIndexChanged(object sender, EventArgs e)
{
// restore splitter distance
if (tc_Main.SelectedTab != tp_News)
sc_Map.SplitterDistance = CurrentMapSplitterDistance;
}
private void tc_Main_DrawItem(object sender, DrawItemEventArgs e)
{
// This event is called once for each tab button in your tab control
// First paint the background with a color based on the current tab
// e.Index is the index of the tab in the TabPages collection.
// fill background
e.Graphics.FillRectangle(new SolidBrush(SystemColors.Control), e.Bounds);
// Then draw the current tab button text
Rectangle paddedBounds = e.Bounds;
paddedBounds.Inflate(-2, -2);
e.Graphics.DrawString(tc_Main.TabPages[e.Index].Text, tc_Main.Font, (tc_Main.Enabled) ? SystemBrushes.ControlText : SystemBrushes.GrayText, paddedBounds);
}
#region Tab Page News
private void tp_News_Enter(object sender, EventArgs e)
{
CurrentMapSplitterDistance = sc_Map.SplitterDistance;
// adjust splitter to maximum if not running under Linux/Mono
if (!SupportFunctions.IsMono)
sc_Map.SplitterDistance = 200;
}
#endregion
#region Tab Page Spectrum
private void tp_Spectrum_Enter(object sender, EventArgs e)
{
// adjust splitter back to normal
sc_Map.SplitterDistance = CurrentMapSplitterDistance;
}
private void tp_Spectrum_Resize(object sender, EventArgs e)
{
// adjust group boxes
// get quadratical nearest plane box
gb_NearestPlaneMap.Width = gb_NearestPlaneMap.Height;
gb_NearestPlaneMap.Left = tp_Spectrum.Width - gb_NearestPlaneMap.Width - 5;
// adjust plane info box
gb_Spectrum_NearestInfo.Left = tp_Spectrum.Width - gb_NearestPlaneMap.Width - gb_Spectrum_NearestInfo.Width - 10;
// adjust spectrum box
gb_Spectrum.Width = tp_Spectrum.Width - gb_NearestPlaneMap.Width - gb_Spectrum_NearestInfo.Width - 30;
tb_Spectrum_Status.Left = 5;
tb_Spectrum_Status.Width = pv_Spectrum.Width - 10;
}
#endregion
#region Tab Page Elevation
private void tp_Elevation_Enter(object sender, EventArgs e)
{
// adjust splitter back to normal
sc_Map.SplitterDistance = CurrentMapSplitterDistance;
}
private void tp_Elevation_Resize(object sender, EventArgs e)
{
// adjust charts
pv_Path.Location = new System.Drawing.Point(0, 0);
pv_Path.Width = tp_Elevation.Width;
pv_Path.Height = tp_Elevation.Height / 2;
pv_Elevation.Location = new System.Drawing.Point(0, tp_Elevation.Height / 2);
pv_Elevation.Width = tp_Elevation.Width;
pv_Elevation.Height = tp_Elevation.Height / 2;
}
#endregion
#region Tab Page Analysis
private void UpdatePlayer()
{
// set players bounds
sb_Analysis_Play.Minimum = 0;
sb_Analysis_Play.Maximum = (int)(dtp_Analysis_MaxValue.Value - dtp_Analysis_MinValue.Value).TotalSeconds;
sb_Analysis_Play.Value = 0;
}
private void tp_Analysis_Enter(object sender, EventArgs e)
{
if (LifeMode == AIRSCOUTLIFEMODE.LIFE)
{
btn_Analysis_ON.Enabled = true;
btn_Analysis_ON.BackColor = Color.YellowGreen;
btn_Analysis_OFF.Enabled = false;
btn_Analysis_OFF.BackColor = Color.Gray;
}
else
{
btn_Analysis_ON.Enabled = false;
btn_Analysis_ON.BackColor = Color.Gray;
btn_Analysis_OFF.Enabled = true;
btn_Analysis_OFF.BackColor = Color.LightCoral;
}
SayAnalysis("Press <ON> to start analysis.");
}
private void tp_Analysis_Leave(object sender, EventArgs e)
{
}
private void btn_Analysis_ON_Click(object sender, EventArgs e)
{
SayAnalysis("Getting database properties, please wait...");
// go into offline mode
btn_Analysis_ON.Enabled = false;
btn_Analysis_ON.BackColor = Color.Gray;
btn_Analysis_OFF.Enabled = true;
btn_Analysis_OFF.BackColor = Color.LightCoral;
btn_Map_PlayPause.Enabled = false;
LifeMode = AIRSCOUTLIFEMODE.HISTORY;
PlayMode = AIRSCOUTPLAYMODE.PAUSE;
if (!bw_Analysis_DataGetter.IsBusy)
bw_Analysis_DataGetter.RunWorkerAsync();
}
private void btn_Analysis_OFF_Click(object sender, EventArgs e)
{
if (bw_Analysis_FileSaver.IsBusy)
bw_Analysis_FileSaver.CancelAsync();
if (bw_Analysis_FileLoader.IsBusy)
bw_Analysis_FileLoader.CancelAsync();
if (bw_Analysis_DataGetter.IsBusy)
{
SayAnalysis("Cancelling background thread, please wait...");
bw_Analysis_DataGetter.CancelAsync();
}
else
{
btn_Analysis_ON.Enabled = true;
btn_Analysis_ON.BackColor = Color.YellowGreen;
}
lock (AllPositions)
{
AllPositions.Clear();
}
GC.Collect();
// go into online mode
btn_Analysis_OFF.Enabled = false;
btn_Analysis_OFF.BackColor = Color.Gray;
btn_Analysis_Planes_Load.Enabled = false;
btn_Analysis_Planes_Save.Enabled = false;
btn_Analysis_Planes_Clear.Enabled = false;
btn_Analysis_Planes_History.Enabled = false;
btn_Analysis_Planes_ShowTraffic.Enabled = false;
btn_Analysis_Path_SaveToFile.Enabled = false;
btn_Analysis_CrossingHistory.Enabled = false;
btn_Analysis_Plane_History.Enabled = false;
btn_Analysis_Rewind.Enabled = false;
btn_Analysis_Back.Enabled = false;
btn_Analysis_Pause.Enabled = false;
btn_Analysis_Forward.Enabled = false;
btn_Analysis_FastForward.Enabled = false;
sb_Analysis_Play.Enabled = false;
dtp_Analysis_MinValue.Enabled = false;
dtp_Analysis_MaxValue.Enabled = false;
btn_Map_PlayPause.Enabled = true;
LifeMode = AIRSCOUTLIFEMODE.LIFE;
PlayMode = AIRSCOUTPLAYMODE.PAUSE;
UpdateStatus();
btn_Map_PlayPause.Focus();
}
private void btn_Analysis_Planes_Save_Click(object sender, EventArgs e)
{
try
{
SaveFileDialog Dlg = new SaveFileDialog();
Dlg.AddExtension = true;
Dlg.Filter = "Java Script Object Notation File|*.json|Comma Separated Values|*.csv";
Dlg.DefaultExt = "json";
Dlg.FileName = "Plane Positions " + dtp_Analysis_MinValue.Value.ToString("yyyy_MM_dd_HH_mm_ss") + " to " + dtp_Analysis_MaxValue.Value.ToString("yyyy_MM_dd_HH_mm_ss");
Dlg.InitialDirectory = TmpDirectory;
Dlg.OverwritePrompt = true;
if (Dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if (!bw_Analysis_FileSaver.IsBusy)
{
btn_Analysis_Planes_Save.Enabled = false;
bw_Analysis_FileSaver.RunWorkerAsync(Dlg.FileName);
}
}
}
catch (Exception ex)
{
Say(ex.Message);
Log.WriteMessage(ex.ToString());
}
}
private void btn_Analysis_Planes_Load_Click(object sender, EventArgs e)
{
try
{
OpenFileDialog Dlg = new OpenFileDialog();
Dlg.Filter = "Java Script Object Notation File|*.json|Comma Separated Values|*.csv";
Dlg.DefaultExt = "json";
Dlg.CheckFileExists = true;
Dlg.CheckPathExists = true;
Dlg.Multiselect = false;
Dlg.InitialDirectory = TmpDirectory;
if (Dlg.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
if (!bw_Analysis_FileLoader.IsBusy)
{
btn_Analysis_Planes_Load.Enabled = false;
bw_Analysis_FileLoader.RunWorkerAsync(Dlg.FileName);
}
}
}
catch (Exception ex)
{
Say(ex.Message);
Log.WriteMessage(ex.ToString());
}
}
private void btn_Analysis_Planes_Clear_Click(object sender, EventArgs e)
{
AircraftPositionData.Database.AircraftPositionDeleteAll();
}
private void btn_Analysis_Planes_History_Click(object sender, EventArgs e)
{
HistoryFromURLDlg Dlg = new HistoryFromURLDlg();
if (Dlg.ShowDialog() == DialogResult.OK)
{
btn_Analysis_Planes_History.Enabled = false;
bw_HistoryDownloader.RunWorkerAsync(Properties.Settings.Default.Analysis_History_Date);
}
}
private void btn_Analysis_Planes_ShowTraffic_Click(object sender, EventArgs e)
{
TrafficDlg Dlg = new TrafficDlg();
Dlg.ShowDialog();
}
private void btn_Analysis_Path_SaveToFile_Click(object sender, EventArgs e)
{
SaveFileDialog Dlg = new SaveFileDialog();
Dlg.CheckPathExists = true;
Dlg.AddExtension = true;
Dlg.DefaultExt = "csv";
Dlg.Filter = "Comma Separated Values *.csv |csv";
Dlg.FileName = "Path Information " + Properties.Settings.Default.MyCall.Replace("/", "_") + " to " + Properties.Settings.Default.DXCall.Replace("/", "_");
Dlg.InitialDirectory = TmpDirectory;
Dlg.OverwritePrompt = true;
if (Dlg.ShowDialog() == DialogResult.OK)
{
try
{
// calculate propagation path
// check and update station database
LocationDesignator myloc = LocationFindOrUpdateOrCreate(Properties.Settings.Default.MyCall, Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
Properties.Settings.Default.MyElevation = myloc.Elevation;
// get qrv info or create default
QRVDesignator myqrv = StationData.Database.QRVFindOrCreateDefault(myloc.Call, myloc.Loc, Properties.Settings.Default.Band);
// set qrv defaults if zero
if (myqrv.AntennaHeight == 0)
myqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band);
if (myqrv.AntennaGain == 0)
myqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band);
if (myqrv.Power == 0)
myqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band);
// check if there are a valid DX settings
if (!Callsign.Check(Properties.Settings.Default.DXCall) ||
!GeographicalPoint.Check(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon))
return;
// OK valid, lets continue
// check and update station database
LocationDesignator dxloc = LocationFindOrUpdateOrCreate(Properties.Settings.Default.DXCall, Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon);
Properties.Settings.Default.DXElevation = dxloc.Elevation;
// get qrv info or create default
QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxloc.Call, dxloc.Loc, Properties.Settings.Default.Band);
// set qrv defaults if zero
if (dxqrv.AntennaHeight == 0)
dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band);
if (dxqrv.AntennaGain == 0)
dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band);
if (dxqrv.Power == 0)
dxqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band);
// find local obstruction, if any
LocalObstructionDesignator o = ElevationData.Database.LocalObstructionFind(myloc.Lat, myloc.Lon, Properties.Settings.Default.ElevationModel);
double mybearing = LatLon.Bearing(myloc.Lat, myloc.Lon, dxloc.Lat, dxloc.Lon);
double myobstr = (o != null) ? o.GetObstruction(myqrv.AntennaHeight, mybearing) : double.MinValue;
// try to find elevation path in database or create new one and store
ElevationPathDesignator epath = ElevationData.Database.ElevationPathFindOrCreateFromLatLon(
null,
myloc.Lat,
myloc.Lon,
dxloc.Lat,
dxloc.Lon,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel);
// add additional info to ppath
epath.Location1 = myloc;
epath.Location2 = dxloc;
epath.QRV1 = myqrv;
epath.QRV2 = dxqrv;
// try to find propagation path in database or create new one and store
PropagationPathDesignator ppath = PropagationData.Database.PropagationPathFindOrCreateFromLatLon(
null,
myloc.Lat,
myloc.Lon,
GetElevation(myloc.Lat, myloc.Lon) + myqrv.AntennaHeight,
dxloc.Lat,
dxloc.Lon,
GetElevation(dxloc.Lat, dxloc.Lon) + dxqrv.AntennaHeight,
Bands.ToGHz(Properties.Settings.Default.Band),
LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].K_Factor,
Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].F1_Clearance,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel,
myobstr);
// add additional info to ppath
ppath.Location1 = myloc;
ppath.Location2 = dxloc;
ppath.QRV1 = myqrv;
ppath.QRV2 = dxqrv;
using (StreamWriter sw = new StreamWriter(Dlg.FileName))
{
sw.WriteLine("Distance[km];Lat[deg];Lon[deg];Elevation[m]; Min_h1[m]; Min_h2[m]; Min_h[m]; Max_h[m]; F1[m];eps1[deg];eps2[deg];eps1_min[deg];eps2_min[deg];ElevationModel");
for (int i = 0; i < epath.Count; i++)
{
double dist = (double)i * epath.StepWidth / 1000.0;
PropagationPoint p = ppath.GetInfoPoint(dist);
sw.WriteLine(dist.ToString() + ";" +
p.Lat.ToString() + ";" +
p.Lon.ToString() + ";" +
epath.Path[i].ToString() + ";" +
p.H1.ToString() + ";" +
p.H2.ToString() + ";" +
Math.Max(p.H1, p.H2).ToString() + ";" +
Properties.Settings.Default.Planes_MaxAlt.ToString() + ";" +
p.F1.ToString() + ";" +
(Propagation.EpsilonFromHeights(ppath.h1, dist, epath.Path[i],ppath.Radius) / Math.PI * 180.0).ToString() + ";" +
(Propagation.EpsilonFromHeights(ppath.h2, ppath.Distance-dist, epath.Path[i], ppath.Radius) / Math.PI * 180.0).ToString() + ";" +
(ppath.Eps1_Min / Math.PI * 180.0).ToString() + ";" +
(ppath.Eps2_Min / Math.PI * 180.0).ToString());
}
}
}
catch (Exception ex)
{
Log.WriteMessage("Error while saving path to file [" + Dlg.FileName + "]:" + ex.ToString());
}
}
}
private void btn_Analysis_CrossingHistory_Click(object sender, EventArgs e)
{
if (dtp_Analysis_MaxValue.Value <= dtp_Analysis_MinValue.Value)
return;
if (Time_Offline_Interval <= 0)
Time_Offline_Interval = 1;
if ((AllPositions == null) || (AllPositions.Count == 0))
return;
CrossingHistoryDlg Dlg = new CrossingHistoryDlg(dtp_Analysis_MinValue.Value, dtp_Analysis_MaxValue.Value, Time_Offline_Interval, ref AllPositions);
Dlg.ShowDialog();
}
private void sb_Analysis_Play_SizeChanged(object sender, EventArgs e)
{
// handle change of scrollbar
// set scrollbar markers
// reduce them to one marker per pixel
// get initial scrollbar width and build array
int[] sb = new int[sb_Analysis_Play.Width];
double stepwidth = (double)sb.Length / (sb_Analysis_Play.Maximum - sb_Analysis_Play.Minimum);
foreach (DateTime dt in AllLastUpdated)
{
int index = (int)((dt - dtp_Analysis_MinValue.Value).TotalSeconds * stepwidth);
int i = (int)(dt - dtp_Analysis_MinValue.Value).TotalSeconds;
if ((i > sb_Analysis_Play.Minimum) && (i < sb_Analysis_Play.Maximum))
sb[index] = i;
}
sb_Analysis_Play.BackgroundMarkers = sb.ToList<int>();
}
private void gb_Analysis_Player_SizeChanged(object sender, EventArgs e)
{
// handle change of size --> arrange elements
sb_Analysis_Play.Left = dtp_Analysis_MinValue.Right + 10;
sb_Analysis_Play.Width = dtp_Analysis_MaxValue.Left - dtp_Analysis_MinValue.Width - 20;
sb_Analysis_Play.Height = dtp_Analysis_MinValue.Height;
}
private void btn_Analysis_Rewind_Click(object sender, EventArgs e)
{
PlayMode = AIRSCOUTPLAYMODE.FASTBACK;
Time_Offline_Interval -= 10;
if (Time_Offline_Interval < 1)
Time_Offline_Interval = 1;
tb_Analysis_Stepwidth.Text = Time_Offline_Interval.ToString();
}
private void btn_Analysis_Back_Click(object sender, EventArgs e)
{
PlayMode = AIRSCOUTPLAYMODE.BACK;
Time_Offline_Interval -= 1;
if (Time_Offline_Interval < 1)
Time_Offline_Interval = 1;
tb_Analysis_Stepwidth.Text = Time_Offline_Interval.ToString();
}
private void btn_Analysis_Pause_Click(object sender, EventArgs e)
{
PlayMode = AIRSCOUTPLAYMODE.PAUSE;
Time_Offline_Interval = 0;
tb_Analysis_Stepwidth.Text = Time_Offline_Interval.ToString();
}
private void btn_Analysis_Forward_Click(object sender, EventArgs e)
{
PlayMode = AIRSCOUTPLAYMODE.FORWARD;
Time_Offline_Interval += 1;
if (Time_Offline_Interval > 3600)
Time_Offline_Interval = 3600;
tb_Analysis_Stepwidth.Text = Time_Offline_Interval.ToString();
}
private void btn_Analysis_FastForward_Click(object sender, EventArgs e)
{
PlayMode = AIRSCOUTPLAYMODE.FASTFORWARD;
Time_Offline_Interval += 10;
if (Time_Offline_Interval > 3600)
Time_Offline_Interval = 3600;
tb_Analysis_Stepwidth.Text = Time_Offline_Interval.ToString();
}
private void sb_Analysis_Play_Scroll(object sender, ScrollEventArgs e)
{
// PlayMode = AIRSCOUTPLAYMODE.PAUSE;
// Time_Offline_Interval = 0;
tb_Analysis_Stepwidth.Text = Time_Offline_Interval.ToString();
Properties.Settings.Default.Time_Offline = dtp_Analysis_MinValue.Value.AddSeconds(sb_Analysis_Play.Value);
if (Properties.Settings.Default.Time_Offline < dtp_Analysis_MinValue.Value)
Properties.Settings.Default.Time_Offline = dtp_Analysis_MinValue.Value;
if (Properties.Settings.Default.Time_Offline > dtp_Analysis_MaxValue.Value)
Properties.Settings.Default.Time_Offline = dtp_Analysis_MaxValue.Value;
CurrentTime = Properties.Settings.Default.Time_Offline;
tb_Analysis_Time.Text = CurrentTime.ToString("yyyy-MM-hh HH:mm:ss");
UpdatePlanes();
}
private void dtp_Analysis_MinValue_ValueChanged(object sender, EventArgs e)
{
// check bounds
if (dtp_Analysis_MinValue.Value < History_OldestEntry)
dtp_Analysis_MinValue.Value = History_OldestEntry;
if (dtp_Analysis_MinValue.Value > History_YoungestEntry)
dtp_Analysis_MinValue.Value = History_YoungestEntry;
UpdatePlayer();
}
private void dtp_Analysis_MaxValue_ValueChanged(object sender, EventArgs e)
{
// check bounds
if (dtp_Analysis_MinValue.Value < History_OldestEntry)
dtp_Analysis_MinValue.Value = History_OldestEntry;
if (dtp_Analysis_MinValue.Value > History_YoungestEntry)
dtp_Analysis_MinValue.Value = History_YoungestEntry;
UpdatePlayer();
}
private void btn_Analysis_Plane_History_Click(object sender, EventArgs e)
{
PlaneHistoryDlg Dlg = new PlaneHistoryDlg(dtp_Analysis_MinValue.Value, dtp_Analysis_MaxValue.Value, TmpDirectory);
Dlg.ShowDialog();
}
#endregion
#endregion
#endregion
#region Background Workers
#region PlaneFeed
private void bw_PlaneFeed_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == (int)PROGRESS.STATUS)
{
if (e.UserState == null)
return;
Say((string)e.UserState);
}
else if (e.ProgressPercentage == (int)PROGRESS.PLANES)
{
List<PlaneInfo> planes = (List<PlaneInfo>)e.UserState;
Planes.BulkInsertOrUpdateIfNewer(planes);
}
}
#endregion
#region WinTestReceive
// suppress console output when in debug mode, needs "Just my code" set in Tools\Options\Debugging
[System.Diagnostics.DebuggerNonUserCode]
private void bw_WinTestReceive_DoWork(object sender, DoWorkEventArgs e)
{
// Background thread for receiving Win-Test messages
// listens to the UDP broadcasts
// use the ReportProgress method to
// return status code and received message
// status values are: <0 = error orrcured (not supported yet)
// 0 = function calls OK, but no bytes received
// >0 = function calls OK, number of bytes received
Log.WriteMessage("Started.");
if (Thread.CurrentThread.Name == null)
Thread.CurrentThread.Name = "bw_WinTestReceive";
// Get own IP addresses
string hostname;
IPAddress[] hostaddresses = new IPAddress[256];
try
{
hostname = Dns.GetHostName();
hostaddresses = Dns.GetHostAddresses(hostname);
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
// initialize UDP socket
IPEndPoint ep = new IPEndPoint(IPAddress.Any, Properties.Settings.Default.Server_Port);
UdpClient u = new UdpClient();
u.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
u.Client.ReceiveTimeout = 1000;
try
{
u.Client.Bind(ep);
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
// receive Win-Test messages in a loop
while (!bw_WinTestReceive.CancellationPending)
{
try
{
// receive bytes in blocking mode
// handle the receive timeout and cancellation
try
{
byte[] data = u.Receive(ref ep);
wtMessage Msg = new wtMessage(data);
// check if message is directed to server
if (Msg.Dst == Properties.Settings.Default.Server_Name)
DispatchWinTestMsg(Msg);
}
catch (SocketException ex)
{
// do nothing
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
Log.WriteMessage("Finished.");
}
private void ASShowPath(wtMessage msg)
{
// a show path message received
try
{
Stopwatch st = new Stopwatch();
st.Start();
if (PlayMode != AIRSCOUTPLAYMODE.PAUSE)
Pause();
// set single mode
tc_Control.SelectedTab = tp_Control_Single;
PathMode = AIRSCOUTPATHMODE.SINGLE;
string[] a = msg.Data.Split(',');
string qrgstr = a[0].Replace("\"", "");
string mycallstr = a[1].Replace("\"", "");
string myloc = a[2].Replace("\"", "").Substring(0, 6);
double mylat = MaidenheadLocator.LatFromLoc(myloc);
double mylon = MaidenheadLocator.LonFromLoc(myloc);
string dxcallstr = a[3].Replace("\"", "");
string dxloc = a[4].Replace("\"", "").Substring(0, 6);
double dxlat = MaidenheadLocator.LatFromLoc(dxloc);
double dxlon = MaidenheadLocator.LonFromLoc(dxloc);
if (Callsign.Check(mycallstr) &&
Callsign.Check(dxcallstr) &&
MaidenheadLocator.Check(myloc) &&
MaidenheadLocator.Check(dxloc))
{
Properties.Settings.Default.MyCall = mycallstr;
Properties.Settings.Default.MyLat = mylat;
Properties.Settings.Default.MyLon = mylon;
Properties.Settings.Default.MyHeight = 10;
Properties.Settings.Default.DXCall = dxcallstr;
Properties.Settings.Default.DXLat = dxlat;
Properties.Settings.Default.DXLon = dxlon;
Properties.Settings.Default.DXHeight = 10;
Properties.Settings.Default.MyElevation = GetElevation(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
LocationDesignator info = StationData.Database.LocationFind(mycallstr);
if ((info != null) && (MaidenheadLocator.LocFromLatLon(info.Lat, info.Lon, false, 3) == myloc))
{
// loc is matching with database --> use detailed info then
Properties.Settings.Default.MyLat = info.Lat;
Properties.Settings.Default.MyLon = info.Lon;
Properties.Settings.Default.MyElevation = GetElevation(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon);
}
else
{
// update database if not found or locator does not match
UpdateLocation(mycallstr, mylat, mylon, GEOSOURCE.FROMLOC);
}
info = StationData.Database.LocationFind(dxcallstr);
if ((info != null) && (MaidenheadLocator.LocFromLatLon(info.Lat, info.Lon, false, 3) == dxloc))
{
// loc is matching with database --> use detailed info then
Properties.Settings.Default.DXLat = info.Lat;
Properties.Settings.Default.DXLon = info.Lon;
Properties.Settings.Default.DXElevation = GetElevation(Properties.Settings.Default.DXLat, Properties.Settings.Default.DXLon);
}
else
{
// update database if not found or locator does not match
UpdateLocation(dxcallstr, dxlat, dxlon, GEOSOURCE.FROMLOC);
}
if (qrgstr == "500000")
Properties.Settings.Default.Band = BAND.B50M;
if (qrgstr == "700000")
Properties.Settings.Default.Band = BAND.B70M;
if (qrgstr == "1440000")
Properties.Settings.Default.Band = BAND.B144M;
if (qrgstr == "4320000")
Properties.Settings.Default.Band = BAND.B432M;
if (qrgstr == "12960000")
Properties.Settings.Default.Band = BAND.B1_2G;
if (qrgstr == "23200000")
Properties.Settings.Default.Band = BAND.B2_3G;
if (qrgstr == "34000000")
Properties.Settings.Default.Band = BAND.B3_4G;
if (qrgstr == "57600000")
Properties.Settings.Default.Band = BAND.B5_7G;
if (qrgstr == "103680000")
Properties.Settings.Default.Band = BAND.B10G;
if (qrgstr == "240480000")
Properties.Settings.Default.Band = BAND.B24G;
if (qrgstr == "470880000")
Properties.Settings.Default.Band = BAND.B47G;
if (qrgstr == "760320000")
Properties.Settings.Default.Band = BAND.B76G;
UpdateStatus();
Play();
// try different methods to bring the window to front under WinXP and Win7
bool max = this.WindowState == FormWindowState.Maximized;
// try to restore window from minimized and normal state --> normal state
this.TopMost = true;
SetForegroundWindow(this.Handle);
ShowWindow(this.Handle, ShowWindowCommands.ShowNoActivate);
this.BringToFront();
this.TopMost = false;
// maximize it if it was maximized before
if (max)
this.WindowState = FormWindowState.Maximized;
// set antenna direction
double az = LatLon.Bearing(Properties.Settings.Default.MyLat,
Properties.Settings.Default.MyLon,
Properties.Settings.Default.DXLat,
Properties.Settings.Default.DXLon);
// set tracking values
Properties.Settings.Default.Track_SetAz = az;
Properties.Settings.Default.Track_SetEl = 0;
}
st.Stop();
Log.WriteMessage("Processing ASSHOWPATH[" + mycallstr + "," + dxcallstr + "]: " + st.ElapsedMilliseconds.ToString() + " ms.");
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
private void ASSetPath(wtMessage msg)
{
try
{
Stopwatch st = new Stopwatch();
st.Start();
string[] a = msg.Data.Split(',');
int qrg = 1296;
int.TryParse(a[0].Replace("\"", ""), out qrg);
qrg = qrg / 10000;
BAND band = BAND.BNONE;
try
{
band = (BAND)qrg;
}
catch
{
// do nothing
}
string mycallstr = a[1].Replace("\"", "");
string mylocstr = a[2].Replace("\"", "").Substring(0, 6);
string dxcallstr = a[3].Replace("\"", "");
string dxlocstr = a[4].Replace("\"", "").Substring(0, 6);
int count = 0;
// return on failure
if (!Callsign.Check(mycallstr))
return;
if (!Callsign.Check(dxcallstr))
return;
if (!MaidenheadLocator.Check(mylocstr))
return;
if (!MaidenheadLocator.Check(dxlocstr))
return;
// get my location info --> if loc is matching, use precise information automatically
LocationDesignator myloc = StationData.Database.LocationFindOrCreate(mycallstr, mylocstr);
// get my QRV info
QRVDesignator myqrv = StationData.Database.QRVFindOrCreateDefault(mycallstr, mylocstr, band);
// set qrv defaults if zero
if (myqrv.AntennaHeight == 0)
myqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band);
if (myqrv.AntennaGain == 0)
myqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band);
if (myqrv.Power == 0)
myqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band);
// get dx location info --> if loc is matching, use precise information automatically
LocationDesignator dxloc = LocationFindOrCreate(dxcallstr, dxlocstr);
// get dx QRV info
QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxcallstr, dxlocstr, band);
// set qrv defaults if zero
if (dxqrv.AntennaHeight == 0)
dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(Properties.Settings.Default.Band);
if (dxqrv.AntennaGain == 0)
dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(Properties.Settings.Default.Band);
if (dxqrv.Power == 0)
dxqrv.Power = StationData.Database.QRVGetDefaultPower(Properties.Settings.Default.Band);
// find local obstruction, if any
LocalObstructionDesignator o = ElevationData.Database.LocalObstructionFind(myloc.Lat, myloc.Lon, Properties.Settings.Default.ElevationModel);
double mybearing = LatLon.Bearing(myloc.Lat, myloc.Lon, dxloc.Lat, dxloc.Lon);
double myobstr = (o != null) ? o.GetObstruction(myqrv.AntennaHeight, mybearing) : double.MinValue;
// try to find propagation path in database or create new one and store
PropagationPathDesignator ppath = PropagationData.Database.PropagationPathFindOrCreateFromLatLon(
null,
myloc.Lat,
myloc.Lon,
GetElevation(myloc.Lat, myloc.Lon) + myqrv.AntennaHeight,
dxloc.Lat,
dxloc.Lon,
GetElevation(dxloc.Lat, dxloc.Lon) + dxqrv.AntennaHeight,
Bands.ToGHz(Properties.Settings.Default.Band),
LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].K_Factor,
Properties.Settings.Default.Path_Band_Settings[Properties.Settings.Default.Band].F1_Clearance,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel,
myobstr);
List<PlaneInfo> allplanes = Planes.GetAll(DateTime.UtcNow, Properties.Settings.Default.Planes_Position_TTL);
List<PlaneInfo> nearestplanes = AircraftData.Database.GetNearestPlanes(DateTime.UtcNow, ppath, allplanes, Properties.Settings.Default.Planes_Filter_Max_Circumcircle, Properties.Settings.Default.Path_Band_Settings[band].MaxDistance, Properties.Settings.Default.Planes_MaxAlt);
count = 0;
string planes = "";
wtMessage SendMsg = new wtMessage(WTMESSAGES.ASNEAREST,
Properties.Settings.Default.Server_Name,
msg.Src,
DateTime.UtcNow.ToString("u") + "," +
mycallstr + "," +
mylocstr + "," +
dxcallstr + "," +
dxlocstr + ",");
if ((nearestplanes != null) && (nearestplanes.Count() > 0))
{
foreach (PlaneInfo planeinfo in nearestplanes)
{
if ((planeinfo.IntPoint != null) && (planeinfo.Potential > 0))
{
int mins = 0;
if (planeinfo.Speed > 0)
mins = (int)(planeinfo.IntQRB / (double)planeinfo.Speed / 1.852 * 60.0);
planes = planes + planeinfo.Call + "," + planeinfo.Category + "," + ((int)planeinfo.IntQRB).ToString() + "," + planeinfo.Potential.ToString() + "," + mins.ToString() + ",";
count++;
}
}
}
planes = planes.TrimEnd(',');
SendMsg.Data = SendMsg.Data + count.ToString() + "," + planes;
SendMsg.Data = SendMsg.Data.TrimEnd(',');
SendMsg.HasChecksum = true;
// send message
UdpClient client = new UdpClient();
client.Client.SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, 1);
client.Client.ReceiveTimeout = 10000; // 10s Receive timeout
IPEndPoint groupEp = new IPEndPoint(IPAddress.Broadcast, Properties.Settings.Default.Server_Port);
client.Connect(groupEp);
byte[] b = SendMsg.ToBytes();
client.Send(b, b.Length);
client.Close();
st.Stop();
Log.WriteMessage("Processing ASSETPATH[" + mycallstr + "," + dxcallstr + "]: " + count.ToString() + " Plane(s), " + st.ElapsedMilliseconds.ToString() + " ms.");
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
private void ASSWatchlist (wtMessage msg)
{
if (!Properties.Settings.Default.Watchlist_SyncWithKST)
return;
// maintain watchlist
try
{
Stopwatch st = new Stopwatch();
st.Start();
// mark all watchlist items to remove
foreach (WatchlistItem item in Properties.Settings.Default.Watchlist)
{
// nasty!! Should never be null!
if (item == null)
continue;
item.Remove = true;
}
// split message
string[] a = msg.Data.Split(',');
// ignore band string so far
string qrgstr = a[0];
// iterate through calls
for (int i = 1; i < a.Length - 1; i += 2)
{
// get call
string dxcallstr = a[i].Trim().ToUpper();
// get loc
string dxlocstr = a[i + 1].Trim().ToUpper();
// skip when invalid
if (!Callsign.Check(dxcallstr))
continue;
if (!MaidenheadLocator.Check(dxlocstr))
continue;
// skip own callsign
if (dxcallstr == Callsign.Cut(Properties.Settings.Default.MyCall))
continue;
// find or create call & loc combination in station database
LocationDesignator dxcall = StationData.Database.LocationFindOrCreate(dxcallstr, dxlocstr);
double qrb = LatLon.Distance(Properties.Settings.Default.MyLat, Properties.Settings.Default.MyLon, dxcall.Lat, dxcall.Lon);
// add to watchlist
int index = Properties.Settings.Default.Watchlist.IndexOf(dxcallstr, dxlocstr);
// reset remove flag if item found, add to watchlist if not
if (index >= 0)
{
Properties.Settings.Default.Watchlist[index].Remove = false;
Properties.Settings.Default.Watchlist[index].OutOfRange = qrb > Properties.Settings.Default.Path_MaxLength;
}
else
{
Properties.Settings.Default.Watchlist.Add(new WatchlistItem(dxcallstr, dxlocstr, qrb > Properties.Settings.Default.Path_MaxLength));
}
}
// remove all items from watchlist which are not logged in anymore
Properties.Settings.Default.Watchlist.RemoveAll(item => item.Remove);
// update watchlist in map
UpdateWatchlistInMap();
// update ListView control
RefreshWatchlistView();
st.Stop();
Log.WriteMessage("Processing ASWATCHLIST: " + Properties.Settings.Default.Watchlist.Count.ToString() + " call(s), " + st.ElapsedMilliseconds.ToString() + " ms.");
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void DispatchWinTestMsg(wtMessage msg)
{
// a Win-Test message was received by the background thread
if (msg.Msg == WTMESSAGES.ASSHOWPATH)
{
// a show path message received
// dispatch it to main thread
bw_WinTestReceive.ReportProgress(1, msg);
}
else if (msg.Msg == WTMESSAGES.ASSETPATH)
{
// a path calculation message received
// keep it in the background thread and calculate
ASSetPath(msg);
}
else if (msg.Msg == WTMESSAGES.ASWATCHLIST)
{
// set users list on watchlist
// dispatch it to main thread
bw_WinTestReceive.ReportProgress(1, msg);
}
}
private void bw_WinTestReceive_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
// a Win-Test message was received by the background thread
NumberFormatInfo provider = new NumberFormatInfo();
provider.NumberDecimalSeparator = ".";
provider.NumberGroupSeparator = ",";
provider.NumberGroupSizes = new int[] { 3 };
wtMessage msg = (wtMessage)e.UserState;
if (msg.Msg == WTMESSAGES.ASSHOWPATH)
ASShowPath(msg);
else if (msg.Msg == WTMESSAGES.ASWATCHLIST)
ASSWatchlist(msg);
}
private void bw_WinTestReceive_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
#endregion
# region SpecLabReceive
// suppress console output when in debug mode, needs "Just my code" set in Tools\Options\Debugging
// [System.Diagnostics.DebuggerNonUserCode]
private void bw_SpecLab_Receive_DoWork(object sender, DoWorkEventArgs e)
{
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_SpecLabReceive";
Log.WriteMessage("Started.");
// get the update interval
int interval = System.Convert.ToInt32(Properties.Settings.Default.SpecLab_Update) * 1000;
// check for minimum
if (interval < 1000)
interval = 1000;
bw_SpecLab_Receive.ReportProgress(0);
int maxcount = 60;
List<SignalLevelDesignator> ads = new List<SignalLevelDesignator>();
while (!bw_SpecLab_Receive.CancellationPending)
{
Thread.Sleep(interval);
// do nothing when not in play mode
if ((LifeMode != AIRSCOUTLIFEMODE.LIFE) || (PlayMode != AIRSCOUTPLAYMODE.FORWARD))
continue;
try
{
// get boundary frequencies
int f1 = Properties.Settings.Default.SpecLab_F1;
if (f1 < 0)
f1 = 0;
if (f1 > 3000)
f1 = 3000;
int f2 = Properties.Settings.Default.SpecLab_F2;
if (f2 < 1)
f2 = 1;
if (f2 > 3000)
f2 = 3000;
if (f1 >= f2)
f1 = f2 - 1;
// get the url
string url = Properties.Settings.Default.SpecLab_URL;
// get the filename
string filename = Properties.Settings.Default.SpecLab_FileName;
if (!url.EndsWith("/"))
url = url + "/";
url = url + filename + "?f1=" + f1.ToString() + "?f2=" + f2.ToString();
string msg = "";
bw_SpecLab_Receive.ReportProgress(1, "Trying to connect to Spectrum Lab...");
WebRequest myWebRequest = WebRequest.Create(url);
WebResponse myWebResponse = myWebRequest.GetResponse();
Stream ReceiveStream = myWebResponse.GetResponseStream();
Encoding encode = System.Text.Encoding.GetEncoding("utf-8");
StreamReader readStream = new StreamReader(ReceiveStream, encode);
string json = readStream.ReadToEnd();
if (!json.StartsWith("["))
throw (new FormatException("Format Exception: Not a JSON file."));
// split the JSON string
// a[1] contains the header
// h contains alle header items
// d contains all data items
string[] a = json.Split('[');
a[1] = a[1].Replace(":", ",");
string[] h = a[1].Split(',');
a[2] = a[2].Replace("\r\n", "");
a[2] = a[2].Remove(a[2].IndexOf("]") - 1);
a[2] = a[2].Replace(",", ";");
a[2] = a[2].Replace(".", ",");
double[] d = System.Array.ConvertAll(a[2].Split(';'), new Converter<string, double>(Double.Parse));
// get the time stamp
long l = (long)System.Convert.ToDouble(h[1], CultureInfo.InvariantCulture);
DateTime utc = new System.DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
utc = utc.AddSeconds(l);
// get number of bins
int count = System.Convert.ToInt32(h[13]);
msg = "FFT-Data received: " + count.ToString() + "bins. F1=" + f1.ToString() + "Hz, F2=" + f2.ToString() + "Hz";
bw_SpecLab_Receive.ReportProgress(1, msg);
double max = d.Max();
// collect and save maximum if in play mode and NearestPlane != null
if ((PlayMode == AIRSCOUTPLAYMODE.FORWARD) && (NearestPlane != null))
ads.Add(new SignalLevelDesignator(max, utc));
// bulk save maximum to database if maxcount is reached
if (ads.Count > maxcount)
{
SignalData.Database.SignalLevelBulkInsertOrUpdateIfNewer(ads);
ads.Clear();
}
// report maximum
bw_SpecLab_Receive.ReportProgress(100, max);
}
catch (WebException ex)
{
// do nothing
}
catch (SocketException ex)
{
// do nothing
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
bw_SpecLab_Receive.ReportProgress(-1, ex.Message);
}
}
Log.WriteMessage("Finished.");
}
private void bw_SpecLab_Receive_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.ProgressPercentage < 0)
{
// an error occured
tb_Spectrum_Status.ForeColor = Color.White;
tb_Spectrum_Status.BackColor = Color.Red;
tb_Spectrum_Status.Text = (string)e.UserState;
}
if (e.ProgressPercentage == 0)
{
// a init message occured
Spectrum.Points.Clear();
SpectrumPointsCount = 0;
Spectrum_X.Reset();
SpectrumRecord.Points.Clear();
}
if (e.ProgressPercentage == 1)
{
// a status message occured
tb_Spectrum_Status.ForeColor = Color.Black;
tb_Spectrum_Status.BackColor = SystemColors.Control;
tb_Spectrum_Status.Text = (string)e.UserState;
}
if (e.ProgressPercentage == 100)
{
// FFT - data received
if ((LifeMode == AIRSCOUTLIFEMODE.LIFE) && (PlayMode == AIRSCOUTPLAYMODE.FORWARD))
{
// draw data
double max = (double)e.UserState;
if (Spectrum.Points.Count >= SpectrumMaxPoints)
{
double pan = -(Spectrum_X.ScreenMax.X - Spectrum_X.ScreenMin.X) / (double)SpectrumMaxPoints;
Spectrum_X.Pan(pan);
Spectrum.Points.RemoveAt(0);
SpectrumRecord.Points.RemoveAt(0);
}
// add background area
SpectrumRecord.Fill = OxyColor.FromArgb(20, 255, 0, 255);
double on, off;
if (Spectrum_Y.Minimum < 0)
{
on = -1000;
off = 1000;
}
else
{
on = 1000;
off = -1000;
}
if (NearestPlane == null)
SpectrumRecord.Points.Add(new DataPoint(SpectrumPointsCount, off));
else
SpectrumRecord.Points.Add(new DataPoint(SpectrumPointsCount, on));
// add signal level point
Spectrum.Points.Add(new DataPoint(SpectrumPointsCount, max));
SpectrumPointsCount++;
// autoscale Y axis
double y_min = double.MaxValue;
double y_max = double.MinValue;
foreach (DataPoint p in Spectrum.Points)
{
if (p.Y > y_max)
y_max = p.Y;
if (p.Y < y_min)
y_min = p.Y;
}
// enlarge scaling Y-axis by 10% in both directions
double y_diff = (y_max - y_min) * 0.1;
Spectrum_Y.Minimum = y_min - y_diff;
Spectrum_Y.Maximum = y_max + y_diff;
pm_Spectrum.InvalidatePlot(true);
}
}
// maintain nearest plane map
if (NearestPlane != null)
{
lbl_Nearest_Call.Text = NearestPlane.Call;
lbl_Nearest_Type.Text = NearestPlane.Type;
lbl_Nearest_Cat.Text = PlaneCategories.GetStringValue(NearestPlane.Category);
lbl_Nearest_Alt.Text = NearestPlane.Alt_m.ToString("F0") + "m";
lbl_Nearest_Angle.Text = (NearestPlane.Angle / Math.PI * 180.0).ToString("F0") + "°";
lbl_Nearest_Dist.Text = NearestPlane.IntQRB.ToString("F0") + "km";
gmo_NearestPlanes.Clear();
gmo_NearestPlanes.Markers.Add(CreatePlaneDetailed(NearestPlane, false));
gm_Nearest.Position = new PointLatLng(NearestPlane.IntPoint.Lat, NearestPlane.IntPoint.Lon);
gm_Nearest.Zoom = 10;
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
private void bw_SpecLab_Receive_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
# endregion
#region Track
private bool Track_DDE_HRD(DdeClient client, double az, double el)
{
// send Az/EL vie DDE to Ham Radio Deluxe Rotor Control (HRDRotator.exe)
// no position feedback expected
if (client == null)
throw new NullReferenceException("[DDE]: Client not initialized.");
if (!client.IsConnected)
throw new InvalidOperationException("[DDE]: Client not connected.");
byte[] data;
if ((az >= 0) && (az <= 360))
{
// send azimuth data
data = Encoding.ASCII.GetBytes("SET-AZ:" + az.ToString("F1"));
client.TryPoke("PositionData", data, 1, 10000);
}
if ((el >= 0) && (el <= 90))
{
// send elevation data
data = Encoding.ASCII.GetBytes("SET-EL:" + el.ToString("F1"));
client.TryPoke("PositionData", data, 1, 10000);
}
return true;
}
private bool Track_UDP_WinTest(UdpClient client, IPEndPoint ip, double az, double el)
{
// send UDP broadcast like Win-Test
// no position feedback expected
if ((client == null) || (ip == null))
if (client == null)
throw new NullReferenceException("[UDP]: Client and/or IP endpoint not initialized.");
wtMessage msg = new wtMessage(WTMESSAGES.SETAZIMUTH, Properties.Settings.Default.Server_Name, "", "AUTO", " 00 " + az.ToString("000"));
byte[] bytes = msg.ToBytes();
client.Send(bytes, bytes.Length, ip);
return true;
}
private bool Track_UDP_AirScout(UdpClient client, IPEndPoint ip, double az, double el)
{
// send UDP broadcast like Win-Test
// no position feedback expected
if ((client == null) || (ip == null))
throw new NullReferenceException("[UDP]: Client and/or IP endpoint not initialized.");
wtMessage msg;
msg = new wtMessage(WTMESSAGES.SETAZIMUTH, Properties.Settings.Default.Server_Name, "", "AUTO", " 00 " + az.ToString("000"));
msg = new wtMessage(WTMESSAGES.SETELEVATION, Properties.Settings.Default.Server_Name, "", "AUTO", " 00 " + el.ToString("000"));
byte[] bytes = msg.ToBytes();
client.Send(bytes, bytes.Length, ip);
return true;
}
private string Serial_SendCommand(SerialPort sp, string command, bool waitanswer)
{
// sends a command via serial port (and optional wait fo answer)
if ((sp == null) || (!sp.IsOpen))
return "";
string s = "";
{
sp.WriteLine(command);
if (waitanswer)
{
s = sp.ReadLine();
s = s.Replace("\n", "");
}
}
return s;
}
private bool Track_SER__GS_232A_AZ(SerialPort sp, double az)
{
// send Az value via serial port (GS-232A protocol)
// communictaion test --> get azimuth value
if (sp == null)
throw new NullReferenceException("[Serial]: Port not initialized.");
if (!sp.IsOpen)
throw new InvalidOperationException("[Serial]: Port not open.");
// communictaion test --> get azimuth value
string s = Serial_SendCommand(sp, "C", true);
if (!s.StartsWith("+0"))
throw new FormatException("[Serial]: Wrong serial data format.");
try
{
double result = System.Convert.ToDouble(s.Substring(2, 3), CultureInfo.InvariantCulture);
}
catch
{
throw new FormatException("[Serial]: Wrong serial data format.");
}
// set azimuth value --> no feedback
Serial_SendCommand(sp, "M" + az.ToString("000"), false);
return true;
}
private bool Track_SER__GS_232A_AZEL(SerialPort sp, double az, double el)
{
// send Az/El value via serial port (GS-232A protocol)
if (sp == null)
throw new NullReferenceException("[Serial]: Port not initialized.");
if (!sp.IsOpen)
throw new InvalidOperationException("[Serial]: Port not open.");
// communictaion test --> get azimuth and elevation value
string s = Serial_SendCommand(sp, "C2", true);
if (!s.StartsWith("+0"))
throw new FormatException("[Serial]: Wrong serial data format.");
try
{
double result = System.Convert.ToDouble(s.Substring(2, 3), CultureInfo.InvariantCulture);
}
catch
{
throw new FormatException("[Serial]: Wrong serial data format.");
}
// set azimuth value --> no feedback
Serial_SendCommand(sp, "W" + az.ToString("000") + " " + el.ToString("000"), false);
return true;
}
private void Track_File_Native(double az, double el)
{
// writes a file with Az/El values in a file (native)
// Syntax: <Az value>,<El value>
using (StreamWriter sw = new StreamWriter(TmpDirectory + Path.DirectorySeparatorChar + "azel.dat"))
{
sw.WriteLine(az.ToString("F1", CultureInfo.InvariantCulture) + "," + el.ToString("F1", CultureInfo.InvariantCulture));
}
}
private void Track_File_WSJT(double az, double el)
{
// writes a file with Az/El values in a file (WSJT)
// the info is filled in the "Source" line (originally intended to follow a radio source
using (StreamWriter sw = new StreamWriter(TmpDirectory + Path.DirectorySeparatorChar + "azel.dat"))
{
string utc = DateTime.UtcNow.ToString("HH:mm:ss");
sw.WriteLine(utc + ",0,0,Moon");
sw.WriteLine(utc + ",0,0,Sun");
sw.WriteLine(utc + "," + az.ToString("F1", CultureInfo.InvariantCulture) + "," + el.ToString("F1", CultureInfo.InvariantCulture) + ",Source");
sw.WriteLine("0, 0, 0, 0, 0,Doppler, R");
}
}
private void bw_Track_DoWork(object sender, DoWorkEventArgs e)
{
Log.WriteMessage("Started.");
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_Track";
// clients and ports
DdeClient ddeclient = null;
UdpClient udpclient = null;
IPEndPoint udpip = null;
SerialPort serialport = null;
// error counters
int ddeerr = 0;
int udperr = 0;
int serialerr = 0;
int maxerr = 10;
// outer loop
do
{
// intializations
if (Properties.Settings.Default.Track_DDE_HRD)
{
ddeclient = new DdeClient("HRDRotator", "Position");
int result = ddeclient.TryConnect();
}
if (Properties.Settings.Default.Track_UDP_WinTest)
{
udpclient = new UdpClient();
udpip = new IPEndPoint(IPAddress.Broadcast, Properties.Settings.Default.Track_UDP_WinTest_Port);
}
else if (Properties.Settings.Default.Track_UDP_AirScout)
{
udpclient = new UdpClient();
udpip = new IPEndPoint(IPAddress.Broadcast, Properties.Settings.Default.Track_UDP_AirScout_Port);
}
if ((Properties.Settings.Default.Track_Serial_GS232_AZ) || (Properties.Settings.Default.Track_Serial_GS232_AZEL))
{
serialport = new SerialPort(Properties.Settings.Default.Track_Serial_Port,
Properties.Settings.Default.Track_Serial_Baudrate,
Parity.None,
8,
StopBits.One);
serialport.Handshake = System.IO.Ports.Handshake.None;
serialport.NewLine = "\r";
serialport.Encoding = Encoding.ASCII;
serialport.ReadTimeout = 1000;
serialport.WriteTimeout = 1000;
serialport.Open();
}
// inner loop
while (Properties.Settings.Default.Track_Activate && !bw_Track.CancellationPending)
{
try
{
// tracking
double az = Properties.Settings.Default.Track_SetAz;
double el = Properties.Settings.Default.Track_SetEl;
if (!double.IsNaN(az) && !double.IsNaN(el))
{
if (Properties.Settings.Default.Track_DDE_HRD)
Track_DDE_HRD(ddeclient, az, el);
if (Properties.Settings.Default.Track_UDP_WinTest)
Track_UDP_WinTest(udpclient, udpip, az, el);
if (Properties.Settings.Default.Track_UDP_AirScout)
Track_UDP_WinTest(udpclient, udpip, az, el);
if (Properties.Settings.Default.Track_Serial_GS232_AZ)
Track_SER__GS_232A_AZ(serialport, az);
if (Properties.Settings.Default.Track_Serial_GS232_AZEL)
Track_SER__GS_232A_AZEL(serialport, az, el);
if (Properties.Settings.Default.Track_File_Native)
Track_File_Native(az, el);
if (Properties.Settings.Default.Track_File_WSJT)
Track_File_WSJT(az, el);
}
else
{
// no tracking!
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
//report error
bw_Track.ReportProgress(-1, ex.Message);
// increment error counters and switch off in case of subsequent errors
if (ex.Message.StartsWith("[DDE]:"))
{
ddeerr++;
if (ddeerr > maxerr)
{
// switch off DDE
Properties.Settings.Default.Track_DDE_None = true;
Properties.Settings.Default.Track_DDE_HRD = false;
bw_Track.ReportProgress(-1, "Tracking via DDE disabled.");
}
}
if (ex.Message.StartsWith("[UDP]:"))
{
udperr++;
if (udperr > maxerr)
{
// switch off UDP
Properties.Settings.Default.Track_UDP_None = true;
Properties.Settings.Default.Track_UDP_WinTest = false;
Properties.Settings.Default.Track_UDP_AirScout = false;
bw_Track.ReportProgress(-1, "Tracking via UDP disabled.");
}
}
if (ex.Message.StartsWith("[Serial]:"))
{
serialerr++;
if (serialerr > maxerr)
{
// switch off Serial
Properties.Settings.Default.Track_Serial_None = true;
Properties.Settings.Default.Track_Serial_GS232_AZ = false;
Properties.Settings.Default.Track_Serial_GS232_AZEL = false;
bw_Track.ReportProgress(-1, "Tracking via Serial disabled.");
}
if (ex.Message.StartsWith("[Serial]:"))
serialerr++;
}
// leave inner loop
break;
}
Thread.Sleep(1000);
}
Thread.Sleep(1000);
// try to close all connections
try
{
if ((ddeclient != null) && (ddeclient.IsConnected))
ddeclient.Disconnect();
if (udpclient != null)
udpclient.Close();
if ((serialport != null) && (serialport.IsOpen))
serialport.Close();
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
while (!bw_Track.CancellationPending);
Log.WriteMessage("Finished.");
}
private void bw_Track_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage < 0)
{
// report Error
tsl_Status.Text = (string)e.UserState;
}
if (e.ProgressPercentage == 1)
{
// report Azimuth
ag_Azimuth.Value = (float)(double)e.UserState;
}
if (e.ProgressPercentage == 2)
{
// report Elevation
ag_Elevation.Value = (float)(double)e.UserState;
}
}
private void bw_Track_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
#endregion
#region JSONWriter
private void bw_JSONWriter_DoWork(object sender, DoWorkEventArgs e)
{
Log.WriteMessage("Started.");
int interval = 60;
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_JSONWriter";
while (!bw_JSONWriter.CancellationPending)
{
// get planes each minute
List<PlaneInfo> list = Planes.GetAll(DateTime.UtcNow, Properties.Settings.Default.Planes_Position_TTL);
// write json file
try
{
using (StreamWriter sw = new StreamWriter(TmpDirectory + Path.DirectorySeparatorChar + "planes.json"))
{
int major = Assembly.GetExecutingAssembly().GetName().Version.Major;
sw.Write("{\"full_count\":" + list.Count().ToString() + ",\"version\":" + major.ToString());
int i = 0;
foreach (PlaneInfo info in list)
{
string index = "\"" + i.ToString("x8") + "\"";
string hex = "\"" + info.Hex + "\"";
string lat = info.Lat.ToString("F4", CultureInfo.InvariantCulture);
string lon = info.Lon.ToString("F4", CultureInfo.InvariantCulture);
string track = info.Track.ToString();
string alt = info.Alt.ToString();
string speed = info.Speed.ToString();
string squawk = "\"" + "" + "\"";
string radar = "\"" + "" + "\"";
string type = "\"" + info.Type + "\"";
string reg = "\"" + info.Reg + "\"";
DateTime sTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
string time = ((long)(info.Time - sTime).TotalSeconds).ToString();
string dep = "\"\"";
string dest = "\"\"";
string flight = "\"\"";
string dummy1 = "0";
string dummy2 = "0";
string call = "\"" + info.Call + "\"";
string dummy3 = "0";
sw.WriteLine("," + index + ":[" +
hex + "," +
lat + "," +
lon + "," +
track + "," +
alt + "," +
speed + "," +
squawk + "," +
radar + "," +
type + "," +
reg + "," +
time + "," +
dep + "," +
dest + "," +
flight + "," +
dummy1 + "," +
dummy2 + "," +
call + "," +
dummy3 +
"]");
}
sw.WriteLine("}");
i++;
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
// do nothing
}
int ii = 0;
while (!bw_JSONWriter.CancellationPending && (ii < interval))
{
Thread.Sleep(1000);
ii++;
}
}
Log.WriteMessage("Finished.");
}
#endregion
#region NewsFeed
private void bw_NewsFeed_DoWork(object sender, DoWorkEventArgs e)
{
Log.WriteMessage("Started.");
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_NewsFeed";
Uri uri = Properties.Settings.Default.News_URL;
int interval = Properties.Settings.Default.News_Interval;
while (!bw_NewsFeed.CancellationPending)
{
try
{
// get the last modified time of the website
AutoDecompressionWebClient cl = new AutoDecompressionWebClient();
DateTime dt = cl.GetWebCreationTimeUtc(Properties.Settings.Default.News_URL);
Log.WriteMessage("Checking news page: " + dt.ToString("yyyy-MM-dd HH:mm:ss") + "<> " + Properties.Settings.Default.News_LastUpdate.ToString("yyyy-MM-dd HH:mm:ss"));
Console.WriteLine("Checking news page: " + dt.ToString("yyyy-MM-dd HH:mm:ss") + "<> " + Properties.Settings.Default.News_LastUpdate.ToString("yyyy-MM-dd HH:mm:ss"));
// report latest news if updated
if (dt > Properties.Settings.Default.News_LastUpdate)
{
// report news to main window
bw_NewsFeed.ReportProgress(1, dt);
}
}
catch (Exception ex)
{
// report error
Log.WriteMessage(ex.Message);
bw_NewsFeed.ReportProgress(-1, DateTime.UtcNow.ToString("[" + "HH:mm:ss") + "] Error while reading the website " + uri.ToString() + ": " + ex.Message);
}
int i = 0;
while (!bw_NewsFeed.CancellationPending && (i < interval))
{
Thread.Sleep(1000);
i++;
}
}
Log.WriteMessage("Finished.");
}
private void bw_NewsFeed_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage < 0)
{
// report error
Say((string)e.UserState);
}
else
{
// report website changes
DateTime dt = (DateTime)e.UserState;
if (!SupportFunctions.IsMono)
{
if (MessageBox.Show("There are news on the website. Latest update: " + dt.ToString() + "\n Do you want to read it now?", "Website News", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
{
try
{
if (wb_News != null)
wb_News.Refresh();
tc_Main.SelectedTab = tp_News;
// save time to settings
Properties.Settings.Default.News_LastUpdate = dt;
}
catch (Exception ex)
{
// do nothing if wb_News fails to refresh
}
}
}
else
{
if (MessageBox.Show("There are news on the website. Latest update: " + dt.ToString() + "\n Do you want to read it now?\n\n Under Linux/Mono open web browser of your choice and goto: \n" + Properties.Settings.Default.News_URL + "\n\n", "Website News", MessageBoxButtons.YesNo) == System.Windows.Forms.DialogResult.Yes)
{
try
{
// save time to settings
Properties.Settings.Default.News_LastUpdate = dt;
}
catch (Exception ex)
{
// do nothing if wb_News fails to refresh
}
}
}
}
}
private void bw_NewsFeed_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
#endregion
#region HistoryDownloader
private void HistoryDownloader_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
// get byte in GB
double bytesin = double.Parse(e.BytesReceived.ToString()) / 1024.0 / 1024.0 / 1024.0;
double totalbytes = double.Parse(e.TotalBytesToReceive.ToString()) / 1024.0 / 1024.0 / 1024.0;
double percentage = bytesin / totalbytes * 100;
try
{
if (bw_HistoryDownloader.IsBusy)
bw_HistoryDownloader.ReportProgress(1, "Downloaded " + bytesin.ToString("F2") + " GB of " + totalbytes.ToString("F2") + " GB (" + percentage.ToString("F2") + "%).");
}
catch
{
}
}
private string ReadPropertyString(JObject o, string propertyname)
{
if (o.Property(propertyname) == null)
return null;
return o.Property(propertyname).Value.Value<string>();
}
private int ReadPropertyDoubleToInt(JObject o, string propertyname)
{
if (o.Property(propertyname) == null)
return int.MinValue;
double d = ReadPropertyDouble(o, propertyname);
if ((d != double.MinValue) && (d >= int.MinValue) && (d <= int.MaxValue))
return (int)d;
return int.MinValue;
}
private double ReadPropertyDouble(JObject o, string propertyname)
{
if (o.Property(propertyname) == null)
return double.MinValue;
return o.Property(propertyname).Value.Value<double>();
}
private long ReadPropertyLong(JObject o, string propertyname)
{
if (o.Property(propertyname) == null)
return long.MinValue;
return o.Property(propertyname).Value.Value<long>();
}
private void HistoryDownloader_DownloadFileCompleted(object sender, AsyncCompletedEventArgs e)
{
try
{
if (bw_HistoryDownloader.IsBusy)
bw_HistoryDownloader.ReportProgress(1, "Reading " + Properties.Settings.Default.Analysis_History_ZIPFileName);
// unzip the file
if (File.Exists(Properties.Settings.Default.Analysis_History_ZIPFileName))
{
string filename = Properties.Settings.Default.Analysis_History_ZIPFileName;
// unzips a zip file content to the same directory
string downloaddir = Path.GetDirectoryName(Properties.Settings.Default.Analysis_History_ZIPFileName);
// set path to calling assembly's path if not otherwise specified
if (String.IsNullOrEmpty(downloaddir))
downloaddir = Assembly.GetCallingAssembly().Location;
// open the zip file
using (ZipFile zip = new ZipFile(filename))
{
zip.ZipErrorAction = ZipErrorAction.Skip;
// here, we extract every entry, but we could extract conditionally
// based on entry name, size, date, checkbox status, etc.
foreach (ZipEntry ze in zip)
{
if (bw_HistoryDownloader.IsBusy)
bw_HistoryDownloader.ReportProgress(1, "Extracting " + ze.FileName);
try
{
/*
ze.Extract(downloaddir, ExtractExistingFileAction.OverwriteSilently);
string fname = Path.Combine(downloaddir, ze.FileName);
File.SetLastWriteTime(fname, ze.LastModified);
*/
}
catch (Exception ex)
{
if (bw_HistoryDownloader.IsBusy)
bw_HistoryDownloader.ReportProgress(-1, ex.Message);
}
}
}
// create csv to load into database
using (StreamWriter sw = new StreamWriter(Properties.Settings.Default.Analysis_History_ZIPFileName.ToLower().Replace(".zip", ".csv")))
{
sw.WriteLine("time;call;reg;hex;lat;lon;track;alt;speed;squawk;radar;type");
// read all files
for (int i = 0; i < 1440; i += (int)Properties.Settings.Default.Analysis_History_Stepwidth)
{
// calculate filename
int hours = i / 60;
int minutes = i % 60;
string fname = Path.Combine(Properties.Settings.Default.Analysis_History_Directory, Properties.Settings.Default.Analysis_History_Date.ToString("yyyy-MM-dd") + "-" + hours.ToString("00") + minutes.ToString("00") + "Z.json");
if (bw_HistoryDownloader.IsBusy)
bw_HistoryDownloader.ReportProgress(1, "Processing " + fname);
if (File.Exists(fname))
{
string json = "";
using (StreamReader sr = new StreamReader(fname))
json = sr.ReadToEnd();
// analyze json string for planes data
JObject root = (JObject)JsonConvert.DeserializeObject(json);
foreach (JProperty proot in root.Children<JProperty>())
{
// get the planes position list
if (proot.Name == "acList")
{
foreach (JArray a in proot.Children<JArray>())
{
foreach (JObject o in a.Values<JObject>())
{
PlaneInfo info = new PlaneInfo();
try
{
info.Call = ReadPropertyString(o, "Call");
info.Lat = ReadPropertyDouble(o, "Lat");
info.Lon = ReadPropertyDouble(o, "Long");
info.Track = ReadPropertyDoubleToInt(o, "Trak");
// 2017-07-23: take "GAlt" (corrected altitude by air pressure) rather than "Alt"
info.Alt = ReadPropertyDoubleToInt(o, "GAlt");
// info.Alt = ReadPropertyDoubleToInt(o, "Alt");
info.Speed = ReadPropertyDoubleToInt(o, "Spd");
info.Reg = ReadPropertyString(o, "Reg");
try
{
string squawk = ReadPropertyString(o, "Sqk");
}
catch
{
}
info.Hex = ReadPropertyString(o, "Icao");
info.Type = ReadPropertyString(o, "Type");
// complete type info
AircraftTypeDesignator td = AircraftData.Database.AircraftTypeFindByICAO(info.Type);
if (td != null)
{
info.Manufacturer = td.Manufacturer;
info.Model = td.Model;
info.Category = td.Category;
}
else
{
info.Manufacturer = "[unknown]";
info.Model = "[unknown]";
info.Category = PLANECATEGORY.NONE;
}
// CAUTION!! time is UNIX time in milliseconds
long l = ReadPropertyLong(o, "PosTime");
if (l != long.MinValue)
{
DateTime timestamp = new System.DateTime(1970, 1, 1, 0, 0, 0, 0);
timestamp = timestamp.AddMilliseconds(l);
info.Time = timestamp;
}
else
{
info.Time = DateTime.MinValue;
}
if (PlaneInfo.Check(info) &&
(info.Alt_m >= Properties.Settings.Default.Planes_MinAlt) &&
(info.Alt_m <= Properties.Settings.Default.Planes_MaxAlt) &&
(info.Lat >= Properties.Settings.Default.MinLat) &&
(info.Lat <= Properties.Settings.Default.MaxLat) &&
(info.Lon >= Properties.Settings.Default.MinLon) &&
(info.Lon <= Properties.Settings.Default.MaxLon))
{
sw.WriteLine(info.Time.ToString("u") + ";" +
info.Call + ";" +
info.Reg + ";" +
info.Hex + ";" +
info.Lat.ToString("F8", CultureInfo.InvariantCulture) + ";" +
info.Lon.ToString("F8", CultureInfo.InvariantCulture) + ";" +
info.Track.ToString() + ";" +
info.Alt.ToString() + ";" +
info.Speed.ToString() + ";" +
"" + ";" +
"" + ";" +
info.Type);
}
}
catch (Exception ex)
{
Log.WriteMessage(ex.Message);
}
}
}
}
}
}
}
}
}
}
catch (Exception ex)
{
if (bw_HistoryDownloader.IsBusy)
bw_HistoryDownloader.ReportProgress(-1, ex.Message);
}
// job is done
// cancel backgroundworker
bw_HistoryDownloader.CancelAsync();
}
private void bw_HistoryDownloader_DoWork(object sender, DoWorkEventArgs e)
{
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_HistoryDownloader";
try
{
DateTime date = (DateTime)e.Argument;
// check history directory first
if (!Directory.Exists(Properties.Settings.Default.Analysis_History_Directory))
Properties.Settings.Default.Analysis_History_Directory = TmpDirectory;
// check free disk space
System.IO.DriveInfo drive = new System.IO.DriveInfo(Properties.Settings.Default.Analysis_History_Directory);
System.IO.DriveInfo a = new System.IO.DriveInfo(drive.Name);
if (a.AvailableFreeSpace < 50.0 * 1024.0 * 1024.0 * 1024.0)
throw new ArgumentException("Not enough disk space to run this operation.");
string url = Properties.Settings.Default.Analysis_History_URL;
Properties.Settings.Default.Analysis_History_ZIPFileName = Path.Combine(Properties.Settings.Default.Analysis_History_Directory, date.ToString("yyyy-MM-dd") + ".zip");
if (!File.Exists(Properties.Settings.Default.Analysis_History_ZIPFileName))
{
// file not found --> donwload it from url
// complete url with "/" and date
if (!url.EndsWith("/"))
url = url + "/";
url = url + date.ToString("yyyy-MM-dd") + ".zip";
// create web client for download
WebClient client = new WebClient();
// register asynchronous file download event handler
client.DownloadProgressChanged += new DownloadProgressChangedEventHandler(HistoryDownloader_DownloadProgressChanged);
client.DownloadFileCompleted += new AsyncCompletedEventHandler(HistoryDownloader_DownloadFileCompleted);
client.DownloadFileAsync(new Uri(url), Properties.Settings.Default.Analysis_History_ZIPFileName);
// remain here in a loop until job is finished
// cancellation will be initiated after download and unzip is complet
}
else
{ // call download completed handler directly
HistoryDownloader_DownloadFileCompleted(this, null);
}
}
catch (Exception ex)
{
bw_HistoryDownloader.ReportProgress(-1, ex.Message);
}
}
private void bw_HistoryDownloader_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string s = (string)e.UserState;
if (String.IsNullOrEmpty(s))
return;
tb_Analysis_Status.Text = s;
}
private void bw_HistoryDownloader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
btn_Analysis_Planes_History.Enabled = true;
}
#endregion
#region ElevationDatabaseUpdater
private void bw_ElevationDatabaseUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.ProgressPercentage < 0)
{
// error message received
string msg = (string)e.UserState;
Log.WriteMessage(msg);
}
else if (e.ProgressPercentage == 0)
{
// status message received
string msg = (string)e.UserState;
// redirect output to splash screen on first run
if (FirstRun && SplashDlg != null)
SplashDlg.Status("Preparing database for first run: " + msg + " (please wait)", Color.Yellow);
else
{
SayDatabase(msg);
Log.WriteMessage(msg);
}
}
else if (e.ProgressPercentage == 1)
{
// database status update message received
if (sender == this.bw_GLOBEUpdater)
{
Properties.Settings.Default.Elevation_GLOBE_DatabaseStatus = (DATABASESTATUS)e.UserState;
Color color = DatabaseStatus.GetDatabaseStatusColor(Properties.Settings.Default.Elevation_GLOBE_DatabaseStatus);
if (tsl_Database_LED_GLOBE.BackColor != color)
tsl_Database_LED_GLOBE.BackColor = color;
string text = "GLOBE Database Status\n\n" + DatabaseStatus.GetDatabaseStatusText(Properties.Settings.Default.Elevation_GLOBE_DatabaseStatus);
if (tsl_Database_LED_GLOBE.ToolTipText != text)
tsl_Database_LED_GLOBE.ToolTipText = text;
}
else if (sender == this.bw_SRTM3Updater)
{
Properties.Settings.Default.Elevation_SRTM3_DatabaseStatus = (DATABASESTATUS)e.UserState;
Color color = DatabaseStatus.GetDatabaseStatusColor(Properties.Settings.Default.Elevation_SRTM3_DatabaseStatus);
if (tsl_Database_LED_SRTM3.BackColor != color)
tsl_Database_LED_SRTM3.BackColor = color;
string text = "SRTM3 Database Status\n\n" + DatabaseStatus.GetDatabaseStatusText(Properties.Settings.Default.Elevation_SRTM3_DatabaseStatus);
if (tsl_Database_LED_SRTM3.ToolTipText != text)
tsl_Database_LED_SRTM3.ToolTipText = text;
}
else if (sender == this.bw_SRTM1Updater)
{
Properties.Settings.Default.Elevation_SRTM1_DatabaseStatus = (DATABASESTATUS)e.UserState;
Color color = DatabaseStatus.GetDatabaseStatusColor(Properties.Settings.Default.Elevation_SRTM1_DatabaseStatus);
if (tsl_Database_LED_SRTM1.BackColor != color)
tsl_Database_LED_SRTM1.BackColor = color;
string text = "SRTM1 Database Status\n\n" + DatabaseStatus.GetDatabaseStatusText(Properties.Settings.Default.Elevation_SRTM1_DatabaseStatus);
if (tsl_Database_LED_SRTM1.ToolTipText != text)
tsl_Database_LED_SRTM1.ToolTipText = text;
}
}
ss_Main.Update();
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
#endregion
#region ElevationPathCalculator
private void bw_ElevationPathCalculator_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 0)
SayCalculations((string)e.UserState);
}
#endregion
#region StationDatabaseUpdater
private void bw_StationDatabaseUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.ProgressPercentage < 0)
{
// error message received
string msg = (string)e.UserState;
Log.WriteMessage(msg);
}
else if (e.ProgressPercentage == 0)
{
// status message received
string msg = (string)e.UserState;
Log.WriteMessage(msg);
// redirect output to splash screen on first run
if (FirstRun && SplashDlg != null)
SplashDlg.Status("Preparing database for first run: " + msg + " (please wait)", Color.Yellow);
else
{
SayDatabase(msg);
}
}
else if (e.ProgressPercentage == 1)
{
Properties.Settings.Default.StationsDatabase_Status = (DATABASESTATUS)e.UserState;
Color color = DatabaseStatus.GetDatabaseStatusColor(Properties.Settings.Default.StationsDatabase_Status);
if (tsl_Database_LED_Stations.BackColor != color)
tsl_Database_LED_Stations.BackColor = color;
string text = "Stations Database Status\n\n" + DatabaseStatus.GetDatabaseStatusText(Properties.Settings.Default.StationsDatabase_Status);
if (tsl_Database_LED_Stations.ToolTipText != text)
tsl_Database_LED_Stations.ToolTipText = text;
}
ss_Main.Update();
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void bw_StationDatabaseUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// refresh display
if (!this.IsDisposed)
{
UpdateAirports();
gm_Main.Refresh();
}
}
#endregion
#region AircraftDatabaseUpdater
private void bw_AircraftDatabaseUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.ProgressPercentage < 0)
{
// error message received
string msg = (string)e.UserState;
Log.WriteMessage(msg);
}
else if (e.ProgressPercentage == 0)
{
// status message received
string msg = (string)e.UserState;
Log.WriteMessage(msg);
// redirect output to splash screen on first run
if (FirstRun && SplashDlg != null)
SplashDlg.Status("Preparing database for first run: " + msg + " (please wait)", Color.Yellow);
else
{
SayDatabase(msg);
}
}
else if (e.ProgressPercentage == 1)
{
Properties.Settings.Default.AircraftDatabase_Status = (DATABASESTATUS)e.UserState;
Color color = DatabaseStatus.GetDatabaseStatusColor(Properties.Settings.Default.AircraftDatabase_Status);
if (tsl_Database_LED_Aircraft.BackColor != color)
{
tsl_Database_LED_Aircraft.BackColor = color;
}
string text = "Aircraft Database Status\n\n" + DatabaseStatus.GetDatabaseStatusText(Properties.Settings.Default.AircraftDatabase_Status);
if (tsl_Database_LED_Aircraft.ToolTipText != text)
tsl_Database_LED_Aircraft.ToolTipText = text;
}
ss_Main.Update();
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void bw_AircraftDatabaseUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// refresh data tables and display
if (!this.IsDisposed)
{
// refresh all dictionnariees
// ScoutData.Database.UpdateFromDataTables(false);
// refresh airports and map
UpdateAirports();
gm_Main.Refresh();
}
}
#endregion
#region AircraftDatabaseMaintainer
private void bw_AircraftDatabaseMaintainer_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
try
{
if (e.ProgressPercentage < 0)
{
// error message received
string msg = (string)e.UserState;
Log.WriteMessage(msg);
}
else if (e.ProgressPercentage == 0)
{
// status message received
string msg = (string)e.UserState;
Log.WriteMessage(msg);
// redirect output to splash screen on first run
if (FirstRun && SplashDlg != null)
SplashDlg.Status("Preparing database for first run: " + msg + " (please wait)", Color.Yellow);
else
{
SayDatabase(msg);
}
}
ss_Main.Update();
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
}
}
private void bw_AircraftDatabaseMaintainer_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
#endregion
#endregion
#region Analysis_DataGetter
private void bw_Analysis_DataGetter_DoWork(object sender, DoWorkEventArgs e)
{
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_Analysis_DataGetter";
Stopwatch st = new Stopwatch();
st.Start();
bw_Analysis_DataGetter.ReportProgress(0, "Getting timespan of all positions in database...");
// calculate min/max values for timespan
History_OldestEntry = AircraftPositionData.Database.AircraftPositionOldestEntry();
if (bw_Analysis_DataGetter.CancellationPending)
{
e.Cancel = true;
return;
}
History_YoungestEntry = AircraftPositionData.Database.AircraftPositionYoungestEntry();
if (bw_Analysis_DataGetter.CancellationPending)
{
e.Cancel = true;
return;
}
bw_Analysis_DataGetter.ReportProgress(0, "Getting positions...");
AircraftPositionsCount = AircraftPositionData.Database.AircraftPositionCount();
// get all aircraft positions into cache
lock (AllPositions)
{
AllPositions.Clear();
}
lock (AllPositions)
{
// get all positions from database, can be interrupted
AllPositions = AircraftPositionData.Database.AircraftPositionGetAll(this.bw_Analysis_DataGetter);
if (bw_Analysis_DataGetter.CancellationPending)
{
e.Cancel = true;
return;
}
}
st.Stop();
bw_Analysis_DataGetter.ReportProgress(0, "Getting positions finished, " + AllPositions.Count.ToString() + " positions, " + st.ElapsedMilliseconds.ToString() + " ms.");
}
private void bw_Analysis_DataGetter_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage == 0)
{
string msg = (string)e.UserState;
// NASTY!! Add the total count of positions after the "of" in the message
// total count is calculated once in DoWork
if (msg.EndsWith("of)"))
msg = msg + " " + AircraftPositionsCount.ToString();
SayAnalysis(msg);
}
}
private void bw_Analysis_DataGetter_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// check if cancelled
// return to default state
if (e.Cancelled)
{
SayAnalysis("Cancelled.");
btn_Analysis_ON.Enabled = true;
btn_Analysis_ON.BackColor = Color.YellowGreen;
return;
}
else
SayAnalysis("Ready.");
// nothing found in database --> show message box and do not enter analysis mode
if ((History_YoungestEntry == DateTime.MinValue) || (History_OldestEntry == DateTime.MinValue))
{
MessageBox.Show("Nothing found for analysis. Please let AirScout run in PLAY mode for a while to collect some data.", "AirScout Analysis", MessageBoxButtons.OK);
return;
}
// set scroll bar bounds
dtp_Analysis_MinValue.Value = History_OldestEntry;
dtp_Analysis_MaxValue.Value = History_YoungestEntry;
// enable buttons
btn_Analysis_Planes_Load.Enabled = true;
btn_Analysis_Planes_Save.Enabled = true;
btn_Analysis_Planes_Clear.Enabled = true;
btn_Analysis_Planes_History.Enabled = true;
btn_Analysis_Planes_ShowTraffic.Enabled = true;
btn_Analysis_Path_SaveToFile.Enabled = true;
btn_Analysis_CrossingHistory.Enabled = true;
btn_Analysis_Plane_History.Enabled = true;
btn_Analysis_Rewind.Enabled = true;
btn_Analysis_Back.Enabled = true;
btn_Analysis_Pause.Enabled = true;
btn_Analysis_Forward.Enabled = true;
btn_Analysis_FastForward.Enabled = true;
sb_Analysis_Play.Enabled = true;
dtp_Analysis_MinValue.Enabled = true;
dtp_Analysis_MaxValue.Enabled = true;
UpdatePlayer();
// set time to oldest entry
Properties.Settings.Default.Time_Offline = History_OldestEntry;
gb_Analysis_Player_SizeChanged(this, null);
UpdatePaths();
UpdateStatus();
btn_Analysis_Planes_Load.Focus();
}
#endregion
#region Analysis_FileSaver
private void Analysis_Planes_Save_JSON(string filename)
{
int saved = 0;
using (StreamWriter sw = new StreamWriter(filename))
{
sw.WriteLine("[");
for (int i = 0; i < AllPositions.Count; i++)
{
if (AllPositions[i].LastUpdated < dtp_Analysis_MinValue.Value)
continue;
if (AllPositions[i].LastUpdated > dtp_Analysis_MaxValue.Value)
continue;
string json = AllPositions[i].ToJSON();
sw.Write(json);
if (i < AllPositions.Count - 1)
{
sw.WriteLine(",");
}
else
sw.WriteLine();
saved++;
if (saved % 1000 == 0)
bw_Analysis_FileSaver.ReportProgress(0, "Saving position " + saved.ToString() + "...");
if (bw_Analysis_FileSaver.CancellationPending)
return;
}
sw.WriteLine("]");
}
}
private void Analysis_Planes_Save_CSV(string filename)
{
int saved = 0;
using (StreamWriter sw = new StreamWriter(filename))
{
sw.WriteLine("time[utc];hex;call;lat[deg];lon[deg];alt[ft];track[deg];speed[kts]");
foreach (AircraftPositionDesignator ap in AllPositions)
{
if (ap.LastUpdated < dtp_Analysis_MinValue.Value)
continue;
if (ap.LastUpdated > dtp_Analysis_MaxValue.Value)
continue;
sw.WriteLine(ap.LastUpdated.ToString("yyyy-MM-dd HH:mm:ssZ") + ";" +
ap.Hex + ";" +
ap.Call + ";" +
ap.Lat.ToString("F8", CultureInfo.InvariantCulture) + ";" +
ap.Lon.ToString("F8", CultureInfo.InvariantCulture) + ";" +
ap.Alt.ToString("F8", CultureInfo.InvariantCulture) + ";" +
ap.Track.ToString("F8", CultureInfo.InvariantCulture) + ";" +
ap.Speed.ToString("F8", CultureInfo.InvariantCulture)
);
saved++;
if (saved % 1000 == 0)
bw_Analysis_FileSaver.ReportProgress(0, "Saving position " + saved.ToString() + "...");
if (bw_Analysis_FileSaver.CancellationPending)
return;
}
}
}
private void bw_Analysis_FileSaver_DoWork(object sender, DoWorkEventArgs e)
{
string filename = (string)e.Argument;
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_Analysis_FileSaver";
try
{
if (filename.ToLower().EndsWith(".json"))
Analysis_Planes_Save_JSON(filename);
else if (filename.ToLower().EndsWith(".csv"))
Analysis_Planes_Save_CSV(filename);
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
bw_Analysis_FileSaver.ReportProgress(-1, ex.Message);
}
if (bw_Analysis_FileSaver.CancellationPending)
e.Cancel = true;
}
private void bw_Analysis_FileSaver_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage <= 0)
SayAnalysis((string)e.UserState);
}
private void bw_Analysis_FileSaver_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
SayAnalysis("Cancelled.");
else
{
btn_Analysis_Planes_Save.Enabled = true;
SayAnalysis("Ready.");
}
}
#endregion
#region Analysis_FileLoader
private void Analysis_Planes_Load_JSON(string filename)
{
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.FloatFormatHandling = FloatFormatHandling.String;
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
settings.Culture = CultureInfo.InvariantCulture;
List<AircraftPositionDesignator> aps = new List<AircraftPositionDesignator>();
bw_Analysis_FileLoader.ReportProgress(0, "Opening file...");
using (StreamReader sr = new StreamReader(File.Open(filename, FileMode.Open)))
{
// check for starting bracket of array
char c = (char)sr.Read();
if (c != '[')
return;
// read 1000 positions and update database
int count = 0;
int updated = 0;
while (!sr.EndOfStream)
{
aps.Clear();
int j = 0;
while ((j < 1000) && !sr.EndOfStream)
{
char nextChar;
StringBuilder line = new StringBuilder();
while ((j < 1000) && sr.Peek() > 0)
{
nextChar = (char)sr.Read();
line.Append(nextChar);
if (line[0] != '{')
line.Clear();
if (nextChar == '}')
{
AircraftPositionDesignator ap = JsonConvert.DeserializeObject<AircraftPositionDesignator>(line.ToString(), settings);
line.Clear();
aps.Add(ap);
j++;
}
}
if (bw_Analysis_FileLoader.CancellationPending)
return;
}
count = count + j;
updated = updated + AircraftPositionData.Database.AircraftPositionBulkInsertOrUpdateIfNewer(aps);
bw_Analysis_FileLoader.ReportProgress(0, "Updating position " + count.ToString() + ", " + updated.ToString() + " updated so far...");
}
}
}
private void Analysis_Planes_Load_CSV(string filename)
{
List<AircraftPositionDesignator> aps = new List<AircraftPositionDesignator>();
bw_Analysis_FileLoader.ReportProgress(0, "Opening file...");
using (StreamReader sr = new StreamReader(File.Open(filename, FileMode.Open)))
{
// read header
string header = sr.ReadLine();
// split header
string[] a = header.Split(';');
// remove unit brackets and lower all
for (int i = 0; i < a.Length; i++)
{
a[i] = a[i].ToLower();
if (a[i].IndexOf('[') >= 0)
a[i] = a[i].Substring(0, a[i].IndexOf('['));
}
int lastupdated_index = Array.IndexOf(a, "time");
int hex_index = Array.IndexOf(a, "hex");
int call_index = Array.IndexOf(a, "call");
int lat_index = Array.IndexOf(a, "lat");
int lon_index = Array.IndexOf(a, "lon");
int alt_index = Array.IndexOf(a, "alt");
int track_index = Array.IndexOf(a, "track");
int speed_index = Array.IndexOf(a, "speed");
bw_Analysis_FileLoader.ReportProgress(0, "Creating position list...");
// read 1000 positions and update database
int count = 0;
int updated = 0;
while (!sr.EndOfStream)
{
aps.Clear();
int j = 0;
while ((j < 1000) && !sr.EndOfStream)
{
string s = sr.ReadLine();
if (!s.Contains(";"))
continue;
a = s.Split(';');
DateTime lastupdated = System.Convert.ToDateTime(a[lastupdated_index]).ToUniversalTime();
string hex = a[hex_index].ToUpper();
string call = a[call_index].ToUpper();
double lat = System.Convert.ToDouble(a[lat_index], CultureInfo.InvariantCulture);
double lon = System.Convert.ToDouble(a[lon_index], CultureInfo.InvariantCulture);
double alt = System.Convert.ToDouble(a[alt_index], CultureInfo.InvariantCulture);
double track = System.Convert.ToDouble(a[track_index], CultureInfo.InvariantCulture);
double speed = System.Convert.ToDouble(a[speed_index], CultureInfo.InvariantCulture);
AircraftPositionDesignator ap = new AircraftPositionDesignator(hex, call, lat, lon, alt, track, speed, lastupdated);
aps.Add(ap);
j++;
if (bw_Analysis_FileLoader.CancellationPending)
return;
}
count = count + j;
updated = updated + AircraftPositionData.Database.AircraftPositionBulkInsertOrUpdateIfNewer(aps);
bw_Analysis_FileLoader.ReportProgress(0, "Updating position " + count.ToString() + ", " + updated.ToString() + " updated so far...");
}
}
}
private void bw_Analysis_FileLoader_DoWork(object sender, DoWorkEventArgs e)
{
string filename = (string)e.Argument;
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = "bw_Analysis_FileLoader";
try
{
if (filename.ToLower().EndsWith(".json"))
Analysis_Planes_Load_JSON(filename);
else if (filename.ToLower().EndsWith(".csv"))
Analysis_Planes_Load_CSV(filename);
}
catch (Exception ex)
{
Log.WriteMessage(ex.ToString());
bw_Analysis_FileLoader.ReportProgress(-1, ex.Message);
}
if (bw_Analysis_FileLoader.CancellationPending)
e.Cancel = true;
}
private void bw_Analysis_FileLoader_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage <= 0)
SayAnalysis((string)e.UserState);
}
private void bw_Analysis_FileLoader_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (e.Cancelled)
SayAnalysis("Cancelled.");
else
{
btn_Analysis_Planes_Load.Enabled = true;
SayAnalysis("Ready.");
}
}
#endregion
#region AirportMapper
private void bw_AirportMapper_DoWork(object sender, DoWorkEventArgs e)
{
bw_AirportMapper.ReportProgress(0, "Getting airports from database...");
Stopwatch st = new Stopwatch();
st.Start();
// clear airports if any
gmo_Airports.Clear();
// fill the airports layer of maps
// return if switched off
if (!Properties.Settings.Default.Airports_Activate)
return;
List<AirportDesignator> airports = new List<AirportDesignator>();
airports = AircraftData.Database.AirportGetAll(bw_AirportMapper);
if (airports != null)
bw_AirportMapper.ReportProgress(100, airports);
st.Stop();
bw_AirportMapper.ReportProgress(0, airports.Count.ToString() + " airports updated, " + st.ElapsedMilliseconds.ToString() + " ms.");
}
private void bw_AirportMapper_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
if (e.ProgressPercentage <= 0)
{
string msg = (string)e.UserState;
Say(msg);
Log.WriteMessage(msg);
}
else if (e.ProgressPercentage == 100)
{
lock (Airports)
{
Airports = (List<AirportDesignator>)e.UserState;
}
UpdateAirports();
}
}
private void bw_AirportMapper_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
}
#endregion
private void gm_Main_Load(object sender, EventArgs e)
{
}
}
public class ClippingToolStripRenderer : ToolStripSystemRenderer
{
protected override void OnRenderItemText(ToolStripItemTextRenderEventArgs e)
{
ToolStripStatusLabel label = e.Item as ToolStripStatusLabel;
if (label != null)
{
TextRenderer.DrawText(e.Graphics, label.Text,
label.Font, e.TextRectangle,
label.ForeColor,
TextFormatFlags.EndEllipsis);
}
else
{
base.OnRenderItemText(e);
}
}
}
public class LocatorDropDownItem
{
public string Locator { get; set; }
public LatLon.GPoint GeoLocation { get; set; }
public LocatorDropDownItem(string locator, LatLon.GPoint geolocation)
{
Locator = locator;
GeoLocation = geolocation;
}
}
}