Subversion Repositories Projects

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
2513 - 1
///============================================================================
2
/// MKLiveView 
3
/// Copyright © 2016 Steph
4
/// 
5
///This file is part of MKLiveView.
6
///
7
///MKLiveView is free software: you can redistribute it and/or modify
8
///it under the terms of the GNU General Public License as published by
9
///the Free Software Foundation, either version 3 of the License, or
10
///(at your option) any later version.
11
///
12
///MKLiveView is distributed in the hope that it will be useful,
13
///but WITHOUT ANY WARRANTY; without even the implied warranty of
14
///MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15
///GNU General Public License for more details.
16
///
17
///You should have received a copy of the GNU General Public License
18
///along with cssRcon.  If not, see <http://www.gnu.org/licenses/>.
19
///
20
///============================================================================
21
///Credits:
22
/// radioman (http://www.codeplex.com/site/users/view/radioman)
23
/// for his really GreatMaps! (http://greatmaps.codeplex.com/)
24
///
25
/// I made some changes to the source, so You need all files from this project here in order to compile and run
26
///
27
/// JOHN C. MACDONALD at Ira A. Fulton College of Engineering and Technology
28
/// for his MIKROKOPTER SERIAL CONTROL TUTORIAL (http://hdl.lib.byu.edu/1877/2747)
29
/// and the sourcecode (http://hdl.lib.byu.edu/1877/2748)
30
/// By his work I finally managed to get the communication with the Mikrokopter controllers to run
31
/// Some of his code was used in this programm like the SimpelSerialPort class (with lots of changes)
32
/// and the FilghtControllerMessage class
33
/// 
34
///============================================================================
35
/// DISCLAIMER
36
/// ===========
37
/// 
38
/// I created this software with my best knowledge and belief.
39
/// 
40
/// IN NO EVENT, UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING, 
41
/// SHALL I, OR ANY PERSON BE LIABLE FOR ANY LOSS, EXPENSE OR DAMAGE, 
42
/// OF ANY TYPE OR NATURE ARISING OUT OF THE USE OF, 
43
/// OR INABILITY TO USE THIS SOFTWARE OR PROGRAM, 
44
/// INCLUDING, BUT NOT LIMITED TO, CLAIMS, SUITS OR CAUSES OF ACTION 
45
/// INVOLVING ALLEGED INFRINGEMENT OF COPYRIGHTS, 
46
/// PATENTS, TRADEMARKS, TRADE SECRETS, OR UNFAIR COMPETITION.
47
/// 
48
/// This means: use it & have fun (but @ Your own risk...)
49
/// ===========================================================================
50
using GMap.NET;
51
using GMap.NET.MapProviders;
52
using GMap.NET.WindowsPresentation;
53
using MKLiveView.GMapCustomMarkers;
54
using System;
55
using System.Collections.Generic;
56
using System.ComponentModel;
57
using System.Data;
58
using System.Diagnostics;
59
using System.IO;
60
using System.Linq;
61
using System.Linq.Expressions;
62
using System.Runtime.InteropServices;
63
using System.Text;
64
using System.Threading;
65
using System.Threading.Tasks;
66
using System.Windows;
67
using System.Windows.Controls;
68
using System.Windows.Data;
69
using System.Windows.Documents;
70
using System.Windows.Input;
71
using System.Windows.Interop;
72
using System.Windows.Media;
73
using System.Windows.Media.Animation;
74
using System.Windows.Media.Imaging;
75
using System.Windows.Navigation;
76
using System.Windows.Shapes;
77
using System.Windows.Threading;
78
using System.Globalization;
79
using System.Xml;
80
using System.Xml.Linq;
81
using Touchless.Vision.Camera;
82
 
83
namespace MKLiveView
84
{
85
    /// <summary>
86
    /// Interaktionslogik für MainWindow.xaml
87
    /// </summary>
88
    public partial class MainWindow : Window
89
    {
90
        #region declarations
91
        object lockObj = new Object();
92
        MediaPlayer.MediaPlayer mediaPlayer = new MediaPlayer.MediaPlayer();
93
 
94
        GMapMarker copter;
95
        GMapMarker home;
96
        PointLatLng start;
97
        PointLatLng end;
98
        PointLatLng pHome;
99
        GMapRoute mRouteWP;
100
        GMapMarker wpActiveMarker;
101
        List<PointLatLng> wpList = new List<PointLatLng>();
102
        List<int> wpOffset = new List<int>();
103
        Circle cWPBound = new Circle();
104
        double dWPMaxRange = 0;
105
 
106
        #region NC-Errors
107
        String[] NC_Error = new string[44]
108
        {
109
            "No Error",
110
            "FC not compatible",
111
            "MK3Mag not compatible",
112
            "no FC communication",
113
            "no compass communication",
114
            "no GPS communication",
115
            "bad compass value",
116
            "RC Signal lost",
117
            "FC spi rx error",
118
            "ERR: no NC communication",
119
            "ERR: FC Nick Gyro",
120
            "ERR: FC Roll Gyro",
121
            "ERR: FC Yaw Gyro",
122
            "ERR: FC Nick ACC",
123
            "ERR: FC Roll ACC",
124
            "ERR: FC Z-ACC",
125
            "ERR: Pressure sensor",
126
            "ERR: FC I2C",
127
            "ERR: Bl Missing",
128
            "Mixer Error",
129
            "FC: Carefree Error",
130
            "ERR: GPS lost",
131
            "ERR: Magnet Error",
132
            "Motor restart",
133
            "BL Limitation",
134
            "Waypoint range",
135
            "ERR:No SD-Card",
136
            "ERR:SD Logging aborted",
137
            "ERR:Flying range!",
138
            "ERR:Max Altitude",
139
            "No GPS Fix",
140
            "compass not calibrated",
141
            "ERR:BL selftest",
142
            "no ext. compass",
143
            "compass sensor",
144
            "FAILSAFE pos.!",
145
            "ERR:Redundancy",
146
            "Redundancy test",
147
            "GPS Update rate",
148
            "ERR:Canbus",
149
            "ERR: 5V RC-Supply",
150
            "ERR:Power-Supply",
151
            "ACC not calibr.",
152
            "ERR:Parachute!"
153
        };
154
        String[] NC_Error_Link = new string[44]
155
        {
156
            "",
157
            "http://wiki.mikrokopter.de/ErrorCodes#A1_.22FC_not_compatible_.22",
158
            "http://wiki.mikrokopter.de/ErrorCodes#A2_.22MK3Mag_not_compatible_.22",
159
            "http://wiki.mikrokopter.de/ErrorCodes#A3_.22no_FC_communication_.22",
160
            "http://wiki.mikrokopter.de/ErrorCodes#A4_.22no_compass_communication_.22",
161
            "http://wiki.mikrokopter.de/ErrorCodes#A5_.22no_GPS_communication_.22",
162
            "http://wiki.mikrokopter.de/ErrorCodes#A6_.22bad_compass_value.22",
163
            "http://wiki.mikrokopter.de/ErrorCodes#A7_.22RC_Signal_lost_.22",
164
            "http://wiki.mikrokopter.de/ErrorCodes#A8_.22FC_spi_rx_error_.22",
165
            "http://wiki.mikrokopter.de/ErrorCodes#A9:_.22ERR:_no_NC_communication.22",
166
            "http://wiki.mikrokopter.de/ErrorCodes#A10_.22ERR:_FC_Nick_Gyro.22",
167
            "http://wiki.mikrokopter.de/ErrorCodes#A11_.22ERR:_FC_Roll_Gyro.22",
168
            "http://wiki.mikrokopter.de/ErrorCodes#A12_.22ERR:_FC_Yaw_Gyro.22",
169
            "http://wiki.mikrokopter.de/ErrorCodes#A13_.22ERR:_FC_Nick_ACC.22",
170
            "http://wiki.mikrokopter.de/ErrorCodes#A14_.22ERR:_FC_Roll_ACC.22",
171
            "http://wiki.mikrokopter.de/ErrorCodes#A15_.22ERR:_FC_Z-ACC.22",
172
            "http://wiki.mikrokopter.de/ErrorCodes#A16_.22ERR:_Pressure_sensor.22",
173
            "http://wiki.mikrokopter.de/ErrorCodes#A17_.22ERR:_FC_I2C.22",
174
            "http://wiki.mikrokopter.de/ErrorCodes#A18_.22ERR:_Bl_Missing.22",
175
            "http://wiki.mikrokopter.de/ErrorCodes#A19_.22Mixer_Error.22",
176
            "http://wiki.mikrokopter.de/ErrorCodes#A20_.22FC:_Carefree_Error.22",
177
            "http://wiki.mikrokopter.de/ErrorCodes#A21_.22ERR:_GPS_lost.22",
178
            "http://wiki.mikrokopter.de/ErrorCodes#A22_.22ERR:_Magnet_Error.22",
179
            "http://wiki.mikrokopter.de/ErrorCodes#A23_.22Motor_restart.22",
180
            "http://wiki.mikrokopter.de/ErrorCodes#A24_.22BL_Limitation.22",
181
            "http://wiki.mikrokopter.de/ErrorCodes#A25_.22Waypoint_range.22",
182
            "http://wiki.mikrokopter.de/ErrorCodes#A26_.22ERR:No_SD-Card.22",
183
            "http://wiki.mikrokopter.de/ErrorCodes#A27_.22ERR:SD_Logging_aborted.22",
184
            "http://wiki.mikrokopter.de/ErrorCodes#A28_.22ERR:Flying_range.21.22",
185
            "http://wiki.mikrokopter.de/ErrorCodes#A29_.22ERR:Max_Altitude.22",
186
            "http://wiki.mikrokopter.de/ErrorCodes#A30_.22No_GPS_Fix.22",
187
            "http://wiki.mikrokopter.de/ErrorCodes#A31_.22compass_not_calibrated.22",
188
            "http://wiki.mikrokopter.de/ErrorCodes#A32_.22ERR:BL_selftest.22",
189
            "http://wiki.mikrokopter.de/ErrorCodes#A33_.22no_ext._compass.22",
190
            "http://wiki.mikrokopter.de/ErrorCodes#A34_.22compass_sensor.22",
191
            "http://wiki.mikrokopter.de/ErrorCodes#A35_.22FAILSAFE_pos..21__.22",
192
            "http://wiki.mikrokopter.de/ErrorCodes#A36_.22ERR:Redundancy__.22",
193
            "http://wiki.mikrokopter.de/ErrorCodes#A37_.22Redundancy_test_.22",
194
            "http://wiki.mikrokopter.de/ErrorCodes#A38_.22GPS_Update_rate.22",
195
            "http://wiki.mikrokopter.de/ErrorCodes#A39_.22ERR:Canbus.22",
196
            "http://wiki.mikrokopter.de/ErrorCodes#A40_.22ERR:_5V_RC-Supply.22",
197
            "http://wiki.mikrokopter.de/ErrorCodes#A41_.22ERR:Power-Supply.22",
198
            "http://wiki.mikrokopter.de/ErrorCodes#A42_.22ACC_not_calibr..22",
199
            "http://wiki.mikrokopter.de/ErrorCodes#A43_.22ERR:Parachute.21.22"
200
        };
201
 
202
        #endregion NC-Errors
203
        [FlagsAttribute]
204
        enum NC_HWError0 : short
205
        {
206
            None = 0,
207
            SPI_RX = 1,
208
            COMPASS_RX = 2,
209
            FC_INCOMPATIBLE = 4,
210
            COMPASS_INCOMPATIBLE = 8,
211
            GPS_RX = 16,
212
            COMPASS_VALUE = 32
213
        };
214
        [FlagsAttribute]
215
        enum FC_HWError0 : short
216
        {
217
            None = 0,
218
            GYRO_NICK = 1,
219
            GYRO_ROLL = 2,
220
            GYRO_YAW = 4,
221
            ACC_NICK = 8,
222
            ACC_ROLL = 16,
223
            ACC_TOP = 32,
224
            PRESSURE = 64,
225
            CAREFREE = 128
226
        };
227
        [FlagsAttribute]
228
        enum FC_HWError1 : short
229
        {
230
            None = 0,
231
            I2C = 1,
232
            BL_MISSING = 2,
233
            SPI_RX = 4,
234
            PPM = 8,
235
            MIXER = 16,
236
            RC_VOLTAGE = 32,
237
            ACC_NOT_CAL = 64,
238
            RES3 = 128
239
        };
240
        public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error };
241
        // Various colors for logging info
242
        private Color[] LogMsgTypeColor = { Color.FromArgb(255, 43, 145, 175), Colors.Green, Colors.Black, Colors.Orange, Colors.Red };
243
 
244
        bool _bCBInit = true;
245
        bool _init = true;
246
        bool check_HWError = false;
247
 
248
        string filePath = Directory.GetCurrentDirectory();
249
        bool bReadContinously = false;
250
        bool _debugDataAutorefresh = true;
251
        bool _navCtrlDataAutorefresh = true;
252
        bool _blctrlDataAutorefresh = true;
253
        bool _OSDAutorefresh = true;
254
        bool _bErrorLog = false;
255
        bool _bConnErr = false;
256
        bool _bFollowCopter = false;
257
        bool _bGPXLog = false;
258
        bool _Simulate = false;
259
 
260
        bool _bSaveWinStateNormal = true;
261
        bool _bSaveWinStateFull = true;
262
 
263
        double scaleNormalAll = 1;
264
        double scaleNormalTopBar = 1;
265
        double scaleNormalMotors = 1;
266
        double scaleNormalOSD = 1;
267
        double scaleNormalLOG = 1;
268
        double scaleNormalHorizon = 1;
269
 
270
        double scaleFullAll = 1;
271
        double scaleFullTopBar = 1;
272
        double scaleFullMotors = 1;
273
        double scaleFullOSD = 1;
274
        double scaleFullLOG = 1;
275
        double scaleFullHorizon = 1;
276
 
277
        int _iCtrlAct = 0;
278
        int iOSDPage = 0;
279
        int iOSDMax = 0;
280
        int _iLifeCounter = 0;
281
        int crcError = 0;
282
 
283
        bool _bSatFix = false;
284
        Storyboard stbSatFixLostAnim;
285
        bool _bAnimSatFixActive = false;
286
        bool _bVoiceSatFixActive = false;
287
        bool _bVoiceSatFixPlay = false;
288
        int _iSatsLast = 0;
289
        int _iSatsJitter = 0;
290
 
291
        bool _bMagneticFieldOK = false;
292
        Storyboard stbMagneticFieldAnim;
293
        bool _bAnimMagneticFieldActive = false;
294
        bool _bVoiceMagneticFieldActive = false;
295
        bool _bVoiceMagneticFieldPlay = false;
296
        int _iMagneticFieldLast = 0;
297
        int _iMagneticFieldJitter = 0;
298
 
299
        bool _bRCLevelOK = false;
300
        Storyboard stbRCLevelAnim;
301
        bool _bAnimRCLevelActive = false;
302
        bool _bVoiceRCLevelActive = false;
303
        bool _bVoiceRCLevelPlay = false;
304
        int _iRCLevelLast = 0;
305
        int _iRCLevelJitter = 0;
306
 
307
        int _iMotors = 4;
308
        int _LipoCells = 3;
309
        bool _bLiPoAutoDetect = false;
310
 
311
        double _dLipoVMax = 16.88;
312
        double _dLipoVMin = 12;
313
        double _dThresholdVoltageWarn = 0;
314
        double _dThresholdVoltageCrit = 0;
315
        Storyboard stbVoltageCritAnim;
316
        bool _bCritAnimVoltActive = false;
317
        bool _bCritVoiceVoltActive = false;
318
        bool _bWarnVoiceVoltActive = false;
319
        bool _bVoiceVoltPlay = false;
320
        double _dVoltLast = 0;
321
        int _iVoltJitter = 0;
322
 
323
        double _dThresholdDistanceWarn = 100;
324
        Storyboard stbDistanceWarnAnim;
325
        bool _bAnimDistanceActive = false;
326
        bool _bVoiceDistanceActive = false;
327
        bool _bVoiceDistancePlay = false;
328
        double _dDistanceLast = 0;
329
        int _iDistanceJitter = 0;
330
 
331
        double _dThresholdDistanceMax = 1000;
332
        int _iThresholdRC = 160;
333
        int _iThresholdMagField = 15;
334
 
335
        bool _bAutoHome = false;
336
        bool _bFirstSatFix = false;
337
        int _iFirstSatFix = 0;
338
 
339
        double _dTopHeight = 36;
340
 
341
        int[] serChan = new int[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
342
        int[] serChan_sub = new int[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
343
        string[] serChanTitle = new string[12];
344
 
345
        string[] sAnalogLabel = new string[32];
346
        string[] sAnalogData = new string[32];
347
        int[] iAnalogData = new int[32];
348
 
349
        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 };
350
        int[] iMotors = new int[] { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12 };
351
        string[] sLiPoCells = new string[] { "3s", "4s", "5s", "6s" };
352
        /// <summary>
353
        /// interval for sending debugdata (multiplied by 10ms)
354
        /// </summary>
355
        byte debugInterval = 10; //(=> 100ms)
356
        /// <summary>
357
        /// interval for sending BL-CTRL status (multiplied by 10ms)
358
        /// </summary>
359
        byte blctrlInterval = 75;
360
        /// <summary>
361
        /// interval for sending NAV-CTRL status (multiplied by 10ms)
362
        /// </summary>
363
        byte navctrlInterval = 20;
364
        /// <summary>
365
        /// interval for sending OSD page update (multiplied by 10ms)
366
        /// </summary>
367
        byte OSDInterval = 85;
368
        /// <summary>
369
        /// datatable for the debug data array - displayed on settings tabpage in datagridview
370
        /// </summary>
371
        DataTable dtAnalog = new DataTable();
372
        /// <summary>
373
        /// datatable for motordata (current,temp)
374
        /// </summary>
375
        DataTable dtMotors = new DataTable();
376
 
377
        DataTable dtWaypoints = new DataTable();
378
        static volatile int _iWPCount = -1;
379
        static volatile int _iWPIndex = -1;
380
        int _iWPTimeout = 1000;
381
        bool _bGetWP = false;
382
        bool _bShowWPRoute = false;
383
        bool _bAutoWPEdit = true;
384
        static volatile bool _bGetWPCount = false;
385
        DataTable dtGPX = new DataTable();
386
        DataRow drGPX;
387
        bool _bAirborne = false;
388
        int _wpIndex = -1, _wpCount = 0, _wpEdit = -1;
389
 
390
        string _wpDefPrefix = "P";
391
        int _wpDefAltitude = 20;
392
        int _wpDefHeading = 0;
393
        int _wpDefCBoxHeading = 0;
394
        int _wpDefSpeed = 10;
395
        int _wpDefCBoxSpeed = 0;
396
        int _wpDefClimb = 10;
397
        int _wpDefCBoxClimb = 0;
398
        int _wpDefRadius = 5;
399
        int _wpDefHoldtime = 5;
400
        int _wpDefAutotrig = 0;
401
        int _wpDefCamangle = 0;
402
        int _wpDefCBoxCamangle = 0;
403
        int _wpDefOut1 = 0;
404
 
405
        bool _wpAddCopterHeight = true;
406
        bool _wpAddCopterHeading = true;
407
 
408
        DispatcherTimer timer = new DispatcherTimer();
409
        DispatcherTimer camTimer = new DispatcherTimer();
410
        BitmapSource _camImageSource;
411
        Storyboard stbCamActiveAnim;
412
        bool _bCamAnim;
413
        /// <summary>
414
        /// stuff for enabeling touch zoom for the map
415
        /// </summary>
416
        Point pTouch1 = new Point(0, 0), pTouch2 = new Point(0, 0);
417
        int iFirstStylusID = -1;
418
 
419
        public string connectButtonText
420
        {
421
            get
422
            {
423
                return bReadContinously ? "stop polling data" + System.Environment.NewLine + "from copter" : "start polling data" + System.Environment.NewLine + "from copter";
424
            }
425
        }
426
 
427
        WinState winState = new WinState();
428
 
429
        #endregion declarations
430
        public MainWindow()
431
        {
432
            String path = Environment.ExpandEnvironmentVariables("%SystemRoot%") + "\\System32\\VCRUNTIME140.DLL";
433
            if (!File.Exists(path))
434
            {
435
                MessageBoxResult dr = MessageBox.Show("Visual C++ Redistributable for Visual Studio 2015 seems not to be installed..." +
436
                    Environment.NewLine + "Please download the file for x86 (32bit) @ https://www.microsoft.com/de-de/download/details.aspx?id=48145" +
437
                    Environment.NewLine + Environment.NewLine + "Do You want me to take You there?", "Visual C++ Redistributable for Visual Studio 2015 missing ...",
438
                    MessageBoxButton.YesNo,
439
                    MessageBoxImage.Stop,MessageBoxResult.No, MessageBoxOptions.DefaultDesktopOnly);
440
 
441
                if (dr == MessageBoxResult.Yes)
442
                    System.Diagnostics.Process.Start("https://www.microsoft.com/de-de/download/details.aspx?id=48145");
443
 
444
                Application.Current.Shutdown();
445
            }
446
            InitializeComponent();
447
            _initForm();
448
            _dataTablesInit();
449
            _setupMap();
450
            _init = false;
451
            timer.Tick += new EventHandler(timerEvent);
452
            timer.Interval = new TimeSpan(0, 0, 1);
453
            timer.Start();
454
            camTimer.Tick += new EventHandler(camTimer_Tick);
455
            camTimer.Interval = new TimeSpan(0, 0, 0, 0, 5);
456
          //  camTimer.Start();
457
        }
458
 
459
        #region init
460
        void _initForm()
461
        {
462
            _readIni();
463
            if (_bSaveWinStateNormal)
464
                _setScaleSliders(false);
465
            cBoxTimingsDebug.ItemsSource =
466
                cBoxTimingsNav.ItemsSource =
467
                cBoxTimingsBl.ItemsSource =
468
                cBoxTimingsOSD.ItemsSource =
469
                iTimings;
470
            cBoxLiPoCells.ItemsSource = sLiPoCells;
471
            cBoxLiPoCells.SelectedItem = _LipoCells.ToString() + "s";
472
            _LipoMinMax();
473
            sliderThresholdVoltageWarn.Value = _dThresholdVoltageWarn;
474
            sliderThresholdVoltageCrit.Value = _dThresholdVoltageCrit;
475
            checkBoxThresholdVoltageVoice.IsChecked = _bVoiceVoltPlay;
476
            checkBoxSatfixLost.IsChecked = _bVoiceSatFixPlay;
477
            checkBoxMagneticField.IsChecked = _bVoiceMagneticFieldPlay;
478
            checkBoxThresholdDistanceVoice.IsChecked = _bVoiceDistancePlay;
479
            sliderThresholdDistanceWarn.Value = _dThresholdDistanceWarn;
480
            checkBoxRClevel.IsChecked = _bVoiceRCLevelPlay;
481
 
482
            sliderThresholdDistanceWarn.Maximum = _dThresholdDistanceMax;
483
 
484
            cBoxMotors.ItemsSource = iMotors;
485
            cBoxMotors.SelectedItem = _iMotors;
486
 
487
            serialPortCtrl.PortClosed += serialPortCtrl_PortClosed;
488
            serialPortCtrl.PortOpened += serialPortCtrl_PortOpened;
489
            serialPortCtrl.DataReceived += processMessage;
490
 
491
            chkbAutoBL.IsChecked = _blctrlDataAutorefresh;
492
            chkbAutoDbg.IsChecked = _debugDataAutorefresh;
493
            chkbAutoNav.IsChecked = _navCtrlDataAutorefresh;
494
            chkbAutoOSD.IsChecked = _OSDAutorefresh;
495
            chkbAutoLiPoDetect.IsChecked = _bLiPoAutoDetect;
496
 
497
            cBoxTimingsDebug.SelectedItem = debugInterval * 10;
498
            cBoxTimingsNav.SelectedItem = navctrlInterval * 10;
499
            cBoxTimingsBl.SelectedItem = blctrlInterval * 10;
500
            cBoxTimingsOSD.SelectedItem = OSDInterval * 10;
501
            checkBoxAutoSetHP.IsChecked = _bAutoHome;
502
            checkBoxFollowCopter.IsChecked = _bFollowCopter;
503
            checkBoxGPXLog.IsChecked = _bGPXLog;
504
            checkBoxShowWPRoute.IsChecked = _bShowWPRoute;
505
            checkBoxAutoShowWPEdit.IsChecked = _bAutoWPEdit;
506
            checkBoxWPAddUseCopterHeight.IsChecked = _wpAddCopterHeight;
507
            checkBoxWPAddUseCopterHeading.IsChecked = _wpAddCopterHeading;
508
            GridSettings.Visibility = Visibility.Visible;
509
            GridCam.Visibility = GridData.Visibility = GridWP.Visibility = GridWPEdit.Visibility = Visibility.Collapsed;
510
            _initSerialCtrl();
511
        }
512
        /// <summary>
513
        /// initialize the datatables
514
        /// with columnnames etc
515
        /// </summary>
516
        void _dataTablesInit()
517
        {
518
            dtMotors.Columns.Add("#");
519
            if (Thread.CurrentThread.CurrentUICulture.Name == "de-DE")
520
                dtMotors.Columns.Add("Strom");
521
            else
522
                dtMotors.Columns.Add("Current");
523
            dtMotors.Columns.Add("Temp");
524
            dgvMotors1.DataContext = dtMotors.DefaultView;
525
            _initDTMotors();
526
 
527
            Setter setter = new Setter(ContentControl.PaddingProperty, new Thickness(5, 0, 5, 0));
528
            Style style = new Style(typeof(System.Windows.Controls.Primitives.DataGridColumnHeader));
529
            style.Setters.Add(setter);
530
            setter = new Setter(ContentControl.BackgroundProperty, new SolidColorBrush(Colors.Transparent));
531
            style.Setters.Add(setter);
532
            setter = new Setter(ContentControl.ForegroundProperty, new SolidColorBrush(Colors.White));
533
            style.Setters.Add(setter);
534
 
535
            dtWaypoints.Columns.Add("Index", typeof(int));
536
            dtWaypoints.Columns.Add("Type", typeof(int));
537
            dtWaypoints.Columns.Add("Name", typeof(string));
538
            dtWaypoints.Columns.Add("Latitude", typeof(double));
539
            dtWaypoints.Columns.Add("Longitude", typeof(double));
540
            dtWaypoints.Columns.Add("Altitude", typeof(string));
541
            dtWaypoints.Columns.Add("Heading", typeof(string));
542
            dtWaypoints.Columns.Add("Speed", typeof(string));
543
            dtWaypoints.Columns.Add("ClimbRate", typeof(string));
544
            dtWaypoints.Columns.Add("Radius", typeof(string));
545
            dtWaypoints.Columns.Add("HoldTime", typeof(string));
546
            dtWaypoints.Columns.Add("AutoTrigger", typeof(string));
547
            dtWaypoints.Columns.Add("CamAngle", typeof(string));
548
            dtWaypoints.Columns.Add("Event", typeof(string));
549
            dtWaypoints.Columns.Add("Out1Timer", typeof(string));
550
            dtWaypoints.Columns.Add("Status", typeof(string));
551
            dtWaypoints.PrimaryKey = new DataColumn[] { dtWaypoints.Columns["Index"] };
552
            dgvWP.ItemsSource = dtWaypoints.DefaultView;
553
            dgvWP.ColumnHeaderStyle = new Style();
554
            dgvWP.ColumnHeaderStyle = style;
555
 
556
            dtGPX.Columns.Add("Index", typeof(int));
557
            dtGPX.Columns.Add("Latitude", typeof(double));
558
            dtGPX.Columns.Add("Longitude", typeof(double));
559
            dtGPX.Columns.Add("Elevation", typeof(int));
560
            dtGPX.Columns.Add("Time", typeof(string));
561
            dtGPX.PrimaryKey = new DataColumn[] { dtGPX.Columns["Index"] };
562
            drGPX = dtGPX.NewRow();
563
 
564
        }
565
        /// <summary>
566
        /// initialize the datatable dtMotors for motor values
567
        /// DataGridView dgvMotors1 is bound to dtMotors1
568
        /// </summary>
569
        void _initDTMotors()
570
        {
571
            for (int i = 0; i < 12; i++)
572
            {
573
                if (dtMotors.Rows.Count < 12)
574
                    dtMotors.Rows.Add((i + 1).ToString(), "NA", "NA");
575
                else
576
                {
577
                    dtMotors.Rows[i].SetField(1, "NA");
578
                    dtMotors.Rows[i].SetField(2, "NA");
579
                }
580
            }
581
        }
582
 
583
        #endregion init
584
 
585
        #region events
586
        private void serialPortCtrl_PortOpened()
587
        {
588
            Dispatcher.Invoke(() => imageWiFi.Source = new BitmapImage(new Uri("Images/WiFi_G.png", UriKind.Relative)));
589
            _getVersion();
590
            Thread.Sleep(100);
591
            _getLic();
592
            //_OSDMenue(0);
593
            //Thread.Sleep(200);
594
            //_sendSerialData();
595
            _readCont(true);
596
        }
597
        private void serialPortCtrl_PortClosed()
598
        {
599
            Dispatcher.Invoke(() => imageWiFi.Source = new BitmapImage(new Uri("Images/WiFi_W.png", UriKind.Relative)));
600
            _readCont(false);
601
        }
602
        bool _bToggle = false;
603
        void timerEvent(object sender, EventArgs e)
604
        {
605
            if (bReadContinously)
606
            {
607
                if (_debugDataAutorefresh) { _readDebugData(true); Thread.Sleep(10); }
608
 
609
                if (_blctrlDataAutorefresh) { _readBLCtrl(true); Thread.Sleep(10); }
610
 
611
                if (_navCtrlDataAutorefresh && _iCtrlAct == 2) { _readNavData(true); Thread.Sleep(10); }
612
                check_HWError = true;
613
                _getVersion();
614
                Thread.Sleep(10);
615
                if (_OSDAutorefresh)
616
                {
617
                    if (iOSDMax == 0 | cbOSD.Items.Count != iOSDMax)
618
                        _initOSDCB();
619
                    _OSDMenueAutoRefresh();
620
                }
621
                if (_iLifeCounter > 0)
622
                {
623
                    Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_G.png", UriKind.Relative)));
624
                    //  Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGreen));
625
                    _iLifeCounter = 0;
626
                    _bConnErr = false;
627
                    if (_bAirborne && _bGPXLog)
628
                    {
629
                        drGPX[0] = dtGPX.Rows.Count;
630
                        dtGPX.Rows.Add(new object[] { drGPX[0], drGPX[1], drGPX[2], drGPX[3], drGPX[4] });
631
                    }
632
                    Dispatcher.Invoke((Action)(() => tbSideBarGPXLog.Background = (_bAirborne && _bGPXLog && _bToggle) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));
633
                    Dispatcher.Invoke((Action)(() => tbSideBarGPXLog.Foreground = (_bAirborne && _bGPXLog) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));
634
                    Dispatcher.Invoke((Action)(() => tbSideBarGPXLog.BorderBrush = (_bAirborne && _bGPXLog) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));
635
                    _bToggle = !_bToggle;
636
                }
637
                else
638
                {
639
                    if (!_bConnErr)
640
                    {
641
                        Log(LogMsgType.Error, "No communication to NC/FC!");
642
                        Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_R.png", UriKind.Relative)));
643
                        // Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.Red));
644
                        _bConnErr = true;
645
                    }
646
                }
647
            }
648
        }
649
        private void camTimer_Tick(object sender, EventArgs e)
650
        {
651
            if (_camImageSource != null && _frameSource != null && _camImage.Visibility == Visibility.Visible)
652
                _camImage.Source = _camImageSource;
653
            camTimer.IsEnabled = false;
654
        }
655
 
656
        #region menues
657
        private void labelData_MouseDown(object sender, MouseButtonEventArgs e)
658
        {
659
            GridData.Visibility = GridData.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
660
            GridSettings.Visibility = GridWP.Visibility = Visibility.Collapsed;
661
        }
662
        private void labelMotorData_MouseDown(object sender, MouseButtonEventArgs e)
663
        {
664
            GridMotors.Visibility = GridMotors.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
665
            if (GridMotors.IsVisible)
666
                _setMotorGridSize();
667
        }
668
        private void labelSettings_MouseDown(object sender, MouseButtonEventArgs e)
669
        {
670
            GridData.Visibility = GridWP.Visibility = Visibility.Collapsed;
671
            GridSettings.Visibility = GridSettings.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
672
        }
673
        private void labelLog_MouseDown(object sender, MouseButtonEventArgs e)
674
        {
675
            GridLog.Visibility = GridLog.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
676
        }
677
        private void labelOSD_MouseDown(object sender, MouseButtonEventArgs e)
678
        {
679
            GridOSD.Visibility = GridOSD.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
680
        }
681
        private void labelWaypoints_MouseDown(object sender, MouseButtonEventArgs e)
682
        {
683
            GridData.Visibility = GridSettings.Visibility = Visibility.Collapsed;
684
            GridWP.Visibility = GridWP.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
685
        }
686
        private void labelWPEdit_MouseDown(object sender, MouseButtonEventArgs e)
687
        {
688
            GridWPEdit.Visibility = GridWPEdit.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
689
        }
690
        private void labelCamera_MouseDown(object sender, MouseButtonEventArgs e)
691
        {
692
            GridCam.Visibility = GridCam.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
693
        }
694
        #endregion menues
695
 
696
        private void btnGetWP_Click(object sender, RoutedEventArgs e)
697
        {
698
            Thread t = new Thread(new ThreadStart(_getWP));
699
            t.Start();
700
        }
701
        private void btnSendWPList_Click(object sender, RoutedEventArgs e)
702
        {
703
            Thread t = new Thread(new ThreadStart(_sendWPList));
704
            t.Start();
705
        }
706
        private void btnConnectToCopter_Click(object sender, RoutedEventArgs e)
707
        {
708
            if (!serialPortCtrl.Port.IsOpen)
709
                serialPortCtrl.Connect(true);
710
            else
711
                _readCont(!bReadContinously);
712
        }
713
        private void btnSetHP_Click(object sender, RoutedEventArgs e)
714
        {
715
            _setHomePos();
716
        }
717
        private void btnClearHP_Click(object sender, RoutedEventArgs e)
718
        {
719
            _clearHomePos();
720
        }
721
        private void btnGotoHP_Click(object sender, RoutedEventArgs e)
722
        {
723
            if (home != null && MainMap.Markers.Contains(home))
724
                MainMap.Position = home.Position;
725
        }
726
        private void checkBoxAutoSetHP_Click(object sender, RoutedEventArgs e)
727
        {
728
            _bAutoHome = (bool)checkBoxAutoSetHP.IsChecked;
729
        }
730
        private void chkBoxSaveNormalState_Click(object sender, RoutedEventArgs e)
731
        {
732
            _bSaveWinStateNormal = (bool)chkBoxSaveNormalState.IsChecked;
733
        }
734
        private void chkBoxSaveFullScreenState_Click(object sender, RoutedEventArgs e)
735
        {
736
            _bSaveWinStateFull = (bool)chkBoxSaveFullScreenState.IsChecked;
737
        }
738
 
739
        #region thresholds
740
        private void sliderThresholdVoltageWarn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
741
        {
742
            if (!_init)
743
            {
744
                _dThresholdVoltageWarn = sliderThresholdVoltageWarn.Value;
745
                _dThresholdVoltageCrit = sliderThresholdVoltageCrit.Value;
746
            }
747
        }
748
        private void sliderThresholdVoltageCrit_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
749
        {
750
            if (!_init)
751
                _dThresholdVoltageCrit = sliderThresholdVoltageCrit.Value;
752
        }
753
        private void checkBoxThresholdVoltageVoice_Click(object sender, RoutedEventArgs e)
754
        {
755
            _bVoiceVoltPlay = (bool)checkBoxThresholdVoltageVoice.IsChecked;
756
        }
757
 
758
        private void sliderThresholdDistanceWarn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
759
        {
760
            if (!_init)
761
                _dThresholdDistanceWarn = sliderThresholdDistanceWarn.Value;
762
        }
763
        private void checkBoxThresholdDistanceVoice_Click(object sender, RoutedEventArgs e)
764
        {
765
            _bVoiceDistancePlay = (bool)checkBoxThresholdDistanceVoice.IsChecked;
766
        }
767
 
768
        private void checkBoxSatfixLost_Click(object sender, RoutedEventArgs e)
769
        {
770
            _bVoiceSatFixPlay = (bool)checkBoxSatfixLost.IsChecked;
771
        }
772
        private void checkBoxMagneticField_Click(object sender, RoutedEventArgs e)
773
        {
774
            _bVoiceMagneticFieldPlay = (bool)checkBoxMagneticField.IsChecked;
775
        }
776
        private void checkBoxRClevel_Click(object sender, RoutedEventArgs e)
777
        {
778
            _bVoiceRCLevelPlay = (bool)checkBoxRClevel.IsChecked;
779
        }
780
        #endregion thresholds
781
 
782
        private void buttonSwitchNC_Click(object sender, RoutedEventArgs e)
783
        {
784
            _switchToNC();
785
        }
786
 
787
        private void Window_Loaded(object sender, RoutedEventArgs e)
788
        {
789
            stbVoltageCritAnim = TryFindResource("VoltageCritAnim") as Storyboard;
790
            stbSatFixLostAnim = TryFindResource("SatFixLostAnim") as Storyboard;
791
            stbMagneticFieldAnim = TryFindResource("MagneticFieldCritAnim") as Storyboard;
792
            stbDistanceWarnAnim = TryFindResource("DistanceCritAnim") as Storyboard;
793
            stbRCLevelAnim = TryFindResource("RCCritAnim") as Storyboard;
794
            stbCamActiveAnim = TryFindResource("CamActiveAnim") as Storyboard;
795
            _setMotorGridSize();
796
            // Refresh the list of available cameras
797
            comboBoxCameras.Items.Clear();
798
 
799
            foreach (Camera cam in CameraService.AvailableCameras)
800
                comboBoxCameras.Items.Add(cam);
801
 
802
            if (comboBoxCameras.Items.Count > 0)
803
                comboBoxCameras.SelectedIndex = 0;
804
        }
805
        private void Window_Closing(object sender, CancelEventArgs e)
806
        {
807
            _writeIni();
808
            if (_bGPXLog && dtGPX.Rows.Count > 0)
809
                _saveGPXLog();
810
            thrashOldCamera();
811
        }
812
        private void Window_Closed(object sender, EventArgs e)
813
        {
814
            Application.Current.Shutdown();
815
        }
816
 
817
        #region contextmenue add point
818
        Point pWPAdd;
819
        private void GridGMapControl_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
820
        {
821
            if(e.ClickCount == 2)
822
            {
823
                double x = 0, y = 0;
824
                var titleHeight = SystemParameters.WindowCaptionHeight + SystemParameters.ResizeFrameHorizontalBorderHeight;
825
 
826
                pWPAdd = new Point(e.GetPosition(this).X, e.GetPosition(this).Y);
827
                if (pWPAdd.X + canvasAddPoint.Width > Width)
828
                    x = pWPAdd.X - canvasAddPoint.Width;
829
                else
830
                    x = pWPAdd.X;
831
                if (pWPAdd.Y + canvasAddPoint.Height > Height - titleHeight)
832
                    y = pWPAdd.Y - canvasAddPoint.Height;
833
                else
834
                    y = pWPAdd.Y;
835
 
836
                canvasAddPoint.Margin = new Thickness(x, y, canvasAddPoint.Margin.Left, canvasAddPoint.Margin.Bottom);
837
                canvasAddPoint.Visibility = Visibility.Visible;
838
            }
839
 
840
        }
841
        private void canvasAddPoint_LostFocus(object sender, RoutedEventArgs e)
842
        {
843
            canvasAddPoint.Visibility = Visibility.Collapsed;
844
        }
845
        private void canvasAddPoint_MouseLeave(object sender, MouseEventArgs e)
846
        {
847
            canvasAddPoint.Visibility = Visibility.Collapsed;
848
        }
849
        private void btnCmAddWP_Click(object sender, RoutedEventArgs e)
850
        {
851
            if (pWPAdd != null)
852
            {
853
                PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
854
                _addWP(p,0);
855
                canvasAddPoint.Visibility = Visibility.Collapsed;
856
            }
857
        }
858
        private void btnCmAddPOI_Click(object sender, RoutedEventArgs e)
859
        {
860
            if (pWPAdd != null)
861
            {
862
                PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
863
                _addWP(p,1);
864
                canvasAddPoint.Visibility = Visibility.Collapsed;
865
            }
866
        }
867
        private void btnCmAddFailsave_Click(object sender, RoutedEventArgs e)
868
        {
869
            if (pWPAdd != null)
870
            {
871
                PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
872
                _addWP(p,2);
873
                canvasAddPoint.Visibility = Visibility.Collapsed;
874
            }
875
        }
876
        private void btnCmAddLanding_Click(object sender, RoutedEventArgs e)
877
        {
878
            if (pWPAdd != null)
879
            {
880
                PointLatLng p = MainMap.FromLocalToLatLng((int)pWPAdd.X, (int)pWPAdd.Y);
881
                _addWP(p,3);
882
                canvasAddPoint.Visibility = Visibility.Collapsed;
883
            }
884
        }
885
        #endregion contextmenue add point
886
 
887
        #endregion events
888
 
889
        #region cam
890
        private CameraFrameSource _frameSource;
891
 
892
        private void btnCamStart_Click(object sender, RoutedEventArgs e)
893
        {
894
            if (_frameSource != null && _frameSource.Camera == comboBoxCameras.SelectedItem)
895
                return;
896
 
897
            thrashOldCamera();
898
            startCapturing();
899
        }
900
        private void btnCamStop_Click(object sender, RoutedEventArgs e)
901
        {
902
            thrashOldCamera();
903
            _camImage.Visibility = Visibility.Collapsed;
904
            if (stbCamActiveAnim != null && _bCamAnim)
905
            {
906
                Dispatcher.Invoke(() => stbCamActiveAnim.Stop());
907
                _bCamAnim = false;
908
                rectCamStart.Visibility = Visibility.Collapsed;
909
            }
910
        }
911
        private void btnCamSettings_Click(object sender, RoutedEventArgs e)
912
        {
913
            if (_frameSource != null && _frameSource.Camera != null)
914
            {
915
                _frameSource.Camera.ShowPropertiesDialog();
916
            }
917
        }
918
        private void btnCamListRefresh_Click(object sender, RoutedEventArgs e)
919
        {
920
            comboBoxCameras.Items.Clear();
921
            CameraService.ClearCameraList();
922
            foreach (Camera cam in CameraService.AvailableCameras)
923
                comboBoxCameras.Items.Add(cam);
924
 
925
            if (comboBoxCameras.Items.Count > 0)
926
                comboBoxCameras.SelectedIndex = 0;
927
            //if (_frameSource != null && comboBoxCameras.Items.Count > 0 && comboBoxCameras.Items.Contains(_frameSource.Camera.ToString()))
928
            //    comboBoxCameras.SelectedItem = (Camera)_frameSource.Camera;
929
 
930
        }
931
 
932
        private void lblCam_Click(object sender, RoutedEventArgs e)
933
        {
934
            if (_frameSource != null && _frameSource.Camera != null)
935
            {
936
                _camImage.Visibility = _camImage.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
937
            }
938
        }
939
 
940
        void _setCamPicStretch(Stretch type)
941
        {
942
            if(_camImage.Stretch == Stretch.None)
943
                _camImageMargin = _camImage.Margin;
944
            if(type != Stretch.None)
945
                _camImage.Margin = new Thickness(0);
946
            _camImage.Stretch = type;
947
        }
948
        private void btnCamPicStretchNone_Click(object sender, RoutedEventArgs e)
949
        {
950
            _setCamPicStretch(Stretch.None);
951
            _camImage.Margin = _camImageMargin;
952
        }
953
        private void btnCamResetZoom_Click(object sender, RoutedEventArgs e)
954
        {
955
            _setCamPicStretch(Stretch.None);
956
            _camImage.Margin = _camImageMargin = new Thickness(0);
957
            SliderCamZoom.Value = 1;
958
        }
959
        private void btnCamPicStretchFill_Click(object sender, RoutedEventArgs e)
960
        {
961
            _setCamPicStretch(Stretch.Fill);
962
        }
963
        private void btnCamPicStretchUniform_Click(object sender, RoutedEventArgs e)
964
        {
965
            _setCamPicStretch(Stretch.Uniform);
966
        }
967
        private void btnCamPicStretchUFill_Click(object sender, RoutedEventArgs e)
968
        {
969
            _setCamPicStretch(Stretch.UniformToFill);
970
        }
971
        private Camera CurrentCamera
972
        {
973
            get
974
            {
975
                return comboBoxCameras.SelectedItem as Camera;
976
            }
977
        }
978
        private void startCapturing()
979
        {
980
            try
981
            {
982
                Camera c = (Camera)comboBoxCameras.SelectedItem;
983
                setFrameSource(new CameraFrameSource(c));
984
                _frameSource.Camera.CaptureWidth = 640;
985
                _frameSource.Camera.CaptureHeight = 480;
986
                _frameSource.Camera.Fps = 25;
987
                _frameSource.NewFrame += OnImageCaptured;
988
                _frameSource.StartFrameCapture();
989
                _camImage.Visibility = Visibility.Visible;
990
                _camImage.Margin = _camImageMargin;
991
                if (stbCamActiveAnim != null && !_bCamAnim)
992
                {
993
                    Dispatcher.Invoke(() => stbCamActiveAnim.Begin());
994
                    _bCamAnim = true;
995
                    rectCamStart.Visibility = Visibility.Visible;
996
                }
997
            }
998
            catch (Exception ex)
999
            {
1000
                comboBoxCameras.Text = "Select A Camera";
1001
                MessageBox.Show(ex.Message);
1002
            }
1003
        }
1004
 
1005
        public void OnImageCaptured(Touchless.Vision.Contracts.IFrameSource frameSource, Touchless.Vision.Contracts.Frame frame, double fps)
1006
        {
1007
            _camImageSource = BitmapConversion.ToWpfBitmap(frame.Image);
1008
            camTimer.IsEnabled = true;
1009
        }
1010
        private void setFrameSource(CameraFrameSource cameraFrameSource)
1011
        {
1012
            if (_frameSource == cameraFrameSource)
1013
                return;
1014
 
1015
            _frameSource = cameraFrameSource;
1016
        }
1017
        private void thrashOldCamera()
1018
        {
1019
 
1020
            // Trash the old camera
1021
            if (_frameSource != null)
1022
            {
1023
                _frameSource.NewFrame -= OnImageCaptured;
1024
                Dispatcher.Invoke(() => {
1025
                    _camImage.Source = null;
1026
                    _camImage.InvalidateVisual();
1027
                });
1028
                using (Dispatcher.DisableProcessing())
1029
                {
1030
                    _frameSource.StopFrameCapture();
1031
                    setFrameSource(null);
1032
                    Thread.Sleep(10);
1033
                }
1034
            }
1035
        }
1036
 
1037
        Point pOffset,mouse_pos;
1038
        Thickness _camImageMargin = new Thickness(0);
1039
        private void _CamImage_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
1040
        {
1041
            if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && _camImage.Stretch == Stretch.None)
1042
            {
1043
                mouse_pos = Mouse.GetPosition(this);
1044
                mouse_pos.Offset(-pOffset.X, -pOffset.Y);
1045
                pOffset = Mouse.GetPosition(this);
1046
                _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);
1047
            }
1048
        }
