Subversion Repositories Projects

Compare Revisions

Ignore whitespace Rev 2535 → Rev 2536

/MKLiveView/v1.0/Source/MKLiveView/MainWindow.xaml.cs
0,0 → 1,6239
///============================================================================
/// MKLiveView
/// Copyright © 2016 Steph
///
///This file is part of MKLiveView.
///
///MKLiveView 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.
///
///MKLiveView 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 cssRcon. If not, see <http://www.gnu.org/licenses/>.
///
///============================================================================
///Credits:
/// radioman (http://www.codeplex.com/site/users/view/radioman)
/// for his really GreatMaps! (http://greatmaps.codeplex.com/)
///
/// I made some changes to the source, so You need all files from this project here in order to compile and run
///
/// JOHN C. MACDONALD at Ira A. Fulton College of Engineering and Technology
/// for his MIKROKOPTER SERIAL CONTROL TUTORIAL (http://hdl.lib.byu.edu/1877/2747)
/// and the sourcecode (http://hdl.lib.byu.edu/1877/2748)
/// By his work I finally managed to get the communication with the Mikrokopter controllers to run
/// Some of his code was used in this programm like the SimpelSerialPort class (with lots of changes)
/// and the FilghtControllerMessage class
///
///============================================================================
/// DISCLAIMER
/// ===========
///
/// I created this software with my best knowledge and belief.
///
/// IN NO EVENT, UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING,
/// SHALL I, OR ANY PERSON BE LIABLE FOR ANY LOSS, EXPENSE OR DAMAGE,
/// OF ANY TYPE OR NATURE ARISING OUT OF THE USE OF,
/// OR INABILITY TO USE THIS SOFTWARE OR PROGRAM,
/// INCLUDING, BUT NOT LIMITED TO, CLAIMS, SUITS OR CAUSES OF ACTION
/// INVOLVING ALLEGED INFRINGEMENT OF COPYRIGHTS,
/// PATENTS, TRADEMARKS, TRADE SECRETS, OR UNFAIR COMPETITION.
///
/// This means: use it & have fun (but @ Your own risk...)
/// ===========================================================================
using GMap.NET;
using GMap.NET.MapProviders;
using GMap.NET.WindowsPresentation;
using MKLiveView.GMapCustomMarkers;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Linq.Expressions;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Interop;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Threading;
using System.Globalization;
using System.Xml;
using System.Xml.Linq;
using Touchless.Vision.Camera;
 
namespace MKLiveView
{
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
#region declarations
object lockObj = new Object();
MediaPlayer.MediaPlayer mediaPlayer = new MediaPlayer.MediaPlayer();
 
GMapMarker copter;
GMapMarker home;
PointLatLng start;
PointLatLng end;
PointLatLng pHome;
GMapRoute mRouteWP;
GMapMarker wpActiveMarker;
List<PointLatLng> wpList = new List<PointLatLng>();
List<int> wpOffset = new List<int>();
Circle cWPBound = new Circle();
double dWPMaxRange = 0;
 
#region NC-Errors
String[] NC_Error = new string[44]
{
"No Error",
"FC not compatible",
"MK3Mag not compatible",
"no FC communication",
"no compass communication",
"no GPS communication",
"bad compass value",
"RC Signal lost",
"FC spi rx error",
"ERR: no NC communication",
"ERR: FC Nick Gyro",
"ERR: FC Roll Gyro",
"ERR: FC Yaw Gyro",
"ERR: FC Nick ACC",
"ERR: FC Roll ACC",
"ERR: FC Z-ACC",
"ERR: Pressure sensor",
"ERR: FC I2C",
"ERR: Bl Missing",
"Mixer Error",
"FC: Carefree Error",
"ERR: GPS lost",
"ERR: Magnet Error",
"Motor restart",
"BL Limitation",
"Waypoint range",
"ERR:No SD-Card",
"ERR:SD Logging aborted",
"ERR:Flying range!",
"ERR:Max Altitude",
"No GPS Fix",
"compass not calibrated",
"ERR:BL selftest",
"no ext. compass",
"compass sensor",
"FAILSAFE pos.!",
"ERR:Redundancy",
"Redundancy test",
"GPS Update rate",
"ERR:Canbus",
"ERR: 5V RC-Supply",
"ERR:Power-Supply",
"ACC not calibr.",
"ERR:Parachute!"
};
String[] NC_Error_Link = new string[44]
{
"",
"http://wiki.mikrokopter.de/ErrorCodes#A1_.22FC_not_compatible_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A2_.22MK3Mag_not_compatible_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A3_.22no_FC_communication_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A4_.22no_compass_communication_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A5_.22no_GPS_communication_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A6_.22bad_compass_value.22",
"http://wiki.mikrokopter.de/ErrorCodes#A7_.22RC_Signal_lost_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A8_.22FC_spi_rx_error_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A9:_.22ERR:_no_NC_communication.22",
"http://wiki.mikrokopter.de/ErrorCodes#A10_.22ERR:_FC_Nick_Gyro.22",
"http://wiki.mikrokopter.de/ErrorCodes#A11_.22ERR:_FC_Roll_Gyro.22",
"http://wiki.mikrokopter.de/ErrorCodes#A12_.22ERR:_FC_Yaw_Gyro.22",
"http://wiki.mikrokopter.de/ErrorCodes#A13_.22ERR:_FC_Nick_ACC.22",
"http://wiki.mikrokopter.de/ErrorCodes#A14_.22ERR:_FC_Roll_ACC.22",
"http://wiki.mikrokopter.de/ErrorCodes#A15_.22ERR:_FC_Z-ACC.22",
"http://wiki.mikrokopter.de/ErrorCodes#A16_.22ERR:_Pressure_sensor.22",
"http://wiki.mikrokopter.de/ErrorCodes#A17_.22ERR:_FC_I2C.22",
"http://wiki.mikrokopter.de/ErrorCodes#A18_.22ERR:_Bl_Missing.22",
"http://wiki.mikrokopter.de/ErrorCodes#A19_.22Mixer_Error.22",
"http://wiki.mikrokopter.de/ErrorCodes#A20_.22FC:_Carefree_Error.22",
"http://wiki.mikrokopter.de/ErrorCodes#A21_.22ERR:_GPS_lost.22",
"http://wiki.mikrokopter.de/ErrorCodes#A22_.22ERR:_Magnet_Error.22",
"http://wiki.mikrokopter.de/ErrorCodes#A23_.22Motor_restart.22",
"http://wiki.mikrokopter.de/ErrorCodes#A24_.22BL_Limitation.22",
"http://wiki.mikrokopter.de/ErrorCodes#A25_.22Waypoint_range.22",
"http://wiki.mikrokopter.de/ErrorCodes#A26_.22ERR:No_SD-Card.22",
"http://wiki.mikrokopter.de/ErrorCodes#A27_.22ERR:SD_Logging_aborted.22",
"http://wiki.mikrokopter.de/ErrorCodes#A28_.22ERR:Flying_range.21.22",
"http://wiki.mikrokopter.de/ErrorCodes#A29_.22ERR:Max_Altitude.22",
"http://wiki.mikrokopter.de/ErrorCodes#A30_.22No_GPS_Fix.22",
"http://wiki.mikrokopter.de/ErrorCodes#A31_.22compass_not_calibrated.22",
"http://wiki.mikrokopter.de/ErrorCodes#A32_.22ERR:BL_selftest.22",
"http://wiki.mikrokopter.de/ErrorCodes#A33_.22no_ext._compass.22",
"http://wiki.mikrokopter.de/ErrorCodes#A34_.22compass_sensor.22",
"http://wiki.mikrokopter.de/ErrorCodes#A35_.22FAILSAFE_pos..21__.22",
"http://wiki.mikrokopter.de/ErrorCodes#A36_.22ERR:Redundancy__.22",
"http://wiki.mikrokopter.de/ErrorCodes#A37_.22Redundancy_test_.22",
"http://wiki.mikrokopter.de/ErrorCodes#A38_.22GPS_Update_rate.22",
"http://wiki.mikrokopter.de/ErrorCodes#A39_.22ERR:Canbus.22",
"http://wiki.mikrokopter.de/ErrorCodes#A40_.22ERR:_5V_RC-Supply.22",
"http://wiki.mikrokopter.de/ErrorCodes#A41_.22ERR:Power-Supply.22",
"http://wiki.mikrokopter.de/ErrorCodes#A42_.22ACC_not_calibr..22",
"http://wiki.mikrokopter.de/ErrorCodes#A43_.22ERR:Parachute.21.22"
};
 
#endregion NC-Errors
[FlagsAttribute]
enum NC_HWError0 : short
{
None = 0,
SPI_RX = 1,
COMPASS_RX = 2,
FC_INCOMPATIBLE = 4,
COMPASS_INCOMPATIBLE = 8,
GPS_RX = 16,
COMPASS_VALUE = 32
};
[FlagsAttribute]
enum FC_HWError0 : short
{
None = 0,
GYRO_NICK = 1,
GYRO_ROLL = 2,
GYRO_YAW = 4,
ACC_NICK = 8,
ACC_ROLL = 16,
ACC_TOP = 32,
PRESSURE = 64,
CAREFREE = 128
};
[FlagsAttribute]
enum FC_HWError1 : short
{
None = 0,
I2C = 1,
BL_MISSING = 2,
SPI_RX = 4,
PPM = 8,
MIXER = 16,
RC_VOLTAGE = 32,
ACC_NOT_CAL = 64,
RES3 = 128
};
public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error };
// Various colors for logging info
private Color[] LogMsgTypeColor = { Color.FromArgb(255, 43, 145, 175), Colors.Green, Colors.Black, Colors.Orange, Colors.Red };
 
bool _bCBInit = true;
bool _init = true;
bool check_HWError = false;
 
string filePath = Directory.GetCurrentDirectory();
bool bReadContinously = false;
bool _debugDataAutorefresh = true;
bool _navCtrlDataAutorefresh = true;
bool _blctrlDataAutorefresh = true;
bool _OSDAutorefresh = true;
bool _bErrorLog = false;
bool _bConnErr = false;
bool _bFollowCopter = true;
bool _bGPXLog = false;
bool _Simulate = false;
 
bool _bSaveWinStateNormal = true;
bool _bSaveWinStateFull = true;
 
double scaleNormalAll = 1;
double scaleNormalTopBar = 1;
double scaleNormalMotors = 1;
double scaleNormalOSD = 1;
double scaleNormalLOG = 1;
double scaleNormalHorizon = 1;
 
double scaleFullAll = 1;
double scaleFullTopBar = 1;
double scaleFullMotors = 1;
double scaleFullOSD = 1;
double scaleFullLOG = 1;
double scaleFullHorizon = 1;
 
int _iCtrlAct = 0;
int iOSDPage = 0;
int iOSDMax = 0;
int _iLifeCounter = 0;
int crcError = 0;
 
string[] _voiceLanguage = new string[] { "EN","DE"};
int _iVoiceIndex = 0;
 
bool _bSatFix = false;
Storyboard stbSatFixLostAnim;
bool _bAnimSatFixActive = false;
bool _bVoiceSatFixActive = false;
bool _bVoiceSatFixPlay = true;
int _iSatsLast = 0;
int _iSatsJitter = 0;
 
bool _bMagneticFieldOK = false;
Storyboard stbMagneticFieldAnim;
bool _bAnimMagneticFieldActive = false;
bool _bVoiceMagneticFieldActive = false;
bool _bVoiceMagneticFieldPlay = true;
int _iMagneticFieldLast = 0;
int _iMagneticFieldJitter = 0;
 
int _iThresholdBLCTRLTempWarn = 80;
Storyboard stbBLCTRLTempAnim;
bool _bAnimBLCTRLTempActive = false;
bool _bVoiceBLCTRLTempActive = false;
bool _bVoiceBLCTRLTempPlay = true;
int[] _iBLCTRLTempLast = new int[12];
int[] _iBLCTRLTempJitter = new int[12];
 
bool _bRCLevelOK = false;
Storyboard stbRCLevelAnim;
bool _bAnimRCLevelActive = false;
bool _bVoiceRCLevelActive = false;
bool _bVoiceRCLevelPlay = true;
int _iRCLevelLast = 0;
int _iRCLevelJitter = 0;
 
int _iMotors = 4;
int _LipoCells = 3;
bool _bLiPoAutoDetect = true;
 
double _dLipoVMax = 16.88;
double _dLipoVMin = 12;
double _dThresholdVoltageWarn = 0;
double _dThresholdVoltageCrit = 0;
Storyboard stbVoltageCritAnim;
bool _bCritAnimVoltActive = false;
bool _bCritVoiceVoltActive = false;
bool _bWarnVoiceVoltActive = false;
bool _bVoiceVoltPlay = true;
double _dVoltLast = 0;
int _iVoltJitter = 0;
 
double _dThresholdDistanceWarn = 100;
Storyboard stbDistanceWarnAnim;
bool _bAnimDistanceActive = false;
bool _bVoiceDistanceActive = false;
bool _bVoiceDistancePlay = true;
double _dDistanceLast = 0;
int _iDistanceJitter = 0;
 
double _dThresholdDistanceMax = 1000;
int _iThresholdRC = 160;
int _iThresholdMagField = 15;
 
bool _bAutoHome = true;
bool _bFirstSatFix = false;
int _iFirstSatFix = 0;
 
double _dTopHeight = 36;
 
int[] serChan = new int[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int[] serChan_sub = new int[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
string[] serChanTitle = new string[12];
 
string[] sAnalogLabel = new string[32];
string[] sAnalogData = new string[32];
int[] iAnalogData = new int[32];
 
int[] iTimings = new int[] { 100, 150, 200, 250, 300, 350, 400, 450, 500, 550, 600, 650, 700, 750, 800, 850, 900, 950, 1000, 1100, 1200, 1300, 1400, 1500, 1600, 1700, 1800, 1900, 2000 };
int[] iMotors = new int[] { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
string[] sLiPoCells = new string[] { "3s", "4s", "5s", "6s" };
/// <summary>
/// interval for sending debugdata (multiplied by 10ms)
/// </summary>
byte debugInterval = 10; //(=> 100ms)
/// <summary>
/// interval for sending BL-CTRL status (multiplied by 10ms)
/// </summary>
byte blctrlInterval = 75;
/// <summary>
/// interval for sending NAV-CTRL status (multiplied by 10ms)
/// </summary>
byte navctrlInterval = 20;
/// <summary>
/// interval for sending OSD page update (multiplied by 10ms)
/// </summary>
byte OSDInterval = 85;
/// <summary>
/// datatable for the debug data array - displayed on settings tabpage in datagridview
/// </summary>
DataTable dtAnalog = new DataTable();
/// <summary>
/// datatable for motordata (current,temp)
/// </summary>
DataTable dtMotors = new DataTable();
 
DataTable dtWaypoints = new DataTable();
static volatile int _iWPCount = -1;
static volatile int _iWPIndex = -1;
int _iWPTimeout = 1000;
bool _bGetWP = false;
bool _bShowWPRoute = true;
bool _bAutoWPEdit = true;
static volatile bool _bGetWPCount = false;
DataTable dtGPX = new DataTable();
DataRow drGPX;
bool _bAirborne = false;
int _wpIndex = -1, _wpCount = 0, _wpEdit = -1;
 
string _wpDefPrefix = "P";
int _wpDefAltitude = 20;
int _wpDefHeading = 0;
int _wpDefCBoxHeading = 0;
int _wpDefSpeed = 10;
int _wpDefCBoxSpeed = 0;
int _wpDefClimb = 10;
int _wpDefCBoxClimb = 0;
int _wpDefRadius = 5;
int _wpDefHoldtime = 5;
int _wpDefAutotrig = 0;
int _wpDefCamangle = 0;
int _wpDefCBoxCamangle = 0;
int _wpDefOut1 = 0;
 
bool _wpAddCopterHeight = true;
bool _wpAddCopterHeading = true;
DispatcherTimer timer = new DispatcherTimer();
DispatcherTimer camTimer = new DispatcherTimer();
BitmapSource _camImageSource;
Storyboard stbCamActiveAnim;
bool _bCamAnim;
/// <summary>
/// stuff for enabeling touch zoom for the map
/// </summary>
Point pTouch1 = new Point(0, 0), pTouch2 = new Point(0, 0);
int iFirstStylusID = -1;
 
public string connectButtonText
{
get
{
return bReadContinously ? "stop polling data" + System.Environment.NewLine + "from copter" : "start polling data" + System.Environment.NewLine + "from copter";
}
}
 
WinState winState = new WinState();
 
#endregion declarations
public MainWindow()
{
String path = Environment.ExpandEnvironmentVariables("%SystemRoot%") + "\\System32\\VCRUNTIME140.DLL";
if (!File.Exists(path))
{
MessageBoxResult dr = MessageBox.Show("Visual C++ Redistributable for Visual Studio 2015 seems not to be installed..." +
Environment.NewLine + "Please download the file for x86 (32bit) @ https://www.microsoft.com/de-de/download/details.aspx?id=48145" +
Environment.NewLine + Environment.NewLine + "Do You want me to take You there, now?", "Visual C++ Redistributable for Visual Studio 2015 missing ...",
MessageBoxButton.YesNo,
MessageBoxImage.Stop,MessageBoxResult.No, MessageBoxOptions.DefaultDesktopOnly);
 
if (dr == MessageBoxResult.Yes)
System.Diagnostics.Process.Start("https://www.microsoft.com/de-de/download/details.aspx?id=48145");
 
Application.Current.Shutdown();
}
InitializeComponent();
_initForm();
_dataTablesInit();
_setupMap();
_init = false;
timer.Tick += new EventHandler(timerEvent);
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
camTimer.Tick += new EventHandler(camTimer_Tick);
camTimer.Interval = new TimeSpan(0, 0, 0, 0, 5);
// camTimer.Start();
}
 
#region init
void _initForm()
{
_readIni();
if (_bSaveWinStateNormal)
_setScaleSliders(false);
cBoxTimingsDebug.ItemsSource =
cBoxTimingsNav.ItemsSource =
cBoxTimingsBl.ItemsSource =
cBoxTimingsOSD.ItemsSource =
iTimings;
cBoxLiPoCells.ItemsSource = sLiPoCells;
cBoxLiPoCells.SelectedItem = _LipoCells.ToString() + "s";
_LipoMinMax();
sliderThresholdVoltageWarn.Value = _dThresholdVoltageWarn;
sliderThresholdVoltageCrit.Value = _dThresholdVoltageCrit;
checkBoxThresholdVoltageVoice.IsChecked = _bVoiceVoltPlay;
checkBoxSatfixLost.IsChecked = _bVoiceSatFixPlay;
checkBoxMagneticField.IsChecked = _bVoiceMagneticFieldPlay;
checkBoxThresholdDistanceVoice.IsChecked = _bVoiceDistancePlay;
sliderThresholdDistanceWarn.Value = _dThresholdDistanceWarn;
checkBoxRClevel.IsChecked = _bVoiceRCLevelPlay;
sliderThresholdDistanceWarn.Maximum = _dThresholdDistanceMax;
sliderThresholdBLCtrlTempWarn.Value = _iThresholdBLCTRLTempWarn;
checkBoxBLCtrlTempVoice.IsChecked = _bVoiceBLCTRLTempPlay;
comboBoxVoiceLanguage.SelectedIndex = _iVoiceIndex;
 
cBoxMotors.ItemsSource = iMotors;
cBoxMotors.SelectedItem = _iMotors;
 
serialPortCtrl.PortClosed += serialPortCtrl_PortClosed;
serialPortCtrl.PortOpened += serialPortCtrl_PortOpened;
serialPortCtrl.DataReceived += processMessage;
 
chkbAutoBL.IsChecked = _blctrlDataAutorefresh;
chkbAutoDbg.IsChecked = _debugDataAutorefresh;
chkbAutoNav.IsChecked = _navCtrlDataAutorefresh;
chkbAutoOSD.IsChecked = _OSDAutorefresh;
chkbAutoLiPoDetect.IsChecked = _bLiPoAutoDetect;
 
cBoxTimingsDebug.SelectedItem = debugInterval * 10;
cBoxTimingsNav.SelectedItem = navctrlInterval * 10;
cBoxTimingsBl.SelectedItem = blctrlInterval * 10;
cBoxTimingsOSD.SelectedItem = OSDInterval * 10;
checkBoxAutoSetHP.IsChecked = _bAutoHome;
checkBoxFollowCopter.IsChecked = _bFollowCopter;
checkBoxGPXLog.IsChecked = _bGPXLog;
checkBoxShowWPRoute.IsChecked = _bShowWPRoute;
checkBoxAutoShowWPEdit.IsChecked = _bAutoWPEdit;
checkBoxWPAddUseCopterHeight.IsChecked = _wpAddCopterHeight;
checkBoxWPAddUseCopterHeading.IsChecked = _wpAddCopterHeading;
GridSettings.Visibility = Visibility.Visible;
GridCam.Visibility = GridData.Visibility = GridWP.Visibility = GridWPEdit.Visibility = Visibility.Collapsed;
_initSerialCtrl();
}
/// <summary>
/// initialize the datatables
/// with columnnames etc
/// </summary>
void _dataTablesInit()
{
dtMotors.Columns.Add("#");
if (Thread.CurrentThread.CurrentUICulture.Name == "de-DE")
dtMotors.Columns.Add("Strom");
else
dtMotors.Columns.Add("Current");
dtMotors.Columns.Add("Temp");
dgvMotors1.DataContext = dtMotors.DefaultView;
_initDTMotors();
 
Setter setter = new Setter(ContentControl.PaddingProperty, new Thickness(5, 0, 5, 0));
Style style = new Style(typeof(System.Windows.Controls.Primitives.DataGridColumnHeader));
style.Setters.Add(setter);
setter = new Setter(ContentControl.BackgroundProperty, new SolidColorBrush(Colors.Transparent));
style.Setters.Add(setter);
setter = new Setter(ContentControl.ForegroundProperty, new SolidColorBrush(Colors.White));
style.Setters.Add(setter);
 
dtWaypoints.Columns.Add("Index", typeof(int));
dtWaypoints.Columns.Add("Type", typeof(int));
dtWaypoints.Columns.Add("Name", typeof(string));
dtWaypoints.Columns.Add("Latitude", typeof(double));
dtWaypoints.Columns.Add("Longitude", typeof(double));
dtWaypoints.Columns.Add("Altitude", typeof(string));
dtWaypoints.Columns.Add("Heading", typeof(string));
dtWaypoints.Columns.Add("Speed", typeof(string));
dtWaypoints.Columns.Add("ClimbRate", typeof(string));
dtWaypoints.Columns.Add("Radius", typeof(string));
dtWaypoints.Columns.Add("HoldTime", typeof(string));
dtWaypoints.Columns.Add("AutoTrigger", typeof(string));
dtWaypoints.Columns.Add("CamAngle", typeof(string));
dtWaypoints.Columns.Add("Event", typeof(string));
dtWaypoints.Columns.Add("Out1Timer", typeof(string));
dtWaypoints.Columns.Add("Status", typeof(string));
dtWaypoints.PrimaryKey = new DataColumn[] { dtWaypoints.Columns["Index"] };
dgvWP.ItemsSource = dtWaypoints.DefaultView;
dgvWP.ColumnHeaderStyle = new Style();
dgvWP.ColumnHeaderStyle = style;
 
dtGPX.Columns.Add("Index", typeof(int));
dtGPX.Columns.Add("Latitude", typeof(double));
dtGPX.Columns.Add("Longitude", typeof(double));
dtGPX.Columns.Add("Elevation", typeof(int));
dtGPX.Columns.Add("Time", typeof(string));
dtGPX.PrimaryKey = new DataColumn[] { dtGPX.Columns["Index"] };
drGPX = dtGPX.NewRow();
 
}
/// <summary>
/// initialize the datatable dtMotors for motor values
/// DataGridView dgvMotors1 is bound to dtMotors1
/// </summary>
void _initDTMotors()
{
for (int i = 0; i < 12; i++)
{
if (dtMotors.Rows.Count < 12)
dtMotors.Rows.Add((i + 1).ToString(), "NA", "NA");
else
{
dtMotors.Rows[i].SetField(1, "NA");
dtMotors.Rows[i].SetField(2, "NA");
}
}
}
 
#endregion init
 
#region events
private void serialPortCtrl_PortOpened()
{
Dispatcher.Invoke(() => imageWiFi.Source = new BitmapImage(new Uri("Images/WiFi_G.png", UriKind.Relative)));
_getVersion();
Thread.Sleep(100);
_getLic();
//_OSDMenue(0);
//Thread.Sleep(200);
//_sendSerialData();
_readCont(true);
}
private void serialPortCtrl_PortClosed()
{
Dispatcher.Invoke(() => imageWiFi.Source = new BitmapImage(new Uri("Images/WiFi_W.png", UriKind.Relative)));
_readCont(false);
}
bool _bToggle = false;
void timerEvent(object sender, EventArgs e)
{
if (bReadContinously)
{
if (_debugDataAutorefresh) { _readDebugData(true); Thread.Sleep(10); }
 
if (_blctrlDataAutorefresh) { _readBLCtrl(true); Thread.Sleep(10); }
 
if (_navCtrlDataAutorefresh && _iCtrlAct == 2) { _readNavData(true); Thread.Sleep(10); }
check_HWError = true;
_getVersion();
Thread.Sleep(10);
if (_OSDAutorefresh)
{
if (iOSDMax == 0 | cbOSD.Items.Count != iOSDMax)
_initOSDCB();
_OSDMenueAutoRefresh();
}
if (_iLifeCounter > 0)
{
Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_G.png", UriKind.Relative)));
// Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGreen));
_iLifeCounter = 0;
_bConnErr = false;
if (_bAirborne && _bGPXLog)
{
drGPX[0] = dtGPX.Rows.Count;
dtGPX.Rows.Add(new object[] { drGPX[0], drGPX[1], drGPX[2], drGPX[3], drGPX[4] });
}
Dispatcher.Invoke((Action)(() => tbSideBarGPXLog.Background = (_bAirborne && _bGPXLog && _bToggle) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));
Dispatcher.Invoke((Action)(() => tbSideBarGPXLog.Foreground = (_bAirborne && _bGPXLog) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));
Dispatcher.Invoke((Action)(() => tbSideBarGPXLog.BorderBrush = (_bAirborne && _bGPXLog) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));
_bToggle = !_bToggle;
}
else
{
if (!_bConnErr)
{
Log(LogMsgType.Error, "No communication to NC/FC!");
Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_R.png", UriKind.Relative)));
// Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.Red));
_bConnErr = true;
}
}
}
}
private void camTimer_Tick(object sender, EventArgs e)
{
if (_camImageSource != null && _frameSource != null && _camImage.Visibility == Visibility.Visible)
_camImage.Source = _camImageSource;
camTimer.IsEnabled = false;
}
 
#region menues
private void labelData_MouseDown(object sender, MouseButtonEventArgs e)
{
GridData.Visibility = GridData.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
GridSettings.Visibility = GridWP.Visibility = Visibility.Collapsed;
}
private void labelMotorData_MouseDown(object sender, MouseButtonEventArgs e)
{
GridMotors.Visibility = GridMotors.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
if (GridMotors.IsVisible)
_setMotorGridSize();
}
private void labelSettings_MouseDown(object sender, MouseButtonEventArgs e)
{
GridData.Visibility = GridWP.Visibility = Visibility.Collapsed;
GridSettings.Visibility = GridSettings.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
private void labelLog_MouseDown(object sender, MouseButtonEventArgs e)
{
GridLog.Visibility = GridLog.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
private void labelOSD_MouseDown(object sender, MouseButtonEventArgs e)
{
GridOSD.Visibility = GridOSD.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
}
private void labelWaypoints_MouseDown(object sender, MouseButtonEventArgs e)
{
GridData.Visibility = GridSettings.Visibility = Visibility.Collapsed;
GridWP.Visibility = GridWP.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
private void labelWPEdit_MouseDown(object sender, MouseButtonEventArgs e)
{
GridWPEdit.Visibility = GridWPEdit.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
private void labelCamera_MouseDown(object sender, MouseButtonEventArgs e)
{
GridCam.Visibility = GridCam.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
#endregion menues
 
private void btnGetWP_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(new ThreadStart(_getWP));
t.Start();
}
private void btnSendWPList_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(new ThreadStart(_sendWPList));
t.Start();
}
private void btnConnectToCopter_Click(object sender, RoutedEventArgs e)
{
if (!serialPortCtrl.Port.IsOpen)
serialPortCtrl.Connect(true);
else
_readCont(!bReadContinously);
}
private void btnSetHP_Click(object sender, RoutedEventArgs e)
{
_setHomePos();
}
private void btnClearHP_Click(object sender, RoutedEventArgs e)
{
_clearHomePos();
}
private void btnGotoHP_Click(object sender, RoutedEventArgs e)
{
if (home != null && MainMap.Markers.Contains(home))
MainMap.Position = home.Position;
}
private void checkBoxAutoSetHP_Click(object sender, RoutedEventArgs e)
{
_bAutoHome = (bool)checkBoxAutoSetHP.IsChecked;
}
private void chkBoxSaveNormalState_Click(object sender, RoutedEventArgs e)
{
_bSaveWinStateNormal = (bool)chkBoxSaveNormalState.IsChecked;
}
private void chkBoxSaveFullScreenState_Click(object sender, RoutedEventArgs e)
{
_bSaveWinStateFull = (bool)chkBoxSaveFullScreenState.IsChecked;
}
 
#region thresholds
private void sliderThresholdVoltageWarn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
{
_dThresholdVoltageWarn = sliderThresholdVoltageWarn.Value;
_dThresholdVoltageCrit = sliderThresholdVoltageCrit.Value;
}
}
private void sliderThresholdVoltageCrit_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
_dThresholdVoltageCrit = sliderThresholdVoltageCrit.Value;
}
private void checkBoxThresholdVoltageVoice_Click(object sender, RoutedEventArgs e)
{
_bVoiceVoltPlay = (bool)checkBoxThresholdVoltageVoice.IsChecked;
}
 
private void sliderThresholdDistanceWarn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
_dThresholdDistanceWarn = sliderThresholdDistanceWarn.Value;
}
private void sliderThresholdBLCtrlTempWarn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
_iThresholdBLCTRLTempWarn = (int)sliderThresholdBLCtrlTempWarn.Value;
}
private void checkBoxThresholdDistanceVoice_Click(object sender, RoutedEventArgs e)
{
_bVoiceDistancePlay = (bool)checkBoxThresholdDistanceVoice.IsChecked;
}
 
private void checkBoxSatfixLost_Click(object sender, RoutedEventArgs e)
{
_bVoiceSatFixPlay = (bool)checkBoxSatfixLost.IsChecked;
}
private void checkBoxMagneticField_Click(object sender, RoutedEventArgs e)
{
_bVoiceMagneticFieldPlay = (bool)checkBoxMagneticField.IsChecked;
}
private void checkBoxRClevel_Click(object sender, RoutedEventArgs e)
{
_bVoiceRCLevelPlay = (bool)checkBoxRClevel.IsChecked;
}
private void checkBoxBLCtrlTempVoice_Click(object sender, RoutedEventArgs e)
{
_bVoiceBLCTRLTempPlay = (bool)checkBoxBLCtrlTempVoice.IsChecked;
}
private void comboBoxVoiceLanguage_DropDownClosed(object sender, EventArgs e)
{
if (comboBoxVoiceLanguage.SelectedIndex > -1)
{
_iVoiceIndex = comboBoxVoiceLanguage.SelectedIndex;
}
}
#endregion thresholds
 
private void buttonSwitchNC_Click(object sender, RoutedEventArgs e)
{
_switchToNC();
}
 
private void Window_Loaded(object sender, RoutedEventArgs e)
{
stbVoltageCritAnim = TryFindResource("VoltageCritAnim") as Storyboard;
stbSatFixLostAnim = TryFindResource("SatFixLostAnim") as Storyboard;
stbMagneticFieldAnim = TryFindResource("MagneticFieldCritAnim") as Storyboard;
stbDistanceWarnAnim = TryFindResource("DistanceCritAnim") as Storyboard;
stbRCLevelAnim = TryFindResource("RCCritAnim") as Storyboard;
stbCamActiveAnim = TryFindResource("CamActiveAnim") as Storyboard;
stbBLCTRLTempAnim = TryFindResource("BLCtrlCritAnim") as Storyboard;
_setMotorGridSize();
// Refresh the list of available cameras
comboBoxCameras.Items.Clear();
 
foreach (Camera cam in CameraService.AvailableCameras)
comboBoxCameras.Items.Add(cam);
 
if (comboBoxCameras.Items.Count > 0)
comboBoxCameras.SelectedIndex = 0;
}
private void Window_Closing(object sender, CancelEventArgs e)
{
_writeIni();
if (_bGPXLog && dtGPX.Rows.Count > 0)
_saveGPXLog();
thrashOldCamera();
}
private void Window_Closed(object sender, EventArgs e)
{
Application.Current.Shutdown();
}
 
#region contextmenue add point
Point pWPAdd;
private void GridGMapControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if(e.ClickCount == 2)
{
double x = 0, y = 0;
var titleHeight = SystemParameters.WindowCaptionHeight + SystemParameters.ResizeFrameHorizontalBorderHeight;
 
pWPAdd = new Point(e.GetPosition(this).X, e.GetPosition(this).Y);
if (pWPAdd.X + canvasAddPoint.Width > Width)
x = pWPAdd.X - canvasAddPoint.Width;
else
x = pWPAdd.X;
if (pWPAdd.Y + canvasAddPoint.Height > Height - titleHeight)
y = pWPAdd.Y - canvasAddPoint.Height;
else
y = pWPAdd.Y;
 
canvasAddPoint.Margin = new Thickness(x, y, canvasAddPoint.Margin.Left, canvasAddPoint.Margin.Bottom);
canvasAddPoint.Visibility = Visibility.Visible;
}
 
}
private void canvasAddPoint_LostFocus(object sender, RoutedEventArgs e)
{
canvasAddPoint.Visibility = Visibility.Collapsed;
}
private void canvasAddPoint_MouseLeave(object sender, MouseEventArgs e)
{
canvasAddPoint.Visibility = Visibility.Collapsed;
}
private void btnCmAddWP_Click(object sender, RoutedEventArgs e)
{
if (pWPAdd != null)
{
PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
_addWP(p,0);
canvasAddPoint.Visibility = Visibility.Collapsed;
}
}
private void btnCmAddPOI_Click(object sender, RoutedEventArgs e)
{
if (pWPAdd != null)
{
PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
_addWP(p,1);
canvasAddPoint.Visibility = Visibility.Collapsed;
}
}
private void btnCmAddFailsave_Click(object sender, RoutedEventArgs e)
{
if (pWPAdd != null)
{
PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
_addWP(p,2);
canvasAddPoint.Visibility = Visibility.Collapsed;
}
}
private void btnCmAddLanding_Click(object sender, RoutedEventArgs e)
{
if (pWPAdd != null)
{
PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
_addWP(p,3);
canvasAddPoint.Visibility = Visibility.Collapsed;
}
}
#endregion contextmenue add point
 
#endregion events
 
#region cam
private CameraFrameSource _frameSource;
 
private void btnCamStart_Click(object sender, RoutedEventArgs e)
{
if (_frameSource != null && _frameSource.Camera == comboBoxCameras.SelectedItem)
return;
 
thrashOldCamera();
startCapturing();
}
private void btnCamStop_Click(object sender, RoutedEventArgs e)
{
thrashOldCamera();
_camImage.Visibility = Visibility.Collapsed;
if (stbCamActiveAnim != null && _bCamAnim)
{
Dispatcher.Invoke(() => stbCamActiveAnim.Stop());
_bCamAnim = false;
rectCamStart.Visibility = Visibility.Collapsed;
}
}
private void btnCamSettings_Click(object sender, RoutedEventArgs e)
{
if (_frameSource != null && _frameSource.Camera != null)
{
_frameSource.Camera.ShowPropertiesDialog();
}
}
private void btnCamListRefresh_Click(object sender, RoutedEventArgs e)
{
comboBoxCameras.Items.Clear();
CameraService.ClearCameraList();
foreach (Camera cam in CameraService.AvailableCameras)
comboBoxCameras.Items.Add(cam);
 
if (comboBoxCameras.Items.Count > 0)
comboBoxCameras.SelectedIndex = 0;
//if (_frameSource != null && comboBoxCameras.Items.Count > 0 && comboBoxCameras.Items.Contains(_frameSource.Camera.ToString()))
// comboBoxCameras.SelectedItem = (Camera)_frameSource.Camera;
 
}
 
private void lblCam_Click(object sender, RoutedEventArgs e)
{
if (_frameSource != null && _frameSource.Camera != null)
{
_camImage.Visibility = _camImage.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
}
}
 
void _setCamPicStretch(Stretch type)
{
if(_camImage.Stretch == Stretch.None)
_camImageMargin = _camImage.Margin;
if(type != Stretch.None)
_camImage.Margin = new Thickness(0);
_camImage.Stretch = type;
}
private void btnCamPicStretchNone_Click(object sender, RoutedEventArgs e)
{
_setCamPicStretch(Stretch.None);
_camImage.Margin = _camImageMargin;
}
private void btnCamResetZoom_Click(object sender, RoutedEventArgs e)
{
_setCamPicStretch(Stretch.None);
_camImage.Margin = _camImageMargin = new Thickness(0);
SliderCamZoom.Value = 1;
}
private void btnCamPicStretchFill_Click(object sender, RoutedEventArgs e)
{
_setCamPicStretch(Stretch.Fill);
}
private void btnCamPicStretchUniform_Click(object sender, RoutedEventArgs e)
{
_setCamPicStretch(Stretch.Uniform);
}
private void btnCamPicStretchUFill_Click(object sender, RoutedEventArgs e)
{
_setCamPicStretch(Stretch.UniformToFill);
}
private Camera CurrentCamera
{
get
{
return comboBoxCameras.SelectedItem as Camera;
}
}
private void startCapturing()
{
try
{
Camera c = (Camera)comboBoxCameras.SelectedItem;
setFrameSource(new CameraFrameSource(c));
_frameSource.Camera.CaptureWidth = 640;
_frameSource.Camera.CaptureHeight = 480;
_frameSource.Camera.Fps = 25;
_frameSource.NewFrame += OnImageCaptured;
_frameSource.StartFrameCapture();
_camImage.Visibility = Visibility.Visible;
_camImage.Margin = _camImageMargin;
if (stbCamActiveAnim != null && !_bCamAnim)
{
Dispatcher.Invoke(() => stbCamActiveAnim.Begin());
_bCamAnim = true;
rectCamStart.Visibility = Visibility.Visible;
}
}
catch (Exception ex)
{
comboBoxCameras.Text = "Select A Camera";
MessageBox.Show(ex.Message);
}
}
 
public void OnImageCaptured(Touchless.Vision.Contracts.IFrameSource frameSource, Touchless.Vision.Contracts.Frame frame, double fps)
{
_camImageSource = BitmapConversion.ToWpfBitmap(frame.Image);
camTimer.IsEnabled = true;
}
private void setFrameSource(CameraFrameSource cameraFrameSource)
{
if (_frameSource == cameraFrameSource)
return;
 
_frameSource = cameraFrameSource;
}
private void thrashOldCamera()
{
 
// Trash the old camera
if (_frameSource != null)
{
_frameSource.NewFrame -= OnImageCaptured;
Dispatcher.Invoke(() => {
_camImage.Source = null;
_camImage.InvalidateVisual();
});
using (Dispatcher.DisableProcessing())
{
_frameSource.StopFrameCapture();
setFrameSource(null);
Thread.Sleep(10);
}
}
}
 
Point pOffset,mouse_pos;
Thickness _camImageMargin = new Thickness(0);
private void _CamImage_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && _camImage.Stretch == Stretch.None)
{
mouse_pos = Mouse.GetPosition(this);
mouse_pos.Offset(-pOffset.X, -pOffset.Y);
pOffset = Mouse.GetPosition(this);
_camImage.Margin =_camImageMargin= new Thickness(_camImage.Margin.Left+ mouse_pos.X + mouse_pos.X * (0.5/ SliderCamZoom.Value), _camImage.Margin.Top + mouse_pos.Y + mouse_pos.Y* (0.5 / SliderCamZoom.Value), _camImage.Margin.Right, _camImage.Margin.Bottom);
}
}
private void _CamImage_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && _camImage.Stretch == Stretch.None)
pOffset = Mouse.GetPosition(this);
}
 
