You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2261 lines
93 KiB
2261 lines
93 KiB
using System; |
|
using System.Collections.Generic; |
|
using System.ComponentModel; |
|
using System.Configuration; |
|
using System.Drawing; |
|
using System.Text; |
|
using System.Windows.Forms; |
|
using System.IO; |
|
using System.Xml; |
|
using System.Collections; |
|
using System.Net; |
|
using System.Text.RegularExpressions; |
|
using System.Diagnostics; |
|
using System.Runtime.InteropServices; |
|
using System.Speech.Synthesis; |
|
using System.Globalization; |
|
using System.Threading; |
|
using System.Net.Sockets; |
|
using ArdupilotMega.Utilities; |
|
using IronPython.Hosting; |
|
using log4net; |
|
using ArdupilotMega.Controls; |
|
using System.Security.Cryptography; |
|
using ArdupilotMega.Comms; |
|
using ArdupilotMega.Arduino; |
|
using System.IO.Ports; |
|
|
|
namespace ArdupilotMega |
|
{ |
|
public partial class MainV2 : Form |
|
{ |
|
private static readonly ILog log = |
|
LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); |
|
|
|
// used to hide/show console window |
|
[DllImport("user32.dll")] |
|
public static extern int FindWindow(string szClass, string szTitle); |
|
[DllImport("user32.dll")] |
|
public static extern int ShowWindow(int Handle, int showState); |
|
|
|
const int SW_SHOWNORMAL = 1; |
|
const int SW_HIDE = 0; |
|
|
|
/// <summary> |
|
/// Main Comport interface |
|
/// </summary> |
|
public static IMAVLink comPort = new MAVLink(); |
|
/// <summary> |
|
/// Comport name |
|
/// </summary> |
|
public static string comPortName = ""; |
|
/// <summary> |
|
/// use to store all internal config |
|
/// </summary> |
|
public static Hashtable config = new Hashtable(); |
|
/// <summary> |
|
/// used to prevent comport access for exclusive use |
|
/// </summary> |
|
public static bool giveComport = false; |
|
/// <summary> |
|
/// mono detection |
|
/// </summary> |
|
public static bool MONO = false; |
|
/// <summary> |
|
/// speech engein enable |
|
/// </summary> |
|
public static bool speechEnable = false; |
|
/// <summary> |
|
/// spech engine static class |
|
/// </summary> |
|
public static Speech speechEngine = null; |
|
/// <summary> |
|
/// joystick static class |
|
/// </summary> |
|
public static Joystick joystick = null; |
|
/// <summary> |
|
/// track last joystick packet sent. used to track timming |
|
/// </summary> |
|
DateTime lastjoystick = DateTime.Now; |
|
/// <summary> |
|
/// hud background image grabber from a video stream - not realy that efficent. ie no hardware overlays etc. |
|
/// </summary> |
|
public static WebCamService.Capture cam = null; |
|
/// <summary> |
|
/// the static global state of the currently connected MAV |
|
/// </summary> |
|
public static CurrentState cs = new CurrentState(); |
|
/// <summary> |
|
/// controls the main serial reader thread |
|
/// </summary> |
|
bool serialThread = false; |
|
/// <summary> |
|
/// unused at this point - potential to move all forms to this single binding source. need to evalutate performance/exception issues |
|
/// </summary> |
|
static internal BindingSource bs; |
|
/// <summary> |
|
/// used for mini https server for websockets/mjpeg video stream, and network link kmls |
|
/// </summary> |
|
private TcpListener listener; |
|
/// <summary> |
|
/// track the last heartbeat sent |
|
/// </summary> |
|
private DateTime heatbeatSend = DateTime.Now; |
|
/// <summary> |
|
/// used to call anything as needed. |
|
/// </summary> |
|
public static MainV2 instance = null; |
|
/// <summary> |
|
/// used to feed in a network link kml to the http server |
|
/// </summary> |
|
public string georefkml = ""; |
|
|
|
/// <summary> |
|
/// store the time we first connect |
|
/// </summary> |
|
DateTime connecttime = DateTime.Now; |
|
|
|
/// <summary> |
|
/// enum of firmwares |
|
/// </summary> |
|
public enum Firmwares |
|
{ |
|
ArduPlane, |
|
ArduCopter2, |
|
ArduRover |
|
} |
|
|
|
DateTime connectButtonUpdate = DateTime.Now; |
|
/// <summary> |
|
/// declared here if i want a "single" instance of the form |
|
/// ie configuration gets reloaded on every click |
|
/// </summary> |
|
GCSViews.FlightData FlightData; |
|
GCSViews.FlightPlanner FlightPlanner; |
|
//GCSViews.ConfigurationView.Setup Configuration; |
|
GCSViews.Simulation Simulation; |
|
//GCSViews.Firmware Firmware; |
|
//GCSViews.Terminal Terminal; |
|
|
|
private Form connectionStatsForm; |
|
private ConnectionStats _connectionStats; |
|
|
|
/// <summary> |
|
/// This 'Control' is the toolstrip control that holds the comport combo, baudrate combo etc |
|
/// Otiginally seperate controls, each hosted in a toolstip sqaure, combined into this custom |
|
/// control for layout reasons. |
|
/// </summary> |
|
private readonly ConnectionControl _connectionControl; |
|
|
|
public MainV2() |
|
{ |
|
Form splash = new Splash(); |
|
splash.Show(); |
|
|
|
string strVersion = System.Reflection.Assembly.GetExecutingAssembly().GetName().Version.ToString(); |
|
|
|
strVersion = "mav " + MAVLink.MAVLINK_WIRE_PROTOCOL_VERSION; |
|
|
|
splash.Text = "Mission Planner " + Application.ProductVersion + " " + strVersion; |
|
|
|
splash.Refresh(); |
|
|
|
Application.DoEvents(); |
|
|
|
instance = this; |
|
|
|
InitializeComponent(); |
|
|
|
_connectionControl = toolStripConnectionControl.ConnectionControl; |
|
_connectionControl.CMB_baudrate.TextChanged += this.CMB_baudrate_TextChanged; |
|
_connectionControl.CMB_baudrate.SelectedIndexChanged += this.CMB_baudrate_SelectedIndexChanged; |
|
_connectionControl.CMB_serialport.SelectedIndexChanged += this.CMB_serialport_SelectedIndexChanged; |
|
_connectionControl.CMB_serialport.Enter += this.CMB_serialport_Enter; |
|
_connectionControl.CMB_serialport.Click += this.CMB_serialport_Click; |
|
_connectionControl.TOOL_APMFirmware.SelectedIndexChanged += this.TOOL_APMFirmware_SelectedIndexChanged; |
|
|
|
_connectionControl.ShowLinkStats += (sender, e) => ShowConnectionStatsForm(); |
|
srtm.datadirectory = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + "srtm"; |
|
|
|
var t = Type.GetType("Mono.Runtime"); |
|
MONO = (t != null); |
|
|
|
speechEngine = new Speech(); |
|
|
|
MyRenderer.currentpressed = MenuFlightData; |
|
|
|
MainMenu.Renderer = new MyRenderer(); |
|
|
|
foreach (object obj in Enum.GetValues(typeof(Firmwares))) |
|
{ |
|
_connectionControl.TOOL_APMFirmware.Items.Add(obj); |
|
} |
|
|
|
if (_connectionControl.TOOL_APMFirmware.Items.Count > 0) |
|
_connectionControl.TOOL_APMFirmware.SelectedIndex = 0; |
|
|
|
this.Text = splash.Text; |
|
|
|
comPort.BaseStream.BaudRate = 115200; |
|
|
|
// ** Old |
|
// CMB_serialport.Items.AddRange(SerialPort.GetPortNames()); |
|
// CMB_serialport.Items.Add("TCP"); |
|
// CMB_serialport.Items.Add("UDP"); |
|
// if (CMB_serialport.Items.Count > 0) |
|
// { |
|
// CMB_baudrate.SelectedIndex = 7; |
|
// CMB_serialport.SelectedIndex = 0; |
|
// } |
|
// ** new |
|
_connectionControl.CMB_serialport.Items.AddRange(ArdupilotMega.Comms.SerialPort.GetPortNames()); |
|
_connectionControl.CMB_serialport.Items.Add("TCP"); |
|
_connectionControl.CMB_serialport.Items.Add("UDP"); |
|
if (_connectionControl.CMB_serialport.Items.Count > 0) |
|
{ |
|
_connectionControl.CMB_baudrate.SelectedIndex = 7; |
|
_connectionControl.CMB_serialport.SelectedIndex = 0; |
|
} |
|
// ** Done |
|
|
|
splash.Refresh(); |
|
Application.DoEvents(); |
|
|
|
// set this before we reset it |
|
MainV2.config["NUM_tracklength"] = "200"; |
|
|
|
xmlconfig(false); |
|
|
|
if (config.ContainsKey("language") && !string.IsNullOrEmpty((string)config["language"])) |
|
changelanguage(CultureInfoEx.GetCultureInfo((string)config["language"])); |
|
|
|
if (!MONO) // windows only |
|
{ |
|
if (MainV2.config["showconsole"] != null && MainV2.config["showconsole"].ToString() == "True") |
|
{ |
|
} |
|
else |
|
{ |
|
int win = FindWindow("ConsoleWindowClass", null); |
|
ShowWindow(win, SW_HIDE); // hide window |
|
} |
|
} |
|
|
|
try |
|
{ |
|
FlightData = new GCSViews.FlightData(); |
|
FlightPlanner = new GCSViews.FlightPlanner(); |
|
//Configuration = new GCSViews.ConfigurationView.Setup(); |
|
Simulation = new GCSViews.Simulation(); |
|
//Firmware = new GCSViews.Firmware(); |
|
//Terminal = new GCSViews.Terminal(); |
|
|
|
// preload |
|
Python.CreateEngine(); |
|
} |
|
catch (Exception e) { CustomMessageBox.Show("A Major error has occured : " + e.ToString()); this.Close(); } |
|
|
|
if (MainV2.config["CHK_GDIPlus"] != null) |
|
GCSViews.FlightData.myhud.UseOpenGL = !bool.Parse(MainV2.config["CHK_GDIPlus"].ToString()); |
|
|
|
ChangeUnits(); |
|
|
|
try |
|
{ |
|
if (config["MainLocX"] != null && config["MainLocY"] != null) |
|
{ |
|
this.StartPosition = FormStartPosition.Manual; |
|
Point startpos = new Point(int.Parse(config["MainLocX"].ToString()), int.Parse(config["MainLocY"].ToString())); |
|
this.Location = startpos; |
|
} |
|
|
|
if (config["MainMaximised"] != null) |
|
{ |
|
this.WindowState = (FormWindowState)Enum.Parse(typeof(FormWindowState), config["MainMaximised"].ToString()); |
|
// dont allow minimised start state |
|
if (this.WindowState == FormWindowState.Minimized) |
|
{ |
|
this.WindowState = FormWindowState.Normal; |
|
this.Location = new Point(100, 100); |
|
} |
|
} |
|
|
|
if (config["MainHeight"] != null) |
|
this.Height = int.Parse(config["MainHeight"].ToString()); |
|
if (config["MainWidth"] != null) |
|
this.Width = int.Parse(config["MainWidth"].ToString()); |
|
|
|
if (config["CMB_rateattitude"] != null) |
|
MainV2.cs.rateattitude = byte.Parse(config["CMB_rateattitude"].ToString()); |
|
if (config["rateposition"] != null) |
|
MainV2.cs.rateposition = byte.Parse(config["CMB_rateposition"].ToString()); |
|
if (config["CMB_ratestatus"] != null) |
|
MainV2.cs.ratestatus = byte.Parse(config["CMB_ratestatus"].ToString()); |
|
if (config["CMB_raterc"] != null) |
|
MainV2.cs.raterc = byte.Parse(config["CMB_raterc"].ToString()); |
|
if (config["CMB_ratesensors"] != null) |
|
MainV2.cs.ratesensors = byte.Parse(config["CMB_ratesensors"].ToString()); |
|
|
|
if (config["speechenable"] != null) |
|
MainV2.speechEnable = bool.Parse(config["speechenable"].ToString()); |
|
|
|
//int fixme; |
|
/* |
|
MainV2.cs.rateattitude = 50; |
|
MainV2.cs.rateposition = 50; |
|
MainV2.cs.ratestatus = 50; |
|
MainV2.cs.raterc = 50; |
|
MainV2.cs.ratesensors = 50; |
|
*/ |
|
try |
|
{ |
|
if (config["TXT_homelat"] != null) |
|
cs.HomeLocation.Lat = double.Parse(config["TXT_homelat"].ToString()); |
|
|
|
if (config["TXT_homelng"] != null) |
|
cs.HomeLocation.Lng = double.Parse(config["TXT_homelng"].ToString()); |
|
|
|
if (config["TXT_homealt"] != null) |
|
cs.HomeLocation.Alt = double.Parse(config["TXT_homealt"].ToString()); |
|
} |
|
catch { } |
|
|
|
} |
|
catch { } |
|
|
|
if (cs.rateattitude == 0) // initilised to 10, configured above from save |
|
{ |
|
CustomMessageBox.Show("NOTE: your attitude rate is 0, the hud will not work\nChange in Configuration > Planner > Telemetry Rates"); |
|
} |
|
|
|
|
|
//System.Threading.Thread.Sleep(2000); |
|
|
|
// make sure new enough .net framework is installed |
|
if (!MONO) |
|
{ |
|
Microsoft.Win32.RegistryKey installed_versions = Microsoft.Win32.Registry.LocalMachine.OpenSubKey(@"SOFTWARE\Microsoft\NET Framework Setup\NDP"); |
|
string[] version_names = installed_versions.GetSubKeyNames(); |
|
//version names start with 'v', eg, 'v3.5' which needs to be trimmed off before conversion |
|
double Framework = Convert.ToDouble(version_names[version_names.Length - 1].Remove(0, 1), CultureInfo.InvariantCulture); |
|
int SP = Convert.ToInt32(installed_versions.OpenSubKey(version_names[version_names.Length - 1]).GetValue("SP", 0)); |
|
|
|
if (Framework < 3.5) |
|
{ |
|
CustomMessageBox.Show("This program requires .NET Framework 3.5. You currently have " + Framework); |
|
} |
|
} |
|
|
|
Application.DoEvents(); |
|
|
|
|
|
splash.Close(); |
|
} |
|
|
|
|
|
private void ResetConnectionStats() |
|
{ |
|
// If the form has been closed, or never shown before, we need do nothing, as |
|
// connection stats will be reset when shown |
|
if (this.connectionStatsForm != null && connectionStatsForm.Visible) |
|
{ |
|
// else the form is already showing. reset the stats |
|
this.connectionStatsForm.Controls.Clear(); |
|
_connectionStats = new ConnectionStats(comPort); |
|
this.connectionStatsForm.Controls.Add(_connectionStats); |
|
ThemeManager.ApplyThemeTo(this.connectionStatsForm); |
|
} |
|
} |
|
|
|
private void ShowConnectionStatsForm() |
|
{ |
|
if (this.connectionStatsForm == null || this.connectionStatsForm.IsDisposed) |
|
{ |
|
// If the form has been closed, or never shown before, we need all new stuff |
|
this.connectionStatsForm = new Form |
|
{ |
|
Width = 430, |
|
Height = 180, |
|
MaximizeBox = false, |
|
MinimizeBox = false, |
|
FormBorderStyle = FormBorderStyle.FixedDialog, |
|
Text = "Link Stats" |
|
}; |
|
// Change the connection stats control, so that when/if the connection stats form is showing, |
|
// there will be something to see |
|
this.connectionStatsForm.Controls.Clear(); |
|
_connectionStats = new ConnectionStats(comPort); |
|
this.connectionStatsForm.Controls.Add(_connectionStats); |
|
} |
|
|
|
this.connectionStatsForm.Show(); |
|
ThemeManager.ApplyThemeTo(this.connectionStatsForm); |
|
} |
|
|
|
/// <summary> |
|
/// used to create planner screenshots - access by control-s |
|
/// </summary> |
|
internal void ScreenShot() |
|
{ |
|
Rectangle bounds = Screen.GetBounds(Point.Empty); |
|
using (Bitmap bitmap = new Bitmap(bounds.Width, bounds.Height)) |
|
{ |
|
using (Graphics g = Graphics.FromImage(bitmap)) |
|
{ |
|
g.CopyFromScreen(Point.Empty, Point.Empty, bounds.Size); |
|
} |
|
string name = "ss" + DateTime.Now.ToString("HHmmss") + ".jpg"; |
|
bitmap.Save(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + name, System.Drawing.Imaging.ImageFormat.Jpeg); |
|
CustomMessageBox.Show("Screenshot saved to " + name); |
|
} |
|
|
|
} |
|
|
|
private void CMB_serialport_Click(object sender, EventArgs e) |
|
{ |
|
string oldport = _connectionControl.CMB_serialport.Text; |
|
_connectionControl.CMB_serialport.Items.Clear(); |
|
_connectionControl.CMB_serialport.Items.AddRange(ArdupilotMega.Comms.SerialPort.GetPortNames()); |
|
_connectionControl.CMB_serialport.Items.Add("TCP"); |
|
_connectionControl.CMB_serialport.Items.Add("UDP"); |
|
if (_connectionControl.CMB_serialport.Items.Contains(oldport)) |
|
_connectionControl.CMB_serialport.Text = oldport; |
|
} |
|
|
|
|
|
private void MenuFlightData_Click(object sender, EventArgs e) |
|
{ |
|
MyView.ShowScreen("FlightData"); |
|
|
|
if (MainV2.config["FlightSplitter"] != null) |
|
{ |
|
FlightData.MainHcopy.SplitterDistance = int.Parse(MainV2.config["FlightSplitter"].ToString()) - 1; |
|
FlightData.MainHcopy.SplitterDistance = int.Parse(MainV2.config["FlightSplitter"].ToString()); |
|
} |
|
} |
|
|
|
private void MenuFlightPlanner_Click(object sender, EventArgs e) |
|
{ |
|
// refresh ap/ac specific items |
|
FlightPlanner.updateCMDParams(); |
|
|
|
MyView.ShowScreen("FlightPlanner"); |
|
} |
|
|
|
private void MenuConfiguration_Click(object sender, EventArgs e) |
|
{ |
|
MyView.ShowScreen("Config"); |
|
} |
|
|
|
private void MenuSimulation_Click(object sender, EventArgs e) |
|
{ |
|
MyView.ShowScreen("Simulation"); |
|
} |
|
|
|
private void MenuFirmware_Click(object sender, EventArgs e) |
|
{ |
|
MyView.ShowScreen("Firmware"); |
|
} |
|
|
|
private void MenuTerminal_Click(object sender, EventArgs e) |
|
{ |
|
if (comPort.BaseStream.IsOpen) |
|
{ |
|
MenuConnect_Click(sender, e); |
|
} |
|
|
|
MyView.ShowScreen("Terminal"); |
|
} |
|
|
|
private void MenuConnect_Click(object sender, EventArgs e) |
|
{ |
|
giveComport = false; |
|
|
|
// sanity check |
|
if (comPort.BaseStream.IsOpen && cs.groundspeed > 4) |
|
{ |
|
if (DialogResult.No == CustomMessageBox.Show("Your model is still moving are you sure you want to disconnect?", "Disconnect", MessageBoxButtons.YesNo)) |
|
{ |
|
return; |
|
} |
|
} |
|
|
|
// cleanup from any previous sessions |
|
if (comPort.logfile != null) |
|
comPort.logfile.Close(); |
|
|
|
if (comPort.rawlogfile != null) |
|
comPort.rawlogfile.Close(); |
|
|
|
comPort.logfile = null; |
|
comPort.rawlogfile = null; |
|
|
|
// decide if this is a connect or disconnect |
|
if (comPort.BaseStream.IsOpen) |
|
{ |
|
try |
|
{ |
|
if (speechEngine != null) // cancel all pending speech |
|
speechEngine.SpeakAsyncCancelAll(); |
|
|
|
comPort.BaseStream.DtrEnable = false; |
|
comPort.Close(); |
|
} |
|
catch (Exception ex) |
|
{ |
|
log.Error(ex); |
|
} |
|
|
|
// now that we have closed the connection, cancel the connection stats |
|
// so that the 'time connected' etc does not grow, but the user can still |
|
// look at the now frozen stats on the still open form |
|
try |
|
{ |
|
// if terminal is used, then closed using this button.... exception |
|
((ConnectionStats)this.connectionStatsForm.Controls[0]).StopUpdates(); |
|
} |
|
catch { } |
|
|
|
this.MenuConnect.BackgroundImage = global::ArdupilotMega.Properties.Resources.connect; |
|
} |
|
else |
|
{ |
|
switch (_connectionControl.CMB_serialport.Text) |
|
{ |
|
case "TCP": |
|
comPort.BaseStream = new TcpSerial(); |
|
break; |
|
case "UDP": |
|
comPort.BaseStream = new UdpSerial(); |
|
break; |
|
default: |
|
comPort.BaseStream = new Comms.SerialPort(); |
|
break; |
|
} |
|
|
|
// Tell the connection UI that we are now connected. |
|
this._connectionControl.IsConnected(true); |
|
|
|
// Here we want to reset the connection stats counter etc. |
|
this.ResetConnectionStats(); |
|
|
|
//cleanup any log being played |
|
comPort.logreadmode = false; |
|
if (comPort.logplaybackfile != null) |
|
comPort.logplaybackfile.Close(); |
|
comPort.logplaybackfile = null; |
|
|
|
try |
|
{ |
|
// set port, then options |
|
comPort.BaseStream.PortName = _connectionControl.CMB_serialport.Text; |
|
|
|
comPort.BaseStream.DataBits = 8; |
|
comPort.BaseStream.StopBits = (StopBits)Enum.Parse(typeof(StopBits), "1"); |
|
comPort.BaseStream.Parity = (Parity)Enum.Parse(typeof(Parity), "None"); |
|
try |
|
{ |
|
comPort.BaseStream.BaudRate = int.Parse(_connectionControl.CMB_baudrate.Text); |
|
} |
|
catch (Exception exp) { log.Error(exp); } |
|
|
|
// false here |
|
comPort.BaseStream.DtrEnable = false; |
|
comPort.BaseStream.RtsEnable = false; |
|
|
|
// reset on connect logic. |
|
if (config["CHK_resetapmonconnect"] == null || bool.Parse(config["CHK_resetapmonconnect"].ToString()) == true) |
|
comPort.BaseStream.toggleDTR(); |
|
|
|
// setup to record new logs |
|
try |
|
{ |
|
Directory.CreateDirectory(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs"); |
|
comPort.logfile = new BinaryWriter(File.Open(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs" + Path.DirectorySeparatorChar + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".tlog", FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read)); |
|
|
|
comPort.rawlogfile = new BinaryWriter(File.Open(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"logs" + Path.DirectorySeparatorChar + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".rlog", FileMode.CreateNew, FileAccess.ReadWrite, FileShare.Read)); |
|
} |
|
catch (Exception exp2) { log.Error(exp2); CustomMessageBox.Show("Failed to create log - wont log this session"); } // soft fail |
|
|
|
// reset connect time - for timeout functions |
|
connecttime = DateTime.Now; |
|
|
|
// do the connect |
|
comPort.Open(true); |
|
|
|
// detect firmware we are conected to. |
|
if (comPort.param["SYSID_SW_TYPE"] != null) |
|
{ |
|
if (float.Parse(comPort.param["SYSID_SW_TYPE"].ToString()) == 10) |
|
{ |
|
_connectionControl.TOOL_APMFirmware.SelectedIndex = _connectionControl.TOOL_APMFirmware.Items.IndexOf(Firmwares.ArduCopter2); |
|
} |
|
else if (float.Parse(comPort.param["SYSID_SW_TYPE"].ToString()) == 20) |
|
{ |
|
_connectionControl.TOOL_APMFirmware.SelectedIndex = _connectionControl.TOOL_APMFirmware.Items.IndexOf(Firmwares.ArduRover); |
|
} |
|
else if (float.Parse(comPort.param["SYSID_SW_TYPE"].ToString()) == 0) |
|
{ |
|
_connectionControl.TOOL_APMFirmware.SelectedIndex = _connectionControl.TOOL_APMFirmware.Items.IndexOf(Firmwares.ArduPlane); |
|
} |
|
} |
|
|
|
// save the baudrate for this port |
|
config[_connectionControl.CMB_serialport.Text + "_BAUD"] = _connectionControl.CMB_baudrate.Text; |
|
|
|
// load wps on connect option. |
|
if (config["loadwpsonconnect"] != null && bool.Parse(config["loadwpsonconnect"].ToString()) == true) |
|
{ |
|
MenuFlightPlanner_Click(null, null); |
|
FlightPlanner.BUT_read_Click(null, null); |
|
} |
|
|
|
// set connected icon |
|
this.MenuConnect.BackgroundImage = global::ArdupilotMega.Properties.Resources.disconnect; |
|
} |
|
catch (Exception ex) |
|
{ |
|
log.Warn(ex); |
|
try |
|
{ |
|
_connectionControl.IsConnected(false); |
|
UpdateConnectIcon(); |
|
comPort.Close(); |
|
} |
|
catch { } |
|
// detect firmware -> scan eeprom contents -> error if no valid ap param/apvar header detected. |
|
try |
|
{ |
|
string version = ArduinoDetect.DetectVersion(comPort.BaseStream.PortName); |
|
ArduinoComms port = new ArduinoSTK(); |
|
if (version == "1280") |
|
{ |
|
port = new ArduinoSTK(); |
|
port.BaudRate = 57600; |
|
} |
|
else if (version == "2560") |
|
{ |
|
port = new ArduinoSTKv2(); |
|
port.BaudRate = 115200; |
|
} |
|
else { throw new Exception("Can not determine APM board type"); } |
|
port.PortName = comPort.BaseStream.PortName; |
|
port.DtrEnable = true; |
|
port.Open(); |
|
if (port.connectAP()) |
|
{ |
|
byte[] buffer = port.download(20); |
|
port.Close(); |
|
|
|
if ((buffer[0] == 'A' || buffer[0] == 'P') && (buffer[1] == 'A' || buffer[1] == 'P')) // this is the apvar header |
|
{ |
|
log.Info("Valid eeprom contents"); |
|
} |
|
else |
|
{ |
|
CustomMessageBox.Show("You dont appear to have uploaded a firmware yet,\n\nPlease goto the firmware page and upload one."); |
|
return; |
|
} |
|
} |
|
else |
|
{ |
|
log.Error("Could not download eeprom contents"); |
|
} |
|
} |
|
catch (Exception exp3) { log.Error(exp3); } |
|
//MessageBox.Show("Can not establish a connection\n\n" + ex.ToString()); |
|
return; |
|
} |
|
} |
|
} |
|
|
|
private void CMB_serialport_SelectedIndexChanged(object sender, EventArgs e) |
|
{ |
|
comPortName = _connectionControl.CMB_serialport.Text; |
|
if (comPortName == "UDP" || comPortName == "TCP") |
|
{ |
|
_connectionControl.CMB_baudrate.Enabled = false; |
|
if (comPortName == "TCP") |
|
MainV2.comPort.BaseStream = new TcpSerial(); |
|
if (comPortName == "UDP") |
|
MainV2.comPort.BaseStream = new UdpSerial(); |
|
} |
|
else |
|
{ |
|
_connectionControl.CMB_baudrate.Enabled = true; |
|
MainV2.comPort.BaseStream = new ArdupilotMega.Comms.SerialPort(); |
|
} |
|
|
|
try |
|
{ |
|
comPort.BaseStream.PortName = _connectionControl.CMB_serialport.Text; |
|
|
|
MainV2.comPort.BaseStream.BaudRate = int.Parse(_connectionControl.CMB_baudrate.Text); |
|
|
|
// check for saved baud rate and restore |
|
if (config[_connectionControl.CMB_serialport.Text + "_BAUD"] != null) |
|
{ |
|
_connectionControl.CMB_baudrate.Text = config[_connectionControl.CMB_serialport.Text + "_BAUD"].ToString(); |
|
} |
|
} |
|
catch { } |
|
} |
|
|
|
private void MainV2_FormClosed(object sender, FormClosedEventArgs e) |
|
{ |
|
// shutdown threads |
|
GCSViews.FlightData.threadrun = 0; |
|
GCSViews.Simulation.threadrun = 0; |
|
|
|
// shutdown local thread |
|
serialThread = false; |
|
|
|
try |
|
{ |
|
if (comPort.BaseStream.IsOpen) |
|
comPort.Close(); |
|
} |
|
catch { } // i get alot of these errors, the port is still open, but not valid - user has unpluged usb |
|
try |
|
{ |
|
FlightData.Dispose(); |
|
} |
|
catch { } |
|
try |
|
{ |
|
FlightPlanner.Dispose(); |
|
} |
|
catch { } |
|
try |
|
{ |
|
Simulation.Dispose(); |
|
} |
|
catch { } |
|
|
|
|
|
// save config |
|
xmlconfig(true); |
|
} |
|
|
|
|
|
private void xmlconfig(bool write) |
|
{ |
|
if (write || !File.Exists(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"config.xml")) |
|
{ |
|
try |
|
{ |
|
XmlTextWriter xmlwriter = new XmlTextWriter(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"config.xml", Encoding.ASCII); |
|
xmlwriter.Formatting = Formatting.Indented; |
|
|
|
xmlwriter.WriteStartDocument(); |
|
|
|
xmlwriter.WriteStartElement("Config"); |
|
|
|
xmlwriter.WriteElementString("comport", comPortName); |
|
|
|
xmlwriter.WriteElementString("baudrate", _connectionControl.CMB_baudrate.Text); |
|
|
|
xmlwriter.WriteElementString("APMFirmware", MainV2.cs.firmware.ToString()); |
|
|
|
foreach (string key in config.Keys) |
|
{ |
|
try |
|
{ |
|
if (key == "" || key.Contains("/")) // "/dev/blah" |
|
continue; |
|
xmlwriter.WriteElementString(key, config[key].ToString()); |
|
} |
|
catch { } |
|
} |
|
|
|
xmlwriter.WriteEndElement(); |
|
|
|
xmlwriter.WriteEndDocument(); |
|
xmlwriter.Close(); |
|
} |
|
catch (Exception ex) { CustomMessageBox.Show(ex.ToString()); } |
|
} |
|
else |
|
{ |
|
try |
|
{ |
|
using (XmlTextReader xmlreader = new XmlTextReader(Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + @"config.xml")) |
|
{ |
|
while (xmlreader.Read()) |
|
{ |
|
xmlreader.MoveToElement(); |
|
try |
|
{ |
|
switch (xmlreader.Name) |
|
{ |
|
case "comport": |
|
string temp = xmlreader.ReadString(); |
|
|
|
_connectionControl.CMB_serialport.SelectedIndex = _connectionControl.CMB_serialport.FindString(temp); |
|
if (_connectionControl.CMB_serialport.SelectedIndex == -1) |
|
{ |
|
_connectionControl.CMB_serialport.Text = temp; // allows ports that dont exist - yet |
|
} |
|
comPort.BaseStream.PortName = temp; |
|
comPortName = temp; |
|
break; |
|
case "baudrate": |
|
string temp2 = xmlreader.ReadString(); |
|
|
|
_connectionControl.CMB_baudrate.SelectedIndex = _connectionControl.CMB_baudrate.FindString(temp2); |
|
if (_connectionControl.CMB_baudrate.SelectedIndex == -1) |
|
{ |
|
_connectionControl.CMB_baudrate.Text = temp2; |
|
//CMB_baudrate.SelectedIndex = CMB_baudrate.FindString("57600"); ; // must exist |
|
} |
|
//bau = int.Parse(CMB_baudrate.Text); |
|
break; |
|
case "APMFirmware": |
|
string temp3 = xmlreader.ReadString(); |
|
_connectionControl.TOOL_APMFirmware.SelectedIndex = _connectionControl.TOOL_APMFirmware.FindStringExact(temp3); |
|
if (_connectionControl.TOOL_APMFirmware.SelectedIndex == -1) |
|
_connectionControl.TOOL_APMFirmware.SelectedIndex = 0; |
|
MainV2.cs.firmware = (MainV2.Firmwares)Enum.Parse(typeof(MainV2.Firmwares), _connectionControl.TOOL_APMFirmware.Text); |
|
break; |
|
case "Config": |
|
break; |
|
case "xml": |
|
break; |
|
default: |
|
if (xmlreader.Name == "") // line feeds |
|
break; |
|
config[xmlreader.Name] = xmlreader.ReadString(); |
|
break; |
|
} |
|
} |
|
// silent fail on bad entry |
|
catch (Exception ee) |
|
{ |
|
log.Error(ee); |
|
} |
|
} |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
log.Error("Bad Config File", ex); |
|
} |
|
} |
|
} |
|
|
|
private void CMB_baudrate_SelectedIndexChanged(object sender, EventArgs e) |
|
{ |
|
try |
|
{ |
|
comPort.BaseStream.BaudRate = int.Parse(_connectionControl.CMB_baudrate.Text); |
|
} |
|
catch |
|
{ |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// thread used to send joystick packets to the MAV |
|
/// </summary> |
|
private void joysticksend() |
|
{ |
|
|
|
float rate = 50; |
|
int count = 0; |
|
|
|
DateTime lastratechange = DateTime.Now; |
|
|
|
while (true) |
|
{ |
|
try |
|
{ |
|
if (MONO) |
|
{ |
|
log.Error("Mono: closing joystick thread"); |
|
break; |
|
} |
|
|
|
if (!MONO) |
|
{ |
|
//joystick stuff |
|
|
|
if (joystick != null && joystick.enabled) |
|
{ |
|
MAVLink.mavlink_rc_channels_override_t rc = new MAVLink.mavlink_rc_channels_override_t(); |
|
|
|
rc.target_component = comPort.compid; |
|
rc.target_system = comPort.sysid; |
|
|
|
if (joystick.getJoystickAxis(1) != Joystick.joystickaxis.None) |
|
rc.chan1_raw = cs.rcoverridech1;//(ushort)(((int)state.Rz / 65.535) + 1000); |
|
if (joystick.getJoystickAxis(2) != Joystick.joystickaxis.None) |
|
rc.chan2_raw = cs.rcoverridech2;//(ushort)(((int)state.Y / 65.535) + 1000); |
|
if (joystick.getJoystickAxis(3) != Joystick.joystickaxis.None) |
|
rc.chan3_raw = cs.rcoverridech3;//(ushort)(1000 - ((int)slider[0] / 65.535 ) + 1000); |
|
if (joystick.getJoystickAxis(4) != Joystick.joystickaxis.None) |
|
rc.chan4_raw = cs.rcoverridech4;//(ushort)(((int)state.X / 65.535) + 1000); |
|
if (joystick.getJoystickAxis(5) != Joystick.joystickaxis.None) |
|
rc.chan5_raw = cs.rcoverridech5; |
|
if (joystick.getJoystickAxis(6) != Joystick.joystickaxis.None) |
|
rc.chan6_raw = cs.rcoverridech6; |
|
if (joystick.getJoystickAxis(7) != Joystick.joystickaxis.None) |
|
rc.chan7_raw = cs.rcoverridech7; |
|
if (joystick.getJoystickAxis(8) != Joystick.joystickaxis.None) |
|
rc.chan8_raw = cs.rcoverridech8; |
|
|
|
if (lastjoystick.AddMilliseconds(rate) < DateTime.Now) |
|
{ |
|
/* |
|
if (cs.rssi > 0 && cs.remrssi > 0) |
|
{ |
|
if (lastratechange.Second != DateTime.Now.Second) |
|
{ |
|
if (cs.txbuffer > 90) |
|
{ |
|
if (rate < 20) |
|
rate = 21; |
|
rate--; |
|
|
|
if (cs.linkqualitygcs < 70) |
|
rate = 50; |
|
} |
|
else |
|
{ |
|
if (rate > 100) |
|
rate = 100; |
|
rate++; |
|
} |
|
|
|
lastratechange = DateTime.Now; |
|
} |
|
|
|
} |
|
*/ |
|
// Console.WriteLine(DateTime.Now.Millisecond + " {0} {1} {2} {3} {4}", rc.chan1_raw, rc.chan2_raw, rc.chan3_raw, rc.chan4_raw,rate); |
|
comPort.sendPacket(rc); |
|
count++; |
|
lastjoystick = DateTime.Now; |
|
} |
|
|
|
} |
|
} |
|
Thread.Sleep(20); |
|
} |
|
catch |
|
{ |
|
|
|
} // cant fall out |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Used to fix the icon status for unexpected unplugs etc... |
|
/// </summary> |
|
private void UpdateConnectIcon() |
|
{ |
|
if ((DateTime.Now - connectButtonUpdate).Milliseconds > 500) |
|
{ |
|
// Console.WriteLine(DateTime.Now.Millisecond); |
|
if (comPort.BaseStream.IsOpen) |
|
{ |
|
if ((string)this.MenuConnect.BackgroundImage.Tag != "Disconnect") |
|
{ |
|
this.BeginInvoke((MethodInvoker)delegate |
|
{ |
|
this.MenuConnect.BackgroundImage = global::ArdupilotMega.Properties.Resources.disconnect; |
|
this.MenuConnect.BackgroundImage.Tag = "Disconnect"; |
|
_connectionControl.IsConnected(true); |
|
}); |
|
} |
|
} |
|
else |
|
{ |
|
if ((string)this.MenuConnect.BackgroundImage.Tag != "Connect") |
|
{ |
|
this.BeginInvoke((MethodInvoker)delegate |
|
{ |
|
this.MenuConnect.BackgroundImage = global::ArdupilotMega.Properties.Resources.connect; |
|
this.MenuConnect.BackgroundImage.Tag = "Connect"; |
|
_connectionControl.IsConnected(false); |
|
if (_connectionStats != null) |
|
{ |
|
_connectionStats.StopUpdates(); |
|
} |
|
}); |
|
} |
|
|
|
if (comPort.logreadmode) |
|
{ |
|
this.BeginInvoke((MethodInvoker)delegate |
|
{ |
|
_connectionControl.IsConnected(true); |
|
}); |
|
} |
|
} |
|
connectButtonUpdate = DateTime.Now; |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// main serial reader thread |
|
/// controls |
|
/// serial reading |
|
/// link quality stats |
|
/// speech voltage - custom - alt warning - data lost |
|
/// heartbeat packet sending |
|
/// |
|
/// and cant fall out |
|
/// </summary> |
|
private void SerialReader() |
|
{ |
|
if (serialThread == true) |
|
return; |
|
serialThread = true; |
|
|
|
int minbytes = 10; |
|
|
|
if (MONO) |
|
minbytes = 0; |
|
|
|
DateTime speechcustomtime = DateTime.Now; |
|
|
|
DateTime linkqualitytime = DateTime.Now; |
|
|
|
while (serialThread) |
|
{ |
|
try |
|
{ |
|
Thread.Sleep(5); |
|
|
|
UpdateConnectIcon(); |
|
|
|
if (speechEnable && speechEngine != null && (DateTime.Now - speechcustomtime).TotalSeconds > 30 && MainV2.cs.lat != 0 && (MainV2.comPort.logreadmode || comPort.BaseStream.IsOpen)) |
|
{ |
|
//speechbatteryvolt |
|
float warnvolt = 0; |
|
float.TryParse(MainV2.getConfig("speechbatteryvolt"), out warnvolt); |
|
|
|
if (MainV2.getConfig("speechbatteryenabled") == "True" && MainV2.cs.battery_voltage <= warnvolt) |
|
{ |
|
MainV2.speechEngine.SpeakAsync(Common.speechConversion(MainV2.getConfig("speechbattery"))); |
|
} |
|
|
|
if (MainV2.getConfig("speechcustomenabled") == "True") |
|
{ |
|
MainV2.speechEngine.SpeakAsync(Common.speechConversion(MainV2.getConfig("speechcustom"))); |
|
} |
|
|
|
speechcustomtime = DateTime.Now; |
|
} |
|
|
|
if (speechEnable && speechEngine != null && (MainV2.comPort.logreadmode || comPort.BaseStream.IsOpen)) |
|
{ |
|
float warnalt = float.MaxValue; |
|
float.TryParse(MainV2.getConfig("speechaltheight"), out warnalt); |
|
try |
|
{ |
|
if (MainV2.getConfig("speechaltenabled") == "True" && (MainV2.cs.alt - (int)double.Parse(MainV2.getConfig("TXT_homealt"))) <= warnalt) |
|
{ |
|
if (MainV2.speechEngine.State == SynthesizerState.Ready) |
|
MainV2.speechEngine.SpeakAsync(Common.speechConversion(MainV2.getConfig("speechalt"))); |
|
} |
|
} |
|
catch { } // silent fail |
|
} |
|
|
|
if (!comPort.BaseStream.IsOpen || giveComport == true) |
|
{ |
|
System.Threading.Thread.Sleep(100); |
|
continue; |
|
} |
|
|
|
if ((DateTime.Now - comPort.lastvalidpacket).TotalSeconds > 10) |
|
{ |
|
MainV2.cs.linkqualitygcs = 0; |
|
} |
|
|
|
if ((DateTime.Now - comPort.lastvalidpacket).TotalSeconds >= 1) |
|
{ |
|
if (linkqualitytime.Second != DateTime.Now.Second) |
|
{ |
|
MainV2.cs.linkqualitygcs = (ushort)(MainV2.cs.linkqualitygcs * 0.8f); |
|
linkqualitytime = DateTime.Now; |
|
|
|
int fixme; |
|
//GCSViews.FlightData.myhud.Invalidate(); |
|
} |
|
} |
|
|
|
if (heatbeatSend.Second != DateTime.Now.Second) |
|
{ |
|
// Console.WriteLine("remote lost {0}", cs.packetdropremote); |
|
|
|
MAVLink.mavlink_heartbeat_t htb = new MAVLink.mavlink_heartbeat_t(); |
|
|
|
#if MAVLINK10 |
|
htb.type = (byte)MAVLink.MAV_TYPE.GCS; |
|
htb.autopilot = (byte)MAVLink.MAV_AUTOPILOT.ARDUPILOTMEGA; |
|
htb.mavlink_version = 3; |
|
#else |
|
htb.type = (byte)MAVLink.MAV_TYPE.MAV_GENERIC; |
|
htb.autopilot = (byte)MAVLink.MAV_AUTOPILOT_TYPE.MAV_AUTOPILOT_ARDUPILOTMEGA; |
|
htb.mavlink_version = 2; |
|
#endif |
|
|
|
comPort.sendPacket(htb); |
|
heatbeatSend = DateTime.Now; |
|
} |
|
|
|
// data loss warning - ignore first 30 seconds of connect |
|
if ((DateTime.Now - comPort.lastvalidpacket).TotalSeconds > 10 && (DateTime.Now - connecttime).TotalSeconds > 30) |
|
{ |
|
if (speechEnable && speechEngine != null) |
|
{ |
|
if (MainV2.speechEngine.State == SynthesizerState.Ready) |
|
MainV2.speechEngine.SpeakAsync("WARNING No Data for " + (int)(DateTime.Now - comPort.lastvalidpacket).TotalSeconds + " Seconds"); |
|
} |
|
} |
|
|
|
//Console.WriteLine(DateTime.Now.Millisecond + " " + comPort.BaseStream.BytesToRead); |
|
|
|
while (comPort.BaseStream.BytesToRead > minbytes && giveComport == false) |
|
{ |
|
comPort.readPacket(); |
|
} |
|
} |
|
catch (Exception e) |
|
{ |
|
log.Error("Serial Reader fail :" + e.Message); |
|
try |
|
{ |
|
comPort.Close(); |
|
} |
|
catch { } |
|
} |
|
} |
|
} |
|
|
|
/// <summary> |
|
/// Override the stock ToolStripProfessionalRenderer to implement 'highlighting' of the |
|
/// currently selected GCS view. |
|
/// </summary> |
|
private class MyRenderer : ToolStripProfessionalRenderer |
|
{ |
|
public static ToolStripItem currentpressed; |
|
protected override void OnRenderButtonBackground(ToolStripItemRenderEventArgs e) |
|
{ |
|
//BackgroundImage |
|
if (e.Item.BackgroundImage == null) base.OnRenderButtonBackground(e); |
|
else |
|
{ |
|
Rectangle bounds = new Rectangle(Point.Empty, e.Item.Size); |
|
e.Graphics.DrawImage(e.Item.BackgroundImage, bounds); |
|
if (e.Item.Pressed || e.Item == currentpressed) |
|
{ |
|
SolidBrush brush = new SolidBrush(Color.FromArgb(73, 0x2b, 0x3a, 0x03)); |
|
e.Graphics.FillRectangle(brush, bounds); |
|
if (e.Item.Name != "MenuConnect") |
|
{ |
|
//Console.WriteLine("new " + e.Item.Name + " old " + currentpressed.Name ); |
|
//e.Item.GetCurrentParent().Invalidate(); |
|
if (currentpressed != e.Item) |
|
currentpressed.Invalidate(); |
|
currentpressed = e.Item; |
|
} |
|
|
|
// Something... |
|
} |
|
else if (e.Item.Selected) // mouse over |
|
{ |
|
SolidBrush brush = new SolidBrush(Color.FromArgb(73, 0x2b, 0x3a, 0x03)); |
|
e.Graphics.FillRectangle(brush, bounds); |
|
// Something... |
|
} |
|
using (Pen pen = new Pen(Color.Black)) |
|
{ |
|
//e.Graphics.DrawRectangle(pen, bounds.X, bounds.Y, bounds.Width - 1, bounds.Height - 1); |
|
} |
|
} |
|
} |
|
|
|
protected override void OnRenderItemImage(ToolStripItemImageRenderEventArgs e) |
|
{ |
|
//base.OnRenderItemImage(e); |
|
} |
|
} |
|
|
|
private void MainV2_Load(object sender, EventArgs e) |
|
{ |
|
MyView.AddScreen(new MainSwitcher.Screen("FlightData",FlightData,true)); |
|
MyView.AddScreen(new MainSwitcher.Screen("FlightPlanner", FlightPlanner, true)); |
|
MyView.AddScreen(new MainSwitcher.Screen("Config", new GCSViews.ConfigurationView.Setup(), false)); |
|
MyView.AddScreen(new MainSwitcher.Screen("Simulation", Simulation, true)); |
|
MyView.AddScreen(new MainSwitcher.Screen("Firmware", new GCSViews.Firmware(), false)); |
|
MyView.AddScreen(new MainSwitcher.Screen("Terminal", new GCSViews.Terminal(), false)); |
|
MyView.AddScreen(new MainSwitcher.Screen("Help", new GCSViews.Help(), false)); |
|
|
|
// init button depressed - ensures correct action |
|
MenuFlightData_Click(sender, e); |
|
|
|
// for long running tasks using own threads. |
|
// for short use threadpool |
|
|
|
// setup http server |
|
try |
|
{ |
|
listener = new TcpListener(IPAddress.Any, 56781); |
|
new Thread(listernforclients) |
|
{ |
|
Name = "motion jpg stream-network kml", |
|
IsBackground = true |
|
}.Start(); |
|
} |
|
catch (Exception ex) |
|
{ |
|
log.Error("Error starting TCP listener thread: ", ex); |
|
CustomMessageBox.Show(ex.ToString()); |
|
} |
|
|
|
/// setup joystick packet sender |
|
new Thread(new ThreadStart(joysticksend)) |
|
{ |
|
IsBackground = true, |
|
Priority = ThreadPriority.AboveNormal, |
|
Name = "Main joystick sender" |
|
}.Start(); |
|
|
|
// setup main serial reader |
|
new Thread(SerialReader) |
|
{ |
|
IsBackground = true, |
|
Name = "Main Serial reader" |
|
}.Start(); |
|
|
|
try |
|
{ |
|
if (!System.Diagnostics.Debugger.IsAttached) |
|
{ |
|
CheckForUpdate(); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
log.Error("Update check failed", ex); |
|
} |
|
} |
|
|
|
public static String ComputeWebSocketHandshakeSecurityHash09(String secWebSocketKey) |
|
{ |
|
const String MagicKEY = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11"; |
|
String secWebSocketAccept = String.Empty; |
|
|
|
// 1. Combine the request Sec-WebSocket-Key with magic key. |
|
String ret = secWebSocketKey + MagicKEY; |
|
|
|
// 2. Compute the SHA1 hash |
|
System.Security.Cryptography.SHA1 sha = new System.Security.Cryptography.SHA1CryptoServiceProvider(); |
|
byte[] sha1Hash = sha.ComputeHash(Encoding.UTF8.GetBytes(ret)); |
|
|
|
// 3. Base64 encode the hash |
|
secWebSocketAccept = Convert.ToBase64String(sha1Hash); |
|
|
|
return secWebSocketAccept; |
|
} |
|
|
|
/// <summary> |
|
/// little web server for sending network link kml's |
|
/// </summary> |
|
void listernforclients() |
|
{ |
|
try |
|
{ |
|
listener.Start(); |
|
} |
|
catch (Exception e) |
|
{ |
|
log.Error("Exception starting lister. Possible multiple instances of planner?", e); |
|
return; |
|
} // in use |
|
// Enter the listening loop. |
|
while (true) |
|
{ |
|
// Perform a blocking call to accept requests. |
|
// You could also user server.AcceptSocket() here. |
|
try |
|
{ |
|
log.Info("Listening for client - 1 client at a time"); |
|
TcpClient client = listener.AcceptTcpClient(); |
|
// Get a stream object for reading and writing |
|
log.Info("Accepted Client " + client.Client.RemoteEndPoint.ToString()); |
|
//client.SendBufferSize = 100 * 1024; // 100kb |
|
//client.LingerState.Enabled = true; |
|
//client.NoDelay = true; |
|
|
|
// makesure we have valid image |
|
GCSViews.FlightData.mymap.streamjpgenable = true; |
|
GCSViews.FlightData.myhud.streamjpgenable = true; |
|
|
|
MethodInvoker m = delegate() |
|
{ |
|
GCSViews.FlightData.mymap.Refresh(); |
|
}; |
|
this.Invoke(m); |
|
|
|
NetworkStream stream = client.GetStream(); |
|
|
|
var asciiEncoding = new ASCIIEncoding(); |
|
|
|
var request = new byte[1024]; |
|
|
|
int len = stream.Read(request, 0, request.Length); |
|
string head = System.Text.Encoding.ASCII.GetString(request, 0, len); |
|
log.Info(head); |
|
|
|
int index = head.IndexOf('\n'); |
|
|
|
string url = head.Substring(0, index - 1); |
|
//url = url.Replace("\r", ""); |
|
//url = url.Replace("GET ",""); |
|
//url = url.Replace(" HTTP/1.0", ""); |
|
//url = url.Replace(" HTTP/1.1", ""); |
|
|
|
if (url.Contains("websocket")) |
|
{ |
|
using (var writer = new StreamWriter(stream, Encoding.Default)) |
|
{ |
|
writer.WriteLine("HTTP/1.1 101 WebSocket Protocol Handshake"); |
|
writer.WriteLine("Upgrade: WebSocket"); |
|
writer.WriteLine("Connection: Upgrade"); |
|
writer.WriteLine("WebSocket-Location: ws://localhost:56781/websocket/server"); |
|
|
|
int start = head.IndexOf("Sec-WebSocket-Key:") + 19; |
|
int end = head.IndexOf('\r', start); |
|
if (end == -1) |
|
end = head.IndexOf('\n', start); |
|
string accept = ComputeWebSocketHandshakeSecurityHash09(head.Substring(start, end - start)); |
|
|
|
writer.WriteLine("Sec-WebSocket-Accept: " + accept); |
|
|
|
writer.WriteLine("Server: APM Planner"); |
|
|
|
writer.WriteLine(""); |
|
|
|
writer.Flush(); |
|
|
|
while (client.Connected) |
|
{ |
|
Thread.Sleep(200); |
|
log.Debug(stream.DataAvailable + " " + client.Available); |
|
|
|
while (client.Available > 0) |
|
{ |
|
Console.Write(stream.ReadByte()); |
|
} |
|
|
|
byte[] packet = new byte[256]; |
|
|
|
string sendme = cs.roll + "," + cs.pitch + "," + cs.yaw; |
|
|
|
packet[0] = 0x81; // fin - binary |
|
packet[1] = (byte)sendme.Length; |
|
|
|
int i = 2; |
|
foreach (char ch in sendme) |
|
{ |
|
packet[i++] = (byte)ch; |
|
} |
|
|
|
stream.Write(packet, 0, i); |
|
|
|
//break; |
|
} |
|
} |
|
} |
|
else if (url.Contains("georefnetwork.kml")) |
|
{ |
|
string header = "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.google-earth.kml+xml\r\n\r\n"; |
|
byte[] temp = asciiEncoding.GetBytes(header); |
|
stream.Write(temp, 0, temp.Length); |
|
|
|
byte[] buffer = Encoding.ASCII.GetBytes(georefkml); |
|
|
|
stream.Write(buffer, 0, buffer.Length); |
|
|
|
stream.Close(); |
|
} |
|
else if (url.Contains("network.kml")) |
|
{ |
|
string header = "HTTP/1.1 200 OK\r\nContent-Type: application/vnd.google-earth.kml+xml\r\n\r\n"; |
|
byte[] temp = asciiEncoding.GetBytes(header); |
|
stream.Write(temp, 0, temp.Length); |
|
|
|
SharpKml.Dom.Document kml = new SharpKml.Dom.Document(); |
|
|
|
SharpKml.Dom.Placemark pmplane = new SharpKml.Dom.Placemark(); |
|
pmplane.Name = "P/Q "; |
|
|
|
pmplane.Visibility = true; |
|
|
|
SharpKml.Dom.Location loc = new SharpKml.Dom.Location(); |
|
loc.Latitude = cs.lat; |
|
loc.Longitude = cs.lng; |
|
loc.Altitude = cs.alt; |
|
|
|
if (loc.Altitude < 0) |
|
loc.Altitude = 0.01; |
|
|
|
SharpKml.Dom.Orientation ori = new SharpKml.Dom.Orientation(); |
|
ori.Heading = cs.yaw; |
|
ori.Roll = -cs.roll; |
|
ori.Tilt = -cs.pitch; |
|
|
|
SharpKml.Dom.Scale sca = new SharpKml.Dom.Scale(); |
|
|
|
sca.X = 2; |
|
sca.Y = 2; |
|
sca.Z = 2; |
|
|
|
SharpKml.Dom.Model model = new SharpKml.Dom.Model(); |
|
model.Location = loc; |
|
model.Orientation = ori; |
|
model.AltitudeMode = SharpKml.Dom.AltitudeMode.Absolute; |
|
model.Scale = sca; |
|
|
|
SharpKml.Dom.Link link = new SharpKml.Dom.Link(); |
|
link.Href = new Uri("block_plane_0.dae", UriKind.Relative); |
|
|
|
model.Link = link; |
|
|
|
pmplane.Geometry = model; |
|
|
|
SharpKml.Dom.LookAt la = new SharpKml.Dom.LookAt() |
|
{ |
|
Altitude = loc.Altitude.Value, |
|
Latitude = loc.Latitude.Value, |
|
Longitude = loc.Longitude.Value, |
|
Tilt = 80, |
|
Heading = cs.yaw, |
|
AltitudeMode = SharpKml.Dom.AltitudeMode.Absolute, |
|
Range = 50 |
|
}; |
|
|
|
kml.Viewpoint = la; |
|
|
|
kml.AddFeature(pmplane); |
|
|
|
SharpKml.Dom.CoordinateCollection coords = new SharpKml.Dom.CoordinateCollection(); |
|
|
|
foreach (var point in GCSViews.FlightPlanner.pointlist) |
|
{ |
|
if (point != null) |
|
coords.Add(new SharpKml.Base.Vector(point.Lat, point.Lng, point.Alt)); |
|
|
|
} |
|
|
|
SharpKml.Dom.LineString ls = new SharpKml.Dom.LineString(); |
|
ls.AltitudeMode = SharpKml.Dom.AltitudeMode.RelativeToGround; |
|
ls.Coordinates = coords; |
|
|
|
SharpKml.Dom.Placemark pm = new SharpKml.Dom.Placemark() { Geometry = ls }; |
|
|
|
kml.AddFeature(pm); |
|
|
|
SharpKml.Base.Serializer serializer = new SharpKml.Base.Serializer(); |
|
serializer.Serialize(kml); |
|
|
|
byte[] buffer = Encoding.ASCII.GetBytes(serializer.Xml); |
|
|
|
stream.Write(buffer, 0, buffer.Length); |
|
|
|
stream.Close(); |
|
} |
|
else if (url.Contains("block_plane_0.dae")) |
|
{ |
|
string header = "HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n"; |
|
byte[] temp = asciiEncoding.GetBytes(header); |
|
stream.Write(temp, 0, temp.Length); |
|
|
|
BinaryReader file = new BinaryReader(File.Open("block_plane_0.dae", FileMode.Open, FileAccess.Read, FileShare.Read)); |
|
byte[] buffer = new byte[1024]; |
|
while (file.PeekChar() != -1) |
|
{ |
|
|
|
int leng = file.Read(buffer, 0, buffer.Length); |
|
|
|
stream.Write(buffer, 0, leng); |
|
} |
|
file.Close(); |
|
stream.Close(); |
|
} |
|
else if (url.Contains("hud.html")) |
|
{ |
|
string header = "HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n"; |
|
byte[] temp = asciiEncoding.GetBytes(header); |
|
stream.Write(temp, 0, temp.Length); |
|
|
|
BinaryReader file = new BinaryReader(File.Open("hud.html", FileMode.Open, FileAccess.Read, FileShare.Read)); |
|
byte[] buffer = new byte[1024]; |
|
while (file.PeekChar() != -1) |
|
{ |
|
|
|
int leng = file.Read(buffer, 0, buffer.Length); |
|
|
|
stream.Write(buffer, 0, leng); |
|
} |
|
file.Close(); |
|
stream.Close(); |
|
} |
|
else if (url.ToLower().Contains("hud.jpg") || url.ToLower().Contains("map.jpg") || url.ToLower().Contains("both.jpg")) |
|
{ |
|
string header = "HTTP/1.1 200 OK\r\nContent-Type: multipart/x-mixed-replace;boundary=APMPLANNER\r\n\r\n--APMPLANNER\r\n"; |
|
byte[] temp = asciiEncoding.GetBytes(header); |
|
stream.Write(temp, 0, temp.Length); |
|
|
|
while (client.Connected) |
|
{ |
|
System.Threading.Thread.Sleep(200); // 5hz |
|
byte[] data = null; |
|
|
|
if (url.ToLower().Contains("hud")) |
|
{ |
|
GCSViews.FlightData.myhud.streamjpgenable = true; |
|
data = GCSViews.FlightData.myhud.streamjpg.ToArray(); |
|
} |
|
else if (url.ToLower().Contains("map")) |
|
{ |
|
GCSViews.FlightData.mymap.streamjpgenable = true; |
|
data = GCSViews.FlightData.mymap.streamjpg.ToArray(); |
|
} |
|
else |
|
{ |
|
GCSViews.FlightData.mymap.streamjpgenable = true; |
|
GCSViews.FlightData.myhud.streamjpgenable = true; |
|
Image img1 = Image.FromStream(GCSViews.FlightData.myhud.streamjpg); |
|
Image img2 = Image.FromStream(GCSViews.FlightData.mymap.streamjpg); |
|
int bigger = img1.Height > img2.Height ? img1.Height : img2.Height; |
|
Image imgout = new Bitmap(img1.Width + img2.Width, bigger); |
|
|
|
Graphics grap = Graphics.FromImage(imgout); |
|
|
|
grap.DrawImageUnscaled(img1, 0, 0); |
|
grap.DrawImageUnscaled(img2, img1.Width, 0); |
|
|
|
MemoryStream streamjpg = new MemoryStream(); |
|
imgout.Save(streamjpg, System.Drawing.Imaging.ImageFormat.Jpeg); |
|
data = streamjpg.ToArray(); |
|
|
|
} |
|
|
|
header = "Content-Type: image/jpeg\r\nContent-Length: " + data.Length + "\r\n\r\n"; |
|
temp = asciiEncoding.GetBytes(header); |
|
stream.Write(temp, 0, temp.Length); |
|
|
|
stream.Write(data, 0, data.Length); |
|
|
|
header = "\r\n--APMPLANNER\r\n"; |
|
temp = asciiEncoding.GetBytes(header); |
|
stream.Write(temp, 0, temp.Length); |
|
|
|
} |
|
GCSViews.FlightData.mymap.streamjpgenable = false; |
|
GCSViews.FlightData.myhud.streamjpgenable = false; |
|
stream.Close(); |
|
|
|
} |
|
stream.Close(); |
|
} |
|
catch (Exception ee) |
|
{ |
|
log.Error("Failed mjpg ", ee); |
|
} |
|
} |
|
} |
|
|
|
private void TOOL_APMFirmware_SelectedIndexChanged(object sender, EventArgs e) |
|
{ |
|
MainV2.cs.firmware = (MainV2.Firmwares)Enum.Parse(typeof(MainV2.Firmwares), _connectionControl.TOOL_APMFirmware.Text); |
|
} |
|
|
|
private void MainV2_Resize(object sender, EventArgs e) |
|
{ |
|
log.Info("myview width " + MyView.Width + " height " + MyView.Height); |
|
log.Info("this width " + this.Width + " height " + this.Height); |
|
} |
|
|
|
private void MenuHelp_Click(object sender, EventArgs e) |
|
{ |
|
MyView.ShowScreen("Help"); |
|
} |
|
|
|
|
|
public static void updateCheckMain(ProgressReporterDialogue frmProgressReporter) |
|
{ |
|
var baseurl = ConfigurationManager.AppSettings["UpdateLocation"]; |
|
try |
|
{ |
|
bool update = updateCheck(frmProgressReporter, baseurl, ""); |
|
var process = new Process(); |
|
string exePath = Path.GetDirectoryName(Application.ExecutablePath); |
|
if (MONO) |
|
{ |
|
process.StartInfo.FileName = "mono"; |
|
process.StartInfo.Arguments = " \"" + exePath + Path.DirectorySeparatorChar + "Updater.exe\"" + "\"" + Application.ExecutablePath + "\""; |
|
} |
|
else |
|
{ |
|
process.StartInfo.FileName = exePath + Path.DirectorySeparatorChar + "Updater.exe"; |
|
process.StartInfo.Arguments = Application.ExecutablePath; |
|
} |
|
|
|
try |
|
{ |
|
foreach (string newupdater in Directory.GetFiles(exePath, "Updater.exe*.new")) |
|
{ |
|
File.Copy(newupdater, newupdater.Remove(newupdater.Length - 4), true); |
|
File.Delete(newupdater); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
log.Error("Exception during update", ex); |
|
} |
|
if (frmProgressReporter != null) |
|
frmProgressReporter.UpdateProgressAndStatus(-1, "Starting Updater"); |
|
log.Info("Starting new process: " + process.StartInfo.FileName + " with " + process.StartInfo.Arguments); |
|
process.Start(); |
|
log.Info("Quitting existing process"); |
|
try |
|
{ |
|
MainV2.instance.BeginInvoke((MethodInvoker)delegate() |
|
{ |
|
Application.Exit(); |
|
}); |
|
} |
|
catch |
|
{ |
|
Application.Exit(); |
|
} |
|
} |
|
catch (Exception ex) |
|
{ |
|
log.Error("Update Failed", ex); |
|
CustomMessageBox.Show("Update Failed " + ex.Message); |
|
} |
|
} |
|
|
|
private static void UpdateLabel(Label loadinglabel, string text) |
|
{ |
|
MainV2.instance.Invoke((MethodInvoker)delegate |
|
{ |
|
loadinglabel.Text = text; |
|
|
|
Application.DoEvents(); |
|
}); |
|
} |
|
|
|
private static void CheckForUpdate() |
|
{ |
|
var baseurl = ConfigurationManager.AppSettings["UpdateLocation"]; |
|
string path = Path.GetDirectoryName(Application.ExecutablePath); |
|
|
|
path = path + Path.DirectorySeparatorChar + "version.txt"; |
|
|
|
log.Debug(path); |
|
|
|
// Create a request using a URL that can receive a post. |
|
string requestUriString = baseurl + Path.GetFileName(path); |
|
log.Debug("Checking for update at: " + requestUriString); |
|
var webRequest = WebRequest.Create(requestUriString); |
|
webRequest.Timeout = 5000; |
|
|
|
// Set the Method property of the request to POST. |
|
webRequest.Method = "GET"; |
|
|
|
((HttpWebRequest)webRequest).IfModifiedSince = File.GetLastWriteTimeUtc(path); |
|
|
|
// Get the response. |
|
var response = webRequest.GetResponse(); |
|
// Display the status. |
|
log.Debug("Response status: " + ((HttpWebResponse)response).StatusDescription); |
|
// Get the stream containing content returned by the server. |
|
//dataStream = response.GetResponseStream(); |
|
// Open the stream using a StreamReader for easy access. |
|
|
|
bool updateFound = false; |
|
|
|
if (File.Exists(path)) |
|
{ |
|
var fi = new FileInfo(path); |
|
|
|
string LocalVersion = ""; |
|
string WebVersion = ""; |
|
|
|
if (File.Exists(path)) |
|
{ |
|
using (Stream fs = File.OpenRead(path)) |
|
{ |
|
using (StreamReader sr = new StreamReader(fs)) |
|
{ |
|
LocalVersion = sr.ReadLine(); |
|
sr.Close(); |
|
} |
|
fs.Close(); |
|
} |
|
} |
|
|
|
using (StreamReader sr = new StreamReader(response.GetResponseStream())) |
|
{ |
|
WebVersion = sr.ReadLine(); |
|
|
|
sr.Close(); |
|
} |
|
|
|
|
|
|
|
log.Info("New file Check: local " + LocalVersion + " vs Remote " + WebVersion); |
|
|
|
if (LocalVersion != WebVersion) |
|
{ |
|
updateFound = true; |
|
} |
|
} |
|
else |
|
{ |
|
updateFound = true; |
|
log.Info("File does not exist: Getting " + path); |
|
// get it |
|
} |
|
|
|
response.Close(); |
|
|
|
if (updateFound) |
|
{ |
|
var dr = CustomMessageBox.Show("Update Found\n\nDo you wish to update now?", "Update Now", MessageBoxButtons.YesNo); |
|
if (dr == DialogResult.Yes) |
|
{ |
|
DoUpdate(); |
|
} |
|
else |
|
{ |
|
return; |
|
} |
|
} |
|
} |
|
|
|
public static void DoUpdate() |
|
{ |
|
ProgressReporterDialogue frmProgressReporter = new ProgressReporterDialogue() |
|
{ |
|
Text = "Check for Updates", |
|
StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen |
|
}; |
|
|
|
ThemeManager.ApplyThemeTo(frmProgressReporter); |
|
|
|
frmProgressReporter.DoWork += new Controls.ProgressReporterDialogue.DoWorkEventHandler(DoUpdateWorker_DoWork); |
|
|
|
frmProgressReporter.UpdateProgressAndStatus(-1, "Checking for Updates"); |
|
|
|
frmProgressReporter.RunBackgroundOperationAsync(); |
|
} |
|
|
|
static void DoUpdateWorker_DoWork(object sender, Controls.ProgressWorkerEventArgs e) |
|
{ |
|
// TODO: Is this the right place? |
|
#region Fetch Parameter Meta Data |
|
|
|
var progressReporterDialogue = ((ProgressReporterDialogue)sender); |
|
progressReporterDialogue.UpdateProgressAndStatus(-1, "Getting Updated Parameters"); |
|
|
|
try |
|
{ |
|
ParameterMetaDataParser.GetParameterInformation(); |
|
} |
|
catch (Exception ex) { log.Error(ex.ToString()); CustomMessageBox.Show("Error getting Parameter Information"); } |
|
|
|
#endregion Fetch Parameter Meta Data |
|
|
|
progressReporterDialogue.UpdateProgressAndStatus(-1, "Getting Base URL"); |
|
// check for updates |
|
if (Debugger.IsAttached) |
|
{ |
|
log.Info("Skipping update test as it appears we are debugging"); |
|
} |
|
else |
|
{ |
|
MainV2.updateCheckMain(progressReporterDialogue); |
|
} |
|
} |
|
|
|
private static bool updateCheck(ProgressReporterDialogue frmProgressReporter, string baseurl, string subdir) |
|
{ |
|
bool update = false; |
|
List<string> files = new List<string>(); |
|
|
|
// Create a request using a URL that can receive a post. |
|
log.Info(baseurl); |
|
WebRequest request = WebRequest.Create(baseurl); |
|
request.Timeout = 10000; |
|
// Set the Method property of the request to POST. |
|
request.Method = "GET"; |
|
// Get the request stream. |
|
Stream dataStream; //= request.GetRequestStream(); |
|
// Get the response. |
|
WebResponse response = request.GetResponse(); |
|
// Display the status. |
|
log.Info(((HttpWebResponse)response).StatusDescription); |
|
// Get the stream containing content returned by the server. |
|
dataStream = response.GetResponseStream(); |
|
// Open the stream using a StreamReader for easy access. |
|
StreamReader reader = new StreamReader(dataStream); |
|
// Read the content. |
|
string responseFromServer = reader.ReadToEnd(); |
|
// Display the content. |
|
Regex regex = new Regex("href=\"([^\"]+)\"", RegexOptions.IgnoreCase); |
|
if (regex.IsMatch(responseFromServer)) |
|
{ |
|
MatchCollection matchs = regex.Matches(responseFromServer); |
|
for (int i = 0; i < matchs.Count; i++) |
|
{ |
|
if (matchs[i].Groups[1].Value.ToString().Contains("..")) |
|
continue; |
|
if (matchs[i].Groups[1].Value.ToString().Contains("http")) |
|
continue; |
|
files.Add(System.Web.HttpUtility.UrlDecode(matchs[i].Groups[1].Value.ToString())); |
|
} |
|
} |
|
|
|
//Console.WriteLine(responseFromServer); |
|
// Clean up the streams. |
|
reader.Close(); |
|
dataStream.Close(); |
|
response.Close(); |
|
|
|
string dir = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + subdir; |
|
if (!Directory.Exists(dir)) |
|
Directory.CreateDirectory(dir); |
|
foreach (string file in files) |
|
{ |
|
if (frmProgressReporter.doWorkArgs.CancelRequested) |
|
{ |
|
frmProgressReporter.doWorkArgs.CancelAcknowledged = true; |
|
throw new Exception("Cancel"); |
|
} |
|
|
|
if (file.Equals("/")) |
|
{ |
|
continue; |
|
} |
|
if (file.EndsWith("/")) |
|
{ |
|
update = updateCheck(frmProgressReporter, baseurl + file, subdir.Replace('/', Path.DirectorySeparatorChar) + file) && update; |
|
continue; |
|
} |
|
if (frmProgressReporter != null) |
|
frmProgressReporter.UpdateProgressAndStatus(-1, "Checking " + file); |
|
|
|
string path = Path.GetDirectoryName(Application.ExecutablePath) + Path.DirectorySeparatorChar + subdir + file; |
|
|
|
|
|
// Create a request using a URL that can receive a post. |
|
request = WebRequest.Create(baseurl + file); |
|
log.Info(baseurl + file + " "); |
|
// Set the Method property of the request to POST. |
|
request.Method = "HEAD"; |
|
|
|
((HttpWebRequest)request).IfModifiedSince = File.GetLastWriteTimeUtc(path); |
|
|
|
// Get the response. |
|
response = request.GetResponse(); |
|
// Display the status. |
|
log.Info(((HttpWebResponse)response).StatusDescription); |
|
// Get the stream containing content returned by the server. |
|
//dataStream = response.GetResponseStream(); |
|
// Open the stream using a StreamReader for easy access. |
|
|
|
bool updateThisFile = false; |
|
|
|
if (File.Exists(path)) |
|
{ |
|
FileInfo fi = new FileInfo(path); |
|
|
|
//log.Info(response.Headers[HttpResponseHeader.ETag]); |
|
string CurrentEtag = ""; |
|
|
|
if (File.Exists(path + ".etag")) |
|
{ |
|
using (Stream fs = File.OpenRead(path + ".etag")) |
|
{ |
|
using (StreamReader sr = new StreamReader(fs)) |
|
{ |
|
CurrentEtag = sr.ReadLine(); |
|
sr.Close(); |
|
} |
|
fs.Close(); |
|
} |
|
} |
|
|
|
log.Debug("New file Check: " + fi.Length + " vs " + response.ContentLength + " " + response.Headers[HttpResponseHeader.ETag] + " vs " + CurrentEtag); |
|
|
|
if (fi.Length != response.ContentLength || response.Headers[HttpResponseHeader.ETag] != CurrentEtag) |
|
{ |
|
using (StreamWriter sw = new StreamWriter(path + ".etag.new")) |
|
{ |
|
sw.WriteLine(response.Headers[HttpResponseHeader.ETag]); |
|
sw.Close(); |
|
} |
|
updateThisFile = true; |
|
log.Info("NEW FILE " + file); |
|
} |
|
} |
|
else |
|
{ |
|
updateThisFile = true; |
|
log.Info("NEW FILE " + file); |
|
// get it |
|
} |
|
|
|
reader.Close(); |
|
//dataStream.Close(); |
|
response.Close(); |
|
|
|
if (updateThisFile) |
|
{ |
|
if (!update) |
|
{ |
|
//DialogResult dr = MessageBox.Show("Update Found\n\nDo you wish to update now?", "Update Now", MessageBoxButtons.YesNo); |
|
//if (dr == DialogResult.Yes) |
|
{ |
|
update = true; |
|
} |
|
//else |
|
{ |
|
// return; |
|
} |
|
} |
|
if (frmProgressReporter != null) |
|
frmProgressReporter.UpdateProgressAndStatus(-1, "Getting " + file); |
|
|
|
// from head |
|
long bytes = response.ContentLength; |
|
|
|
// Create a request using a URL that can receive a post. |
|
request = HttpWebRequest.Create(baseurl + file); |
|
// Set the Method property of the request to POST. |
|
request.Method = "GET"; |
|
|
|
((HttpWebRequest)request).AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate; |
|
|
|
request.Headers.Add("Accept-Encoding", "gzip,deflate"); |
|
|
|
// Get the response. |
|
response = request.GetResponse(); |
|
// Display the status. |
|
log.Debug(((HttpWebResponse)response).StatusDescription); |
|
// Get the stream containing content returned by the server. |
|
dataStream = response.GetResponseStream(); |
|
|
|
long contlen = bytes; |
|
|
|
byte[] buf1 = new byte[1024]; |
|
|
|
FileStream fs = new FileStream(path + ".new", FileMode.Create); // |
|
|
|
DateTime dt = DateTime.Now; |
|
|
|
dataStream.ReadTimeout = 30000; |
|
|
|
while (dataStream.CanRead) |
|
{ |
|
try |
|
{ |
|
if (dt.Second != DateTime.Now.Second) |
|
{ |
|
if (frmProgressReporter != null) |
|
frmProgressReporter.UpdateProgressAndStatus((int)(((double)(contlen - bytes) / (double)contlen) * 100), "Getting " + file + ": " + (((double)(contlen - bytes) / (double)contlen) * 100).ToString("0.0") + "%"); //+ Math.Abs(bytes) + " bytes"); |
|
dt = DateTime.Now; |
|
} |
|
} |
|
catch { } |
|
log.Debug(file + " " + bytes); |
|
int len = dataStream.Read(buf1, 0, 1024); |
|
if (len == 0) |
|
break; |
|
bytes -= len; |
|
fs.Write(buf1, 0, len); |
|
} |
|
|
|
fs.Close(); |
|
dataStream.Close(); |
|
response.Close(); |
|
} |
|
|
|
|
|
} |
|
|
|
//P.StartInfo.CreateNoWindow = true; |
|
//P.StartInfo.RedirectStandardOutput = true; |
|
return update; |
|
|
|
|
|
} |
|
|
|
|
|
/// <summary> |
|
/// trying to replicate google code etags....... this doesnt work. |
|
/// </summary> |
|
/// <param name="fileName"></param> |
|
/// <param name="modifyDate"></param> |
|
/// <returns></returns> |
|
private string GetFileETag(string fileName, DateTime modifyDate) |
|
{ |
|
|
|
string FileString; |
|
|
|
System.Text.Encoder StringEncoder; |
|
|
|
byte[] StringBytes; |
|
|
|
MD5CryptoServiceProvider MD5Enc; |
|
|
|
//use file name and modify date as the unique identifier |
|
|
|
FileString = fileName + modifyDate.ToString("d", CultureInfo.InvariantCulture); |
|
|
|
//get string bytes |
|
|
|
StringEncoder = Encoding.UTF8.GetEncoder(); |
|
|
|
StringBytes = new byte[StringEncoder.GetByteCount(FileString.ToCharArray(), 0, FileString.Length, true)]; |
|
|
|
StringEncoder.GetBytes(FileString.ToCharArray(), 0, FileString.Length, StringBytes, 0, true); |
|
|
|
//hash string using MD5 and return the hex-encoded hash |
|
|
|
MD5Enc = new MD5CryptoServiceProvider(); |
|
|
|
byte[] hash = MD5Enc.ComputeHash((Stream)File.OpenRead(fileName)); |
|
|
|
return "\"" + BitConverter.ToString(hash).Replace("-", string.Empty) + "\""; |
|
|
|
} |
|
|
|
/// <summary> |
|
/// keyboard shortcuts override |
|
/// </summary> |
|
/// <param name="msg"></param> |
|
/// <param name="keyData"></param> |
|
/// <returns></returns> |
|
protected override bool ProcessCmdKey(ref Message msg, Keys keyData) |
|
{ |
|
if (keyData == (Keys.Control | Keys.F)) // temp |
|
{ |
|
Form frm = new temp(); |
|
ThemeManager.ApplyThemeTo(frm); |
|
frm.Show(); |
|
return true; |
|
} |
|
if (keyData == (Keys.Control | Keys.S)) // screenshot |
|
{ |
|
ScreenShot(); |
|
return true; |
|
} |
|
if (keyData == (Keys.Control | Keys.G)) // nmea out |
|
{ |
|
Form frm = new SerialOutput(); |
|
ThemeManager.ApplyThemeTo(frm); |
|
frm.Show(); |
|
return true; |
|
} |
|
if (keyData == (Keys.Control | Keys.A)) // 3dr radio |
|
{ |
|
Form temp = new Form(); |
|
Control frm = new _3DRradio(); |
|
temp.Controls.Add(frm); |
|
temp.Size = frm.Size; |
|
frm.Dock = DockStyle.Fill; |
|
ThemeManager.ApplyThemeTo(temp); |
|
temp.Show(); |
|
return true; |
|
} |
|
if (keyData == (Keys.Control | Keys.W)) // test ac config |
|
{ |
|
|
|
Controls.ConfigPanel cfg = new Controls.ConfigPanel(); |
|
|
|
cfg.LoadXML("ArduCopterConfig.xml"); |
|
|
|
//cfg.ShowDialog(); |
|
|
|
return true; |
|
} |
|
if (keyData == (Keys.Control | Keys.T)) // for override connect |
|
{ |
|
try |
|
{ |
|
MainV2.comPort.Open(false); |
|
} |
|
catch (Exception ex) { CustomMessageBox.Show(ex.ToString()); } |
|
return true; |
|
} |
|
if (keyData == (Keys.Control | Keys.Y)) // for ryan beall |
|
{ |
|
#if MAVLINK10 |
|
// write |
|
MainV2.comPort.doCommand(MAVLink.MAV_CMD.PREFLIGHT_STORAGE, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); |
|
//read |
|
///////MainV2.comPort.doCommand(MAVLink09.MAV_CMD.PREFLIGHT_STORAGE, 1.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f, 0.0f); |
|
#else |
|
MainV2.comPort.doAction(MAVLink.MAV_ACTION.MAV_ACTION_STORAGE_WRITE); |
|
#endif |
|
CustomMessageBox.Show("Done MAV_ACTION_STORAGE_WRITE"); |
|
return true; |
|
} |
|
if (keyData == (Keys.Control | Keys.J)) // for jani |
|
{ |
|
string data = "!!"; |
|
Common.InputBox("inject", "enter data to be written", ref data); |
|
MainV2.comPort.Write(data + "\r"); |
|
return true; |
|
} |
|
return base.ProcessCmdKey(ref msg, keyData); |
|
} |
|
|
|
public void changelanguage(CultureInfo ci) |
|
{ |
|
if (ci != null && !Thread.CurrentThread.CurrentUICulture.Equals(ci)) |
|
{ |
|
Thread.CurrentThread.CurrentUICulture = ci; |
|
config["language"] = ci.Name; |
|
//System.Threading.Thread.CurrentThread.CurrentCulture = ci; |
|
|
|
HashSet<Control> views = new HashSet<Control> { FlightData, FlightPlanner, Simulation }; |
|
|
|
foreach (Control view in MyView.Controls) |
|
views.Add(view); |
|
|
|
foreach (Control view in views) |
|
{ |
|
if (view != null) |
|
{ |
|
ComponentResourceManager rm = new ComponentResourceManager(view.GetType()); |
|
foreach (Control ctrl in view.Controls) |
|
rm.ApplyResource(ctrl); |
|
rm.ApplyResources(view, "$this"); |
|
} |
|
} |
|
} |
|
} |
|
|
|
private void MainV2_FormClosing(object sender, FormClosingEventArgs e) |
|
{ |
|
config["MainHeight"] = this.Height; |
|
config["MainWidth"] = this.Width; |
|
config["MainMaximised"] = this.WindowState.ToString(); |
|
|
|
config["MainLocX"] = this.Location.X.ToString(); |
|
config["MainLocY"] = this.Location.Y.ToString(); |
|
|
|
try |
|
{ |
|
comPort.logreadmode = false; |
|
if (comPort.logfile != null) |
|
comPort.logfile.Close(); |
|
|
|
if (comPort.rawlogfile != null) |
|
comPort.rawlogfile.Close(); |
|
|
|
comPort.logfile = null; |
|
comPort.rawlogfile = null; |
|
} |
|
catch { } |
|
|
|
} |
|
|
|
public static string getConfig(string paramname) |
|
{ |
|
if (config[paramname] != null) |
|
return config[paramname].ToString(); |
|
return ""; |
|
} |
|
|
|
public void ChangeUnits() |
|
{ |
|
try |
|
{ |
|
// dist |
|
if (MainV2.config["distunits"] != null) |
|
{ |
|
switch ((Common.distances)Enum.Parse(typeof(Common.distances), MainV2.config["distunits"].ToString())) |
|
{ |
|
case Common.distances.Meters: |
|
MainV2.cs.multiplierdist = 1; |
|
break; |
|
case Common.distances.Feet: |
|
MainV2.cs.multiplierdist = 3.2808399f; |
|
break; |
|
} |
|
} |
|
|
|
// speed |
|
if (MainV2.config["speedunits"] != null) |
|
{ |
|
switch ((Common.speeds)Enum.Parse(typeof(Common.speeds), MainV2.config["speedunits"].ToString())) |
|
{ |
|
case Common.speeds.ms: |
|
MainV2.cs.multiplierspeed = 1; |
|
break; |
|
case Common.speeds.fps: |
|
MainV2.cs.multiplierdist = 3.2808399f; |
|
break; |
|
case Common.speeds.kph: |
|
MainV2.cs.multiplierspeed = 3.6f; |
|
break; |
|
case Common.speeds.mph: |
|
MainV2.cs.multiplierspeed = 2.23693629f; |
|
break; |
|
case Common.speeds.knots: |
|
MainV2.cs.multiplierspeed = 1.94384449f; |
|
break; |
|
} |
|
} |
|
} |
|
catch { } |
|
|
|
} |
|
|
|
private void CMB_baudrate_TextChanged(object sender, EventArgs e) |
|
{ |
|
var sb = new StringBuilder(); |
|
int baud = 0; |
|
for (int i = 0; i < _connectionControl.CMB_baudrate.Text.Length; i++) |
|
if (char.IsDigit(_connectionControl.CMB_baudrate.Text[i])) |
|
{ |
|
sb.Append(_connectionControl.CMB_baudrate.Text[i]); |
|
baud = baud * 10 + _connectionControl.CMB_baudrate.Text[i] - '0'; |
|
} |
|
if (_connectionControl.CMB_baudrate.Text != sb.ToString()) |
|
{ |
|
_connectionControl.CMB_baudrate.Text = sb.ToString(); |
|
} |
|
try |
|
{ |
|
if (baud > 0 && comPort.BaseStream.BaudRate != baud) |
|
comPort.BaseStream.BaudRate = baud; |
|
} |
|
catch (Exception) |
|
{ |
|
} |
|
} |
|
|
|
private void CMB_serialport_Enter(object sender, EventArgs e) |
|
{ |
|
CMB_serialport_Click(sender, e); |
|
} |
|
|
|
private void MenuConnect_MouseHover(object sender, EventArgs e) |
|
{ |
|
|
|
} |
|
} |
|
} |