AirScout/AirScout/Webserver.cs

942 wiersze
40 KiB
C#

// 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 System.Diagnostics;
using AquaControls;
using AirScout.Core;
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 MimeTypes;
namespace AirScout
{
public partial class MapDlg
{
#region Webserver
private void bw_Webserver_DoWork(object sender, DoWorkEventArgs e)
{
// name the thread for debugging
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = this.GetType().Name;
string tmpdir = Application.StartupPath;
// get temp directory from arguments
if (e != null)
{
tmpdir = ((WebserverStartArgs)e.Argument).TmpDirectory;
}
string webserverdir = Path.Combine(Application.StartupPath, "wwwroot");
// get webserver directory from arguments
if (e != null)
{
webserverdir = ((WebserverStartArgs)e.Argument).WebserverDirectory;
}
Log.WriteMessage("started.");
// run simple web server
string hosturl = "http://+:" + Properties.Settings.Default.Webserver_Port.ToString() + "/";
string userName = System.Security.Principal.WindowsIdentity.GetCurrent().Name;
HttpListener listener = null;
while (!bw_Webserver.CancellationPending)
{
string[] prefixes = new string[1];
prefixes[0] = hosturl;
int id = 0;
try
{
if (!HttpListener.IsSupported)
{
Console.WriteLine("Windows XP SP2 or Server 2003 is required to use the HttpListener class.");
return;
}
// URI prefixes are required,
if (prefixes == null || prefixes.Length == 0)
throw new ArgumentException("prefixes");
// Create a listener.
listener = new HttpListener();
// Add the prefixes.
foreach (string s in prefixes)
{
listener.Prefixes.Add(s);
}
listener.Start();
Console.WriteLine("Listening...");
while (!bw_Webserver.CancellationPending)
{
// Note: The GetContext method blocks while waiting for a request.
HttpListenerContext context = listener.GetContext();
List<PlaneInfo> allplanes = Planes.GetAll(DateTime.UtcNow, Properties.Settings.Default.Planes_Position_TTL);
id++;
// send response from a background thread
WebServerDelivererArgs args = new WebServerDelivererArgs();
args.ID = id;
args.TmpDirectory = tmpdir;
args.WebserverDirectory = webserverdir;
args.Context = context;
args.AllPlanes = allplanes;
WebserverDeliver bw = new WebserverDeliver();
bw.RunWorkerAsync(args);
}
}
catch (HttpListenerException ex)
{
if (ex.ErrorCode == 5)
{
// gain additional access rights for that specific host url
// user will be prompted for allow changes
// DO NOT USE THE "listener=yes" option as recommended!!!
string args = "http add urlacl " + hosturl + " user=" + userName;
ProcessStartInfo psi = new ProcessStartInfo("netsh", args);
psi.Verb = "runas";
psi.CreateNoWindow = true;
psi.WindowStyle = ProcessWindowStyle.Hidden;
psi.UseShellExecute = true;
Process.Start(psi).WaitForExit();
}
// do almost nothing
// wait 10 seconds and restart the listener
Thread.Sleep(10000);
}
catch (Exception ex)
{
// do almost nothing
// wait 10 seconds and restart the listener
Thread.Sleep(10000);
}
finally
{
}
}
if (listener != null)
{
lock (listener)
{
listener.Stop();
}
}
Log.WriteMessage("Finished.");
}
private void bw_Webserver_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
}
#endregion
}
public class WebserverDeliver : BackgroundWorker
{
string TmpDirectory = Application.StartupPath;
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 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 List<LocationDesignator> LocationFindAll(string call)
{
// check all parameters
if (!Callsign.Check(call))
return null;
// get location info
List<LocationDesignator> l = StationData.Database.LocationFindAll(call);
// return null if not found
if (l == null)
return null;
foreach (LocationDesignator ld in l)
{
// 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 l;
}
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;
}
private string DeliverPlanes(string tmpdir)
{
string json = "";
var fs = File.OpenRead(tmpdir + Path.DirectorySeparatorChar + "planes.json");
using (StreamReader sr = new StreamReader(fs))
{
json = sr.ReadToEnd();
}
return json;
}
private string DeliverVersion(string paramstr)
{
string version = Application.ProductVersion;
string json = "";
// convert path to json
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.FloatFormatHandling = FloatFormatHandling.String;
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
json = JsonConvert.SerializeObject(version, settings);
return json;
}
private string DeliverSettings(string paramstr)
{
//save settings
Properties.Settings.Default.Save();
string json = "";
// convert path to json
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.FloatFormatHandling = FloatFormatHandling.String;
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
json = JsonConvert.SerializeObject(Properties.Settings.Default, settings);
return json;
}
private string DeliverBands(string paramstr)
{
string json = "";
string[] bands = Bands.GetStringValuesExceptNoneAndAll();
json = JsonConvert.SerializeObject(bands);
return json;
}
private string DeliverLocation(string paramstr)
{
string json = "";
// set default values
string callstr = "";
string locstr = "";
// get parameters
try
{
if (paramstr.Contains("?"))
{
// OK, we have parameters --> cut them out and make all uppercase
paramstr = paramstr.Substring(paramstr.IndexOf("?") + 1).ToUpper();
var pars = System.Web.HttpUtility.ParseQueryString(paramstr);
callstr = pars.Get("CALL");
locstr = pars.Get("LOC");
}
}
catch (Exception ex)
{
// return error
return "Error while parsing parameters!";
}
// check parameters
if (!Callsign.Check(callstr))
return "Error: " + callstr + " is not a valid callsign!";
LocationDesignator ld = null;
// locstr == null or empty --> return last recent location
if (String.IsNullOrEmpty(locstr))
{
ld = LocationFind(callstr);
if (ld == null)
return "Error: Location not found in database!";
json = ld.ToJSON();
return json;
}
if(locstr == "ALL")
{
List<LocationDesignator> l = LocationFindAll(callstr);
if (l == null)
return "Error: Location not found in database!";
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.FloatFormatHandling = FloatFormatHandling.String;
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
settings.Culture = CultureInfo.InvariantCulture;
json = JsonConvert.SerializeObject(l, settings);
return json;
}
if (!MaidenheadLocator.Check(locstr))
return "Error: " + locstr + " is not a valid Maidenhead locator!";
// search call in station database, return empty string if not found
ld = LocationFind(callstr, locstr);
if (ld == null)
return "Error: Location not found in database!";
json = ld.ToJSON();
return json;
}
private string DeliverQRV(string paramstr)
{
string json = "";
// set default values
string callstr = "";
string locstr = "";
string bandstr = "";
BAND band = Properties.Settings.Default.Band;
// get parameters
try
{
if (paramstr.Contains("?"))
{
// OK, we have parameters --> cut them out and make all uppercase
paramstr = paramstr.Substring(paramstr.IndexOf("?") + 1).ToUpper();
var pars = System.Web.HttpUtility.ParseQueryString(paramstr);
callstr = pars.Get("CALL");
locstr = pars.Get("LOC");
bandstr = pars.Get("BAND");
}
}
catch (Exception ex)
{
// return error
return "Error while parsing parameters!";
}
// check parameters
if (!Callsign.Check(callstr))
return "Error: " + callstr + " is not a valid callsign!";
if (!MaidenheadLocator.Check(locstr))
return "Error: " + locstr + " is not a valid Maidenhead locator!";
// set band to currently selected if empty
if (string.IsNullOrEmpty(bandstr))
band = Properties.Settings.Default.Band;
else
band = Bands.ParseStringValue(bandstr);
if (band == BAND.BNONE)
return "Error: " + bandstr + " is not a valid band value!";
// search call in station database, return empty string if not found
if (band != BAND.BALL)
{
QRVDesignator qrv = StationData.Database.QRVFind(callstr, locstr, band);
if (qrv == null)
return "Error: QRV info not found in database!";
json = qrv.ToJSON();
return json;
}
List<QRVDesignator> qrvs = StationData.Database.QRVFind(callstr, locstr);
if ((qrvs == null) || (qrvs.Count() == 0))
return "Error: QRV info not found in database!";
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.FloatFormatHandling = FloatFormatHandling.String;
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
json = JsonConvert.SerializeObject(qrvs, settings);
return json;
}
private string DeliverElevationPath(string paramstr)
{
string json = "";
// set default values
string mycallstr = "";
string mylocstr = "";
string dxcallstr = "";
string dxlocstr = "";
BAND band = Properties.Settings.Default.Band;
// get parameters
try
{
if (paramstr.Contains("?"))
{
// OK, we have parameters --> cut them out and make all uppercase
paramstr = paramstr.Substring(paramstr.IndexOf("?") + 1).ToUpper();
var pars = System.Web.HttpUtility.ParseQueryString(paramstr);
mycallstr = pars.Get("MYCALL");
mylocstr = pars.Get("MYLOC");
dxcallstr = pars.Get("DXCALL");
dxlocstr = pars.Get("DXLOC");
}
}
catch (Exception ex)
{
// return error
return "Error while parsing parameters!";
}
// check parameters
if (!Callsign.Check(mycallstr))
return "Error: " + mycallstr + " is not a valid callsign!";
if (!Callsign.Check(dxcallstr))
return "Error: " + dxcallstr + " is not a valid callsign!";
if (!String.IsNullOrEmpty(mylocstr) && !MaidenheadLocator.Check(mylocstr))
return "Error: " + mylocstr + " is not a valid Maidenhead locator!";
if (!String.IsNullOrEmpty(dxlocstr) && !MaidenheadLocator.Check(dxlocstr))
return "Error: " + dxlocstr + " is not a valid Maidenhead locator!";
// search call in station database, return empty string if not found
LocationDesignator myloc = LocationFind(mycallstr, mylocstr);
if (myloc == null)
return "Error: MyLocation not found in database!";
LocationDesignator dxloc = LocationFind(dxcallstr, dxlocstr);
if (dxloc == null)
return "Error: DXLocation not found in database!";
// get qrv info or create default
QRVDesignator myqrv = StationData.Database.QRVFindOrCreateDefault(myloc.Call, myloc.Loc, band);
// set qrv defaults if zero
if (myqrv.AntennaHeight == 0)
myqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(band);
if (myqrv.AntennaGain == 0)
myqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(band);
if (myqrv.Power == 0)
myqrv.Power = StationData.Database.QRVGetDefaultPower(band);
// get qrv info or create default
QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxloc.Call, dxloc.Loc, band);
// set qrv defaults if zero
if (dxqrv.AntennaHeight == 0)
dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(band);
if (dxqrv.AntennaGain == 0)
dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(band);
if (dxqrv.Power == 0)
dxqrv.Power = StationData.Database.QRVGetDefaultPower(band);
// get or calculate elevation path
ElevationPathDesignator epath = ElevationData.Database.ElevationPathFindOrCreateFromLatLon(
this,
myloc.Lat,
myloc.Lon,
dxloc.Lat,
dxloc.Lon,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel);
if (epath == null)
return json;
// add additional info to ppath
epath.Location1 = myloc;
epath.Location2 = dxloc;
epath.QRV1 = myqrv;
epath.QRV2 = dxqrv;
// convert path to json
json = epath.ToJSON();
return json;
}
private string DeliverPropagationPath(string paramstr)
{
string json = "";
// set default values
string mycallstr = "";
string mylocstr = "";
string dxcallstr = "";
string dxlocstr = "";
string bandstr = "";
BAND band = Properties.Settings.Default.Band;
// get parameters
try
{
if (paramstr.Contains("?"))
{
// OK, we have parameters --> cut them out and make all uppercase
paramstr = paramstr.Substring(paramstr.IndexOf("?") + 1).ToUpper();
var pars = System.Web.HttpUtility.ParseQueryString(paramstr);
mycallstr = pars.Get("MYCALL");
mylocstr = pars.Get("MYLOC");
dxcallstr = pars.Get("DXCALL");
dxlocstr = pars.Get("DXLOC");
bandstr = pars.Get("BAND");
}
}
catch (Exception ex)
{
// return error
return "Error while parsing parameters!";
}
// check parameters
if (!Callsign.Check(mycallstr))
return "Error: " + mycallstr + " is not a valid callsign!";
if (!Callsign.Check(dxcallstr))
return "Error: " + dxcallstr + " is not a valid callsign!";
if (!String.IsNullOrEmpty(mylocstr) && !MaidenheadLocator.Check(mylocstr))
return "Error: " + mylocstr + " is not a valid Maidenhead locator!";
if (!String.IsNullOrEmpty(dxlocstr) && !MaidenheadLocator.Check(dxlocstr))
return "Error: " + dxlocstr + " is not a valid Maidenhead locator!";
// set band to currently selected if empty
if (string.IsNullOrEmpty(bandstr))
band = Properties.Settings.Default.Band;
else
band = Bands.ParseStringValue(bandstr);
if (band == BAND.BNONE)
return "Error: " + bandstr + " is not a valid band value!";
// search call in station database, return empty string if not found
LocationDesignator myloc = LocationFind(mycallstr, mylocstr);
if (myloc == null)
return "Error: MyLocation not found in database!";
LocationDesignator dxloc = LocationFind(dxcallstr, dxlocstr);
if (dxloc == null)
return "Error: DXLocation not found in database!";
// get qrv info or create default
QRVDesignator myqrv = StationData.Database.QRVFindOrCreateDefault(myloc.Call, myloc.Loc, band);
// set qrv defaults if zero
if (myqrv.AntennaHeight == 0)
myqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(band);
if (myqrv.AntennaGain == 0)
myqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(band);
if (myqrv.Power == 0)
myqrv.Power = StationData.Database.QRVGetDefaultPower(band);
// get qrv info or create default
QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxloc.Call, dxloc.Loc, band);
// set qrv defaults if zero
if (dxqrv.AntennaHeight == 0)
dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(band);
if (dxqrv.AntennaGain == 0)
dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(band);
if (dxqrv.Power == 0)
dxqrv.Power = StationData.Database.QRVGetDefaultPower(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;
// get or calculate propagation path
PropagationPathDesignator ppath = PropagationData.Database.PropagationPathFindOrCreateFromLatLon(
this,
myloc.Lat,
myloc.Lon,
GetElevation(myloc.Lat, myloc.Lon) + myqrv.AntennaHeight,
dxloc.Lat,
dxloc.Lon,
GetElevation(dxloc.Lat, dxloc.Lon) + dxqrv.AntennaHeight,
Bands.ToGHz(band),
LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[band].K_Factor,
Properties.Settings.Default.Path_Band_Settings[band].F1_Clearance,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel,
myobstr);
if (ppath == null)
return json;
// add additional info to ppath
ppath.Location1 = myloc;
ppath.Location2 = dxloc;
ppath.QRV1 = myqrv;
ppath.QRV2 = dxqrv;
// convert path to json
json = ppath.ToJSON();
return json;
}
private string DeliverNearestPlanes(string paramstr, List<PlaneInfo> allplanes)
{
string json = "";
// set default values
string mycallstr = "";
string mylocstr = "";
string dxcallstr = "";
string dxlocstr = "";
string bandstr = "";
BAND band = Properties.Settings.Default.Band;
// get parameters
try
{
if (paramstr.Contains("?"))
{
// OK, we have parameters --> cut them out and make all uppercase
paramstr = paramstr.Substring(paramstr.IndexOf("?") + 1).ToUpper();
var pars = System.Web.HttpUtility.ParseQueryString(paramstr);
mycallstr = pars.Get("MYCALL");
mylocstr = pars.Get("MYLOC");
dxcallstr = pars.Get("DXCALL");
dxlocstr = pars.Get("DXLOC");
bandstr = pars.Get("BAND");
}
}
catch (Exception ex)
{
// return error
return "Error while parsing parameters!";
}
// check parameters
if (!Callsign.Check(mycallstr))
return "Error: " + mycallstr + " is not a valid callsign!";
if (!Callsign.Check(dxcallstr))
return "Error: " + dxcallstr + " is not a valid callsign!";
if (!String.IsNullOrEmpty(mylocstr) && !MaidenheadLocator.Check(mylocstr))
return "Error: " + mylocstr + " is not a valid Maidenhead locator!";
if (!String.IsNullOrEmpty(dxlocstr) && !MaidenheadLocator.Check(dxlocstr))
return "Error: " + dxlocstr + " is not a valid Maidenhead locator!";
// set band to currently selected if empty
if (string.IsNullOrEmpty(bandstr))
band = Properties.Settings.Default.Band;
else
band = Bands.ParseStringValue(bandstr);
if (band == BAND.BNONE)
return "Error: " + bandstr + " is not a valid band value!";
// search call in station database, return empty string if not found
LocationDesignator myloc = LocationFind(mycallstr, mylocstr);
if (myloc == null)
return "Error: MyLocation not found in database!";
LocationDesignator dxloc = LocationFind(dxcallstr, dxlocstr);
if (dxloc == null)
return "Error: DXLocation not found in database!";
// get qrv info or create default
QRVDesignator myqrv = StationData.Database.QRVFindOrCreateDefault(myloc.Call, myloc.Loc, band);
// set qrv defaults if zero
if (myqrv.AntennaHeight == 0)
myqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(band);
if (myqrv.AntennaGain == 0)
myqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(band);
if (myqrv.Power == 0)
myqrv.Power = StationData.Database.QRVGetDefaultPower(band);
// get qrv info or create default
QRVDesignator dxqrv = StationData.Database.QRVFindOrCreateDefault(dxloc.Call, dxloc.Loc, band);
// set qrv defaults if zero
if (dxqrv.AntennaHeight == 0)
dxqrv.AntennaHeight = StationData.Database.QRVGetDefaultAntennaHeight(band);
if (dxqrv.AntennaGain == 0)
dxqrv.AntennaGain = StationData.Database.QRVGetDefaultAntennaGain(band);
if (dxqrv.Power == 0)
dxqrv.Power = StationData.Database.QRVGetDefaultPower(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;
// get or calculate propagation path
PropagationPathDesignator ppath = PropagationData.Database.PropagationPathFindOrCreateFromLatLon(
this,
myloc.Lat,
myloc.Lon,
GetElevation(myloc.Lat, myloc.Lon) + myqrv.AntennaHeight,
dxloc.Lat,
dxloc.Lon,
GetElevation(dxloc.Lat, dxloc.Lon) + dxqrv.AntennaHeight,
Bands.ToGHz(band),
LatLon.Earth.Radius * Properties.Settings.Default.Path_Band_Settings[band].K_Factor,
Properties.Settings.Default.Path_Band_Settings[band].F1_Clearance,
ElevationData.Database.GetDefaultStepWidth(Properties.Settings.Default.ElevationModel),
Properties.Settings.Default.ElevationModel,
myobstr);
if (ppath == null)
return json;
// add additional info to ppath
ppath.Location1 = myloc;
ppath.Location2 = dxloc;
ppath.QRV1 = myqrv;
ppath.QRV2 = dxqrv;
/*
// estimate positions according to time
DateTime time = DateTime.UtcNow;
foreach(PlaneInfo plane in allplanes.Planes)
{
// change speed to km/h
double speed = plane.Speed_kmh;
// calculate distance after timespan
double dist = speed * (time - allplanes.At).TotalHours;
LatLon.GPoint newpos = LatLon.DestinationPoint(plane.Lat, plane.Lon, plane.Track, dist);
plane.Lat = newpos.Lat;
plane.Lon = newpos.Lon;
plane.Time = time;
}
*/
// get nearest planes
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);
// convert nearestplanes to json
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.DateTimeZoneHandling = DateTimeZoneHandling.Utc;
settings.FloatFormatHandling = FloatFormatHandling.String;
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
json = JsonConvert.SerializeObject(nearestplanes, settings);
return json;
}
protected override void OnDoWork(DoWorkEventArgs e)
{
WebServerDelivererArgs args = (WebServerDelivererArgs)e.Argument;
if (String.IsNullOrEmpty(Thread.CurrentThread.Name))
Thread.CurrentThread.Name = this.GetType().Name + "_" + args.ID;
byte[] buffer = new byte[0];
string mime = "text/html";
HttpStatusCode status = HttpStatusCode.OK;
HttpListenerRequest request = args.Context.Request;
// Obtain a response object.
HttpListenerResponse response = args.Context.Response;
// get unescaped raw url from request
string rawurl = Uri.UnescapeDataString(request.RawUrl);
// redirect parameterless calls to index.html
if (!rawurl.Contains("/") || (rawurl == "/"))
{
rawurl = "/index.html";
}
// try to create local file name
string filename = "";
if (SupportFunctions.IsMono)
{
filename = rawurl.Substring(1);
}
else
{
filename = rawurl.Substring(1).Replace("/", "\\");
}
// cut parameters
if (filename.Contains("?"))
filename = filename.Substring(0, filename.IndexOf("?"));
// try to find local file and deliver it
filename = Path.Combine(args.WebserverDirectory, filename);
if (File.Exists(filename))
{
buffer = File.ReadAllBytes(filename);
mime = MimeTypeMap.GetMimeType(Path.GetExtension(filename));
}
// check for content delivery request
else if (request.RawUrl.ToLower() == "/planes.json")
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverPlanes(args.TmpDirectory));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/version.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverVersion(request.RawUrl));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/settings.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverSettings(request.RawUrl));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/bands.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverBands(request.RawUrl));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/location.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverLocation(request.RawUrl));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/qrv.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverQRV(request.RawUrl));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/elevationpath.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverElevationPath(request.RawUrl));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/propagationpath.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverPropagationPath(request.RawUrl));
mime = "text/json";
}
else if (request.RawUrl.ToLower().StartsWith("/nearestplanes.json"))
{
buffer = System.Text.Encoding.UTF8.GetBytes(DeliverNearestPlanes(request.RawUrl, args.AllPlanes));
mime = "text/json";
}
else
{
// mit Error 404 antworten
buffer = System.Text.Encoding.UTF8.GetBytes("Not found!");
status = HttpStatusCode.NotFound;
}
// Get a response stream and write the response to it.
response.Headers.Add(HttpResponseHeader.CacheControl, "no-cache");
response.ContentType = mime;
response.StatusCode = (int)status;
response.ContentLength64 = buffer.Length;
System.IO.Stream output = response.OutputStream;
output.Write(buffer, 0, buffer.Length);
// Thread.Sleep(1000);
// You must close the output stream.
output.Close();
}
}
public class WebServerDelivererArgs
{
public int ID;
public string TmpDirectory = "";
public string WebserverDirectory = "";
public HttpListenerContext Context;
public List<PlaneInfo> AllPlanes;
}
}