#endregion cam
 
#region GMap
string _mapPosition = "Landshut";
void _setupMap()
{
MainMap.Manager.Mode = AccessMode.ServerAndCache;
MainMap.MapProvider = GMapProviders.BingHybridMap;
textBoxGeo.Text = _mapPosition;
MainMap.SetPositionByKeywords(_mapPosition);
textBoxLat_currentPos.Text = MainMap.Position.Lat.ToString() + "°";
textBoxLng_currentPos.Text = MainMap.Position.Lng.ToString() + "°";
MainMap.MinZoom = 0;
MainMap.MaxZoom = 24;
MainMap.Zoom = 16;
MainMap.ShowCenter = true;
MainMap.ShowTileGridLines = false;
sliderMapZoom.Value = 16;
comboBoxMapType.ItemsSource = providerList;
comboBoxMapType.DisplayMemberPath = "Name";
comboBoxMapType.SelectedItem = MainMap.MapProvider;
 
// acccess mode
comboBoxMode.ItemsSource = Enum.GetValues(typeof(AccessMode));
comboBoxMode.SelectedItem = MainMap.Manager.Mode;
 
}
 
/// <summary>
/// selection of relevant map providers --> if You need more, You can change the line:
/// comboBoxMapType.ItemsSource = providerList;
/// to:
/// comboBoxMapType.ItemsSource = GMapProviders.List;
/// in _setupMap()
/// or add items here:
/// </summary>
List<GMap.NET.MapProviders.GMapProvider> providerList = new List<GMap.NET.MapProviders.GMapProvider>
{ GMap.NET.MapProviders.GMapProviders.OpenCycleMap, GMap.NET.MapProviders.GMapProviders.OpenCycleLandscapeMap, GMap.NET.MapProviders.GMapProviders.OpenCycleTransportMap,
GMap.NET.MapProviders.GMapProviders.BingMap,GMap.NET.MapProviders.GMapProviders.BingSatelliteMap,GMap.NET.MapProviders.GMapProviders.BingHybridMap,
GMap.NET.MapProviders.GMapProviders.GoogleMap,GMap.NET.MapProviders.GMapProviders.GoogleSatelliteMap,GMap.NET.MapProviders.GMapProviders.GoogleHybridMap,GMap.NET.MapProviders.GMapProviders.GoogleTerrainMap,
GMap.NET.MapProviders.GMapProviders.OviMap,GMap.NET.MapProviders.GMapProviders.OviSatelliteMap,GMap.NET.MapProviders.GMapProviders.OviHybridMap,GMap.NET.MapProviders.GMapProviders.OviTerrainMap};
 