1049
        private void _CamImage_MouseDown(object sender, MouseButtonEventArgs e)
1050
        {
1051
            if (e.LeftButton == System.Windows.Input.MouseButtonState.Pressed && _camImage.Stretch == Stretch.None)
1052
                pOffset = Mouse.GetPosition(this);
1053
        }
1054
 
1055
        #endregion cam
1056
 
1057
        #region GMap
1058
        string _mapPosition = "Landshut";
1059
        void _setupMap()
1060
        {
1061
            MainMap.Manager.Mode = AccessMode.ServerAndCache;
1062
            MainMap.MapProvider = GMapProviders.BingHybridMap;
1063
            textBoxGeo.Text = _mapPosition;
1064
            MainMap.SetPositionByKeywords(_mapPosition);
1065
            MainMap.MinZoom = 0;
1066
            MainMap.MaxZoom = 24;
1067
            MainMap.Zoom = 16;
1068
            MainMap.ShowCenter = true;
1069
            MainMap.ShowTileGridLines = false;
1070
            sliderMapZoom.Value = 16;
1071
            comboBoxMapType.ItemsSource = providerList;
1072
            comboBoxMapType.DisplayMemberPath = "Name";
1073
            comboBoxMapType.SelectedItem = MainMap.MapProvider;
1074
 
1075
            // acccess mode
1076
            comboBoxMode.ItemsSource = Enum.GetValues(typeof(AccessMode));
1077
            comboBoxMode.SelectedItem = MainMap.Manager.Mode;
1078
 
1079
        }
1080
 
1081
        /// <summary>
1082
        /// selection of relevant map providers --> if You need more, You can change the line:
1083
        ///     comboBoxMapType.ItemsSource = providerList; 
1084
        /// to:
1085
        ///     comboBoxMapType.ItemsSource = GMapProviders.List;
1086
        /// in _setupMap()
1087
        /// or add items here:
1088
        /// </summary>
1089
        List<GMap.NET.MapProviders.GMapProvider> providerList = new List<GMap.NET.MapProviders.GMapProvider>
1090
        { GMap.NET.MapProviders.GMapProviders.OpenCycleMap, GMap.NET.MapProviders.GMapProviders.OpenCycleLandscapeMap, GMap.NET.MapProviders.GMapProviders.OpenCycleTransportMap,
1091
        GMap.NET.MapProviders.GMapProviders.BingMap,GMap.NET.MapProviders.GMapProviders.BingSatelliteMap,GMap.NET.MapProviders.GMapProviders.BingHybridMap,
1092
        GMap.NET.MapProviders.GMapProviders.GoogleMap,GMap.NET.MapProviders.GMapProviders.GoogleSatelliteMap,GMap.NET.MapProviders.GMapProviders.GoogleHybridMap,GMap.NET.MapProviders.GMapProviders.GoogleTerrainMap,
1093
        GMap.NET.MapProviders.GMapProviders.OviMap,GMap.NET.MapProviders.GMapProviders.OviSatelliteMap,GMap.NET.MapProviders.GMapProviders.OviHybridMap,GMap.NET.MapProviders.GMapProviders.OviTerrainMap};
1094
 
1095
        private void MainMap_Loaded(object sender, RoutedEventArgs e)
