kopia lustrzana https://github.com/dl2alf/AirScout
1903 wiersze
82 KiB
C#
1903 wiersze
82 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.ComponentModel;
|
|
using System.Data;
|
|
using System.Drawing;
|
|
using System.Linq;
|
|
using System.Text;
|
|
using System.Windows.Forms;
|
|
using System.Net;
|
|
using System.IO;
|
|
using System.Globalization;
|
|
using System.Threading;
|
|
using System.Xml;
|
|
using System.Xml.Linq;
|
|
using GMap.NET;
|
|
using GMap.NET.MapProviders;
|
|
using GMap.NET.WindowsForms;
|
|
using GMap.NET.WindowsForms.Markers;
|
|
using GMap.NET.WindowsForms.ToolTips;
|
|
using ScoutBase;
|
|
using ScoutBase.Core;
|
|
using ScoutBase.Elevation;
|
|
using ScoutBase.Stations;
|
|
using SQLiteDatabase;
|
|
using Newtonsoft.Json;
|
|
using HtmlAgilityPack;
|
|
using AirScout.Aircrafts;
|
|
using Newtonsoft.Json.Linq;
|
|
using Renci.SshNet.Sftp;
|
|
using Renci.SshNet;
|
|
|
|
namespace AirScoutDatabaseManager
|
|
{
|
|
public partial class MainDlg : 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("Tempfile Directory")]
|
|
public string ExportDirectory
|
|
{
|
|
get
|
|
{
|
|
// get Property
|
|
string expdir = Properties.Settings.Default.Export_Directory;
|
|
// replace Windows/Linux directory spearator chars
|
|
expdir = expdir.Replace('\\', Path.DirectorySeparatorChar);
|
|
expdir = expdir.Replace('/', Path.DirectorySeparatorChar);
|
|
// set to default value if empty
|
|
if (String.IsNullOrEmpty(expdir))
|
|
expdir = "Tmp";
|
|
// replace variables, if any
|
|
expdir = VC.ReplaceAllVars(expdir);
|
|
// remove directory separator chars at begin and end
|
|
expdir = expdir.TrimStart(Path.DirectorySeparatorChar);
|
|
expdir = expdir.TrimEnd(Path.DirectorySeparatorChar);
|
|
// fully qualify path
|
|
if (!expdir.Contains(Path.VolumeSeparatorChar))
|
|
expdir = Path.Combine(AppDataDirectory, expdir);
|
|
return expdir;
|
|
}
|
|
}
|
|
|
|
GMapOverlay Coverageoverlay = new GMapOverlay("Coveragepolygons");
|
|
GMapOverlay Locationsoverlay = new GMapOverlay("Locations");
|
|
|
|
DataSet SB = new DataSet();
|
|
|
|
DataTableLocations Locations = new DataTableLocations();
|
|
DataView LocationsView;
|
|
|
|
DataTable QRV = new DataTable();
|
|
DataView QRVView;
|
|
|
|
NumberFormatInfo ENprovider;
|
|
|
|
public LogWriter Log = LogWriter.Instance;
|
|
public VarConverter VC = new VarConverter();
|
|
|
|
private bool IsMarkerDragging = false;
|
|
private bool IsMarkerDragged = false;
|
|
|
|
private GMarkerGoogle CurrentMarker = null;
|
|
private double CurrentMarkerLat;
|
|
private double CurrentMarkerLon;
|
|
|
|
private double OfsLat, OfsLon;
|
|
|
|
public MainDlg()
|
|
{
|
|
InitializeComponent();
|
|
ENprovider = new NumberFormatInfo();
|
|
ENprovider.NumberDecimalSeparator = ".";
|
|
ENprovider.NumberGroupSeparator = ",";
|
|
CheckDirectories();
|
|
// set directories and formats for logfile
|
|
ScoutBase.Core.Properties.Settings.Default.LogWriter_Directory = LogDirectory;
|
|
ScoutBase.Core.Properties.Settings.Default.LogWriter_FileFormat = "Log_{0:yyyy_MM_dd}.log";
|
|
ScoutBase.Core.Properties.Settings.Default.LogWriter_MessageFormat = "{0:u} {1}";
|
|
Locations.RowChanged += new DataRowChangeEventHandler(Locations_Row_Changed);
|
|
QRV.RowChanged += new DataRowChangeEventHandler(QRV_Row_Changed);
|
|
tc_Main.Enabled = false;
|
|
}
|
|
|
|
private void MainDlg_Load(object sender, EventArgs e)
|
|
{
|
|
Log.WriteMessage("Starting up.");
|
|
// set initial settings for CoverageMap
|
|
GMap.NET.MapProviders.GMapProvider.UserAgent = "AirScout";
|
|
// clearing referrer URL issue 2019-12-14
|
|
gm_Coverage.MapProvider.RefererUrl = "";
|
|
gm_Coverage.MapProvider = GMapProviders.Find(Properties.Settings.Default.Map_Provider);
|
|
gm_Coverage.IgnoreMarkerOnMouseWheel = true;
|
|
gm_Coverage.MinZoom = 0;
|
|
gm_Coverage.MaxZoom = 20;
|
|
gm_Coverage.Zoom = 6;
|
|
gm_Coverage.DragButton = System.Windows.Forms.MouseButtons.Left;
|
|
gm_Coverage.CanDragMap = true;
|
|
gm_Coverage.ScalePen = new Pen(Color.Black, 3);
|
|
gm_Coverage.HelperLinePen = null;
|
|
gm_Coverage.SelectionPen = null;
|
|
gm_Coverage.MapScaleInfoEnabled = true;
|
|
gm_Coverage.Overlays.Add(Coverageoverlay);
|
|
// set initial settings for locations map
|
|
GMap.NET.MapProviders.GMapProvider.UserAgent = "AirScout";
|
|
// clearing referrer URL issue 2019-12-14
|
|
gm_Locations.MapProvider.RefererUrl = "";
|
|
gm_Locations.MapProvider = GMapProviders.Find(Properties.Settings.Default.Map_Provider);
|
|
gm_Locations.IgnoreMarkerOnMouseWheel = true;
|
|
gm_Locations.MinZoom = 0;
|
|
gm_Locations.MaxZoom = 20;
|
|
gm_Locations.Zoom = 6;
|
|
gm_Locations.DragButton = System.Windows.Forms.MouseButtons.Left;
|
|
gm_Locations.CanDragMap = true;
|
|
gm_Locations.ScalePen = new Pen(Color.Black, 3);
|
|
gm_Locations.HelperLinePen = null;
|
|
gm_Locations.SelectionPen = null;
|
|
gm_Locations.MapScaleInfoEnabled = true;
|
|
gm_Locations.Overlays.Add(Locationsoverlay);
|
|
gm_Locations.ShowCenter = false;
|
|
// initialize QRV table
|
|
DataColumn qrv_call = new DataColumn("Call", typeof(string));
|
|
QRV.Columns.Add(qrv_call);
|
|
DataColumn qrv_loc = new DataColumn("Loc", typeof(string));
|
|
QRV.Columns.Add(qrv_loc);
|
|
QRV.PrimaryKey = new DataColumn[2] { qrv_call, qrv_loc };
|
|
string[] bands = Bands.GetStringValuesExceptNoneAndAll();
|
|
foreach (string band in bands)
|
|
{
|
|
if (!band.StartsWith("50M") && !band.StartsWith("70M"))
|
|
{
|
|
QRV.Columns.Add(band + "_AH", typeof(double));
|
|
QRV.Columns.Add(band + "_AG", typeof(double));
|
|
QRV.Columns.Add(band + "_P", typeof(double));
|
|
}
|
|
}
|
|
QRV.Columns.Add("LastUpdated", typeof(DateTime));
|
|
// initilize databases
|
|
AircraftData.Database.GetDBLocation();
|
|
StationData.Database.GetDBLocation();
|
|
bw_DatabaseUpdater.RunWorkerAsync();
|
|
}
|
|
|
|
private void MainDlg_FormClosing(object sender, FormClosingEventArgs e)
|
|
{
|
|
Properties.Settings.Default.Save();
|
|
bw_QRZ.CancelAsync();
|
|
Log.WriteMessage("Closing.");
|
|
}
|
|
|
|
public void CheckDirectories()
|
|
{
|
|
// check if directories exist
|
|
if (!Directory.Exists(TmpDirectory))
|
|
Directory.CreateDirectory(TmpDirectory);
|
|
if (!Directory.Exists(LogDirectory))
|
|
Directory.CreateDirectory(LogDirectory);
|
|
if (!Directory.Exists(ExportDirectory))
|
|
Directory.CreateDirectory(ExportDirectory);
|
|
}
|
|
|
|
|
|
private void Say(string text)
|
|
{
|
|
if (tsl_Status.Text != text)
|
|
{
|
|
tsl_Status.Text = text;
|
|
ss_Main.Refresh();
|
|
}
|
|
}
|
|
|
|
private void SayLocations(string text)
|
|
{
|
|
if (tb_Locations_Status.Text != text)
|
|
{
|
|
tb_Locations_Status.Text = text;
|
|
tb_Locations_Status.Refresh();
|
|
Application.DoEvents();
|
|
}
|
|
}
|
|
|
|
private void SayQRV(string text)
|
|
{
|
|
if (tb_QRV_Status.Text != text)
|
|
{
|
|
tb_QRV_Status.Text = text;
|
|
tb_QRV_Status.Refresh();
|
|
Application.DoEvents();
|
|
}
|
|
}
|
|
|
|
#region tp_General
|
|
|
|
private void tp_General_Enter(object sender, EventArgs e)
|
|
{
|
|
tp_General_Update(this, null);
|
|
}
|
|
|
|
private void tp_General_Update(object sender, EventArgs e)
|
|
{
|
|
Coverageoverlay.Clear();
|
|
// add tile to map polygons
|
|
List<PointLatLng> l = new List<PointLatLng>();
|
|
l.Add(new PointLatLng(tb_Coverage_MinLat.Value, tb_Coverage_MinLon.Value));
|
|
l.Add(new PointLatLng(tb_Coverage_MinLat.Value, tb_Coverage_MaxLon.Value));
|
|
l.Add(new PointLatLng(tb_Coverage_MaxLat.Value, tb_Coverage_MaxLon.Value));
|
|
l.Add(new PointLatLng(tb_Coverage_MaxLat.Value, tb_Coverage_MinLon.Value));
|
|
GMapPolygon p = new GMapPolygon(l, "Coverage");
|
|
p.Stroke = new Pen(Color.FromArgb(255, Color.Magenta), 3);
|
|
p.Fill = new SolidBrush(Color.FromArgb(0, Color.Magenta));
|
|
Coverageoverlay.Polygons.Add(p);
|
|
// zoom the map
|
|
gm_Coverage.SetZoomToFitRect(RectLatLng.FromLTRB(tb_Coverage_MinLon.Value - 1, tb_Coverage_MaxLat.Value + 1, tb_Coverage_MaxLon.Value + 1, tb_Coverage_MinLat.Value - 1));
|
|
}
|
|
|
|
|
|
#endregion
|
|
|
|
#region tp_Locations
|
|
|
|
private void tp_Locations_Enter(object sender, EventArgs e)
|
|
{
|
|
// clear map
|
|
Locationsoverlay.Clear();
|
|
Locations.Clear();
|
|
Locations.Merge(StationData.Database.LocationToDataTable());
|
|
Locations.AcceptChanges();
|
|
LocationsView = new DataView(Locations);
|
|
BindingSource source = new BindingSource();
|
|
source.DataSource = LocationsView;
|
|
dgv_Locations.DataSource = source;
|
|
dgv_Locations.ShowRowErrors = true;
|
|
}
|
|
|
|
private void btn_QRZ_Start_Click(object sender, EventArgs e)
|
|
{
|
|
if (!bw_QRZ.IsBusy)
|
|
bw_QRZ.RunWorkerAsync();
|
|
}
|
|
|
|
private void btn_QRZ_Stop_Click(object sender, EventArgs e)
|
|
{
|
|
bw_QRZ.CancelAsync();
|
|
}
|
|
|
|
private void btn_Locations_Sort_Click(object sender, EventArgs e)
|
|
{
|
|
// sort data table
|
|
DataTableLocations sorted = (DataTableLocations)Locations.Clone();
|
|
DataRow[] rows = Locations.Select("", "Call ASC");
|
|
if (rows.Length > 0)
|
|
{
|
|
foreach (DataRow row in rows)
|
|
sorted.ImportRow(row);
|
|
}
|
|
Locations.Clear();
|
|
foreach (DataRow row in sorted.Rows)
|
|
Locations.ImportRow(row);
|
|
}
|
|
|
|
private void btn_Locations_Save_Click(object sender, EventArgs e)
|
|
{
|
|
SayLocations("Saving changes to database...");
|
|
foreach (DataRow row in Locations.Rows)
|
|
{
|
|
LocationDesignator ld = new LocationDesignator(row);
|
|
StationData.Database.LocationInsertOrUpdateIfNewer(ld);
|
|
}
|
|
SayLocations("Finished.");
|
|
}
|
|
|
|
private void btn_Locations_Export_Click(object sender, EventArgs e)
|
|
{
|
|
string filename = Path.Combine(ExportDirectory, "locations.json");
|
|
SayLocations("Exporting database to " + filename);
|
|
string json = StationData.Database.LocationToJSON();
|
|
SupportFunctions.WriteStringToFile(json, filename);
|
|
SayLocations("Finished.");
|
|
}
|
|
|
|
private void btn_Locations_Import_AirScout_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private void btn_Locations_Import_CALL3_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private void btn_Locations_Import_DTB_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private void btn_Locations_Import_CSV_Click(object sender, EventArgs e)
|
|
{
|
|
}
|
|
|
|
private void btn_Locations_Import_USR_Click(object sender, EventArgs e)
|
|
{
|
|
FolderBrowserDialog Dlg = new FolderBrowserDialog();
|
|
Dlg.ShowNewFolderButton = false;
|
|
if (Dlg.ShowDialog() == DialogResult.OK)
|
|
{
|
|
DataTableLocations dt = new DataTableLocations();
|
|
string[] files = Directory.GetFiles(Dlg.SelectedPath, "*.usr");
|
|
foreach (string file in files)
|
|
{
|
|
try
|
|
{
|
|
SayLocations("Importing " + file + "...");
|
|
string s = "";
|
|
using (StreamReader sr = new StreamReader(File.OpenRead(file)))
|
|
{
|
|
while (!sr.EndOfStream)
|
|
{
|
|
s = sr.ReadLine();
|
|
if (!String.IsNullOrEmpty(s) && !s.StartsWith("//"))
|
|
{
|
|
string[] a = s.Split(';');
|
|
// store array values in DataTable
|
|
DataRow row = dt.NewRow();
|
|
string call = a[0];
|
|
if (Callsign.Check(call))
|
|
{
|
|
double lat = System.Convert.ToDouble(a[1], CultureInfo.InvariantCulture);
|
|
double lon = System.Convert.ToDouble(a[2], CultureInfo.InvariantCulture);
|
|
GEOSOURCE source = (MaidenheadLocator.IsPrecise(lat, lon, 3) ? GEOSOURCE.FROMUSER : GEOSOURCE.FROMLOC);
|
|
string lastupdated = a[6];
|
|
DateTime lu = System.Convert.ToDateTime(lastupdated).ToUniversalTime();
|
|
if (GeographicalPoint.Check(lat, lon))
|
|
{
|
|
row["Call"] = call;
|
|
row["Lat"] = lat;
|
|
row["Lon"] = lon;
|
|
row["Source"] = source;
|
|
row["LastUpdated"] = lu;
|
|
dt.Rows.Add(row);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
ImportLocations(dt);
|
|
}
|
|
}
|
|
|
|
private void cb_Locations_ChangedOnly_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (cb_Locations_ChangedOnly.Checked)
|
|
{
|
|
LocationsView.RowStateFilter = DataViewRowState.ModifiedCurrent | DataViewRowState.Added;
|
|
}
|
|
else
|
|
{
|
|
LocationsView.RowStateFilter = DataViewRowState.CurrentRows;
|
|
}
|
|
}
|
|
|
|
private void gm_Locations_MouseDown(object sender, MouseEventArgs e)
|
|
{
|
|
if (e.Button == MouseButtons.Left && CurrentMarker != null && CurrentMarker.IsMouseOver)
|
|
{
|
|
// get geographic coordinates of mouse pointer and calulate offsets
|
|
PointLatLng p = gm_Locations.FromLocalToLatLng(e.X, e.Y);
|
|
OfsLat = p.Lat - CurrentMarker.Position.Lat;
|
|
OfsLon = p.Lng - CurrentMarker.Position.Lng;
|
|
IsMarkerDragging = true;
|
|
IsMarkerDragged = false;
|
|
CurrentMarkerLat = CurrentMarker.Position.Lat;
|
|
CurrentMarkerLon = CurrentMarker.Position.Lng;
|
|
foreach (DataGridViewRow row in dgv_Locations.Rows)
|
|
{
|
|
try
|
|
{
|
|
string call = row.Cells["Call"].Value.ToString();
|
|
string markercall = (string)CurrentMarker.Tag;
|
|
if (String.Equals(call, markercall))
|
|
{
|
|
dgv_Locations.ClearSelection();
|
|
row.Selected = true;
|
|
dgv_Locations.FirstDisplayedScrollingRowIndex = row.Index;
|
|
break;
|
|
}
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
private void gm_Locations_MouseMove(object sender, MouseEventArgs e)
|
|
{
|
|
if (IsMarkerDragging && (CurrentMarker != null))
|
|
{
|
|
// get geographic coordinates of mouse pointer
|
|
PointLatLng p = gm_Locations.FromLocalToLatLng(e.X, e.Y);
|
|
p.Lat = p.Lat - OfsLat;
|
|
p.Lng = p.Lng - OfsLon;
|
|
CurrentMarker.Position = p;
|
|
GPoint c = gm_Locations.FromLatLngToLocal(new PointLatLng(CurrentMarkerLat, CurrentMarkerLon));
|
|
if ((Math.Abs(c.X - e.X) > 20) || (Math.Abs(c.Y - e.Y) > 20))
|
|
{
|
|
IsMarkerDragged = true;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void gm_Locations_MouseUp(object sender, MouseEventArgs e)
|
|
{
|
|
if (CurrentMarker != null)
|
|
{
|
|
if (IsMarkerDragged)
|
|
{
|
|
// get geographic coordinates of mouse pointer
|
|
PointLatLng p = gm_Locations.FromLocalToLatLng(e.X, e.Y);
|
|
double lat = p.Lat - OfsLat;
|
|
double lon = p.Lng - OfsLon;
|
|
string call = CurrentMarker.Tag.ToString();
|
|
string loc = MaidenheadLocator.LocFromLatLon(lat, lon, false, 3);
|
|
GEOSOURCE source = (MaidenheadLocator.IsPrecise(lat, lon, 3) ? GEOSOURCE.FROMUSER : GEOSOURCE.FROMLOC);
|
|
DataRow oldrow = Locations.Rows.Find(new string[] { call, loc });
|
|
if (oldrow != null)
|
|
{
|
|
// call found --> check for update
|
|
if ((double)oldrow["Lat"] != lat)
|
|
{
|
|
oldrow["Lat"] = lat;
|
|
AddRowError(oldrow, "UPDATED", "Lat", "UpdatedValue", "OldValue:" + ((double)oldrow["Lat"]).ToString("F8", CultureInfo.InvariantCulture));
|
|
}
|
|
if ((double)oldrow["Lon"] != lon)
|
|
{
|
|
oldrow["Lon"] = lon;
|
|
AddRowError(oldrow, "UPDATED", "Lon", "UpdatedValue", "OldValue:" + ((double)oldrow["Lon"]).ToString("F8", CultureInfo.InvariantCulture));
|
|
}
|
|
oldrow["Source"] = source;
|
|
AddRowError(oldrow, "UPDATED", "Source", "UpdatedValue", "OldValue:" + oldrow["Source"].ToString());
|
|
oldrow["LastUpdated"] = DateTime.UtcNow;
|
|
}
|
|
else
|
|
{
|
|
// marker is mpved beyond old locator
|
|
// create new line
|
|
if (MessageBox.Show("Marker is moved to a different locator which is not in database so far. Create new entry?","Create new entry", MessageBoxButtons.YesNo) == DialogResult.Yes)
|
|
{
|
|
DataRow row = Locations.NewRow();
|
|
row["Call"] = call;
|
|
row["Loc"] = loc;
|
|
row["Lat"] = lat;
|
|
row["Lon"] = lon;
|
|
row["Source"] = source;
|
|
row["Hits"] = 0;
|
|
row["LastUpdated"] = DateTime.UtcNow;
|
|
Locations.Rows.Add(row);
|
|
}
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// restore original marker position
|
|
CurrentMarker.Position = new PointLatLng(CurrentMarkerLat, CurrentMarkerLon);
|
|
}
|
|
}
|
|
gm_Locations.CanDragMap = true;
|
|
IsMarkerDragging = false;
|
|
IsMarkerDragged = false;
|
|
}
|
|
|
|
private void gm_Locations_OnMarkerEnter(GMapMarker item)
|
|
{
|
|
CurrentMarker = (GMarkerGoogle)item;
|
|
}
|
|
|
|
private void gm_Locations_OnMarkerLeave(GMapMarker item)
|
|
{
|
|
// CurrentMarker = null;
|
|
}
|
|
|
|
private void tb_Locations_Callsign_Filter_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if (String.IsNullOrEmpty(tb_Locations_Callsign_Filter.Text))
|
|
{
|
|
LocationsView.RowFilter = "Call LIKE '*'";
|
|
return;
|
|
}
|
|
string filter = tb_Locations_Callsign_Filter.Text;
|
|
if (!filter.EndsWith("*"))
|
|
filter = filter + "*";
|
|
LocationsView.RowFilter = "Call LIKE '" + filter + "'";
|
|
}
|
|
|
|
#endregion
|
|
|
|
private void dgv_Locations_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
if ((e.RowIndex < 0) || (e.RowIndex >= dgv_Locations.Rows.Count))
|
|
return;
|
|
DataGridViewRow dgvrow = dgv_Locations.Rows[e.RowIndex];
|
|
if ((e.ColumnIndex < 0) || (e.ColumnIndex >= dgvrow.Cells.Count))
|
|
return;
|
|
DataGridViewCell cell = dgvrow.Cells[e.ColumnIndex];
|
|
if (!cell.Displayed)
|
|
return;
|
|
if (String.IsNullOrEmpty(dgvrow.ErrorText))
|
|
return;
|
|
XElement xml = XElement.Parse(dgvrow.ErrorText);
|
|
LOCATIONSTATE state = LOCATIONSTATE.UNKNOWN;
|
|
try
|
|
{
|
|
state = (LOCATIONSTATE)Enum.Parse(typeof(LOCATIONSTATE), xml.Name.ToString());
|
|
}
|
|
catch
|
|
{
|
|
|
|
}
|
|
if (state == LOCATIONSTATE.ERROR)
|
|
cell.Style.BackColor = Color.Red;
|
|
else if (state == LOCATIONSTATE.LOCDIFF)
|
|
cell.Style.BackColor = Color.Khaki;
|
|
else if (state == LOCATIONSTATE.UPTODATE)
|
|
cell.Style.BackColor = Color.LightGreen;
|
|
else if (state == LOCATIONSTATE.ADDED)
|
|
cell.Style.BackColor = Color.LightBlue;
|
|
else if (state == LOCATIONSTATE.UPDATED)
|
|
{
|
|
string s = xml.ToString();
|
|
string propertyname = dgv_Locations.Columns[e.ColumnIndex].DataPropertyName;
|
|
if (s.IndexOf("<" + propertyname + " />") >= 0)
|
|
{
|
|
cell.Style.BackColor = Color.Bisque;
|
|
}
|
|
}
|
|
}
|
|
|
|
private void bw_QRZ_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
// check callsign location against QRZ.com entry
|
|
// name current thread
|
|
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
|
|
Thread.CurrentThread.Name = "QRZ";
|
|
int callschecked = 0;
|
|
int callsfound = 0;
|
|
int callsnotfound = 0;
|
|
int callsuptodate = 0;
|
|
int callsupdated = 0;
|
|
int callsdiffloc = 0;
|
|
int errors = 0;
|
|
// get session key
|
|
WebRequest myWebRequest = WebRequest.Create(Properties.Settings.Default.QRZ_URL_Login);
|
|
myWebRequest.Timeout = 10000;
|
|
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();
|
|
XmlDocument doc = new XmlDocument();
|
|
doc.LoadXml(s);
|
|
var nodes = doc.GetElementsByTagName("Key");
|
|
string sessionkey = nodes[0].InnerText;
|
|
foreach (DataRow row in Locations.Rows)
|
|
{
|
|
try
|
|
{
|
|
callschecked++;
|
|
string call = row["Call"].ToString();
|
|
double lat = (double)row["Lat"];
|
|
double lon = (double)row["Lon"];
|
|
GEOSOURCE source = (GEOSOURCE)row["Source"];
|
|
DateTime lastupdated = (DateTime)row["LastUpdated"];
|
|
string loc = MaidenheadLocator.LocFromLatLon(lat, lon, false, 3);
|
|
string qrzloc = "";
|
|
double qrzlat = 0;
|
|
double qrzlon = 0;
|
|
string geoloc = "";
|
|
string addr1 = "";
|
|
string addr2 = "";
|
|
string zip = "";
|
|
string country = "";
|
|
string error = "";
|
|
// get xml data
|
|
myWebRequest = WebRequest.Create(Properties.Settings.Default.QRZ_URL_XMLData + "?s=" + sessionkey + ";callsign=" + call);
|
|
myWebRequest.Timeout = 10000;
|
|
myWebResponse = myWebRequest.GetResponse();
|
|
ReceiveStream = myWebResponse.GetResponseStream();
|
|
encode = System.Text.Encoding.GetEncoding("utf-8");
|
|
readStream = new StreamReader(ReceiveStream, encode);
|
|
s = readStream.ReadToEnd();
|
|
// load xml document
|
|
doc = new XmlDocument();
|
|
doc.LoadXml(s);
|
|
// check for errors
|
|
nodes = doc.GetElementsByTagName("Error");
|
|
if (nodes.Count > 0)
|
|
{
|
|
error = nodes[0].InnerText;
|
|
if (error.ToUpper().Contains("NOT FOUND"))
|
|
{
|
|
callsnotfound++;
|
|
}
|
|
else if (error.ToUpper().Contains("SESSION TIMEOUT"))
|
|
{
|
|
// session timeout --> obtain a new session key and try again
|
|
myWebRequest = WebRequest.Create(Properties.Settings.Default.QRZ_URL_Login);
|
|
myWebRequest.Timeout = 10000;
|
|
myWebResponse = myWebRequest.GetResponse();
|
|
ReceiveStream = myWebResponse.GetResponseStream();
|
|
encode = System.Text.Encoding.GetEncoding("utf-8");
|
|
readStream = new StreamReader(ReceiveStream, encode);
|
|
s = readStream.ReadToEnd();
|
|
doc = new XmlDocument();
|
|
doc.LoadXml(s);
|
|
nodes = doc.GetElementsByTagName("Key");
|
|
sessionkey = nodes[0].InnerText;
|
|
bw_QRZ.ReportProgress((int)LOCATIONSTATE.INFO, "Obtained new session key: " + sessionkey);
|
|
// get xml data
|
|
myWebRequest = WebRequest.Create(Properties.Settings.Default.QRZ_URL_XMLData + "?s=" + sessionkey + ";callsign=" + call);
|
|
myWebRequest.Timeout = 10000;
|
|
myWebResponse = myWebRequest.GetResponse();
|
|
ReceiveStream = myWebResponse.GetResponseStream();
|
|
encode = System.Text.Encoding.GetEncoding("utf-8");
|
|
readStream = new StreamReader(ReceiveStream, encode);
|
|
s = readStream.ReadToEnd();
|
|
// load xml document
|
|
doc = new XmlDocument();
|
|
doc.LoadXml(s);
|
|
}
|
|
else
|
|
{
|
|
// report error
|
|
errors++;
|
|
bw_QRZ.ReportProgress((int)LOCATIONSTATE.ERROR, error);
|
|
}
|
|
}
|
|
// write xml to file
|
|
else
|
|
{
|
|
using (StreamWriter sw = new StreamWriter(call.Replace("/", "_") + ".xml"))
|
|
{
|
|
sw.WriteLine(s);
|
|
}
|
|
callsfound++;
|
|
nodes = doc.GetElementsByTagName("lat");
|
|
if (nodes.Count > 0)
|
|
qrzlat = System.Convert.ToDouble(nodes[0].InnerText, CultureInfo.InvariantCulture);
|
|
nodes = doc.GetElementsByTagName("lon");
|
|
if (nodes.Count > 0)
|
|
qrzlon = System.Convert.ToDouble(nodes[0].InnerText, CultureInfo.InvariantCulture);
|
|
nodes = doc.GetElementsByTagName("grid");
|
|
if (nodes.Count > 0)
|
|
qrzloc = nodes[0].InnerText.ToUpper().Trim();
|
|
nodes = doc.GetElementsByTagName("geoloc");
|
|
if (nodes.Count > 0)
|
|
geoloc = nodes[0].InnerText;
|
|
nodes = doc.GetElementsByTagName("addr1");
|
|
if (nodes.Count > 0)
|
|
addr1 = nodes[0].InnerText;
|
|
nodes = doc.GetElementsByTagName("addr2");
|
|
if (nodes.Count > 0)
|
|
addr2 = nodes[0].InnerText;
|
|
nodes = doc.GetElementsByTagName("zip");
|
|
if (nodes.Count > 0)
|
|
zip = nodes[0].InnerText;
|
|
nodes = doc.GetElementsByTagName("country");
|
|
if (nodes.Count > 0)
|
|
country = nodes[0].InnerText;
|
|
// different loc?
|
|
if (loc != qrzloc)
|
|
{
|
|
Log.WriteMessage("QRZ.COM: Locator is different [" + call + "]: " + loc + " <> " + qrzloc, LogLevel.Warning);
|
|
callsdiffloc++;
|
|
}
|
|
// precise location by user or geocode?
|
|
else if (geoloc.ToUpper().Contains("USER") || geoloc.ToUpper().Contains("GEOCODE"))
|
|
{
|
|
if ((qrzlat != lat) || (qrzlon != lon))
|
|
{
|
|
Log.WriteMessage("QRZ.COM: Location updated [" + call + "].");
|
|
callsupdated++;
|
|
LocationDesignator ld = new LocationDesignator(call, qrzlat, qrzlon, GEOSOURCE.FROMUSER);
|
|
bw_QRZ.ReportProgress((int)LOCATIONSTATE.UPDATED, ld);
|
|
}
|
|
else
|
|
{
|
|
// already up to date
|
|
Log.WriteMessage("QRZ.COM: Location up to date [" + call + "].");
|
|
callsuptodate++;
|
|
}
|
|
}
|
|
else if (geoloc.ToUpper().Contains("GRID"))
|
|
{
|
|
// try to get info by OpenStreetMaps API
|
|
string url = "https://nominatim.openstreetmap.org/search?q=" + addr1 + "+" + addr2 + "+" + zip + "+" + country + "&format=xml&polygon=1&addressdetails=1";
|
|
HttpWebRequest httpWebRequest = (HttpWebRequest)HttpWebRequest.Create(url);
|
|
httpWebRequest.UserAgent = "Mozilla / 5.0(Windows NT 10.0; Win64; x64; rv: 61.0) Gecko / 20100101 Firefox / 61.0";
|
|
HttpWebResponse httpWebResponse= (HttpWebResponse)httpWebRequest.GetResponse();
|
|
ReceiveStream = httpWebResponse.GetResponseStream();
|
|
// encode = System.Text.Encoding.GetEncoding("utf-8");
|
|
readStream = new StreamReader(ReceiveStream, encode);
|
|
s = readStream.ReadToEnd();
|
|
// load xml document
|
|
doc = new XmlDocument();
|
|
doc.LoadXml(s);
|
|
double glat = 0;
|
|
double glon = 0;
|
|
string gloc = "";
|
|
nodes = doc.GetElementsByTagName("place");
|
|
if (nodes.Count > 0)
|
|
{
|
|
glat = System.Convert.ToDouble(nodes[0].Attributes["lat"].Value.ToString(), CultureInfo.InvariantCulture);
|
|
glon = System.Convert.ToDouble(nodes[0].Attributes["lon"].Value.ToString(), CultureInfo.InvariantCulture);
|
|
}
|
|
gloc = MaidenheadLocator.LocFromLatLon(glat, glon, false, 3);
|
|
if (gloc == qrzloc)
|
|
{
|
|
// precise location from address
|
|
Log.WriteMessage("QRZ.COM: Location updated from postal address[" + call + "].");
|
|
callsupdated++;
|
|
LocationDesignator ld = new LocationDesignator(call, glat, glon, GEOSOURCE.FROMUSER);
|
|
bw_QRZ.ReportProgress((int)LOCATIONSTATE.UPDATED, ld);
|
|
}
|
|
else
|
|
{
|
|
Log.WriteMessage("QRZ.COM: Locator is different [" + call + "]: " + loc + " <> " + qrzloc, LogLevel.Warning);
|
|
callsdiffloc++;
|
|
}
|
|
}
|
|
// alreadyup to date?
|
|
else if ((lat == qrzlat) && (lon == qrzlon))
|
|
{
|
|
callsuptodate++;
|
|
}
|
|
}
|
|
string status = "QRZ.COM query is running: " +
|
|
callschecked.ToString() + " checked, " +
|
|
callsnotfound.ToString() + " not found, " +
|
|
callsfound.ToString() + " found, " +
|
|
callsuptodate.ToString() + " up to date, " +
|
|
callsupdated.ToString() + " updated, " +
|
|
callsdiffloc.ToString() + " different loc, " +
|
|
errors.ToString() + " errors";
|
|
bw_QRZ.ReportProgress((int)LOCATIONSTATE.INFO, status);
|
|
if (bw_QRZ.CancellationPending)
|
|
return;
|
|
Thread.Sleep(10);
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
errors++;
|
|
bw_QRZ.ReportProgress((int)LOCATIONSTATE.ERROR, ex.Message);
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void bw_QRZ_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
|
{
|
|
LOCATIONSTATE state = (LOCATIONSTATE)e.ProgressPercentage;
|
|
if (state <= 0)
|
|
SayLocations((string)e.UserState);
|
|
else
|
|
{
|
|
LocationDesignator ld = (LocationDesignator)e.UserState;
|
|
// update data table
|
|
try
|
|
{
|
|
DataRow row = Locations.Rows.Find(new string[2] { ld.Call, ld.Loc });
|
|
if (row != null)
|
|
{
|
|
if (state == LOCATIONSTATE.UPTODATE)
|
|
AddRowError(row, state.ToString(), "", "", "");
|
|
else if (state == LOCATIONSTATE.LOCDIFF)
|
|
AddRowError(row, state.ToString(), "", "", "");
|
|
else
|
|
{
|
|
if ((double)row["Lat"] != ld.Lat)
|
|
{
|
|
AddRowError(row, state.ToString(), "Lat", "UpdatedValue", "OldValue:" + ((double)row["Lat"]).ToString("F8", CultureInfo.InvariantCulture));
|
|
row["Lat"] = ld.Lat;
|
|
}
|
|
if ((double)row["Lon"] != ld.Lon)
|
|
{
|
|
AddRowError(row, state.ToString(), "Lon", "UpdatedValue", "OldValue:" + ((double)row["Lon"]).ToString("F8", CultureInfo.InvariantCulture));
|
|
row["Lon"] = ld.Lon;
|
|
}
|
|
row["Source"] = ld.Source;
|
|
row["LastUpdated"] = ld.LastUpdated;
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void bw_QRZ_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
SayLocations("Finished.");
|
|
}
|
|
|
|
|
|
private void AddRowError(DataRow row, string category, string node, string item, string text)
|
|
{
|
|
try
|
|
{
|
|
// create XML document if not already created
|
|
if (String.IsNullOrEmpty(row.RowError))
|
|
{
|
|
XElement x = new XElement(category);
|
|
row.RowError = x.ToString();
|
|
}
|
|
// read out Errors as XML from RowError
|
|
XElement xml = XElement.Parse(row.RowError);
|
|
if (String.IsNullOrEmpty(node))
|
|
return;
|
|
xml.Add(new XElement(node));
|
|
if (String.IsNullOrEmpty(item))
|
|
return;
|
|
xml.Add(new XElement(item, text));
|
|
row.RowError = xml.ToString();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
|
|
private void ImportLocations(DataTable dt)
|
|
{
|
|
if (dt != null)
|
|
{
|
|
int callsimported = dt.Rows.Count;
|
|
int callsupdated = 0;
|
|
int callsadded = 0;
|
|
foreach (DataRow row in dt.Rows)
|
|
{
|
|
DataRow oldrow = Locations.Rows.Find(row["Call"].ToString());
|
|
if (oldrow != null)
|
|
{
|
|
// call found --> check for update
|
|
if ((DateTime)row["LastUpdated"] > (DateTime)oldrow["LastUpdated"])
|
|
{
|
|
if (oldrow["Lat"] != row["Lat"])
|
|
{
|
|
oldrow["Lat"] = row["Lat"];
|
|
AddRowError(oldrow, "UPDATED", "Lat", "UpdatedValue", "OldValue:" + ((double)oldrow["Lat"]).ToString("F8", CultureInfo.InvariantCulture));
|
|
}
|
|
if (oldrow["Lon"] != row["Lon"])
|
|
{
|
|
oldrow["Lon"] = row["Lon"];
|
|
AddRowError(oldrow, "UPDATED", "Lon", "UpdatedValue", "OldValue:" + ((double)oldrow["Lon"]).ToString("F8", CultureInfo.InvariantCulture));
|
|
}
|
|
if (oldrow["Source"] != row["Source"])
|
|
{
|
|
oldrow["Source"] = row["Source"];
|
|
AddRowError(oldrow, "UPDATED", "Source", "UpdatedValue", "OldValue:" + oldrow["Source"].ToString());
|
|
}
|
|
oldrow["LastUpdated"] = row["LastUpdated"];
|
|
callsupdated++;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
// add new row
|
|
AddRowError(row, LOCATIONSTATE.ADDED.ToString(), "", "", "");
|
|
Locations.ImportRow(row);
|
|
callsadded++;
|
|
}
|
|
}
|
|
SayLocations("Import of " + dt.TableName + " finished: " + callsimported.ToString() + " calls imported, " + callsadded.ToString() + " calls added, " + callsupdated.ToString() + " calls updated.");
|
|
}
|
|
}
|
|
|
|
private void Locations_Row_Changed(object sender, DataRowChangeEventArgs e)
|
|
{
|
|
|
|
try
|
|
{
|
|
string call = e.Row["Call"].ToString();
|
|
double lat = (double)e.Row["Lat"];
|
|
double lon = (double)e.Row["Lon"];
|
|
GEOSOURCE source = (GEOSOURCE)Enum.Parse(typeof(GEOSOURCE), e.Row["Source"].ToString());
|
|
if (e.Action == DataRowAction.Add)
|
|
{
|
|
GMarkerGoogle gm = new GMarkerGoogle(new PointLatLng(lat, lon), (source == GEOSOURCE.FROMUSER) ? GMarkerGoogleType.green_small : GMarkerGoogleType.white_small);
|
|
gm.ToolTipText = call;
|
|
gm.ToolTipMode = MarkerTooltipMode.OnMouseOver;
|
|
gm.Tag = call;
|
|
Locationsoverlay.Markers.Add(gm);
|
|
}
|
|
else if (e.Action == DataRowAction.Change)
|
|
{
|
|
GMarkerGoogle gm = (GMarkerGoogle)Locationsoverlay.Markers.First(c => (string)c.Tag == call);
|
|
if (gm != null)
|
|
gm.Position = new PointLatLng(lat, lon);
|
|
}
|
|
else if (e.Action == DataRowAction.Delete)
|
|
{
|
|
GMarkerGoogle gm = (GMarkerGoogle)Locationsoverlay.Markers.First(c => (string)c.Tag == call);
|
|
if (gm != null)
|
|
Locationsoverlay.Markers.Remove(gm);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
|
|
private void btn_QRV_Import_WinTest_Click(object sender, EventArgs e)
|
|
{
|
|
DataTable dt = QRV.Clone();
|
|
dt.Rows.Clear();
|
|
OpenFileDialog Dlg = new OpenFileDialog();
|
|
Dlg.DefaultExt = ".xdt";
|
|
Dlg.Filter = "Win-Test database|*.xdt";
|
|
Dlg.CheckFileExists = true;
|
|
if (Dlg.ShowDialog() == DialogResult.OK)
|
|
{
|
|
try
|
|
{
|
|
int qrv_ok = 0;
|
|
int qrv_err = 0;
|
|
using (StreamReader sr = new StreamReader(File.OpenRead(Dlg.FileName)))
|
|
{
|
|
while (!sr.EndOfStream)
|
|
{
|
|
string s = sr.ReadLine().Trim();
|
|
string[] a = s.Split();
|
|
DataRow row = dt.NewRow();
|
|
row["Call"] = a[0];
|
|
SayQRV("Importing call: " + a[0] + "...");
|
|
DateTime lastupdated = DateTime.MinValue;
|
|
try
|
|
{
|
|
a[1] = a[1].Replace("[", "").Replace("]", "");
|
|
lastupdated = DateTime.ParseExact(a[1], "yyyy-MM-dd", CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal);
|
|
lastupdated = lastupdated.ToUniversalTime();
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
qrv_err++;
|
|
}
|
|
row["LastUpdated"] = lastupdated;
|
|
for (int i = 2; i < a.Length; i++)
|
|
{
|
|
a[i] = a[i].Trim();
|
|
if (!String.IsNullOrEmpty(a[i]))
|
|
{
|
|
try
|
|
{
|
|
row[a[i] + "_AH"] = 0;
|
|
row[a[i] + "_AG"] = 0;
|
|
row[a[i] + "_P"] = 0;
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
qrv_err++;
|
|
}
|
|
}
|
|
}
|
|
dt.Rows.Add(row);
|
|
qrv_ok++;
|
|
}
|
|
}
|
|
QRV.Merge(dt);
|
|
SayQRV("Importing calls finished: " + qrv_ok + " calls, " + qrv_err + " error(s).");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void tp_QRV_Enter(object sender, EventArgs e)
|
|
{
|
|
QRV.Rows.Clear();
|
|
BAND[] bands = Bands.GetValuesExceptNoneAndAll();
|
|
foreach (BAND band in bands)
|
|
{
|
|
if (band > BAND.B70M)
|
|
{
|
|
SayQRV("Importing band: " + Bands.GetStringValue(band) + "...");
|
|
List<QRVDesignator> qrvs = StationData.Database.QRVGetAll(band);
|
|
string band_ah = Bands.GetStringValue(band) + "_AH";
|
|
string band_ag = Bands.GetStringValue(band) + "_AG";
|
|
string band_p = Bands.GetStringValue(band) + "_P";
|
|
if (qrvs != null)
|
|
{
|
|
foreach (QRVDesignator qrv in qrvs)
|
|
{
|
|
DataRow row = QRV.Rows.Find(new string[]{ qrv.Call, qrv.Loc});
|
|
if (row == null)
|
|
{
|
|
row = QRV.NewRow();
|
|
row["Call"] = qrv.Call;
|
|
row["Loc"] = qrv.Loc;
|
|
row["LastUpdated"] = DateTime.MinValue;
|
|
QRV.Rows.Add(row);
|
|
}
|
|
row[band_ah] = qrv.AntennaHeight;
|
|
row[band_ag] = qrv.AntennaGain;
|
|
row[band_p] = qrv.Power;
|
|
if ((DateTime)row["LastUpdated"] < qrv.LastUpdated)
|
|
row["LastUpdated"] = qrv.LastUpdated;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
QRV.AcceptChanges();
|
|
QRVView = new DataView(QRV);
|
|
BindingSource source = new BindingSource();
|
|
source.DataSource = QRVView;
|
|
dgv_QRV.DataSource = source;
|
|
dgv_QRV.ShowRowErrors = true;
|
|
dgv_QRV.AutoSizeColumnsMode = DataGridViewAutoSizeColumnsMode.Fill;
|
|
for (int i = 0; i < dgv_QRV.Columns.Count; i++)
|
|
{
|
|
if (i % 2 == 0)
|
|
dgv_QRV.Columns[i].DefaultCellStyle.BackColor = Color.LightGray;
|
|
}
|
|
SayQRV("Finished.");
|
|
}
|
|
|
|
private void tb_QRV_Callsign_Filter_TextChanged(object sender, EventArgs e)
|
|
{
|
|
if (String.IsNullOrEmpty(tb_QRV_Callsign_Filter.Text))
|
|
{
|
|
QRVView.RowFilter = "Call LIKE '*'";
|
|
return;
|
|
}
|
|
string filter = tb_QRV_Callsign_Filter.Text;
|
|
if (!filter.EndsWith("*"))
|
|
filter = filter + "*";
|
|
QRVView.RowFilter = "Call LIKE '" + filter + "'";
|
|
|
|
}
|
|
|
|
private void btn_QRV_Sort_Click(object sender, EventArgs e)
|
|
{
|
|
// sort data table
|
|
DataTable sorted = QRV.Clone();
|
|
DataRow[] rows = QRV.Select("", "Call ASC");
|
|
if (rows.Length > 0)
|
|
{
|
|
foreach (DataRow row in rows)
|
|
sorted.ImportRow(row);
|
|
}
|
|
QRV.Clear();
|
|
foreach (DataRow row in sorted.Rows)
|
|
QRV.ImportRow(row);
|
|
}
|
|
|
|
private void btn_QRV_Save_Click(object sender, EventArgs e)
|
|
{
|
|
SayQRV("Saving changes to database...");
|
|
try
|
|
{
|
|
foreach (DataRow row in QRV.Rows)
|
|
{
|
|
if ((row.RowState == DataRowState.Added) || (row.RowState == DataRowState.Modified))
|
|
{
|
|
BAND[] bands = Bands.GetValuesExceptNoneAndAll();
|
|
foreach (BAND band in bands)
|
|
{
|
|
if (band > BAND.B70M)
|
|
{
|
|
string band_ah = Bands.GetStringValue(band) + "_AH";
|
|
string band_ag = Bands.GetStringValue(band) + "_AG";
|
|
string band_p = Bands.GetStringValue(band) + "_P";
|
|
QRVDesignator qrv = new QRVDesignator();
|
|
qrv.Call = row["Call"].ToString().ToUpper();
|
|
qrv.Loc = row["Loc"].ToString().ToUpper();
|
|
qrv.Band = band;
|
|
if ((row[band_ah].GetType() != typeof(DBNull)) && (row[band_ah].GetType() != typeof(DBNull)) && (row[band_ah].GetType() != typeof(DBNull)))
|
|
{
|
|
qrv.AntennaHeight = (double)row[band_ah];
|
|
qrv.AntennaGain = (double)row[band_ag];
|
|
qrv.Power = (double)row[band_p];
|
|
qrv.LastUpdated = (DateTime)row["LastUpdated"];
|
|
SayQRV("Updating " + qrv.Call + ", " + qrv.Loc + "...");
|
|
StationData.Database.QRVInsertOrUpdateIfNewer(qrv);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Log.WriteMessage(ex.ToString(), LogLevel.Error);
|
|
}
|
|
SayQRV("Finished.");
|
|
|
|
}
|
|
|
|
private void btn_QRV_Export_Click(object sender, EventArgs e)
|
|
{
|
|
string filename = Path.Combine(ExportDirectory, "qrv.json");
|
|
SayQRV("Exporting database to " + filename);
|
|
string json = StationData.Database.QRVToJSON();
|
|
SupportFunctions.WriteStringToFile(json, filename);
|
|
SayQRV("Finished.");
|
|
}
|
|
|
|
private void QRV_Row_Changed(object sender, DataRowChangeEventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void dgv_QRV_CellValueChanged(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
// update LastUpdated column in case of changes
|
|
if (e.ColumnIndex < dgv_QRV.Columns.Count - 1)
|
|
{
|
|
dgv_QRV.Rows[e.RowIndex].Cells["LastUpdated"].Value = DateTime.UtcNow;
|
|
}
|
|
}
|
|
|
|
private void dgv_QRV_CellEndEdit(object sender, DataGridViewCellEventArgs e)
|
|
{
|
|
}
|
|
|
|
private void btn_QRV_Import_EDI_Click(object sender, EventArgs e)
|
|
{
|
|
|
|
}
|
|
|
|
private void cb_QRV_ChangedOnly_CheckedChanged(object sender, EventArgs e)
|
|
{
|
|
if (cb_QRV_ChangedOnly.Checked)
|
|
{
|
|
QRVView.RowStateFilter = DataViewRowState.ModifiedCurrent | DataViewRowState.Added;
|
|
}
|
|
else
|
|
{
|
|
QRVView.RowStateFilter = DataViewRowState.CurrentRows;
|
|
}
|
|
}
|
|
|
|
private void btn_SFTP_GenerateFile_Click(object sender, EventArgs e)
|
|
{
|
|
// generates password file for SFTP and other
|
|
if (String.IsNullOrEmpty(tb_SFTP_URL.Text) || String.IsNullOrEmpty(tb_SFTP_User.Text) || String.IsNullOrEmpty(tb_SFTP_Password.Text))
|
|
{
|
|
MessageBox.Show("Invalid entries for URL, user or password!");
|
|
return;
|
|
}
|
|
SaveFileDialog Dlg = new SaveFileDialog();
|
|
Dlg.FileName = "airscout.pwd";
|
|
if (Dlg.ShowDialog() == DialogResult.OK)
|
|
{
|
|
using (StreamWriter sw = new StreamWriter(Dlg.FileName,false))
|
|
{
|
|
string s = tb_SFTP_URL.Text + "\t" + Encryption.SimpleEncryptString(tb_SFTP_User.Text) + "\t" + Encryption.SimpleEncryptString(tb_SFTP_Password.Text);
|
|
sw.WriteLine(s);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void dgv_QRV_CellFormatting(object sender, DataGridViewCellFormattingEventArgs e)
|
|
{
|
|
if ((e.Value != null) && (e.Value != DBNull.Value))
|
|
{
|
|
e.Value = e.Value.ToString().ToUpper();
|
|
e.FormattingApplied = true;
|
|
}
|
|
}
|
|
|
|
private void btn_Update_Airlines_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
string json = "";
|
|
using (var client = new WebClient())
|
|
{
|
|
json = client.DownloadString(Properties.Settings.Default.Airlines_Update_URL);
|
|
}
|
|
JsonSerializerSettings settings = new JsonSerializerSettings();
|
|
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
|
settings.FloatFormatHandling = FloatFormatHandling.String;
|
|
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
FR24Airlines fr24airlines = (FR24Airlines)JsonConvert.DeserializeObject<FR24Airlines>(json, settings);
|
|
int count = 0;
|
|
int errors = 0;
|
|
foreach (FR24AirlineDesignator fr24ad in fr24airlines.rows)
|
|
{
|
|
if (!String.IsNullOrEmpty(fr24ad.Code) && !String.IsNullOrEmpty(fr24ad.ICAO))
|
|
{
|
|
AirlineDesignator ad = new AirlineDesignator(fr24ad.ICAO, fr24ad.Code, fr24ad.Name, "[unknown]");
|
|
int result = AircraftData.Database.AirlineInsertOrUpdateIfNewer(ad);
|
|
if (result >= 0)
|
|
count += result;
|
|
else
|
|
errors++;
|
|
}
|
|
}
|
|
Say("Airlines updated from " + Properties.Settings.Default.Airlines_Update_URL + ": " + count.ToString() + " updated, " + errors.ToString() + " error(s).");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
}
|
|
}
|
|
|
|
private void btn_Update_Airports_Click(object sender, EventArgs e)
|
|
{
|
|
try
|
|
{
|
|
string json = "";
|
|
using (var client = new WebClient())
|
|
{
|
|
json = client.DownloadString(Properties.Settings.Default.Airports_Update_URL);
|
|
}
|
|
JsonSerializerSettings settings = new JsonSerializerSettings();
|
|
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
|
settings.FloatFormatHandling = FloatFormatHandling.String;
|
|
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
FR24Airports fr24airports = (FR24Airports)JsonConvert.DeserializeObject<FR24Airports>(json, settings);
|
|
int count = 0;
|
|
int errors = 0;
|
|
foreach (FR24AirportDesignator fr24ad in fr24airports.rows)
|
|
{
|
|
if (!String.IsNullOrEmpty(fr24ad.icao) && !String.IsNullOrEmpty(fr24ad.iata))
|
|
{
|
|
AirportDesignator ad = new AirportDesignator(fr24ad.icao, fr24ad.iata, fr24ad.lat, fr24ad.lon, fr24ad.alt, fr24ad.name.Replace("\t","").Replace("\r","").Replace("\n",""), fr24ad.country);
|
|
int result = AircraftData.Database.AirportInsertOrUpdateIfNewer(ad);
|
|
if (result >= 0)
|
|
count += result;
|
|
else
|
|
errors++;
|
|
}
|
|
}
|
|
Say("Airports updated from " + Properties.Settings.Default.Airports_Update_URL + ": " + count.ToString() + " updated, " + errors.ToString() + " error(s).");
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Say(ex.Message);
|
|
}
|
|
|
|
}
|
|
|
|
private void bw_AircraftUpdater_DoWork(object sender, DoWorkEventArgs e)
|
|
{
|
|
// Divide the earth surface into zones optimized for flights density
|
|
List<string> world_zones = new List<string>(new string[] {
|
|
"90, 70, -180, 180",
|
|
"70, 50, -180, -20",
|
|
"70, 50, -20, 0",
|
|
"70, 50, 0, 20",
|
|
"70, 50, 20, 40",
|
|
"70, 50, 40, 180",
|
|
"50, 30, -180, -120",
|
|
"50, 40, -120, -110",
|
|
"50, 40, -110, -100",
|
|
"40, 30, -120, -110",
|
|
"40, 30, -110, -100",
|
|
"50, 40, -100, -90",
|
|
"50, 40, -90, -80",
|
|
"40, 30, -100, -90",
|
|
"40, 30, -90, -80",
|
|
"50, 30, -80, -60",
|
|
"50, 30, -60, -40",
|
|
"50, 30, -40, -20",
|
|
"50, 30, -20, 0",
|
|
"50, 40, 0, 10",
|
|
"50, 40, 10, 20",
|
|
"40, 30, 0, 10",
|
|
"40, 30, 10, 20",
|
|
"50, 30, 20, 40",
|
|
"50, 30, 40, 60",
|
|
"50, 30, 60, 180",
|
|
"30, 10, -180, -100",
|
|
"30, 10, -100, -80",
|
|
"30, 10, -80, 100",
|
|
"30, 10, 100, 180",
|
|
"10, -10, -180, 180",
|
|
"-10, -30, -180, 180",
|
|
"-30, -90, -180, 180"
|
|
} );
|
|
while (!bw_AircraftUpdater.CancellationPending)
|
|
{
|
|
try
|
|
{
|
|
List<AircraftDesignator> aircrafts = new List<AircraftDesignator>();
|
|
int errors = 0;
|
|
foreach (string zone in world_zones)
|
|
{
|
|
string url = Properties.Settings.Default.Aircrafts_BaseURL + "&bounds=" + zone;
|
|
bw_AircraftUpdater.ReportProgress(0, "getting aircrafts from: " + url);
|
|
string json = "";
|
|
using (var client = new WebClient())
|
|
{
|
|
json = client.DownloadString(url);
|
|
}
|
|
// modify the JSON string to get a list of aircrafts
|
|
json = json.Substring(json.IndexOf(",") + 1);
|
|
json = json.Substring(json.IndexOf(",") + 1);
|
|
json = "{rows:{" + json;
|
|
json = json.Remove(json.IndexOf(",\"stats\""));
|
|
json = json + "}}";
|
|
JsonSerializerSettings settings = new JsonSerializerSettings();
|
|
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
|
|
settings.FloatFormatHandling = FloatFormatHandling.String;
|
|
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
|
|
FR24Aircrafts fr24aircrafts = (FR24Aircrafts)JsonConvert.DeserializeObject<FR24Aircrafts>(json, new FR24AircraftConverter());
|
|
foreach (FR24AircraftDesignator fr24ad in fr24aircrafts.rows.Values)
|
|
{
|
|
try
|
|
{
|
|
AircraftDesignator ad = new AircraftDesignator();
|
|
ad.Hex = fr24ad.hex;
|
|
ad.Call = fr24ad.call;
|
|
ad.Reg = fr24ad.reg;
|
|
ad.TypeCode = fr24ad.typecode;
|
|
ad.LastUpdated = DateTime.UtcNow;
|
|
if (PlaneInfoChecker.Check_Hex(ad.Hex) && PlaneInfoChecker.Check_Call(ad.Call) && PlaneInfoChecker.Check_Reg(ad.Reg) && PlaneInfoChecker.Check_Type(ad.TypeCode))
|
|
aircrafts.Add(ad);
|
|
else
|
|
{
|
|
// Console.WriteLine("Invalid aircraft data: " + fr24ad.hex + "," + fr24ad.call + "," + fr24ad.reg + "," + fr24ad.typecode);
|
|
errors++;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
bw_AircraftUpdater.ReportProgress(-1, ex.Message);
|
|
}
|
|
}
|
|
Thread.Sleep(1000);
|
|
}
|
|
bw_AircraftUpdater.ReportProgress(0, "Updating aircrafts...");
|
|
// update aircraft data
|
|
AircraftData.Database.AircraftBulkInsertOrUpdateIfNewer(aircrafts);
|
|
bw_AircraftUpdater.ReportProgress(0, "Aircafts updated from " + Properties.Settings.Default.Aircrafts_BaseURL + ": " + aircrafts.Count.ToString() + " updated, " + errors.ToString() + " error(s).");
|
|
int timeout = 0;
|
|
while (!bw_AircraftUpdater.CancellationPending && (timeout < 600))
|
|
{
|
|
Thread.Sleep(1000);
|
|
timeout++;
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
bw_AircraftUpdater.ReportProgress(-1, ex.Message);
|
|
}
|
|
}
|
|
}
|
|
|
|
private void bw_AircraftUpdater_ProgressChanged(object sender, ProgressChangedEventArgs e)
|
|
{
|
|
if (e.ProgressPercentage < 0)
|
|
Say((string)(e.UserState));
|
|
else if (e.ProgressPercentage == 0)
|
|
Say((string)(e.UserState));
|
|
ReportAircraftsStats();
|
|
}
|
|
|
|
private void bw_AircraftUpdater_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
|
|
{
|
|
btn_Update_Aicrafts_Start.Enabled = true;
|
|
btn_Update_Aircrafts_Stop.Enabled = false;
|
|
}
|
|
|
|
private void ReportAircraftsStats()
|
|
{
|
|
lbl_Aircrafts_Total.Text = "total: " + AircraftData.Database.AircraftCount().ToString();
|
|
lbl_Aircrafts_UnkownHex.Text = "unknown hex: " + AircraftData.Database.AircraftCountUnknownHex().ToString();
|
|
lbl_Aircrafts_UnkownCall.Text = "unknown call: " + AircraftData.Database.AircraftCountUnknownCall().ToString();
|
|
lbl_Aircrafts_UnkownType.Text = "unknown type: " + AircraftData.Database.AircraftCountUnknownType().ToString();
|
|
}
|
|
|
|
private void btn_Update_Aicrafts_Start_Click(object sender, EventArgs e)
|
|
{
|
|
bw_AircraftUpdater.RunWorkerAsync();
|
|
while (!bw_AircraftUpdater.IsBusy)
|
|
Application.DoEvents();
|
|
btn_Update_Aicrafts_Start.Enabled = false;
|
|
btn_Update_Aircrafts_Stop.Enabled = true;
|
|
}
|
|
|
|
private void btn_Update_Aircrafts_Stop_Click(object sender, EventArgs e)
|
|
{
|
|
bw_AircraftUpdater.CancelAsync();
|
|
}
|
|
|
|
private void tp_Aircrafts_Enter(object sender, EventArgs e)
|
|
{
|
|
if (bw_AircraftUpdater.IsBusy)
|
|
{
|
|
btn_Update_Aicrafts_Start.Enabled = false;
|
|
btn_Update_Aircrafts_Stop.Enabled = true;
|
|
}
|
|
else
|
|
{
|
|
btn_Update_Aicrafts_Start.Enabled = true;
|
|
btn_Update_Aircrafts_Stop.Enabled = false;
|
|
}
|
|
|
|
ReportAircraftsStats();
|
|
}
|
|
|
|
private void btn_StationDatabase_Export_Click(object sender, EventArgs e)
|
|
{
|
|
// export and upload station database
|
|
if (!SupportFunctions.ValidateDirectoryPath(Properties.Settings.Default.StationDatabase_Export_LocalDir))
|
|
{
|
|
MessageBox.Show("Local Path is not valid: " + Properties.Settings.Default.StationDatabase_Export_LocalDir, " Export Station Database");
|
|
return;
|
|
}
|
|
Say("Getting locations...");
|
|
string locations = StationData.Database.LocationToJSON();
|
|
string locationsfile = Path.Combine(Properties.Settings.Default.StationDatabase_Export_LocalDir, "locations.json");
|
|
string locationszipfile = Path.Combine(Properties.Settings.Default.StationDatabase_Export_LocalDir, "locations.zip");
|
|
SupportFunctions.WriteStringToFile(locations, locationsfile);
|
|
Say("Creating zip file...");
|
|
ZIP.CompressFile(locationsfile, false, 60);
|
|
string qrvs = StationData.Database.QRVToJSON();
|
|
Say("Getting qrv information...");
|
|
string qrvfile = Path.Combine(Properties.Settings.Default.StationDatabase_Export_LocalDir, "qrv.json");
|
|
string qrvzipfile = Path.Combine(Properties.Settings.Default.StationDatabase_Export_LocalDir, "qrv.zip");
|
|
SupportFunctions.WriteStringToFile(qrvs, qrvfile);
|
|
Say("Creating zip file...");
|
|
ZIP.CompressFile(qrvfile, false, 60);
|
|
Say("Upload files...");
|
|
SftpClient client = new SftpClient(Properties.Settings.Default.StationDatabase_Export_RemoteHost, Properties.Settings.Default.StationDatabase_Export_User, Properties.Settings.Default.StationDatabase_Export_Password);
|
|
try
|
|
{
|
|
client.Connect();
|
|
using (FileStream file = new FileStream(locationszipfile, FileMode.Open))
|
|
{
|
|
string uploadfile = Properties.Settings.Default.StationDatabase_Export_RemoteDir + "/" + "locations.zip";
|
|
client.BufferSize = 4 * 1024;
|
|
client.UploadFile(file, uploadfile, true);
|
|
}
|
|
using (FileStream file = new FileStream(qrvzipfile, FileMode.Open))
|
|
{
|
|
string uploadfile = Properties.Settings.Default.StationDatabase_Export_RemoteDir + "/" + "qrv.zip";
|
|
client.BufferSize = 4 * 1024;
|
|
client.UploadFile(file, uploadfile, true);
|
|
}
|
|
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.Message);
|
|
}
|
|
Say("Station database exported and uploaded.");
|
|
}
|
|
|
|
private void btn_AircraftDatabase_Export_Click(object sender, EventArgs e)
|
|
{
|
|
// export and upload aircraftdatabase
|
|
if (!SupportFunctions.ValidateDirectoryPath(Properties.Settings.Default.AircraftDatabase_Export_LocalDir))
|
|
{
|
|
MessageBox.Show("Local Path is not valid: " + Properties.Settings.Default.AircraftDatabase_Export_LocalDir, " Export Aircraft Database");
|
|
return;
|
|
}
|
|
Say("Getting aircraft registrations...");
|
|
string ars = AircraftData.Database.AircraftRegistrationToJSON();
|
|
string arsfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "AircraftRegistrations.json");
|
|
string arszipfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "AircraftRegistrations.zip");
|
|
SupportFunctions.WriteStringToFile(ars, arsfile);
|
|
Say("Creating zip file...");
|
|
ZIP.CompressFile(arsfile, false, 60);
|
|
Say("Getting aircrafts...");
|
|
string acs = AircraftData.Database.AircraftToJSON();
|
|
string acsfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "Aircrafts.json");
|
|
string acszipfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "Aircrafts.zip");
|
|
SupportFunctions.WriteStringToFile(acs, acsfile);
|
|
Say("Creating zip file...");
|
|
ZIP.CompressFile(acsfile, false, 60);
|
|
Say("Getting aircraft typess...");
|
|
string ats = AircraftData.Database.AircraftTypeToJSON();
|
|
string atsfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "AircraftTypes.json");
|
|
string atszipfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "AircraftTypes.zip");
|
|
SupportFunctions.WriteStringToFile(ats, atsfile);
|
|
Say("Creating zip file...");
|
|
ZIP.CompressFile(atsfile, false, 60);
|
|
Say("Getting airlines...");
|
|
string als = AircraftData.Database.AirlineToJSON();
|
|
string alsfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "Airlines.json");
|
|
string alszipfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "Airlines.zip");
|
|
SupportFunctions.WriteStringToFile(als, alsfile);
|
|
Say("Creating zip file...");
|
|
ZIP.CompressFile(alsfile, false, 60);
|
|
Say("Getting airports...");
|
|
string aps = AircraftData.Database.AirportToJSON();
|
|
string apsfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "Airports.json");
|
|
string apszipfile = Path.Combine(Properties.Settings.Default.AircraftDatabase_Export_LocalDir, "Airports.zip");
|
|
SupportFunctions.WriteStringToFile(aps, apsfile);
|
|
Say("Creating zip file...");
|
|
ZIP.CompressFile(apsfile, false, 60);
|
|
Say("Upload files...");
|
|
SftpClient client = new SftpClient(Properties.Settings.Default.AircraftDatabase_Export_RemoteHost, Properties.Settings.Default.AircraftDatabase_Export_User, Properties.Settings.Default.AircraftDatabase_Export_Password);
|
|
try
|
|
{
|
|
client.Connect();
|
|
using (FileStream file = new FileStream(arszipfile, FileMode.Open))
|
|
{
|
|
string uploadfile = Properties.Settings.Default.AircraftDatabase_Export_RemoteDir + "/" + "AircraftRegistrations.zip";
|
|
client.BufferSize = 4 * 1024;
|
|
client.UploadFile(file, uploadfile, true);
|
|
}
|
|
using (FileStream file = new FileStream(acszipfile, FileMode.Open))
|
|
{
|
|
string uploadfile = Properties.Settings.Default.AircraftDatabase_Export_RemoteDir + "/" + "Aircrafts.zip";
|
|
client.BufferSize = 4 * 1024;
|
|
client.UploadFile(file, uploadfile, true);
|
|
}
|
|
using (FileStream file = new FileStream(atszipfile, FileMode.Open))
|
|
{
|
|
string uploadfile = Properties.Settings.Default.AircraftDatabase_Export_RemoteDir + "/" + "AircraftTypes.zip";
|
|
client.BufferSize = 4 * 1024;
|
|
client.UploadFile(file, uploadfile, true);
|
|
}
|
|
using (FileStream file = new FileStream(alszipfile, FileMode.Open))
|
|
{
|
|
string uploadfile = Properties.Settings.Default.AircraftDatabase_Export_RemoteDir + "/" + "Airlines.zip";
|
|
client.BufferSize = 4 * 1024;
|
|
client.UploadFile(file, uploadfile, true);
|
|
}
|
|
using (FileStream file = new FileStream(apszipfile, FileMode.Open))
|
|
{
|
|
string uploadfile = Properties.Settings.Default.AircraftDatabase_Export_RemoteDir + "/" + "Airports.zip";
|
|
client.BufferSize = 4 * 1024;
|
|
client.UploadFile(file, uploadfile, true);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
Console.WriteLine(ex.Message);
|
|
}
|
|
Say("Aircraft database exported and uploaded.");
|
|
}
|
|
|
|
private void dgv_Locations_SelectionChanged(object sender, EventArgs e)
|
|
{
|
|
DataGridViewSelectedRowCollection rows = dgv_Locations.SelectedRows;
|
|
if (!IsMarkerDragging && (rows.Count > 0))
|
|
{
|
|
try
|
|
{
|
|
// clear locations
|
|
Locationsoverlay.Clear();
|
|
double minlat = double.MaxValue;
|
|
double maxlat = double.MinValue;
|
|
double minlon = double.MaxValue;
|
|
double maxlon = double.MinValue;
|
|
foreach (DataGridViewRow row in rows)
|
|
{
|
|
// get info
|
|
string call = row.Cells["Call"].Value.ToString();
|
|
double lat = (double)row.Cells["Lat"].Value;
|
|
double lon = (double)row.Cells["Lon"].Value;
|
|
GEOSOURCE source = (GEOSOURCE)row.Cells["Source"].Value;
|
|
// add location
|
|
GMarkerGoogle gm = new GMarkerGoogle(new PointLatLng(lat, lon), (source == GEOSOURCE.FROMUSER) ? GMarkerGoogleType.green_small : GMarkerGoogleType.white_small);
|
|
gm.ToolTipText = call;
|
|
gm.ToolTipMode = MarkerTooltipMode.OnMouseOver;
|
|
gm.Tag = call;
|
|
Locationsoverlay.Markers.Add(gm);
|
|
if (minlat > lat)
|
|
minlat = lat;
|
|
if (maxlat < lat)
|
|
maxlat = lat;
|
|
if (minlon > lon)
|
|
minlon = lon;
|
|
if (maxlon < lon)
|
|
maxlon = lon;
|
|
}
|
|
// ensure that all location are visible
|
|
if (rows.Count > 1)
|
|
{
|
|
gm_Locations.SetZoomToFitRect(RectLatLng.FromLTRB(minlon, maxlat, maxlon, minlat));
|
|
}
|
|
else
|
|
{
|
|
// set standard zoom if only 1 location
|
|
gm_Locations.Zoom = 15;
|
|
gm_Locations.Position = new PointLatLng(minlat,minlon);
|
|
}
|
|
}
|
|
catch (Exception ex)
|
|
{
|
|
// cannot set position -- > do nothing
|
|
}
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
public class FR24Airlines
|
|
{
|
|
public int version;
|
|
public FR24AirlineDesignator[] rows;
|
|
|
|
public FR24Airlines()
|
|
{
|
|
version = 0;
|
|
rows = null;
|
|
}
|
|
}
|
|
|
|
public class FR24AirlineDesignator
|
|
{
|
|
public string Name;
|
|
public string Code;
|
|
public string ICAO;
|
|
|
|
public FR24AirlineDesignator()
|
|
{
|
|
Name = "";
|
|
Code = "";
|
|
ICAO = "";
|
|
}
|
|
}
|
|
|
|
public class FR24Airports
|
|
{
|
|
public int version;
|
|
public FR24AirportDesignator[] rows;
|
|
|
|
public FR24Airports()
|
|
{
|
|
version = 0;
|
|
rows = null;
|
|
}
|
|
}
|
|
|
|
public class FR24AirportDesignator
|
|
{
|
|
public string name;
|
|
public string iata;
|
|
public string icao;
|
|
public string city;
|
|
public double lat;
|
|
public double lon;
|
|
public string country;
|
|
public double alt;
|
|
public double size;
|
|
|
|
public FR24AirportDesignator()
|
|
{
|
|
name = "";
|
|
iata = "";
|
|
icao = "";
|
|
city = "";
|
|
lat = 0;
|
|
lon = 0;
|
|
country = "";
|
|
alt = 0;
|
|
size = 0;
|
|
}
|
|
}
|
|
|
|
public class FR24Aircrafts
|
|
{
|
|
public Dictionary<string, FR24AircraftDesignator> rows;
|
|
public FR24Aircrafts()
|
|
{
|
|
rows = null;
|
|
}
|
|
}
|
|
|
|
public class FR24AircraftDesignator
|
|
{
|
|
public string hex;
|
|
public double lat;
|
|
public double lon;
|
|
public int track;
|
|
public int alt;
|
|
public int speed;
|
|
public string squawk;
|
|
public string radar;
|
|
public string typecode;
|
|
public string reg;
|
|
public long time;
|
|
public string src;
|
|
public string dst;
|
|
public string call;
|
|
public int dummy1;
|
|
public int dummy2;
|
|
public string flight;
|
|
public int dummy3;
|
|
public string airline;
|
|
|
|
public FR24AircraftDesignator()
|
|
{
|
|
hex = "";
|
|
lat = 0;
|
|
lon = 0;
|
|
track = 0;
|
|
alt = 0;
|
|
speed = 0;
|
|
squawk = "";
|
|
radar = "";
|
|
typecode = "";
|
|
reg = "";
|
|
time = 0;
|
|
src = "";
|
|
dst = "";
|
|
call = "";
|
|
dummy1 = 0;
|
|
dummy2 = 0;
|
|
flight = "";
|
|
dummy3 = 0;
|
|
airline = "";
|
|
}
|
|
}
|
|
|
|
class FR24AircraftConverter : JsonConverter
|
|
{
|
|
public override bool CanConvert(Type objectType)
|
|
{
|
|
return (objectType == typeof(FR24AircraftDesignator));
|
|
}
|
|
|
|
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
|
|
{
|
|
JArray array = JArray.Load(reader);
|
|
return new FR24AircraftDesignator
|
|
{
|
|
hex = (string)array[0],
|
|
lat = (double)array[1],
|
|
lon = (double)array[2],
|
|
track = (int)array[3],
|
|
alt = (int)array[4],
|
|
speed = (int)array[5],
|
|
squawk = (string)array[6],
|
|
radar = (string)array[7],
|
|
typecode = (string)array[8],
|
|
reg = (string)array[9],
|
|
time = (long)array[10],
|
|
src = (string)array[11],
|
|
dst = (string)array[12],
|
|
flight = (string)array[13],
|
|
dummy1 = (int)array[14],
|
|
dummy2 = (int)array[15],
|
|
call = (string)array[16],
|
|
dummy3 = (int)array[17],
|
|
airline = (string)array[18]
|
|
};
|
|
}
|
|
|
|
public override bool CanWrite
|
|
{
|
|
get { return false; }
|
|
}
|
|
|
|
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
|
|
{
|
|
throw new NotImplementedException();
|
|
}
|
|
}
|
|
public enum DATABASEUPDATERSTARTOPTIONS
|
|
{
|
|
NONE = 0,
|
|
FIRSTRUN = 1,
|
|
RUNONCE = 2,
|
|
RUNPERIODICALLY = 3
|
|
}
|
|
|
|
public enum LOCATIONSTATE
|
|
{
|
|
UNKNOWN = -2,
|
|
ERROR = -1,
|
|
INFO = 0,
|
|
UPTODATE = 1,
|
|
UPDATED = 2,
|
|
LOCDIFF = 3,
|
|
ADDED = 4
|
|
}
|
|
}
|