private void MainMap_Loaded(object sender, RoutedEventArgs e)
{
MainMap.Manager.Mode = AccessMode.ServerAndCache;
copter = new GMapMarker(MainMap.Position);
 
copter.Shape = new CustomMarkerCopter(this, copter, MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"), "red");
if (comboBoxCopterColor.SelectionBoxItem != null)
{
string s = comboBoxCopterColor.SelectionBoxItem.ToString();
((CustomMarkerCopter)(copter.Shape)).setCopterColor(s);
}
Dispatcher.Invoke(() => {
if (comboBoxCopterHeadingColor.SelectionBoxItem != null)
{
string s = comboBoxCopterHeadingColor.SelectionBoxItem.ToString();
((CustomMarkerCopter)(copter.Shape)).setHeadingColor(s);
}
});
copter.Offset = new System.Windows.Point(-26, -26);
copter.ZIndex = int.MaxValue;
MainMap.Markers.Add(copter);
copter.Position = MainMap.Position;
_setMapItemsSize("Copter", SliderCopterZoom.Value);
}
void _setHomePos()
{
pHome = MainMap.Position;
if (!MainMap.Markers.Contains(home))
{
home = new GMapMarker(MainMap.Position);
home.Shape = new CustomMarkerHome(this, home, MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"));
home.Offset = new System.Windows.Point(-16.5, -16.5);
// home.ZIndex = int.MaxValue;
MainMap.Markers.Add(home);
}
home.Position = MainMap.Position;
((CustomMarkerHome)(home.Shape)).setText(MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"));
_setMapItemsSize("Home", SliderHPZoom.Value);
if (checkBoxShowWPMaxRange.IsChecked == true)
{
if (cWPBound != null && cWPBound.Tag != null)
MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
 
createCircle(home.Position, dWPMaxRange);
Dispatcher.Invoke(() =>
{
if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
{
string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
cWPBound.setColor(s);
}
});
}
 
}
void _setActiveWP(int iIndex)
{
if (iIndex < wpList.Count)
{
if (wpActiveMarker == null || !MainMap.Markers.Contains(wpActiveMarker))
{
Dispatcher.Invoke(() =>
{
wpActiveMarker = new GMapMarker(wpList[iIndex]);
wpActiveMarker.Shape = new CustomMarkerWPActive(this, wpActiveMarker, "wpActive", 0);
wpActiveMarker.Offset = new Point(-17.5, -17.5);
MainMap.Markers.Add(wpActiveMarker);
});
}
else
Dispatcher.Invoke(() => wpActiveMarker.Position = wpList[iIndex]);
}
 
Dispatcher.Invoke(() => tbWPStatusHeight.Text = dtWaypoints.Rows[iIndex][5].ToString() + " m");
}
void _clearHomePos()
{
MainMap.Markers.Remove(home);
if (cWPBound != null && cWPBound.Tag != null)
MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
}
void _clearMapMarkers(Type markerType)
{
for (int k = 0; k < MainMap.Markers.Count;)
{
GMapMarker p = MainMap.Markers[k];
if (p.GetType() == markerType | (p.Shape != null && p.Shape.GetType() == markerType))
MainMap.Markers.Remove(p);
else
k++;
}
_WPisMouseCaptured = false;
}
 
GMapMarker _findWPMarker(string name)
{
for (int k = 0; k < MainMap.Markers.Count;)
{
GMapMarker p = MainMap.Markers[k];
if (p.GetType() == typeof(CustomMarkerWP) | (p.Shape != null && p.Shape.GetType() == typeof(CustomMarkerWP)))
if (((CustomMarkerWP)p.Shape).WPText == name)
return p;
else
k++;
else
k++;
}
return null;
}
void _clearWPMarker(string name)
{
GMapMarker p = _findWPMarker(name);
if (p != null)
MainMap.Markers.Remove(p);
}
void _renameWPMarker(string s1, string s2)
{
GMapMarker p = _findWPMarker(s1);
if (p != null)
((CustomMarkerWP)p.Shape).WPText = s2;
}
void _WPMarkerSetType(string text, int type)
{
GMapMarker p = _findWPMarker(text);
if (p != null)
((CustomMarkerWP)p.Shape).WPType = type;
}
void _repositionWPMarker(PointLatLng point, string name)
{
GMapMarker p = _findWPMarker(name);
if (p != null)
p.Position = point;
}
 
void createCircle(PointLatLng center, double distance)
{
 
GMapMarker it = new GMapMarker(center);
it.ZIndex = -1;
 
cWPBound.Center = center;
cWPBound.Bound = GMap.NET.PureProjection.GetPointFromDistance(center, distance);
cWPBound.Tag = it;
cWPBound.IsHitTestVisible = false;
UpdateCircle(cWPBound);
it.Shape = cWPBound;
MainMap.Markers.Add(it);
}
// calculates circle radius
void UpdateCircle(Circle c)
{
var pxCenter = MainMap.FromLatLngToLocal(c.Center);
var pxBounds = MainMap.FromLatLngToLocal(c.Bound);
 
double a = (double)(pxBounds.X - pxCenter.X);
double b = (double)(pxBounds.Y - pxCenter.Y);
var pxCircleRadius = Math.Sqrt(a * a + b * b);
 
c.Width = c.Height = pxCircleRadius * 2;
//c.Width = 55 + pxCircleRadius * 2;
//c.Height = 55 + pxCircleRadius * 2;
(c.Tag as GMapMarker).Offset = new System.Windows.Point(-c.Width / 2, -c.Height / 2);
}
 
// access mode
private void comboBoxMode_DropDownClosed(object sender, EventArgs e)
{
MainMap.Manager.Mode = (AccessMode)comboBoxMode.SelectedItem;
MainMap.ReloadMap();
}
// zoom up
private void czuZoomUp_Click(object sender, RoutedEventArgs e)
{
MainMap.Zoom = ((int)MainMap.Zoom) + 1;
}
 
// zoom down
private void czuZoomDown_Click(object sender, RoutedEventArgs e)
{
MainMap.Zoom = ((int)(MainMap.Zoom + 0.99)) - 1;
}
 
// prefetch
private void buttonPrefetch_Click(object sender, RoutedEventArgs e)
{
RectLatLng area = MainMap.SelectedArea;
if (!area.IsEmpty)
{
for (int i = (int)MainMap.Zoom; i <= MainMap.MaxZoom; i++)
{
MessageBoxResult res = MessageBox.Show("Ready ripp at Zoom = " + i + " ?", "GMap.NET", MessageBoxButton.YesNoCancel);
 
if (res == MessageBoxResult.Yes)
{
TilePrefetcher obj = new TilePrefetcher();
obj.Owner = this;
obj.ShowCompleteMessage = true;
obj.Start(area, i, MainMap.MapProvider, 100);
}
else if (res == MessageBoxResult.No)
{
continue;
}
else if (res == MessageBoxResult.Cancel)
{
break;
}
}
}
else
{
MessageBox.Show("Select map area holding ALT", "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
}
 
// goto by geocoder
private void buttonGeoCoding_Click(object sender, RoutedEventArgs e)
{
_goto_byGeoCoder();
}
// goto by geocoder
private void textBoxGeo_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
{
if (e.Key == System.Windows.Input.Key.Enter)
_goto_byGeoCoder();
}
void _goto_byGeoCoder()
{
GeoCoderStatusCode status = MainMap.SetPositionByKeywords(textBoxGeo.Text);
_mapPosition = textBoxGeo.Text;
if (status != GeoCoderStatusCode.G_GEO_SUCCESS)
{
MessageBox.Show("Geocoder can't find: '" + textBoxGeo.Text + "', reason: " + status.ToString(), "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Exclamation);
}
}
private void buttonGeoLoc_Click(object sender, RoutedEventArgs e)
{
try
{
double lat = double.Parse(textBoxLat.Text, System.Globalization.CultureInfo.InvariantCulture);
double lng = double.Parse(textBoxLng.Text, System.Globalization.CultureInfo.InvariantCulture);
 
MainMap.Position = new PointLatLng(lat, lng);
}
catch (Exception ex)
{
MessageBox.Show("incorrect coordinate format: " + ex.Message);
}
 
}
 
private void ReloadMap_Click(object sender, RoutedEventArgs e)
{
MainMap.ReloadMap();
}
 
private void MainMap_OnPositionChanged(PointLatLng point)
{
if (_bFollowCopter)
_setCopterData(MainMap.Position);
}
 
private void MainMap_OnMapZoomChanged()
{
if (_bFollowCopter)
_setCopterData(MainMap.Position);
if ((int)sliderMapZoom.Value != MainMap.Zoom)
sliderMapZoom.Value = MainMap.Zoom;
if (cWPBound != null && cWPBound.Tag != null)
UpdateCircle(cWPBound);
}
 
void _setCopterData(PointLatLng p)
{
Dispatcher.Invoke(() =>
{
copter.Position = p;
((CustomMarkerCopter)(copter.Shape)).setText(p.Lat.ToString("0.#######°") + System.Environment.NewLine + p.Lng.ToString("0.#######°"));
textBoxLat_currentPos.Text = p.Lat.ToString() + "°";
textBoxLng_currentPos.Text = p.Lng.ToString() + "°";
});
if (home != null && MainMap.Markers.Contains(home))
{
Dispatcher.Invoke(() => ArtHor.rotateHome = GMapProviders.EmptyProvider.Projection.GetBearing(copter.Position, home.Position));
double d = GMapProviders.EmptyProvider.Projection.GetDistance(home.Position, copter.Position);
Dispatcher.Invoke(() => tbTopDistanceHP.Text = (d * 1000).ToString("0.0 m"));
 
if (d * 1000 < _dThresholdDistanceWarn)
{
_iDistanceJitter = 0; _bVoiceDistanceActive = false;
if (stbDistanceWarnAnim != null && _bAnimDistanceActive)
{
Dispatcher.Invoke(() => stbDistanceWarnAnim.Stop());
_bAnimDistanceActive = false;
}
}
else
{
if (_iDistanceJitter < 20)
{ _iDistanceJitter++; }
if (_iDistanceJitter == 20)
{
if (stbDistanceWarnAnim != null && !_bAnimDistanceActive)
{
Dispatcher.Invoke(() => stbDistanceWarnAnim.Begin());
_bAnimDistanceActive = true;
}
if (_bVoiceDistancePlay && !_bVoiceDistanceActive)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\Distance.mp3");
//Thread t = new Thread(()=>_mediaPlayer("Voice\\Distance.mp3"));
//t.Start();
_bVoiceDistanceActive = true;
}
_iDistanceJitter++;
}
}
}
}
 
void _setMapItemsSize(string item, double value)
{
ScaleTransform scaleTransform = new ScaleTransform();
scaleTransform.ScaleY = value;
scaleTransform.ScaleX = value;
TransformGroup transformGroup = new TransformGroup();
transformGroup.Children.Add(scaleTransform);
 
switch (item)
{
case "Copter":
if (copter != null && copter.Shape != null)
{
((ScaleTransform)transformGroup.Children[0]).CenterX = 26;
((ScaleTransform)transformGroup.Children[0]).CenterY = 26;
copter.Shape.RenderTransform = transformGroup;
}
break;
case "Home":
if (home != null && MainMap.Markers.Contains(home))
{
((ScaleTransform)transformGroup.Children[0]).CenterX = 16.5;
((ScaleTransform)transformGroup.Children[0]).CenterY = 16.5;
home.Shape.RenderTransform = transformGroup;
home.Shape.InvalidateVisual();
}
break;
case "WP":
Dispatcher.Invoke(() =>
{
((ScaleTransform)transformGroup.Children[0]).CenterX = 11.5;
((ScaleTransform)transformGroup.Children[0]).CenterY = 11.5;
for (int k = 0; k < MainMap.Markers.Count;)
{
GMapMarker p = MainMap.Markers[k];
if (p.Shape != null && (p.Shape.GetType() == typeof(CustomMarkerWP) || p.Shape.GetType() == typeof(CustomMarkerWPActive)))
{
((CustomMarkerWP)(p.Shape)).RenderTransform = transformGroup;
}
k++;
}
});
break;
}
 
}
 
private void checkBoxFollowCopter_Click(object sender, RoutedEventArgs e)
{
_bFollowCopter = (bool)checkBoxFollowCopter.IsChecked;
}
 
private void sliderMapZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (MainMap.Zoom != sliderMapZoom.Value)
MainMap.Zoom = (int)sliderMapZoom.Value;
}
 
private void SliderCopterZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (copter != null && copter.Shape != null)
_setMapItemsSize("Copter",SliderCopterZoom.Value);
}
private void SliderWPZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (MainMap.Markers.Count > 2)
_setMapItemsSize("WP",SliderWPZoom.Value);
}
private void SliderHomeZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (home != null && MainMap.Markers.Contains(home))
_setMapItemsSize("Home",SliderHPZoom.Value);
}
 
 
 
#region Touch zooming hackattack ;)
/// <summary>
/// inspired by http://www.codeproject.com/Articles/692286/WPF-and-multi-touch
/// </summary>
bool bFirstAccess = true;
double dDistance = 0;
int iZoom;
private void MainMap_StylusDown(object sender, StylusDownEventArgs e)
{
if (!_WPisMouseCaptured)
{
var id = e.StylusDevice.Id;
e.StylusDevice.Capture(MainMap);
if (iFirstStylusID == -1)
{
iFirstStylusID = id;
}
else
{
 
MainMap.CanDragMap = false;
}
}
}
private void MainMap_StylusUp(object sender, StylusEventArgs e)
{
MainMap.ReleaseStylusCapture();
iFirstStylusID = -1;
bFirstAccess = true;
MainMap.CanDragMap = true;
iZoom = 0;
}
private void MainMap_StylusMove(object sender, StylusEventArgs e)
{
var id = e.StylusDevice.Id;
var tp = e.GetPosition(MainMap);
 
// This is the first Stylus point; just record its position.
if (id == iFirstStylusID)
{
pTouch1.X = tp.X;
pTouch1.Y = tp.Y;
}
else
if (iFirstStylusID > -1)
{
pTouch2.X = tp.X;
pTouch2.Y = tp.Y;
double distance = Point.Subtract(pTouch1, pTouch2).Length;
if (!bFirstAccess)
{
if (distance > dDistance)
iZoom++;
else
if (distance < dDistance)
iZoom--;
}
if (iZoom > 30)
{
iZoom = 0;
Dispatcher.Invoke(() => sliderMapZoom.Value += 1);
}
if (iZoom < -30)
{
iZoom = 0;
Dispatcher.Invoke(() => sliderMapZoom.Value -= 1);
}
dDistance = distance;
bFirstAccess = false;
}
}
#endregion Touch zooming hackattack ;)
 
#endregion GMap
 
#region settings
private void cBoxTimingsDebug_DropDownClosed(object sender, EventArgs e)
{
if (!_bCBInit && cBoxTimingsDebug.SelectedIndex > -1)
debugInterval = (byte)(Convert.ToInt16(cBoxTimingsDebug.SelectedItem) / 10);
}
private void cBoxTimingsNav_DropDownClosed(object sender, EventArgs e)
{
if (!_bCBInit && cBoxTimingsNav.SelectedIndex > -1)
navctrlInterval = (byte)(Convert.ToInt16(cBoxTimingsNav.SelectedItem) / 10);
}
private void cBoxTimingsBl_DropDownClosed(object sender, EventArgs e)
{
if (!_bCBInit && cBoxTimingsBl.SelectedIndex > -1)
blctrlInterval = (byte)(Convert.ToInt16(cBoxTimingsBl.SelectedItem) / 10);
}
private void cBoxTimingsOSD_DropDownClosed(object sender, EventArgs e)
{
if (!_bCBInit && cBoxTimingsOSD.SelectedIndex > -1)
OSDInterval = (byte)(Convert.ToInt16(cBoxTimingsOSD.SelectedItem) / 10);
}
private void chkbAutoDbg_Click(object sender, RoutedEventArgs e)
{
if (!_init) _debugDataAutorefresh = (bool)chkbAutoDbg.IsChecked;
}
private void chkbAutoNav_Click(object sender, RoutedEventArgs e)
{
if (!_init) _navCtrlDataAutorefresh = (bool)chkbAutoNav.IsChecked;
}
private void chkbAutoBL_Click(object sender, RoutedEventArgs e)
{
if (!_init) _blctrlDataAutorefresh = (bool)chkbAutoBL.IsChecked;
}
private void chkbAutoOSD_Click(object sender, RoutedEventArgs e)
{
if (!_init) _OSDAutorefresh = (bool)chkbAutoOSD.IsChecked;
}
 
private void cBoxLiPoCells_DropDownClosed(object sender, EventArgs e)
{
if (cBoxLiPoCells.SelectedIndex > -1)
{
_LipoCells = cBoxLiPoCells.SelectedIndex + 3;
_LipoMinMax();
}
}
private void chkbAutoLiPo_Click(object sender, RoutedEventArgs e)
{
_bLiPoAutoDetect = (bool)chkbAutoLiPoDetect.IsChecked;
}
 
void _LipoMinMax()
{
_dLipoVMax = (double)(_LipoCells) * 4.22;
_dLipoVMin = (double)_LipoCells * 3;
pbTopVoltage.Maximum = _dLipoVMax;
pbTopVoltage.Minimum = _dLipoVMin;
sliderThresholdVoltageWarn.Maximum = _dLipoVMax;
sliderThresholdVoltageWarn.Minimum = _dLipoVMin;
}
private void cBoxMotors_DropDownClosed(object sender, EventArgs e)
{
if (cBoxMotors.SelectedIndex > -1)
{
_iMotors = cBoxMotors.SelectedIndex + 3;
Dispatcher.Invoke(() =>
{
dgvMotors1.Height = (272 / 12.6) * (_iMotors + 1); //272 / 12.6 --> Workaround, cause the headerheight = NaN...?
GridMotors.Height = dgvMotors1.Height + 10;
});
}
}
void _setMotorGridSize()
{
if (dgvMotors1.Columns.Count > 2)
{
dgvMotors1.Columns[0].Width = 24;
dgvMotors1.Columns[1].Width = 50;
dgvMotors1.Columns[2].Width = 50;
dgvMotors1.Height = (272 / 12.6) * (_iMotors + 1);
GridMotors.Height = dgvMotors1.Height + 10;
}
 
}
#endregion settings
 
#region functions
 
#region logging
/// <summary> Log data to the terminal window. </summary>
/// <param name="msgtype"> The type of message to be written. </param>
/// <param name="msg"> The string containing the message to be shown. </param>
private void Log(LogMsgType msgtype, string msg)
{
Dispatcher.Invoke(() =>
{
// rtfTerminal.CaretPosition = rtfTerminal.CaretPosition.DocumentEnd;
// rtfTerminal.Foreground = new SolidColorBrush(LogMsgTypeColor[(int)msgtype]);
// rtfTerminal.AppendText(msg + "\r");
TextRange tr = new TextRange(rtfTerminal.Document.ContentEnd, rtfTerminal.Document.ContentEnd);
tr.Text = msg;
tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
rtfTerminal.AppendText("\r");
rtfTerminal.ScrollToEnd();
});
}
private void ErrorLog(LogMsgType msgtype, string msg, string linkURL, string linkName)
{
 
Dispatcher.Invoke(() =>
{
Paragraph para = new Paragraph();
para.Margin = new Thickness(0); // remove indent between paragraphs
 
Hyperlink link = new Hyperlink();
if (linkURL != "" && linkName != "")
{
link.IsEnabled = true;
link.Inlines.Add(linkName);
link.NavigateUri = new Uri(linkURL);
link.RequestNavigate += (sender, args) => Process.Start(args.Uri.ToString());
}
//msg = DateTime.Now.ToLongTimeString() + msg;
para.Foreground = new SolidColorBrush(LogMsgTypeColor[(int)msgtype]);
Run r = new Run("[" + DateTime.Now.ToLongTimeString() + "]: ");
r.Foreground = new SolidColorBrush(Colors.Black);
para.Inlines.Add(r);
para.Inlines.Add(msg);
para.Inlines.Add(link);
rtfError.Document.Blocks.Add(para);
//TextRange tr = new TextRange(rtfError.Document.ContentEnd, rtfError.Document.ContentEnd);
//tr.Text = msg + link;
//tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
//rtfError.AppendText("\r");
rtfError.ScrollToEnd();
 
//_bErrorLog = true;
});
}
/// <summary>
/// Clear the line in the errorlog window
/// containing the error string when error has ceased
/// </summary>
/// <param name="s">substring of errrormessage</param>
void _clearErrorLog(string s)
{
Dispatcher.Invoke((Action)(() =>
{
TextRange searchRange = new TextRange(rtfError.Document.ContentStart, rtfError.Document.ContentEnd);
TextRange foundRange = FindTextInRange(searchRange, s);
 
int iStart = searchRange.Text.IndexOf(s, StringComparison.OrdinalIgnoreCase);
 
 
if (iStart > -1)
{
int iLength = 0;
int iEnd = searchRange.Text.IndexOf('\r', iStart);
if (iEnd > 0)
{
iLength = iEnd + 1;
int iHttp = searchRange.Text.IndexOf("http", iEnd);
if (iHttp == iLength)
{
int iEnd2 = searchRange.Text.IndexOf('\r', iLength);
if (iEnd2 > iLength)
{
iLength = iEnd2 + 1;
// TextRange result = new TextRange(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
 
rtfError.Selection.Select(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
rtfError.Selection.Text = string.Empty;
if (rtfError.Document.ContentEnd.GetTextRunLength(LogicalDirection.Backward) < 2) _bErrorLog = false;
}
 
}
else
{
rtfError.Selection.Select(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
rtfError.Selection.Text = string.Empty;
if (rtfError.Document.ContentEnd.GetTextRunLength(LogicalDirection.Backward) < 2) _bErrorLog = false;
}
}
}
}));
 
}
public TextRange FindTextInRange(TextRange searchRange, string searchText)
{
int offset = searchRange.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase);
if (offset < 0)
return null; // Not found
 
var start = GetTextPositionAtOffset(searchRange.Start, offset);
TextRange result = new TextRange(start, GetTextPositionAtOffset(start, searchText.Length));
 
return result;
}
TextPointer GetTextPositionAtOffset(TextPointer position, int characterCount)
{
while (position != null)
{
if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
{
int count = position.GetTextRunLength(LogicalDirection.Forward);
if (characterCount <= count)
{
return position.GetPositionAtOffset(characterCount);
}
 
characterCount -= count;
}
 
TextPointer nextContextPosition = position.GetNextContextPosition(LogicalDirection.Forward);
if (nextContextPosition == null)
return position;
 
position = nextContextPosition;
}
 
return position;
}
#endregion logging
 
#region processing received data
 
private void processMessage(byte[] message)
{
if (message.Length > 0)
{
_iLifeCounter++;
//Log(LogMsgType.Incoming, BitConverter.ToString(message));
//Log(LogMsgType.Incoming, message.Length.ToString());
string s = new string(ASCIIEncoding.ASCII.GetChars(message, 0, message.Length));
char cmdID;
byte adr;
byte[] data;
byte[] tmp = null;
if (message[0] != '#')
{
int iFound = -1;
for (int i = 0; i < message.Length; i++) //Sometimes the FC/NC sends strings without termination (like WP messages)
{ //so this is a workaround to not spam the log box
if (message[i] == 35)
{
iFound = i;
break;
}
}
if (iFound > 0)
{
s = new string(ASCIIEncoding.ASCII.GetChars(message, 0, iFound));
tmp = new byte[message.Length - iFound];
Buffer.BlockCopy(message, iFound, tmp, 0, message.Length - iFound);
}
s = s.Trim('\0', '\n', '\r');
if (s.Length > 0)
Log(LogMsgType.Normal, s);
if (tmp != null)
{
s = new string(ASCIIEncoding.ASCII.GetChars(tmp, 0, tmp.Length));
processMessage(tmp);
}
}
//Debug.Print(s);
else
{
FlightControllerMessage.ParseMessage(message, out cmdID, out adr, out data);
 
if (adr == 255) { crcError++; }
else crcError = 0;
Dispatcher.Invoke(() => tbCrc.Text = crcError.ToString());
//display the active controller (FC / NC)
if (adr > 0 && adr < 3 && adr != _iCtrlAct) //adr < 3: temporary workaround cause when I've connected the FC alone it always switches between mk3mag & FC every second...???
{
_iCtrlAct = adr;
switch (adr)
{
case 1:
Dispatcher.Invoke(() => tbCtrl.Text = "FC");
Dispatcher.Invoke(() => buttonSwitchNC.Visibility = Visibility.Visible);
Dispatcher.Invoke(() => labelSwitchToNavi.Visibility = Visibility.Visible);
// _setFieldsNA(); //display fields NA for FC
break;
case 2:
Dispatcher.Invoke(() => tbCtrl.Text = "NC");
Dispatcher.Invoke(() => buttonSwitchNC.Visibility = Visibility.Hidden);
Dispatcher.Invoke(() => labelSwitchToNavi.Visibility = Visibility.Hidden);
break;
//case 3:
// lblCtrl.Invoke((Action)(() => lblCtrl.Text = "MK3MAG"));
// break;
//case 4:
// lblCtrl.Invoke((Action)(() => lblCtrl.Text = "BL-CTRL"));
// break;
default:
Dispatcher.Invoke(() => tbCtrl.Text = "NA");
break;
}
// _loadLabelNames();
}
// else
// Debug.Print("Address == 0?");
 
if (data != null && data.Length > 0)
{
s = new string(ASCIIEncoding.ASCII.GetChars(data, 1, data.Length - 1));
s = s.Trim('\0', '\n');
 
switch (cmdID)
{
//case 'A': //Label names
// _processLabelNames(s);
// break;
 
case 'D': //Debug data
_processDebugVals(adr, data);
break;
 
case 'V': //Version
_processVersion(adr, data);
break;
 
case 'K'://BL-CTRL data
_processBLCtrl(data);
break;
 
case 'M'://License info
_processLicense(data);
break;
 
case 'O': //NC Data
if (data[0] < 10)
_processNCData(data);
else
_processNCDataV2(data);
break;
 
//case 'E': //NC error-string
// ErrorLog(LogMsgType.Error, "NC Error: " + s);
// break;
 
case 'L': //OSD Menue (called by pagenumber)
_processOSDSingle(data);
break;
 
case 'H': //OSD Menue (with autoupdate - called by Key)
_processOSDAuto(data);
break;
 
case 'X': //Waypoint data
_processWPData(data);
break;
 
case 'W': //return new Waypoint items count after sending waypoint to copter
_iWPCount = data[0];
break;
//default:
// Log(LogMsgType.Incoming, "cmd: " + cmdID.ToString());
// Log(LogMsgType.Incoming, BitConverter.ToString(data));
// break;
}
}
//else
//{
// Log(LogMsgType.Incoming, "cmd: " + cmdID.ToString());
// Log(LogMsgType.Incoming, BitConverter.ToString(data));
//}
}
}
}
/// <summary>
/// Analog label names 'A'
/// each label name is returned as a single string
/// and added to string array sAnalogLabel[]
/// and the datatable dtAnalog
/// </summary>
/// <param name="s">the label name</param>
void _processLabelNames(string s)
{
//if (iLableIndex < 32)
//{
// sAnalogLabel[iLableIndex] = s;
// if (dtAnalog.Rows.Count < 32)
// dtAnalog.Rows.Add(s, "");
// else
// dtAnalog.Rows[iLableIndex].SetField(0, s);
 
// // _getAnalogLabels(iLableIndex + 1);
//}
//Debug.Print(s);
}
/// <summary>
/// Debug values 'D'
/// </summary>
/// <param name="adr">adress of the active controller (1-FC, 2-NC)</param>
/// <param name="data">the received byte array to process</param>
void _processDebugVals(byte adr, byte[] data)
{
if (data.Length == 66)
{
 
double v;
int index = 0;
Int16 i16 = 0;
double dTemp = 0;
for (int i = 2; i < 66; i += 2)
{
i16 = data[i + 1];
i16 = (Int16)(i16 << 8);
iAnalogData[index] = data[i] + i16;
sAnalogData[index] = (data[i] + i16).ToString();
// dtAnalog.Rows[index].SetField(1, sAnalogData[index]);
 
if (adr == 2) //NC
{
switch (index)
{
case 0: //pitch (German: nick)
Dispatcher.Invoke(() => ArtHor.Pitch = ((double)iAnalogData[index] / (double)10));
Dispatcher.Invoke((Action)(() => tbPitch.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0°")));
break;
case 1: //roll
Dispatcher.Invoke(() => ArtHor.Roll = ((double)iAnalogData[index] / (double)10));
Dispatcher.Invoke((Action)(() => tbRoll.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0°")));
break;
case 4: //altitude
Dispatcher.Invoke(() => tbAlt.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 m"));
Dispatcher.Invoke(() => tbTopHeight.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 m"));
Dispatcher.Invoke(() => { drGPX[3] = (double)iAnalogData[index] / (double)10; });
break;
case 7: //Voltage
v = (double)iAnalogData[index] / (double)10;
Dispatcher.Invoke(() => tbVolt.Text = v.ToString("0.0 V"));
Dispatcher.Invoke(() => tbTopVoltage.Text = v.ToString("0.0 V"));
Dispatcher.Invoke(() => pbTopVoltage.Value = v);
if (v - _dLipoVMin < 1 | v < _dThresholdVoltageWarn)
{
if (v == _dVoltLast)
if (_iVoltJitter < 20) _iVoltJitter++;
else
{
_iVoltJitter = 0;
_dVoltLast = v;
}
_dVoltLast = v;
if (_iVoltJitter == 20)
{
Dispatcher.Invoke(() => pbTopVoltage.Foreground = Brushes.Orange);
 
if (v - _dLipoVMin < 1 | v < _dThresholdVoltageCrit)
{
Dispatcher.Invoke(() => pbTopVoltage.Foreground = Brushes.Red);
if (stbVoltageCritAnim != null && !_bCritAnimVoltActive)
{
Dispatcher.Invoke(() => stbVoltageCritAnim.Begin());
_bCritAnimVoltActive = true;
}
if (_bVoiceVoltPlay && !_bCritVoiceVoltActive)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\CriticalBattery.mp3");
//Thread t = new Thread(() => _mediaPlayer("Voice\\CriticalBattery.mp3"));
//t.Start();
_bCritVoiceVoltActive = true;
}
}
else
{
if (stbVoltageCritAnim != null && _bCritAnimVoltActive)
{
Dispatcher.Invoke(() => stbVoltageCritAnim.Stop());
_bCritAnimVoltActive = false;
}
_bCritVoiceVoltActive = false;
 
if (_bVoiceVoltPlay && !_bWarnVoiceVoltActive)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\LowBattery.mp3");
//Thread t = new Thread(() => _mediaPlayer("Voice\\LowBattery.mp3"));
//t.Start();
_bWarnVoiceVoltActive = true;
}
}
}
}
else
{
Dispatcher.Invoke(() => pbTopVoltage.Foreground = new SolidColorBrush(Color.FromArgb(255, 107, 195, 123)));
if (stbVoltageCritAnim != null && _bCritAnimVoltActive)
{
Dispatcher.Invoke(() => stbVoltageCritAnim.Stop());
_bCritAnimVoltActive = false;
}
_bCritVoiceVoltActive = false;
_bWarnVoiceVoltActive = false;
_iVoltJitter = 0;
}
break;
case 8: // Current
Dispatcher.Invoke(() => tbCur.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 A"));
Dispatcher.Invoke(() => tbTopCurrent.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 A"));
break;
case 10: //heading
Dispatcher.Invoke((Action)(() => tbHeading.Text = sAnalogData[index] + "°"));
if (!_Simulate) //use NavData for simulation
{
Dispatcher.Invoke(() => ArtHor.rotate = iAnalogData[index]);
Dispatcher.Invoke(() => ((CustomMarkerCopter)(copter.Shape)).rotate = iAnalogData[index]);
}
break;
case 12: // SPI error
Dispatcher.Invoke((Action)(() => tbSPI.Text = sAnalogData[index]));
break;
case 14: //i2c error
Dispatcher.Invoke((Action)(() => tbI2C.Text = sAnalogData[index]));
break;
case 20: //Earthmagnet field
Dispatcher.Invoke((Action)(() => tbMagF.Text = sAnalogData[index] + "%"));
Dispatcher.Invoke((Action)(() => tbTopEarthMag.Text = sAnalogData[index] + "%"));
 
if (Math.Abs(100 - iAnalogData[index]) < _iThresholdMagField)
{
Dispatcher.Invoke(() => imageEarthMag.Source = new BitmapImage(new Uri("Images/EarthMag.png", UriKind.Relative)));
_iMagneticFieldJitter = 0; _bVoiceMagneticFieldActive = false;
if (stbMagneticFieldAnim != null && _bAnimMagneticFieldActive)
{
Dispatcher.Invoke(() => stbMagneticFieldAnim.Stop());
_bAnimMagneticFieldActive = false;
}
}
else
{
Dispatcher.Invoke(() => imageEarthMag.Source = new BitmapImage(new Uri("Images/EarthMag_R.png", UriKind.Relative)));
if (_iMagneticFieldLast >= Math.Abs(100 - iAnalogData[index]))
{
if (_iMagneticFieldJitter < 20)
_iMagneticFieldJitter++;
}
else
{
_iMagneticFieldJitter = 0;
_iMagneticFieldLast = Math.Abs(100 - iAnalogData[index]);
}
if (_iMagneticFieldJitter == 20)
{
if (stbMagneticFieldAnim != null && !_bAnimMagneticFieldActive)
{
Dispatcher.Invoke(() => stbMagneticFieldAnim.Begin());
_bAnimMagneticFieldActive = true;
}
if (_bVoiceMagneticFieldPlay && !_bVoiceMagneticFieldActive)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\MagneticField.mp3");
//Thread t = new Thread(() => _mediaPlayer("Voice\\MagneticField.mp3"));
//t.Start();
_bVoiceMagneticFieldActive = true;
}
}
}
break;
case 21: //GroundSpeed
Dispatcher.Invoke((Action)(() => tbSpeed.Text = ((double)iAnalogData[index] / (double)100).ToString("0.00 m/s")));
if (!_Simulate)
Dispatcher.Invoke((Action)(() => tbTopSpeed.Text = ((double)iAnalogData[index] / (double)100).ToString("0.00 m/s")));
break;
 
///********** needs testing --> not sure what position this is ***************
case 28: //Distance East from saved home position -> calculate distance with distance N + height
dTemp = Math.Pow((double)iAnalogData[index], 2) + Math.Pow((double)iAnalogData[index - 1], 2);
dTemp = Math.Sqrt(dTemp) / (double)10; //'flat' distance from HP with N/E
// lblNCDist.Invoke((Action)(() => lblNCDist.Text = dTemp.ToString("0.00")));
dTemp = Math.Pow(dTemp, 2) + Math.Pow(((double)iAnalogData[4] / (double)10), 2); //adding 'height' into calculation
dTemp = Math.Sqrt(dTemp) / (double)10;
// Dispatcher.Invoke((Action)(() => tbTopDistanceHP.Text = dTemp.ToString("0.0 m")));
Dispatcher.Invoke((Action)(() => tbHP1.Text = dTemp.ToString("0.0 m")));
break;
 
case 31: //Sats used
Dispatcher.Invoke((Action)(() => tbSats.Text = sAnalogData[index]));
// Dispatcher.Invoke((Action)(() => tbTopSats.Text = sAnalogData[index]));
break;
}
}
index++;
}
}
else
Debug.Print("wrong data-length (66): " + data.Length.ToString());
}
/// <summary>
/// Version string 'V'
/// </summary>
/// <param name="adr">adress of the active controller (1-FC, 2-NC)</param>
/// <param name="data">the received byte array to process</param>
void _processVersion(byte adr, byte[] data)
{
if (data.Length == 12)
{
if (!check_HWError)
{
string[] sVersionStruct = new string[10] { "SWMajor: ", "SWMinor: ", "ProtoMajor: ", "LabelTextCRC: ", "SWPatch: ", "HardwareError 1: ", "HardwareError 2: ", "HWMajor: ", "BL_Firmware: ", "Flags: " };
string sVersion = "";
//sbyte[] signed = Array.ConvertAll(data, b => unchecked((sbyte)b));
Log(LogMsgType.Warning, (adr == 1 ? "FC-" : "NC-") + "Version: ");
sVersion = "HW V" + (data[7] / 10).ToString() + "." + (data[7] % 10).ToString();
Log(LogMsgType.Incoming, sVersion);
sVersion = "SW V" + (data[0]).ToString() + "." + (data[1]).ToString() + ((char)(data[4] + 'a')).ToString();
Log(LogMsgType.Incoming, sVersion);
Log(LogMsgType.Incoming, "BL-Firmware: V" + (data[8] / 100).ToString() + "." + (data[8] % 100).ToString());
}
if (data[5] > 0) //error0
{
if (adr == 1)
ErrorLog(LogMsgType.Error, " FC - HW-Error " + data[5].ToString() + ": " + ((FC_HWError0)data[5]).ToString(), "", "");
if (adr == 2)
ErrorLog(LogMsgType.Error, " NC - HW-Error " + data[5].ToString() + ": " + ((NC_HWError0)data[5]).ToString(), "", "");
}
if (data[6] > 0) //error1
{
if (adr == 1)
ErrorLog(LogMsgType.Error, " FC - HW-Error " + data[6].ToString() + ": " + ((FC_HWError1)data[6]).ToString(), "", "");
if (adr == 2)
ErrorLog(LogMsgType.Error, " NC - Unknown HW-ERROR: " + data[6].ToString(), "", ""); //@moment NC has only one error field
}
//if ((data[5] + data[6] == 0) && _bErrorLog)
// _clearErrorLog(adr == 1 ? "FC - HW-Error" : "NC - HW-Error");
 
}
check_HWError = false;
}
 
void _processLicense(byte[] data)
{
if (data.Length > 480)
{
Dispatcher.Invoke(() => {
tbDataLicenseUser.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 1, 127));
tbDataLicenseMail.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 129, 127));
tbDataLicenseFeature.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 257, 127));
tbDataLicenseExpire.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 385, 11));
tbDataLicenseLicense.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 397, 16));
});
}
}
/// <summary>
/// BL-Ctrl data 'K'
/// for FC you have to use a customized firmware
/// </summary>
/// <param name="data">the received byte array to process</param>
void _processBLCtrl(byte[] data)
{
if (data.Length % 6 == 0) //data.Length up to 96 (16 motors x 6 byte data) --> new datastruct in FC -> not standard!
{
bool bAvailable = false;
bool bTempError = false;
for (int i = 0; i < data.Length && data[i] < _iMotors; i += 6) // data[i] < _iMotors -- only show set number of motors (12 max @ moment)
{
 
if ((data[i + 4] & 128) == 128) //Status bit at pos 7 = 128 dec -- if true, motor is available
bAvailable = true;
else
bAvailable = false;
 
if (data[i] < _iMotors)
{
if (bAvailable)
{
dtMotors.Rows[data[i]].SetField(1, ((double)data[i + 1] / (double)10).ToString("0.0 A"));
dtMotors.Rows[data[i]].SetField(2, data[i + 2].ToString("0 °C"));
int temp = data[i + 2];
if (temp < _iThresholdBLCTRLTempWarn)
{
_iBLCTRLTempJitter[data[i]] = 0;
}
else
{
if (_iBLCTRLTempLast[data[i]] > _iThresholdBLCTRLTempWarn)
{
if (_iBLCTRLTempJitter[data[i]] < 12)
_iBLCTRLTempJitter[data[i]]++;
}
else
{
_iBLCTRLTempJitter[data[i]] = 0;
}
_iBLCTRLTempLast[data[i]] = temp;
if (_iBLCTRLTempJitter[data[i]] == 12)
{
bTempError = true;
Dispatcher.Invoke(() =>
{
DataGridRow row = (DataGridRow)dgvMotors1.ItemContainerGenerator.ContainerFromIndex(data[i]);
if (row != null)
{
DataGridCell cell = dgvMotors1.Columns[2].GetCellContent(row).Parent as DataGridCell;
if(cell != null)
cell.Background = new SolidColorBrush(Colors.Red);
}
});
if (stbBLCTRLTempAnim != null && !_bAnimBLCTRLTempActive)
{
Dispatcher.Invoke(() => stbBLCTRLTempAnim.Begin());
_bAnimBLCTRLTempActive = true;
}
if (_bVoiceBLCTRLTempPlay && !_bVoiceBLCTRLTempActive)
{
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\BLCtrlTemp.mp3");
_bVoiceBLCTRLTempActive = true;
}
}
}
if(_iBLCTRLTempJitter.All(x=>x<12))
{
_bVoiceBLCTRLTempActive = false;
if (stbBLCTRLTempAnim != null && _bAnimBLCTRLTempActive)
{
Dispatcher.Invoke(() => stbBLCTRLTempAnim.Stop());
_bAnimBLCTRLTempActive = false;
Dispatcher.Invoke(() =>
{
for (int k = 0; k < _iMotors; k++)
{
dgvMotors1.Items.Refresh();
dgvMotors1.UpdateLayout();
 
DataGridRow row = (DataGridRow)dgvMotors1.ItemContainerGenerator.ContainerFromIndex(data[k]);
if (row != null)
{
DataGridCell cell = dgvMotors1.Columns[2].GetCellContent(row).Parent as DataGridCell;
if (cell != null)
cell.Background = new SolidColorBrush(Colors.Transparent);
}
}
});
}
}
}
else
{
dtMotors.Rows[data[i]].SetField(1, "NA");
dtMotors.Rows[data[i]].SetField(2, "NA");
}
}
//if (data[i] > 3 && data[i] < 8)
//{
// if (bAvailable)
// {
// dtMotors2.Rows[data[i] - 4].SetField(1, ((double)data[i + 1] / (double)10).ToString("0.0 A"));
// dtMotors2.Rows[data[i] - 4].SetField(2, data[i + 2].ToString("0 °C"));
// }
// else
// {
// dtMotors2.Rows[data[i] - 4].SetField(1, "NA");
// dtMotors2.Rows[data[i] - 4].SetField(2, "NA");
// }
//}
}
}
}
/// <summary>
/// Navi-Ctrl data 'O'
/// GPS-Position, capacatiy, flying time...
/// </summary>
/// <param name="data">the received byte array to process</param>
 
 
byte OSDSTATUSFLAGS1 = 0;
byte OSDSTATUSFLAGS2 = 0;
void _processNCDataV2(byte[] data)
{
if ((int)data[0] < 17)
{
int i_32, i_16, iVal;
double d;
OSD_Base_Data_t osd = new OSD_Base_Data_t(data);
OSDSTATUSFLAGS1 = osd.OSDSTATUSFLAGS1();
Dispatcher.Invoke(() => { drGPX[2] = osd.Pos().Lng; });
Dispatcher.Invoke(() => { drGPX[1] = osd.Pos().Lat; });
Dispatcher.Invoke(() => { drGPX[4] = DateTime.UtcNow.ToString("u", System.Globalization.CultureInfo.InvariantCulture); }); //2011-01-14T01:59:01Z });
Dispatcher.Invoke((Action)(() => tbNCGrSpeed.Text = osd.Speed().ToString("0.0 m/s")));
if (_Simulate)
Dispatcher.Invoke((Action)(() => tbTopSpeed.Text = osd.Speed().ToString("0.0 m/s")));
 
switch ((int)data[0])
{
case 10:
char[] c = Encoding.ASCII.GetChars(new byte[] { data[13] });
Dispatcher.Invoke((Action)(() => tbCamCtrl.Text = c[0].ToString()));
break;
case 11:
OSDSTATUSFLAGS2 = osd.OSDSTATUSFLAGS2();
//---------------NC-Flags--------------------------
Dispatcher.Invoke((Action)(() => NC1_2.Background = ((data[14] & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_PH 0x02
Dispatcher.Invoke((Action)(() => NC1_3.Background = ((data[14] & 4) == 4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => NC1_4.Background = ((data[14] & 8) == 8) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_RANGE_LIMIT 0x08
Dispatcher.Invoke((Action)(() => NC1_5.Background = ((data[14] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_NOSERIALLINK 0x10
Dispatcher.Invoke((Action)(() => NC1_6.Background = ((data[14] & 32) == 32) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_TARGET_REACHED 0x20
Dispatcher.Invoke((Action)(() => NC1_7.Background = ((data[14] & 64) == 64) ? new SolidColorBrush(Colors.DodgerBlue) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_MANUAL_CONTROL 0x40
Dispatcher.Invoke((Action)(() => NC1_8.Background = ((data[14] & 128) == 128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_GPS_OK 0x80
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Text = ((data[14] & 4) == 4) ? "CH" : "PH"));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Background = (((data[14] & 2) == 2) | ((data[14] & 4) == 4)) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Foreground = (((data[14] & 2) == 2) | ((data[14] & 4) == 4)) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.BorderBrush = (((data[14] & 2) == 2) | ((data[14] & 4) == 4)) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
 
//--------------- NC Error ------------------------
Dispatcher.Invoke((Action)(() => tbNCErr.Text = data[16].ToString())); //NC Errornumber
if (data[16] > 0)
_readNCError();
if (data[16] > 0 & data[16] < 44)
ErrorLog(LogMsgType.Error, " NC Error [" + data[16].ToString() + "]: ", NC_Error_Link[data[16]], NC_Error[data[16]]);
 
break;
case 12:
//--------------- RC quality ------------------------
Dispatcher.Invoke((Action)(() => tbRCQ.Text = data[23].ToString()));
Dispatcher.Invoke((Action)(() => tbTopRC.Text = data[23].ToString()));
 
if (data[23] > _iThresholdRC)
{
_iRCLevelJitter = 0; _bVoiceRCLevelActive = false;
if (stbRCLevelAnim != null && _bAnimRCLevelActive)
{
Dispatcher.Invoke(() => stbRCLevelAnim.Stop());
_bAnimRCLevelActive = false;
}
}
else
{
if (_iRCLevelJitter < 20) _iRCLevelJitter++;
if (_iRCLevelJitter == 20)
{
if (stbRCLevelAnim != null && !_bAnimRCLevelActive)
{
Dispatcher.Invoke(() => stbRCLevelAnim.Begin());
_bAnimRCLevelActive = true;
}
if (_bVoiceRCLevelPlay && !_bVoiceRCLevelActive)
{
_bVoiceRCLevelActive = true;
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\RCLevel.mp3");
//Thread th = new Thread(() => _mediaPlayer("Voice\\RCLevel.mp3"));
//th.Start();
}
_iRCLevelJitter++;
}
}
break;
case 13:
//-------------------------Waypoint max range (by license)------------------------------
i_32 = data[24];
iVal = i_32 << 8;
iVal += data[23];
 
if (dWPMaxRange != iVal)
{
dWPMaxRange = iVal;
if (home != null && checkBoxShowWPMaxRange.IsChecked == true)
{
if (cWPBound != null && cWPBound.Tag != null)
MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
 
createCircle(home.Position, dWPMaxRange);
Dispatcher.Invoke(() =>
{
if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
{
string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
cWPBound.setColor(s);
}
});
}
Dispatcher.Invoke((Action)(() => tbWPMaxRange.Text = iVal.ToString() + " m"));
}
//--------------- LiPoCell count ------------------------
Dispatcher.Invoke((Action)(() => tbLiPoCells.Text = data[25].ToString()));
Dispatcher.Invoke((Action)(() => {
if (_bLiPoAutoDetect == true)
{
if(data[25] > 2 && data[25] < 7 && _LipoCells != data[25])
{
cBoxLiPoCells.SelectedIndex = data[25] - 3;
_LipoCells = data[25];
_LipoMinMax();
}
}
}));
 
break;
 
case 14:
//--------------- Flying time ------------------------
i_16 = data[14];
i_16 = (Int16)(i_16 << 8);
iVal = data[13] + i_16;
TimeSpan t = TimeSpan.FromSeconds(iVal);
string Text = t.Hours.ToString("D2") + ":" + t.Minutes.ToString("D2") + ":" + t.Seconds.ToString("D2");
Dispatcher.Invoke((Action)(() => tbFTime.Text = Text.ToString()));
Dispatcher.Invoke((Action)(() => tbTopFTime.Text = Text.ToString()));
 
//--------------------------------Distance HP------------------------------------
i_16 = data[16];
i_16 = (Int16)(i_16 << 8);
iVal = data[15] + i_16;
Dispatcher.Invoke((Action)(() => tbHP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
 
//--------------------------Distance to next WP--------------------------------
i_16 = data[19];
i_16 = (Int16)(i_16 << 8);
iVal = data[18] + i_16;
Dispatcher.Invoke((Action)(() => tbWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
Dispatcher.Invoke((Action)(() => lblWPRouteDistanceWP.Content = ((double)iVal / (double)10).ToString("0.0 m")));
Dispatcher.Invoke((Action)(() => tbWPStatusDistanceWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
 
//-------------------Satellites----------------------------------
Dispatcher.Invoke((Action)(() => tbTopSats.Text = data[23].ToString()));
 
if (data[23] > 4)//if more than 4 sats in use . otherwise the map would jump and scroll insane at beginning
{
_bSatFix = true; _iSatsJitter = 0; _bVoiceSatFixActive = false;
if (_bAutoHome && !_bFirstSatFix)
{
if (_iFirstSatFix < 3)
_iFirstSatFix++;
else
{
_bFirstSatFix = true;
Dispatcher.Invoke(() => _setHomePos());
}
}
if (stbSatFixLostAnim != null && _bAnimSatFixActive)
{
Dispatcher.Invoke(() => stbSatFixLostAnim.Stop());
_bAnimSatFixActive = false;
}
if (!_bFollowCopter)
{
_setCopterData(osd.Pos());
if (!MainMap.ViewArea.Contains(osd.Pos()))
Dispatcher.Invoke(() => MainMap.Position = osd.Pos());
 
}
else
Dispatcher.Invoke(() => MainMap.Position = osd.Pos());
}
else
{
if (_bSatFix)
{
if (data[23] == _iSatsLast)
{
if (_iSatsJitter < 20) _iSatsJitter++;
}
else
{
_iSatsJitter = 0;
_iSatsLast = data[23];
}
 
if (_iSatsJitter == 20)
{
if (stbSatFixLostAnim != null && !_bAnimSatFixActive)
{
Dispatcher.Invoke(() => stbSatFixLostAnim.Begin());
_bAnimSatFixActive = true;
}
if (_bVoiceSatFixPlay && !_bVoiceSatFixActive)
{
_bVoiceSatFixActive = true;
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\SatFixLost.mp3");
//Thread th = new Thread(() => _mediaPlayer("Voice\\SatFixLost.mp3"));
//th.Start();
}
 
_bSatFix = false;
}
}
}
 
break;
 
case 15:
//--------------------------------Waypoint index------------------------------------
Dispatcher.Invoke((Action)(() => tbWPIndex.Text = data[13].ToString()));
Dispatcher.Invoke((Action)(() => lblWPIndexNC.Content = data[13].ToString()));
Dispatcher.Invoke((Action)(() => lblWPStatusIndexNC.Content = data[13].ToString()));
if (data[13] > 0 && _wpIndex != data[13] - 1 && wpList.Count > data[13] - 1)
{
_setActiveWP(data[13] - 1);
if ((OSDSTATUSFLAGS2 & 2) == 2)
Dispatcher.Invoke(() =>
{
DataGridRow row;
if (_wpIndex > -1)
{
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
row.Background = new SolidColorBrush(Colors.Transparent);
row.BorderBrush = new SolidColorBrush(Colors.Transparent);
row.BorderThickness = new Thickness(0);
}
 
_wpIndex = data[13] - 1;
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 255, 100));
row.BorderBrush = new SolidColorBrush(Colors.SpringGreen);
row.BorderThickness = new Thickness(2);
dgvWP.UpdateLayout();
});
_wpIndex = data[13] - 1;
}
else
{
if ((data[13] == 0 || wpList.Count == 0) & MainMap.Markers.Contains(wpActiveMarker))
{
Dispatcher.Invoke(() => MainMap.Markers.Remove(wpActiveMarker));
Dispatcher.Invoke(() =>
{
DataGridRow row;
if (_wpIndex > -1 && data[13] == 0 && wpList.Count > _wpIndex)
{
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
row.Background = new SolidColorBrush(Colors.Transparent);
row.BorderBrush = new SolidColorBrush(Colors.Transparent);
row.BorderThickness = new Thickness(0);
_wpIndex = -1;
}
});
 
}
}
//----------------Waypoints count----------------------
Dispatcher.Invoke((Action)(() => tbWPCount.Text = data[14].ToString())); //Waypoints count
Dispatcher.Invoke((Action)(() => lblWPCountNC.Content = data[14].ToString())); //Waypoints count
Dispatcher.Invoke((Action)(() => lblWPStatusCountNC.Content = data[14].ToString())); //Waypoints count
_wpCount = data[14];
if(_wpCount > dtWaypoints.Rows.Count)
{
Log(LogMsgType.Warning, "The copter reports more waypoints than there are in the local list!");
}
 
//---------------------------------Target hold time------------------------------
Dispatcher.Invoke((Action)(() => lblWPHoldTime.Content = data[15].ToString() + " s"));
Dispatcher.Invoke((Action)(() => tbWPStatusHoldTime.Text = data[15].ToString() + " s"));
 
break;
 
case 16:
//--------------- Capacity used ------------------------
i_16 = data[18];
i_16 = (Int16)(i_16 << 8);
iVal = data[17] + i_16;
Dispatcher.Invoke((Action)(() => tbCapacity.Text = iVal.ToString() + " mAh"));
Dispatcher.Invoke((Action)(() => tbTopCapacity.Text = iVal.ToString() + " mAh"));
 
//--------------- Heading compass ------------------------
i_16 = data[21];
iVal = 2 * i_16;
Dispatcher.Invoke((Action)(() => tbHeadingCompass.Text = iVal.ToString() + " °"));
if (_Simulate)
{
Dispatcher.Invoke(() => ArtHor.rotate = iVal);
Dispatcher.Invoke(() => ((CustomMarkerCopter)(copter.Shape)).rotate = iVal);
}
 
break;
case 17:
 
break;
case 18:
 
break;
default:
break;
}
//--------------------------------------------------------------------------------
//-----------------------------FC Status Flags-------------------------------
//--------------------------------------------------------------------------------
Dispatcher.Invoke((Action)(() => FC1_1.Background = ((OSDSTATUSFLAGS2 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN 0x01
Dispatcher.Invoke((Action)(() => FC1_2.Background = ((OSDSTATUSFLAGS2 & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_FLY 0x02
Dispatcher.Invoke((Action)(() => FC1_3.Background = ((OSDSTATUSFLAGS1 & 4) == 4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_CALIBRATE 0x04
Dispatcher.Invoke((Action)(() => FC1_4.Background = ((OSDSTATUSFLAGS2 & 8) == 8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_START 0x08
Dispatcher.Invoke((Action)(() => FC1_5.Background = ((OSDSTATUSFLAGS2 & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING 0x10
Dispatcher.Invoke((Action)(() => FC1_6.Background = ((OSDSTATUSFLAGS1 & 32) == 32) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_LOWBAT 0x20
 
Dispatcher.Invoke((Action)(() => FC2_1.Background = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE 0x01
Dispatcher.Invoke((Action)(() => FC2_2.Background = ((OSDSTATUSFLAGS1 & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL 0x02
Dispatcher.Invoke((Action)(() => FC2_3.Background = ((OSDSTATUSFLAGS2 & 4) == 4) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_RC_FAILSAVE_ACTIVE 0x04
Dispatcher.Invoke((Action)(() => FC2_4.Background = ((OSDSTATUSFLAGS1 & 8) == 8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT1_ACTIVE 0x08
Dispatcher.Invoke((Action)(() => FC2_5.Background = ((OSDSTATUSFLAGS1 & 16) == 16) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT2_ACTIVE 0x10
Dispatcher.Invoke((Action)(() => FC2_6.Background = ((OSDSTATUSFLAGS2 & 32) == 32) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_WAIT_FOR_TAKEOFF 0x20 // Motor Running, but still on the ground
Dispatcher.Invoke((Action)(() => FC2_7.Background = ((OSDSTATUSFLAGS2 & 64) == 64) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_STARTING 0x40
Dispatcher.Invoke((Action)(() => FC2_8.Background = ((OSDSTATUSFLAGS2 & 128) == 128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_LANDING 0x80
 
//Sidebar StatusSymbols
Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.Background = ((OSDSTATUSFLAGS2 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.Foreground = ((OSDSTATUSFLAGS2 & 1) == 1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS_MOTOR_RUN 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.BorderBrush = ((OSDSTATUSFLAGS2 & 1) == 1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS_MOTOR_RUN 0x01
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Background = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Foreground = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_CAREFREE 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.BorderBrush = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_CAREFREE 0x01
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.Background = ((OSDSTATUSFLAGS2 & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING 0x10
Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.Foreground = ((OSDSTATUSFLAGS2 & 16) == 16) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS_EMERGENCY_LANDING 0x10
Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.BorderBrush = ((OSDSTATUSFLAGS2 & 16) == 16) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS_EMERGENCY_LANDING 0x10
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.Background = ((OSDSTATUSFLAGS1 & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL 0x02
Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.Foreground = ((OSDSTATUSFLAGS1 & 2) == 2) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_ALTITUDE_CONTROL 0x02
Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.BorderBrush = ((OSDSTATUSFLAGS1 & 2) == 2) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_ALTITUDE_CONTROL 0x02
 
_bAirborne = (OSDSTATUSFLAGS2 & 2) == 2 ? true : false;
}
}
public class OSD_Base_Data_t
{
byte[] data;
 
public OSD_Base_Data_t(byte [] _data)
{
data = _data;
}
 
public PointLatLng Pos()
{
PointLatLng p = new PointLatLng();
int i_32, iVal;
double d;
 
i_32 = data[4];
iVal = i_32 << 24;
i_32 = data[3];
iVal += i_32 << 16;
i_32 = data[2];
iVal += i_32 << 8;
iVal += data[1];
d = (double)iVal / Math.Pow(10, 7);
p.Lng = d;
 
i_32 = data[8];
iVal = i_32 << 24;
i_32 = data[7];
iVal += i_32 << 16;
i_32 = data[6];
iVal += i_32 << 8;
iVal += data[5];
d = (double)iVal / Math.Pow(10, 7);
p.Lat = d;
 
return p;
 
}
 
public int Height()
{
int i_32, iVal;
i_32 = data[10];
iVal = i_32 << 8;
iVal += data[9];
 
return iVal;
}
 
public double Speed()
{
if (data.Length > 11)
return (double)data[11]/10;
else return 0;
}
 
public byte OSDSTATUSFLAGS1()
{
if (data.Length > 12)
return data[12];
else return 0;
}
public byte OSDSTATUSFLAGS2()
{
if (data.Length > 13)
return data[13];
else return 0;
}
}
void _processNCData(byte[] data)
{
int i_32, i_16, iVal;
double d;
 
//----------------------------POSITION------------------------------------
i_32 = data[4];
iVal = i_32 << 24;
i_32 = data[3];
iVal += i_32 << 16;
i_32 = data[2];
iVal += i_32 << 8;
iVal += data[1];
d = (double)iVal / Math.Pow(10, 7);
Dispatcher.Invoke(() => { drGPX[2] = d; });
 
PointLatLng p = new PointLatLng();
 
p.Lng = d;
// lblNCGPSLong.Invoke((Action)(() => lblNCGPSLong.Text = d.ToString("0.######°"))); //GPS-Position: Longitude in decimal degree
//lblNCGPSLong.Invoke((Action)(() => lblNCGPSLong.Text = _convertDegree(d))); //GPS-Position: Longitude in minutes, seconds
 
i_32 = data[8];
iVal = i_32 << 24;
i_32 = data[7];
iVal += i_32 << 16;
i_32 = data[6];
iVal += i_32 << 8;
iVal += data[5];
d = (double)iVal / Math.Pow(10, 7);
Dispatcher.Invoke(() => { drGPX[1] = d; });
Dispatcher.Invoke(() => { drGPX[4] = DateTime.UtcNow.ToString("u", System.Globalization.CultureInfo.InvariantCulture); }); //2011-01-14T01:59:01Z });
p.Lat = d;
 
//---------------------------SATS-------------------------------------------------
if (data[50] > 4)//if more than 4 sats in use . otherwise the map would jump and scroll insane at beginning
{
_bSatFix = true; _iSatsJitter = 0; _bVoiceSatFixActive = false;
if(_bAutoHome && !_bFirstSatFix)
{
if (_iFirstSatFix < 3)
_iFirstSatFix++;
else
{
_bFirstSatFix = true;
Dispatcher.Invoke(() => _setHomePos());
}
}
if (stbSatFixLostAnim != null && _bAnimSatFixActive)
{
Dispatcher.Invoke(() => stbSatFixLostAnim.Stop());
_bAnimSatFixActive = false;
}
if (!_bFollowCopter)
{
_setCopterData(p);
if (!MainMap.ViewArea.Contains(p))
Dispatcher.Invoke(() => MainMap.Position = p);
 
}
else
Dispatcher.Invoke(() => MainMap.Position = p);
}
else
{
if(_bSatFix)
{
if (data[50] == _iSatsLast)
{
if (_iSatsJitter < 20) _iSatsJitter++;
}
else
{
_iSatsJitter = 0;
_iSatsLast = data[50];
}
 
if (_iSatsJitter == 20)
{
if (stbSatFixLostAnim != null && !_bAnimSatFixActive)
{
Dispatcher.Invoke(() => stbSatFixLostAnim.Begin());
_bAnimSatFixActive = true;
}
if (_bVoiceSatFixPlay && !_bVoiceSatFixActive)
{
_bVoiceSatFixActive = true;
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\SatFixLost.mp3");
//Thread th = new Thread(() => _mediaPlayer("Voice\\SatFixLost.mp3"));
//th.Start();
}
 
_bSatFix = false;
}
}
}
 
//--------------------------Distance to next WP--------------------------------
i_16 = data[28];
i_16 = (Int16)(i_16 << 8);
iVal = data[27] + i_16;
Dispatcher.Invoke((Action)(() => tbWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
Dispatcher.Invoke((Action)(() => lblWPRouteDistanceWP.Content = ((double)iVal / (double)10).ToString("0.0 m")));
Dispatcher.Invoke((Action)(() => tbWPStatusDistanceWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
 
//-------------------------Distance to HP set by GPS on----------------------------------
i_16 = data[45];
i_16 = (Int16)(i_16 << 8);
iVal = data[44] + i_16;
Dispatcher.Invoke((Action)(() => tbHP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
 
//--------------------------------Waypoint index------------------------------------
Dispatcher.Invoke((Action)(() => tbWPIndex.Text = data[48].ToString()));
Dispatcher.Invoke((Action)(() => lblWPIndexNC.Content = data[48].ToString()));
Dispatcher.Invoke((Action)(() => lblWPStatusIndexNC.Content = data[48].ToString()));
if(data[48] > 0 && _wpIndex != data[48] -1 && wpList.Count >= data[48] -1)
{
_setActiveWP(data[48]- 1);
if((data[67] & 2) == 2)
Dispatcher.Invoke(() => {
DataGridRow row;
if (_wpIndex > -1)
{
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
row.Background = new SolidColorBrush(Colors.Transparent);
row.BorderBrush = new SolidColorBrush(Colors.Transparent);
row.BorderThickness = new Thickness(0);
}
 
_wpIndex = data[48] - 1;
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 255, 100));
row.BorderBrush = new SolidColorBrush(Colors.SpringGreen);
row.BorderThickness = new Thickness(2);
dgvWP.UpdateLayout();
});
_wpIndex = data[48]- 1;
}
else
{
if ((data[48] == 0 || wpList.Count == 0) & MainMap.Markers.Contains(wpActiveMarker))
{
Dispatcher.Invoke(() => MainMap.Markers.Remove(wpActiveMarker));
Dispatcher.Invoke(() =>
{
DataGridRow row;
if (_wpIndex > -1 && data[48] == 0 && wpList.Count > _wpIndex)
{
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
row.Background = new SolidColorBrush(Colors.Transparent);
row.BorderBrush = new SolidColorBrush(Colors.Transparent);
row.BorderThickness = new Thickness(0);
_wpIndex = -1;
}
});
 
}
}
//----------------Waypoints count----------------------
Dispatcher.Invoke((Action)(() => tbWPCount.Text = data[49].ToString())); //Waypoints count
Dispatcher.Invoke((Action)(() => lblWPCountNC.Content = data[49].ToString())); //Waypoints count
Dispatcher.Invoke((Action)(() => lblWPStatusCountNC.Content = data[49].ToString())); //Waypoints count
_wpCount = data[49];
//-------------------Satellites----------------------------------
Dispatcher.Invoke((Action)(() => tbTopSats.Text = data[50].ToString()));
 
//--------------- Capacity used ------------------------
i_16 = data[81];
i_16 = (Int16)(i_16 << 8);
iVal = data[80] + i_16;
Dispatcher.Invoke((Action)(() => tbCapacity.Text = iVal.ToString() + " mAh"));
Dispatcher.Invoke((Action)(() => tbTopCapacity.Text = iVal.ToString() + " mAh"));
 
//--------------- Ground speed ------------------------
i_16 = data[59];
i_16 = (Int16)(i_16 << 8);
iVal = data[58] + i_16;
Dispatcher.Invoke((Action)(() => tbNCGrSpeed.Text = ((double)(iVal)/100).ToString("0.00 m/s")));
if(_Simulate)
Dispatcher.Invoke((Action)(() => tbTopSpeed.Text = ((double)(iVal)/100).ToString("0.00 m/s")));
 
//--------------- Heading north ------------------------
//i_16 = data[61];
//i_16 = (Int16)(i_16 << 8);
//iVal = data[60] + i_16;
//Dispatcher.Invoke((Action)(() => tbHeadingNorth.Text = iVal.ToString() + " °"));
 
//--------------- Heading compass ------------------------
i_16 = data[63];
i_16 = (Int16)(i_16 << 8);
iVal = data[62] + i_16;
Dispatcher.Invoke((Action)(() => tbHeadingCompass.Text = iVal.ToString() + " °"));
if (_Simulate)
{
Dispatcher.Invoke(() => ArtHor.rotate = iVal);
Dispatcher.Invoke(() => ((CustomMarkerCopter)(copter.Shape)).rotate = iVal);
}
//--------------- Flying time ------------------------
i_16 = data[56];
i_16 = (Int16)(i_16 << 8);
iVal = data[55] + i_16;
TimeSpan t = TimeSpan.FromSeconds(iVal);
string Text = t.Hours.ToString("D2") + ":" + t.Minutes.ToString("D2") + ":" + t.Seconds.ToString("D2");
Dispatcher.Invoke((Action)(() => tbFTime.Text = Text.ToString()));
Dispatcher.Invoke((Action)(() => tbTopFTime.Text = Text.ToString()));
 
//--------------- RC quality ------------------------
Dispatcher.Invoke((Action)(() => tbRCQ.Text = data[66].ToString()));
Dispatcher.Invoke((Action)(() => tbTopRC.Text = data[66].ToString()));
 
if(data[66] > _iThresholdRC)
{
_iRCLevelJitter = 0; _bVoiceRCLevelActive = false;
if (stbRCLevelAnim != null && _bAnimRCLevelActive)
{
Dispatcher.Invoke(() => stbRCLevelAnim.Stop());
_bAnimRCLevelActive = false;
}
}
else
{
if (_iRCLevelJitter < 20) _iRCLevelJitter++;
if (_iRCLevelJitter == 20)
{
if (stbRCLevelAnim != null && !_bAnimRCLevelActive)
{
Dispatcher.Invoke(() => stbRCLevelAnim.Begin());
_bAnimRCLevelActive = true;
}
if (_bVoiceRCLevelPlay && !_bVoiceRCLevelActive)
{
_bVoiceRCLevelActive = true;
ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\" + _voiceLanguage[_iVoiceIndex] + "\\MagneticField.mp3");
//Thread th = new Thread(() => _mediaPlayer("Voice\\RCLevel.mp3"));
//th.Start();
}
_iRCLevelJitter++;
}
}
 
//-------------------------Waypoint max range (by license)------------------------------
if(dWPMaxRange != (double)data[70])
{
dWPMaxRange = (double)data[70];
if (home != null && checkBoxShowWPMaxRange.IsChecked == true)
{
if (cWPBound != null && cWPBound.Tag != null)
MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
 
createCircle(home.Position, dWPMaxRange);
Dispatcher.Invoke(() =>
{
if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
{
string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
cWPBound.setColor(s);
}
});
}
Dispatcher.Invoke((Action)(() => tbWPMaxRange.Text = data[70].ToString() + " m"));
}
//---------------------------------Target hold time------------------------------
Dispatcher.Invoke((Action)(() => lblWPHoldTime.Content = data[73].ToString()+ " s"));
Dispatcher.Invoke((Action)(() => tbWPStatusHoldTime.Text = data[73].ToString()+ " s"));
 
//--------------- NC Error ------------------------
Dispatcher.Invoke((Action)(() => tbNCErr.Text = data[69].ToString())); //NC Errornumber
if (data[69] > 0)
_readNCError();
if (data[69] > 0 & data[69] < 44)
ErrorLog(LogMsgType.Error," NC Error [" + data[69].ToString() + "]: ",NC_Error_Link[data[69]], NC_Error[data[69]]);
//else
// if (_bErrorLog) _clearErrorLog("NC Error");
 
//--------------------------------------------------------------------------------
//-----------------------------FC / NC Status Flags-------------------------------
//--------------------------------------------------------------------------------
Dispatcher.Invoke((Action)(() => FC1_1.Background = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN 0x01
Dispatcher.Invoke((Action)(() => FC1_2.Background = ((data[67] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_FLY 0x02
Dispatcher.Invoke((Action)(() => FC1_3.Background = ((data[67] & 4) ==4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_CALIBRATE 0x04
Dispatcher.Invoke((Action)(() => FC1_4.Background = ((data[67] & 8) ==8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_START 0x08
Dispatcher.Invoke((Action)(() => FC1_5.Background = ((data[67] & 16) ==16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING 0x10
Dispatcher.Invoke((Action)(() => FC1_6.Background = ((data[67] & 32) ==32) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_LOWBAT 0x20
 
Dispatcher.Invoke((Action)(() => FC2_1.Background = ((data[74] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE 0x01
Dispatcher.Invoke((Action)(() => FC2_2.Background = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL 0x02
Dispatcher.Invoke((Action)(() => FC2_3.Background = ((data[74] & 4) ==4) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_RC_FAILSAVE_ACTIVE 0x04
Dispatcher.Invoke((Action)(() => FC2_4.Background = ((data[74] & 8) ==8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT1_ACTIVE 0x08
Dispatcher.Invoke((Action)(() => FC2_5.Background = ((data[74] & 16) ==16) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT2_ACTIVE 0x10
Dispatcher.Invoke((Action)(() => FC2_6.Background = ((data[74] & 32) ==32) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_WAIT_FOR_TAKEOFF 0x20 // Motor Running, but still on the ground
Dispatcher.Invoke((Action)(() => FC2_7.Background = ((data[74] & 64) ==64) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_STARTING 0x40
Dispatcher.Invoke((Action)(() => FC2_8.Background = ((data[74] & 128) ==128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_LANDING 0x80
 
Dispatcher.Invoke((Action)(() => NC1_2.Background = ((data[68] & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_PH 0x02
Dispatcher.Invoke((Action)(() => NC1_3.Background = ((data[68] & 4) == 4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => NC1_4.Background = ((data[68] & 8) == 8) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_RANGE_LIMIT 0x08
Dispatcher.Invoke((Action)(() => NC1_5.Background = ((data[68] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_NOSERIALLINK 0x10
Dispatcher.Invoke((Action)(() => NC1_6.Background = ((data[68] & 32) == 32) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_TARGET_REACHED 0x20
Dispatcher.Invoke((Action)(() => NC1_7.Background = ((data[68] & 64) == 64) ? new SolidColorBrush(Colors.DodgerBlue) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_MANUAL_CONTROL 0x40
Dispatcher.Invoke((Action)(() => NC1_8.Background = ((data[68] & 128) == 128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_GPS_OK 0x80
 
//Sidebar StatusSymbols
Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.Background = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.Foreground = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255,211,210,210))));// FC_STATUS_MOTOR_RUN 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.BorderBrush = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS_MOTOR_RUN 0x01
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Background = ((data[74] & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Foreground = ((data[74] & 1) == 1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_CAREFREE 0x01
Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.BorderBrush = ((data[74] & 1) ==1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_CAREFREE 0x01
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.Background = ((data[67] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING 0x10
Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.Foreground = ((data[67] & 16) == 16) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS_EMERGENCY_LANDING 0x10
Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.BorderBrush = ((data[67] & 16) == 16) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS_EMERGENCY_LANDING 0x10
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.Background = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL 0x02
Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.Foreground = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_ALTITUDE_CONTROL 0x02
Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.BorderBrush = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_ALTITUDE_CONTROL 0x02
 
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Text = ((data[68] & 4) == 4) ? "CH" : "PH"));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Background = (((data[68] & 2) == 2)|((data[68] & 4) == 4)) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Foreground = (((data[68] & 2) == 2)|((data[68] & 4) == 4)) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.BorderBrush = (((data[68] & 2) == 2)|((data[68] & 4) == 4)) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
 
_bAirborne = (data[67] & 2) == 2 ? true : false;
}
/// <summary>
/// Navi-Ctrl WP data struct 'X'
/// called by index
/// </summary>
/// <param name="data">the received byte array to process</param>
void _processWPData(byte[] data)
{
_iWPCount = data[0];
_bGetWPCount = false;
if (data.Length >= 28)
{
Dispatcher.Invoke(() => lblWPIndex.Content = data[1].ToString());
Dispatcher.Invoke(() => lblWPCount.Content = data[0].ToString());
if (_bGetWP)
{
if (data[1] == 1)
{
Dispatcher.Invoke(() =>
{
wpList.Clear();
_clearMapMarkers(typeof(CustomMarkerWP));
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
if (wpActiveMarker != null)
MainMap.Markers.Remove(wpActiveMarker);
lblWPRouteDistance.Content = "0 m";
dtWaypoints.Rows.Clear();
_wpEdit = -1;_wpIndex = -1;
wpOffset.Clear();
});
}
DataRow dr = dtWaypoints.NewRow();
dr = Waypoints.toDataRow(data, dr);
dtWaypoints.Rows.Add(dr);
_createWP(new PointLatLng((double)dr[3], (double)dr[4]), (string)dr[2], (int)dr[1],(int)data[1]-1);
Dispatcher.Invoke(() => dgvWP.Items.Refresh());
Dispatcher.Invoke(() => _iWPIndex = data[1]);
if (data[1] == data[0])
{
_bGetWP = false;
_routeUpdate();
}
 
}
}
else
{
Dispatcher.Invoke(() => lblWPIndex.Content = 0);
Dispatcher.Invoke(() => lblWPCount.Content = 0);
}
}
/// <summary>
/// OSD Menue 'L'
/// single page called by pagenumber
/// no autoupdate
/// </summary>
/// <param name="data">the received byte array to process</param>
void _processOSDSingle(byte[] data)
{
if (data.Length == 84)
{
string sMessage = "";
iOSDPage = data[0];
iOSDMax = data[1];
if (cbOSD.Items.Count != iOSDMax) _initOSDCB();
sMessage = new string(ASCIIEncoding.ASCII.GetChars(data, 2, data.Length - 4));
OSD(LogMsgType.Incoming, sMessage.Substring(0, 20)+ "\r", true);
OSD(LogMsgType.Incoming, sMessage.Substring(20, 20)+ "\r", false);
OSD(LogMsgType.Incoming, sMessage.Substring(40, 20)+ "\r", false);
OSD(LogMsgType.Incoming, sMessage.Substring(60, 20), false);
Dispatcher.Invoke(() => { cbOSD.SelectedValue = iOSDPage; });
// lblOSDPageNr.Invoke((Action)(() => lblOSDPageNr.Text = iOSDPage.ToString("[0]")));
 
}
//else
// OSD(LogMsgType.Incoming, "Wrong length: " + data.Length + " (should be 84)");
 
}
/// <summary>
/// OSD Menue 'H'
/// called by keys (0x01,0x02,0x03,0x04)
/// autoupdate
/// </summary>
/// <param name="data">the received byte array to process</param>
void _processOSDAuto(byte[] data)
{
if (data.Length == 81)
{
string sMessage = "";
sMessage = new string(ASCIIEncoding.ASCII.GetChars(data, 0, data.Length - 1));
OSD(LogMsgType.Incoming, sMessage.Substring(0, 20)+ "\r", true);
OSD(LogMsgType.Incoming, sMessage.Substring(20, 20)+ "\r", false);
OSD(LogMsgType.Incoming, sMessage.Substring(40, 20)+ "\r", false);
OSD(LogMsgType.Incoming, sMessage.Substring(60, 20), false);
 
}
//else
// OSD(LogMsgType.Incoming, "Wrong length: " + data.Length + " (should be 81)");
}
 
#endregion processing received data
#region controller messages
/// <summary> send message to controller to request data
/// for detailed info see http://wiki.mikrokopter.de/en/SerialProtocol/
/// </summary>
/// <param name="CMDID"> the command ID </param>
/// <param name="address"> the address of the controller: 0-any, 1-FC, 2-NC </param>
private void _sendControllerMessage(char CMDID, byte address)
{
if (serialPortCtrl.Port.IsOpen)
{
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes = FlightControllerMessage.CreateMessage(CMDID, address);
serialStream.Write(bytes, 0, bytes.Length);
 
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
}
/// <summary> send message to controller to request data
/// for detailed info see http://wiki.mikrokopter.de/en/SerialProtocol/
/// </summary>
/// <param name="CMDID"> the command ID </param>
/// <param name="address"> the address of the controller: 0-any, 1-FC, 2-NC </param>
/// <param name="data"> additional data for the request</param>
private void _sendControllerMessage(char CMDID, byte address, byte[] data)
{
if (serialPortCtrl.Port.IsOpen)
{
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes = FlightControllerMessage.CreateMessage(CMDID, address, data);
serialStream.Write(bytes, 0, bytes.Length);
 
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
}
 
/// <summary>
/// start/stop continous polling of controller values
/// </summary>
/// <param name="b">start/stop switch</param>
void _readCont(bool b)
{
bReadContinously = b;
if (bReadContinously)
{
if (_debugDataAutorefresh) { _readDebugData(true); Thread.Sleep(10); }
if (_blctrlDataAutorefresh) { _readBLCtrl(true); Thread.Sleep(10); }
if (_navCtrlDataAutorefresh && _iCtrlAct == 2) { _readNavData(true); Thread.Sleep(10); }
if (_OSDAutorefresh) { _OSDMenueAutoRefresh(); Thread.Sleep(10); }
// Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGreen));
Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_G.png", UriKind.Relative)));
}
else
{
// Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGray));
Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_W.png", UriKind.Relative)));
_bConnErr = false;
}
_iLifeCounter = 0;
}
 
private void _getVersion()
{
_sendControllerMessage('v', 0);
}
/// <summary>
/// get FC version struct via NC
/// by sending '1' as data (not documented in wiki...)
/// returns HW error 255 (comment in uart1.c : tells the KopterTool that it is the FC-version)
/// </summary>
/// <param name="ctrl">controller number 1=FC</param>
private void _getVersion(byte ctrl)
{
_sendControllerMessage('v', 0, new byte[1] { ctrl });
}
/// <summary>
/// Switch back to NC by sending the 'Magic Packet' 0x1B,0x1B,0x55,0xAA,0x00
/// </summary>
private void _switchToNC()
{
if (serialPortCtrl.Port.IsOpen)
{
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes = new byte[5] { 0x1B, 0x1B, 0x55, 0xAA, 0x00 };
serialStream.Write(bytes, 0, bytes.Length);
 
Thread.Sleep(100);
_getVersion();
Thread.Sleep(100);
_getLic();
// _OSDMenue(0);
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
}
/// <summary>
/// switch to FC
/// </summary>
private void _switchToFC()
{
_sendControllerMessage('u', 2, new byte[1] { (byte)0 });
Thread.Sleep(100);
_getVersion();
Thread.Sleep(100);
// _OSDMenue(0);
}
/// <summary>
/// send RESET signal to FC
/// </summary>
private void _resetCtrl()
{
_sendControllerMessage('R', 1);
}
/// <summary>
/// poll the debug data (4sec subscription)
/// </summary>
/// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
private void _readDebugData(bool auto)
{
byte interval = auto ? debugInterval : (byte)0;
_sendControllerMessage('d', 0, new byte[1] { debugInterval });
}
/// <summary>
/// poll the BL-CTRL status via NC (4sec subscription)
/// </summary>
/// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
private void _readBLCtrl(bool auto)
{
byte interval = auto ? blctrlInterval : (byte)0;
_sendControllerMessage('k', 0, new byte[1] { interval });
}
/// <summary>
/// poll the NC data struct (4sec subscription)
/// </summary>
/// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
private void _readNavData(bool auto)
{
byte interval = auto ? navctrlInterval : (byte)0;
// _sendControllerMessage('o', 2, new byte[1] { interval });
_sendControllerMessage('o', 2, new byte[3] { interval,4,0 });
}
/// <summary>
/// request the license info
/// </summary>
void _getLic()
{
if (serialPortCtrl.Port.IsOpen)
{
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes = FlightControllerMessage.CreateMessage('m', 2, new byte[1] { (byte)1 });
serialStream.Write(bytes, 0, bytes.Length);
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
 
}
/// <summary>
/// get the errortext for pending NC error
/// </summary>
private void _readNCError()
{
_sendControllerMessage('e', 2);
}
/// <summary>
/// request the Waypoint at index
/// </summary>
/// <param name="index"></param>
void _getpWP(int index)
{
if (serialPortCtrl.Port.IsOpen)
{
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes = FlightControllerMessage.CreateMessage('x', 2, new byte[1] { (byte)index });
serialStream.Write(bytes, 0, bytes.Length);
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
 
}
void _getWP()
{
int iTimeout = 0;
_bGetWPCount = true;
_getpWP(1); //get the itemscount of wp
while (_bGetWPCount & iTimeout < _iWPTimeout * 5)
{
Thread.Sleep(10);
iTimeout++;
}
if (_iWPCount > 0 & !_bGetWPCount)
_getWPList();
}
void _getWPList()
{
_bGetWP = true;
int iTimeout=0;
for (int j = 0; j < _iWPCount; j++)
{
_getpWP(j + 1);
iTimeout = 0;
while (_iWPIndex != j + 1 & iTimeout < _iWPTimeout * 5)
{
Thread.Sleep(1);
iTimeout++;
}
}
Dispatcher.Invoke(() =>
{
// MainMap.ZoomAndCenterMarkers(null);
MainMap.Position = new PointLatLng((double)dtWaypoints.Rows[0][3], (double)dtWaypoints.Rows[0][4]);
MainMap.Zoom = 19;
});
}
/// <summary>
/// Wrapper for _clearCopterWPList()
/// necessary, cause it is called by threadnew which does not like return values...
/// </summary>
void clearCopterWPList()
{
_clearCopterWPList();
}
/// <summary>
/// clear the WP list of the copter
/// by sending 'invalid' and index '0'
/// </summary>
/// <returns></returns>
bool _clearCopterWPList()
{
int iTimeout = 0;
if (serialPortCtrl.Port.IsOpen)
{
byte[] bData = new byte[30];
for (int i = 0; i < 30; i++)
bData[i] = 0;
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes = FlightControllerMessage.CreateMessage('w', 2, bData); //delete all WP on Copter by sending 'invalid'(==0) at index 0
serialStream.Write(bytes, 0, bytes.Length);
 
_iWPCount = -1;
while (_iWPCount == -1 & iTimeout < _iWPTimeout)
{
Thread.Sleep(10);
iTimeout++;
}
Dispatcher.Invoke(() => lblWPCount.Content = _iWPCount.ToString());
if (_iWPCount > -1)
return true;
else
Log(LogMsgType.Error, "Timeout while sending list!");
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
 
return false;
}
void _sendWPList()
{
_sendWPList(0);
}
void _sendWPList(int iStart)
{
int iTimeout = 0;
if (serialPortCtrl.Port.IsOpen)
{
if (_clearCopterWPList())
{
int k = 1;
for (int i = iStart; i < dtWaypoints.Rows.Count; i++)
{
k = iStart > 0 ? k : -1;
_sendWayPoint(dtWaypoints.Rows[i], k, 'w',false);
 
_iWPCount = -1;
iTimeout = 0;
while (_iWPCount == -1 & iTimeout < _iWPTimeout * 5)
{
Thread.Sleep(10);
iTimeout++;
}
if (_iWPCount == -1)
{
Log(LogMsgType.Error, "Timeout while sending list!");
break;
}
Dispatcher.Invoke(() => lblWPCount.Content = _iWPCount.ToString());
k++;
}
}
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
 
}
bool _sendWayPoint(DataRow dr, int index, char command,bool bSim)
{
 
if (serialPortCtrl.Port.IsOpen)
{
byte[] bData = new byte[30];
for (int i = 0; i < 30; i++)
bData[i] = 0;
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes;
int iVal;
double dVal;
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ",";
 
//longitude
dVal = Convert.ToDouble(dr[4], nfi);
iVal = (int)(dVal * Math.Pow(10, 7));
bData[0] = (byte)(iVal & 0xff);
bData[1] = (byte)((iVal >> 8) & 0xff);
bData[2] = (byte)((iVal >> 16) & 0xff);
bData[3] = (byte)(iVal >> 24);
//latitude
dVal = Convert.ToDouble(dr[3], nfi);
iVal = (int)(dVal * Math.Pow(10, 7));
bData[4] = (byte)(iVal & 0xff);
bData[5] = (byte)((iVal >> 8) & 0xff);
bData[6] = (byte)((iVal >> 16) & 0xff);
bData[7] = (byte)(iVal >> 24);
//altitude
dVal = Convert.ToDouble(dr[5], nfi);
iVal = (int)(dVal * 10);
bData[8] = (byte)(iVal & 0xff);
bData[9] = (byte)((iVal >> 8) & 0xff);
bData[10] = (byte)((iVal >> 16) & 0xff);
bData[11] = (byte)(iVal >> 24);
if(bSim)
bData[12] = 3; //Status 'SIMULATE'
//Status 'NEWDATA'
else
bData[12] = 1;
//heading
iVal = Convert.ToInt16(dr[6]);
bData[13] = (byte)(iVal & 0xff);
bData[14] = (byte)((iVal >> 8) & 0xff);
//ToleranceRadius
bData[15] = Convert.ToByte(dr[9]);
//HoldTime
bData[16] = Convert.ToByte(dr[10]);
//Event_Flag
bData[17] = Convert.ToByte(dr[13]);
//Index
bData[18] = index > -1 ? (byte)index : Convert.ToByte((int)dr[0]);
//Type
bData[19] = Convert.ToByte(dr[1]);
//WP_EventChannelValue
bData[20] = Convert.ToByte(dr[14]);
//AltitudeRate
bData[21] = Convert.ToByte(dr[8]);
//Speed
bData[22] = Convert.ToByte(dr[7]);
//CamAngle
bData[23] = (byte)Convert.ToInt16(dr[12]);
//Name
string s = index > 0 ? ((string)dr[2]).Substring(0, 1) + index.ToString() : (string)dr[2];
byte[] name = ASCIIEncoding.ASCII.GetBytes(s);
bData[24] = name.Length > 0 ? name[0] : (byte)0;
bData[25] = name.Length > 1 ? name[1] : (byte)0;
bData[26] = name.Length > 2 ? name[2] : (byte)0;
bData[27] = name.Length > 3 ? name[3] : (byte)0;
//Autotrigger
bData[28] = Convert.ToByte(dr[11]);
 
bytes = FlightControllerMessage.CreateMessage(command, 2, bData);
serialStream.Write(bytes, 0, bytes.Length);
 
return true;
}
 
return false;
}
#region OSD-Menue
 
/// <summary>
/// one time query of the OSD Menue with pagenumber
/// </summary>
/// <param name="iMenue">Menue page</param>
void _OSDMenue(int iMenue)
{
if (serialPortCtrl.Port.IsOpen)
{
if (iMenue > iOSDMax)
iMenue = 0;
Stream serialStream = serialPortCtrl.Port.BaseStream;
byte[] bytes = FlightControllerMessage.CreateMessage('l', 0, new byte[1] { (byte)iMenue });
serialStream.Write(bytes, 0, bytes.Length);
}
else
Log(LogMsgType.Error, "NOT CONNECTED!");
 
}
/// <summary>
/// call the OSDMenue and start autorefresh
/// usually by sending a menuekey
/// a bit tricky - but by sending inverted value of 32 (32 = 0010 0000) you can start the OSD menue with autoupdate (abo) without switching the page with the keyvalues (0x1, 0x2)
/// therefore the value has to be negative (inverted) in order to distinguish from old (2 line) menuestyle
/// and must not have any bits of the menue keys 0x1 0x2 0x4 0x8 (0x10?) --> 0x20 = -33
/// </summary>
void _OSDMenueAutoRefresh()
{
_sendControllerMessage('h', 0, new byte[2] { unchecked((byte)(-33)), OSDInterval });
}
void _OSDMenueAutoRefresh(byte key)
{
_sendControllerMessage('h', 0, new byte[2] { unchecked((byte)~key), OSDInterval });
}
/// <summary>
/// initialize the OSD menue combobox
/// combox is filled by numbers from 0 to max pagenumber
/// </summary>
void _initOSDCB()
{
_bCBInit = true;
if (iOSDMax == 0)
{
_OSDMenue(0);
Thread.Sleep(10);
}
Dispatcher.Invoke((Action)(() => cbOSD.Items.Clear()));
for (int i = 0; i <= iOSDMax; i++)
{
Dispatcher.Invoke((Action)(() => cbOSD.Items.Add(i)));
}
Dispatcher.Invoke((Action)(() => cbOSD.SelectedItem = iOSDPage));
_bCBInit = false;
}
private void btnOSDForward_Click(object sender, RoutedEventArgs e)
{
iOSDPage++;
if (iOSDPage > iOSDMax)
iOSDPage = 0;
 
_OSDMenue(iOSDPage);
}
private void btnOSDBackward_Click(object sender, RoutedEventArgs e)
{
iOSDPage--;
if (iOSDPage < 0)
iOSDPage = iOSDMax;
 
_OSDMenue(iOSDPage);
}
private void btnOSDLeave_Click(object sender, RoutedEventArgs e)
{
_OSDMenueAutoRefresh(8);
}
private void btnOSDEnter_Click(object sender, RoutedEventArgs e)
{
_OSDMenueAutoRefresh(4);
}
private void cbOSD_DropDownClosing(object sender, EventArgs e)
{
if (!_bCBInit && cbOSD.SelectedIndex > -1)
_OSDMenue(cbOSD.SelectedIndex);
}
private void OSD(LogMsgType msgtype, string msg, bool bNew)
{
Dispatcher.Invoke(() =>
{
TextRange tr;
if (bNew)
{
rtfOSD.SelectAll();
rtfOSD.Selection.Text = string.Empty;
}
tr = new TextRange(rtfOSD.Document.ContentEnd, rtfOSD.Document.ContentEnd);
tr.Text = msg;
tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
// rtfOSD.AppendText("\r");
rtfOSD.ScrollToEnd();
 
});
}
 
#endregion OSD-Menue
 
#endregion controller messages
 
void _mediaPlayer(object file)
{
Monitor.TryEnter(lockObj);
try
{
if (File.Exists((string)file))
{
 
mediaPlayer.Open((string)file);
mediaPlayer.Play();
}
else
Log(LogMsgType.Warning, "File not found: " + file.ToString());
 
}
finally
{
Monitor.Exit(lockObj);
}
}
 
#region ui
/// <summary>
/// Switch between fullscreen and normal window mode
/// save & restore scaling settings
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void imageFullscreen_MouseDown(object sender, MouseButtonEventArgs e)
{
if (winState.isMaximized)
{
winState.Restore(this);
imageFullscreen.Source = new BitmapImage(new Uri("Images/Fullscreen.png", UriKind.Relative));
if(_bSaveWinStateFull)
_saveScaleSliders(true);
if(_bSaveWinStateNormal)
_setScaleSliders(false);
}
else
{
winState.Maximize(this);
imageFullscreen.Source = new BitmapImage(new Uri("Images/RestoreScreen.png", UriKind.Relative));
if(_bSaveWinStateNormal)
_saveScaleSliders(false);
if(_bSaveWinStateFull)
_setScaleSliders(true);
}
}
 
/// <summary>
/// reset the scaling of all UI elements to default
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void buttonUIScaleReset_Click(object sender, RoutedEventArgs e)
{
UIScaleHorizonSlider.Value =
UIScaleLOGSlider.Value =
UIScaleMotorsSlider.Value =
UIScaleOSDSlider.Value =
UIScaleSlider.Value =
UIScaleTopSlider.Value = 1;
}
/// <summary>
/// adjust the top postion of UI elements below the top bar to fit the bottom position of the bar when scaling the top bar
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void UIScaleTopSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
GridSettings.Margin = new Thickness(GridSettings.Margin.Left, 36 * UIScaleTopSlider.Value, GridSettings.Margin.Right, GridSettings.Margin.Bottom);
if (GridMotors != null)
GridMotors.Margin = new Thickness(GridMotors.Margin.Left, 36 * UIScaleTopSlider.Value, GridMotors.Margin.Right, GridMotors.Margin.Bottom);
if (GridSideBar != null)
GridSideBar.Margin = new Thickness(GridSideBar.Margin.Left, 36 * UIScaleTopSlider.Value, GridSideBar.Margin.Right, GridSideBar.Margin.Bottom);
if (WPStatus != null)
WPStatus.Margin = new Thickness(WPStatus.Margin.Left, 36 * UIScaleTopSlider.Value, WPStatus.Margin.Right, WPStatus.Margin.Bottom);
if (GridOSD != null)
{
if(WPStatus.Visibility == Visibility.Visible)
GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value + WPStatus.Margin.Bottom, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
else
GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
}
if (GridData != null)
GridData.Margin = new Thickness(GridData.Margin.Left, 36 * UIScaleTopSlider.Value, GridData.Margin.Right, GridData.Margin.Bottom);
if (GridWP != null)
GridWP.Margin = new Thickness(GridWP.Margin.Left, 36 * UIScaleTopSlider.Value, GridWP.Margin.Right, GridWP.Margin.Bottom);
}
private void UIScaleOSDSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
{
if (WPStatus != null && (WPStatus.Visibility == Visibility.Visible))
GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value + 36, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
else
GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
}
}
 
/// <summary>
/// restore the saved scalings for the fullscreen/normal window mode
/// </summary>
/// <param name="bFull">the mode the window is set to</param>
void _setScaleSliders(bool bFull)
{
if(bFull)
{
UIScaleSlider.Value = scaleFullAll;
UIScaleTopSlider.Value = scaleFullTopBar;
UIScaleMotorsSlider.Value = scaleFullMotors;
UIScaleOSDSlider.Value = scaleFullOSD;
UIScaleLOGSlider.Value = scaleFullLOG;
UIScaleHorizonSlider.Value = scaleFullHorizon;
}
else
{
UIScaleSlider.Value = scaleNormalAll;
UIScaleTopSlider.Value = scaleNormalTopBar;
UIScaleMotorsSlider.Value = scaleNormalMotors;
UIScaleOSDSlider.Value = scaleNormalOSD;
UIScaleLOGSlider.Value = scaleNormalLOG;
UIScaleHorizonSlider.Value = scaleNormalHorizon;
}
}
 
/// <summary>
/// save the scalings for the actual window mode
/// </summary>
/// <param name="bFull">the actual window mode</param>
void _saveScaleSliders(bool bFull)
{
 
if (bFull)
{
scaleFullAll = UIScaleSlider.Value;
scaleFullTopBar = UIScaleTopSlider.Value;
scaleFullMotors = UIScaleMotorsSlider.Value;
scaleFullOSD = UIScaleOSDSlider.Value;
scaleFullLOG = UIScaleLOGSlider.Value;
scaleFullHorizon = UIScaleHorizonSlider.Value;
}
else
{
scaleNormalAll = UIScaleSlider.Value;
scaleNormalTopBar = UIScaleTopSlider.Value;
scaleNormalMotors = UIScaleMotorsSlider.Value;
scaleNormalOSD = UIScaleOSDSlider.Value;
scaleNormalLOG = UIScaleLOGSlider.Value;
scaleNormalHorizon = UIScaleHorizonSlider.Value;
}
}
#endregion ui
 
#region ini
/// <summary>
/// read settings from ini-file
/// </summary>
void _readIni()
{
if (!File.Exists(filePath + "\\MKLiveViewSettings.ini"))
_writeIni();
IniFile ini = new IniFile("MKLiveViewSettings.ini");
ini.path = filePath + "\\MKLiveViewSettings.ini";
try
{
 
string sVal = ini.IniReadValue("timings", "AutorefreshDebugData");
if (sVal != "") _debugDataAutorefresh = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("timings", "AutorefreshNavCtrlData");
if (sVal != "") _navCtrlDataAutorefresh = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("timings", "AutorefreshBLCtrlData");
if (sVal != "") _blctrlDataAutorefresh = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("timings", "AutorefreshOSDData");
if (sVal != "") _OSDAutorefresh = Convert.ToBoolean(sVal);
 
sVal = ini.IniReadValue("timings", "IntervalDebugData");
if (sVal != "") debugInterval = (byte)Convert.ToInt16(sVal);
sVal = ini.IniReadValue("timings", "IntervalNavCtrlData");
if (sVal != "") navctrlInterval = (byte)Convert.ToInt16(sVal);
sVal = ini.IniReadValue("timings", "IntervalBLCtrlData");
if (sVal != "") blctrlInterval = (byte)Convert.ToInt16(sVal);
sVal = ini.IniReadValue("timings", "IntervalOSDData");
if (sVal != "") OSDInterval = (byte)Convert.ToInt16(sVal);
 
sVal = ini.IniReadValue("topBar", "voltage");
if (sVal != "") chkBoxTopBarShowVoltage.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "capacity");
if (sVal != "") chkBoxTopBarShowCapacity.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "current");
if (sVal != "") chkBoxTopBarShowCurrent.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "flightTime");
if (sVal != "") chkBoxTopBarShowFlightTime.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "distanceHP");
if (sVal != "") chkBoxTopBarShowDistanceHP.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "height");
if (sVal != "") chkBoxTopBarShowHeight.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "speed");
if (sVal != "") chkBoxTopBarShowSpeed.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "magneticField");
if (sVal != "") chkBoxTopBarShowMF.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "satellites");
if (sVal != "") chkBoxTopBarShowSatellites.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("topBar", "rc");
if (sVal != "") chkBoxTopBarShowRC.IsChecked = Convert.ToBoolean(sVal);
 
sVal = ini.IniReadValue("style", "saveFullScreen");
if (sVal != "") chkBoxSaveFullScreenState.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("style", "saveNormalState");
if (sVal != "") chkBoxSaveNormalState.IsChecked = Convert.ToBoolean(sVal);
 
sVal = ini.IniReadValue("style", "scaleNormalAll");
if (sVal != "") scaleNormalAll = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleNormalTopBar");
if (sVal != "") scaleNormalTopBar = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleNormalMotors");
if (sVal != "") scaleNormalMotors = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleNormalOSD");
if (sVal != "") scaleNormalOSD = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleNormalLOG");
if (sVal != "") scaleNormalLOG = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleNormalHorizon");
if (sVal != "") scaleNormalHorizon = Convert.ToDouble(sVal);
 
sVal = ini.IniReadValue("style", "scaleFullAll");
if (sVal != "") scaleFullAll = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleFullTopBar");
if (sVal != "") scaleFullTopBar = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleFullMotors");
if (sVal != "") scaleFullMotors = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleFullOSD");
if (sVal != "") scaleFullOSD = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleFullLOG");
if (sVal != "") scaleFullLOG = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("style", "scaleFullHorizon");
if (sVal != "") scaleFullHorizon = Convert.ToDouble(sVal);
 
sVal = ini.IniReadValue("general", "LiPoCells");
_LipoCells = Convert.ToInt16(sVal);
sVal = ini.IniReadValue("general", "LiPoAutoDetect");
_bLiPoAutoDetect = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("general", "Motors");
if (sVal != "") _iMotors = Convert.ToInt16(sVal);
 
sVal = ini.IniReadValue("map", "followMe");
if (sVal != "") _bFollowCopter = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("map", "location");
if (sVal != "") _mapPosition = sVal;
sVal = ini.IniReadValue("map", "AutoSetHome");
if (sVal != "") _bAutoHome = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("map", "GPXLog");
if (sVal != "") _bGPXLog = Convert.ToBoolean(sVal);
 
sVal = ini.IniReadValue("threshold", "VoltageWarning");
if(sVal != "") _dThresholdVoltageWarn = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("threshold", "VoltageCritical");
if(sVal != "") _dThresholdVoltageCrit = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("threshold", "VoiceVoltageEnable");
if(sVal != "") _bVoiceVoltPlay = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("threshold", "VoiceSatFixEnable");
if(sVal != "") _bVoiceSatFixPlay = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("threshold", "VoiceMagFieldEnable");
if(sVal != "") _bVoiceMagneticFieldPlay = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("threshold", "DistanceWarning");
if(sVal != "") _dThresholdDistanceWarn = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("threshold", "VoiceDistanceWarnEnable");
if(sVal != "") _bVoiceDistancePlay = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("threshold", "VoiceRCLevelWarnEnable");
if(sVal != "") _bVoiceRCLevelPlay = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("threshold", "MaxDistance");
if(sVal != "") _dThresholdDistanceMax = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("threshold", "RCThreshold");
if(sVal != "") _iThresholdRC = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("threshold", "MagFieldThreshold");
if(sVal != "") _iThresholdMagField = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("threshold", "BLCtrlTemp");
if(sVal != "") _iThresholdBLCTRLTempWarn = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("threshold", "VoiceBLCtrlTempEnable");
if(sVal != "") _bVoiceBLCTRLTempPlay = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("threshold", "VoiceLanguageIndex");
if(sVal != "") _iVoiceIndex = Convert.ToInt32(sVal);
 
sVal = ini.IniReadValue("waypoints", "wpcolor");
if(sVal != "") comboBoxWPColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "poicolor");
if(sVal != "") comboBoxPOIColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "fscolor");
if(sVal != "") comboBoxFSColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "coptercolor");
if(sVal != "") comboBoxCopterColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "copterheadingcolor");
if(sVal != "") comboBoxCopterHeadingColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "landingcolor");
if(sVal != "") comboBoxLandingColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "routecolor");
if(sVal != "") comboBoxRouteColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "showWPRoute");
if(sVal != "") _bShowWPRoute = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("waypoints", "autoShowWPEdit");
if(sVal != "") _bAutoWPEdit = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("waypoints", "showWPMaxRange");
if(sVal != "") checkBoxShowWPMaxRange.IsChecked = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("waypoints", "WPMaxRangecolor");
if(sVal != "") comboBoxWPMaxRangeColor.SelectedIndex = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefPrefix");
if(sVal != "") _wpDefPrefix = sVal;
sVal = ini.IniReadValue("waypoints", "WPDefAltitude");
if(sVal != "") _wpDefAltitude = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefHeading");
if(sVal != "") _wpDefHeading = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefCBoxHeading");
if(sVal != "") _wpDefCBoxHeading = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefSpeed");
if(sVal != "") _wpDefSpeed = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefCBoxSpeed");
if(sVal != "") _wpDefCBoxSpeed = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefClimb");
if(sVal != "") _wpDefClimb = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefCBoxClimb");
if(sVal != "") _wpDefCBoxClimb = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefRadius");
if(sVal != "") _wpDefRadius = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefHoldtime");
if(sVal != "") _wpDefHoldtime = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefAutotrig");
if(sVal != "") _wpDefAutotrig = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefCamangle");
if(sVal != "") _wpDefCamangle = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefCBoxCamangle");
if(sVal != "") _wpDefCBoxCamangle = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPDefOut1");
if(sVal != "") _wpDefOut1 = Convert.ToInt32(sVal);
sVal = ini.IniReadValue("waypoints", "WPAddCopterHeight");
if (sVal != "") _wpAddCopterHeight = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("waypoints", "WPAddCopterHeading");
if (sVal != "") _wpAddCopterHeading = Convert.ToBoolean(sVal);
sVal = ini.IniReadValue("waypoints", "CopterSize");
if (sVal != "") SliderCopterZoom.Value = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("waypoints", "WPSize");
if (sVal != "") SliderWPZoom.Value = Convert.ToDouble(sVal);
 
sVal = ini.IniReadValue("cam", "CamImagePosLeft");
if (sVal != "") _camImageMargin.Left = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("cam", "CamImagePosTop");
if (sVal != "") _camImageMargin.Top = Convert.ToDouble(sVal);
sVal = ini.IniReadValue("cam", "CamImageZoom");
if (sVal != "") SliderCamZoom.Value = Convert.ToDouble(sVal);
 
for (int i = 0; i < 12; i++)
{
sVal = ini.IniReadValue("serial", "ch" + i.ToString() + "Val");
if (sVal != "")
serChan[i] = Convert.ToInt16(sVal);
sVal = ini.IniReadValue("serial", "ch" + i.ToString() + "Title");
if (sVal != "")
serChanTitle[i] = sVal;
for (int y = 0; i < 4 && y < 3; y++)
{
sVal = ini.IniReadValue("serial", "ch" + i.ToString() + "ValSub" + y.ToString());
if (sVal != "")
serChan_sub[(i * 3) + y] = Convert.ToInt16(sVal);
}
}
 
}
catch (Exception e)
{
 
MessageBox.Show("Error parsing ini-file!" + Environment.NewLine + e.Message,"Read ini-file" ,MessageBoxButton.OK,MessageBoxImage.Error);
}
 
}
 
/// <summary>
/// save settings to ini-file
/// </summary>
void _writeIni()
{
 
IniFile ini = new IniFile("MKLiveViewSettings.ini");
ini.path = filePath + "\\MKLiveViewSettings.ini";
 
try
{
 
ini.IniWriteValue("timings", "AutorefreshDebugData", _debugDataAutorefresh ? "true" : "false");
ini.IniWriteValue("timings", "AutorefreshNavCtrlData", _navCtrlDataAutorefresh ? "true" : "false");
ini.IniWriteValue("timings", "AutorefreshBLCtrlData", _blctrlDataAutorefresh ? "true" : "false");
ini.IniWriteValue("timings", "AutorefreshOSDData", _OSDAutorefresh ? "true" : "false");
 
ini.IniWriteValue("timings", "IntervalDebugData", debugInterval.ToString());
ini.IniWriteValue("timings", "IntervalNavCtrlData", navctrlInterval.ToString());
ini.IniWriteValue("timings", "IntervalBLCtrlData", blctrlInterval.ToString());
ini.IniWriteValue("timings", "IntervalOSDData", OSDInterval.ToString());
 
ini.IniWriteValue("general", "LiPoCells", _LipoCells.ToString());
ini.IniWriteValue("general", "LiPoAutoDetect", _bLiPoAutoDetect.ToString());
ini.IniWriteValue("general", "Motors", _iMotors.ToString());
 
ini.IniWriteValue("map", "location", _mapPosition);
ini.IniWriteValue("map", "followMe", _bFollowCopter.ToString());
ini.IniWriteValue("map", "AutoSetHome", _bAutoHome.ToString());
ini.IniWriteValue("map", "GPXLog", _bGPXLog.ToString());
 
ini.IniWriteValue("topBar", "voltage", chkBoxTopBarShowVoltage.IsChecked.ToString());
ini.IniWriteValue("topBar", "capacity", chkBoxTopBarShowCapacity.IsChecked.ToString());
ini.IniWriteValue("topBar", "current", chkBoxTopBarShowCurrent.IsChecked.ToString());
ini.IniWriteValue("topBar", "flightTime", chkBoxTopBarShowFlightTime.IsChecked.ToString());
ini.IniWriteValue("topBar", "distanceHP", chkBoxTopBarShowDistanceHP.IsChecked.ToString());
ini.IniWriteValue("topBar", "height", chkBoxTopBarShowHeight.IsChecked.ToString());
ini.IniWriteValue("topBar", "speed", chkBoxTopBarShowSpeed.IsChecked.ToString());
ini.IniWriteValue("topBar", "magneticField", chkBoxTopBarShowMF.IsChecked.ToString());
ini.IniWriteValue("topBar", "satellites", chkBoxTopBarShowSatellites.IsChecked.ToString());
ini.IniWriteValue("topBar", "rc", chkBoxTopBarShowRC.IsChecked.ToString());
 
ini.IniWriteValue("style", "saveFullScreen", chkBoxSaveFullScreenState.IsChecked.ToString());
ini.IniWriteValue("style", "saveNormalState", chkBoxSaveNormalState.IsChecked.ToString());
 
ini.IniWriteValue("style", "scaleNormalAll", scaleNormalAll.ToString());
ini.IniWriteValue("style", "scaleNormalTopBar", scaleNormalTopBar.ToString());
ini.IniWriteValue("style", "scaleNormalMotors", scaleNormalMotors.ToString());
ini.IniWriteValue("style", "scaleNormalOSD", scaleNormalOSD.ToString());
ini.IniWriteValue("style", "scaleNormalLOG", scaleNormalLOG.ToString());
ini.IniWriteValue("style", "scaleNormalHorizon", scaleNormalHorizon.ToString());
 
ini.IniWriteValue("style", "scaleFullAll", scaleFullAll.ToString());
ini.IniWriteValue("style", "scaleFullTopBar", scaleFullTopBar.ToString());
ini.IniWriteValue("style", "scaleFullMotors", scaleFullMotors.ToString());
ini.IniWriteValue("style", "scaleFullOSD", scaleFullOSD.ToString());
ini.IniWriteValue("style", "scaleFullLOG", scaleFullLOG.ToString());
ini.IniWriteValue("style", "scaleFullHorizon", scaleFullHorizon.ToString());
 
ini.IniWriteValue("style", "horizon", chkBoxShowHorizon.IsChecked.ToString());
 
ini.IniWriteValue("threshold", "VoltageWarning", _dThresholdVoltageWarn.ToString());
ini.IniWriteValue("threshold", "VoltageCritical", _dThresholdVoltageCrit.ToString());
ini.IniWriteValue("threshold", "VoiceVoltageEnable", _bVoiceVoltPlay.ToString());
ini.IniWriteValue("threshold", "VoiceSatFixEnable", _bVoiceSatFixPlay.ToString());
ini.IniWriteValue("threshold", "VoiceMagFieldEnable", _bVoiceMagneticFieldPlay.ToString());
ini.IniWriteValue("threshold", "VoiceDistanceWarnEnable", _bVoiceDistancePlay.ToString());
ini.IniWriteValue("threshold", "VoiceRCLevelWarnEnable", _bVoiceRCLevelPlay.ToString());
ini.IniWriteValue("threshold", "DistanceWarning", _dThresholdDistanceWarn.ToString());
ini.IniWriteValue("threshold", "MaxDistance", _dThresholdDistanceMax.ToString());
ini.IniWriteValue("threshold", "RCThreshold", _iThresholdRC.ToString());
ini.IniWriteValue("threshold", "MagFieldThreshold", _iThresholdMagField.ToString());
ini.IniWriteValue("threshold", "BLCtrlTemp", _iThresholdBLCTRLTempWarn.ToString());
ini.IniWriteValue("threshold", "VoiceBLCtrlTempEnable", _bVoiceBLCTRLTempPlay.ToString());
ini.IniWriteValue("threshold", "VoiceLanguageIndex", _iVoiceIndex.ToString());
 
ini.IniWriteValue("waypoints", "wpcolor", comboBoxWPColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "poicolor", comboBoxPOIColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "fscolor", comboBoxFSColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "coptercolor", comboBoxCopterColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "copterheadingcolor", comboBoxCopterHeadingColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "landingcolor", comboBoxLandingColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "routecolor", comboBoxRouteColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "showWPRoute", _bShowWPRoute.ToString());
ini.IniWriteValue("waypoints", "showWPMaxRange", ((bool)checkBoxShowWPMaxRange.IsChecked).ToString());
ini.IniWriteValue("waypoints", "autoShowWPEdit", ((bool)checkBoxAutoShowWPEdit.IsChecked).ToString());
ini.IniWriteValue("waypoints", "WPMaxRangecolor", comboBoxWPMaxRangeColor.SelectedIndex.ToString());
ini.IniWriteValue("waypoints", "WPDefPrefix", _wpDefPrefix);
ini.IniWriteValue("waypoints", "WPDefAltitude", _wpDefAltitude.ToString());
ini.IniWriteValue("waypoints", "WPDefHeading", _wpDefHeading.ToString());
ini.IniWriteValue("waypoints", "WPDefCBoxHeading", _wpDefCBoxHeading.ToString());
ini.IniWriteValue("waypoints", "WPDefSpeed", _wpDefSpeed.ToString());
ini.IniWriteValue("waypoints", "WPDefCBoxSpeed", _wpDefCBoxSpeed.ToString());
ini.IniWriteValue("waypoints", "WPDefClimb", _wpDefClimb.ToString());
ini.IniWriteValue("waypoints", "WPDefCBoxClimb", _wpDefCBoxClimb.ToString());
ini.IniWriteValue("waypoints", "WPDefRadius", _wpDefRadius.ToString());
ini.IniWriteValue("waypoints", "WPDefHoldtime", _wpDefHoldtime.ToString());
ini.IniWriteValue("waypoints", "WPDefAutotrig", _wpDefAutotrig.ToString());
ini.IniWriteValue("waypoints", "WPDefCamangle", _wpDefCamangle.ToString());
ini.IniWriteValue("waypoints", "WPDefCBoxCamangle", _wpDefCBoxCamangle.ToString());
ini.IniWriteValue("waypoints", "WPDefOut1", _wpDefOut1.ToString());
ini.IniWriteValue("waypoints", "WPAddCopterHeight", _wpAddCopterHeight.ToString());
ini.IniWriteValue("waypoints", "WPAddCopterHeading", _wpAddCopterHeading.ToString());
ini.IniWriteValue("waypoints", "CopterSize", SliderCopterZoom.Value.ToString());
ini.IniWriteValue("waypoints", "WPSize", SliderWPZoom.Value.ToString());
 
ini.IniWriteValue("cam", "CamImagePosLeft", _camImageMargin.Left.ToString());
ini.IniWriteValue("cam", "CamImagePosTop", _camImageMargin.Top.ToString());
ini.IniWriteValue("cam", "CamImageZoom", SliderCamZoom.Value.ToString());
 
for (int i = 0; i < 12; i++)
{
ini.IniWriteValue("serial", "ch" + i.ToString() + "Val", serChan[i].ToString());
ini.IniWriteValue("serial", "ch" + i.ToString() + "Title", serChanTitle[i]);
for (int y = 0; i < 4 && y < 3; y++)
{
ini.IniWriteValue("serial", "ch" + i.ToString() + "ValSub" + y.ToString(), serChan_sub[(i * 3) + y].ToString());
}
}
 
}
catch (Exception e)
{
 
MessageBox.Show("Error writing ini-file!" + Environment.NewLine + "Please make sure that the programm is in a location where it is allowed to write" + Environment.NewLine + e.Message, "Write ini-file", MessageBoxButton.OK, MessageBoxImage.Error);
}
}
#endregion ini
 
#region serial channels
/// <summary>
/// Sending the serial channel values
/// </summary>
void _sendSerialData()
{
byte[] serData = new byte[12];
for (int i = 0; i < 12; i++)
{
serData[i] = unchecked((byte)(serChan[i] - 127));
}
_sendControllerMessage('y', 1, serData);
}
/// <summary>
/// init the controls for displaying
/// and setting serial control channels
/// </summary>
void _initSerialCtrl()
{
SerChan1ScaleSlider.Value = serChan[0];
textBoxSerial1.Text = serChanTitle[0];
SerChan2ScaleSlider.Value = serChan[1];
textBoxSerial2.Text = serChanTitle[1];
SerChan3ScaleSlider.Value = serChan[2];
textBoxSerial3.Text = serChanTitle[2];
//SerChan4ScaleSlider.Value = serChan[3];
//textBoxSerial4.Text = serChanTitle[3];
//trckbarSerial5.Value = serChan[4];
//textBoxSerial5.Text = serChanTitle[4];
//trckbarSerial6.Value = serChan[5];
//textBoxSerial6.Text = serChanTitle[5];
//trckbarSerial7.Value = serChan[6];
//textBoxSerial7.Text = serChanTitle[6];
//trckbarSerial8.Value = serChan[7];
//textBoxSerial8.Text = serChanTitle[7];
 
textBoxSerial1_val1.Text = serChan_sub[0].ToString();
textBoxSerial1_val2.Text = serChan_sub[1].ToString();
textBoxSerial1_val3.Text = serChan_sub[2].ToString();
textBoxSerial2_val1.Text = serChan_sub[3].ToString();
textBoxSerial2_val2.Text = serChan_sub[4].ToString();
textBoxSerial2_val3.Text = serChan_sub[5].ToString();
textBoxSerial3_val1.Text = serChan_sub[6].ToString();
textBoxSerial3_val2.Text = serChan_sub[7].ToString();
textBoxSerial3_val3.Text = serChan_sub[8].ToString();
//textBoxSerial4_val1.Text = serChan_sub[9].ToString();
//textBoxSerial4_val2.Text = serChan_sub[10].ToString();
//textBoxSerial4_val3.Text = serChan_sub[11].ToString();
}
private void SerChan1ScaleSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
{
serChan[0] = (int)SerChan1ScaleSlider.Value;
_sendSerialData();
}
}
private void textBoxSerial1_TextChanged(object sender, TextChangedEventArgs e)
{
if (!_init)
{
serChanTitle[0] = textBoxSerial1.Text;
}
}
private void textBoxSerial1_val1_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial1_val1.Text.Length > 0 & !_init)
{
serChan_sub[0] = Convert.ToInt16(textBoxSerial1_val1.Text);
}
}
private void textBoxSerial1_val2_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial1_val2.Text.Length > 0 & !_init)
{
serChan_sub[1] = Convert.ToInt16(textBoxSerial1_val2.Text);
}
}
private void textBoxSerial1_val3_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial1_val3.Text.Length > 0 & !_init)
{
serChan_sub[2] = Convert.ToInt16(textBoxSerial1_val3.Text);
}
}
private void btnSer1_val1_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial1_val1.Text.Length > 0)
{
SerChan1ScaleSlider.Value = Convert.ToInt16(textBoxSerial1_val1.Text);
}
}
private void btnSer1_0_Click(object sender, RoutedEventArgs e)
{
SerChan1ScaleSlider.Value = 0;
}
private void btnSer1_127_Click(object sender, RoutedEventArgs e)
{
SerChan1ScaleSlider.Value = 127;
}
private void btnSer1_254_Click(object sender, RoutedEventArgs e)
{
SerChan1ScaleSlider.Value = 254;
}
private void btnSer1_val2_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial1_val2.Text.Length > 0)
{
SerChan1ScaleSlider.Value = Convert.ToInt16(textBoxSerial1_val2.Text);
}
}
private void btnSer1_val3_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial1_val3.Text.Length > 0)
{
SerChan1ScaleSlider.Value = Convert.ToInt16(textBoxSerial1_val3.Text);
}
}
 
private void SerChan2ScaleSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
{
serChan[1] = (int)SerChan2ScaleSlider.Value;
_sendSerialData();
}
}
private void textBoxSerial2_TextChanged(object sender, TextChangedEventArgs e)
{
if (!_init)
{
serChanTitle[1] = textBoxSerial2.Text;
}
}
private void textBoxSerial2_val1_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial2_val1.Text.Length > 0 & !_init)
{
serChan_sub[3] = Convert.ToInt16(textBoxSerial2_val1.Text);
}
}
private void textBoxSerial2_val2_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial2_val2.Text.Length > 0 & !_init)
{
serChan_sub[4] = Convert.ToInt16(textBoxSerial2_val2.Text);
}
}
private void textBoxSerial2_val3_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial2_val3.Text.Length > 0 & !_init)
{
serChan_sub[5] = Convert.ToInt16(textBoxSerial2_val3.Text);
}
}
private void btnSer2_0_Click(object sender, RoutedEventArgs e)
{
SerChan2ScaleSlider.Value = 0;
}
private void btnSer2_127_Click(object sender, RoutedEventArgs e)
{
SerChan2ScaleSlider.Value = 127;
}
private void btnSer2_254_Click(object sender, RoutedEventArgs e)
{
SerChan2ScaleSlider.Value = 254;
}
private void btnSer2_val1_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial2_val1.Text.Length > 0)
{
SerChan2ScaleSlider.Value = Convert.ToInt16(textBoxSerial2_val1.Text);
}
}
private void btnSer2_val2_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial2_val2.Text.Length > 0)
{
SerChan2ScaleSlider.Value = Convert.ToInt16(textBoxSerial2_val2.Text);
}
}
private void btnSer2_val3_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial2_val3.Text.Length > 0)
{
SerChan2ScaleSlider.Value = Convert.ToInt16(textBoxSerial2_val3.Text);
}
}
 
private void SerChan3ScaleSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (!_init)
{
serChan[2] = (int)SerChan3ScaleSlider.Value;
_sendSerialData();
}
}
private void textBoxSerial3_TextChanged(object sender, TextChangedEventArgs e)
{
if (!_init)
{
serChanTitle[2] = textBoxSerial3.Text;
}
}
private void textBoxSerial3_val1_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial3_val1.Text.Length > 0 & !_init)
{
serChan_sub[6] = Convert.ToInt16(textBoxSerial3_val1.Text);
}
}
private void textBoxSerial3_val2_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial3_val2.Text.Length > 0 & !_init)
{
serChan_sub[7] = Convert.ToInt16(textBoxSerial3_val2.Text);
}
}
private void textBoxSerial3_val3_TextChanged(object sender, TextChangedEventArgs e)
{
if (textBoxSerial3_val3.Text.Length > 0 & !_init)
{
serChan_sub[8] = Convert.ToInt16(textBoxSerial3_val3.Text);
}
}
private void btnSer3_0_Click(object sender, RoutedEventArgs e)
{
SerChan3ScaleSlider.Value = 0;
}
private void btnSer3_127_Click(object sender, RoutedEventArgs e)
{
SerChan3ScaleSlider.Value = 127;
}
private void btnSer3_254_Click(object sender, RoutedEventArgs e)
{
SerChan3ScaleSlider.Value = 254;
}
private void btnSer3_val1_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial3_val1.Text.Length > 0)
{
SerChan3ScaleSlider.Value = Convert.ToInt16(textBoxSerial3_val1.Text);
}
}
private void btnSer3_val2_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial3_val2.Text.Length > 0)
{
SerChan3ScaleSlider.Value = Convert.ToInt16(textBoxSerial3_val2.Text);
}
}
private void btnSer3_val3_Click(object sender, RoutedEventArgs e)
{
if (textBoxSerial3_val3.Text.Length > 0)
{
SerChan3ScaleSlider.Value = Convert.ToInt16(textBoxSerial3_val3.Text);
}
}
/// <summary>
/// checks the input of a textbox
/// for valid data
/// in this case values 0-254
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void textBox_serial_KeyPress(object sender, KeyEventArgs e)
{
if ("1234567890,\b".IndexOf(e.Key.ToString()) < 0) //general check for valid chars(0-9) and backspace (\b)
e.Handled = true;
else
if ("\b".IndexOf(e.Key.ToString()) < 0)
if (Convert.ToInt16(((TextBox)sender).Text + e.Key) > 254) //if valid and not backspace, check for upper limit of the resulting number
e.Handled = true;
else
{
int i = -1;
switch (((TextBox)sender).Name)
{
case "textBoxSerial1_val1":
i = 0;
break;
case "textBoxSerial1_val2":
i = 1;
break;
case "textBoxSerial1_val3":
i = 2;
break;
case "textBoxSerial2_val1":
i = 3;
break;
case "textBoxSerial2_val2":
i = 4;
break;
case "textBoxSerial2_val3":
i = 5;
break;
case "textBoxSerial3_val1":
i = 6;
break;
case "textBoxSerial3_val2":
i = 7;
break;
case "textBoxSerial3_val3":
i = 8;
break;
case "textBoxSerial4_val1":
i = 9;
break;
case "textBoxSerial4_val2":
i = 10;
break;
case "textBoxSerial4_val3":
i = 11;
break;
}
if (i > -1)
serChan_sub[i] = Convert.ToInt16(((TextBox)sender).Text + e.Key.ToString());
}
}
 
#endregion serial channels
#region WP
void _readWPLFile()
{
Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
fd.Filter = "Waypointlists | *.wpl";
fd.Multiselect = false;
if (fd.ShowDialog().Value)
{
string file = fd.SafeFileName;
IniFile ini = new IniFile(fd.SafeFileName);
ini.path = fd.FileName;
 
try
{
string sVal = ini.IniReadValue("General", "FileVersion");
if (sVal == "")
MessageBox.Show("The file has no version declared - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
else
{
if (Convert.ToInt16(sVal) < 3)
MessageBox.Show("The file version is not supported - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
else
{
sVal = ini.IniReadValue("General", "NumberOfWaypoints");
if (sVal == "")
MessageBox.Show("The file has no number of waypoints declared - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
else
{
int wpnum = Convert.ToInt16(sVal);
string wp;
int i;
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";
dtWaypoints.Rows.Clear();
_wpEdit = -1;_wpIndex = -1;
wpOffset.Clear();
_clearMapMarkers(typeof(CustomMarkerWP));
_clearMapMarkers(typeof(CustomMarkerWPActive));
wpList.Clear();
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
//if (wpActiveMarker != null)
// MainMap.Markers.Remove(wpActiveMarker);
Dispatcher.Invoke(() => lblWPRouteDistance.Content = "0 m");
 
for (int k = 1; k <= wpnum; k++)
{
DataRow dr = dtWaypoints.NewRow();
dr.ItemArray = new object[16];
object[] o = new object[16];
i = 0;
wp = "Point" + k.ToString();
o[i] = k;
i++;
sVal = ini.IniReadValue(wp, "Type");
if (sVal != "")
o[i] = Convert.ToInt16(sVal) - 1;
i++;
sVal = ini.IniReadValue(wp, "Prefix");
if (sVal != "")
o[i] = sVal + k.ToString();
// o[i] = sVal == "0" ? "!" + k.ToString() : sVal + k.ToString();
i++;
sVal = ini.IniReadValue(wp, "Latitude");
if (sVal != "")
o[i] = Convert.ToDouble(sVal, nfi);
i++;
sVal = ini.IniReadValue(wp, "Longitude");
if (sVal != "")
o[i] = Convert.ToDouble(sVal, nfi);
i++;
sVal = ini.IniReadValue(wp, "Altitude");
if (sVal != "")
o[i] = Convert.ToDouble(sVal, nfi);
i++;
sVal = ini.IniReadValue(wp, "Heading");
if (sVal != "")
o[i] = Convert.ToInt16(sVal);
i++;
sVal = ini.IniReadValue(wp, "Speed");
if (sVal != "")
o[i] = Convert.ToInt16(sVal);
i++;
sVal = ini.IniReadValue(wp, "ClimbRate");
if (sVal != "")
o[i] = Convert.ToInt16(sVal);
i++;
sVal = ini.IniReadValue(wp, "Radius");
if (sVal != "")
o[i] = Convert.ToInt16(sVal);
i++;
sVal = ini.IniReadValue(wp, "DelayTime");
if (sVal != "")
o[i] = Convert.ToInt16(sVal);
i++;
sVal = ini.IniReadValue(wp, "AutoTrigger");
if (sVal != "")
o[i] = Convert.ToInt16(sVal); ;
i++;
sVal = ini.IniReadValue(wp, "CAM-Nick");
if (sVal != "")
o[i] = Convert.ToInt16(sVal);
i++;
o[i] = 0;
i++;
sVal = ini.IniReadValue(wp, "WP_Event_Channel_Value");
if (sVal != "")
o[i] = Convert.ToInt16(sVal);
i++;
o[i] = "New";
 
dr.ItemArray = o;
dtWaypoints.Rows.Add(dr);
_createWP(new PointLatLng((double)o[3], (double)o[4]), (string)dr[2], (int)o[1], (int)o[0]-1);
 
Dispatcher.Invoke(() => lblWPIndex.Content = k.ToString());
Dispatcher.Invoke(() => lblWPCount.Content = k.ToString());
Dispatcher.Invoke(() => dgvWP.Items.Refresh());
Thread.Sleep(1);
}
Dispatcher.Invoke(() => MainMap.Position = new PointLatLng((double)dtWaypoints.Rows[0][3], (double)dtWaypoints.Rows[0][4]));
Dispatcher.Invoke(() => MainMap.Zoom = 19);
// Dispatcher.Invoke(() => MainMap.ZoomAndCenterMarkers(null));
Dispatcher.Invoke(() => _routeUpdate());
}
}
}
 
}
catch (Exception e)
{
 
MessageBox.Show("Error parsing wpl-file!" + Environment.NewLine + e.Message, "Read wpl-file", MessageBoxButton.OK, MessageBoxImage.Error);
}
 
}
}
void _saveWPLFile()
{
if (dtWaypoints.Rows.Count > 0)
{
Microsoft.Win32.SaveFileDialog fd = new Microsoft.Win32.SaveFileDialog();
fd.Filter = "Waypointlists | *.wpl";
fd.AddExtension = true;
if (fd.ShowDialog().Value)
{
string file = fd.SafeFileName;
IniFile ini = new IniFile(fd.SafeFileName);
ini.path = fd.FileName;
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";
 
try
{
ini.IniWriteValue("General", "FileVersion", "3");
ini.IniWriteValue("General", "NumberOfWaypoints", dtWaypoints.Rows.Count.ToString());
ini.IniWriteValue("General", "Mapfile", "");
for(int i = 1; i<=dtWaypoints.Rows.Count; i++)
{
ini.IniWriteValue("Point" + i.ToString(), "Latitude", ((double)(dtWaypoints.Rows[i-1][3])).ToString(nfi));
ini.IniWriteValue("Point" + i.ToString(), "Longitude", ((double)(dtWaypoints.Rows[i - 1][4])).ToString(nfi));
ini.IniWriteValue("Point" + i.ToString(), "Radius", dtWaypoints.Rows[i - 1][9].ToString());
ini.IniWriteValue("Point" + i.ToString(), "Altitude", dtWaypoints.Rows[i - 1][5].ToString());
ini.IniWriteValue("Point" + i.ToString(), "ClimbRate", dtWaypoints.Rows[i - 1][8].ToString());
ini.IniWriteValue("Point" + i.ToString(), "DelayTime", dtWaypoints.Rows[i - 1][10].ToString());
ini.IniWriteValue("Point" + i.ToString(), "WP_Event_Channel_Value", dtWaypoints.Rows[i - 1][14].ToString());
ini.IniWriteValue("Point" + i.ToString(), "Heading", dtWaypoints.Rows[i - 1][6].ToString());
ini.IniWriteValue("Point" + i.ToString(), "Speed", dtWaypoints.Rows[i - 1][7].ToString());
ini.IniWriteValue("Point" + i.ToString(), "CAM-Nick", dtWaypoints.Rows[i - 1][12].ToString());
ini.IniWriteValue("Point" + i.ToString(), "Type", ((int)dtWaypoints.Rows[i - 1][1]+1).ToString());
ini.IniWriteValue("Point" + i.ToString(), "Prefix", dtWaypoints.Rows[i - 1][2].ToString().Substring(0, 1)); // == "!" ? "0" : dtWaypoints.Rows[i - 1][2].ToString().Substring(0, 1));
ini.IniWriteValue("Point" + i.ToString(), "AutoTrigger", dtWaypoints.Rows[i - 1][11].ToString());
}
MessageBox.Show(dtWaypoints.Rows.Count.ToString() + " points saved to " + file, "Waypointlist saved", MessageBoxButton.OK, MessageBoxImage.Information);
}
catch { }
}
}
else
MessageBox.Show("Nothing to save...");
}
private void btnSaveWPLFile_Click(object sender, RoutedEventArgs e)
{
_saveWPLFile();
}
/// <summary>
/// set the selected color for the route
/// </summary>
/// <param name="color"></param>
/// <returns></returns>
Brush _getBrush(string color)
{
switch (color)
{
case "red":
return Brushes.Red;
case "green":
return Brushes.Lime;
case "blue":
return Brushes.Aqua;
case "pink":
return Brushes.Magenta;
case "yellow":
return Brushes.Yellow;
default:
return Brushes.Magenta;
}
}
void _routeUpdate()
{
Dispatcher.Invoke(() =>
{
if (comboBoxRouteColor.SelectionBoxItem != null)
{
string s = comboBoxRouteColor.SelectionBoxItem.ToString();
mRouteWP = new GMapRoute(wpList, _getBrush(s));
}
else
mRouteWP = new GMapRoute(wpList, null);
 
if (_bShowWPRoute)
MainMap.Markers.Add(mRouteWP);
});
 
MapRoute mr = new MapRoute(wpList, "WPList");
Dispatcher.Invoke(() => lblWPRouteDistance.Content = (mr.Distance * 1000).ToString("0 m"));
}
GMapMarker _createWP(PointLatLng p, string name, int type, int index)
{
GMapMarker wpMarker = new GMapMarker(p);
Dispatcher.Invoke(()=>
{
wpMarker.Shape = new CustomMarkerWP(this, wpMarker, name, type);
wpMarker.Tag = name;
wpMarker.Offset = new System.Windows.Point(-11.5, -11.5);
wpMarker.ZIndex = 100;
_setMarkerColor(wpMarker, type);
MainMap.Markers.Add(wpMarker);
if (type == 0 || type == 3)
{
wpList.Add(p);
wpOffset.Add(index);
}
((CustomMarkerWP)wpMarker.Shape).positionChanged += _updateDTWPPos;
((CustomMarkerWP)wpMarker.Shape).newPosition += _updateDTWPPosFin;
((CustomMarkerWP)wpMarker.Shape).mouseCaptured += _WPMouseCaptured;
_setMapItemsSize("WP", SliderWPZoom.Value);
});
return wpMarker;
}
bool _WPisMouseCaptured = false;
void _WPMouseCaptured(bool isCaptured)
{
_WPisMouseCaptured = isCaptured;
MainMap.CanDragMap = !isCaptured;
}
void _updateDTWPPos(CustomMarkerWP wp)
{
string sIndex = wp.WPText.Substring(1, wp.WPText.Length - 1);
int index = Convert.ToInt16(sIndex) -1;
GMapMarker p = ((GMapMarker)wp.DataContext);
if (p != null && index < dtWaypoints.Rows.Count)
{
//Dispatcher.Invoke(() => dgvWP.Items.Refresh());
if(wp.WPType == 0 | wp.WPType == 3)
{
PointLatLng x = new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]);
int wpListIndex = wpList.IndexOf(x);
if (wpListIndex > -1)
{
wpList[wpListIndex] = p.Position;
MainMap.Markers.Remove(mRouteWP);
_routeUpdate();
}
}
dtWaypoints.Rows[index][3] = p.Position.Lat;
dtWaypoints.Rows[index][4] = p.Position.Lng;
}
}
void _updateDTWPPosFin(CustomMarkerWP wp)
{
string sIndex = wp.WPText.Substring(1, wp.WPText.Length - 1);
int index = Convert.ToInt16(sIndex) -1;
GMapMarker p = ((GMapMarker)wp.DataContext);
if (p != null && index < dtWaypoints.Rows.Count)
{
dtWaypoints.Rows[index][3] = p.Position.Lat;
dtWaypoints.Rows[index][4] = p.Position.Lng;
Dispatcher.Invoke(() =>
{
dgvWP.Items.Refresh();
dgvWP.SelectedIndex = index;
_dgvWPselectEditRow();
});
 
}
 
}
void _addWP(PointLatLng p,int type)
{
object[] o = new object[16];
 
o[0] = dgvWP.ItemContainerGenerator.Items.Count + 1;
o[1] = type;
// cbWPEditType.SelectedIndex = 0;
// tbWPEditPrefix.Text = "P";
o[2] = _wpDefPrefix + o[0].ToString();
// tbWPEditLat.Text = copter.Position.Lat.ToString();
o[3] = p.Lat;
// tbWPEditLon.Text = copter.Position.Lng.ToString();
o[4] = p.Lng;
// lblWPEditAlt.Content = ((double)iAnalogData[4] / (double)10).ToString();
o[5] = _wpAddCopterHeight ? iAnalogData[4].ToString(): _wpDefAltitude.ToString();
 
cbWPEditHeading.SelectedIndex = _wpDefCBoxHeading;
o[6] = _wpAddCopterHeading ? iAnalogData[10].ToString(): _wpDefHeading.ToString();
//lblWPEditHeading.Content = iAnalogData[10].ToString();
// tbWPEditHeading.IsReadOnly = false;
 
cbWPEditSpeed.SelectedIndex = _wpDefCBoxSpeed;
// tbWPEditSpeed.Text = "5.0";
// tbWPEditSpeed.IsReadOnly = false;
o[7] = _wpDefSpeed.ToString();
 
cbWPEditClimbrate.SelectedIndex = _wpDefCBoxClimb;
// lblWPEditClimbrate.Content = "5.0";
// tbWPEditClimbrate.IsReadOnly = false;
o[8] = _wpDefClimb.ToString();
 
// lblWPEditRadius.Content = "10";
o[9] = _wpDefRadius.ToString();
// lblWPEditHoldtime.Content = "5";
o[10] = _wpDefHoldtime.ToString();
// lblWPEditAutoTrigger.Content = "0";
o[11] = _wpDefAutotrig.ToString();
cbWPEditCamAngle.SelectedIndex = _wpDefCBoxCamangle;
// lblWPEditCamAngle.Content = "AUTO";
// tbWPEditCamAngle.IsReadOnly = true;
o[12] = _wpDefCamangle.ToString();
 
o[13] = "0";
// lblWPEditOut1.Content = "0";
o[14] = _wpDefOut1.ToString();
o[15] = "0";
 
dtWaypoints.Rows.Add(o);
_createWP(new PointLatLng((double)o[3], (double)o[4]), (string)o[2], (int)o[1], (int)o[0] - 1);
// Dispatcher.Invoke(() => lblWPCount.Content = o[0].ToString());
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
_routeUpdate();
Dispatcher.Invoke(() =>
{
dgvWP.Items.Refresh();
dgvWP.UpdateLayout();
dgvWP.SelectedIndex = (int)o[0] - 1;
_dgvWPselectEditRow();
});
}
/// <summary>
/// find the index of of a wp from datatable in the waypointlist wpList
/// </summary>
/// <param name="dtIndex">the index of wp in datatable (0-based)</param>
/// <returns></returns>
int _getWPIndexfromList(int dtIndex)
{
if ((int)dtWaypoints.Rows[dtIndex][1] == 0 || (int)dtWaypoints.Rows[dtIndex][1] == 3)
{
GMapMarker wp = _findWPMarker((string)dtWaypoints.Rows[dtIndex][2]);
if (wp != null)
return wpList.IndexOf(wp.Position);
}
return -1;
}
/// <summary>
/// find the index of of a wp from datatable in the waypointlist wpList
/// </summary>
/// <param name="name">the name of the wp</param>
/// <returns></returns>
int _getWPIndexfromList(string name)
{
GMapMarker wp = _findWPMarker(name);
if ((wp != null && wp.Shape != null) && ((CustomMarkerWP)wp.Shape).WPType == 0 | ((CustomMarkerWP)wp.Shape).WPType == 3)
return wpList.IndexOf(wp.Position);
else
return -1;
}
int _getWPListOffset(int index)
{
int k = 0;
for(int i = 0; i < wpOffset.Count;i++)
{
if (wpOffset[i] <= index)
k++;
}
 
return k;
}
void _setMarkerColor(GMapMarker wpMarker,int iType)
{
if(wpMarker != null)
Dispatcher.Invoke(() =>
{
switch (iType)
{
case 0:
if (comboBoxWPColor.SelectionBoxItem != null)
{
string s = comboBoxWPColor.SelectionBoxItem.ToString();
((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
}
else
((CustomMarkerWP)(wpMarker.Shape)).setColor("green");
break;
case 1:
if (comboBoxPOIColor.SelectionBoxItem != null)
{
string s = comboBoxPOIColor.SelectionBoxItem.ToString();
((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
}
else
((CustomMarkerWP)(wpMarker.Shape)).setColor("pink");
break;
case 2:
if (comboBoxFSColor.SelectionBoxItem != null)
{
string s = comboBoxFSColor.SelectionBoxItem.ToString();
((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
}
else
((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
break;
case 3:
if (comboBoxLandingColor.SelectionBoxItem != null)
{
string s = comboBoxLandingColor.SelectionBoxItem.ToString();
((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
}
else
((CustomMarkerWP)(wpMarker.Shape)).setColor("blue");
break;
default:
((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
break;
}
});
 
}
void _MarkerColorSelection(object sender,int type)
{
Dispatcher.Invoke(() =>
{
if (((ComboBox)sender).SelectionBoxItem != null)
{
for (int k = 0; k < MainMap.Markers.Count; k++)
{
GMapMarker p = MainMap.Markers[k];
if (p.Shape != null && p.Shape.GetType() == typeof(CustomMarkerWP))
{
if (((CustomMarkerWP)p.Shape).WPType == type)
{
string s = ((ComboBox)sender).SelectionBoxItem.ToString();
((CustomMarkerWP)(p.Shape)).setColor(s);
}
}
}
}
});
}
private void comboBoxWPColor_DropDownClosed(object sender, EventArgs e)
{
_MarkerColorSelection(sender, 0);
}
private void comboBoxPOIColor_DropDownClosed(object sender, EventArgs e)
{
_MarkerColorSelection(sender, 1);
}
private void comboBoxFSColor_DropDownClosed(object sender, EventArgs e)
{
_MarkerColorSelection(sender, 2);
}
private void comboBoxLandingColor_DropDownClosed(object sender, EventArgs e)
{
_MarkerColorSelection(sender,3);
}
private void comboBoxCopterColor_DropDownClosed(object sender, EventArgs e)
{
Dispatcher.Invoke(() => {
if (comboBoxCopterColor.SelectionBoxItem != null)
{
string s = comboBoxCopterColor.SelectionBoxItem.ToString();
((CustomMarkerCopter)(copter.Shape)).setCopterColor(s);
}
else
((CustomMarkerCopter)(copter.Shape)).setCopterColor("red");
});
}
private void comboBoxCopterHeadingColor_DropDownClosed(object sender, EventArgs e)
{
Dispatcher.Invoke(() => {
if (comboBoxCopterHeadingColor.SelectionBoxItem != null)
{
string s = comboBoxCopterHeadingColor.SelectionBoxItem.ToString();
((CustomMarkerCopter)(copter.Shape)).setHeadingColor(s);
}
else
((CustomMarkerCopter)(copter.Shape)).setHeadingColor("red");
});
}
private void comboBoxRouteColor_DropDownClosed(object sender, EventArgs e)
{
Dispatcher.Invoke(() =>
{
if (comboBoxRouteColor.SelectionBoxItem != null)
{
string s = comboBoxRouteColor.SelectionBoxItem.ToString();
MainMap.Markers.Remove(mRouteWP);
mRouteWP = new GMapRoute(wpList, _getBrush(s));
if (_bShowWPRoute)
MainMap.Markers.Add(mRouteWP);
}
});
}
private void comboBoxWPMaxRangeColor_DropDownClosed(object sender, EventArgs e)
{
Dispatcher.Invoke(() =>
{
if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
{
if (home != null && checkBoxShowWPMaxRange.IsChecked == true && dWPMaxRange > 0)
{
if (cWPBound != null && cWPBound.Tag != null)
MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
 
createCircle(home.Position, dWPMaxRange);
string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
cWPBound.setColor(s);
 
}
}
});
 
}
private void checkBoxShowWPRoute_Click(object sender, RoutedEventArgs e)
{
_bShowWPRoute = (bool)checkBoxShowWPRoute.IsChecked;
if (_bShowWPRoute)
{
if (mRouteWP != null)
MainMap.Markers.Add(mRouteWP);
}
else
{
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
}
}
 
private void btnLoadWPLFile_Click(object sender, RoutedEventArgs e)
{
_readWPLFile();
}
private void btnClearWPList_Click(object sender, RoutedEventArgs e)
{
_clearMapMarkers(typeof(CustomMarkerWP));
_clearMapMarkers(typeof(CustomMarkerWPActive));
wpList.Clear();
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
//if (wpActiveMarker != null)
// MainMap.Markers.Remove(wpActiveMarker);
dtWaypoints.Rows.Clear();
_wpEdit = -1;
_wpIndex = -1;
wpOffset.Clear();
Dispatcher.Invoke(() => dgvWP.Items.Refresh());
Dispatcher.Invoke(() => lblWPIndex.Content = 0);
Dispatcher.Invoke(() => lblWPCount.Content = 0);
Dispatcher.Invoke(() => lblWPRouteDistance.Content = "0 m");
}
private void btnClearCopterList_Click(object sender, RoutedEventArgs e)
{
Thread t = new Thread(new ThreadStart(clearCopterWPList));
t.Start();
}
private void btnSendActiveWP_Click(object sender, RoutedEventArgs e)
{
if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
{
if (_wpCount > 0)
_sendWayPoint(dtWaypoints.Rows[dgvWP.SelectedIndex], -1, 's',false);
else
_sendWayPoint(dtWaypoints.Rows[dgvWP.SelectedIndex], 1, 's',false);
 
//int index = dgvWP.SelectedIndex;
//Thread t = new Thread(() => _sendWPList(index));
//t.Start();
 
Dispatcher.Invoke(() => {
DataGridRow row;
if (_wpEdit > -1 && _wpEdit < dgvWP.ItemContainerGenerator.Items.Count)
{
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
row.Background = new SolidColorBrush(Colors.Transparent);
row.BorderBrush = new SolidColorBrush(Colors.Transparent);
row.BorderThickness = new Thickness(0);
dgvWP.UpdateLayout();
}
//_wpEdit = dgvWP.SelectedIndex;
//row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
//row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 255, 100));
//row.BorderBrush = new SolidColorBrush(Colors.SpringGreen);
//row.BorderThickness = new Thickness(2);
});
}
}
private void btnEditWPSendToCopter_Click(object sender, RoutedEventArgs e)
{
if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
{
 
object[] o = new object[16];
o[0] = dgvWP.SelectedIndex + 1;
o[1] = cbWPEditType.SelectedIndex;
o[2] = tbWPEditPrefix.Text + (dgvWP.SelectedIndex + 1).ToString();
o[3] = Convert.ToDouble(tbWPEditLat.Text.Replace('.', ','));
o[4] = Convert.ToDouble(tbWPEditLon.Text.Replace('.', ','));
o[5] = lblWPEditAlt.Content;
switch (cbWPEditHeading.SelectedIndex)
{
case 0:
o[6] = "0";
break;
case 1:
o[6] = "-" + lblWPEditHeading.Content;
break;
case 2:
o[6] = lblWPEditHeading.Content;
break;
}
switch (cbWPEditSpeed.SelectedIndex)
{
case 0:
o[7] = "0";
break;
case 1:
o[7] = (System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10).ToString("0");
break;
case 2:
o[7] = (256 - Convert.ToInt16(lblWPEditSpeed.Content)).ToString();
break;
}
switch (cbWPEditClimbrate.SelectedIndex)
{
case 0:
o[8] = "255";
break;
case 1:
o[8] = (System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.', ',')) * 10).ToString("0");
break;
}
o[9] = lblWPEditRadius.Content;
o[10] = lblWPEditHoldtime.Content;
o[11] = lblWPEditAutoTrigger.Content;
switch (cbWPEditCamAngle.SelectedIndex)
{
case 0:
o[12] = "0";
break;
case 1:
o[12] = "255";
break;
case 2:
o[12] = lblWPEditCamAngle.Content;
break;
}
o[13] = 0;
o[14] = lblWPEditOut1.Content;
DataRow dr = dtWaypoints.NewRow();
dr.ItemArray = o;
 
if (_wpCount > 0)
_sendWayPoint(dr, -1, 'w', false);
else
_sendWayPoint(dr, 1, 'w', false);
 
if (_wpIndex > -1 && _wpIndex < dtWaypoints.Rows.Count)
_sendWayPoint(dtWaypoints.Rows[wpOffset[_wpIndex]], _wpIndex+1, 's', false);
}
}
private void btnWPSimulateStart_Click(object sender, RoutedEventArgs e)
{
_Simulate = !_Simulate;
if (dtWaypoints.Rows.Count > 0)
{
DataRow dr = dtWaypoints.Rows[0];
dr[13] = _Simulate ? 3 : 0;
_sendWayPoint(dr, 0, 's', true);
rectSimulate.Visibility = lblSimu.Visibility = _Simulate ? Visibility.Visible : Visibility.Hidden;
}
}
 
private void dgvWP_MouseUp(object sender, MouseButtonEventArgs e)
{
_dgvWPselectEditRow();
}
private void dgvWP_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
}
void _dgvWPselectEditRow()
{
if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
{
Dispatcher.Invoke(() => {
DataGridRow row;
dgvWP.Items.Refresh();
dgvWP.UpdateLayout();
if (_wpEdit > -1 && _wpEdit < dgvWP.ItemContainerGenerator.Items.Count)
{
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
if (row != null)
{
row.Background = new SolidColorBrush(Colors.Transparent);
row.BorderBrush = new SolidColorBrush(Colors.Transparent);
row.BorderThickness = new Thickness(0);
}
}
_wpEdit = dgvWP.SelectedIndex;
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
if (row != null)
{
row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 100, 255));
row.BorderBrush = new SolidColorBrush(Colors.Aqua);
row.BorderThickness = new Thickness(2);
dgvWP.UpdateLayout();
}
if (GridWPEdit.Visibility == Visibility.Collapsed && _bAutoWPEdit)
GridWPEdit.Visibility = Visibility.Visible;
 
_setWPEditFields(_wpEdit);
});
}
}
void _setWPEditFields(int index)
{
if (GridWPEdit.Visibility == Visibility.Collapsed && _bAutoWPEdit)
GridWPEdit.Visibility = Visibility.Visible;
 
int iVal;
lblWPEditIndex.Content = dtWaypoints.Rows[index][0].ToString();
cbWPEditType.SelectedIndex = (int)dtWaypoints.Rows[index][1];
tbWPEditPrefix.Text = dtWaypoints.Rows[index][2].ToString().Substring(0,1);
tbWPEditLat.Text = dtWaypoints.Rows[index][3].ToString();
tbWPEditLon.Text = dtWaypoints.Rows[index][4].ToString();
 
SliderAlt.Value = Convert.ToInt16(dtWaypoints.Rows[index][5]);
 
iVal = Convert.ToInt16(dtWaypoints.Rows[index][6]);
SliderHeading.Value = Math.Abs(iVal);
if (iVal == 0)
{
cbWPEditHeading.SelectedIndex = 0;
// lblWPEditHeading.Content = " - - -";
}
if (iVal > 0 && iVal < 360)
{
cbWPEditHeading.SelectedIndex = 2;
// lblWPEditHeading.Content = iVal.ToString();
}
if (iVal < 0)
{
cbWPEditHeading.SelectedIndex = 1;
// lblWPEditHeading.Content = (Math.Abs(iVal).ToString());
}
iVal = Convert.ToInt16(dtWaypoints.Rows[index][7]);
SliderSpeed.Value = (double)iVal * 0.1; //------------!!!!!!!!
if (iVal == 0)
{
cbWPEditSpeed.SelectedIndex = 0;
// lblWPEditSpeed.Content = "MAX";
}
if (iVal > 0 && iVal < 248)
{
cbWPEditSpeed.SelectedIndex = 1;
// lblWPEditSpeed.Content = ((double)iVal * 0.1).ToString();
}
if (iVal > 247)
{
cbWPEditSpeed.SelectedIndex = 256 - iVal + 1;
// lblWPEditSpeed.Content = "";
}
iVal = Convert.ToInt16(dtWaypoints.Rows[index][8]);
SliderClimbrate.Value = (System.Convert.ToDouble(iVal) / 10); //------------!!!!!!!!
if (iVal == 255)
{
cbWPEditClimbrate.SelectedIndex = 0;
// lblWPEditClimbrate.Content = "AUTO";
}
else
{
cbWPEditClimbrate.SelectedIndex = 1;
// lblWPEditClimbrate.Content = (System.Convert.ToDouble(iVal) / 10).ToString("0.0");
}
iVal = Convert.ToInt16(dtWaypoints.Rows[index][9]);
SliderRadius.Value = iVal;
iVal = Convert.ToInt16(dtWaypoints.Rows[index][10]);
SliderHoldTime.Value = iVal;
iVal = Convert.ToInt16(dtWaypoints.Rows[index][11]);
SliderAutoTrigger.Value = iVal;
iVal = Convert.ToInt16(dtWaypoints.Rows[index][12]);
SliderCamAngle.Value = iVal;
if (iVal == 0)
{
cbWPEditCamAngle.SelectedIndex = 0;
// lblWPEditCamAngle.Content = " - - - ";
}
if (iVal < 0 | iVal == 255)
{
cbWPEditCamAngle.SelectedIndex = 1;
// lblWPEditCamAngle.Content = "AUTO";
}
if (iVal > 0 & iVal < 255)
{
cbWPEditCamAngle.SelectedIndex = 2;
// lblWPEditCamAngle.Content = iVal.ToString();
}
iVal = Convert.ToInt16(dtWaypoints.Rows[index][14]);
SliderOut1.Value = iVal;
}
private void btnEditWPSave_Click(object sender, RoutedEventArgs e)
{
if(dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
{
string oldName = (string)dtWaypoints.Rows[dgvWP.SelectedIndex][2];
int oldType = (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1];
PointLatLng pOld = new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]);
int i = wpList.IndexOf(pOld);
dtWaypoints.Rows[dgvWP.SelectedIndex][1] = cbWPEditType.SelectedIndex;
dtWaypoints.Rows[dgvWP.SelectedIndex][2] = tbWPEditPrefix.Text + (dgvWP.SelectedIndex + 1).ToString();
dtWaypoints.Rows[dgvWP.SelectedIndex][3] = Convert.ToDouble(tbWPEditLat.Text.Replace('.', ','));
dtWaypoints.Rows[dgvWP.SelectedIndex][4] = Convert.ToDouble(tbWPEditLon.Text.Replace('.', ','));
if (i > -1)
{
if ((int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 0 || (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 3)
wpList[i] = (new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]));
else
{
wpList.Remove(pOld);
wpOffset.Remove(wpOffset[i]);
}
}
else
{
if ((int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 0 || (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 3)
{
int found = 0;
for (int k = 0; k < dgvWP.SelectedIndex; k++)
{
if ((int)dtWaypoints.Rows[k][1] == 0 || (int)dtWaypoints.Rows[k][1] == 3)
{
found++;
}
}
wpList.Insert(found, new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]));
wpOffset.Insert(found, dgvWP.SelectedIndex);
}
}
dtWaypoints.Rows[dgvWP.SelectedIndex][5] = lblWPEditAlt.Content;
switch (cbWPEditHeading.SelectedIndex)
{
case 0:
dtWaypoints.Rows[dgvWP.SelectedIndex][6] = "0";
break;
case 1:
dtWaypoints.Rows[dgvWP.SelectedIndex][6] = "-" + lblWPEditHeading.Content;
break;
case 2:
dtWaypoints.Rows[dgvWP.SelectedIndex][6] = lblWPEditHeading.Content;
break;
}
switch (cbWPEditSpeed.SelectedIndex)
{
case 0:
dtWaypoints.Rows[dgvWP.SelectedIndex][7] = "0";
break;
case 1:
dtWaypoints.Rows[dgvWP.SelectedIndex][7] = (System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10).ToString("0");
break;
case 2:
dtWaypoints.Rows[dgvWP.SelectedIndex][7] = (256 - Convert.ToInt16(lblWPEditSpeed.Content)).ToString();
break;
}
switch (cbWPEditClimbrate.SelectedIndex)
{
case 0:
dtWaypoints.Rows[dgvWP.SelectedIndex][8] = "255";
break;
case 1:
dtWaypoints.Rows[dgvWP.SelectedIndex][8] = (System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.',',')) * 10).ToString("0");
break;
}
dtWaypoints.Rows[dgvWP.SelectedIndex][9] = lblWPEditRadius.Content;
dtWaypoints.Rows[dgvWP.SelectedIndex][10] = lblWPEditHoldtime.Content;
dtWaypoints.Rows[dgvWP.SelectedIndex][11] = lblWPEditAutoTrigger.Content;
switch (cbWPEditCamAngle.SelectedIndex)
{
case 0:
dtWaypoints.Rows[dgvWP.SelectedIndex][12] = "0";
break;
case 1:
dtWaypoints.Rows[dgvWP.SelectedIndex][12] = "255";
break;
case 2:
dtWaypoints.Rows[dgvWP.SelectedIndex][12] = lblWPEditCamAngle.Content;
break;
}
dtWaypoints.Rows[dgvWP.SelectedIndex][14] = lblWPEditOut1.Content;
 
// _clearMapMarkers(typeof(CustomMarkerWP));
_repositionWPMarker(new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]),oldName);
_renameWPMarker(oldName, (string)dtWaypoints.Rows[dgvWP.SelectedIndex][2]);
_clearMapMarkers(typeof(CustomMarkerWPActive));
_setMarkerColor(_findWPMarker((string)dtWaypoints.Rows[dgvWP.SelectedIndex][2]), (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1]);
_WPMarkerSetType((string)dtWaypoints.Rows[dgvWP.SelectedIndex][2], (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1]);
// wpList.Clear();
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
 
//for (int k = 0; k < dtWaypoints.Rows.Count; k++)
//{
// _createWP(new PointLatLng((double)dtWaypoints.Rows[k][3], (double)dtWaypoints.Rows[k][4]), (string)dtWaypoints.Rows[k][2], (int)dtWaypoints.Rows[k][1]);
//}
_routeUpdate();
dgvWP.Items.Refresh();
 
}
 
}
private void btnEditWPAdd_Click(object sender, RoutedEventArgs e)
{
DataRow dr = dtWaypoints.NewRow();
dr[0] = dtWaypoints.Rows.Count+1;
dr[1] = cbWPEditType.SelectedIndex;
dr[2] = tbWPEditPrefix.Text + dr[0].ToString();
dr[3] = Convert.ToDouble(tbWPEditLat.Text.Replace('.', ',')) + 0.00000001;
dr[4] = Convert.ToDouble(tbWPEditLon.Text.Replace('.', ',')) + 0.00000001;
dr[5] = lblWPEditAlt.Content;
switch (cbWPEditHeading.SelectedIndex)
{
case 0:
dr[6] = "0";
break;
case 1:
dr[6] = "-" + lblWPEditHeading.Content;
break;
case 2:
dr[6] = lblWPEditHeading.Content;
break;
}
switch (cbWPEditSpeed.SelectedIndex)
{
case 0:
dr[7] = "0";
break;
case 1:
dr[7] = (System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10).ToString("0");
break;
case 2:
dr[7] = (256 - Convert.ToInt16(lblWPEditSpeed.Content)).ToString();
break;
}
switch (cbWPEditClimbrate.SelectedIndex)
{
case 0:
dr[8] = "255";
break;
case 1:
dr[8] = (System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.', ',')) * 10).ToString("0");
break;
}
dr[9] = lblWPEditRadius.Content;
dr[10] = lblWPEditHoldtime.Content;
dr[11] = lblWPEditAutoTrigger.Content;
switch (cbWPEditCamAngle.SelectedIndex)
{
case 0:
dr[12] = "0";
break;
case 1:
dr[12] = "255";
break;
case 2:
dr[12] = lblWPEditCamAngle.Content;
break;
}
dr[13] = "";
dr[14] = lblWPEditOut1.Content;
dr[15] = "";
_createWP(new PointLatLng((double)dr[3], (double)dr[4]),(string) dr[2], (int)dr[1], (int)dr[0]);
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
_routeUpdate();
dtWaypoints.Rows.Add(dr);
dgvWP.Items.Refresh();
}
private void btnEditWPDel_Click(object sender, RoutedEventArgs e)
{
if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
{
int index = dgvWP.SelectedIndex;
Dispatcher.Invoke(() => {
DataGridRow row;
if (_wpEdit > -1 && _wpEdit < dgvWP.ItemContainerGenerator.Items.Count)
{
row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
row.Background = new SolidColorBrush(Colors.Transparent);
row.BorderBrush = new SolidColorBrush(Colors.Transparent);
row.BorderThickness = new Thickness(0);
}
if ((int)dtWaypoints.Rows[index][1] == 0 || (int)dtWaypoints.Rows[index][1] == 3)
wpList.Remove(new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]));
else
wpOffset.Remove((int)dtWaypoints.Rows[index][0] + 1);
_clearWPMarker((string)dtWaypoints.Rows[index][2]);
if (wpActiveMarker != null)
MainMap.Markers.Remove(wpActiveMarker);
dtWaypoints.Rows[index].Delete();
_wpIndex = -1;
_wpEdit = -1;
for (int i = index; i < dtWaypoints.Rows.Count; i++) //change the index of points behind deleted point + rename to new index
{
dtWaypoints.Rows[i][0] = i + 1;
string s1 = (string)dtWaypoints.Rows[i][2]; //old name of WP (Prefix + index)
string s2 = s1.Substring(0, 1) + (i + 1).ToString(); //new name of WP
_renameWPMarker(s1, s2);
dtWaypoints.Rows[i][2] = s2;
}
lblWPCount.Content = dtWaypoints.Rows.Count;
if (mRouteWP != null)
MainMap.Markers.Remove(mRouteWP);
_routeUpdate();
 
dgvWP.UpdateLayout();
});
}
}
private void tbWPEdit_TouchDown(object sender, TouchEventArgs e)
{
_wpWEdit(sender);
}
private void tbWPEdit_KeyDown(object sender, KeyEventArgs e)
{
_wpWEdit(sender);
}
private void tbWPEdit_MouseDown(object sender, MouseButtonEventArgs e)
{
_wpWEdit(sender);
}
void _wpWEdit(object sender)
{
// if (!((TextBox)sender).IsReadOnly)
{
KeyPad.Keypad k = new KeyPad.Keypad(this);
 
switch (((TextBox)sender).Name)
{
case "tbWPEditLat":
k.Title = "Latitude";
k.LENGTH = 17;
k.MAX = 359.9;
break;
case "tbWPEditLon":
k.Title = "Longitude";
k.LENGTH = 17;
k.MAX = 359.9;
break;
case "tbWPEditAlt":
k.Title = "Altitude";
k.LENGTH = 3;
k.MAX = 254;
k.disableDecimal();
break;
case "tbWPEditHeading":
k.Title = "Heading";
k.LENGTH = 3;
k.MAX = 359;
k.MIN = 1;
k.disableDecimal();
break;
case "tbWPEditSpeed":
k.Title = "Speed";
k.LENGTH = 4;
k.MAX = 24.7;
k.MIN = 0.1;
break;
case "tbWPEditClimbrate":
k.Title = "Climbrate";
k.LENGTH = 4;
k.MAX = 25.4;
k.MIN = 0.1;
break;
case "tbWPEditRadius":
k.Title = "Radius";
k.LENGTH = 3;
k.MAX = 254;
k.disableDecimal();
break;
case "tbWPEditHoldtime":
k.Title = "Holdtime";
k.LENGTH = 3;
k.MAX = 254;
break;
case "tbWPEditAutoTrigger":
k.Title = "Autotrigger";
k.LENGTH = 3;
k.MAX = 254;
k.disableDecimal();
break;
case "tbWPEditCamAngle":
k.Title = "Camera angle";
k.LENGTH = 3;
k.MAX = 254;
k.MIN = 1;
k.disableDecimal();
break;
case "tbWPEditOut1":
k.Title = "OUT1 timer interval";
k.LENGTH = 3;
k.MAX = 254;
k.disableDecimal();
break;
}
k.Result = ((TextBox)sender).Text;
if (k.ShowDialog() == true && k.Result.Length > 0)
((TextBox)sender).Text = k.Result;
}
 
}
private void btnWPAddCurrentPos_Click(object sender, RoutedEventArgs e)
{
_addWP(new PointLatLng(copter.Position.Lat, copter.Position.Lng),0);
}
private void checkBoxWPAddUseCopterHeading_Click(object sender, RoutedEventArgs e)
{
_wpAddCopterHeading = (bool)checkBoxWPAddUseCopterHeading.IsChecked;
}
private void checkBoxWPAddUseCopterHeight_Click(object sender, RoutedEventArgs e)
{
_wpAddCopterHeight = (bool)checkBoxWPAddUseCopterHeight.IsChecked;
}
private void btnSaveDefault_Click(object sender, RoutedEventArgs e)
{
_wpDefPrefix = tbWPEditPrefix.Text;
_wpDefAltitude = Convert.ToInt16(lblWPEditAlt.Content);
switch (cbWPEditHeading.SelectedIndex)
{
case 0:
_wpDefHeading = 0;
break;
case 1:
_wpDefHeading = -Convert.ToInt16(lblWPEditHeading.Content);
break;
case 2:
_wpDefHeading = Convert.ToInt16(lblWPEditHeading.Content);
break;
}
_wpDefCBoxHeading = cbWPEditHeading.SelectedIndex;
switch (cbWPEditSpeed.SelectedIndex)
{
case 0:
_wpDefSpeed = 0;
break;
case 1:
_wpDefSpeed = (int)(System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10);
break;
case 2:
_wpDefSpeed = 256 - Convert.ToInt16(lblWPEditSpeed.Content);
break;
}
_wpDefCBoxSpeed = cbWPEditSpeed.SelectedIndex;
switch (cbWPEditClimbrate.SelectedIndex)
{
case 0:
_wpDefClimb = 255;
break;
case 1:
_wpDefClimb = (int)(System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.', ',')) * 10);
break;
}
_wpDefCBoxClimb = cbWPEditClimbrate.SelectedIndex;
_wpDefRadius = Convert.ToInt16(lblWPEditRadius.Content);
_wpDefHoldtime = Convert.ToInt16(lblWPEditHoldtime.Content);
_wpDefAutotrig = Convert.ToInt16(lblWPEditAutoTrigger.Content);
switch (cbWPEditCamAngle.SelectedIndex)
{
case 0:
_wpDefCamangle = 0;
break;
case 1:
_wpDefCamangle = 255;
break;
case 2:
_wpDefCamangle = Convert.ToInt16(lblWPEditCamAngle.Content);
break;
}
_wpDefCBoxCamangle = cbWPEditCamAngle.SelectedIndex;
_wpDefOut1 = Convert.ToInt16(lblWPEditOut1.Content);
}
 
private void btnWPEditmoveUp_Click(object sender, RoutedEventArgs e)
{
if (dgvWP.SelectedIndex > 0 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
{
int index = dgvWP.SelectedIndex;
if (((int)dtWaypoints.Rows[index][1] == 0 | (int)dtWaypoints.Rows[index][1] == 3) && ((int)dtWaypoints.Rows[index - 1][1] == 0 | (int)dtWaypoints.Rows[index - 1][1] == 3))// && wpList.Count > index)
{
PointLatLng x = new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]);
int wpListIndex = wpList.IndexOf(x);
if (wpListIndex > 0)
{
wpList.RemoveAt(wpListIndex);
wpList.Insert(wpListIndex - 1, x);
MainMap.Markers.Remove(mRouteWP);
_routeUpdate();
}
}
DataRow dr = dtWaypoints.Rows[index];
DataRow newRow = dtWaypoints.NewRow();
newRow.ItemArray = dr.ItemArray;
dtWaypoints.Rows.Remove(dr);
dtWaypoints.Rows.InsertAt(newRow, index - 1);
dtWaypoints.Rows[index][0] = 100;
dtWaypoints.Rows[index - 1][0] = index;
GMapMarker m1 = _findWPMarker(dtWaypoints.Rows[index - 1][2].ToString());
GMapMarker m2 = _findWPMarker(dtWaypoints.Rows[index][2].ToString());
dtWaypoints.Rows[index - 1][2] = dtWaypoints.Rows[index - 1][2].ToString().Substring(0, 1) + index.ToString();
((CustomMarkerWP)m1.Shape).text.Text = dtWaypoints.Rows[index - 1][2].ToString();
dtWaypoints.Rows[index][0] = index + 1;
dtWaypoints.Rows[index][2] = dtWaypoints.Rows[index][2].ToString().Substring(0, 1) + (index+1).ToString();
((CustomMarkerWP)m2.Shape).text.Text = dtWaypoints.Rows[index][2].ToString();
dgvWP.Items.Refresh();
dgvWP.SelectedIndex = index - 1;
_dgvWPselectEditRow();
if (wpOffset.Contains(index)) // calculating offset for wpList (index is 0-based - offset starts with index 1)
{
int iOffset = wpOffset.IndexOf(index);
if (iOffset > 0) // if not first element
{
if (wpOffset[iOffset - 1] < index-1) //if previous element is not immediately before actual offset
wpOffset[iOffset] = index-1; //then decrease offset value by one
}
else
wpOffset[iOffset] = index-1; //if first element, decrease offset by one
}
else //selected line is POI
{
if (wpOffset.Contains(index - 1)) // if next point is WP
{
int iOffset = wpOffset.IndexOf(index - 1);
wpOffset[iOffset] = index; //decrease linenumber of following WP
}
}
 
}
}
private void btnWPEditmoveDown_Click(object sender, RoutedEventArgs e)
{
if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count - 1)
{
int index = dgvWP.SelectedIndex;
if (((int)dtWaypoints.Rows[index][1] == 0 | (int)dtWaypoints.Rows[index][1] == 3) && ((int)dtWaypoints.Rows[index+1][1] == 0 | (int)dtWaypoints.Rows[index+1][1] == 3))// && wpList.Count > index)
{
PointLatLng x = new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]);
int wpListIndex = wpList.IndexOf(x);
if (wpListIndex > -1)
{
wpList.RemoveAt(wpListIndex);
if (wpList.Count > wpListIndex)
wpList.Insert(wpListIndex + 1, x);
else
wpList.Add(x);
MainMap.Markers.Remove(mRouteWP);
_routeUpdate();
}
}
DataRow dr = dtWaypoints.Rows[index];
DataRow newRow = dtWaypoints.NewRow();
newRow.ItemArray = dr.ItemArray;
dtWaypoints.Rows.Remove(dr);
dtWaypoints.Rows.InsertAt(newRow, index + 1);
dtWaypoints.Rows[index][0] = 100;
dtWaypoints.Rows[index + 1][0] = index + 2;
GMapMarker m1 = _findWPMarker(dtWaypoints.Rows[index + 1][2].ToString());
GMapMarker m2 = _findWPMarker(dtWaypoints.Rows[index][2].ToString());
dtWaypoints.Rows[index + 1][2] = dtWaypoints.Rows[index + 1][2].ToString().Substring(0, 1) + (index+2).ToString();
((CustomMarkerWP)m1.Shape).text.Text = dtWaypoints.Rows[index + 1][2].ToString();
dtWaypoints.Rows[index][0] = index + 1;
dtWaypoints.Rows[index][2] = dtWaypoints.Rows[index][2].ToString().Substring(0, 1) + (index+1).ToString();
((CustomMarkerWP)m2.Shape).text.Text = dtWaypoints.Rows[index][2].ToString();
dgvWP.Items.Refresh();
dgvWP.SelectedIndex = index + 1;
_dgvWPselectEditRow();
if(wpOffset.Contains(index)) // If selected line is WP
{
int iOffset = wpOffset.IndexOf(index);
if(iOffset < wpOffset.Count -1) // if not last element
{
if (wpOffset[iOffset + 1] > index + 1) //if next element is not immediately after actual offset
wpOffset[iOffset] = index + 1; //then increase offset value by one
}
else
wpOffset[iOffset] = index + 1; //if last element increase offset by one
}
else //selected line is POI
{
if (wpOffset.Contains(index + 1)) // if next point is WP
{
int iOffset = wpOffset.IndexOf(index + 1);
wpOffset[iOffset] = index; //decrease linenumber of following WP
}
}
}
 
}
 
private void checkBoxShowWPStatus_Click(object sender, RoutedEventArgs e)
{
if (WPStatus.Visibility == Visibility.Visible)
GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value + 36, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
else
GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
}
private void checkBoxShowWPMaxRange_click(object sender, RoutedEventArgs e)
{
if (home != null && checkBoxShowWPMaxRange.IsChecked == true && dWPMaxRange > 0)
{
if (cWPBound != null && cWPBound.Tag != null)
MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
 
createCircle(home.Position, dWPMaxRange);
if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
{
string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
cWPBound.setColor(s);
}
}
 
if (checkBoxShowWPMaxRange.IsChecked == false && (cWPBound != null && cWPBound.Tag != null))
MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
}
private void checkBoxAutoShowWPEdit_Click(object sender, RoutedEventArgs e)
{
_bAutoWPEdit = (bool)checkBoxAutoShowWPEdit.IsChecked;
}
 
#endregion WP
#region GPX
private void checkBoxGPXLog_Click(object sender, RoutedEventArgs e)
{
_bGPXLog = (bool)checkBoxGPXLog.IsChecked;
}
void _gpxAdd(double lat,double lon, int elevation)
{
DataRow dr = dtGPX.NewRow();
dr[0] = dtGPX.Rows.Count - 1;
dr[1] = lat;
dr[2] = lon;
dr[3] = elevation;
dr[4] = DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture); //2011-01-14T01:59:01Z
dtGPX.Rows.Add(dr);
}
 
void _saveGPXLog()
{
if (!Directory.Exists("GPXLog"))
Directory.CreateDirectory("GPXLog");
string SaveFileName = "GPXLog\\" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".gpx";
XmlTextWriter myXmlTextWriter = null;
myXmlTextWriter = new XmlTextWriter(SaveFileName, null);
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";
 
try
{
myXmlTextWriter.Formatting = Formatting.Indented;
 
myXmlTextWriter.WriteStartDocument();
 
myXmlTextWriter.WriteStartElement("gpx");
 
myXmlTextWriter.WriteAttributeString("version", "1.0");
myXmlTextWriter.WriteAttributeString("creator", "MKLiveView v1.0");
myXmlTextWriter.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
myXmlTextWriter.WriteAttributeString("xmlns", "http://www.topografix.com/GPX/1/1");
myXmlTextWriter.WriteAttributeString("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1/gpx.xsd");
 
myXmlTextWriter.WriteElementString("time", DateTime.UtcNow.ToString("u", System.Globalization.CultureInfo.InvariantCulture));
 
myXmlTextWriter.WriteStartElement("trk");
myXmlTextWriter.WriteStartElement("trkseg");
for(int i = 0; i< dtGPX.Rows.Count;i++)
{
myXmlTextWriter.WriteStartElement("trkpt");
myXmlTextWriter.WriteAttributeString("lat", dtGPX.Rows[i][1].ToString() != "" ? ((double)dtGPX.Rows[i][1]).ToString(nfi) : "");
myXmlTextWriter.WriteAttributeString("lon", dtGPX.Rows[i][2].ToString() != "" ? ((double)dtGPX.Rows[i][2]).ToString(nfi) : "");
myXmlTextWriter.WriteElementString("ele", dtGPX.Rows[i][3].ToString());
myXmlTextWriter.WriteElementString("time", dtGPX.Rows[i][4].ToString());
myXmlTextWriter.WriteEndElement();
}
myXmlTextWriter.WriteEndElement();
myXmlTextWriter.WriteEndElement();
myXmlTextWriter.WriteEndElement();
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.ToString());
}
finally
{
if (myXmlTextWriter != null)
{
myXmlTextWriter.Close();
}
}
}
 
private void btnLoadGPXLog_Click(object sender, RoutedEventArgs e)
{
_loadGPXLog();
}
private void btnClearRoute_Click(object sender, RoutedEventArgs e)
{
_clearMapMarkers(typeof(GMapRoute));
}
void _loadGPXLog()
{
 
Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
fd.Filter = "GPX-Logfile | *.gpx";
fd.Multiselect = false;
if (fd.ShowDialog().Value)
{
string file = fd.FileName;
try
{
XDocument gpxDoc = XDocument.Load(file);
XNamespace gpx = XNamespace.Get("http://www.topografix.com/GPX/1/1");
 
NumberFormatInfo nfi = new NumberFormatInfo();
nfi.NumberDecimalSeparator = ".";
 
var tracks = from track in gpxDoc.Descendants(gpx + "trk")
select new
{
Name = track.Element(gpx + "name") != null ? track.Element(gpx + "name").Value : null,
Segs = (
from trackpoint in track.Descendants(gpx + "trkpt")
select new
{
Latitude = trackpoint.Attribute("lat").Value,
Longitude = trackpoint.Attribute("lon").Value,
Elevation = trackpoint.Element(gpx + "ele") != null ?
trackpoint.Element(gpx + "ele").Value : null,
Time = trackpoint.Element(gpx + "time") != null ?
trackpoint.Element(gpx + "time").Value : null
}
)
};
 
List<PointLatLng> wpl = new List<PointLatLng>();
foreach(var trk in tracks)
{
foreach(var trkseg in trk.Segs)
{
if(trkseg.Latitude != "" && trkseg.Longitude !="")
wpl.Add(new PointLatLng(Convert.ToDouble(trkseg.Latitude, nfi), Convert.ToDouble(trkseg.Longitude, nfi)));
}
 
}
if(wpl.Count() > 0)
{
_clearMapMarkers(typeof(GMapRoute));
MapRoute mr = new MapRoute(wpl, "flying");
Dispatcher.Invoke(() =>
{
GMapRoute mRoute;
if (comboBoxRouteColor.SelectionBoxItem != null)
{
string s = comboBoxRouteColor.SelectionBoxItem.ToString();
mRoute = new GMapRoute(wpl, _getBrush(s));
}
else
mRoute = new GMapRoute(wpl, null);
 
MainMap.Markers.Add(mRoute);
});
}
 
}
catch (Exception e)
{
Console.WriteLine("Exception: {0}", e.ToString());
}
}
}
#endregion GPX
#endregion functions
}
 
/// <summary>
/// formats the wp datatable values for display in datagrid - this is bound in the datagrid as a converter
/// </summary>
public class waypointsConverter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value != null)
{
switch ((string)parameter)
{
case "Latitude":
return value.ToString() + " °";
case "Longitude":
return value.ToString() + " °";
case "Radius":
return value.ToString() + " m";
case "Altitude":
return value.ToString() + " m";
case "ClimbRate":
return value.ToString() == "255" ? "Auto" : (System.Convert.ToDouble(value) / 10).ToString("0.0 m/s");
case "DelayTime":
return value.ToString() + " s";
case "Heading":
return Waypoints.Heading(System.Convert.ToInt32(value));
case "Speed":
return Waypoints.WPSpeed(System.Convert.ToInt16(value));
case "CamAngle":
return Waypoints.CAMAngle(System.Convert.ToInt16(value));
case "Type":
return ((Waypoints.pointType)(System.Convert.ToInt16(value))).ToString();
case "AutoTrigger":
return value.ToString() == "0" ? "- - -" : value.ToString() + " m";
case "Status":
return (Waypoints.status)(System.Convert.ToInt16(value));
}
 
return value.ToString();
}
else return value;
}
 
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
public class IniFile
{
public string path;
 
[DllImport("kernel32")]
private static extern long WritePrivateProfileString(string section,
string key, string val, string filePath);
 
[DllImport("kernel32.dll", CharSet = CharSet.Auto)]
static extern uint GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer,
uint nSize, string lpFileName);
 
[DllImport("kernel32")]
private static extern int GetPrivateProfileString(string section,
string key, string def, StringBuilder retVal,
int size, string filePath);
 
public IniFile(string INIPath)
{
path = INIPath;
}
 
public void IniWriteValue(string Section, string Key, string Value)
{
WritePrivateProfileString(Section, Key, Value, this.path);
}
 
public string IniReadValue(string Section, string Key)
{
StringBuilder temp = new StringBuilder(255);
int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path);
return temp.ToString();
}
//Ini_sections auslesen in String-Array
public string[] IniSectionNames()
{
 
// uint MAX_BUFFER = 32767;
uint MAX_BUFFER = 8388608;
IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER);
uint bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, this.path);
if (bytesReturned == 0)
{
Marshal.FreeCoTaskMem(pReturnedString);
return null;
}
string local = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned).ToString();
Marshal.FreeCoTaskMem(pReturnedString);
//use of Substring below removes terminating null for split
return local.Substring(0, local.Length - 1).Split('\0');
 
 
}
}
/// <summary>
/// Selected Win AI Function Calls
/// </summary>
public class WinApi
{
[DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
public static extern int GetSystemMetrics(int which);
[DllImport("user32.dll")]
public static extern void
SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter,
int X, int Y, int width, int height, uint flags);
 
private const int SM_CXSCREEN = 0;
private const int SM_CYSCREEN = 1;
private static IntPtr HWND_TOP = IntPtr.Zero;
private const int SWP_SHOWWINDOW = 64; // 0x0040
 
public static int ScreenX
{
get { return GetSystemMetrics(SM_CXSCREEN); }
}
 
public static int ScreenY
{
get { return GetSystemMetrics(SM_CYSCREEN); }
}
 
public static void SetWinFullScreen(IntPtr hwnd)
{
SetWindowPos(hwnd, HWND_TOP, -8, -7, ScreenX+15, ScreenY+14, SWP_SHOWWINDOW);
}
}
/// <summary>
/// Class used to preserve / restore state of the window
/// </summary>
public class WinState
{
private WindowState winState;
private WindowStyle brdStyle;
private bool topMost;
private Rect restore;
private bool IsMaximized = false;
 
public bool isMaximized
{
get { return IsMaximized; }
}
public void Maximize(Window targetForm)
{
if (!IsMaximized)
{
IsMaximized = true;
Save(targetForm);
targetForm.WindowState = WindowState.Maximized;
targetForm.WindowStyle = WindowStyle.None;
targetForm.Topmost = true;
WinApi.SetWinFullScreen(new WindowInteropHelper(targetForm).Handle);
}
}
 
public void Save(Window targetForm)
{
winState = targetForm.WindowState;
brdStyle = targetForm.WindowStyle;
topMost = targetForm.Topmost;
restore = targetForm.RestoreBounds;
}
public void Restore(Window targetForm)
{
targetForm.WindowState = winState;
targetForm.WindowStyle = brdStyle;
targetForm.Topmost = topMost;
 
targetForm.Left = restore.Left;
targetForm.Top = restore.Top;
targetForm.Height = restore.Height;
targetForm.Width = restore.Width;
IsMaximized = false;
}
}
 
public static class BitmapConversion
{
public static System.Drawing.Bitmap ToWinFormsBitmap(this BitmapSource bitmapsource)
{
using (MemoryStream stream = new MemoryStream())
{
BitmapEncoder enc = new BmpBitmapEncoder();
enc.Frames.Add(BitmapFrame.Create(bitmapsource));
enc.Save(stream);
using (var tempBitmap = new System.Drawing.Bitmap(stream))
{
// According to MSDN, one "must keep the stream open for the lifetime of the Bitmap."
// So we return a copy of the new bitmap, allowing us to dispose both the bitmap and the stream.
return new System.Drawing.Bitmap(tempBitmap);
}
}
}
public static BitmapSource ToWpfBitmap(this System.Drawing.Bitmap bitmap)
{
using (MemoryStream stream = new MemoryStream())
{
bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); stream.Position = 0;
BitmapImage result = new BitmapImage();
result.BeginInit();
// According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."
// Force the bitmap to load right now so we can dispose the stream.
result.CacheOption = BitmapCacheOption.OnLoad;
result.StreamSource = stream;
result.EndInit();
result.Freeze();
return result;
}
}
}
 
}