1096
        {
1097
            MainMap.Manager.Mode = AccessMode.ServerAndCache;
1098
            copter = new GMapMarker(MainMap.Position);
1099
 
1100
            copter.Shape = new CustomMarkerCopter(this, copter, MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"), "red");
1101
            if (comboBoxCopterColor.SelectionBoxItem != null)
1102
            {
1103
                string s = comboBoxCopterColor.SelectionBoxItem.ToString();
1104
                ((CustomMarkerCopter)(copter.Shape)).setCopterColor(s);
1105
            }
1106
            Dispatcher.Invoke(() => {
1107
                if (comboBoxCopterHeadingColor.SelectionBoxItem != null)
1108
                {
1109
                    string s = comboBoxCopterHeadingColor.SelectionBoxItem.ToString();
1110
                    ((CustomMarkerCopter)(copter.Shape)).setHeadingColor(s);
1111
                }
1112
            });
1113
            copter.Offset = new System.Windows.Point(-26, -26);
1114
            copter.ZIndex = int.MaxValue;
1115
            MainMap.Markers.Add(copter);
1116
            copter.Position = MainMap.Position;
1117
            _setMapItemsSize("Copter", SliderCopterZoom.Value);
1118
        }
1119
        void _setHomePos()
1120
        {
1121
            pHome = MainMap.Position;
1122
            if (!MainMap.Markers.Contains(home))
1123
            {
1124
                home = new GMapMarker(MainMap.Position);
1125
                home.Shape = new CustomMarkerHome(this, home, MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"));
1126
                home.Offset = new System.Windows.Point(-16.5, -16.5);
1127
                // home.ZIndex = int.MaxValue;
1128
                MainMap.Markers.Add(home);
1129
            }
1130
            home.Position = MainMap.Position;
1131
            ((CustomMarkerHome)(home.Shape)).setText(MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"));
1132
            _setMapItemsSize("Home", SliderHPZoom.Value);
1133
            if (checkBoxShowWPMaxRange.IsChecked == true)
1134
            {
1135
                if (cWPBound != null && cWPBound.Tag != null)
1136
                    MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
1137
 
1138
                createCircle(home.Position, dWPMaxRange);
1139
                Dispatcher.Invoke(() =>
1140
                {
1141
                    if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
1142
                    {
1143
                        string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
1144
                        cWPBound.setColor(s);
1145
                    }
1146
                });
1147
            }
1148
 
1149
        }
1150
        void _setActiveWP(int iIndex)
1151
        {
1152
            if (iIndex < wpList.Count)
1153
            {
1154
                if (wpActiveMarker == null || !MainMap.Markers.Contains(wpActiveMarker))
1155
                {
1156
                    Dispatcher.Invoke(() =>
1157
                    {
1158
                        wpActiveMarker = new GMapMarker(wpList[iIndex]);
1159
                        wpActiveMarker.Shape = new CustomMarkerWPActive(this, wpActiveMarker, "wpActive", 0);
1160
                        wpActiveMarker.Offset = new Point(-17.5, -17.5);
1161
                        MainMap.Markers.Add(wpActiveMarker);
1162
                    });
1163
                }
1164
                else
1165
                    Dispatcher.Invoke(() => wpActiveMarker.Position = wpList[iIndex]);
1166
            }
1167
 
1168
            Dispatcher.Invoke(() => tbWPStatusHeight.Text = dtWaypoints.Rows[iIndex][5].ToString() + " m");
1169
        }
1170
        void _clearHomePos()
1171
        {
1172
            MainMap.Markers.Remove(home);
1173
            if (cWPBound != null && cWPBound.Tag != null)
1174
                MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
1175
        }
1176
        void _clearMapMarkers(Type markerType)
1177
        {
1178
            for (int k = 0; k < MainMap.Markers.Count;)
1179
            {
1180
                GMapMarker p = MainMap.Markers[k];
1181
                if (p.GetType() == markerType | (p.Shape != null && p.Shape.GetType() == markerType))
1182
                    MainMap.Markers.Remove(p);
1183
                else
1184
                    k++;
1185
            }
1186
            _WPisMouseCaptured = false;
1187
        }
1188
 
1189
        GMapMarker _findWPMarker(string name)
1190
        {
1191
            for (int k = 0; k < MainMap.Markers.Count;)
1192
            {
1193
                GMapMarker p = MainMap.Markers[k];
1194
                if (p.GetType() == typeof(CustomMarkerWP) | (p.Shape != null && p.Shape.GetType() == typeof(CustomMarkerWP)))
1195
                    if (((CustomMarkerWP)p.Shape).WPText == name)
1196
                        return p;
1197
                    else
1198
                        k++;
1199
                else
1200
                    k++;
1201
            }
1202
            return null;
1203
        }
1204
        void _clearWPMarker(string name)
1205
        {
1206
            GMapMarker p = _findWPMarker(name);
1207
            if (p != null)
1208
                MainMap.Markers.Remove(p);
1209
        }
1210
        void _renameWPMarker(string s1, string s2)
1211
        {
1212
            GMapMarker p = _findWPMarker(s1);
1213
            if (p != null)
1214
                ((CustomMarkerWP)p.Shape).WPText = s2;
1215
        }
1216
        void _WPMarkerSetType(string text, int type)
1217
        {
1218
            GMapMarker p = _findWPMarker(text);
1219
            if (p != null)
1220
                ((CustomMarkerWP)p.Shape).WPType = type;
1221
        }
1222
        void _repositionWPMarker(PointLatLng point, string name)
1223
        {
1224
            GMapMarker p = _findWPMarker(name);
1225
            if (p != null)
1226
                p.Position = point;
1227
        }
1228
 
1229
        void createCircle(PointLatLng center, double distance)
1230
        {
1231
 
1232
            GMapMarker it = new GMapMarker(center);
1233
            it.ZIndex = -1;
1234
 
1235
            cWPBound.Center = center;
1236
            cWPBound.Bound = GMap.NET.PureProjection.GetPointFromDistance(center, distance);
1237
            cWPBound.Tag = it;
1238
            cWPBound.IsHitTestVisible = false;
1239
            UpdateCircle(cWPBound);
1240
            it.Shape = cWPBound;
1241
            MainMap.Markers.Add(it);
1242
        }
1243
        // calculates circle radius
1244
        void UpdateCircle(Circle c)
1245
        {
1246
            var pxCenter = MainMap.FromLatLngToLocal(c.Center);
1247
            var pxBounds = MainMap.FromLatLngToLocal(c.Bound);
1248
 
1249
            double a = (double)(pxBounds.X - pxCenter.X);
1250
            double b = (double)(pxBounds.Y - pxCenter.Y);
1251
            var pxCircleRadius = Math.Sqrt(a * a + b * b);
1252
 
1253
            c.Width = c.Height = pxCircleRadius * 2;
1254
            //c.Width = 55 + pxCircleRadius * 2;
1255
            //c.Height = 55 + pxCircleRadius * 2;
1256
            (c.Tag as GMapMarker).Offset = new System.Windows.Point(-c.Width / 2, -c.Height / 2);
1257
        }
1258
 
1259
        // access mode
1260
        private void comboBoxMode_DropDownClosed(object sender, EventArgs e)
1261
        {
1262
            MainMap.Manager.Mode = (AccessMode)comboBoxMode.SelectedItem;
1263
            MainMap.ReloadMap();
1264
        }
1265
        // zoom up
1266
        private void czuZoomUp_Click(object sender, RoutedEventArgs e)
1267
        {
1268
            MainMap.Zoom = ((int)MainMap.Zoom) + 1;
1269
        }
1270
 
1271
        // zoom down
1272
        private void czuZoomDown_Click(object sender, RoutedEventArgs e)
1273
        {
1274
            MainMap.Zoom = ((int)(MainMap.Zoom + 0.99)) - 1;
1275
        }
1276
 
1277
        // prefetch
1278
        private void buttonPrefetch_Click(object sender, RoutedEventArgs e)
1279
        {
1280
            RectLatLng area = MainMap.SelectedArea;
1281
            if (!area.IsEmpty)
1282
            {
1283
                for (int i = (int)MainMap.Zoom; i <= MainMap.MaxZoom; i++)
1284
                {
1285
                    MessageBoxResult res = MessageBox.Show("Ready ripp at Zoom = " + i + " ?", "GMap.NET", MessageBoxButton.YesNoCancel);
1286
 
1287
                    if (res == MessageBoxResult.Yes)
1288
                    {
1289
                        TilePrefetcher obj = new TilePrefetcher();
1290
                        obj.Owner = this;
1291
                        obj.ShowCompleteMessage = true;
1292
                        obj.Start(area, i, MainMap.MapProvider, 100);
1293
                    }
1294
                    else if (res == MessageBoxResult.No)
1295
                    {
1296
                        continue;
1297
                    }
1298
                    else if (res == MessageBoxResult.Cancel)
1299
                    {
1300
                        break;
1301
                    }
1302
                }
1303
            }
1304
            else
1305
            {
1306
                MessageBox.Show("Select map area holding ALT", "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Exclamation);
1307
            }
1308
        }
1309
 
1310
        // goto by geocoder
1311
        private void buttonGeoCoding_Click(object sender, RoutedEventArgs e)
1312
        {
1313
            _goto_byGeoCoder();
1314
        }
1315
        // goto by geocoder
1316
        private void textBoxGeo_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
1317
        {
1318
            if (e.Key == System.Windows.Input.Key.Enter)
1319
                _goto_byGeoCoder();
1320
        }
1321
        void _goto_byGeoCoder()
1322
        {
1323
            GeoCoderStatusCode status = MainMap.SetPositionByKeywords(textBoxGeo.Text);
1324
            _mapPosition = textBoxGeo.Text;
1325
            if (status != GeoCoderStatusCode.G_GEO_SUCCESS)
1326
            {
1327
                MessageBox.Show("Geocoder can't find: '" + textBoxGeo.Text + "', reason: " + status.ToString(), "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Exclamation);
1328
            }
1329
        }
1330
        private void buttonGeoLoc_Click(object sender, RoutedEventArgs e)
1331
        {
1332
            try
1333
            {
1334
                double lat = double.Parse(textBoxLat.Text, System.Globalization.CultureInfo.InvariantCulture);
1335
                double lng = double.Parse(textBoxLng.Text, System.Globalization.CultureInfo.InvariantCulture);
1336
 
1337
                MainMap.Position = new PointLatLng(lat, lng);
1338
            }
1339
            catch (Exception ex)
1340
            {
1341
                MessageBox.Show("incorrect coordinate format: " + ex.Message);
1342
            }
1343
 
1344
        }
1345
 
1346
        private void ReloadMap_Click(object sender, RoutedEventArgs e)
1347
        {
1348
            MainMap.ReloadMap();
1349
        }
1350
 
1351
        private void MainMap_OnPositionChanged(PointLatLng point)
1352
        {
1353
            if (_bFollowCopter)
1354
                _setCopterData(MainMap.Position);
1355
        }
1356
 
1357
        private void MainMap_OnMapZoomChanged()
1358
        {
1359
            if (_bFollowCopter)
1360
                _setCopterData(MainMap.Position);
1361
            if ((int)sliderMapZoom.Value != MainMap.Zoom)
1362
                sliderMapZoom.Value = MainMap.Zoom;
1363
            if (cWPBound != null && cWPBound.Tag != null)
1364
                UpdateCircle(cWPBound);
1365
        }
1366
 
1367
        void _setCopterData(PointLatLng p)
1368
        {
1369
            Dispatcher.Invoke(() =>
1370
            {
1371
                copter.Position = p;
1372
                ((CustomMarkerCopter)(copter.Shape)).setText(p.Lat.ToString("0.#######°") + System.Environment.NewLine + p.Lng.ToString("0.#######°"));
1373
                textBoxLat_currentPos.Text = p.Lat.ToString() + "°";
1374
                textBoxLng_currentPos.Text = p.Lng.ToString() + "°";
1375
            });
1376
            if (home != null && MainMap.Markers.Contains(home))
1377
            {
1378
                Dispatcher.Invoke(() => ArtHor.rotateHome = GMapProviders.EmptyProvider.Projection.GetBearing(copter.Position, home.Position));
1379
                double d = GMapProviders.EmptyProvider.Projection.GetDistance(home.Position, copter.Position);
1380
                Dispatcher.Invoke(() => tbTopDistanceHP.Text = (d * 1000).ToString("0.0 m"));
1381
 
1382
                if (d * 1000 < _dThresholdDistanceWarn)
1383
                {
1384
                    _iDistanceJitter = 0; _bVoiceDistanceActive = false;
1385
                    if (stbDistanceWarnAnim != null && _bAnimDistanceActive)
1386
                    {
1387
                        Dispatcher.Invoke(() => stbDistanceWarnAnim.Stop());
1388
                        _bAnimDistanceActive = false;
1389
                    }
1390
                }
1391
                else
1392
                {
1393
                    if (_iDistanceJitter < 20)
1394
                    { _iDistanceJitter++; }
1395
                    if (_iDistanceJitter == 20)
1396
                    {
1397
                        if (stbDistanceWarnAnim != null && !_bAnimDistanceActive)
1398
                        {
1399
                            Dispatcher.Invoke(() => stbDistanceWarnAnim.Begin());
1400
                            _bAnimDistanceActive = true;
1401
                        }
1402
                        if (_bVoiceDistancePlay && !_bVoiceDistanceActive)
1403
                        {
1404
                            ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\Distance.mp3");
1405
                            //Thread t = new Thread(()=>_mediaPlayer("Voice\\Distance.mp3"));
1406
                            //t.Start();
1407
                            _bVoiceDistanceActive = true;
1408
                        }
1409
                        _iDistanceJitter++;
1410
                    }
1411
                }
1412
            }
1413
        }
1414
 
1415
        void _setMapItemsSize(string item, double value)
1416
        {
1417
            ScaleTransform scaleTransform = new ScaleTransform();
1418
            scaleTransform.ScaleY = value;
1419
            scaleTransform.ScaleX = value;
1420
            TransformGroup transformGroup = new TransformGroup();
1421
            transformGroup.Children.Add(scaleTransform);
1422
 
1423
            switch (item)
1424
            {
1425
                case "Copter":
1426
                    if (copter != null && copter.Shape != null)
1427
                    {
1428
                        ((ScaleTransform)transformGroup.Children[0]).CenterX = 26;
1429
                        ((ScaleTransform)transformGroup.Children[0]).CenterY = 26;
1430
                        copter.Shape.RenderTransform = transformGroup;
1431
                    }
1432
                    break;
1433
                case "Home":
1434
                    if (home != null && MainMap.Markers.Contains(home))
1435
                    {
1436
                        ((ScaleTransform)transformGroup.Children[0]).CenterX = 16.5;
1437
                        ((ScaleTransform)transformGroup.Children[0]).CenterY = 16.5;
1438
                        home.Shape.RenderTransform = transformGroup;
1439
                        home.Shape.InvalidateVisual();
1440
                    }
1441
                    break;
1442
                case "WP":
1443
                    Dispatcher.Invoke(() =>
1444
                    {
1445
                        ((ScaleTransform)transformGroup.Children[0]).CenterX = 11.5;
1446
                        ((ScaleTransform)transformGroup.Children[0]).CenterY = 11.5;
1447
                        for (int k = 0; k < MainMap.Markers.Count;)
1448
                        {
1449
                            GMapMarker p = MainMap.Markers[k];
1450
                            if (p.Shape != null && (p.Shape.GetType() == typeof(CustomMarkerWP) || p.Shape.GetType() == typeof(CustomMarkerWPActive)))
1451
                            {
1452
                                ((CustomMarkerWP)(p.Shape)).RenderTransform = transformGroup;
1453
                            }
1454
                            k++;
1455
                        }
1456
                    });
1457
                    break;
1458
            }
1459
 
1460
        }
1461
 
1462
        private void checkBoxFollowCopter_Click(object sender, RoutedEventArgs e)
1463
        {
1464
            _bFollowCopter = (bool)checkBoxFollowCopter.IsChecked;
1465
        }
1466
 
1467
        private void sliderMapZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
1468
        {
1469
            if (MainMap.Zoom != sliderMapZoom.Value)
1470
                MainMap.Zoom = (int)sliderMapZoom.Value;
1471
        }
1472
 
1473
        private void SliderCopterZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
1474
        {
1475
            if (copter != null && copter.Shape != null)
1476
                _setMapItemsSize("Copter",SliderCopterZoom.Value);
1477
        }
1478
        private void SliderWPZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
1479
        {
1480
            if (MainMap.Markers.Count > 2)
1481
                _setMapItemsSize("WP",SliderWPZoom.Value);
1482
        }
1483
        private void SliderHomeZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
1484
        {
1485
            if (home != null && MainMap.Markers.Contains(home))
1486
                _setMapItemsSize("Home",SliderHPZoom.Value);
1487
        }
1488
 
1489
 
1490
 
1491
        #region Touch zooming hackattack ;) 
1492
        /// <summary>
1493
        /// inspired by http://www.codeproject.com/Articles/692286/WPF-and-multi-touch
1494
        /// </summary>
1495
        bool bFirstAccess = true;
1496
        double dDistance = 0;
1497
        int iZoom;
1498
        private void MainMap_StylusDown(object sender, StylusDownEventArgs e)
1499
        {
1500
            if (!_WPisMouseCaptured)
1501
            {
1502
                var id = e.StylusDevice.Id;
1503
                e.StylusDevice.Capture(MainMap);
1504
                if (iFirstStylusID == -1)
1505
                {
1506
                    iFirstStylusID = id;
1507
                }
1508
                else
1509
                {
1510
 
1511
                    MainMap.CanDragMap = false;
1512
                }
1513
            }
1514
        }
1515
        private void MainMap_StylusUp(object sender, StylusEventArgs e)
1516
        {
1517
            MainMap.ReleaseStylusCapture();
1518
            iFirstStylusID = -1;
1519
            bFirstAccess = true;
1520
            MainMap.CanDragMap = true;
1521
            iZoom = 0;
1522
        }
1523
        private void MainMap_StylusMove(object sender, StylusEventArgs e)
1524
        {
1525
            var id = e.StylusDevice.Id;
1526
            var tp = e.GetPosition(MainMap);
1527
 
1528
            // This is the first Stylus point; just record its position. 
1529
            if (id == iFirstStylusID)
1530
            {
1531
                pTouch1.X = tp.X;
1532
                pTouch1.Y = tp.Y;
1533
            }
1534
            else
1535
            if (iFirstStylusID > -1)
1536
            {
1537
                pTouch2.X = tp.X;
1538
                pTouch2.Y = tp.Y;
1539
                double distance = Point.Subtract(pTouch1, pTouch2).Length;
1540
                if (!bFirstAccess)
1541
                {
1542
                    if (distance > dDistance)
1543
                        iZoom++;
1544
                    else
1545
                        if (distance < dDistance)
1546
                        iZoom--;
1547
                }
1548
                if (iZoom > 30)
1549
                {
1550
                    iZoom = 0;
1551
                    Dispatcher.Invoke(() => sliderMapZoom.Value += 1);
1552
                }
1553
                if (iZoom < -30)
1554
                {
1555
                    iZoom = 0;
1556
                    Dispatcher.Invoke(() => sliderMapZoom.Value -= 1);
1557
                }
1558
                dDistance = distance;
1559
                bFirstAccess = false;
1560
            }
1561
        }
1562
        #endregion Touch zooming hackattack ;)
1563
 
1564
        #endregion GMap
1565
 
1566
        #region settings
1567
        private void cBoxTimingsDebug_DropDownClosed(object sender, EventArgs e)
1568
        {
1569
            if (!_bCBInit && cBoxTimingsDebug.SelectedIndex > -1)
1570
                debugInterval = (byte)(Convert.ToInt16(cBoxTimingsDebug.SelectedItem) / 10);
1571
        }
1572
        private void cBoxTimingsNav_DropDownClosed(object sender, EventArgs e)
1573
        {
1574
            if (!_bCBInit && cBoxTimingsNav.SelectedIndex > -1)
1575
                navctrlInterval = (byte)(Convert.ToInt16(cBoxTimingsNav.SelectedItem) / 10);
1576
        }
1577
        private void cBoxTimingsBl_DropDownClosed(object sender, EventArgs e)
1578
        {
1579
            if (!_bCBInit && cBoxTimingsBl.SelectedIndex > -1)
1580
                blctrlInterval = (byte)(Convert.ToInt16(cBoxTimingsBl.SelectedItem) / 10);
1581
        }
1582
        private void cBoxTimingsOSD_DropDownClosed(object sender, EventArgs e)
1583
        {
1584
            if (!_bCBInit && cBoxTimingsOSD.SelectedIndex > -1)
1585
                OSDInterval = (byte)(Convert.ToInt16(cBoxTimingsOSD.SelectedItem) / 10);
1586
        }
1587
        private void chkbAutoDbg_Click(object sender, RoutedEventArgs e)
1588
        {
1589
            if (!_init) _debugDataAutorefresh = (bool)chkbAutoDbg.IsChecked;
1590
        }
1591
        private void chkbAutoNav_Click(object sender, RoutedEventArgs e)
1592
        {
1593
            if (!_init) _navCtrlDataAutorefresh = (bool)chkbAutoNav.IsChecked;
1594
        }
1595
        private void chkbAutoBL_Click(object sender, RoutedEventArgs e)
1596
        {
1597
            if (!_init) _blctrlDataAutorefresh = (bool)chkbAutoBL.IsChecked;
1598
        }
1599
        private void chkbAutoOSD_Click(object sender, RoutedEventArgs e)
1600
        {
1601
            if (!_init) _OSDAutorefresh = (bool)chkbAutoOSD.IsChecked;
1602
        }
1603
 
1604
        private void cBoxLiPoCells_DropDownClosed(object sender, EventArgs e)
1605
        {
1606
            if (cBoxLiPoCells.SelectedIndex > -1)
1607
            {
1608
                _LipoCells = cBoxLiPoCells.SelectedIndex + 3;
1609
                _LipoMinMax();
1610
            }
1611
        }
1612
        private void chkbAutoLiPo_Click(object sender, RoutedEventArgs e)
1613
        {
1614
            _bLiPoAutoDetect = (bool)chkbAutoLiPoDetect.IsChecked;
1615
        }
1616
 
1617
        void _LipoMinMax()
1618
        {
1619
            _dLipoVMax = (double)(_LipoCells) * 4.22;
1620
            _dLipoVMin = (double)_LipoCells * 3;
1621
            pbTopVoltage.Maximum = _dLipoVMax;
1622
            pbTopVoltage.Minimum = _dLipoVMin;
1623
            sliderThresholdVoltageWarn.Maximum = _dLipoVMax;
1624
            sliderThresholdVoltageWarn.Minimum = _dLipoVMin;
1625
        }
1626
        private void cBoxMotors_DropDownClosed(object sender, EventArgs e)
1627
        {
1628
            if (cBoxMotors.SelectedIndex > -1)
1629
            {
1630
                _iMotors = cBoxMotors.SelectedIndex + 3;
1631
                Dispatcher.Invoke(() =>
1632
                {
1633
                    dgvMotors1.Height = (272 / 12.6) * (_iMotors + 1);  //272 / 12.6 --> Workaround, cause the headerheight = NaN...?
1634
                    GridMotors.Height = dgvMotors1.Height + 10;
1635
                });
1636
            }
1637
        }
1638
        void _setMotorGridSize()
1639
        {
1640
            if (dgvMotors1.Columns.Count > 2)
1641
            {
1642
                dgvMotors1.Columns[0].Width = 24;
1643
                dgvMotors1.Columns[1].Width = 50;
1644
                dgvMotors1.Columns[2].Width = 50;
1645
                dgvMotors1.Height = (272 / 12.6) * (_iMotors + 1);
1646
                GridMotors.Height = dgvMotors1.Height + 10;
1647
            }
1648
 
1649
        }
1650
        #endregion settings
1651
 
1652
        #region functions  
1653
 
1654
        #region logging      
1655
        /// <summary> Log data to the terminal window. </summary>
1656
        /// <param name="msgtype"> The type of message to be written. </param>
1657
        /// <param name="msg"> The string containing the message to be shown. </param>
1658
        private void Log(LogMsgType msgtype, string msg)
1659
        {
1660
            Dispatcher.Invoke(() =>
1661
            {
1662
                // rtfTerminal.CaretPosition = rtfTerminal.CaretPosition.DocumentEnd;
1663
                // rtfTerminal.Foreground = new SolidColorBrush(LogMsgTypeColor[(int)msgtype]);
1664
                //                rtfTerminal.AppendText(msg + "\r");
1665
                TextRange tr = new TextRange(rtfTerminal.Document.ContentEnd, rtfTerminal.Document.ContentEnd);
1666
                tr.Text = msg;
1667
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
1668
                rtfTerminal.AppendText("\r");
1669
                rtfTerminal.ScrollToEnd();
1670
            });
1671
        }
1672
        private void ErrorLog(LogMsgType msgtype, string msg, string linkURL, string linkName)
1673
        {
1674
 
1675
            Dispatcher.Invoke(() =>
1676
            {
1677
                Paragraph para = new Paragraph();
1678
                para.Margin = new Thickness(0); // remove indent between paragraphs
1679
 
1680
                Hyperlink link = new Hyperlink();
1681
                if (linkURL != "" && linkName != "")
1682
                {
1683
                    link.IsEnabled = true;
1684
                    link.Inlines.Add(linkName);
1685
                    link.NavigateUri = new Uri(linkURL);
1686
                    link.RequestNavigate += (sender, args) => Process.Start(args.Uri.ToString());
1687
                }
1688
                //msg = DateTime.Now.ToLongTimeString() + msg;
1689
                para.Foreground = new SolidColorBrush(LogMsgTypeColor[(int)msgtype]);
1690
                Run r = new Run("[" + DateTime.Now.ToLongTimeString() + "]: ");
1691
                r.Foreground = new SolidColorBrush(Colors.Black);
1692
                para.Inlines.Add(r);
1693
                para.Inlines.Add(msg);
1694
                para.Inlines.Add(link);
1695
                rtfError.Document.Blocks.Add(para);
1696
                //TextRange tr = new TextRange(rtfError.Document.ContentEnd, rtfError.Document.ContentEnd);
1697
                //tr.Text = msg + link;
1698
                //tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
1699
                //rtfError.AppendText("\r");
1700
                rtfError.ScrollToEnd();
1701
 
1702
                //_bErrorLog = true;
1703
            });
1704
        }
1705
        /// <summary>
1706
        /// Clear the line in the  errorlog window 
1707
        /// containing the error string when error has ceased
1708
        /// </summary>
1709
        /// <param name="s">substring of errrormessage</param>
1710
        void _clearErrorLog(string s)
1711
        {
1712
            Dispatcher.Invoke((Action)(() =>
1713
            {
1714
                TextRange searchRange = new TextRange(rtfError.Document.ContentStart, rtfError.Document.ContentEnd);
1715
                TextRange foundRange = FindTextInRange(searchRange, s);
1716
 
1717
                int iStart = searchRange.Text.IndexOf(s, StringComparison.OrdinalIgnoreCase);
1718
 
1719
 
1720
                if (iStart > -1)
1721
                {
1722
                    int iLength = 0;
1723
                    int iEnd = searchRange.Text.IndexOf('\r', iStart);
1724
                    if (iEnd > 0)
1725
                    {
1726
                        iLength = iEnd + 1;
1727
                        int iHttp = searchRange.Text.IndexOf("http", iEnd);
1728
                        if (iHttp == iLength)
1729
                        {
1730
                            int iEnd2 = searchRange.Text.IndexOf('\r', iLength);
1731
                            if (iEnd2 > iLength)
1732
                            {
1733
                                iLength = iEnd2 + 1;
1734
                                //  TextRange result = new TextRange(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
1735
 
1736
                                rtfError.Selection.Select(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
1737
                                rtfError.Selection.Text = string.Empty;
1738
                                if (rtfError.Document.ContentEnd.GetTextRunLength(LogicalDirection.Backward) < 2) _bErrorLog = false;
1739
                            }
1740
 
1741
                        }
1742
                        else
1743
                        {
1744
                            rtfError.Selection.Select(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
1745
                            rtfError.Selection.Text = string.Empty;
1746
                            if (rtfError.Document.ContentEnd.GetTextRunLength(LogicalDirection.Backward) < 2) _bErrorLog = false;
1747
                        }
1748
                    }
1749
                }
1750
            }));
1751
 
1752
        }
1753
        public TextRange FindTextInRange(TextRange searchRange, string searchText)
1754
        {
1755
            int offset = searchRange.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase);
1756
            if (offset < 0)
1757
                return null;  // Not found
1758
 
1759
            var start = GetTextPositionAtOffset(searchRange.Start, offset);
1760
            TextRange result = new TextRange(start, GetTextPositionAtOffset(start, searchText.Length));
1761
 
1762
            return result;
1763
        }
1764
        TextPointer GetTextPositionAtOffset(TextPointer position, int characterCount)
1765
        {
1766
            while (position != null)
1767
            {
1768
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
1769
                {
1770
                    int count = position.GetTextRunLength(LogicalDirection.Forward);
1771
                    if (characterCount <= count)
1772
                    {
1773
                        return position.GetPositionAtOffset(characterCount);
1774
                    }
1775
 
1776
                    characterCount -= count;
1777
                }
1778
 
1779
                TextPointer nextContextPosition = position.GetNextContextPosition(LogicalDirection.Forward);
1780
                if (nextContextPosition == null)
1781
                    return position;
1782
 
1783
                position = nextContextPosition;
1784
            }
1785
 
1786
            return position;
1787
        }
1788
        #endregion logging
1789
 
1790
        #region processing received data
1791
 
1792
        private void processMessage(byte[] message)
1793
        {
1794
            if (message.Length > 0)
1795
            {
1796
                _iLifeCounter++;
1797
                //Log(LogMsgType.Incoming, BitConverter.ToString(message));
1798
                //Log(LogMsgType.Incoming, message.Length.ToString());
1799
                string s = new string(ASCIIEncoding.ASCII.GetChars(message, 0, message.Length));
1800
                char cmdID;
1801
                byte adr;
1802
                byte[] data;
1803
                byte[] tmp = null;
1804
                if (message[0] != '#')
1805
                {
1806
                    int iFound = -1;
1807
                    for (int i = 0; i < message.Length; i++)   //Sometimes the FC/NC sends strings without termination (like WP messages)
1808
                    {                                   //so this is a workaround to not spam the log box
1809
                        if (message[i] == 35)
1810
                        {
1811
                            iFound = i;
1812
                            break;
1813
                        }
1814
                    }
1815
                    if (iFound > 0)
1816
                    {
1817
                        s = new string(ASCIIEncoding.ASCII.GetChars(message, 0, iFound));
1818
                        tmp = new byte[message.Length - iFound];
1819
                        Buffer.BlockCopy(message, iFound, tmp, 0, message.Length - iFound);
1820
                    }
1821
                    s = s.Trim('\0', '\n', '\r');
1822
                    if (s.Length > 0)
1823
                        Log(LogMsgType.Normal, s);
1824
                    if (tmp != null)
1825
                    {
1826
                        s = new string(ASCIIEncoding.ASCII.GetChars(tmp, 0, tmp.Length));
1827
                        processMessage(tmp);
1828
                    }
1829
                }
1830
                //Debug.Print(s);
1831
                else
1832
                {
1833
                    FlightControllerMessage.ParseMessage(message, out cmdID, out adr, out data);
1834
 
1835
                    if (adr == 255) { crcError++; }
1836
                    else crcError = 0;
1837
                    Dispatcher.Invoke(() => tbCrc.Text = crcError.ToString());
1838
                    //display the active controller (FC / NC) 
1839
                    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...???
1840
                    {
1841
                        _iCtrlAct = adr;
1842
                        switch (adr)
1843
                        {
1844
                            case 1:
1845
                                Dispatcher.Invoke(() => tbCtrl.Text = "FC");
1846
                                Dispatcher.Invoke(() => buttonSwitchNC.Visibility = Visibility.Visible);
1847
                                Dispatcher.Invoke(() => labelSwitchToNavi.Visibility = Visibility.Visible);
1848
                                //  _setFieldsNA(); //display fields NA for FC 
1849
                                break;
1850
                            case 2:
1851
                                Dispatcher.Invoke(() => tbCtrl.Text = "NC");
1852
                                Dispatcher.Invoke(() => buttonSwitchNC.Visibility = Visibility.Hidden);
1853
                                Dispatcher.Invoke(() => labelSwitchToNavi.Visibility = Visibility.Hidden);
1854
                                break;
1855
                            //case 3:
1856
                            //    lblCtrl.Invoke((Action)(() => lblCtrl.Text = "MK3MAG"));
1857
                            //    break;
1858
                            //case 4:
1859
                            //    lblCtrl.Invoke((Action)(() => lblCtrl.Text = "BL-CTRL"));
1860
                            //    break;
1861
                            default:
1862
                                Dispatcher.Invoke(() => tbCtrl.Text = "NA");
1863
                                break;
1864
                        }
1865
                        // _loadLabelNames();
1866
                    }
1867
                    // else
1868
                    //     Debug.Print("Address == 0?");
1869
 
1870
                    if (data != null && data.Length > 0)
1871
                    {
1872
                        s = new string(ASCIIEncoding.ASCII.GetChars(data, 1, data.Length - 1));
1873
                        s = s.Trim('\0', '\n');
1874
 
1875
                        switch (cmdID)
1876
                        {
1877
                            //case 'A': //Label names
1878
                            //    _processLabelNames(s);
1879
                            //    break;
1880
 
1881
                            case 'D': //Debug data
1882
                                _processDebugVals(adr, data);
1883
                                break;
1884
 
1885
                            case 'V': //Version
1886
                                _processVersion(adr, data);
1887
                                break;
1888
 
1889
                            case 'K'://BL-CTRL data
1890
                                _processBLCtrl(data);
1891
                                break;
1892
 
1893
                            case 'M'://License info
1894
                                _processLicense(data);
1895
                                break;
1896
 
1897
                            case 'O': //NC Data
1898
                                if (data[0] < 10)
1899
                                    _processNCData(data);
1900
                                else
1901
                                    _processNCDataV2(data);
1902
                                break;
1903
 
1904
                            //case 'E': //NC error-string
1905
                            //    ErrorLog(LogMsgType.Error, "NC Error: " + s);
1906
                            //    break;
1907
 
1908
                            case 'L': //OSD Menue (called by pagenumber)
1909
                                _processOSDSingle(data);
1910
                                break;
1911
 
1912
                            case 'H': //OSD Menue (with autoupdate - called by Key)
1913
                                _processOSDAuto(data);
1914
                                break;
1915
 
1916
                            case 'X': //Waypoint data
1917
                                _processWPData(data);
1918
                                break;
1919
 
1920
                            case 'W': //return new Waypoint items count after sending waypoint to copter
1921
                                _iWPCount = data[0];
1922
                                break;
1923
                                //default:
1924
                                //    Log(LogMsgType.Incoming, "cmd: " + cmdID.ToString());
1925
                                //    Log(LogMsgType.Incoming, BitConverter.ToString(data));
1926
                                //    break;
1927
                        }
1928
                    }
1929
                    //else
1930
                    //{
1931
                    //    Log(LogMsgType.Incoming, "cmd: " + cmdID.ToString());
1932
                    //    Log(LogMsgType.Incoming, BitConverter.ToString(data));
1933
                    //}
1934
                }
1935
            }
1936
        }
1937
        /// <summary>
1938
        /// Analog label names 'A'
1939
        /// each label name is returned as a single string 
1940
        /// and added to string array sAnalogLabel[]
1941
        /// and the datatable dtAnalog
1942
        /// </summary>
1943
        /// <param name="s">the label name</param>
1944
        void _processLabelNames(string s)
1945
        {
1946
            //if (iLableIndex < 32)
1947
            //{
1948
            //    sAnalogLabel[iLableIndex] = s;
1949
            //    if (dtAnalog.Rows.Count < 32)
1950
            //        dtAnalog.Rows.Add(s, "");
1951
            //    else
1952
            //        dtAnalog.Rows[iLableIndex].SetField(0, s);
1953
 
1954
            //  //  _getAnalogLabels(iLableIndex + 1);
1955
            //}
1956
            //Debug.Print(s);
1957
        }
1958
        /// <summary>
1959
        /// Debug values 'D'
1960
        /// </summary>
1961
        /// <param name="adr">adress of the active controller (1-FC, 2-NC)</param>
1962
        /// <param name="data">the received byte array to process</param>
1963
        void _processDebugVals(byte adr, byte[] data)
1964
        {
1965
            if (data.Length == 66)
1966
            {
1967
 
1968
                double v;
1969
                int index = 0;
1970
                Int16 i16 = 0;
1971
                double dTemp = 0;
1972
                for (int i = 2; i < 66; i += 2)
1973
                {
1974
                    i16 = data[i + 1];
1975
                    i16 = (Int16)(i16 << 8);
1976
                    iAnalogData[index] = data[i] + i16;
1977
                    sAnalogData[index] = (data[i] + i16).ToString();
1978
                    // dtAnalog.Rows[index].SetField(1, sAnalogData[index]);
1979
 
1980
                    if (adr == 2) //NC
1981
                    {
1982
                        switch (index)
1983
                        {
1984
                            case 0: //pitch (German: nick)
1985
                                Dispatcher.Invoke(() => ArtHor.Pitch = ((double)iAnalogData[index] / (double)10));
1986
                                Dispatcher.Invoke((Action)(() => tbPitch.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0°")));
1987
                                break;
1988
                            case 1: //roll
1989
                                Dispatcher.Invoke(() => ArtHor.Roll = ((double)iAnalogData[index] / (double)10));
1990
                                Dispatcher.Invoke((Action)(() => tbRoll.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0°")));
1991
                                break;
1992
                            case 4: //altitude
1993
                                Dispatcher.Invoke(() => tbAlt.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 m"));
1994
                                Dispatcher.Invoke(() => tbTopHeight.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 m"));
1995
                                Dispatcher.Invoke(() => { drGPX[3] = (double)iAnalogData[index] / (double)10; });
1996
                                break;
1997
                            case 7: //Voltage
1998
                                v = (double)iAnalogData[index] / (double)10;
1999
                                Dispatcher.Invoke(() => tbVolt.Text = v.ToString("0.0 V"));
2000
                                Dispatcher.Invoke(() => tbTopVoltage.Text = v.ToString("0.0 V"));
2001
                                Dispatcher.Invoke(() => pbTopVoltage.Value = v);
2002
                                if (v - _dLipoVMin < 1 | v < _dThresholdVoltageWarn)
2003
                                {
2004
                                    if (v == _dVoltLast)
2005
                                        if (_iVoltJitter < 20) _iVoltJitter++;
2006
                                        else
2007
                                        {
2008
                                            _iVoltJitter = 0;
2009
                                            _dVoltLast = v;
2010
                                        }
2011
                                    _dVoltLast = v;
2012
                                    if (_iVoltJitter == 20)
2013
                                    {
2014
                                        Dispatcher.Invoke(() => pbTopVoltage.Foreground = Brushes.Orange);
2015
 
2016
                                        if (v - _dLipoVMin < 1 | v < _dThresholdVoltageCrit)
2017
                                        {
2018
                                            Dispatcher.Invoke(() => pbTopVoltage.Foreground = Brushes.Red);
2019
                                            if (stbVoltageCritAnim != null && !_bCritAnimVoltActive)
2020
                                            {
2021
                                                Dispatcher.Invoke(() => stbVoltageCritAnim.Begin());
2022
                                                _bCritAnimVoltActive = true;
2023
                                            }
2024
                                            if (_bVoiceVoltPlay && !_bCritVoiceVoltActive)
2025
                                            {
2026
                                                ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\CriticalBattery.mp3");
2027
                                                //Thread t = new Thread(() => _mediaPlayer("Voice\\CriticalBattery.mp3"));
2028
                                                //t.Start();
2029
                                                _bCritVoiceVoltActive = true;
2030
                                            }
2031
                                        }
2032
                                        else
2033
                                        {
2034
                                            if (stbVoltageCritAnim != null && _bCritAnimVoltActive)
2035
                                            {
2036
                                                Dispatcher.Invoke(() => stbVoltageCritAnim.Stop());
2037
                                                _bCritAnimVoltActive = false;
2038
                                            }
2039
                                            _bCritVoiceVoltActive = false;
2040
 
2041
                                            if (_bVoiceVoltPlay && !_bWarnVoiceVoltActive)
2042
                                            {
2043
                                                ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\LowBattery.mp3");
2044
                                                //Thread t = new Thread(() => _mediaPlayer("Voice\\LowBattery.mp3"));
2045
                                                //t.Start();
2046
                                                _bWarnVoiceVoltActive = true;
2047
                                            }
2048
                                        }
2049
                                    }
2050
                                }
2051
                                else
2052
                                {
2053
                                    Dispatcher.Invoke(() => pbTopVoltage.Foreground = new SolidColorBrush(Color.FromArgb(255, 107, 195, 123)));
2054
                                    if (stbVoltageCritAnim != null && _bCritAnimVoltActive)
2055
                                    {
2056
                                        Dispatcher.Invoke(() => stbVoltageCritAnim.Stop());
2057
                                        _bCritAnimVoltActive = false;
2058
                                    }
2059
                                    _bCritVoiceVoltActive = false;
2060
                                    _bWarnVoiceVoltActive = false;
2061
                                    _iVoltJitter = 0;
2062
                                }
2063
                                break;
2064
                            case 8: // Current
2065
                                Dispatcher.Invoke(() => tbCur.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 A"));
2066
                                Dispatcher.Invoke(() => tbTopCurrent.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 A"));
2067
                                break;
2068
                            case 10: //heading
2069
                                Dispatcher.Invoke((Action)(() => tbHeading.Text = sAnalogData[index] + "°"));
2070
                                if (!_Simulate) //use NavData for simulation
2071
                                {
2072
                                    Dispatcher.Invoke(() => ArtHor.rotate = iAnalogData[index]);
2073
                                    Dispatcher.Invoke(() => ((CustomMarkerCopter)(copter.Shape)).rotate = iAnalogData[index]);
2074
                                }
2075
                                break;
2076
                            case 12: // SPI error
2077
                                Dispatcher.Invoke((Action)(() => tbSPI.Text = sAnalogData[index]));
2078
                                break;
2079
                            case 14: //i2c error
2080
                                Dispatcher.Invoke((Action)(() => tbI2C.Text = sAnalogData[index]));
2081
                                break;
2082
                            case 20: //Earthmagnet field
2083
                                Dispatcher.Invoke((Action)(() => tbMagF.Text = sAnalogData[index] + "%"));
2084
                                Dispatcher.Invoke((Action)(() => tbTopEarthMag.Text = sAnalogData[index] + "%"));
2085
 
2086
                                if (Math.Abs(100 - iAnalogData[index]) < _iThresholdMagField)
2087
                                {
2088
                                    Dispatcher.Invoke(() => imageEarthMag.Source = new BitmapImage(new Uri("Images/EarthMag.png", UriKind.Relative)));
2089
                                    _iMagneticFieldJitter = 0; _bVoiceMagneticFieldActive = false;
2090
                                    if (stbMagneticFieldAnim != null && _bAnimMagneticFieldActive)
2091
                                    {
2092
                                        Dispatcher.Invoke(() => stbMagneticFieldAnim.Stop());
2093
                                        _bAnimMagneticFieldActive = false;
2094
                                    }
2095
                                }
2096
                                else
2097
                                {
2098
                                    Dispatcher.Invoke(() => imageEarthMag.Source = new BitmapImage(new Uri("Images/EarthMag_R.png", UriKind.Relative)));
2099
                                    if (_iMagneticFieldLast >= Math.Abs(100 - iAnalogData[index]))
2100
                                    {
2101
                                        if (_iMagneticFieldJitter < 20)
2102
                                            _iMagneticFieldJitter++;
2103
                                    }
2104
                                    else
2105
                                    {
2106
                                        _iMagneticFieldJitter = 0;
2107
                                        _iMagneticFieldLast = Math.Abs(100 - iAnalogData[index]);
2108
                                    }
2109
                                    if (_iMagneticFieldJitter == 20)
2110
                                    {
2111
                                        if (stbMagneticFieldAnim != null && !_bAnimMagneticFieldActive)
2112
                                        {
2113
                                            Dispatcher.Invoke(() => stbMagneticFieldAnim.Begin());
2114
                                            _bAnimMagneticFieldActive = true;
2115
                                        }
2116
                                        if (_bVoiceMagneticFieldPlay && !_bVoiceMagneticFieldActive)
2117
                                        {
2118
                                            ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\MagneticField.mp3");
2119
                                            //Thread t = new Thread(() => _mediaPlayer("Voice\\MagneticField.mp3"));
2120
                                            //t.Start();
2121
                                            _bVoiceMagneticFieldActive = true;
2122
                                        }
2123
                                    }
2124
                                }
2125
                                break;
2126
                            case 21: //GroundSpeed
2127
                                Dispatcher.Invoke((Action)(() => tbSpeed.Text = ((double)iAnalogData[index] / (double)100).ToString("0.00 m/s")));
2128
                                if (!_Simulate)
2129
                                    Dispatcher.Invoke((Action)(() => tbTopSpeed.Text = ((double)iAnalogData[index] / (double)100).ToString("0.00 m/s")));
2130
                                break;
2131
 
2132
                            ///**********   needs testing --> not sure what position this is  ***************
2133
                            case 28: //Distance East from saved home position -> calculate distance with distance N + height
2134
                                dTemp = Math.Pow((double)iAnalogData[index], 2) + Math.Pow((double)iAnalogData[index - 1], 2);
2135
                                dTemp = Math.Sqrt(dTemp) / (double)10; //'flat' distance from HP with N/E
2136
                                                                       //  lblNCDist.Invoke((Action)(() => lblNCDist.Text = dTemp.ToString("0.00")));
2137
                                dTemp = Math.Pow(dTemp, 2) + Math.Pow(((double)iAnalogData[4] / (double)10), 2); //adding 'height' into calculation
2138
                                dTemp = Math.Sqrt(dTemp) / (double)10;
2139
                                //     Dispatcher.Invoke((Action)(() => tbTopDistanceHP.Text = dTemp.ToString("0.0 m")));
2140
                                Dispatcher.Invoke((Action)(() => tbHP1.Text = dTemp.ToString("0.0 m")));
2141
                                break;
2142
 
2143
                            case 31: //Sats used
2144
                                Dispatcher.Invoke((Action)(() => tbSats.Text = sAnalogData[index]));
2145
                                // Dispatcher.Invoke((Action)(() => tbTopSats.Text = sAnalogData[index]));                                   
2146
                                break;
2147
                        }
2148
                    }
2149
                    index++;
2150
                }
2151
            }
2152
            else
2153
                Debug.Print("wrong data-length (66): " + data.Length.ToString());
2154
        }
2155
        /// <summary>
2156
        /// Version string 'V'
2157
        /// </summary>
2158
        /// <param name="adr">adress of the active controller (1-FC, 2-NC)</param>
2159
        /// <param name="data">the received byte array to process</param>
2160
        void _processVersion(byte adr, byte[] data)
2161
        {
2162
            if (data.Length == 12)
2163
            {
2164
                if (!check_HWError)
2165
                {
2166
                    string[] sVersionStruct = new string[10] { "SWMajor: ", "SWMinor: ", "ProtoMajor: ", "LabelTextCRC: ", "SWPatch: ", "HardwareError 1: ", "HardwareError 2: ", "HWMajor: ", "BL_Firmware: ", "Flags: " };
2167
                    string sVersion = "";
2168
                    //sbyte[] signed = Array.ConvertAll(data, b => unchecked((sbyte)b));
2169
                    Log(LogMsgType.Warning, (adr == 1 ? "FC-" : "NC-") + "Version: ");
2170
                    sVersion = "HW V" + (data[7] / 10).ToString() + "." + (data[7] % 10).ToString();
2171
                    Log(LogMsgType.Incoming, sVersion);
2172
                    sVersion = "SW V" + (data[0]).ToString() + "." + (data[1]).ToString() + ((char)(data[4] + 'a')).ToString();
2173
                    Log(LogMsgType.Incoming, sVersion);
2174
                    Log(LogMsgType.Incoming, "BL-Firmware: V" + (data[8] / 100).ToString() + "." + (data[8] % 100).ToString());
2175
                }
2176
                if (data[5] > 0) //error0 
2177
                {
2178
                    if (adr == 1)
2179
                        ErrorLog(LogMsgType.Error, " FC - HW-Error " + data[5].ToString() + ": " + ((FC_HWError0)data[5]).ToString(), "", "");
2180
                    if (adr == 2)
2181
                        ErrorLog(LogMsgType.Error, " NC - HW-Error " + data[5].ToString() + ": " + ((NC_HWError0)data[5]).ToString(), "", "");
2182
                }
2183
                if (data[6] > 0) //error1 
2184
                {
2185
                    if (adr == 1)
2186
                        ErrorLog(LogMsgType.Error, " FC - HW-Error " + data[6].ToString() + ": " + ((FC_HWError1)data[6]).ToString(), "", "");
2187
                    if (adr == 2)
2188
                        ErrorLog(LogMsgType.Error, " NC - Unknown HW-ERROR: " + data[6].ToString(), "", ""); //@moment NC has only one error field
2189
                }
2190
                //if ((data[5] + data[6] == 0) && _bErrorLog)
2191
                //    _clearErrorLog(adr == 1 ? "FC - HW-Error" : "NC - HW-Error");
2192
 
2193
            }
2194
            check_HWError = false;
2195
        }
2196
 
2197
        void _processLicense(byte[] data)
2198
        {
2199
            if (data.Length > 480)
2200
            {
2201
                Dispatcher.Invoke(() => {
2202
                    tbDataLicenseUser.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 1, 127));
2203
                    tbDataLicenseMail.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 129, 127));
2204
                    tbDataLicenseFeature.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 257, 127));
2205
                    tbDataLicenseExpire.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 385, 11));
2206
                    tbDataLicenseLicense.Text = new string(ASCIIEncoding.ASCII.GetChars(data, 397, 16));
2207
                });
2208
            }
2209
        }
2210
        /// <summary>
2211
        /// BL-Ctrl data 'K'
2212
        /// for FC you have to use a customized firmware
2213
        /// </summary>
2214
        /// <param name="data">the received byte array to process</param>
2215
        void _processBLCtrl(byte[] data)
2216
        {
2217
            if (data.Length % 6 == 0) //data.Length up to 96 (16 motors x 6 byte data) --> new datastruct in FC -> not standard!
2218
            {
2219
                bool bAvailable = false;
2220
                for (int i = 0; i < data.Length && data[i] < _iMotors; i += 6) // data[i] < _iMotors -- only show set number of motors (12 max @ moment)
2221
                {
2222
 
2223
                    if ((data[i + 4] & 128) == 128) //Status bit at pos 7 = 128 dec -- if true, motor is available
2224
                        bAvailable = true;
2225
                    else
2226
                        bAvailable = false;
2227
 
2228
                    if (data[i] < _iMotors)
2229
                    {
2230
                        if (bAvailable)
2231
                        {
2232
                            dtMotors.Rows[data[i]].SetField(1, ((double)data[i + 1] / (double)10).ToString("0.0 A"));
2233
                            dtMotors.Rows[data[i]].SetField(2, data[i + 2].ToString("0 °C"));
2234
                        }
2235
                        else
2236
                        {
2237
                            dtMotors.Rows[data[i]].SetField(1, "NA");
2238
                            dtMotors.Rows[data[i]].SetField(2, "NA");
2239
                        }
2240
                    }
2241
                    //if (data[i] > 3 && data[i] < 8)
2242
                    //{
2243
                    //    if (bAvailable)
2244
                    //    {
2245
                    //        dtMotors2.Rows[data[i] - 4].SetField(1, ((double)data[i + 1] / (double)10).ToString("0.0 A"));
2246
                    //        dtMotors2.Rows[data[i] - 4].SetField(2, data[i + 2].ToString("0 °C"));
2247
                    //    }
2248
                    //    else
2249
                    //    {
2250
                    //        dtMotors2.Rows[data[i] - 4].SetField(1, "NA");
2251
                    //        dtMotors2.Rows[data[i] - 4].SetField(2, "NA");
2252
                    //    }
2253
                    //}
2254
                }
2255
            }
2256
        }
2257
        /// <summary>
2258
        /// Navi-Ctrl data 'O'
2259
        /// GPS-Position, capacatiy, flying time...
2260
        /// </summary>
2261
        /// <param name="data">the received byte array to process</param>
2262
 
2263
 
2264
        byte OSDSTATUSFLAGS1 = 0;
2265
        byte OSDSTATUSFLAGS2 = 0;
2266
        void _processNCDataV2(byte[] data)
2267
        {
2268
            if ((int)data[0] < 17)
2269
            {
2270
                int i_32, i_16, iVal;
2271
                double d;
2272
                OSD_Base_Data_t osd = new OSD_Base_Data_t(data);
2273
                OSDSTATUSFLAGS1 = osd.OSDSTATUSFLAGS1();
2274
                Dispatcher.Invoke(() => { drGPX[2] = osd.Pos().Lng; });
2275
                Dispatcher.Invoke(() => { drGPX[1] = osd.Pos().Lat; });
2276
                Dispatcher.Invoke(() => { drGPX[4] = DateTime.UtcNow.ToString("u", System.Globalization.CultureInfo.InvariantCulture); }); //2011-01-14T01:59:01Z });
2277
                Dispatcher.Invoke((Action)(() => tbNCGrSpeed.Text = osd.Speed().ToString("0.0 m/s")));
2278
                if (_Simulate)
2279
                    Dispatcher.Invoke((Action)(() => tbTopSpeed.Text = osd.Speed().ToString("0.0 m/s")));
2280
 
2281
                switch ((int)data[0])
2282
                {
2283
                    case 10:
2284
                        char[] c = Encoding.ASCII.GetChars(new byte[] { data[13] });
2285
                        Dispatcher.Invoke((Action)(() => tbCamCtrl.Text = c[0].ToString()));
2286
                        break;
2287
                    case 11:
2288
                        OSDSTATUSFLAGS2 = osd.OSDSTATUSFLAGS2();
2289
                        //---------------NC-Flags--------------------------
2290
                        Dispatcher.Invoke((Action)(() => NC1_2.Background = ((data[14] & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_PH                                 0x02
2291
                        Dispatcher.Invoke((Action)(() => NC1_3.Background = ((data[14] & 4) == 4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_CH                                 0x04
2292
                        Dispatcher.Invoke((Action)(() => NC1_4.Background = ((data[14] & 8) == 8) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_RANGE_LIMIT                           0x08
2293
                        Dispatcher.Invoke((Action)(() => NC1_5.Background = ((data[14] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_NOSERIALLINK                                0x10
2294
                        Dispatcher.Invoke((Action)(() => NC1_6.Background = ((data[14] & 32) == 32) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_TARGET_REACHED                           0x20
2295
                        Dispatcher.Invoke((Action)(() => NC1_7.Background = ((data[14] & 64) == 64) ? new SolidColorBrush(Colors.DodgerBlue) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_MANUAL_CONTROL                              0x40
2296
                        Dispatcher.Invoke((Action)(() => NC1_8.Background = ((data[14] & 128) == 128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_GPS_OK                                 0x80
2297
 
2298
                        Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Text = ((data[14] & 4) == 4) ? "CH" : "PH"));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
2299
                        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
2300
                        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
2301
                        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
2302
 
2303
                        //--------------- NC Error ------------------------
2304
                        Dispatcher.Invoke((Action)(() => tbNCErr.Text = data[16].ToString()));  //NC Errornumber
2305
                        if (data[16] > 0)
2306
                            _readNCError();
2307
                        if (data[16] > 0 & data[16] < 44)
2308
                            ErrorLog(LogMsgType.Error, " NC Error [" + data[16].ToString() + "]: ", NC_Error_Link[data[16]], NC_Error[data[16]]);
2309
 
2310
                        break;
2311
                    case 12:
2312
                        //--------------- RC quality ------------------------
2313
                        Dispatcher.Invoke((Action)(() => tbRCQ.Text = data[23].ToString()));
2314
                        Dispatcher.Invoke((Action)(() => tbTopRC.Text = data[23].ToString()));
2315
 
2316
                        if (data[23] > _iThresholdRC)
2317
                        {
2318
                            _iRCLevelJitter = 0; _bVoiceRCLevelActive = false;
2319
                            if (stbRCLevelAnim != null && _bAnimRCLevelActive)
2320
                            {
2321
                                Dispatcher.Invoke(() => stbRCLevelAnim.Stop());
2322
                                _bAnimRCLevelActive = false;
2323
                            }
2324
                        }
2325
                        else
2326
                        {
2327
                            if (_iRCLevelJitter < 20) _iRCLevelJitter++;
2328
                            if (_iRCLevelJitter == 20)
2329
                            {
2330
                                if (stbRCLevelAnim != null && !_bAnimRCLevelActive)
2331
                                {
2332
                                    Dispatcher.Invoke(() => stbRCLevelAnim.Begin());
2333
                                    _bAnimRCLevelActive = true;
2334
                                }
2335
                                if (_bVoiceRCLevelPlay && !_bVoiceRCLevelActive)
2336
                                {
2337
                                    _bVoiceRCLevelActive = true;
2338
                                    ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\MagneticField.mp3");
2339
                                    //Thread th = new Thread(() => _mediaPlayer("Voice\\RCLevel.mp3"));
2340
                                    //th.Start();
2341
                                }
2342
                                _iRCLevelJitter++;
2343
                            }
2344
                        }
2345
                        break;
2346
                    case 13:
2347
                        //-------------------------Waypoint max range (by license)------------------------------
2348
                        i_32 = data[24];
2349
                        iVal = i_32 << 8;
2350
                        iVal += data[23];
2351
 
2352
                        if (dWPMaxRange != iVal)
2353
                        {
2354
                            dWPMaxRange = iVal;
2355
                            if (home != null && checkBoxShowWPMaxRange.IsChecked == true)
2356
                            {
2357
                                if (cWPBound != null && cWPBound.Tag != null)
2358
                                    MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
2359
 
2360
                                createCircle(home.Position, dWPMaxRange);
2361
                                Dispatcher.Invoke(() =>
2362
                                {
2363
                                    if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
2364
                                    {
2365
                                        string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
2366
                                        cWPBound.setColor(s);
2367
                                    }
2368
                                });
2369
                            }
2370
                            Dispatcher.Invoke((Action)(() => tbWPMaxRange.Text = iVal.ToString() + " m"));
2371
                        }
2372
                        //--------------- LiPoCell count ------------------------
2373
                        Dispatcher.Invoke((Action)(() => tbLiPoCells.Text = data[25].ToString()));
2374
                        Dispatcher.Invoke((Action)(() => {
2375
                            if (_bLiPoAutoDetect == true)
2376
                            {
2377
                                if(data[25] > 2 && data[25] < 7 && _LipoCells != data[25])
2378
                                {
2379
                                    cBoxLiPoCells.SelectedIndex = data[25] - 3;
2380
                                    _LipoCells = data[25];
2381
                                    _LipoMinMax();
2382
                                }
2383
                            }
2384
                        }));
2385
 
2386
                        break;
2387
 
2388
                    case 14:
2389
                        //--------------- Flying time ------------------------
2390
                        i_16 = data[14];
2391
                        i_16 = (Int16)(i_16 << 8);
2392
                        iVal = data[13] + i_16;
2393
                        TimeSpan t = TimeSpan.FromSeconds(iVal);
2394
                        string Text = t.Hours.ToString("D2") + ":" + t.Minutes.ToString("D2") + ":" + t.Seconds.ToString("D2");
2395
                        Dispatcher.Invoke((Action)(() => tbFTime.Text = Text.ToString()));
2396
                        Dispatcher.Invoke((Action)(() => tbTopFTime.Text = Text.ToString()));
2397
 
2398
                        //--------------------------------Distance HP------------------------------------
2399
                        i_16 = data[16];
2400
                        i_16 = (Int16)(i_16 << 8);
2401
                        iVal = data[15] + i_16;
2402
                        Dispatcher.Invoke((Action)(() => tbHP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
2403
 
2404
                        //--------------------------Distance to next WP--------------------------------
2405
                        i_16 = data[19];
2406
                        i_16 = (Int16)(i_16 << 8);
2407
                        iVal = data[18] + i_16;
2408
                        Dispatcher.Invoke((Action)(() => tbWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
2409
                        Dispatcher.Invoke((Action)(() => lblWPRouteDistanceWP.Content = ((double)iVal / (double)10).ToString("0.0 m")));
2410
                        Dispatcher.Invoke((Action)(() => tbWPStatusDistanceWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
2411
 
2412
                        //-------------------Satellites----------------------------------
2413
                        Dispatcher.Invoke((Action)(() => tbTopSats.Text = data[23].ToString()));
2414
 
2415
                        if (data[23] > 4)//if more than 4 sats in use . otherwise the map would jump and scroll insane at beginning
2416
                        {
2417
                            _bSatFix = true; _iSatsJitter = 0; _bVoiceSatFixActive = false;
2418
                            if (_bAutoHome && !_bFirstSatFix)
2419
                            {
2420
                                if (_iFirstSatFix < 3)
2421
                                    _iFirstSatFix++;
2422
                                else
2423
                                {
2424
                                    _bFirstSatFix = true;
2425
                                    Dispatcher.Invoke(() => _setHomePos());
2426
                                }
2427
                            }
2428
                            if (stbSatFixLostAnim != null && _bAnimSatFixActive)
2429
                            {
2430
                                Dispatcher.Invoke(() => stbSatFixLostAnim.Stop());
2431
                                _bAnimSatFixActive = false;
2432
                            }
2433
                            if (!_bFollowCopter)
2434
                            {
2435
                                _setCopterData(osd.Pos());
2436
                                if (!MainMap.ViewArea.Contains(osd.Pos()))
2437
                                    Dispatcher.Invoke(() => MainMap.Position = osd.Pos());
2438
 
2439
                            }
2440
                            else
2441
                                Dispatcher.Invoke(() => MainMap.Position = osd.Pos());
2442
                        }
2443
                        else
2444
                        {
2445
                            if (_bSatFix)
2446
                            {
2447
                                if (data[23] == _iSatsLast)
2448
                                {
2449
                                    if (_iSatsJitter < 20) _iSatsJitter++;
2450
                                }
2451
                                else
2452
                                {
2453
                                    _iSatsJitter = 0;
2454
                                    _iSatsLast = data[23];
2455
                                }
2456
 
2457
                                if (_iSatsJitter == 20)
2458
                                {
2459
                                    if (stbSatFixLostAnim != null && !_bAnimSatFixActive)
2460
                                    {
2461
                                        Dispatcher.Invoke(() => stbSatFixLostAnim.Begin());
2462
                                        _bAnimSatFixActive = true;
2463
                                    }
2464
                                    if (_bVoiceSatFixPlay && !_bVoiceSatFixActive)
2465
                                    {
2466
                                        _bVoiceSatFixActive = true;
2467
                                        ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\SatFixLost.mp3");
2468
                                        //Thread th = new Thread(() => _mediaPlayer("Voice\\SatFixLost.mp3"));
2469
                                        //th.Start();
2470
                                    }
2471
 
2472
                                    _bSatFix = false;
2473
                                }
2474
                            }
2475
                        }
2476
 
2477
                        break;
2478
 
2479
                    case 15:
2480
                        //--------------------------------Waypoint index------------------------------------
2481
                        Dispatcher.Invoke((Action)(() => tbWPIndex.Text = data[13].ToString()));
2482
                        Dispatcher.Invoke((Action)(() => lblWPIndexNC.Content = data[13].ToString()));
2483
                        Dispatcher.Invoke((Action)(() => lblWPStatusIndexNC.Content = data[13].ToString()));
2484
                        if (data[13] > 0 && _wpIndex != data[13] - 1 && wpList.Count > data[13] - 1)
2485
                        {
2486
                            _setActiveWP(data[13] - 1);
2487
                            if ((OSDSTATUSFLAGS2 & 2) == 2)
2488
                                Dispatcher.Invoke(() =>
2489
                                {
2490
                                    DataGridRow row;
2491
                                    if (_wpIndex > -1)
2492
                                    {
2493
                                        row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
2494
                                        row.Background = new SolidColorBrush(Colors.Transparent);
2495
                                        row.BorderBrush = new SolidColorBrush(Colors.Transparent);
2496
                                        row.BorderThickness = new Thickness(0);
2497
                                    }
2498
 
2499
                                    _wpIndex = data[13] - 1;
2500
                                    row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
2501
                                    row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 255, 100));
2502
                                    row.BorderBrush = new SolidColorBrush(Colors.SpringGreen);
2503
                                    row.BorderThickness = new Thickness(2);
2504
                                    dgvWP.UpdateLayout();
2505
                                });
2506
                            _wpIndex = data[13] - 1;
2507
                        }
2508
                        else
2509
                        {
2510
                            if ((data[13] == 0 || wpList.Count == 0) & MainMap.Markers.Contains(wpActiveMarker))
2511
                            {
2512
                                Dispatcher.Invoke(() => MainMap.Markers.Remove(wpActiveMarker));
2513
                                Dispatcher.Invoke(() =>
2514
                                {
2515
                                    DataGridRow row;
2516
                                    if (_wpIndex > -1 && data[13] == 0 && wpList.Count > _wpIndex)
2517
                                    {
2518
                                        row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
2519
                                        row.Background = new SolidColorBrush(Colors.Transparent);
2520
                                        row.BorderBrush = new SolidColorBrush(Colors.Transparent);
2521
                                        row.BorderThickness = new Thickness(0);
2522
                                        _wpIndex = -1;
2523
                                    }
2524
                                });
2525
 
2526
                            }
2527
                        }
2528
                        //----------------Waypoints count----------------------
2529
                        Dispatcher.Invoke((Action)(() => tbWPCount.Text = data[14].ToString())); //Waypoints count
2530
                        Dispatcher.Invoke((Action)(() => lblWPCountNC.Content = data[14].ToString())); //Waypoints count
2531
                        Dispatcher.Invoke((Action)(() => lblWPStatusCountNC.Content = data[14].ToString())); //Waypoints count
2532
                        _wpCount = data[14];
2533
                        if(_wpCount > dtWaypoints.Rows.Count)
2534
                        {
2535
                            Log(LogMsgType.Warning, "The copter reports more waypoints than there are in the local list!");
2536
                        }
2537
 
2538
                        //---------------------------------Target hold time------------------------------
2539
                        Dispatcher.Invoke((Action)(() => lblWPHoldTime.Content = data[15].ToString() + " s"));
2540
                        Dispatcher.Invoke((Action)(() => tbWPStatusHoldTime.Text = data[15].ToString() + " s"));
2541
 
2542
                        break;
2543
 
2544
                    case 16:
2545
                        //--------------- Capacity used ------------------------
2546
                        i_16 = data[18];
2547
                        i_16 = (Int16)(i_16 << 8);
2548
                        iVal = data[17] + i_16;
2549
                        Dispatcher.Invoke((Action)(() => tbCapacity.Text = iVal.ToString() + " mAh"));
2550
                        Dispatcher.Invoke((Action)(() => tbTopCapacity.Text = iVal.ToString() + " mAh"));
2551
 
2552
                        //--------------- Heading compass ------------------------
2553
                        i_16 = data[21];
2554
                        iVal = 2 * i_16;
2555
                        Dispatcher.Invoke((Action)(() => tbHeadingCompass.Text = iVal.ToString() + " °"));
2556
                        if (_Simulate)
2557
                        {
2558
                            Dispatcher.Invoke(() => ArtHor.rotate = iVal);
2559
                            Dispatcher.Invoke(() => ((CustomMarkerCopter)(copter.Shape)).rotate = iVal);
2560
                        }
2561
 
2562
                        break;
2563
                    case 17:
2564
 
2565
                        break;
2566
                    case 18:
2567
 
2568
                        break;
2569
                    default:
2570
                        break;
2571
                }
2572
                //--------------------------------------------------------------------------------
2573
                //-----------------------------FC Status Flags-------------------------------
2574
                //--------------------------------------------------------------------------------
2575
                Dispatcher.Invoke((Action)(() => FC1_1.Background = ((OSDSTATUSFLAGS2 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN                                 0x01
2576
                Dispatcher.Invoke((Action)(() => FC1_2.Background = ((OSDSTATUSFLAGS2 & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_FLY                                       0x02
2577
                Dispatcher.Invoke((Action)(() => FC1_3.Background = ((OSDSTATUSFLAGS1 & 4) == 4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_CALIBRATE                                 0x04
2578
                Dispatcher.Invoke((Action)(() => FC1_4.Background = ((OSDSTATUSFLAGS2 & 8) == 8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_START                                     0x08
2579
                Dispatcher.Invoke((Action)(() => FC1_5.Background = ((OSDSTATUSFLAGS2 & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING          0x10
2580
                Dispatcher.Invoke((Action)(() => FC1_6.Background = ((OSDSTATUSFLAGS1 & 32) == 32) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_LOWBAT                                 0x20
2581
 
2582
                Dispatcher.Invoke((Action)(() => FC2_1.Background = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE                         0x01
2583
                Dispatcher.Invoke((Action)(() => FC2_2.Background = ((OSDSTATUSFLAGS1 & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL                 0x02
2584
                Dispatcher.Invoke((Action)(() => FC2_3.Background = ((OSDSTATUSFLAGS2 & 4) == 4) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_RC_FAILSAVE_ACTIVE                  0x04
2585
                Dispatcher.Invoke((Action)(() => FC2_4.Background = ((OSDSTATUSFLAGS1 & 8) == 8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT1_ACTIVE                              0x08
2586
                Dispatcher.Invoke((Action)(() => FC2_5.Background = ((OSDSTATUSFLAGS1 & 16) == 16) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT2_ACTIVE                            0x10
2587
                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
2588
                Dispatcher.Invoke((Action)(() => FC2_7.Background = ((OSDSTATUSFLAGS2 & 64) == 64) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_STARTING                  0x40
2589
                Dispatcher.Invoke((Action)(() => FC2_8.Background = ((OSDSTATUSFLAGS2 & 128) == 128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_LANDING                 0x80
2590
 
2591
                //Sidebar StatusSymbols
2592
                Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.Background = ((OSDSTATUSFLAGS2 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN                                         0x01
2593
                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
2594
                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
2595
 
2596
                Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Background = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE                                 0x01
2597
                Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Foreground = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_CAREFREE                     0x01
2598
                Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.BorderBrush = ((OSDSTATUSFLAGS1 & 1) == 1) ? new SolidColorBrush(Colors.White) : new SolidColorBrush(Color.FromArgb(255, 211, 210, 210))));// FC_STATUS2_CAREFREE                    0x01
2599
 
2600
                Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.Background = ((OSDSTATUSFLAGS2 & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING        0x10
2601
                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
2602
                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
2603
 
2604
                Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.Background = ((OSDSTATUSFLAGS1 & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL                             0x02
2605
                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
2606
                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
2607
 
2608
                _bAirborne = (OSDSTATUSFLAGS2 & 2) == 2 ? true : false;
2609
            }
2610
        }
2611
        public class OSD_Base_Data_t
2612
        {
2613
            byte[] data;
2614
 
2615
            public OSD_Base_Data_t(byte [] _data)
2616
            {
2617
                data = _data;
2618
            }
2619
 
2620
            public PointLatLng Pos()
2621
            {
2622
                PointLatLng p = new PointLatLng();
2623
                int i_32, iVal;
2624
                double d;
2625
 
2626
                i_32 = data[4];
2627
                iVal = i_32 << 24;
2628
                i_32 = data[3];
2629
                iVal += i_32 << 16;
2630
                i_32 = data[2];
2631
                iVal += i_32 << 8;
2632
                iVal += data[1];
2633
                d = (double)iVal / Math.Pow(10, 7);
2634
                p.Lng = d;
2635
 
2636
                i_32 = data[8];
2637
                iVal = i_32 << 24;
2638
                i_32 = data[7];
2639
                iVal += i_32 << 16;
2640
                i_32 = data[6];
2641
                iVal += i_32 << 8;
2642
                iVal += data[5];
2643
                d = (double)iVal / Math.Pow(10, 7);
2644
                p.Lat = d;
2645
 
2646
                return p;
2647
 
2648
            }
2649
 
2650
            public int Height()
2651
            {
2652
                int i_32, iVal;
2653
                i_32 = data[10];
2654
                iVal = i_32 << 8;
2655
                iVal += data[9];
2656
 
2657
                return iVal;
2658
            }
2659
 
2660
            public double Speed()
2661
            {
2662
                if (data.Length > 11)
2663
                    return (double)data[11]/10;
2664
                else return 0;
2665
            }
2666
 
2667
            public byte OSDSTATUSFLAGS1()
2668
            {
2669
                if (data.Length > 12)
2670
                    return data[12];
2671
                else return 0;
2672
            }
2673
            public byte OSDSTATUSFLAGS2()
2674
            {
2675
                if (data.Length > 13)
2676
                    return data[13];
2677
                else return 0;
2678
            }
2679
        }
2680
        void _processNCData(byte[] data)
2681
        {
2682
            int i_32, i_16, iVal;
2683
            double d;
2684
 
2685
            //----------------------------POSITION------------------------------------
2686
            i_32 = data[4];
2687
            iVal = i_32 << 24;
2688
            i_32 = data[3];
2689
            iVal += i_32 << 16;
2690
            i_32 = data[2];
2691
            iVal += i_32 << 8;
2692
            iVal += data[1];
2693
            d = (double)iVal / Math.Pow(10, 7);
2694
            Dispatcher.Invoke(() => { drGPX[2] = d; });
2695
 
2696
            PointLatLng p = new PointLatLng();
2697
 
2698
            p.Lng = d;
2699
          //  lblNCGPSLong.Invoke((Action)(() => lblNCGPSLong.Text = d.ToString("0.######°"))); //GPS-Position: Longitude in decimal degree
2700
            //lblNCGPSLong.Invoke((Action)(() => lblNCGPSLong.Text = _convertDegree(d))); //GPS-Position: Longitude in minutes, seconds
2701
 
2702
            i_32 = data[8];
2703
            iVal = i_32 << 24;
2704
            i_32 = data[7];
2705
            iVal += i_32 << 16;
2706
            i_32 = data[6];
2707
            iVal += i_32 << 8;
2708
            iVal += data[5];
2709
            d = (double)iVal / Math.Pow(10, 7);
2710
            Dispatcher.Invoke(() => { drGPX[1] = d; });
2711
            Dispatcher.Invoke(() => { drGPX[4] = DateTime.UtcNow.ToString("u", System.Globalization.CultureInfo.InvariantCulture); }); //2011-01-14T01:59:01Z });
2712
            p.Lat = d;
2713
 
2714
            //---------------------------SATS-------------------------------------------------
2715
            if (data[50] > 4)//if more than 4 sats in use . otherwise the map would jump and scroll insane at beginning
2716
            {
2717
                _bSatFix = true; _iSatsJitter = 0; _bVoiceSatFixActive = false;
2718
                if(_bAutoHome && !_bFirstSatFix)
2719
                {
2720
                    if (_iFirstSatFix < 3)
2721
                        _iFirstSatFix++;
2722
                    else
2723
                    {
2724
                        _bFirstSatFix = true;
2725
                        Dispatcher.Invoke(() => _setHomePos());
2726
                    }
2727
                }
2728
                if (stbSatFixLostAnim != null && _bAnimSatFixActive)
2729
                {
2730
                    Dispatcher.Invoke(() => stbSatFixLostAnim.Stop());
2731
                    _bAnimSatFixActive = false;
2732
                }
2733
                if (!_bFollowCopter)
2734
                {
2735
                    _setCopterData(p);
2736
                    if (!MainMap.ViewArea.Contains(p))
2737
                        Dispatcher.Invoke(() => MainMap.Position = p);
2738
 
2739
                }
2740
                else
2741
                    Dispatcher.Invoke(() => MainMap.Position = p);
2742
            }
2743
            else
2744
            {
2745
                if(_bSatFix)
2746
                {
2747
                    if (data[50] == _iSatsLast)
2748
                    {
2749
                        if (_iSatsJitter < 20) _iSatsJitter++;
2750
                    }
2751
                    else
2752
                    {
2753
                        _iSatsJitter = 0;
2754
                        _iSatsLast = data[50];
2755
                    }
2756
 
2757
                    if (_iSatsJitter == 20)
2758
                    {
2759
                        if (stbSatFixLostAnim != null && !_bAnimSatFixActive)
2760
                        {
2761
                            Dispatcher.Invoke(() => stbSatFixLostAnim.Begin());
2762
                            _bAnimSatFixActive = true;
2763
                        }
2764
                        if (_bVoiceSatFixPlay && !_bVoiceSatFixActive)
2765
                        {
2766
                            _bVoiceSatFixActive = true;
2767
                            ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\SatFixLost.mp3");
2768
                            //Thread th = new Thread(() => _mediaPlayer("Voice\\SatFixLost.mp3"));
2769
                            //th.Start();
2770
                        }
2771
 
2772
                        _bSatFix = false;
2773
                    }
2774
                }
2775
            }
2776
 
2777
            //--------------------------Distance to next WP--------------------------------
2778
            i_16 = data[28];
2779
            i_16 = (Int16)(i_16 << 8);
2780
            iVal = data[27] + i_16;
2781
            Dispatcher.Invoke((Action)(() => tbWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
2782
            Dispatcher.Invoke((Action)(() => lblWPRouteDistanceWP.Content = ((double)iVal / (double)10).ToString("0.0 m")));
2783
            Dispatcher.Invoke((Action)(() => tbWPStatusDistanceWP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
2784
 
2785
            //-------------------------Distance to HP set by GPS on----------------------------------
2786
            i_16 = data[45];
2787
            i_16 = (Int16)(i_16 << 8);
2788
            iVal = data[44] + i_16;
2789
            Dispatcher.Invoke((Action)(() => tbHP.Text = ((double)iVal / (double)10).ToString("0.0 m")));
2790
 
2791
            //--------------------------------Waypoint index------------------------------------
2792
            Dispatcher.Invoke((Action)(() => tbWPIndex.Text = data[48].ToString()));
2793
            Dispatcher.Invoke((Action)(() => lblWPIndexNC.Content = data[48].ToString()));
2794
            Dispatcher.Invoke((Action)(() => lblWPStatusIndexNC.Content = data[48].ToString()));
2795
            if(data[48] > 0 && _wpIndex != data[48] -1 && wpList.Count >= data[48] -1)
2796
            {
2797
                _setActiveWP(data[48]- 1);
2798
                if((data[67] & 2) == 2)
2799
                    Dispatcher.Invoke(() => {
2800
                        DataGridRow row;
2801
                        if (_wpIndex > -1)
2802
                        {
2803
                            row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
2804
                            row.Background = new SolidColorBrush(Colors.Transparent);
2805
                            row.BorderBrush = new SolidColorBrush(Colors.Transparent);
2806
                            row.BorderThickness = new Thickness(0);
2807
                        }
2808
 
2809
                        _wpIndex = data[48] - 1;
2810
                        row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
2811
                        row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 255, 100));
2812
                        row.BorderBrush = new SolidColorBrush(Colors.SpringGreen);
2813
                        row.BorderThickness = new Thickness(2);
2814
                        dgvWP.UpdateLayout();
2815
                    });
2816
                _wpIndex = data[48]- 1;
2817
            }
2818
            else
2819
            {
2820
                if ((data[48] == 0 || wpList.Count == 0) & MainMap.Markers.Contains(wpActiveMarker))
2821
                {
2822
                    Dispatcher.Invoke(() => MainMap.Markers.Remove(wpActiveMarker));
2823
                    Dispatcher.Invoke(() =>
2824
                    {
2825
                        DataGridRow row;
2826
                        if (_wpIndex > -1 && data[48] == 0 && wpList.Count > _wpIndex)
2827
                        {
2828
                            row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(wpOffset[_wpIndex]);
2829
                            row.Background = new SolidColorBrush(Colors.Transparent);
2830
                            row.BorderBrush = new SolidColorBrush(Colors.Transparent);
2831
                            row.BorderThickness = new Thickness(0);
2832
                            _wpIndex = -1;
2833
                        }
2834
                    });
2835
 
2836
                }
2837
            }
2838
            //----------------Waypoints count----------------------
2839
            Dispatcher.Invoke((Action)(() => tbWPCount.Text = data[49].ToString())); //Waypoints count
2840
            Dispatcher.Invoke((Action)(() => lblWPCountNC.Content = data[49].ToString())); //Waypoints count
2841
            Dispatcher.Invoke((Action)(() => lblWPStatusCountNC.Content = data[49].ToString())); //Waypoints count
2842
            _wpCount = data[49];
2843
            //-------------------Satellites----------------------------------
2844
            Dispatcher.Invoke((Action)(() => tbTopSats.Text = data[50].ToString()));
2845
 
2846
            //--------------- Capacity used ------------------------
2847
            i_16 = data[81];
2848
            i_16 = (Int16)(i_16 << 8);
2849
            iVal = data[80] + i_16;
2850
            Dispatcher.Invoke((Action)(() => tbCapacity.Text = iVal.ToString() + " mAh"));
2851
            Dispatcher.Invoke((Action)(() => tbTopCapacity.Text = iVal.ToString() + " mAh"));
2852
 
2853
            //--------------- Ground speed ------------------------
2854
            i_16 = data[59];
2855
            i_16 = (Int16)(i_16 << 8);
2856
            iVal = data[58] + i_16;
2857
            Dispatcher.Invoke((Action)(() => tbNCGrSpeed.Text = ((double)(iVal)/100).ToString("0.00 m/s")));
2858
            if(_Simulate)
2859
                Dispatcher.Invoke((Action)(() => tbTopSpeed.Text = ((double)(iVal)/100).ToString("0.00 m/s")));
2860
 
2861
            //--------------- Heading north ------------------------
2862
            //i_16 = data[61];
2863
            //i_16 = (Int16)(i_16 << 8);
2864
            //iVal = data[60] + i_16;
2865
            //Dispatcher.Invoke((Action)(() => tbHeadingNorth.Text = iVal.ToString() + " °"));
2866
 
2867
            //--------------- Heading compass ------------------------
2868
            i_16 = data[63];
2869
            i_16 = (Int16)(i_16 << 8);
2870
            iVal = data[62] + i_16;
2871
            Dispatcher.Invoke((Action)(() => tbHeadingCompass.Text = iVal.ToString() + " °"));
2872
            if (_Simulate)
2873
            {
2874
                Dispatcher.Invoke(() => ArtHor.rotate = iVal);
2875
                Dispatcher.Invoke(() => ((CustomMarkerCopter)(copter.Shape)).rotate = iVal);
2876
            }
2877
            //--------------- Flying time ------------------------
2878
            i_16 = data[56];
2879
            i_16 = (Int16)(i_16 << 8);
2880
            iVal = data[55] + i_16;
2881
            TimeSpan t = TimeSpan.FromSeconds(iVal);
2882
            string Text = t.Hours.ToString("D2") + ":" + t.Minutes.ToString("D2") + ":" + t.Seconds.ToString("D2");
2883
            Dispatcher.Invoke((Action)(() => tbFTime.Text = Text.ToString()));
2884
            Dispatcher.Invoke((Action)(() => tbTopFTime.Text = Text.ToString()));
2885
 
2886
            //--------------- RC quality ------------------------
2887
            Dispatcher.Invoke((Action)(() => tbRCQ.Text = data[66].ToString()));
2888
            Dispatcher.Invoke((Action)(() => tbTopRC.Text = data[66].ToString()));
2889
 
2890
            if(data[66] > _iThresholdRC)
2891
            {
2892
                _iRCLevelJitter = 0; _bVoiceRCLevelActive = false;
2893
                if (stbRCLevelAnim != null && _bAnimRCLevelActive)
2894
                {
2895
                    Dispatcher.Invoke(() => stbRCLevelAnim.Stop());
2896
                    _bAnimRCLevelActive = false;
2897
                }
2898
            }
2899
            else
2900
            {
2901
                if (_iRCLevelJitter < 20) _iRCLevelJitter++;
2902
                if (_iRCLevelJitter == 20)
2903
                {
2904
                    if (stbRCLevelAnim != null && !_bAnimRCLevelActive)
2905
                    {
2906
                        Dispatcher.Invoke(() => stbRCLevelAnim.Begin());
2907
                        _bAnimRCLevelActive = true;
2908
                    }
2909
                    if (_bVoiceRCLevelPlay && !_bVoiceRCLevelActive)
2910
                    {
2911
                        _bVoiceRCLevelActive = true;
2912
                        ThreadPool.QueueUserWorkItem(new WaitCallback(_mediaPlayer), "Voice\\MagneticField.mp3");
2913
                        //Thread th = new Thread(() => _mediaPlayer("Voice\\RCLevel.mp3"));
2914
                        //th.Start();
2915
                    }
2916
                        _iRCLevelJitter++;
2917
                }
2918
            }
2919
 
2920
            //-------------------------Waypoint max range (by license)------------------------------
2921
            if(dWPMaxRange != (double)data[70])
2922
            {
2923
                dWPMaxRange = (double)data[70];
2924
                if (home != null && checkBoxShowWPMaxRange.IsChecked == true)
2925
                {
2926
                    if (cWPBound != null && cWPBound.Tag != null)
2927
                        MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
2928
 
2929
                    createCircle(home.Position, dWPMaxRange);
2930
                    Dispatcher.Invoke(() =>
2931
                    {
2932
                        if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
2933
                        {
2934
                            string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
2935
                            cWPBound.setColor(s);
2936
                        }
2937
                    });
2938
                }
2939
                Dispatcher.Invoke((Action)(() => tbWPMaxRange.Text = data[70].ToString() + " m"));
2940
            }
2941
            //---------------------------------Target hold time------------------------------
2942
            Dispatcher.Invoke((Action)(() => lblWPHoldTime.Content = data[73].ToString()+ " s"));
2943
            Dispatcher.Invoke((Action)(() => tbWPStatusHoldTime.Text = data[73].ToString()+ " s"));
2944
 
2945
            //--------------- NC Error ------------------------
2946
            Dispatcher.Invoke((Action)(() => tbNCErr.Text = data[69].ToString()));  //NC Errornumber
2947
            if (data[69] > 0)
2948
                _readNCError();
2949
            if (data[69] > 0 & data[69] < 44)
2950
                ErrorLog(LogMsgType.Error," NC Error [" + data[69].ToString() + "]: ",NC_Error_Link[data[69]], NC_Error[data[69]]);
2951
            //else
2952
            //    if (_bErrorLog) _clearErrorLog("NC Error");
2953
 
2954
            //--------------------------------------------------------------------------------
2955
            //-----------------------------FC / NC Status Flags-------------------------------
2956
            //--------------------------------------------------------------------------------
2957
            Dispatcher.Invoke((Action)(() => FC1_1.Background = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN                             0x01
2958
            Dispatcher.Invoke((Action)(() => FC1_2.Background = ((data[67] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_FLY                                   0x02
2959
            Dispatcher.Invoke((Action)(() => FC1_3.Background = ((data[67] & 4) ==4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_CALIBRATE                             0x04
2960
            Dispatcher.Invoke((Action)(() => FC1_4.Background = ((data[67] & 8) ==8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_START                                 0x08
2961
            Dispatcher.Invoke((Action)(() => FC1_5.Background = ((data[67] & 16) ==16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING                      0x10
2962
            Dispatcher.Invoke((Action)(() => FC1_6.Background = ((data[67] & 32) ==32) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_LOWBAT                         0x20
2963
 
2964
            Dispatcher.Invoke((Action)(() => FC2_1.Background = ((data[74] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE                             0x01
2965
            Dispatcher.Invoke((Action)(() => FC2_2.Background = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL                     0x02
2966
            Dispatcher.Invoke((Action)(() => FC2_3.Background = ((data[74] & 4) ==4) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_RC_FAILSAVE_ACTIVE                      0x04
2967
            Dispatcher.Invoke((Action)(() => FC2_4.Background = ((data[74] & 8) ==8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT1_ACTIVE                          0x08
2968
            Dispatcher.Invoke((Action)(() => FC2_5.Background = ((data[74] & 16) ==16) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT2_ACTIVE                        0x10
2969
            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
2970
            Dispatcher.Invoke((Action)(() => FC2_7.Background = ((data[74] & 64) ==64) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_STARTING                              0x40
2971
            Dispatcher.Invoke((Action)(() => FC2_8.Background = ((data[74] & 128) ==128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_LANDING                             0x80
2972
 
2973
            Dispatcher.Invoke((Action)(() => NC1_2.Background = ((data[68] & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_PH                                     0x02
2974
            Dispatcher.Invoke((Action)(() => NC1_3.Background = ((data[68] & 4) == 4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_CH                                     0x04
2975
            Dispatcher.Invoke((Action)(() => NC1_4.Background = ((data[68] & 8) == 8) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_RANGE_LIMIT                               0x08
2976
            Dispatcher.Invoke((Action)(() => NC1_5.Background = ((data[68] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_NOSERIALLINK                            0x10
2977
            Dispatcher.Invoke((Action)(() => NC1_6.Background = ((data[68] & 32) == 32) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_TARGET_REACHED                               0x20
2978
            Dispatcher.Invoke((Action)(() => NC1_7.Background = ((data[68] & 64) == 64) ? new SolidColorBrush(Colors.DodgerBlue) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_MANUAL_CONTROL                          0x40
2979
            Dispatcher.Invoke((Action)(() => NC1_8.Background = ((data[68] & 128) == 128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_GPS_OK                                     0x80
2980
 
2981
            //Sidebar StatusSymbols
2982
            Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.Background = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN                             0x01
2983
            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
2984
            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
2985
 
2986
            Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Background = ((data[74] & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE                                0x01
2987
            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
2988
            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
2989
 
2990
            Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.Background = ((data[67] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING                   0x10
2991
            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
2992
            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
2993
 
2994
            Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.Background = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL                         0x02
2995
            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
2996
            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
2997
 
2998
            Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Text = ((data[68] & 4) == 4) ? "CH" : "PH"));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
2999
            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
3000
            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
3001
            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
3002
 
3003
            _bAirborne = (data[67] & 2) == 2 ? true : false;
3004
        }
3005
        /// <summary>
3006
        /// Navi-Ctrl WP data struct 'X'
3007
        /// called by index
3008
        /// </summary>
3009
        /// <param name="data">the received byte array to process</param>
3010
        void _processWPData(byte[] data)
3011
        {
3012
            _iWPCount = data[0];
3013
            _bGetWPCount = false;
3014
            if (data.Length >= 28)
3015
            {
3016
                Dispatcher.Invoke(() => lblWPIndex.Content = data[1].ToString());
3017
                Dispatcher.Invoke(() => lblWPCount.Content = data[0].ToString());
3018
                if (_bGetWP)
3019
                {
3020
                    if (data[1] == 1)
3021
                    {
3022
                        Dispatcher.Invoke(() =>
3023
                        {
3024
                            wpList.Clear();
3025
                            _clearMapMarkers(typeof(CustomMarkerWP));
3026
                            if (mRouteWP != null)
3027
                                MainMap.Markers.Remove(mRouteWP);
3028
                            if (wpActiveMarker != null)
3029
                                MainMap.Markers.Remove(wpActiveMarker);
3030
                            lblWPRouteDistance.Content = "0 m";
3031
                            dtWaypoints.Rows.Clear();
3032
                            _wpEdit = -1;_wpIndex = -1;
3033
                            wpOffset.Clear();
3034
                        });
3035
                    }
3036
                    DataRow dr = dtWaypoints.NewRow();
3037
                    dr = Waypoints.toDataRow(data, dr);
3038
                    dtWaypoints.Rows.Add(dr);
3039
                    _createWP(new PointLatLng((double)dr[3], (double)dr[4]), (string)dr[2], (int)dr[1],(int)data[1]-1);
3040
                    Dispatcher.Invoke(() => dgvWP.Items.Refresh());
3041
                    Dispatcher.Invoke(() => _iWPIndex = data[1]);
3042
                    if (data[1] == data[0])
3043
                    {
3044
                        _bGetWP = false;
3045
                        _routeUpdate();
3046
                    }
3047
 
3048
                }
3049
            }
3050
            else
3051
            {
3052
                Dispatcher.Invoke(() => lblWPIndex.Content = 0);
3053
                Dispatcher.Invoke(() => lblWPCount.Content = 0);
3054
            }
3055
        }
3056
        /// <summary>
3057
        /// OSD Menue 'L'
3058
        /// single page called by pagenumber
3059
        /// no autoupdate
3060
        /// </summary>
3061
        /// <param name="data">the received byte array to process</param>
3062
        void _processOSDSingle(byte[] data)
3063
        {
3064
            if (data.Length == 84)
3065
            {
3066
                string sMessage = "";
3067
                iOSDPage = data[0];
3068
                iOSDMax = data[1];
3069
                if (cbOSD.Items.Count != iOSDMax) _initOSDCB();
3070
                sMessage = new string(ASCIIEncoding.ASCII.GetChars(data, 2, data.Length - 4));
3071
                OSD(LogMsgType.Incoming, sMessage.Substring(0, 20)+ "\r", true);
3072
                OSD(LogMsgType.Incoming, sMessage.Substring(20, 20)+ "\r", false);
3073
                OSD(LogMsgType.Incoming, sMessage.Substring(40, 20)+ "\r", false);
3074
                OSD(LogMsgType.Incoming, sMessage.Substring(60, 20), false);
3075
                Dispatcher.Invoke(() => { cbOSD.SelectedValue = iOSDPage; });
3076
              //  lblOSDPageNr.Invoke((Action)(() => lblOSDPageNr.Text = iOSDPage.ToString("[0]")));
3077
 
3078
            }
3079
            //else
3080
            //    OSD(LogMsgType.Incoming, "Wrong length: " + data.Length + " (should be 84)");
3081
 
3082
        }
3083
        /// <summary>
3084
        /// OSD Menue 'H'
3085
        /// called by keys (0x01,0x02,0x03,0x04)
3086
        /// autoupdate
3087
        /// </summary>
3088
        /// <param name="data">the received byte array to process</param>
3089
        void _processOSDAuto(byte[] data)
3090
        {
3091
            if (data.Length == 81)
3092
            {
3093
                string sMessage = "";
3094
                sMessage = new string(ASCIIEncoding.ASCII.GetChars(data, 0, data.Length - 1));
3095
                OSD(LogMsgType.Incoming, sMessage.Substring(0, 20)+ "\r", true);
3096
                OSD(LogMsgType.Incoming, sMessage.Substring(20, 20)+ "\r", false);
3097
                OSD(LogMsgType.Incoming, sMessage.Substring(40, 20)+ "\r", false);
3098
                OSD(LogMsgType.Incoming, sMessage.Substring(60, 20), false);
3099
 
3100
            }
3101
            //else
3102
            //    OSD(LogMsgType.Incoming, "Wrong length: " + data.Length + " (should be 81)");
3103
        }
3104
 
3105
        #endregion processing received data
3106
 
3107
        #region controller messages
3108
        /// <summary> send message to controller to request data
3109
        /// for detailed info see http://wiki.mikrokopter.de/en/SerialProtocol/
3110
        /// </summary>
3111
        /// <param name="CMDID"> the command ID </param>
3112
        /// <param name="address"> the address of the controller: 0-any, 1-FC, 2-NC </param>
3113
        private void _sendControllerMessage(char CMDID, byte address)
3114
        {
3115
            if (serialPortCtrl.Port.IsOpen)
3116
            {
3117
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3118
                byte[] bytes = FlightControllerMessage.CreateMessage(CMDID, address);
3119
                serialStream.Write(bytes, 0, bytes.Length);
3120
 
3121
            }
3122
            else
3123
                Log(LogMsgType.Error, "NOT CONNECTED!");
3124
        }
3125
        /// <summary> send message to controller to request data
3126
        /// for detailed info see http://wiki.mikrokopter.de/en/SerialProtocol/
3127
        /// </summary>
3128
        /// <param name="CMDID"> the command ID </param>
3129
        /// <param name="address"> the address of the controller: 0-any, 1-FC, 2-NC </param>
3130
        /// <param name="data"> additional data for the request</param>
3131
        private void _sendControllerMessage(char CMDID, byte address, byte[] data)
3132
        {
3133
            if (serialPortCtrl.Port.IsOpen)
3134
            {
3135
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3136
                byte[] bytes = FlightControllerMessage.CreateMessage(CMDID, address, data);
3137
                serialStream.Write(bytes, 0, bytes.Length);
3138
 
3139
            }
3140
            else
3141
                Log(LogMsgType.Error, "NOT CONNECTED!");
3142
        }
3143
 
3144
        /// <summary>
3145
        /// start/stop continous polling of controller values
3146
        /// </summary>
3147
        /// <param name="b">start/stop switch</param>
3148
        void _readCont(bool b)
3149
        {
3150
            bReadContinously = b;
3151
            if (bReadContinously)
3152
            {
3153
                if (_debugDataAutorefresh) { _readDebugData(true); Thread.Sleep(10); }
3154
                if (_blctrlDataAutorefresh) { _readBLCtrl(true); Thread.Sleep(10); }
3155
                if (_navCtrlDataAutorefresh && _iCtrlAct == 2) { _readNavData(true); Thread.Sleep(10); }
3156
                if (_OSDAutorefresh) { _OSDMenueAutoRefresh(); Thread.Sleep(10); }
3157
                // Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGreen));
3158
                Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_G.png", UriKind.Relative)));
3159
            }
3160
            else
3161
            {
3162
                // Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGray));
3163
                Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_W.png", UriKind.Relative)));
3164
                _bConnErr = false;
3165
            }
3166
            _iLifeCounter = 0;
3167
        }
3168
 
3169
        private void _getVersion()
3170
        {
3171
            _sendControllerMessage('v', 0);
3172
        }
3173
        /// <summary>
3174
        /// get FC version struct via NC
3175
        /// by sending '1' as data (not documented in wiki...)
3176
        /// returns HW error 255 (comment in uart1.c : tells the KopterTool that it is the FC-version)
3177
        /// </summary>
3178
        /// <param name="ctrl">controller number 1=FC</param> 
3179
        private void _getVersion(byte ctrl)
3180
        {
3181
            _sendControllerMessage('v', 0, new byte[1] { ctrl });
3182
        }
3183
        /// <summary>
3184
        /// Switch back to NC by sending the 'Magic Packet' 0x1B,0x1B,0x55,0xAA,0x00
3185
        /// </summary>
3186
        private void _switchToNC()
3187
        {
3188
            if (serialPortCtrl.Port.IsOpen)
3189
            {
3190
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3191
                byte[] bytes = new byte[5] { 0x1B, 0x1B, 0x55, 0xAA, 0x00 };
3192
                serialStream.Write(bytes, 0, bytes.Length);
3193
 
3194
                Thread.Sleep(100);
3195
                _getVersion();
3196
                Thread.Sleep(100);
3197
                _getLic();
3198
               // _OSDMenue(0);
3199
            }
3200
            else
3201
                Log(LogMsgType.Error, "NOT CONNECTED!");
3202
        }
3203
        /// <summary>
3204
        /// switch to FC
3205
        /// </summary>
3206
        private void _switchToFC()
3207
        {
3208
            _sendControllerMessage('u', 2, new byte[1] { (byte)0 });
3209
            Thread.Sleep(100);
3210
            _getVersion();
3211
            Thread.Sleep(100);
3212
          //  _OSDMenue(0);
3213
        }
3214
        /// <summary>
3215
        /// send RESET signal to FC
3216
        /// </summary>
3217
        private void _resetCtrl()
3218
        {
3219
            _sendControllerMessage('R', 1);
3220
        }
3221
        /// <summary>
3222
        /// poll the debug data (4sec subscription)
3223
        /// </summary>
3224
        /// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
3225
        private void _readDebugData(bool auto)
3226
        {
3227
            byte interval = auto ? debugInterval : (byte)0;
3228
            _sendControllerMessage('d', 0, new byte[1] { debugInterval });
3229
        }
3230
        /// <summary>
3231
        /// poll the BL-CTRL status via NC (4sec subscription)
3232
        /// </summary>
3233
        /// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
3234
        private void _readBLCtrl(bool auto)
3235
        {
3236
            byte interval = auto ? blctrlInterval : (byte)0;
3237
            _sendControllerMessage('k', 0, new byte[1] { interval });
3238
        }
3239
        /// <summary>
3240
        /// poll the NC data struct (4sec subscription)
3241
        /// </summary>
3242
        /// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
3243
        private void _readNavData(bool auto)
3244
        {
3245
            byte interval = auto ? navctrlInterval : (byte)0;
3246
          // _sendControllerMessage('o', 2, new byte[1] { interval });
3247
             _sendControllerMessage('o', 2, new byte[3] { interval,4,0 });
3248
        }
3249
        /// <summary>
3250
        /// request the license info
3251
        /// </summary>
3252
        void _getLic()
3253
        {
3254
            if (serialPortCtrl.Port.IsOpen)
3255
            {
3256
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3257
                byte[] bytes = FlightControllerMessage.CreateMessage('m', 2, new byte[1] { (byte)1 });
3258
                serialStream.Write(bytes, 0, bytes.Length);
3259
            }
3260
            else
3261
                Log(LogMsgType.Error, "NOT CONNECTED!");
3262
 
3263
        }
3264
        /// <summary>
3265
        /// get the errortext for pending NC error
3266
        /// </summary>
3267
        private void _readNCError()
3268
        {
3269
            _sendControllerMessage('e', 2);
3270
        }
3271
        /// <summary>
3272
        /// request the Waypoint at index
3273
        /// </summary>
3274
        /// <param name="index"></param>
3275
        void _getpWP(int index)
3276
        {
3277
            if (serialPortCtrl.Port.IsOpen)
3278
            {
3279
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3280
                byte[] bytes = FlightControllerMessage.CreateMessage('x', 2, new byte[1] { (byte)index });
3281
                serialStream.Write(bytes, 0, bytes.Length);
3282
            }
3283
            else
3284
                Log(LogMsgType.Error, "NOT CONNECTED!");
3285
 
3286
        }
3287
        void _getWP()
3288
        {
3289
            int iTimeout = 0;
3290
            _bGetWPCount = true;
3291
            _getpWP(1); //get the itemscount of wp
3292
            while (_bGetWPCount & iTimeout < _iWPTimeout * 5)
3293
            {
3294
                Thread.Sleep(10);
3295
                iTimeout++;
3296
            }
3297
            if (_iWPCount > 0 & !_bGetWPCount)
3298
                _getWPList();
3299
        }
3300
        void _getWPList()
3301
        {
3302
            _bGetWP = true;
3303
            int iTimeout=0;
3304
            for (int j = 0; j < _iWPCount; j++)
3305
            {
3306
                _getpWP(j + 1);
3307
                iTimeout = 0;
3308
                while (_iWPIndex != j + 1 & iTimeout < _iWPTimeout * 5)
3309
                {
3310
                    Thread.Sleep(1);
3311
                    iTimeout++;
3312
                }
3313
            }
3314
            Dispatcher.Invoke(() =>
3315
            {
3316
               // MainMap.ZoomAndCenterMarkers(null);
3317
                MainMap.Position = new PointLatLng((double)dtWaypoints.Rows[0][3], (double)dtWaypoints.Rows[0][4]);
3318
                MainMap.Zoom = 19;
3319
            });
3320
        }
3321
        /// <summary>
3322
        /// Wrapper for _clearCopterWPList()
3323
        /// necessary, cause it is called by threadnew which does not like return values...
3324
        /// </summary>
3325
        void clearCopterWPList()
3326
        {
3327
            _clearCopterWPList();
3328
        }
3329
        /// <summary>
3330
        /// clear the WP list of the copter
3331
        /// by sending 'invalid' and index '0'
3332
        /// </summary>
3333
        /// <returns></returns>
3334
        bool _clearCopterWPList()
3335
        {
3336
            int iTimeout = 0;
3337
            if (serialPortCtrl.Port.IsOpen)
3338
            {
3339
                byte[] bData = new byte[30];
3340
                for (int i = 0; i < 30; i++)
3341
                    bData[i] = 0;
3342
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3343
                byte[] bytes = FlightControllerMessage.CreateMessage('w', 2, bData); //delete all WP on Copter by sending 'invalid'(==0) at index 0
3344
                serialStream.Write(bytes, 0, bytes.Length);
3345
 
3346
                _iWPCount = -1;
3347
                while (_iWPCount == -1 & iTimeout < _iWPTimeout)
3348
                {
3349
                    Thread.Sleep(10);
3350
                    iTimeout++;
3351
                }
3352
                Dispatcher.Invoke(() => lblWPCount.Content = _iWPCount.ToString());
3353
                if (_iWPCount > -1)
3354
                    return true;
3355
                else
3356
                    Log(LogMsgType.Error, "Timeout while sending list!");
3357
            }
3358
            else
3359
                Log(LogMsgType.Error, "NOT CONNECTED!");
3360
 
3361
            return false;
3362
}
3363
        void _sendWPList()
3364
        {
3365
            _sendWPList(0);
3366
        }
3367
        void _sendWPList(int iStart)
3368
        {
3369
            int iTimeout = 0;
3370
            if (serialPortCtrl.Port.IsOpen)
3371
            {
3372
                if (_clearCopterWPList())
3373
                {
3374
                    int k = 1;
3375
                    for (int i = iStart; i < dtWaypoints.Rows.Count; i++)
3376
                    {
3377
                        k = iStart > 0 ? k : -1;
3378
                        _sendWayPoint(dtWaypoints.Rows[i], k, 'w',false);
3379
 
3380
                        _iWPCount = -1;
3381
                        iTimeout = 0;
3382
                        while (_iWPCount == -1 & iTimeout < _iWPTimeout * 5)
3383
                        {
3384
                            Thread.Sleep(10);
3385
                            iTimeout++;
3386
                        }
3387
                        if (_iWPCount == -1)
3388
                        {
3389
                            Log(LogMsgType.Error, "Timeout while sending list!");
3390
                            break;
3391
                        }
3392
                        Dispatcher.Invoke(() => lblWPCount.Content = _iWPCount.ToString());
3393
                        k++;
3394
                    }
3395
                }
3396
            }
3397
            else
3398
                Log(LogMsgType.Error, "NOT CONNECTED!");
3399
 
3400
        }
3401
        bool _sendWayPoint(DataRow dr, int index, char command,bool bSim)
3402
        {
3403
 
3404
            if (serialPortCtrl.Port.IsOpen)
3405
            {
3406
                byte[] bData = new byte[30];
3407
                for (int i = 0; i < 30; i++)
3408
                    bData[i] = 0;
3409
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3410
                byte[] bytes;
3411
                int iVal;
3412
                double dVal;
3413
                NumberFormatInfo nfi = new NumberFormatInfo();
3414
                nfi.NumberDecimalSeparator = ",";
3415
 
3416
                //longitude
3417
                dVal = Convert.ToDouble(dr[4], nfi);
3418
                iVal = (int)(dVal * Math.Pow(10, 7));
3419
                bData[0] = (byte)(iVal & 0xff);
3420
                bData[1] = (byte)((iVal >> 8) & 0xff);
3421
                bData[2] = (byte)((iVal >> 16) & 0xff);
3422
                bData[3] = (byte)(iVal >> 24);
3423
                //latitude
3424
                dVal = Convert.ToDouble(dr[3], nfi);
3425
                iVal = (int)(dVal * Math.Pow(10, 7));
3426
                bData[4] = (byte)(iVal & 0xff);
3427
                bData[5] = (byte)((iVal >> 8) & 0xff);
3428
                bData[6] = (byte)((iVal >> 16) & 0xff);
3429
                bData[7] = (byte)(iVal >> 24);
3430
                //altitude
3431
                dVal = Convert.ToDouble(dr[5], nfi);
3432
                iVal = (int)(dVal * 10);
3433
                bData[8] = (byte)(iVal & 0xff);
3434
                bData[9] = (byte)((iVal >> 8) & 0xff);
3435
                bData[10] = (byte)((iVal >> 16) & 0xff);
3436
                bData[11] = (byte)(iVal >> 24);
3437
                if(bSim)
3438
                    bData[12] = 3; //Status 'SIMULATE'
3439
                //Status 'NEWDATA'
3440
                else
3441
                    bData[12] = 1;
3442
                //heading
3443
                iVal = Convert.ToInt16(dr[6]);
3444
                bData[13] = (byte)(iVal & 0xff);
3445
                bData[14] = (byte)((iVal >> 8) & 0xff);
3446
                //ToleranceRadius
3447
                bData[15] = Convert.ToByte(dr[9]);
3448
                //HoldTime
3449
                bData[16] = Convert.ToByte(dr[10]);
3450
                //Event_Flag
3451
                bData[17] = Convert.ToByte(dr[13]);
3452
                //Index
3453
                bData[18] = index > -1 ? (byte)index : Convert.ToByte((int)dr[0]);
3454
                //Type
3455
                bData[19] = Convert.ToByte(dr[1]);
3456
                //WP_EventChannelValue
3457
                bData[20] = Convert.ToByte(dr[14]);
3458
                //AltitudeRate
3459
                bData[21] = Convert.ToByte(dr[8]);
3460
                //Speed
3461
                bData[22] = Convert.ToByte(dr[7]);
3462
                //CamAngle
3463
                bData[23] = (byte)Convert.ToInt16(dr[12]);
3464
                //Name
3465
                string s = index > 0 ? ((string)dr[2]).Substring(0, 1) + index.ToString() : (string)dr[2];
3466
                byte[] name = ASCIIEncoding.ASCII.GetBytes(s);
3467
                bData[24] = name.Length > 0 ? name[0] : (byte)0;
3468
                bData[25] = name.Length > 1 ? name[1] : (byte)0;
3469
                bData[26] = name.Length > 2 ? name[2] : (byte)0;
3470
                bData[27] = name.Length > 3 ? name[3] : (byte)0;
3471
                //Autotrigger
3472
                bData[28] = Convert.ToByte(dr[11]);
3473
 
3474
                bytes = FlightControllerMessage.CreateMessage(command, 2, bData);
3475
                serialStream.Write(bytes, 0, bytes.Length);
3476
 
3477
                return true;
3478
            }
3479
 
3480
            return false;
3481
        }
3482
        #region OSD-Menue
3483
 
3484
        /// <summary>
3485
        /// one time query of the OSD Menue with pagenumber
3486
        /// </summary>
3487
        /// <param name="iMenue">Menue page</param>
3488
        void _OSDMenue(int iMenue)
3489
        {
3490
            if (serialPortCtrl.Port.IsOpen)
3491
            {
3492
                if (iMenue > iOSDMax)
3493
                    iMenue = 0;
3494
                Stream serialStream = serialPortCtrl.Port.BaseStream;
3495
                byte[] bytes = FlightControllerMessage.CreateMessage('l', 0, new byte[1] { (byte)iMenue });
3496
                serialStream.Write(bytes, 0, bytes.Length);
3497
            }
3498
            else
3499
                Log(LogMsgType.Error, "NOT CONNECTED!");
3500
 
3501
        }
3502
        /// <summary>
3503
        /// call the OSDMenue and start autorefresh
3504
        ///  usually by sending a menuekey
3505
        /// 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)
3506
        /// therefore the value has to be negative (inverted) in order to distinguish from old (2 line) menuestyle
3507
        /// and must not have any bits of the menue keys 0x1 0x2 0x4 0x8 (0x10?) --> 0x20 = -33
3508
        /// </summary>
3509
        void _OSDMenueAutoRefresh()
3510
        {
3511
            _sendControllerMessage('h', 0, new byte[2] { unchecked((byte)(-33)), OSDInterval });
3512
        }
3513
        void _OSDMenueAutoRefresh(byte key)
3514
        {
3515
            _sendControllerMessage('h', 0, new byte[2] { unchecked((byte)~key), OSDInterval });
3516
        }
3517
        /// <summary>
3518
        /// initialize the OSD menue combobox
3519
        /// combox is filled by numbers from 0 to max pagenumber
3520
        /// </summary>
3521
        void _initOSDCB()
3522
        {
3523
            _bCBInit = true;
3524
            if (iOSDMax == 0)
3525
            {
3526
                _OSDMenue(0);
3527
                Thread.Sleep(10);
3528
            }
3529
            Dispatcher.Invoke((Action)(() => cbOSD.Items.Clear()));
3530
            for (int i = 0; i <= iOSDMax; i++)
3531
            {
3532
                Dispatcher.Invoke((Action)(() => cbOSD.Items.Add(i)));
3533
            }
3534
            Dispatcher.Invoke((Action)(() => cbOSD.SelectedItem = iOSDPage));
3535
            _bCBInit = false;
3536
        }
3537
        private void btnOSDForward_Click(object sender, RoutedEventArgs e)
3538
        {
3539
            iOSDPage++;
3540
            if (iOSDPage > iOSDMax)
3541
                iOSDPage = 0;
3542
 
3543
            _OSDMenue(iOSDPage);
3544
        }
3545
        private void btnOSDBackward_Click(object sender, RoutedEventArgs e)
3546
        {
3547
            iOSDPage--;
3548
            if (iOSDPage < 0)
3549
                iOSDPage = iOSDMax;
3550
 
3551
            _OSDMenue(iOSDPage);
3552
        }
3553
        private void btnOSDLeave_Click(object sender, RoutedEventArgs e)
3554
        {
3555
            _OSDMenueAutoRefresh(8);
3556
        }
3557
        private void btnOSDEnter_Click(object sender, RoutedEventArgs e)
3558
        {
3559
            _OSDMenueAutoRefresh(4);
3560
        }
3561
        private void cbOSD_DropDownClosing(object sender, EventArgs e)
3562
        {
3563
            if (!_bCBInit && cbOSD.SelectedIndex > -1)
3564
                _OSDMenue(cbOSD.SelectedIndex);
3565
        }
3566
        private void OSD(LogMsgType msgtype, string msg, bool bNew)
3567
        {
3568
            Dispatcher.Invoke(() =>
3569
            {
3570
                TextRange tr;
3571
                if (bNew)
3572
                {
3573
                    rtfOSD.SelectAll();
3574
                    rtfOSD.Selection.Text = string.Empty;
3575
                }
3576
                tr = new TextRange(rtfOSD.Document.ContentEnd, rtfOSD.Document.ContentEnd);
3577
                tr.Text = msg;
3578
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
3579
                //     rtfOSD.AppendText("\r");
3580
                rtfOSD.ScrollToEnd();
3581
 
3582
            });
3583
        }
3584
 
3585
        #endregion OSD-Menue
3586
 
3587
        #endregion controller messages
3588
 
3589
        void _mediaPlayer(object file)
3590
        {
3591
            Monitor.TryEnter(lockObj);
3592
            try
3593
            {
3594
                if (File.Exists((string)file))
3595
                {
3596
 
3597
                    mediaPlayer.Open((string)file);
3598
                    mediaPlayer.Play();
3599
                }
3600
 
3601
            }
3602
            finally
3603
            {
3604
                Monitor.Exit(lockObj);
3605
            }
3606
        }
3607
 
3608
        #region ui
3609
        /// <summary>
3610
        /// Switch between fullscreen and normal window mode
3611
        /// save & restore scaling settings
3612
        /// </summary>
3613
        /// <param name="sender"></param>
3614
        /// <param name="e"></param>
3615
        private void imageFullscreen_MouseDown(object sender, MouseButtonEventArgs e)
3616
        {
3617
            if (winState.isMaximized)
3618
            {
3619
                winState.Restore(this);
3620
                imageFullscreen.Source = new BitmapImage(new Uri("Images/Fullscreen.png", UriKind.Relative));
3621
                if(_bSaveWinStateFull)
3622
                    _saveScaleSliders(true);
3623
                if(_bSaveWinStateNormal)
3624
                    _setScaleSliders(false);
3625
            }
3626
            else
3627
            {
3628
                winState.Maximize(this);
3629
                imageFullscreen.Source = new BitmapImage(new Uri("Images/RestoreScreen.png", UriKind.Relative));
3630
                if(_bSaveWinStateNormal)
3631
                    _saveScaleSliders(false);
3632
                if(_bSaveWinStateFull)
3633
                    _setScaleSliders(true);
3634
            }
3635
        }
3636
 
3637
        /// <summary>
3638
        /// reset the scaling of all UI elements to default
3639
        /// </summary>
3640
        /// <param name="sender"></param>
3641
        /// <param name="e"></param>
3642
        private void buttonUIScaleReset_Click(object sender, RoutedEventArgs e)
3643
        {
3644
            UIScaleHorizonSlider.Value =
3645
                UIScaleLOGSlider.Value =
3646
                UIScaleMotorsSlider.Value =
3647
                UIScaleOSDSlider.Value =
3648
                UIScaleSlider.Value =
3649
                UIScaleTopSlider.Value = 1;
3650
        }
3651
        /// <summary>
3652
        /// adjust the top postion of UI elements below the top bar to fit the bottom position of the bar when scaling the top bar
3653
        /// </summary>
3654
        /// <param name="sender"></param>
3655
        /// <param name="e"></param>
3656
        private void UIScaleTopSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
3657
        {
3658
            GridSettings.Margin = new Thickness(GridSettings.Margin.Left, 36 * UIScaleTopSlider.Value, GridSettings.Margin.Right, GridSettings.Margin.Bottom);
3659
            if (GridMotors != null)
3660
                GridMotors.Margin = new Thickness(GridMotors.Margin.Left, 36 * UIScaleTopSlider.Value, GridMotors.Margin.Right, GridMotors.Margin.Bottom);
3661
            if (GridSideBar != null)
3662
                GridSideBar.Margin = new Thickness(GridSideBar.Margin.Left, 36 * UIScaleTopSlider.Value, GridSideBar.Margin.Right, GridSideBar.Margin.Bottom);
3663
            if (WPStatus != null)
3664
                WPStatus.Margin = new Thickness(WPStatus.Margin.Left, 36 * UIScaleTopSlider.Value, WPStatus.Margin.Right, WPStatus.Margin.Bottom);
3665
            if (GridOSD != null)
3666
            {
3667
                if(WPStatus.Visibility == Visibility.Visible)
3668
                    GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value + WPStatus.Margin.Bottom, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
3669
                else
3670
                    GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
3671
            }
3672
            if (GridData != null)
3673
                GridData.Margin = new Thickness(GridData.Margin.Left, 36 * UIScaleTopSlider.Value, GridData.Margin.Right, GridData.Margin.Bottom);
3674
            if (GridWP != null)
3675
                GridWP.Margin = new Thickness(GridWP.Margin.Left, 36 * UIScaleTopSlider.Value, GridWP.Margin.Right, GridWP.Margin.Bottom);
3676
        }
3677
        private void UIScaleOSDSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
3678
        {
3679
            if (!_init)
3680
            {
3681
                if (WPStatus != null && (WPStatus.Visibility == Visibility.Visible))
3682
                    GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value + 36, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
3683
                else
3684
                    GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
3685
            }
3686
        }
3687
 
3688
        /// <summary>
3689
        /// restore the saved scalings for the fullscreen/normal window mode
3690
        /// </summary>
3691
        /// <param name="bFull">the mode the window is set to</param>
3692
        void _setScaleSliders(bool bFull)
3693
        {
3694
            if(bFull)
3695
            {
3696
                UIScaleSlider.Value = scaleFullAll;
3697
                UIScaleTopSlider.Value = scaleFullTopBar;
3698
                UIScaleMotorsSlider.Value = scaleFullMotors;
3699
                UIScaleOSDSlider.Value = scaleFullOSD;
3700
                UIScaleLOGSlider.Value = scaleFullLOG;
3701
                UIScaleHorizonSlider.Value = scaleFullHorizon;
3702
            }
3703
            else
3704
            {
3705
                UIScaleSlider.Value = scaleNormalAll;
3706
                UIScaleTopSlider.Value = scaleNormalTopBar;
3707
                UIScaleMotorsSlider.Value = scaleNormalMotors;
3708
                UIScaleOSDSlider.Value = scaleNormalOSD;
3709
                UIScaleLOGSlider.Value = scaleNormalLOG;
3710
                UIScaleHorizonSlider.Value = scaleNormalHorizon;
3711
            }
3712
        }
3713
 
3714
        /// <summary>
3715
        /// save the scalings for the actual window mode
3716
        /// </summary>
3717
        /// <param name="bFull">the actual window mode</param>
3718
        void _saveScaleSliders(bool bFull)
3719
        {
3720
 
3721
            if (bFull)
3722
            {
3723
                scaleFullAll = UIScaleSlider.Value;
3724
                scaleFullTopBar = UIScaleTopSlider.Value;
3725
                scaleFullMotors = UIScaleMotorsSlider.Value;
3726
                scaleFullOSD = UIScaleOSDSlider.Value;
3727
                scaleFullLOG = UIScaleLOGSlider.Value;
3728
                scaleFullHorizon = UIScaleHorizonSlider.Value;
3729
            }
3730
            else
3731
            {
3732
                scaleNormalAll = UIScaleSlider.Value;
3733
                scaleNormalTopBar = UIScaleTopSlider.Value;
3734
                scaleNormalMotors = UIScaleMotorsSlider.Value;
3735
                scaleNormalOSD = UIScaleOSDSlider.Value;
3736
                scaleNormalLOG = UIScaleLOGSlider.Value;
3737
                scaleNormalHorizon = UIScaleHorizonSlider.Value;
3738
            }
3739
        }
3740
        #endregion ui
3741
 
3742
        #region ini
3743
        /// <summary>
3744
        /// read settings from ini-file
3745
        /// </summary>
3746
        void _readIni()
3747
        {
3748
            if (!File.Exists(filePath + "\\MKLiveViewSettings.ini"))
3749
                _writeIni();
3750
            IniFile ini = new IniFile("MKLiveViewSettings.ini");
3751
            ini.path = filePath + "\\MKLiveViewSettings.ini";
3752
            try
3753
            {
3754
 
3755
                string sVal = ini.IniReadValue("timings", "AutorefreshDebugData");
3756
                if (sVal != "") _debugDataAutorefresh = Convert.ToBoolean(sVal);
3757
                sVal = ini.IniReadValue("timings", "AutorefreshNavCtrlData");
3758
                if (sVal != "") _navCtrlDataAutorefresh = Convert.ToBoolean(sVal);
3759
                sVal = ini.IniReadValue("timings", "AutorefreshBLCtrlData");
3760
                if (sVal != "") _blctrlDataAutorefresh = Convert.ToBoolean(sVal);
3761
                sVal = ini.IniReadValue("timings", "AutorefreshOSDData");
3762
                if (sVal != "") _OSDAutorefresh = Convert.ToBoolean(sVal);
3763
 
3764
                sVal = ini.IniReadValue("timings", "IntervalDebugData");
3765
                if (sVal != "") debugInterval = (byte)Convert.ToInt16(sVal);
3766
                sVal = ini.IniReadValue("timings", "IntervalNavCtrlData");
3767
                if (sVal != "") navctrlInterval = (byte)Convert.ToInt16(sVal);
3768
                sVal = ini.IniReadValue("timings", "IntervalBLCtrlData");
3769
                if (sVal != "") blctrlInterval = (byte)Convert.ToInt16(sVal);
3770
                sVal = ini.IniReadValue("timings", "IntervalOSDData");
3771
                if (sVal != "") OSDInterval = (byte)Convert.ToInt16(sVal);
3772
 
3773
                sVal = ini.IniReadValue("topBar", "voltage");
3774
                if (sVal != "") chkBoxTopBarShowVoltage.IsChecked = Convert.ToBoolean(sVal);
3775
                sVal = ini.IniReadValue("topBar", "capacity");
3776
                if (sVal != "") chkBoxTopBarShowCapacity.IsChecked = Convert.ToBoolean(sVal);
3777
                sVal = ini.IniReadValue("topBar", "current");
3778
                if (sVal != "") chkBoxTopBarShowCurrent.IsChecked = Convert.ToBoolean(sVal);
3779
                sVal = ini.IniReadValue("topBar", "flightTime");
3780
                if (sVal != "") chkBoxTopBarShowFlightTime.IsChecked = Convert.ToBoolean(sVal);
3781
                sVal = ini.IniReadValue("topBar", "distanceHP");
3782
                if (sVal != "") chkBoxTopBarShowDistanceHP.IsChecked = Convert.ToBoolean(sVal);
3783
                sVal = ini.IniReadValue("topBar", "height");
3784
                if (sVal != "") chkBoxTopBarShowHeight.IsChecked = Convert.ToBoolean(sVal);
3785
                sVal = ini.IniReadValue("topBar", "speed");
3786
                if (sVal != "") chkBoxTopBarShowSpeed.IsChecked = Convert.ToBoolean(sVal);
3787
                sVal = ini.IniReadValue("topBar", "magneticField");
3788
                if (sVal != "") chkBoxTopBarShowMF.IsChecked = Convert.ToBoolean(sVal);
3789
                sVal = ini.IniReadValue("topBar", "satellites");
3790
                if (sVal != "") chkBoxTopBarShowSatellites.IsChecked = Convert.ToBoolean(sVal);
3791
                sVal = ini.IniReadValue("topBar", "rc");
3792
                if (sVal != "") chkBoxTopBarShowRC.IsChecked = Convert.ToBoolean(sVal);
3793
 
3794
                sVal = ini.IniReadValue("style", "saveFullScreen");
3795
                if (sVal != "") chkBoxSaveFullScreenState.IsChecked = Convert.ToBoolean(sVal);
3796
                sVal = ini.IniReadValue("style", "saveNormalState");
3797
                if (sVal != "") chkBoxSaveNormalState.IsChecked = Convert.ToBoolean(sVal);
3798
 
3799
                sVal = ini.IniReadValue("style", "scaleNormalAll");
3800
                if (sVal != "") scaleNormalAll = Convert.ToDouble(sVal);
3801
                sVal = ini.IniReadValue("style", "scaleNormalTopBar");
3802
                if (sVal != "") scaleNormalTopBar = Convert.ToDouble(sVal);
3803
                sVal = ini.IniReadValue("style", "scaleNormalMotors");
3804
                if (sVal != "") scaleNormalMotors = Convert.ToDouble(sVal);
3805
                sVal = ini.IniReadValue("style", "scaleNormalOSD");
3806
                if (sVal != "") scaleNormalOSD = Convert.ToDouble(sVal);
3807
                sVal = ini.IniReadValue("style", "scaleNormalLOG");
3808
                if (sVal != "") scaleNormalLOG = Convert.ToDouble(sVal);
3809
                sVal = ini.IniReadValue("style", "scaleNormalHorizon");
3810
                if (sVal != "") scaleNormalHorizon = Convert.ToDouble(sVal);
3811
 
3812
                sVal = ini.IniReadValue("style", "scaleFullAll");
3813
                if (sVal != "") scaleFullAll = Convert.ToDouble(sVal);
3814
                sVal = ini.IniReadValue("style", "scaleFullTopBar");
3815
                if (sVal != "") scaleFullTopBar = Convert.ToDouble(sVal);
3816
                sVal = ini.IniReadValue("style", "scaleFullMotors");
3817
                if (sVal != "") scaleFullMotors = Convert.ToDouble(sVal);
3818
                sVal = ini.IniReadValue("style", "scaleFullOSD");
3819
                if (sVal != "") scaleFullOSD = Convert.ToDouble(sVal);
3820
                sVal = ini.IniReadValue("style", "scaleFullLOG");
3821
                if (sVal != "") scaleFullLOG = Convert.ToDouble(sVal);
3822
                sVal = ini.IniReadValue("style", "scaleFullHorizon");
3823
                if (sVal != "") scaleFullHorizon = Convert.ToDouble(sVal);
3824
 
3825
                sVal = ini.IniReadValue("general", "LiPoCells");
3826
                _LipoCells = Convert.ToInt16(sVal);
3827
                sVal = ini.IniReadValue("general", "LiPoAutoDetect");
3828
                _bLiPoAutoDetect = Convert.ToBoolean(sVal);
3829
                sVal = ini.IniReadValue("general", "Motors");
3830
                if (sVal != "") _iMotors = Convert.ToInt16(sVal);
3831
 
3832
                sVal = ini.IniReadValue("map", "followMe");
3833
                if (sVal != "") _bFollowCopter = Convert.ToBoolean(sVal);
3834
                sVal = ini.IniReadValue("map", "location");
3835
                if (sVal != "") _mapPosition = sVal;
3836
                sVal = ini.IniReadValue("map", "AutoSetHome");
3837
                if (sVal != "") _bAutoHome = Convert.ToBoolean(sVal);
3838
                sVal = ini.IniReadValue("map", "GPXLog");
3839
                if (sVal != "") _bGPXLog = Convert.ToBoolean(sVal);
3840
 
3841
                sVal = ini.IniReadValue("threshold", "VoltageWarning");
3842
                if(sVal != "") _dThresholdVoltageWarn = Convert.ToDouble(sVal);
3843
                sVal = ini.IniReadValue("threshold", "VoltageCritical");
3844
                if(sVal != "") _dThresholdVoltageCrit = Convert.ToDouble(sVal);
3845
                sVal = ini.IniReadValue("threshold", "VoiceVoltageEnable");
3846
                if(sVal != "") _bVoiceVoltPlay = Convert.ToBoolean(sVal);
3847
                sVal = ini.IniReadValue("threshold", "VoiceSatFixEnable");
3848
                if(sVal != "") _bVoiceSatFixPlay = Convert.ToBoolean(sVal);
3849
                sVal = ini.IniReadValue("threshold", "VoiceMagFieldEnable");
3850
                if(sVal != "") _bVoiceMagneticFieldPlay = Convert.ToBoolean(sVal);
3851
                sVal = ini.IniReadValue("threshold", "DistanceWarning");
3852
                if(sVal != "") _dThresholdDistanceWarn = Convert.ToDouble(sVal);
3853
                sVal = ini.IniReadValue("threshold", "VoiceDistanceWarnEnable");
3854
                if(sVal != "") _bVoiceDistancePlay = Convert.ToBoolean(sVal);
3855
                sVal = ini.IniReadValue("threshold", "VoiceRCLevelWarnEnable");
3856
                if(sVal != "") _bVoiceRCLevelPlay = Convert.ToBoolean(sVal);
3857
                sVal = ini.IniReadValue("threshold", "MaxDistance");
3858
                if(sVal != "") _dThresholdDistanceMax = Convert.ToDouble(sVal);
3859
                sVal = ini.IniReadValue("threshold", "RCThreshold");
3860
                if(sVal != "") _iThresholdRC = Convert.ToInt32(sVal);
3861
                sVal = ini.IniReadValue("threshold", "MagFieldThreshold");
3862
                if(sVal != "") _iThresholdMagField = Convert.ToInt32(sVal);
3863
 
3864
                sVal = ini.IniReadValue("waypoints", "wpcolor");
3865
                if(sVal != "") comboBoxWPColor.SelectedIndex = Convert.ToInt32(sVal);
3866
                sVal = ini.IniReadValue("waypoints", "poicolor");
3867
                if(sVal != "") comboBoxPOIColor.SelectedIndex = Convert.ToInt32(sVal);
3868
                sVal = ini.IniReadValue("waypoints", "fscolor");
3869
                if(sVal != "") comboBoxFSColor.SelectedIndex = Convert.ToInt32(sVal);
3870
                sVal = ini.IniReadValue("waypoints", "coptercolor");
3871
                if(sVal != "") comboBoxCopterColor.SelectedIndex = Convert.ToInt32(sVal);
3872
                sVal = ini.IniReadValue("waypoints", "copterheadingcolor");
3873
                if(sVal != "") comboBoxCopterHeadingColor.SelectedIndex = Convert.ToInt32(sVal);
3874
                sVal = ini.IniReadValue("waypoints", "landingcolor");
3875
                if(sVal != "") comboBoxLandingColor.SelectedIndex = Convert.ToInt32(sVal);
3876
                sVal = ini.IniReadValue("waypoints", "routecolor");
3877
                if(sVal != "") comboBoxRouteColor.SelectedIndex = Convert.ToInt32(sVal);
3878
                sVal = ini.IniReadValue("waypoints", "showWPRoute");
3879
                if(sVal != "") _bShowWPRoute = Convert.ToBoolean(sVal);
3880
                sVal = ini.IniReadValue("waypoints", "autoShowWPEdit");
3881
                if(sVal != "") _bAutoWPEdit = Convert.ToBoolean(sVal);
3882
                sVal = ini.IniReadValue("waypoints", "showWPMaxRange");
3883
                if(sVal != "") checkBoxShowWPMaxRange.IsChecked = Convert.ToBoolean(sVal);
3884
                sVal = ini.IniReadValue("waypoints", "WPMaxRangecolor");
3885
                if(sVal != "") comboBoxWPMaxRangeColor.SelectedIndex = Convert.ToInt32(sVal);
3886
                sVal = ini.IniReadValue("waypoints", "WPDefPrefix");
3887
                if(sVal != "") _wpDefPrefix = sVal;
3888
                sVal = ini.IniReadValue("waypoints", "WPDefAltitude");
3889
                if(sVal != "") _wpDefAltitude = Convert.ToInt32(sVal);
3890
                sVal = ini.IniReadValue("waypoints", "WPDefHeading");
3891
                if(sVal != "") _wpDefHeading = Convert.ToInt32(sVal);
3892
                sVal = ini.IniReadValue("waypoints", "WPDefCBoxHeading");
3893
                if(sVal != "") _wpDefCBoxHeading = Convert.ToInt32(sVal);
3894
                sVal = ini.IniReadValue("waypoints", "WPDefSpeed");
3895
                if(sVal != "") _wpDefSpeed = Convert.ToInt32(sVal);
3896
                sVal = ini.IniReadValue("waypoints", "WPDefCBoxSpeed");
3897
                if(sVal != "") _wpDefCBoxSpeed = Convert.ToInt32(sVal);
3898
                sVal = ini.IniReadValue("waypoints", "WPDefClimb");
3899
                if(sVal != "") _wpDefClimb = Convert.ToInt32(sVal);
3900
                sVal = ini.IniReadValue("waypoints", "WPDefCBoxClimb");
3901
                if(sVal != "") _wpDefCBoxClimb = Convert.ToInt32(sVal);
3902
                sVal = ini.IniReadValue("waypoints", "WPDefRadius");
3903
                if(sVal != "") _wpDefRadius = Convert.ToInt32(sVal);
3904
                sVal = ini.IniReadValue("waypoints", "WPDefHoldtime");
3905
                if(sVal != "") _wpDefHoldtime = Convert.ToInt32(sVal);
3906
                sVal = ini.IniReadValue("waypoints", "WPDefAutotrig");
3907
                if(sVal != "") _wpDefAutotrig = Convert.ToInt32(sVal);
3908
                sVal = ini.IniReadValue("waypoints", "WPDefCamangle");
3909
                if(sVal != "") _wpDefCamangle = Convert.ToInt32(sVal);
3910
                sVal = ini.IniReadValue("waypoints", "WPDefCBoxCamangle");
3911
                if(sVal != "") _wpDefCBoxCamangle = Convert.ToInt32(sVal);
3912
                sVal = ini.IniReadValue("waypoints", "WPDefOut1");
3913
                if(sVal != "") _wpDefOut1 = Convert.ToInt32(sVal);
3914
                sVal = ini.IniReadValue("waypoints", "WPAddCopterHeight");
3915
                if (sVal != "") _wpAddCopterHeight = Convert.ToBoolean(sVal);
3916
                sVal = ini.IniReadValue("waypoints", "WPAddCopterHeading");
3917
                if (sVal != "") _wpAddCopterHeading = Convert.ToBoolean(sVal);
3918
                sVal = ini.IniReadValue("waypoints", "CopterSize");
3919
                if (sVal != "") SliderCopterZoom.Value = Convert.ToDouble(sVal);
3920
                sVal = ini.IniReadValue("waypoints", "WPSize");
3921
                if (sVal != "") SliderWPZoom.Value = Convert.ToDouble(sVal);
3922
 
3923
                sVal = ini.IniReadValue("cam", "CamImagePosLeft");
3924
                if (sVal != "") _camImageMargin.Left = Convert.ToDouble(sVal);
3925
                sVal = ini.IniReadValue("cam", "CamImagePosTop");
3926
                if (sVal != "") _camImageMargin.Top = Convert.ToDouble(sVal);
3927
                sVal = ini.IniReadValue("cam", "CamImageZoom");
3928
                if (sVal != "") SliderCamZoom.Value = Convert.ToDouble(sVal);
3929
 
3930
                for (int i = 0; i < 12; i++)
3931
                {
3932
                    sVal = ini.IniReadValue("serial", "ch" + i.ToString() + "Val");
3933
                    if (sVal != "")
3934
                        serChan[i] = Convert.ToInt16(sVal);
3935
                    sVal = ini.IniReadValue("serial", "ch" + i.ToString() + "Title");
3936
                    if (sVal != "")
3937
                        serChanTitle[i] = sVal;
3938
                    for (int y = 0; i < 4 && y < 3; y++)
3939
                    {
3940
                        sVal = ini.IniReadValue("serial", "ch" + i.ToString() + "ValSub" + y.ToString());
3941
                        if (sVal != "")
3942
                            serChan_sub[(i * 3) + y] = Convert.ToInt16(sVal);
3943
                    }
3944
                }
3945
 
3946
            }
3947
            catch (Exception e)
3948
            {
3949
 
3950
                MessageBox.Show("Error parsing ini-file!" + Environment.NewLine + e.Message,"Read ini-file" ,MessageBoxButton.OK,MessageBoxImage.Error);
3951
            }
3952
 
3953
        }
3954
 
3955
        /// <summary>
3956
        /// save settings to ini-file
3957
        /// </summary>
3958
        void _writeIni()
3959
        {
3960
 
3961
            IniFile ini = new IniFile("MKLiveViewSettings.ini");
3962
            ini.path = filePath + "\\MKLiveViewSettings.ini";
3963
 
3964
            try
3965
            {
3966
 
3967
                ini.IniWriteValue("timings", "AutorefreshDebugData", _debugDataAutorefresh ? "true" : "false");
3968
                ini.IniWriteValue("timings", "AutorefreshNavCtrlData", _navCtrlDataAutorefresh ? "true" : "false");
3969
                ini.IniWriteValue("timings", "AutorefreshBLCtrlData", _blctrlDataAutorefresh ? "true" : "false");
3970
                ini.IniWriteValue("timings", "AutorefreshOSDData", _OSDAutorefresh ? "true" : "false");
3971
 
3972
                ini.IniWriteValue("timings", "IntervalDebugData", debugInterval.ToString());
3973
                ini.IniWriteValue("timings", "IntervalNavCtrlData", navctrlInterval.ToString());
3974
                ini.IniWriteValue("timings", "IntervalBLCtrlData", blctrlInterval.ToString());
3975
                ini.IniWriteValue("timings", "IntervalOSDData", OSDInterval.ToString());
3976
 
3977
                ini.IniWriteValue("general", "LiPoCells", _LipoCells.ToString());
3978
                ini.IniWriteValue("general", "LiPoAutoDetect", _bLiPoAutoDetect.ToString());
3979
                ini.IniWriteValue("general", "Motors", _iMotors.ToString());
3980
 
3981
                ini.IniWriteValue("map", "location", _mapPosition);
3982
                ini.IniWriteValue("map", "followMe", _bFollowCopter.ToString());
3983
                ini.IniWriteValue("map", "AutoSetHome", _bAutoHome.ToString());
3984
                ini.IniWriteValue("map", "GPXLog", _bGPXLog.ToString());
3985
 
3986
                ini.IniWriteValue("topBar", "voltage", chkBoxTopBarShowVoltage.IsChecked.ToString());
3987
                ini.IniWriteValue("topBar", "capacity", chkBoxTopBarShowCapacity.IsChecked.ToString());
3988
                ini.IniWriteValue("topBar", "current", chkBoxTopBarShowCurrent.IsChecked.ToString());
3989
                ini.IniWriteValue("topBar", "flightTime", chkBoxTopBarShowFlightTime.IsChecked.ToString());
3990
                ini.IniWriteValue("topBar", "distanceHP", chkBoxTopBarShowDistanceHP.IsChecked.ToString());
3991
                ini.IniWriteValue("topBar", "height", chkBoxTopBarShowHeight.IsChecked.ToString());
3992
                ini.IniWriteValue("topBar", "speed", chkBoxTopBarShowSpeed.IsChecked.ToString());
3993
                ini.IniWriteValue("topBar", "magneticField", chkBoxTopBarShowMF.IsChecked.ToString());
3994
                ini.IniWriteValue("topBar", "satellites", chkBoxTopBarShowSatellites.IsChecked.ToString());
3995
                ini.IniWriteValue("topBar", "rc", chkBoxTopBarShowRC.IsChecked.ToString());
3996
 
3997
                ini.IniWriteValue("style", "saveFullScreen", chkBoxSaveFullScreenState.IsChecked.ToString());
3998
                ini.IniWriteValue("style", "saveNormalState", chkBoxSaveNormalState.IsChecked.ToString());
3999
 
4000
                ini.IniWriteValue("style", "scaleNormalAll", scaleNormalAll.ToString());
4001
                ini.IniWriteValue("style", "scaleNormalTopBar", scaleNormalTopBar.ToString());
4002
                ini.IniWriteValue("style", "scaleNormalMotors", scaleNormalMotors.ToString());
4003
                ini.IniWriteValue("style", "scaleNormalOSD", scaleNormalOSD.ToString());
4004
                ini.IniWriteValue("style", "scaleNormalLOG", scaleNormalLOG.ToString());
4005
                ini.IniWriteValue("style", "scaleNormalHorizon", scaleNormalHorizon.ToString());
4006
 
4007
                ini.IniWriteValue("style", "scaleFullAll", scaleFullAll.ToString());
4008
                ini.IniWriteValue("style", "scaleFullTopBar", scaleFullTopBar.ToString());
4009
                ini.IniWriteValue("style", "scaleFullMotors", scaleFullMotors.ToString());
4010
                ini.IniWriteValue("style", "scaleFullOSD", scaleFullOSD.ToString());
4011
                ini.IniWriteValue("style", "scaleFullLOG", scaleFullLOG.ToString());
4012
                ini.IniWriteValue("style", "scaleFullHorizon", scaleFullHorizon.ToString());
4013
 
4014
                ini.IniWriteValue("style", "horizon", chkBoxShowHorizon.IsChecked.ToString());
4015
 
4016
                ini.IniWriteValue("threshold", "VoltageWarning", _dThresholdVoltageWarn.ToString());
4017
                ini.IniWriteValue("threshold", "VoltageCritical", _dThresholdVoltageCrit.ToString());
4018
                ini.IniWriteValue("threshold", "VoiceVoltageEnable", _bVoiceVoltPlay.ToString());
4019
                ini.IniWriteValue("threshold", "VoiceSatFixEnable", _bVoiceSatFixPlay.ToString());
4020
                ini.IniWriteValue("threshold", "VoiceMagFieldEnable", _bVoiceMagneticFieldPlay.ToString());
4021
                ini.IniWriteValue("threshold", "VoiceDistanceWarnEnable", _bVoiceDistancePlay.ToString());
4022
                ini.IniWriteValue("threshold", "VoiceRCLevelWarnEnable", _bVoiceRCLevelPlay.ToString());
4023
                ini.IniWriteValue("threshold", "DistanceWarning", _dThresholdDistanceWarn.ToString());
4024
                ini.IniWriteValue("threshold", "MaxDistance", _dThresholdDistanceMax.ToString());
4025
                ini.IniWriteValue("threshold", "RCThreshold", _iThresholdRC.ToString());
4026
                ini.IniWriteValue("threshold", "MagFieldThreshold", _iThresholdMagField.ToString());
4027
 
4028
                ini.IniWriteValue("waypoints", "wpcolor", comboBoxWPColor.SelectedIndex.ToString());
4029
                ini.IniWriteValue("waypoints", "poicolor", comboBoxPOIColor.SelectedIndex.ToString());
4030
                ini.IniWriteValue("waypoints", "fscolor", comboBoxFSColor.SelectedIndex.ToString());
4031
                ini.IniWriteValue("waypoints", "coptercolor", comboBoxCopterColor.SelectedIndex.ToString());
4032
                ini.IniWriteValue("waypoints", "copterheadingcolor", comboBoxCopterHeadingColor.SelectedIndex.ToString());
4033
                ini.IniWriteValue("waypoints", "landingcolor", comboBoxLandingColor.SelectedIndex.ToString());
4034
                ini.IniWriteValue("waypoints", "routecolor", comboBoxRouteColor.SelectedIndex.ToString());
4035
                ini.IniWriteValue("waypoints", "showWPRoute", _bShowWPRoute.ToString());
4036
                ini.IniWriteValue("waypoints", "showWPMaxRange", ((bool)checkBoxShowWPMaxRange.IsChecked).ToString());
4037
                ini.IniWriteValue("waypoints", "autoShowWPEdit", ((bool)checkBoxAutoShowWPEdit.IsChecked).ToString());
4038
                ini.IniWriteValue("waypoints", "WPMaxRangecolor", comboBoxWPMaxRangeColor.SelectedIndex.ToString());
4039
                ini.IniWriteValue("waypoints", "WPDefPrefix", _wpDefPrefix);
4040
                ini.IniWriteValue("waypoints", "WPDefAltitude", _wpDefAltitude.ToString());
4041
                ini.IniWriteValue("waypoints", "WPDefHeading", _wpDefHeading.ToString());
4042
                ini.IniWriteValue("waypoints", "WPDefCBoxHeading", _wpDefCBoxHeading.ToString());
4043
                ini.IniWriteValue("waypoints", "WPDefSpeed", _wpDefSpeed.ToString());
4044
                ini.IniWriteValue("waypoints", "WPDefCBoxSpeed", _wpDefCBoxSpeed.ToString());
4045
                ini.IniWriteValue("waypoints", "WPDefClimb", _wpDefClimb.ToString());
4046
                ini.IniWriteValue("waypoints", "WPDefCBoxClimb", _wpDefCBoxClimb.ToString());
4047
                ini.IniWriteValue("waypoints", "WPDefRadius", _wpDefRadius.ToString());
4048
                ini.IniWriteValue("waypoints", "WPDefHoldtime", _wpDefHoldtime.ToString());
4049
                ini.IniWriteValue("waypoints", "WPDefAutotrig", _wpDefAutotrig.ToString());
4050
                ini.IniWriteValue("waypoints", "WPDefCamangle", _wpDefCamangle.ToString());
4051
                ini.IniWriteValue("waypoints", "WPDefCBoxCamangle", _wpDefCBoxCamangle.ToString());
4052
                ini.IniWriteValue("waypoints", "WPDefOut1", _wpDefOut1.ToString());
4053
                ini.IniWriteValue("waypoints", "WPAddCopterHeight", _wpAddCopterHeight.ToString());
4054
                ini.IniWriteValue("waypoints", "WPAddCopterHeading", _wpAddCopterHeading.ToString());
4055
                ini.IniWriteValue("waypoints", "CopterSize", SliderCopterZoom.Value.ToString());
4056
                ini.IniWriteValue("waypoints", "WPSize", SliderWPZoom.Value.ToString());
4057
 
4058
                ini.IniWriteValue("cam", "CamImagePosLeft", _camImageMargin.Left.ToString());
4059
                ini.IniWriteValue("cam", "CamImagePosTop", _camImageMargin.Top.ToString());
4060
                ini.IniWriteValue("cam", "CamImageZoom", SliderCamZoom.Value.ToString());
4061
 
4062
                for (int i = 0; i < 12; i++)
4063
                {
4064
                    ini.IniWriteValue("serial", "ch" + i.ToString() + "Val", serChan[i].ToString());
4065
                    ini.IniWriteValue("serial", "ch" + i.ToString() + "Title", serChanTitle[i]);
4066
                    for (int y = 0; i < 4 && y < 3; y++)
4067
                    {
4068
                        ini.IniWriteValue("serial", "ch" + i.ToString() + "ValSub" + y.ToString(), serChan_sub[(i * 3) + y].ToString());
4069
                    }
4070
                }
4071
 
4072
            }
4073
            catch (Exception e)
4074
            {
4075
 
4076
                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);
4077
            }
4078
        }
4079
        #endregion ini
4080
 
4081
        #region serial channels
4082
        /// <summary>
4083
        /// Sending the serial channel values
4084
        /// </summary>
4085
        void _sendSerialData()
4086
        {
4087
            byte[] serData = new byte[12];
4088
            for (int i = 0; i < 12; i++)
4089
            {
4090
                serData[i] = unchecked((byte)(serChan[i] - 127));
4091
            }
4092
            _sendControllerMessage('y', 1, serData);
4093
        }
4094
        /// <summary>
4095
        /// init the controls for displaying
4096
        /// and setting serial control channels
4097
        /// </summary>
4098
        void _initSerialCtrl()
4099
        {
4100
            SerChan1ScaleSlider.Value = serChan[0];
4101
            textBoxSerial1.Text = serChanTitle[0];
4102
            SerChan2ScaleSlider.Value = serChan[1];
4103
            textBoxSerial2.Text = serChanTitle[1];
4104
            SerChan3ScaleSlider.Value = serChan[2];
4105
            textBoxSerial3.Text = serChanTitle[2];
4106
            //SerChan4ScaleSlider.Value = serChan[3];
4107
            //textBoxSerial4.Text = serChanTitle[3];
4108
            //trckbarSerial5.Value = serChan[4];
4109
            //textBoxSerial5.Text = serChanTitle[4];
4110
            //trckbarSerial6.Value = serChan[5];
4111
            //textBoxSerial6.Text = serChanTitle[5];
4112
            //trckbarSerial7.Value = serChan[6];
4113
            //textBoxSerial7.Text = serChanTitle[6];
4114
            //trckbarSerial8.Value = serChan[7];
4115
            //textBoxSerial8.Text = serChanTitle[7];
4116
 
4117
            textBoxSerial1_val1.Text = serChan_sub[0].ToString();
4118
            textBoxSerial1_val2.Text = serChan_sub[1].ToString();
4119
            textBoxSerial1_val3.Text = serChan_sub[2].ToString();
4120
            textBoxSerial2_val1.Text = serChan_sub[3].ToString();
4121
            textBoxSerial2_val2.Text = serChan_sub[4].ToString();
4122
            textBoxSerial2_val3.Text = serChan_sub[5].ToString();
4123
            textBoxSerial3_val1.Text = serChan_sub[6].ToString();
4124
            textBoxSerial3_val2.Text = serChan_sub[7].ToString();
4125
            textBoxSerial3_val3.Text = serChan_sub[8].ToString();
4126
            //textBoxSerial4_val1.Text = serChan_sub[9].ToString();
4127
            //textBoxSerial4_val2.Text = serChan_sub[10].ToString();
4128
            //textBoxSerial4_val3.Text = serChan_sub[11].ToString();
4129
        }
4130
        private void SerChan1ScaleSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
4131
        {
4132
            if (!_init)
4133
            {
4134
                serChan[0] = (int)SerChan1ScaleSlider.Value;
4135
                _sendSerialData();
4136
            }
4137
        }
4138
        private void textBoxSerial1_TextChanged(object sender, TextChangedEventArgs e)
4139
        {
4140
            if (!_init)
4141
            {
4142
                serChanTitle[0] = textBoxSerial1.Text;
4143
            }
4144
        }
4145
        private void textBoxSerial1_val1_TextChanged(object sender, TextChangedEventArgs e)
4146
        {
4147
            if (textBoxSerial1_val1.Text.Length > 0 & !_init)
4148
            {
4149
                serChan_sub[0] = Convert.ToInt16(textBoxSerial1_val1.Text);
4150
            }
4151
        }
4152
        private void textBoxSerial1_val2_TextChanged(object sender, TextChangedEventArgs e)
4153
        {
4154
            if (textBoxSerial1_val2.Text.Length > 0 & !_init)
4155
            {
4156
                serChan_sub[1] = Convert.ToInt16(textBoxSerial1_val2.Text);
4157
            }
4158
        }
4159
        private void textBoxSerial1_val3_TextChanged(object sender, TextChangedEventArgs e)
4160
        {
4161
            if (textBoxSerial1_val3.Text.Length > 0 & !_init)
4162
            {
4163
                serChan_sub[2] = Convert.ToInt16(textBoxSerial1_val3.Text);
4164
            }
4165
        }
4166
        private void btnSer1_val1_Click(object sender, RoutedEventArgs e)
4167
        {
4168
            if (textBoxSerial1_val1.Text.Length > 0)
4169
            {
4170
                SerChan1ScaleSlider.Value = Convert.ToInt16(textBoxSerial1_val1.Text);
4171
            }
4172
        }
4173
        private void btnSer1_0_Click(object sender, RoutedEventArgs e)
4174
        {
4175
            SerChan1ScaleSlider.Value = 0;
4176
        }
4177
        private void btnSer1_127_Click(object sender, RoutedEventArgs e)
4178
        {
4179
            SerChan1ScaleSlider.Value = 127;
4180
        }
4181
        private void btnSer1_254_Click(object sender, RoutedEventArgs e)
4182
        {
4183
            SerChan1ScaleSlider.Value = 254;
4184
        }
4185
        private void btnSer1_val2_Click(object sender, RoutedEventArgs e)
4186
        {
4187
            if (textBoxSerial1_val2.Text.Length > 0)
4188
            {
4189
                SerChan1ScaleSlider.Value = Convert.ToInt16(textBoxSerial1_val2.Text);
4190
            }
4191
        }
4192
        private void btnSer1_val3_Click(object sender, RoutedEventArgs e)
4193
        {
4194
            if (textBoxSerial1_val3.Text.Length > 0)
4195
            {
4196
                SerChan1ScaleSlider.Value = Convert.ToInt16(textBoxSerial1_val3.Text);
4197
            }
4198
        }
4199
 
4200
        private void SerChan2ScaleSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
4201
        {
4202
            if (!_init)
4203
            {
4204
                serChan[1] = (int)SerChan2ScaleSlider.Value;
4205
                _sendSerialData();
4206
            }
4207
        }
4208
        private void textBoxSerial2_TextChanged(object sender, TextChangedEventArgs e)
4209
        {
4210
            if (!_init)
4211
            {
4212
                serChanTitle[1] = textBoxSerial2.Text;
4213
            }
4214
        }
4215
        private void textBoxSerial2_val1_TextChanged(object sender, TextChangedEventArgs e)
4216
        {
4217
            if (textBoxSerial2_val1.Text.Length > 0 & !_init)
4218
            {
4219
                serChan_sub[3] = Convert.ToInt16(textBoxSerial2_val1.Text);
4220
            }
4221
        }
4222
        private void textBoxSerial2_val2_TextChanged(object sender, TextChangedEventArgs e)
4223
        {
4224
            if (textBoxSerial2_val2.Text.Length > 0 & !_init)
4225
            {
4226
                serChan_sub[4] = Convert.ToInt16(textBoxSerial2_val2.Text);
4227
            }
4228
        }
4229
        private void textBoxSerial2_val3_TextChanged(object sender, TextChangedEventArgs e)
4230
        {
4231
            if (textBoxSerial2_val3.Text.Length > 0 & !_init)
4232
            {
4233
                serChan_sub[5] = Convert.ToInt16(textBoxSerial2_val3.Text);
4234
            }
4235
        }
4236
        private void btnSer2_0_Click(object sender, RoutedEventArgs e)
4237
        {
4238
            SerChan2ScaleSlider.Value = 0;
4239
        }
4240
        private void btnSer2_127_Click(object sender, RoutedEventArgs e)
4241
        {
4242
            SerChan2ScaleSlider.Value = 127;
4243
        }
4244
        private void btnSer2_254_Click(object sender, RoutedEventArgs e)
4245
        {
4246
            SerChan2ScaleSlider.Value = 254;
4247
        }
4248
        private void btnSer2_val1_Click(object sender, RoutedEventArgs e)
4249
        {
4250
            if (textBoxSerial2_val1.Text.Length > 0)
4251
            {
4252
                SerChan2ScaleSlider.Value = Convert.ToInt16(textBoxSerial2_val1.Text);
4253
            }
4254
        }
4255
        private void btnSer2_val2_Click(object sender, RoutedEventArgs e)
4256
        {
4257
            if (textBoxSerial2_val2.Text.Length > 0)
4258
            {
4259
                SerChan2ScaleSlider.Value = Convert.ToInt16(textBoxSerial2_val2.Text);
4260
            }
4261
        }
4262
        private void btnSer2_val3_Click(object sender, RoutedEventArgs e)
4263
        {
4264
            if (textBoxSerial2_val3.Text.Length > 0)
4265
            {
4266
                SerChan2ScaleSlider.Value = Convert.ToInt16(textBoxSerial2_val3.Text);
4267
            }
4268
        }
4269
 
4270
        private void SerChan3ScaleSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
4271
        {
4272
            if (!_init)
4273
            {
4274
                serChan[2] = (int)SerChan3ScaleSlider.Value;
4275
                _sendSerialData();
4276
            }
4277
        }
4278
        private void textBoxSerial3_TextChanged(object sender, TextChangedEventArgs e)
4279
        {
4280
            if (!_init)
4281
            {
4282
                serChanTitle[2] = textBoxSerial3.Text;
4283
            }
4284
        }
4285
        private void textBoxSerial3_val1_TextChanged(object sender, TextChangedEventArgs e)
4286
        {
4287
            if (textBoxSerial3_val1.Text.Length > 0 & !_init)
4288
            {
4289
                serChan_sub[6] = Convert.ToInt16(textBoxSerial3_val1.Text);
4290
            }
4291
        }
4292
        private void textBoxSerial3_val2_TextChanged(object sender, TextChangedEventArgs e)
4293
        {
4294
            if (textBoxSerial3_val2.Text.Length > 0 & !_init)
4295
            {
4296
                serChan_sub[7] = Convert.ToInt16(textBoxSerial3_val2.Text);
4297
            }
4298
        }
4299
        private void textBoxSerial3_val3_TextChanged(object sender, TextChangedEventArgs e)
4300
        {
4301
            if (textBoxSerial3_val3.Text.Length > 0 & !_init)
4302
            {
4303
                serChan_sub[8] = Convert.ToInt16(textBoxSerial3_val3.Text);
4304
            }
4305
        }
4306
        private void btnSer3_0_Click(object sender, RoutedEventArgs e)
4307
        {
4308
            SerChan3ScaleSlider.Value = 0;
4309
        }
4310
        private void btnSer3_127_Click(object sender, RoutedEventArgs e)
4311
        {
4312
            SerChan3ScaleSlider.Value = 127;
4313
        }
4314
        private void btnSer3_254_Click(object sender, RoutedEventArgs e)
4315
        {
4316
            SerChan3ScaleSlider.Value = 254;
4317
        }
4318
        private void btnSer3_val1_Click(object sender, RoutedEventArgs e)
4319
        {
4320
            if (textBoxSerial3_val1.Text.Length > 0)
4321
            {
4322
                SerChan3ScaleSlider.Value = Convert.ToInt16(textBoxSerial3_val1.Text);
4323
            }
4324
        }
4325
        private void btnSer3_val2_Click(object sender, RoutedEventArgs e)
4326
        {
4327
            if (textBoxSerial3_val2.Text.Length > 0)
4328
            {
4329
                SerChan3ScaleSlider.Value = Convert.ToInt16(textBoxSerial3_val2.Text);
4330
            }
4331
        }
4332
        private void btnSer3_val3_Click(object sender, RoutedEventArgs e)
4333
        {
4334
            if (textBoxSerial3_val3.Text.Length > 0)
4335
            {
4336
                SerChan3ScaleSlider.Value = Convert.ToInt16(textBoxSerial3_val3.Text);
4337
            }
4338
        }
4339
        /// <summary>
4340
        /// checks the input of a textbox
4341
        /// for valid data
4342
        /// in this case values 0-254
4343
        /// </summary>
4344
        /// <param name="sender"></param>
4345
        /// <param name="e"></param>
4346
        private void textBox_serial_KeyPress(object sender, KeyEventArgs e)
4347
        {
4348
            if ("1234567890,\b".IndexOf(e.Key.ToString()) < 0) //general check for valid chars(0-9) and backspace (\b)
4349
                e.Handled = true;
4350
            else
4351
            if ("\b".IndexOf(e.Key.ToString()) < 0)
4352
                if (Convert.ToInt16(((TextBox)sender).Text + e.Key) > 254) //if valid and not backspace, check for upper limit of the resulting number
4353
                    e.Handled = true;
4354
                else
4355
                {
4356
                    int i = -1;
4357
                    switch (((TextBox)sender).Name)
4358
                    {
4359
                        case "textBoxSerial1_val1":
4360
                            i = 0;
4361
                            break;
4362
                        case "textBoxSerial1_val2":
4363
                            i = 1;
4364
                            break;
4365
                        case "textBoxSerial1_val3":
4366
                            i = 2;
4367
                            break;
4368
                        case "textBoxSerial2_val1":
4369
                            i = 3;
4370
                            break;
4371
                        case "textBoxSerial2_val2":
4372
                            i = 4;
4373
                            break;
4374
                        case "textBoxSerial2_val3":
4375
                            i = 5;
4376
                            break;
4377
                        case "textBoxSerial3_val1":
4378
                            i = 6;
4379
                            break;
4380
                        case "textBoxSerial3_val2":
4381
                            i = 7;
4382
                            break;
4383
                        case "textBoxSerial3_val3":
4384
                            i = 8;
4385
                            break;
4386
                        case "textBoxSerial4_val1":
4387
                            i = 9;
4388
                            break;
4389
                        case "textBoxSerial4_val2":
4390
                            i = 10;
4391
                            break;
4392
                        case "textBoxSerial4_val3":
4393
                            i = 11;
4394
                            break;
4395
                    }
4396
                    if (i > -1)
4397
                        serChan_sub[i] = Convert.ToInt16(((TextBox)sender).Text + e.Key.ToString());
4398
                }
4399
        }
4400
 
4401
        #endregion serial channels
4402
        #region WP
4403
        void _readWPLFile()
4404
        {
4405
            Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
4406
            fd.Filter = "Waypointlists | *.wpl";
4407
            fd.Multiselect = false;
4408
            if (fd.ShowDialog().Value)
4409
            {
4410
                string file = fd.SafeFileName;
4411
                IniFile ini = new IniFile(fd.SafeFileName);
4412
                ini.path = fd.FileName;
4413
 
4414
                try
4415
                {
4416
                    string sVal = ini.IniReadValue("General", "FileVersion");
4417
                    if (sVal == "")
4418
                        MessageBox.Show("The file has no version declared - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
4419
                    else
4420
                    {
4421
                        if (Convert.ToInt16(sVal) < 3)
4422
                            MessageBox.Show("The file version is not supported - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
4423
                        else
4424
                        {
4425
                            sVal = ini.IniReadValue("General", "NumberOfWaypoints");
4426
                            if (sVal == "")
4427
                                MessageBox.Show("The file has no number of waypoints declared - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
4428
                            else
4429
                            {
4430
                                int wpnum = Convert.ToInt16(sVal);
4431
                                string wp;
4432
                                int i;
4433
                                NumberFormatInfo nfi = new NumberFormatInfo();
4434
                                nfi.NumberDecimalSeparator = ".";
4435
                                dtWaypoints.Rows.Clear();
4436
                                _wpEdit = -1;_wpIndex = -1;
4437
                                wpOffset.Clear();
4438
                                _clearMapMarkers(typeof(CustomMarkerWP));
4439
                                _clearMapMarkers(typeof(CustomMarkerWPActive));
4440
                                wpList.Clear();
4441
                                if (mRouteWP != null)
4442
                                    MainMap.Markers.Remove(mRouteWP);
4443
                                //if (wpActiveMarker != null)
4444
                                //    MainMap.Markers.Remove(wpActiveMarker);
4445
                                Dispatcher.Invoke(() => lblWPRouteDistance.Content = "0 m");
4446
 
4447
                                for (int k = 1; k <= wpnum; k++)
4448
                                {
4449
                                    DataRow dr = dtWaypoints.NewRow();
4450
                                    dr.ItemArray = new object[16];
4451
                                    object[] o = new object[16];
4452
                                    i = 0;
4453
                                    wp = "Point" + k.ToString();
4454
                                    o[i] = k;
4455
                                    i++;
4456
                                    sVal = ini.IniReadValue(wp, "Type");
4457
                                    if (sVal != "")
4458
                                        o[i] = Convert.ToInt16(sVal) - 1;
4459
                                    i++;
4460
                                    sVal = ini.IniReadValue(wp, "Prefix");
4461
                                    if (sVal != "")
4462
                                        o[i] = sVal + k.ToString();
4463
                                   //     o[i] = sVal == "0" ? "!" + k.ToString() : sVal + k.ToString();
4464
                                    i++;
4465
                                    sVal = ini.IniReadValue(wp, "Latitude");
4466
                                    if (sVal != "")
4467
                                        o[i] = Convert.ToDouble(sVal, nfi);
4468
                                    i++;
4469
                                    sVal = ini.IniReadValue(wp, "Longitude");
4470
                                    if (sVal != "")
4471
                                        o[i] = Convert.ToDouble(sVal, nfi);
4472
                                    i++;
4473
                                    sVal = ini.IniReadValue(wp, "Altitude");
4474
                                    if (sVal != "")
4475
                                        o[i] = Convert.ToDouble(sVal, nfi);
4476
                                    i++;
4477
                                    sVal = ini.IniReadValue(wp, "Heading");
4478
                                    if (sVal != "")
4479
                                        o[i] = Convert.ToInt16(sVal);
4480
                                    i++;
4481
                                    sVal = ini.IniReadValue(wp, "Speed");
4482
                                    if (sVal != "")
4483
                                        o[i] = Convert.ToInt16(sVal);
4484
                                    i++;
4485
                                    sVal = ini.IniReadValue(wp, "ClimbRate");
4486
                                    if (sVal != "")
4487
                                        o[i] = Convert.ToInt16(sVal);
4488
                                    i++;
4489
                                    sVal = ini.IniReadValue(wp, "Radius");
4490
                                    if (sVal != "")
4491
                                        o[i] = Convert.ToInt16(sVal);
4492
                                    i++;
4493
                                    sVal = ini.IniReadValue(wp, "DelayTime");
4494
                                    if (sVal != "")
4495
                                        o[i] = Convert.ToInt16(sVal);
4496
                                    i++;
4497
                                    sVal = ini.IniReadValue(wp, "AutoTrigger");
4498
                                    if (sVal != "")
4499
                                        o[i] = Convert.ToInt16(sVal); ;
4500
                                    i++;
4501
                                    sVal = ini.IniReadValue(wp, "CAM-Nick");
4502
                                    if (sVal != "")
4503
                                        o[i] = Convert.ToInt16(sVal);
4504
                                    i++;
4505
                                    o[i] = 0;
4506
                                    i++;
4507
                                    sVal = ini.IniReadValue(wp, "WP_Event_Channel_Value");
4508
                                    if (sVal != "")
4509
                                        o[i] = Convert.ToInt16(sVal);
4510
                                    i++;
4511
                                    o[i] = "New";
4512
 
4513
                                    dr.ItemArray = o;
4514
                                    dtWaypoints.Rows.Add(dr);
4515
                                    _createWP(new PointLatLng((double)o[3], (double)o[4]), (string)dr[2], (int)o[1], (int)o[0]-1);
4516
 
4517
                                    Dispatcher.Invoke(() => lblWPIndex.Content = k.ToString());
4518
                                    Dispatcher.Invoke(() => lblWPCount.Content = k.ToString());
4519
                                    Dispatcher.Invoke(() => dgvWP.Items.Refresh());
4520
                                    Thread.Sleep(1);
4521
                                }
4522
                                Dispatcher.Invoke(() => MainMap.Position = new PointLatLng((double)dtWaypoints.Rows[0][3], (double)dtWaypoints.Rows[0][4]));
4523
                                Dispatcher.Invoke(() => MainMap.Zoom = 19);
4524
                             //   Dispatcher.Invoke(() => MainMap.ZoomAndCenterMarkers(null));
4525
                                Dispatcher.Invoke(() => _routeUpdate());
4526
                            }
4527
                        }
4528
                    }
4529
 
4530
                }
4531
                catch (Exception e)
4532
                {
4533
 
4534
                    MessageBox.Show("Error parsing wpl-file!" + Environment.NewLine + e.Message, "Read wpl-file", MessageBoxButton.OK, MessageBoxImage.Error);
4535
                }
4536
 
4537
            }
4538
        }
4539
        void _saveWPLFile()
4540
        {
4541
            if (dtWaypoints.Rows.Count > 0)
4542
            {
4543
                Microsoft.Win32.SaveFileDialog fd = new Microsoft.Win32.SaveFileDialog();
4544
                fd.Filter = "Waypointlists | *.wpl";
4545
                fd.AddExtension = true;
4546
                if (fd.ShowDialog().Value)
4547
                {
4548
                    string file = fd.SafeFileName;
4549
                    IniFile ini = new IniFile(fd.SafeFileName);
4550
                    ini.path = fd.FileName;
4551
                    NumberFormatInfo nfi = new NumberFormatInfo();
4552
                    nfi.NumberDecimalSeparator = ".";
4553
 
4554
                    try
4555
                    {
4556
                        ini.IniWriteValue("General", "FileVersion", "3");
4557
                        ini.IniWriteValue("General", "NumberOfWaypoints", dtWaypoints.Rows.Count.ToString());
4558
                        ini.IniWriteValue("General", "Mapfile", "");
4559
                        for(int i = 1; i<=dtWaypoints.Rows.Count; i++)
4560
                        {
4561
                            ini.IniWriteValue("Point" + i.ToString(), "Latitude", ((double)(dtWaypoints.Rows[i-1][3])).ToString(nfi));
4562
                            ini.IniWriteValue("Point" + i.ToString(), "Longitude", ((double)(dtWaypoints.Rows[i - 1][4])).ToString(nfi));
4563
                            ini.IniWriteValue("Point" + i.ToString(), "Radius", dtWaypoints.Rows[i - 1][9].ToString());
4564
                            ini.IniWriteValue("Point" + i.ToString(), "Altitude", dtWaypoints.Rows[i - 1][5].ToString());
4565
                            ini.IniWriteValue("Point" + i.ToString(), "ClimbRate", dtWaypoints.Rows[i - 1][8].ToString());
4566
                            ini.IniWriteValue("Point" + i.ToString(), "DelayTime", dtWaypoints.Rows[i - 1][10].ToString());
4567
                            ini.IniWriteValue("Point" + i.ToString(), "WP_Event_Channel_Value", dtWaypoints.Rows[i - 1][14].ToString());
4568
                            ini.IniWriteValue("Point" + i.ToString(), "Heading", dtWaypoints.Rows[i - 1][6].ToString());
4569
                            ini.IniWriteValue("Point" + i.ToString(), "Speed", dtWaypoints.Rows[i - 1][7].ToString());
4570
                            ini.IniWriteValue("Point" + i.ToString(), "CAM-Nick", dtWaypoints.Rows[i - 1][12].ToString());
4571
                            ini.IniWriteValue("Point" + i.ToString(), "Type", ((int)dtWaypoints.Rows[i - 1][1]+1).ToString());
4572
                            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));
4573
                            ini.IniWriteValue("Point" + i.ToString(), "AutoTrigger", dtWaypoints.Rows[i - 1][11].ToString());
4574
                        }
4575
                        MessageBox.Show(dtWaypoints.Rows.Count.ToString() + " points saved to " + file, "Waypointlist saved", MessageBoxButton.OK, MessageBoxImage.Information);
4576
                    }
4577
                    catch { }
4578
                }
4579
            }
4580
            else
4581
                MessageBox.Show("Nothing to save...");
4582
        }
4583
        private void btnSaveWPLFile_Click(object sender, RoutedEventArgs e)
4584
        {
4585
            _saveWPLFile();
4586
        }
4587
        /// <summary>
4588
        /// set the selected color for the route
4589
        /// </summary>
4590
        /// <param name="color"></param>
4591
        /// <returns></returns>
4592
        Brush _getBrush(string color)
4593
        {
4594
            switch (color)
4595
            {
4596
                case "red":
4597
                    return Brushes.Red;
4598
                case "green":
4599
                    return Brushes.Lime;
4600
                case "blue":
4601
                    return Brushes.Aqua;
4602
                case "pink":
4603
                    return Brushes.Magenta;
4604
                case "yellow":
4605
                    return Brushes.Yellow;
4606
                default:
4607
                    return Brushes.Magenta;
4608
            }
4609
        }
4610
        void _routeUpdate()
4611
        {
4612
            Dispatcher.Invoke(() =>
4613
            {
4614
                if (comboBoxRouteColor.SelectionBoxItem != null)
4615
                {
4616
                    string s = comboBoxRouteColor.SelectionBoxItem.ToString();
4617
                    mRouteWP = new GMapRoute(wpList, _getBrush(s));
4618
                }
4619
                else
4620
                    mRouteWP = new GMapRoute(wpList, null);
4621
 
4622
                if (_bShowWPRoute)
4623
                    MainMap.Markers.Add(mRouteWP);
4624
            });
4625
 
4626
            MapRoute mr = new MapRoute(wpList, "WPList");
4627
            Dispatcher.Invoke(() => lblWPRouteDistance.Content = (mr.Distance * 1000).ToString("0 m"));
4628
        }
4629
        GMapMarker _createWP(PointLatLng p, string name, int type, int index)
4630
        {
4631
            GMapMarker wpMarker = new GMapMarker(p);
4632
            Dispatcher.Invoke(()=>
4633
            {
4634
                wpMarker.Shape = new CustomMarkerWP(this, wpMarker, name, type);
4635
                wpMarker.Tag = name;
4636
                wpMarker.Offset = new System.Windows.Point(-11.5, -11.5);
4637
                wpMarker.ZIndex = 100;
4638
                _setMarkerColor(wpMarker, type);
4639
                MainMap.Markers.Add(wpMarker);
4640
                if (type == 0 || type == 3)
4641
                {
4642
                    wpList.Add(p);
4643
                    wpOffset.Add(index);
4644
                }
4645
                ((CustomMarkerWP)wpMarker.Shape).positionChanged += _updateDTWPPos;
4646
                ((CustomMarkerWP)wpMarker.Shape).newPosition += _updateDTWPPosFin;
4647
                ((CustomMarkerWP)wpMarker.Shape).mouseCaptured += _WPMouseCaptured;
4648
                _setMapItemsSize("WP", SliderWPZoom.Value);
4649
            });
4650
            return wpMarker;
4651
        }
4652
        bool _WPisMouseCaptured = false;
4653
        void _WPMouseCaptured(bool isCaptured)
4654
        {
4655
            _WPisMouseCaptured = isCaptured;
4656
            MainMap.CanDragMap = !isCaptured;
4657
        }
4658
        void _updateDTWPPos(CustomMarkerWP wp)
4659
        {
4660
            string sIndex = wp.WPText.Substring(1, wp.WPText.Length - 1);
4661
            int index = Convert.ToInt16(sIndex) -1;
4662
            GMapMarker p = ((GMapMarker)wp.DataContext);
4663
            if (p != null && index < dtWaypoints.Rows.Count)
4664
            {
4665
                //Dispatcher.Invoke(() => dgvWP.Items.Refresh());
4666
                if(wp.WPType == 0 | wp.WPType == 3)
4667
                {
4668
                    PointLatLng x = new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]);
4669
                    int wpListIndex = wpList.IndexOf(x);
4670
                    if (wpListIndex > -1)
4671
                    {
4672
                        wpList[wpListIndex] = p.Position;
4673
                        MainMap.Markers.Remove(mRouteWP);
4674
                        _routeUpdate();
4675
                    }
4676
                }
4677
                dtWaypoints.Rows[index][3] = p.Position.Lat;
4678
                dtWaypoints.Rows[index][4] = p.Position.Lng;
4679
            }
4680
        }
4681
        void _updateDTWPPosFin(CustomMarkerWP wp)
4682
        {
4683
            string sIndex = wp.WPText.Substring(1, wp.WPText.Length - 1);
4684
            int index = Convert.ToInt16(sIndex) -1;
4685
            GMapMarker p = ((GMapMarker)wp.DataContext);
4686
            if (p != null && index < dtWaypoints.Rows.Count)
4687
            {
4688
                dtWaypoints.Rows[index][3] = p.Position.Lat;
4689
                dtWaypoints.Rows[index][4] = p.Position.Lng;
4690
                Dispatcher.Invoke(() =>
4691
                {
4692
                    dgvWP.Items.Refresh();
4693
                    dgvWP.SelectedIndex = index;
4694
                    _dgvWPselectEditRow();
4695
                });
4696
 
4697
            }
4698
 
4699
        }
4700
        void _addWP(PointLatLng p,int type)
4701
        {
4702
            object[] o = new object[16];
4703
 
4704
            o[0] = dgvWP.ItemContainerGenerator.Items.Count + 1;
4705
            o[1] = type;
4706
            //     cbWPEditType.SelectedIndex = 0;
4707
            //  tbWPEditPrefix.Text = "P";
4708
            o[2] = _wpDefPrefix + o[0].ToString();
4709
            //   tbWPEditLat.Text = copter.Position.Lat.ToString();
4710
            o[3] = p.Lat;
4711
            //  tbWPEditLon.Text = copter.Position.Lng.ToString();
4712
            o[4] = p.Lng;
4713
            //   lblWPEditAlt.Content = ((double)iAnalogData[4] / (double)10).ToString();
4714
            o[5] = _wpAddCopterHeight ? iAnalogData[4].ToString(): _wpDefAltitude.ToString();
4715
 
4716
            cbWPEditHeading.SelectedIndex = _wpDefCBoxHeading;
4717
            o[6] = _wpAddCopterHeading ? iAnalogData[10].ToString(): _wpDefHeading.ToString();
4718
            //lblWPEditHeading.Content = iAnalogData[10].ToString();
4719
            //    tbWPEditHeading.IsReadOnly = false;
4720
 
4721
            cbWPEditSpeed.SelectedIndex = _wpDefCBoxSpeed;
4722
            //     tbWPEditSpeed.Text = "5.0";
4723
            //     tbWPEditSpeed.IsReadOnly = false;
4724
            o[7] = _wpDefSpeed.ToString();
4725
 
4726
            cbWPEditClimbrate.SelectedIndex = _wpDefCBoxClimb;
4727
            //       lblWPEditClimbrate.Content = "5.0";
4728
            //       tbWPEditClimbrate.IsReadOnly = false;
4729
            o[8] = _wpDefClimb.ToString();
4730
 
4731
            //       lblWPEditRadius.Content = "10";
4732
            o[9] = _wpDefRadius.ToString();
4733
            //       lblWPEditHoldtime.Content = "5";
4734
            o[10] = _wpDefHoldtime.ToString();
4735
            //      lblWPEditAutoTrigger.Content = "0";
4736
            o[11] = _wpDefAutotrig.ToString();
4737
            cbWPEditCamAngle.SelectedIndex = _wpDefCBoxCamangle;
4738
            //       lblWPEditCamAngle.Content = "AUTO";
4739
            //       tbWPEditCamAngle.IsReadOnly = true;
4740
            o[12] = _wpDefCamangle.ToString();
4741
 
4742
            o[13] = "0";
4743
            //     lblWPEditOut1.Content = "0";
4744
            o[14] = _wpDefOut1.ToString();
4745
            o[15] = "0";
4746
 
4747
            dtWaypoints.Rows.Add(o);
4748
            _createWP(new PointLatLng((double)o[3], (double)o[4]), (string)o[2], (int)o[1], (int)o[0] - 1);
4749
            // Dispatcher.Invoke(() => lblWPCount.Content = o[0].ToString());
4750
            if (mRouteWP != null)
4751
                MainMap.Markers.Remove(mRouteWP);
4752
            _routeUpdate();
4753
            Dispatcher.Invoke(() =>
4754
            {
4755
                dgvWP.Items.Refresh();
4756
                dgvWP.UpdateLayout();
4757
                dgvWP.SelectedIndex = (int)o[0] - 1;
4758
                _dgvWPselectEditRow();
4759
            });
4760
        }
4761
        /// <summary>
4762
        /// find the index of of a wp from datatable in the waypointlist wpList
4763
        /// </summary>
4764
        /// <param name="dtIndex">the index of wp in datatable (0-based)</param>
4765
        /// <returns></returns>
4766
        int _getWPIndexfromList(int dtIndex)
4767
        {
4768
            if ((int)dtWaypoints.Rows[dtIndex][1] == 0 || (int)dtWaypoints.Rows[dtIndex][1] == 3)
4769
            {
4770
                GMapMarker wp = _findWPMarker((string)dtWaypoints.Rows[dtIndex][2]);
4771
                if (wp != null)
4772
                    return wpList.IndexOf(wp.Position);
4773
            }
4774
            return -1;
4775
        }
4776
        /// <summary>
4777
        /// find the index of of a wp from datatable in the waypointlist wpList
4778
        /// </summary>
4779
        /// <param name="name">the name of the wp</param>
4780
        /// <returns></returns>
4781
        int _getWPIndexfromList(string name)
4782
        {
4783
            GMapMarker wp = _findWPMarker(name);
4784
            if ((wp != null && wp.Shape != null) && ((CustomMarkerWP)wp.Shape).WPType == 0 | ((CustomMarkerWP)wp.Shape).WPType == 3)
4785
                return wpList.IndexOf(wp.Position);
4786
            else
4787
                return -1;
4788
        }
4789
        int _getWPListOffset(int index)
4790
        {
4791
            int k = 0;
4792
            for(int i = 0; i < wpOffset.Count;i++)
4793
            {
4794
                if (wpOffset[i] <= index)
4795
                    k++;
4796
            }
4797
 
4798
            return k;
4799
        }
4800
        void _setMarkerColor(GMapMarker wpMarker,int iType)
4801
        {
4802
            if(wpMarker != null)
4803
            Dispatcher.Invoke(() =>
4804
            {
4805
                switch (iType)
4806
                {
4807
                    case 0:
4808
                        if (comboBoxWPColor.SelectionBoxItem != null)
4809
                        {
4810
                            string s = comboBoxWPColor.SelectionBoxItem.ToString();
4811
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
4812
                        }
4813
                        else
4814
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor("green");
4815
                        break;
4816
                    case 1:
4817
                        if (comboBoxPOIColor.SelectionBoxItem != null)
4818
                        {
4819
                            string s = comboBoxPOIColor.SelectionBoxItem.ToString();
4820
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
4821
                        }
4822
                        else
4823
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor("pink");
4824
                        break;
4825
                    case 2:
4826
                        if (comboBoxFSColor.SelectionBoxItem != null)
4827
                        {
4828
                            string s = comboBoxFSColor.SelectionBoxItem.ToString();
4829
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
4830
                        }
4831
                        else
4832
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
4833
                        break;
4834
                    case 3:
4835
                        if (comboBoxLandingColor.SelectionBoxItem != null)
4836
                        {
4837
                            string s = comboBoxLandingColor.SelectionBoxItem.ToString();
4838
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
4839
                        }
4840
                        else
4841
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor("blue");
4842
                        break;
4843
                    default:
4844
                        ((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
4845
                        break;
4846
                }
4847
            });
4848
 
4849
        }
4850
        void _MarkerColorSelection(object sender,int type)
4851
        {
4852
            Dispatcher.Invoke(() =>
4853
            {
4854
                if (((ComboBox)sender).SelectionBoxItem != null)
4855
                {
4856
                    for (int k = 0; k < MainMap.Markers.Count; k++)
4857
                    {
4858
                        GMapMarker p = MainMap.Markers[k];
4859
                        if (p.Shape != null && p.Shape.GetType() == typeof(CustomMarkerWP))
4860
                        {
4861
                            if (((CustomMarkerWP)p.Shape).WPType == type)
4862
                            {
4863
                                string s = ((ComboBox)sender).SelectionBoxItem.ToString();
4864
                                ((CustomMarkerWP)(p.Shape)).setColor(s);
4865
                            }
4866
                        }
4867
                    }
4868
                }
4869
            });
4870
        }
4871
        private void comboBoxWPColor_DropDownClosed(object sender, EventArgs e)
4872
        {
4873
            _MarkerColorSelection(sender, 0);
4874
        }
4875
        private void comboBoxPOIColor_DropDownClosed(object sender, EventArgs e)
4876
        {
4877
            _MarkerColorSelection(sender, 1);
4878
        }
4879
        private void comboBoxFSColor_DropDownClosed(object sender, EventArgs e)
4880
        {
4881
            _MarkerColorSelection(sender, 2);
4882
        }
4883
        private void comboBoxLandingColor_DropDownClosed(object sender, EventArgs e)
4884
        {
4885
            _MarkerColorSelection(sender,3);
4886
        }
4887
        private void comboBoxCopterColor_DropDownClosed(object sender, EventArgs e)
4888
        {
4889
            Dispatcher.Invoke(() => {
4890
                if (comboBoxCopterColor.SelectionBoxItem != null)
4891
                {
4892
                    string s = comboBoxCopterColor.SelectionBoxItem.ToString();
4893
                    ((CustomMarkerCopter)(copter.Shape)).setCopterColor(s);
4894
                }
4895
                else
4896
                    ((CustomMarkerCopter)(copter.Shape)).setCopterColor("red");
4897
            });
4898
        }
4899
        private void comboBoxCopterHeadingColor_DropDownClosed(object sender, EventArgs e)
4900
        {
4901
            Dispatcher.Invoke(() => {
4902
                if (comboBoxCopterHeadingColor.SelectionBoxItem != null)
4903
                {
4904
                    string s = comboBoxCopterHeadingColor.SelectionBoxItem.ToString();
4905
                    ((CustomMarkerCopter)(copter.Shape)).setHeadingColor(s);
4906
                }
4907
                else
4908
                    ((CustomMarkerCopter)(copter.Shape)).setHeadingColor("red");
4909
            });
4910
        }
4911
        private void comboBoxRouteColor_DropDownClosed(object sender, EventArgs e)
4912
        {
4913
            Dispatcher.Invoke(() =>
4914
            {
4915
                if (comboBoxRouteColor.SelectionBoxItem != null)
4916
                {
4917
                    string s = comboBoxRouteColor.SelectionBoxItem.ToString();
4918
                    MainMap.Markers.Remove(mRouteWP);
4919
                    mRouteWP = new GMapRoute(wpList, _getBrush(s));
4920
                    if (_bShowWPRoute)
4921
                        MainMap.Markers.Add(mRouteWP);
4922
                }
4923
            });
4924
        }
4925
        private void comboBoxWPMaxRangeColor_DropDownClosed(object sender, EventArgs e)
4926
        {
4927
            Dispatcher.Invoke(() =>
4928
            {
4929
                if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
4930
                {
4931
                    if (home != null && checkBoxShowWPMaxRange.IsChecked == true && dWPMaxRange > 0)
4932
                    {
4933
                        if (cWPBound != null && cWPBound.Tag != null)
4934
                            MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
4935
 
4936
                       createCircle(home.Position, dWPMaxRange);
4937
                       string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
4938
                       cWPBound.setColor(s);
4939
 
4940
                    }
4941
                }
4942
            });
4943
 
4944
        }
4945
        private void checkBoxShowWPRoute_Click(object sender, RoutedEventArgs e)
4946
        {
4947
            _bShowWPRoute = (bool)checkBoxShowWPRoute.IsChecked;
4948
            if (_bShowWPRoute)
4949
            {
4950
                if (mRouteWP != null)
4951
                    MainMap.Markers.Add(mRouteWP);
4952
            }
4953
            else
4954
            {
4955
                if (mRouteWP != null)
4956
                    MainMap.Markers.Remove(mRouteWP);
4957
            }
4958
        }
4959
 
4960
        private void btnLoadWPLFile_Click(object sender, RoutedEventArgs e)
4961
        {
4962
            _readWPLFile();
4963
        }
4964
        private void btnClearWPList_Click(object sender, RoutedEventArgs e)
4965
        {
4966
            _clearMapMarkers(typeof(CustomMarkerWP));
4967
            _clearMapMarkers(typeof(CustomMarkerWPActive));
4968
            wpList.Clear();
4969
            if (mRouteWP != null)
4970
                MainMap.Markers.Remove(mRouteWP);
4971
            //if (wpActiveMarker != null)
4972
            //    MainMap.Markers.Remove(wpActiveMarker);
4973
            dtWaypoints.Rows.Clear();
4974
            _wpEdit = -1;
4975
            _wpIndex = -1;
4976
            wpOffset.Clear();
4977
            Dispatcher.Invoke(() => dgvWP.Items.Refresh());
4978
            Dispatcher.Invoke(() => lblWPIndex.Content = 0);
4979
            Dispatcher.Invoke(() => lblWPCount.Content = 0);
4980
            Dispatcher.Invoke(() => lblWPRouteDistance.Content = "0 m");
4981
        }
4982
        private void btnClearCopterList_Click(object sender, RoutedEventArgs e)
4983
        {
4984
            Thread t = new Thread(new ThreadStart(clearCopterWPList));
4985
            t.Start();
4986
        }
4987
        private void btnSendActiveWP_Click(object sender, RoutedEventArgs e)
4988
        {
4989
            if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
4990
            {
4991
                if (_wpCount > 0)
4992
                    _sendWayPoint(dtWaypoints.Rows[dgvWP.SelectedIndex], -1, 's',false);
4993
                else
4994
                    _sendWayPoint(dtWaypoints.Rows[dgvWP.SelectedIndex], 1, 's',false);
4995
 
4996
                //int index = dgvWP.SelectedIndex;
4997
                //Thread t = new Thread(() => _sendWPList(index));
4998
                //t.Start();
4999
 
5000
                Dispatcher.Invoke(() => {
5001
                    DataGridRow row;
5002
                    if (_wpEdit > -1 && _wpEdit < dgvWP.ItemContainerGenerator.Items.Count)
5003
                    {
5004
                        row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
5005
                        row.Background = new SolidColorBrush(Colors.Transparent);
5006
                        row.BorderBrush = new SolidColorBrush(Colors.Transparent);
5007
                        row.BorderThickness = new Thickness(0);
5008
                        dgvWP.UpdateLayout();
5009
                    }
5010
                    //_wpEdit = dgvWP.SelectedIndex;
5011
                    //row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
5012
                    //row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 255, 100));
5013
                    //row.BorderBrush = new SolidColorBrush(Colors.SpringGreen);
5014
                    //row.BorderThickness = new Thickness(2);
5015
                });
5016
            }
5017
        }
5018
        private void btnEditWPSendToCopter_Click(object sender, RoutedEventArgs e)
5019
        {
5020
            if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
5021
            {
5022
 
5023
                object[] o = new object[16];
5024
                o[0] = dgvWP.SelectedIndex + 1;
5025
                o[1] = cbWPEditType.SelectedIndex;
5026
                o[2] = tbWPEditPrefix.Text + (dgvWP.SelectedIndex + 1).ToString();
5027
                o[3] = Convert.ToDouble(tbWPEditLat.Text.Replace('.', ','));
5028
                o[4] = Convert.ToDouble(tbWPEditLon.Text.Replace('.', ','));
5029
                o[5] = lblWPEditAlt.Content;
5030
                switch (cbWPEditHeading.SelectedIndex)
5031
                {
5032
                    case 0:
5033
                        o[6] = "0";
5034
                        break;
5035
                    case 1:
5036
                        o[6] = "-" + lblWPEditHeading.Content;
5037
                        break;
5038
                    case 2:
5039
                        o[6] = lblWPEditHeading.Content;
5040
                        break;
5041
                }
5042
                switch (cbWPEditSpeed.SelectedIndex)
5043
                {
5044
                    case 0:
5045
                        o[7] = "0";
5046
                        break;
5047
                    case 1:
5048
                        o[7] = (System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10).ToString("0");
5049
                        break;
5050
                    case 2:
5051
                        o[7] = (256 - Convert.ToInt16(lblWPEditSpeed.Content)).ToString();
5052
                        break;
5053
                }
5054
                switch (cbWPEditClimbrate.SelectedIndex)
5055
                {
5056
                    case 0:
5057
                        o[8] = "255";
5058
                        break;
5059
                    case 1:
5060
                        o[8] = (System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.', ',')) * 10).ToString("0");
5061
                        break;
5062
                }
5063
                o[9] = lblWPEditRadius.Content;
5064
                o[10] = lblWPEditHoldtime.Content;
5065
                o[11] = lblWPEditAutoTrigger.Content;
5066
                switch (cbWPEditCamAngle.SelectedIndex)
5067
                {
5068
                    case 0:
5069
                        o[12] = "0";
5070
                        break;
5071
                    case 1:
5072
                        o[12] = "255";
5073
                        break;
5074
                    case 2:
5075
                        o[12] = lblWPEditCamAngle.Content;
5076
                        break;
5077
                }
5078
                o[13] = 0;
5079
                o[14] = lblWPEditOut1.Content;
5080
                DataRow dr = dtWaypoints.NewRow();
5081
                dr.ItemArray = o;
5082
 
5083
                if (_wpCount > 0)
5084
                    _sendWayPoint(dr, -1, 'w', false);
5085
                else
5086
                    _sendWayPoint(dr, 1, 'w', false);
5087
 
5088
                if (_wpIndex > -1 && _wpIndex < dtWaypoints.Rows.Count)
5089
                    _sendWayPoint(dtWaypoints.Rows[wpOffset[_wpIndex]], _wpIndex+1, 's', false);
5090
            }
5091
        }
5092
        private void btnWPSimulateStart_Click(object sender, RoutedEventArgs e)
5093
        {
5094
            _Simulate = !_Simulate;
5095
            if (dtWaypoints.Rows.Count > 0)
5096
            {
5097
                DataRow dr = dtWaypoints.Rows[0];
5098
                dr[13] = _Simulate ? 3 : 0;
5099
                _sendWayPoint(dr, 0, 's', true);
5100
                rectSimulate.Visibility = lblSimu.Visibility = _Simulate ? Visibility.Visible : Visibility.Hidden;
5101
            }
5102
        }
5103
 
5104
        private void dgvWP_MouseUp(object sender, MouseButtonEventArgs e)
5105
        {
5106
            _dgvWPselectEditRow();
5107
        }
5108
        private void dgvWP_MouseDoubleClick(object sender, MouseButtonEventArgs e)
5109
        {
5110
        }
5111
        void _dgvWPselectEditRow()
5112
        {
5113
            if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
5114
            {
5115
               Dispatcher.Invoke(() => {
5116
                    DataGridRow row;
5117
                    dgvWP.Items.Refresh();
5118
                    dgvWP.UpdateLayout();
5119
                    if (_wpEdit > -1 && _wpEdit < dgvWP.ItemContainerGenerator.Items.Count)
5120
                    {
5121
                        row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
5122
                       if (row != null)
5123
                       {
5124
                           row.Background = new SolidColorBrush(Colors.Transparent);
5125
                           row.BorderBrush = new SolidColorBrush(Colors.Transparent);
5126
                           row.BorderThickness = new Thickness(0);
5127
                       }
5128
                    }
5129
                    _wpEdit = dgvWP.SelectedIndex;
5130
                    row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
5131
                   if (row != null)
5132
                   {
5133
                       row.Background = new SolidColorBrush(Color.FromArgb(80, 0, 100, 255));
5134
                       row.BorderBrush = new SolidColorBrush(Colors.Aqua);
5135
                       row.BorderThickness = new Thickness(2);
5136
                       dgvWP.UpdateLayout();
5137
                   }
5138
                    if (GridWPEdit.Visibility == Visibility.Collapsed && _bAutoWPEdit)
5139
                        GridWPEdit.Visibility = Visibility.Visible;
5140
 
5141
                    _setWPEditFields(_wpEdit);
5142
                });
5143
            }
5144
        }
5145
        void _setWPEditFields(int index)
5146
        {
5147
            if (GridWPEdit.Visibility == Visibility.Collapsed && _bAutoWPEdit)
5148
                GridWPEdit.Visibility = Visibility.Visible;
5149
 
5150
            int iVal;
5151
            lblWPEditIndex.Content = dtWaypoints.Rows[index][0].ToString();
5152
            cbWPEditType.SelectedIndex = (int)dtWaypoints.Rows[index][1];
5153
            tbWPEditPrefix.Text = dtWaypoints.Rows[index][2].ToString().Substring(0,1);
5154
            tbWPEditLat.Text = dtWaypoints.Rows[index][3].ToString();
5155
            tbWPEditLon.Text = dtWaypoints.Rows[index][4].ToString();
5156
 
5157
            SliderAlt.Value = Convert.ToInt16(dtWaypoints.Rows[index][5]);
5158
 
5159
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][6]);
5160
            SliderHeading.Value = Math.Abs(iVal);
5161
            if (iVal == 0)
5162
            {
5163
                cbWPEditHeading.SelectedIndex = 0;
5164
              //  lblWPEditHeading.Content = " - - -";
5165
            }
5166
            if (iVal > 0 && iVal < 360)
5167
            {
5168
                cbWPEditHeading.SelectedIndex = 2;
5169
              //  lblWPEditHeading.Content = iVal.ToString();
5170
            }
5171
            if (iVal < 0)
5172
            {
5173
                cbWPEditHeading.SelectedIndex = 1;
5174
             //   lblWPEditHeading.Content = (Math.Abs(iVal).ToString());
5175
            }
5176
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][7]);
5177
            SliderSpeed.Value = (double)iVal * 0.1;                                                  //------------!!!!!!!!
5178
            if (iVal == 0)
5179
            {
5180
                cbWPEditSpeed.SelectedIndex = 0;
5181
              //  lblWPEditSpeed.Content = "MAX";
5182
            }
5183
            if (iVal > 0 && iVal < 248)
5184
            {
5185
                cbWPEditSpeed.SelectedIndex = 1;
5186
              //  lblWPEditSpeed.Content = ((double)iVal * 0.1).ToString();
5187
            }
5188
            if (iVal > 247)
5189
            {
5190
                cbWPEditSpeed.SelectedIndex = 256 - iVal + 1;
5191
              //  lblWPEditSpeed.Content = "";
5192
            }
5193
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][8]);
5194
            SliderClimbrate.Value = (System.Convert.ToDouble(iVal) / 10);                              //------------!!!!!!!!
5195
            if (iVal == 255)
5196
            {
5197
                cbWPEditClimbrate.SelectedIndex = 0;
5198
             //   lblWPEditClimbrate.Content = "AUTO";
5199
            }
5200
            else
5201
            {
5202
                cbWPEditClimbrate.SelectedIndex = 1;
5203
               // lblWPEditClimbrate.Content = (System.Convert.ToDouble(iVal) / 10).ToString("0.0");
5204
            }
5205
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][9]);
5206
            SliderRadius.Value = iVal;
5207
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][10]);
5208
            SliderHoldTime.Value = iVal;
5209
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][11]);
5210
            SliderAutoTrigger.Value = iVal;
5211
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][12]);
5212
            SliderCamAngle.Value = iVal;
5213
            if (iVal == 0)
5214
            {
5215
                cbWPEditCamAngle.SelectedIndex = 0;
5216
              //  lblWPEditCamAngle.Content = " - - - ";
5217
            }
5218
            if (iVal < 0 | iVal == 255)
5219
            {
5220
                cbWPEditCamAngle.SelectedIndex = 1;
5221
              //  lblWPEditCamAngle.Content = "AUTO";
5222
            }
5223
            if (iVal > 0 & iVal < 255)
5224
            {
5225
                cbWPEditCamAngle.SelectedIndex = 2;
5226
             //   lblWPEditCamAngle.Content = iVal.ToString();
5227
            }
5228
            iVal = Convert.ToInt16(dtWaypoints.Rows[index][14]);
5229
            SliderOut1.Value = iVal;
5230
        }
5231
        private void btnEditWPSave_Click(object sender, RoutedEventArgs e)
5232
        {
5233
            if(dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
5234
            {
5235
                string oldName = (string)dtWaypoints.Rows[dgvWP.SelectedIndex][2];
5236
                int oldType = (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1];
5237
                PointLatLng pOld = new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]);
5238
                int i = wpList.IndexOf(pOld);
5239
                dtWaypoints.Rows[dgvWP.SelectedIndex][1] = cbWPEditType.SelectedIndex;
5240
                dtWaypoints.Rows[dgvWP.SelectedIndex][2] = tbWPEditPrefix.Text + (dgvWP.SelectedIndex + 1).ToString();
5241
                dtWaypoints.Rows[dgvWP.SelectedIndex][3] = Convert.ToDouble(tbWPEditLat.Text.Replace('.', ','));
5242
                dtWaypoints.Rows[dgvWP.SelectedIndex][4] = Convert.ToDouble(tbWPEditLon.Text.Replace('.', ','));
5243
                if (i > -1)
5244
                {
5245
                    if ((int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 0 || (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 3)
5246
                        wpList[i] = (new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]));
5247
                    else
5248
                    {
5249
                        wpList.Remove(pOld);
5250
                        wpOffset.Remove(wpOffset[i]);
5251
                    }
5252
                }
5253
                else
5254
                {
5255
                    if ((int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 0 || (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1] == 3)
5256
                    {
5257
                        int found = 0;
5258
                        for (int k = 0; k < dgvWP.SelectedIndex; k++)
5259
                        {
5260
                            if ((int)dtWaypoints.Rows[k][1] == 0 || (int)dtWaypoints.Rows[k][1] == 3)
5261
                            {
5262
                                found++;
5263
                            }
5264
                        }
5265
                        wpList.Insert(found, new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]));
5266
                        wpOffset.Insert(found, dgvWP.SelectedIndex);
5267
                    }
5268
                }
5269
                dtWaypoints.Rows[dgvWP.SelectedIndex][5] = lblWPEditAlt.Content;
5270
                switch (cbWPEditHeading.SelectedIndex)
5271
                {
5272
                    case 0:
5273
                        dtWaypoints.Rows[dgvWP.SelectedIndex][6] = "0";
5274
                        break;
5275
                    case 1:
5276
                        dtWaypoints.Rows[dgvWP.SelectedIndex][6] = "-" + lblWPEditHeading.Content;
5277
                        break;
5278
                    case 2:
5279
                        dtWaypoints.Rows[dgvWP.SelectedIndex][6] = lblWPEditHeading.Content;
5280
                        break;
5281
                }
5282
                switch (cbWPEditSpeed.SelectedIndex)
5283
                {
5284
                    case 0:
5285
                        dtWaypoints.Rows[dgvWP.SelectedIndex][7] = "0";
5286
                        break;
5287
                    case 1:
5288
                        dtWaypoints.Rows[dgvWP.SelectedIndex][7] = (System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10).ToString("0");
5289
                        break;
5290
                    case 2:
5291
                        dtWaypoints.Rows[dgvWP.SelectedIndex][7] = (256 - Convert.ToInt16(lblWPEditSpeed.Content)).ToString();
5292
                        break;
5293
                }
5294
                switch (cbWPEditClimbrate.SelectedIndex)
5295
                {
5296
                    case 0:
5297
                        dtWaypoints.Rows[dgvWP.SelectedIndex][8] = "255";
5298
                        break;
5299
                    case 1:
5300
                        dtWaypoints.Rows[dgvWP.SelectedIndex][8] = (System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.',',')) * 10).ToString("0");
5301
                        break;
5302
                }
5303
                dtWaypoints.Rows[dgvWP.SelectedIndex][9] = lblWPEditRadius.Content;
5304
                dtWaypoints.Rows[dgvWP.SelectedIndex][10] = lblWPEditHoldtime.Content;
5305
                dtWaypoints.Rows[dgvWP.SelectedIndex][11] = lblWPEditAutoTrigger.Content;
5306
                switch (cbWPEditCamAngle.SelectedIndex)
5307
                {
5308
                    case 0:
5309
                        dtWaypoints.Rows[dgvWP.SelectedIndex][12] = "0";
5310
                        break;
5311
                    case 1:
5312
                        dtWaypoints.Rows[dgvWP.SelectedIndex][12] = "255";
5313
                        break;
5314
                    case 2:
5315
                        dtWaypoints.Rows[dgvWP.SelectedIndex][12] = lblWPEditCamAngle.Content;
5316
                        break;
5317
                }
5318
                dtWaypoints.Rows[dgvWP.SelectedIndex][14] = lblWPEditOut1.Content;
5319
 
5320
                // _clearMapMarkers(typeof(CustomMarkerWP));
5321
                _repositionWPMarker(new PointLatLng((double)dtWaypoints.Rows[dgvWP.SelectedIndex][3], (double)dtWaypoints.Rows[dgvWP.SelectedIndex][4]),oldName);
5322
                _renameWPMarker(oldName, (string)dtWaypoints.Rows[dgvWP.SelectedIndex][2]);
5323
                _clearMapMarkers(typeof(CustomMarkerWPActive));
5324
                _setMarkerColor(_findWPMarker((string)dtWaypoints.Rows[dgvWP.SelectedIndex][2]), (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1]);
5325
                _WPMarkerSetType((string)dtWaypoints.Rows[dgvWP.SelectedIndex][2], (int)dtWaypoints.Rows[dgvWP.SelectedIndex][1]);
5326
               // wpList.Clear();
5327
                if (mRouteWP != null)
5328
                    MainMap.Markers.Remove(mRouteWP);
5329
 
5330
                //for (int k = 0; k < dtWaypoints.Rows.Count; k++)
5331
                //{
5332
                //    _createWP(new PointLatLng((double)dtWaypoints.Rows[k][3], (double)dtWaypoints.Rows[k][4]), (string)dtWaypoints.Rows[k][2], (int)dtWaypoints.Rows[k][1]);
5333
                //}
5334
                _routeUpdate();
5335
                dgvWP.Items.Refresh();
5336
 
5337
            }
5338
 
5339
        }
5340
        private void btnEditWPAdd_Click(object sender, RoutedEventArgs e)
5341
        {
5342
            DataRow dr = dtWaypoints.NewRow();
5343
            dr[0] = dtWaypoints.Rows.Count+1;
5344
            dr[1] = cbWPEditType.SelectedIndex;
5345
            dr[2] = tbWPEditPrefix.Text + dr[0].ToString();
5346
            dr[3] = Convert.ToDouble(tbWPEditLat.Text.Replace('.', ',')) + 0.00000001;
5347
            dr[4] = Convert.ToDouble(tbWPEditLon.Text.Replace('.', ',')) + 0.00000001;
5348
            dr[5] = lblWPEditAlt.Content;
5349
            switch (cbWPEditHeading.SelectedIndex)
5350
            {
5351
                case 0:
5352
                    dr[6] = "0";
5353
                    break;
5354
                case 1:
5355
                    dr[6] = "-" + lblWPEditHeading.Content;
5356
                    break;
5357
                case 2:
5358
                    dr[6] = lblWPEditHeading.Content;
5359
                    break;
5360
            }
5361
            switch (cbWPEditSpeed.SelectedIndex)
5362
            {
5363
                case 0:
5364
                    dr[7] = "0";
5365
                    break;
5366
                case 1:
5367
                    dr[7] = (System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10).ToString("0");
5368
                    break;
5369
                case 2:
5370
                    dr[7] = (256 - Convert.ToInt16(lblWPEditSpeed.Content)).ToString();
5371
                    break;
5372
            }
5373
            switch (cbWPEditClimbrate.SelectedIndex)
5374
            {
5375
                case 0:
5376
                    dr[8] = "255";
5377
                    break;
5378
                case 1:
5379
                    dr[8] = (System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.', ',')) * 10).ToString("0");
5380
                    break;
5381
            }
5382
            dr[9] = lblWPEditRadius.Content;
5383
            dr[10] = lblWPEditHoldtime.Content;
5384
            dr[11] = lblWPEditAutoTrigger.Content;
5385
            switch (cbWPEditCamAngle.SelectedIndex)
5386
            {
5387
                case 0:
5388
                    dr[12] = "0";
5389
                    break;
5390
                case 1:
5391
                    dr[12] = "255";
5392
                    break;
5393
                case 2:
5394
                    dr[12] = lblWPEditCamAngle.Content;
5395
                    break;
5396
            }
5397
            dr[13] = "";
5398
            dr[14] = lblWPEditOut1.Content;
5399
            dr[15] = "";
5400
            _createWP(new PointLatLng((double)dr[3], (double)dr[4]),(string) dr[2], (int)dr[1], (int)dr[0]);
5401
            if (mRouteWP != null)
5402
                MainMap.Markers.Remove(mRouteWP);
5403
            _routeUpdate();
5404
            dtWaypoints.Rows.Add(dr);
5405
            dgvWP.Items.Refresh();
5406
        }
5407
        private void btnEditWPDel_Click(object sender, RoutedEventArgs e)
5408
        {
5409
            if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
5410
            {
5411
                int index = dgvWP.SelectedIndex;
5412
                Dispatcher.Invoke(() => {
5413
                    DataGridRow row;
5414
                    if (_wpEdit > -1 && _wpEdit < dgvWP.ItemContainerGenerator.Items.Count)
5415
                    {
5416
                        row = (DataGridRow)dgvWP.ItemContainerGenerator.ContainerFromIndex(_wpEdit);
5417
                        row.Background = new SolidColorBrush(Colors.Transparent);
5418
                        row.BorderBrush = new SolidColorBrush(Colors.Transparent);
5419
                        row.BorderThickness = new Thickness(0);
5420
                    }
5421
                    if ((int)dtWaypoints.Rows[index][1] == 0 || (int)dtWaypoints.Rows[index][1] == 3)
5422
                        wpList.Remove(new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]));
5423
                    else
5424
                        wpOffset.Remove((int)dtWaypoints.Rows[index][0] + 1);
5425
                    _clearWPMarker((string)dtWaypoints.Rows[index][2]);
5426
                    if (wpActiveMarker != null)
5427
                        MainMap.Markers.Remove(wpActiveMarker);
5428
                    dtWaypoints.Rows[index].Delete();
5429
                    _wpIndex = -1;
5430
                    _wpEdit = -1;
5431
                    for (int i = index; i < dtWaypoints.Rows.Count; i++) //change the index of points behind deleted point + rename to new index
5432
                    {
5433
                        dtWaypoints.Rows[i][0] = i + 1;
5434
                        string s1 = (string)dtWaypoints.Rows[i][2]; //old name of WP (Prefix + index)
5435
                        string s2 = s1.Substring(0, 1) + (i + 1).ToString(); //new name of WP
5436
                        _renameWPMarker(s1, s2);
5437
                        dtWaypoints.Rows[i][2] = s2;
5438
                    }
5439
                    lblWPCount.Content = dtWaypoints.Rows.Count;
5440
                    if (mRouteWP != null)
5441
                        MainMap.Markers.Remove(mRouteWP);
5442
                    _routeUpdate();
5443
 
5444
                    dgvWP.UpdateLayout();
5445
                });
5446
            }
5447
        }
5448
        private void tbWPEdit_TouchDown(object sender, TouchEventArgs e)
5449
        {
5450
            _wpWEdit(sender);
5451
        }
5452
        private void tbWPEdit_KeyDown(object sender, KeyEventArgs e)
5453
        {
5454
            _wpWEdit(sender);
5455
        }
5456
        private void tbWPEdit_MouseDown(object sender, MouseButtonEventArgs e)
5457
        {
5458
            _wpWEdit(sender);
5459
        }
5460
        void _wpWEdit(object sender)
5461
        {
5462
           // if (!((TextBox)sender).IsReadOnly)
5463
            {
5464
                KeyPad.Keypad k = new KeyPad.Keypad(this);
5465
 
5466
                switch (((TextBox)sender).Name)
5467
                {
5468
                    case "tbWPEditLat":
5469
                        k.Title = "Latitude";
5470
                        k.LENGTH = 17;
5471
                        k.MAX = 359.9;
5472
                        break;
5473
                    case "tbWPEditLon":
5474
                        k.Title = "Longitude";
5475
                        k.LENGTH = 17;
5476
                        k.MAX = 359.9;
5477
                        break;
5478
                    case "tbWPEditAlt":
5479
                        k.Title = "Altitude";
5480
                        k.LENGTH = 3;
5481
                        k.MAX = 254;
5482
                        k.disableDecimal();
5483
                        break;
5484
                    case "tbWPEditHeading":
5485
                        k.Title = "Heading";
5486
                        k.LENGTH = 3;
5487
                        k.MAX = 359;
5488
                        k.MIN = 1;
5489
                        k.disableDecimal();
5490
                        break;
5491
                    case "tbWPEditSpeed":
5492
                        k.Title = "Speed";
5493
                        k.LENGTH = 4;
5494
                        k.MAX = 24.7;
5495
                        k.MIN = 0.1;
5496
                        break;
5497
                    case "tbWPEditClimbrate":
5498
                        k.Title = "Climbrate";
5499
                        k.LENGTH = 4;
5500
                        k.MAX = 25.4;
5501
                        k.MIN = 0.1;
5502
                        break;
5503
                    case "tbWPEditRadius":
5504
                        k.Title = "Radius";
5505
                        k.LENGTH = 3;
5506
                        k.MAX = 254;
5507
                        k.disableDecimal();
5508
                        break;
5509
                    case "tbWPEditHoldtime":
5510
                        k.Title = "Holdtime";
5511
                        k.LENGTH = 3;
5512
                        k.MAX = 254;
5513
                        break;
5514
                    case "tbWPEditAutoTrigger":
5515
                        k.Title = "Autotrigger";
5516
                        k.LENGTH = 3;
5517
                        k.MAX = 254;
5518
                        k.disableDecimal();
5519
                        break;
5520
                    case "tbWPEditCamAngle":
5521
                        k.Title = "Camera angle";
5522
                        k.LENGTH = 3;
5523
                        k.MAX = 254;
5524
                        k.MIN = 1;
5525
                        k.disableDecimal();
5526
                        break;
5527
                    case "tbWPEditOut1":
5528
                        k.Title = "OUT1 timer interval";
5529
                        k.LENGTH = 3;
5530
                        k.MAX = 254;
5531
                        k.disableDecimal();
5532
                        break;
5533
                }
5534
                k.Result = ((TextBox)sender).Text;
5535
                if (k.ShowDialog() == true && k.Result.Length > 0)
5536
                    ((TextBox)sender).Text = k.Result;
5537
            }
5538
 
5539
        }
5540
        private void btnWPAddCurrentPos_Click(object sender, RoutedEventArgs e)
5541
        {
5542
            _addWP(new PointLatLng(copter.Position.Lat, copter.Position.Lng),0);
5543
        }
5544
        private void checkBoxWPAddUseCopterHeading_Click(object sender, RoutedEventArgs e)
5545
        {
5546
            _wpAddCopterHeading = (bool)checkBoxWPAddUseCopterHeading.IsChecked;
5547
        }
5548
        private void checkBoxWPAddUseCopterHeight_Click(object sender, RoutedEventArgs e)
5549
        {
5550
            _wpAddCopterHeight = (bool)checkBoxWPAddUseCopterHeight.IsChecked;
5551
        }
5552
        private void btnSaveDefault_Click(object sender, RoutedEventArgs e)
5553
        {
5554
            _wpDefPrefix = tbWPEditPrefix.Text;
5555
            _wpDefAltitude = Convert.ToInt16(lblWPEditAlt.Content);
5556
            switch (cbWPEditHeading.SelectedIndex)
5557
            {
5558
                case 0:
5559
                    _wpDefHeading = 0;
5560
                    break;
5561
                case 1:
5562
                    _wpDefHeading = -Convert.ToInt16(lblWPEditHeading.Content);
5563
                    break;
5564
                case 2:
5565
                    _wpDefHeading = Convert.ToInt16(lblWPEditHeading.Content);
5566
                    break;
5567
            }            
5568
            _wpDefCBoxHeading = cbWPEditHeading.SelectedIndex;
5569
            switch (cbWPEditSpeed.SelectedIndex)
5570
            {
5571
                case 0:
5572
                    _wpDefSpeed = 0;
5573
                    break;
5574
                case 1:
5575
                    _wpDefSpeed = (int)(System.Convert.ToDouble(lblWPEditSpeed.Content.ToString().Replace('.', ',')) * 10);
5576
                    break;
5577
                case 2:
5578
                    _wpDefSpeed = 256 - Convert.ToInt16(lblWPEditSpeed.Content);
5579
                    break;
5580
            }
5581
            _wpDefCBoxSpeed = cbWPEditSpeed.SelectedIndex;
5582
            switch (cbWPEditClimbrate.SelectedIndex)
5583
            {
5584
                case 0:
5585
                    _wpDefClimb = 255;
5586
                    break;
5587
                case 1:
5588
                    _wpDefClimb = (int)(System.Convert.ToDouble(lblWPEditClimbrate.Content.ToString().Replace('.', ',')) * 10);
5589
                    break;
5590
            }
5591
            _wpDefCBoxClimb = cbWPEditClimbrate.SelectedIndex;
5592
            _wpDefRadius = Convert.ToInt16(lblWPEditRadius.Content);
5593
            _wpDefHoldtime = Convert.ToInt16(lblWPEditHoldtime.Content);
5594
            _wpDefAutotrig = Convert.ToInt16(lblWPEditAutoTrigger.Content);
5595
            switch (cbWPEditCamAngle.SelectedIndex)
5596
            {
5597
                case 0:
5598
                    _wpDefCamangle = 0;
5599
                    break;
5600
                case 1:
5601
                    _wpDefCamangle = 255;
5602
                    break;
5603
                case 2:
5604
                    _wpDefCamangle = Convert.ToInt16(lblWPEditCamAngle.Content);
5605
                    break;
5606
            }
5607
            _wpDefCBoxCamangle = cbWPEditCamAngle.SelectedIndex;
5608
            _wpDefOut1 = Convert.ToInt16(lblWPEditOut1.Content);
5609
        }
5610
 
5611
        private void btnWPEditmoveUp_Click(object sender, RoutedEventArgs e)
5612
        {
5613
            if (dgvWP.SelectedIndex > 0 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count)
5614
            {
5615
                int index = dgvWP.SelectedIndex;
5616
                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)
5617
                {
5618
                    PointLatLng x = new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]);
5619
                    int wpListIndex = wpList.IndexOf(x);
5620
                    if (wpListIndex > 0)
5621
                    {
5622
                        wpList.RemoveAt(wpListIndex);
5623
                        wpList.Insert(wpListIndex - 1, x);
5624
                        MainMap.Markers.Remove(mRouteWP);
5625
                        _routeUpdate();
5626
                    }
5627
                }
5628
                DataRow dr = dtWaypoints.Rows[index];
5629
                DataRow newRow = dtWaypoints.NewRow();
5630
                newRow.ItemArray = dr.ItemArray;
5631
                dtWaypoints.Rows.Remove(dr);
5632
                dtWaypoints.Rows.InsertAt(newRow, index - 1);
5633
                dtWaypoints.Rows[index][0] = 100;
5634
                dtWaypoints.Rows[index - 1][0] = index;
5635
                GMapMarker m1 = _findWPMarker(dtWaypoints.Rows[index - 1][2].ToString());
5636
                GMapMarker m2 = _findWPMarker(dtWaypoints.Rows[index][2].ToString());
5637
                dtWaypoints.Rows[index - 1][2] = dtWaypoints.Rows[index - 1][2].ToString().Substring(0, 1) + index.ToString();
5638
                ((CustomMarkerWP)m1.Shape).text.Text = dtWaypoints.Rows[index - 1][2].ToString();
5639
                dtWaypoints.Rows[index][0] = index + 1;
5640
                dtWaypoints.Rows[index][2] = dtWaypoints.Rows[index][2].ToString().Substring(0, 1) + (index+1).ToString();
5641
                ((CustomMarkerWP)m2.Shape).text.Text = dtWaypoints.Rows[index][2].ToString();
5642
                dgvWP.Items.Refresh();
5643
                dgvWP.SelectedIndex = index - 1;
5644
                _dgvWPselectEditRow();
5645
                if (wpOffset.Contains(index)) // calculating offset for wpList (index is 0-based - offset starts with index 1)
5646
                {
5647
                    int iOffset = wpOffset.IndexOf(index);
5648
                    if (iOffset > 0) // if not first element
5649
                    {
5650
                        if (wpOffset[iOffset - 1] < index-1) //if previous element is not immediately before actual offset
5651
                            wpOffset[iOffset] = index-1;  //then decrease offset value by one
5652
                    }
5653
                    else
5654
                        wpOffset[iOffset] = index-1; //if first element, decrease offset by one
5655
                }
5656
                else //selected line is POI
5657
                {
5658
                    if (wpOffset.Contains(index - 1)) // if next point is WP
5659
                    {
5660
                        int iOffset = wpOffset.IndexOf(index - 1);
5661
                        wpOffset[iOffset] = index; //decrease linenumber of following WP
5662
                    }
5663
                }
5664
 
5665
            }
5666
        }
5667
        private void btnWPEditmoveDown_Click(object sender, RoutedEventArgs e)
5668
        {
5669
            if (dgvWP.SelectedIndex > -1 && dgvWP.SelectedIndex < dtWaypoints.Rows.Count - 1)
5670
            {
5671
                int index = dgvWP.SelectedIndex;
5672
                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)
5673
                {
5674
                    PointLatLng x = new PointLatLng((double)dtWaypoints.Rows[index][3], (double)dtWaypoints.Rows[index][4]);
5675
                    int wpListIndex = wpList.IndexOf(x);
5676
                    if (wpListIndex > -1)
5677
                    {
5678
                        wpList.RemoveAt(wpListIndex);
5679
                        if (wpList.Count > wpListIndex)
5680
                            wpList.Insert(wpListIndex + 1, x);
5681
                        else
5682
                            wpList.Add(x);
5683
                        MainMap.Markers.Remove(mRouteWP);
5684
                        _routeUpdate();
5685
                    }
5686
                }
5687
                DataRow dr = dtWaypoints.Rows[index];
5688
                DataRow newRow = dtWaypoints.NewRow();
5689
                newRow.ItemArray = dr.ItemArray;
5690
                dtWaypoints.Rows.Remove(dr);
5691
                dtWaypoints.Rows.InsertAt(newRow, index + 1);
5692
                dtWaypoints.Rows[index][0] = 100;
5693
                dtWaypoints.Rows[index + 1][0] = index + 2;
5694
                GMapMarker m1 = _findWPMarker(dtWaypoints.Rows[index + 1][2].ToString());
5695
                GMapMarker m2 = _findWPMarker(dtWaypoints.Rows[index][2].ToString());
5696
                dtWaypoints.Rows[index + 1][2] = dtWaypoints.Rows[index + 1][2].ToString().Substring(0, 1) + (index+2).ToString();
5697
                ((CustomMarkerWP)m1.Shape).text.Text = dtWaypoints.Rows[index + 1][2].ToString();
5698
                dtWaypoints.Rows[index][0] = index + 1;
5699
                dtWaypoints.Rows[index][2] = dtWaypoints.Rows[index][2].ToString().Substring(0, 1) + (index+1).ToString();
5700
                ((CustomMarkerWP)m2.Shape).text.Text = dtWaypoints.Rows[index][2].ToString();
5701
                dgvWP.Items.Refresh();
5702
                dgvWP.SelectedIndex = index + 1;
5703
                _dgvWPselectEditRow();
5704
                if(wpOffset.Contains(index)) // If selected line is WP
5705
                {
5706
                    int iOffset = wpOffset.IndexOf(index);
5707
                    if(iOffset < wpOffset.Count -1) // if not last element
5708
                    {
5709
                        if (wpOffset[iOffset + 1] > index + 1) //if next element is not immediately after actual offset
5710
                            wpOffset[iOffset] = index + 1;  //then increase offset value by one
5711
                    }
5712
                    else
5713
                        wpOffset[iOffset] = index + 1; //if last element increase offset by one
5714
                }
5715
                else //selected line is POI
5716
                {
5717
                    if (wpOffset.Contains(index + 1)) // if next point is WP
5718
                    {
5719
                        int iOffset = wpOffset.IndexOf(index + 1);
5720
                        wpOffset[iOffset] = index; //decrease linenumber of following WP
5721
                    }
5722
                }
5723
            }
5724
 
5725
        }
5726
 
5727
        private void checkBoxShowWPStatus_Click(object sender, RoutedEventArgs e)
5728
        {
5729
            if (WPStatus.Visibility == Visibility.Visible)
5730
                GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value + 36, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
5731
            else
5732
                GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
5733
        }
5734
        private void checkBoxShowWPMaxRange_click(object sender, RoutedEventArgs e)
5735
        {
5736
            if (home != null && checkBoxShowWPMaxRange.IsChecked == true && dWPMaxRange > 0)
5737
            {
5738
                if (cWPBound != null && cWPBound.Tag != null)
5739
                    MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
5740
 
5741
                createCircle(home.Position, dWPMaxRange);
5742
                if (comboBoxWPMaxRangeColor.SelectionBoxItem != null)
5743
                {
5744
                    string s = comboBoxWPMaxRangeColor.SelectionBoxItem.ToString();
5745
                    cWPBound.setColor(s);
5746
                }
5747
            }
5748
 
5749
            if (checkBoxShowWPMaxRange.IsChecked == false && (cWPBound != null && cWPBound.Tag != null))
5750
                MainMap.Markers.Remove(cWPBound.Tag as GMapMarker);
5751
        }
5752
        private void checkBoxAutoShowWPEdit_Click(object sender, RoutedEventArgs e)
5753
        {
5754
             _bAutoWPEdit = (bool)checkBoxAutoShowWPEdit.IsChecked;
5755
        }
5756
 
5757
        #endregion WP
5758
        #region GPX
5759
        private void checkBoxGPXLog_Click(object sender, RoutedEventArgs e)
5760
        {
5761
            _bGPXLog = (bool)checkBoxGPXLog.IsChecked;
5762
        }
5763
        void _gpxAdd(double lat,double lon, int elevation)
5764
        {
5765
            DataRow dr = dtGPX.NewRow();
5766
            dr[0] = dtGPX.Rows.Count - 1;
5767
            dr[1] = lat;
5768
            dr[2] = lon;
5769
            dr[3] = elevation;
5770
            dr[4] = DateTime.UtcNow.ToString("s", System.Globalization.CultureInfo.InvariantCulture); //2011-01-14T01:59:01Z
5771
            dtGPX.Rows.Add(dr);
5772
        }
5773
 
5774
        void _saveGPXLog()
5775
        {
5776
            if (!Directory.Exists("GPXLog"))
5777
                Directory.CreateDirectory("GPXLog");
5778
            string SaveFileName = "GPXLog\\" + DateTime.Now.ToString("yyyyMMdd_HHmm") + ".gpx";
5779
            XmlTextWriter myXmlTextWriter = null;
5780
            myXmlTextWriter = new XmlTextWriter(SaveFileName, null);
5781
            NumberFormatInfo nfi = new NumberFormatInfo();
5782
            nfi.NumberDecimalSeparator = ".";
5783
 
5784
            try
5785
            {
5786
                myXmlTextWriter.Formatting = Formatting.Indented;
5787
 
5788
                myXmlTextWriter.WriteStartDocument();
5789
 
5790
                myXmlTextWriter.WriteStartElement("gpx");
5791
 
5792
                myXmlTextWriter.WriteAttributeString("version", "1.0");
5793
                myXmlTextWriter.WriteAttributeString("creator", "MKLiveView v1.0");
5794
                myXmlTextWriter.WriteAttributeString("xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance");
5795
                myXmlTextWriter.WriteAttributeString("xmlns", "http://www.topografix.com/GPX/1/1");
5796
                myXmlTextWriter.WriteAttributeString("xsi:schemaLocation", "http://www.topografix.com/GPX/1/1/gpx.xsd");
5797
 
5798
                myXmlTextWriter.WriteElementString("time", DateTime.UtcNow.ToString("u", System.Globalization.CultureInfo.InvariantCulture));
5799
 
5800
                myXmlTextWriter.WriteStartElement("trk");
5801
                myXmlTextWriter.WriteStartElement("trkseg");
5802
                for(int i = 0; i< dtGPX.Rows.Count;i++)
5803
                {
5804
                    myXmlTextWriter.WriteStartElement("trkpt");
5805
                    myXmlTextWriter.WriteAttributeString("lat", dtGPX.Rows[i][1].ToString() != "" ? ((double)dtGPX.Rows[i][1]).ToString(nfi) : "");
5806
                    myXmlTextWriter.WriteAttributeString("lon", dtGPX.Rows[i][2].ToString() != "" ? ((double)dtGPX.Rows[i][2]).ToString(nfi) : "");
5807
                    myXmlTextWriter.WriteElementString("ele", dtGPX.Rows[i][3].ToString());
5808
                    myXmlTextWriter.WriteElementString("time", dtGPX.Rows[i][4].ToString());
5809
                    myXmlTextWriter.WriteEndElement();
5810
                }
5811
                myXmlTextWriter.WriteEndElement();
5812
                myXmlTextWriter.WriteEndElement();
5813
                myXmlTextWriter.WriteEndElement();
5814
            }
5815
            catch (Exception e)
5816
            {
5817
                Console.WriteLine("Exception: {0}", e.ToString());
5818
            }
5819
            finally
5820
            {
5821
                if (myXmlTextWriter != null)
5822
                {
5823
                    myXmlTextWriter.Close();
5824
                }
5825
            }
5826
        }
5827
 
5828
        private void btnLoadGPXLog_Click(object sender, RoutedEventArgs e)
5829
        {
5830
            _loadGPXLog();
5831
        }
5832
        private void btnClearRoute_Click(object sender, RoutedEventArgs e)
5833
        {
5834
            _clearMapMarkers(typeof(GMapRoute));
5835
        }
5836
        void _loadGPXLog()
5837
        {
5838
 
5839
            Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
5840
            fd.Filter = "GPX-Logfile | *.gpx";
5841
            fd.Multiselect = false;
5842
            if (fd.ShowDialog().Value)
5843
            {
5844
                string file = fd.FileName;
5845
                try
5846
                {
5847
                    XDocument gpxDoc = XDocument.Load(file);
5848
                    XNamespace gpx = XNamespace.Get("http://www.topografix.com/GPX/1/1");
5849
 
5850
                    NumberFormatInfo nfi = new NumberFormatInfo();
5851
                    nfi.NumberDecimalSeparator = ".";
5852
 
5853
                    var tracks = from track in gpxDoc.Descendants(gpx + "trk")
5854
                                 select new
5855
                                 {
5856
                                     Name = track.Element(gpx + "name") != null ? track.Element(gpx + "name").Value : null,
5857
                                     Segs = (
5858
                                         from trackpoint in track.Descendants(gpx + "trkpt")
5859
                                         select new
5860
                                         {
5861
                                             Latitude = trackpoint.Attribute("lat").Value,
5862
                                             Longitude = trackpoint.Attribute("lon").Value,
5863
                                             Elevation = trackpoint.Element(gpx + "ele") != null ?
5864
                                             trackpoint.Element(gpx + "ele").Value : null,
5865
                                             Time = trackpoint.Element(gpx + "time") != null ?
5866
                                             trackpoint.Element(gpx + "time").Value : null
5867
                                         }
5868
                                     )
5869
                                 };
5870
 
5871
                    List<PointLatLng> wpl = new List<PointLatLng>();
5872
                    foreach(var trk in tracks)
5873
                    {
5874
                        foreach(var trkseg in trk.Segs)
5875
                        {
5876
                            if(trkseg.Latitude != "" && trkseg.Longitude !="")
5877
                            wpl.Add(new PointLatLng(Convert.ToDouble(trkseg.Latitude, nfi), Convert.ToDouble(trkseg.Longitude, nfi)));
5878
                        }
5879
 
5880
                    }
5881
                    if(wpl.Count() > 0)
5882
                    {
5883
                        _clearMapMarkers(typeof(GMapRoute));
5884
                        MapRoute mr = new MapRoute(wpl, "flying");
5885
                        Dispatcher.Invoke(() =>
5886
                        {
5887
                            GMapRoute mRoute;
5888
                            if (comboBoxRouteColor.SelectionBoxItem != null)
5889
                            {
5890
                                string s = comboBoxRouteColor.SelectionBoxItem.ToString();
5891
                                mRoute = new GMapRoute(wpl, _getBrush(s));
5892
                            }
5893
                            else
5894
                                mRoute = new GMapRoute(wpl, null);
5895
 
5896
                            MainMap.Markers.Add(mRoute);
5897
                        });
5898
                    }
5899
 
5900
                }
5901
                catch (Exception e)
5902
                {
5903
                    Console.WriteLine("Exception: {0}", e.ToString());
5904
                }
5905
            }
5906
        }
5907
        #endregion GPX
5908
        #endregion functions
5909
    }
5910
 
5911
    /// <summary>
5912
    /// formats the wp datatable values for display in datagrid - this is bound in the datagrid as a converter
5913
    /// </summary>
5914
    public class waypointsConverter : IValueConverter
5915
    {
5916
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
5917
        {
5918
            if (value != null)
5919
            {
5920
                switch ((string)parameter)
5921
                {
5922
                    case "Latitude":
5923
                        return value.ToString() + " °";
5924
                    case "Longitude":
5925
                        return value.ToString() + " °";
5926
                    case "Radius":
5927
                        return value.ToString() + " m";
5928
                    case "Altitude":
5929
                        return value.ToString() + " m";
5930
                    case "ClimbRate":
5931
                        return value.ToString() == "255" ? "Auto" : (System.Convert.ToDouble(value) / 10).ToString("0.0 m/s");
5932
                    case "DelayTime":
5933
                        return value.ToString() + " s";
5934
                    case "Heading":
5935
                        return Waypoints.Heading(System.Convert.ToInt32(value));
5936
                    case "Speed":
5937
                        return Waypoints.WPSpeed(System.Convert.ToInt16(value));
5938
                    case "CamAngle":
5939
                        return Waypoints.CAMAngle(System.Convert.ToInt16(value));
5940
                    case "Type":
5941
                        return ((Waypoints.pointType)(System.Convert.ToInt16(value))).ToString();
5942
                    case "AutoTrigger":
5943
                        return value.ToString() == "0" ? "- - -" : value.ToString() + " m";
5944
                    case "Status":
5945
                        return (Waypoints.status)(System.Convert.ToInt16(value));
5946
                }
5947
 
5948
                return value.ToString();
5949
            }
5950
            else return value;
5951
        }
5952
 
5953
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
5954
        {
5955
            throw new NotImplementedException();
5956
        }
5957
    }
5958
    public class IniFile
5959
    {
5960
        public string path;
5961
 
5962
        [DllImport("kernel32")]
5963
        private static extern long WritePrivateProfileString(string section,
5964
          string key, string val, string filePath);
5965
 
5966
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
5967
        static extern uint GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer,
5968
               uint nSize, string lpFileName);
5969
 
5970
        [DllImport("kernel32")]
5971
        private static extern int GetPrivateProfileString(string section,
5972
          string key, string def, StringBuilder retVal,
5973
          int size, string filePath);
5974
 
5975
        public IniFile(string INIPath)
5976
        {
5977
            path = INIPath;
5978
        }
5979
 
5980
        public void IniWriteValue(string Section, string Key, string Value)
5981
        {
5982
            WritePrivateProfileString(Section, Key, Value, this.path);
5983
        }
5984
 
5985
        public string IniReadValue(string Section, string Key)
5986
        {
5987
            StringBuilder temp = new StringBuilder(255);
5988
            int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path);
5989
            return temp.ToString();
5990
        }
5991
        //Ini_sections auslesen in String-Array
5992
        public string[] IniSectionNames()
5993
        {
5994
 
5995
            //  uint MAX_BUFFER = 32767;
5996
            uint MAX_BUFFER = 8388608;
5997
            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER);
5998
            uint bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, this.path);
5999
            if (bytesReturned == 0)
6000
            {
6001
                Marshal.FreeCoTaskMem(pReturnedString);
6002
                return null;
6003
            }
6004
            string local = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned).ToString();
6005
            Marshal.FreeCoTaskMem(pReturnedString);
6006
            //use of Substring below removes terminating null for split
6007
            return local.Substring(0, local.Length - 1).Split('\0');
6008
 
6009
 
6010
        }
6011
    }
6012
    /// <summary>
6013
    /// Selected Win AI Function Calls
6014
    /// </summary>
6015
    public class WinApi
6016
    {
6017
        [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
6018
        public static extern int GetSystemMetrics(int which);
6019
        [DllImport("user32.dll")]
6020
        public static extern void
6021
                SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter,
6022
                             int X, int Y, int width, int height, uint flags);
6023
 
6024
        private const int SM_CXSCREEN = 0;
6025
        private const int SM_CYSCREEN = 1;
6026
        private static IntPtr HWND_TOP = IntPtr.Zero;
6027
        private const int SWP_SHOWWINDOW = 64; // 0x0040
6028
 
6029
        public static int ScreenX
6030
        {
6031
            get { return GetSystemMetrics(SM_CXSCREEN); }
6032
        }
6033
 
6034
        public static int ScreenY
6035
        {
6036
            get { return GetSystemMetrics(SM_CYSCREEN); }
6037
        }
6038
 
6039
        public static void SetWinFullScreen(IntPtr hwnd)
6040
        {
6041
            SetWindowPos(hwnd, HWND_TOP, -8, -7, ScreenX+15, ScreenY+14, SWP_SHOWWINDOW);
6042
        }
6043
    }
6044
    /// <summary>
6045
    /// Class used to preserve / restore state of the window
6046
    /// </summary>
6047
    public class WinState
6048
    {
6049
        private WindowState winState;
6050
        private WindowStyle brdStyle;
6051
        private bool topMost;
6052
        private Rect restore;
6053
        private bool IsMaximized = false;
6054
 
6055
        public bool isMaximized
6056
        {
6057
            get { return IsMaximized; }
6058
        }
6059
        public void Maximize(Window targetForm)
6060
        {
6061
            if (!IsMaximized)
6062
            {
6063
                IsMaximized = true;
6064
                Save(targetForm);
6065
                targetForm.WindowState = WindowState.Maximized;
6066
                targetForm.WindowStyle = WindowStyle.None;
6067
                targetForm.Topmost = true;
6068
                WinApi.SetWinFullScreen(new WindowInteropHelper(targetForm).Handle);
6069
            }
6070
        }
6071
 
6072
        public void Save(Window targetForm)
6073
        {
6074
            winState = targetForm.WindowState;
6075
            brdStyle = targetForm.WindowStyle;
6076
            topMost = targetForm.Topmost;
6077
            restore = targetForm.RestoreBounds;
6078
        }
6079
        public void Restore(Window targetForm)
6080
        {
6081
            targetForm.WindowState = winState;
6082
            targetForm.WindowStyle = brdStyle;
6083
            targetForm.Topmost = topMost;
6084
 
6085
            targetForm.Left = restore.Left;
6086
            targetForm.Top = restore.Top;
6087
            targetForm.Height = restore.Height;
6088
            targetForm.Width = restore.Width;
6089
            IsMaximized = false;
6090
        }
6091
    }
6092
 
6093
    public static class BitmapConversion
6094
    {
6095
        public static System.Drawing.Bitmap ToWinFormsBitmap(this BitmapSource bitmapsource)
6096
        {
6097
            using (MemoryStream stream = new MemoryStream())
6098
            {
6099
                BitmapEncoder enc = new BmpBitmapEncoder();
6100
                enc.Frames.Add(BitmapFrame.Create(bitmapsource));
6101
                enc.Save(stream);
6102
                using (var tempBitmap = new System.Drawing.Bitmap(stream))
6103
                {
6104
                    // According to MSDN, one "must keep the stream open for the lifetime of the Bitmap."
6105
                    // So we return a copy of the new bitmap, allowing us to dispose both the bitmap and the stream.
6106
                    return new System.Drawing.Bitmap(tempBitmap);
6107
                }
6108
            }
6109
        }
6110
        public static BitmapSource ToWpfBitmap(this System.Drawing.Bitmap bitmap)
6111
        {
6112
            using (MemoryStream stream = new MemoryStream())
6113
            {
6114
                bitmap.Save(stream, System.Drawing.Imaging.ImageFormat.Bmp); stream.Position = 0;
6115
                BitmapImage result = new BitmapImage();
6116
                result.BeginInit();
6117
                // According to MSDN, "The default OnDemand cache option retains access to the stream until the image is needed."
6118
                // Force the bitmap to load right now so we can dispose the stream.
6119
                result.CacheOption = BitmapCacheOption.OnLoad;
6120
                result.StreamSource = stream;
6121
                result.EndInit();
6122
                result.Freeze();
6123
                return result;
6124
            }
6125
        }
6126
    }
6127
 
6128
}