Subversion Repositories Projects

Rev

Rev 2315 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed

Rev Author Line No. Line
2287 - 1
using GMap.NET;
2
using GMap.NET.MapProviders;
3
using GMap.NET.WindowsPresentation;
4
using MKLiveView.GMapCustomMarkers;
5
using System;
6
using System.Collections.Generic;
7
using System.ComponentModel;
8
using System.Data;
9
using System.Diagnostics;
10
using System.IO;
11
using System.Linq;
12
using System.Linq.Expressions;
13
using System.Runtime.InteropServices;
14
using System.Text;
15
using System.Threading;
16
using System.Threading.Tasks;
17
using System.Windows;
18
using System.Windows.Controls;
19
using System.Windows.Data;
20
using System.Windows.Documents;
21
using System.Windows.Input;
22
using System.Windows.Interop;
23
using System.Windows.Media;
24
using System.Windows.Media.Animation;
25
using System.Windows.Media.Imaging;
26
using System.Windows.Navigation;
27
using System.Windows.Shapes;
28
using System.Windows.Threading;
2313 - 29
using System.Globalization;
2287 - 30
 
31
namespace MKLiveView
32
{
33
    /// <summary>
34
    /// Interaktionslogik für MainWindow.xaml
35
    /// </summary>
36
    public partial class MainWindow : Window
37
    {
2304 - 38
        #region declarations
39
 
2287 - 40
        GMapMarker copter;
41
        GMapMarker home;
42
        PointLatLng start;
43
        PointLatLng end;
44
        PointLatLng pHome;
45
 
46
 
47
        String[] NC_Error = new string[44]
48
        {
49
            "No Error",
50
            "FC not compatible" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A1_.22FC_not_compatible_.22",
51
            "MK3Mag not compatible" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A2_.22MK3Mag_not_compatible_.22",
52
            "no FC communication" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A3_.22no_FC_communication_.22",
53
            "no compass communication" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A4_.22no_compass_communication_.22",
54
            "no GPS communication" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A5_.22no_GPS_communication_.22",
55
            "bad compass value" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A6_.22bad_compass_value.22",
56
            "RC Signal lost" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A7_.22RC_Signal_lost_.22",
57
            "FC spi rx error" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A8_.22FC_spi_rx_error_.22",
58
            "ERR: no NC communication" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A9:_.22ERR:_no_NC_communication.22",
59
            "ERR: FC Nick Gyro" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A10_.22ERR:_FC_Nick_Gyro.22",
60
            "ERR: FC Roll Gyro" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A11_.22ERR:_FC_Roll_Gyro.22",
61
            "ERR: FC Yaw Gyro" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A12_.22ERR:_FC_Yaw_Gyro.22",
62
            "ERR: FC Nick ACC" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A13_.22ERR:_FC_Nick_ACC.22",
63
            "ERR: FC Roll ACC" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A14_.22ERR:_FC_Roll_ACC.22",
64
            "ERR: FC Z-ACC" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A15_.22ERR:_FC_Z-ACC.22",
65
            "ERR: Pressure sensor" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A16_.22ERR:_Pressure_sensor.22",
66
            "ERR: FC I2C" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A17_.22ERR:_FC_I2C.22",
67
            "ERR: Bl Missing" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A18_.22ERR:_Bl_Missing.22",
68
            "Mixer Error" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A19_.22Mixer_Error.22",
69
            "FC: Carefree Error" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A20_.22FC:_Carefree_Error.22",
70
            "ERR: GPS lost" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A21_.22ERR:_GPS_lost.22",
71
            "ERR: Magnet Error" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A22_.22ERR:_Magnet_Error.22",
72
            "Motor restart" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A23_.22Motor_restart.22",
73
            "BL Limitation" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A24_.22BL_Limitation.22",
74
            "Waypoint range" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A25_.22Waypoint_range.22",
75
            "ERR:No SD-Card" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A26_.22ERR:No_SD-Card.22",
76
            "ERR:SD Logging aborted" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A27_.22ERR:SD_Logging_aborted.22",
77
            "ERR:Flying range!" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A28_.22ERR:Flying_range.21.22",
78
            "ERR:Max Altitude" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A29_.22ERR:Max_Altitude.22",
79
            "No GPS Fix" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A30_.22No_GPS_Fix.22",
80
            "compass not calibrated" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A31_.22compass_not_calibrated.22",
81
            "ERR:BL selftest" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A32_.22ERR:BL_selftest.22",
82
            "no ext. compass" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A33_.22no_ext._compass.22",
83
            "compass sensor" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A34_.22compass_sensor.22",
84
            "FAILSAFE pos.!" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A35_.22FAILSAFE_pos..21__.22",
85
            "ERR:Redundancy" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A36_.22ERR:Redundancy__.22",
86
            "Redundancy test" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A37_.22Redundancy_test_.22",
87
            "GPS Update rate" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A38_.22GPS_Update_rate.22",
88
            "ERR:Canbus" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A39_.22ERR:Canbus.22",
89
            "ERR: 5V RC-Supply" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A40_.22ERR:_5V_RC-Supply.22",
90
            "ERR:Power-Supply" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A41_.22ERR:Power-Supply.22",
91
            "ACC not calibr." + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A42_.22ACC_not_calibr..22",
92
            "ERR:Parachute!" + Environment.NewLine + "http://wiki.mikrokopter.de/ErrorCodes#A43_.22ERR:Parachute.21.22"
93
        };
94
 
95
        [FlagsAttribute]
96
        enum NC_HWError0 : short
97
        {
98
            None = 0,
99
            SPI_RX = 1,
100
            COMPASS_RX = 2,
101
            FC_INCOMPATIBLE = 4,
102
            COMPASS_INCOMPATIBLE = 8,
103
            GPS_RX = 16,
104
            COMPASS_VALUE = 32
105
        };
106
        [FlagsAttribute]
107
        enum FC_HWError0 : short
108
        {
109
            None = 0,
110
            GYRO_NICK = 1,
111
            GYRO_ROLL = 2,
112
            GYRO_YAW = 4,
113
            ACC_NICK = 8,
114
            ACC_ROLL = 16,
115
            ACC_TOP = 32,
116
            PRESSURE = 64,
117
            CAREFREE = 128
118
        };
119
        [FlagsAttribute]
120
        enum FC_HWError1 : short
121
        {
122
            None = 0,
123
            I2C = 1,
124
            BL_MISSING = 2,
125
            SPI_RX = 4,
126
            PPM = 8,
127
            MIXER = 16,
128
            RC_VOLTAGE = 32,
129
            ACC_NOT_CAL = 64,
130
            RES3 = 128
131
        };
132
        public enum LogMsgType { Incoming, Outgoing, Normal, Warning, Error };
133
        // Various colors for logging info
134
        private Color[] LogMsgTypeColor = { Color.FromArgb(255, 43, 145, 175), Colors.Green, Colors.Black, Colors.Orange, Colors.Red };
135
 
136
        bool _bCBInit = true;
137
        bool _init = true;
138
        bool check_HWError = false;
139
 
140
        string filePath = Directory.GetCurrentDirectory();
141
        bool bReadContinously = false;
142
        bool _debugDataAutorefresh = true;
143
        bool _navCtrlDataAutorefresh = true;
144
        bool _blctrlDataAutorefresh = true;
145
        bool _OSDAutorefresh = true;
146
        bool _bErrorLog = false;
147
        bool _bConnErr = false;
148
        bool _bFollowCopter = false;
149
 
150
        bool _bSaveWinStateNormal = true;
151
        bool _bSaveWinStateFull = true;
152
 
153
        double scaleNormalAll = 1;
154
        double scaleNormalTopBar = 1;
155
        double scaleNormalMotors = 1;
156
        double scaleNormalOSD = 1;
157
        double scaleNormalLOG = 1;
158
        double scaleNormalHorizon = 1;
159
 
160
        double scaleFullAll = 1;
161
        double scaleFullTopBar = 1;
162
        double scaleFullMotors = 1;
163
        double scaleFullOSD = 1;
164
        double scaleFullLOG = 1;
165
        double scaleFullHorizon = 1;
166
 
167
        int _iCtrlAct = 0;
168
        int iOSDPage = 0;
169
        int iOSDMax = 0;
170
        int _iLifeCounter = 0;
171
        int crcError = 0;
172
 
2291 - 173
        bool _bSatFix = false;
174
        Storyboard stbSatFixLostAnim;
175
        bool _bAnimSatFixActive = false;
176
        bool _bVoiceSatFixActive = false;
177
        bool _bVoiceSatFixPlay = false;
178
        int _iSatsLast = 0;
179
        int _iSatsJitter = 0;
180
 
181
        bool _bMagneticFieldOK = false;
182
        Storyboard stbMagneticFieldAnim;
183
        bool _bAnimMagneticFieldActive = false;
184
        bool _bVoiceMagneticFieldActive = false;
185
        bool _bVoiceMagneticFieldPlay = false;
186
        int _iMagneticFieldLast = 0;
187
        int _iMagneticFieldJitter = 0;
188
 
189
        bool _bRCLevelOK = false;
190
        Storyboard stbRCLevelAnim;
191
        bool _bAnimRCLevelActive = false;
192
        bool _bVoiceRCLevelActive = false;
193
        bool _bVoiceRCLevelPlay = false;
194
        int _iRCLevelLast = 0;
195
        int _iRCLevelJitter = 0;
196
 
2287 - 197
        int _iMotors = 4;
198
        int _LipoCells = 4;
199
 
200
        double _dLipoVMax = 16.88;
201
        double _dLipoVMin = 12;
202
        double _dThresholdVoltageWarn = 0;
203
        double _dThresholdVoltageCrit = 0;
204
        Storyboard stbVoltageCritAnim;
205
        bool _bCritAnimVoltActive = false;
206
        bool _bCritVoiceVoltActive = false;
2291 - 207
        bool _bWarnVoiceVoltActive = false;
2287 - 208
        bool _bVoiceVoltPlay = false;
209
        double _dVoltLast = 0;
210
        int _iVoltJitter = 0;
211
 
2291 - 212
        double _dThresholdDistanceWarn = 100;
213
        Storyboard stbDistanceWarnAnim;
214
        bool _bAnimDistanceActive = false;
215
        bool _bVoiceDistanceActive = false;
216
        bool _bVoiceDistancePlay = false;
217
        double _dDistanceLast = 0;
218
        int _iDistanceJitter = 0;
219
 
220
        double _dThresholdDistanceMax = 1000;
221
        int _iThresholdRC = 160;
222
        int _iThresholdMagField = 15;
223
 
2295 - 224
        bool _bAutoHome = false;
225
        bool _bFirstSatFix = false;
226
        int _iFirstSatFix = 0;
2291 - 227
 
2287 - 228
        double _dTopHeight = 36;
229
 
230
        int[] serChan = new int[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
231
        int[] serChan_sub = new int[12] { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
232
        string[] serChanTitle = new string[12];
233
 
234
        string[] sAnalogLabel = new string[32];
235
        string[] sAnalogData = new string[32];
236
 
237
        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 };
238
        int[] iMotors = new int[] {3,4,5,6,7,8,9,10,11,12 };
239
        string[] sLiPoCells = new string[] { "3s", "4s", "5s", "6s" };
240
        /// <summary>
241
        /// interval for sending debugdata (multiplied by 10ms)
242
        /// </summary>
243
        byte debugInterval = 10; //(=> 100ms)
244
        /// <summary>
245
        /// interval for sending BL-CTRL status (multiplied by 10ms)
246
        /// </summary>
247
        byte blctrlInterval = 75;
248
        /// <summary>
249
        /// interval for sending NAV-CTRL status (multiplied by 10ms)
250
        /// </summary>
251
        byte navctrlInterval = 80;
252
        /// <summary>
253
        /// interval for sending OSD page update (multiplied by 10ms)
254
        /// </summary>
255
        byte OSDInterval = 85;
256
        /// <summary>
257
        /// datatable for the debug data array - displayed on settings tabpage in datagridview
258
        /// </summary>
259
        DataTable dtAnalog = new DataTable();
260
        /// <summary>
261
        /// datatable for motordata (current,temp)
262
        /// </summary>
2315 - 263
        DataTable dtMotors = new DataTable();
2287 - 264
 
265
        DataTable dtWaypoints = new DataTable();
2313 - 266
        static volatile int _iWPCount = -1;
267
        static volatile int _iWPIndex = -1;
268
        int _iWPTimeout = 1000;
2287 - 269
        bool _bGetWP = false;
270
        static volatile bool _bGetWPCount = false;
271
 
272
        DispatcherTimer timer = new DispatcherTimer();
273
 
274
        /// <summary>
275
        /// stuff for enabeling touch zoom for the map
276
        /// </summary>
277
        Point pTouch1 = new Point(0,0), pTouch2 = new Point(0,0);
278
        int iFirstStylusID = -1;
279
        public string connectButtonText
280
        {
281
            get
282
            {
283
                return bReadContinously ? "stop polling data" + System.Environment.NewLine + "from copter" : "start polling data" + System.Environment.NewLine + "from copter";
284
            }
285
        }
286
 
287
        WinState winState = new WinState();
2304 - 288
        #endregion declarations
2287 - 289
        public MainWindow()
290
        {
291
            InitializeComponent();
292
            _initForm();
293
            _dataTablesInit();
294
            _setupMap();
295
            _init = false;
296
            timer.Tick += new EventHandler(timerEvent);
297
            timer.Interval = new TimeSpan(0, 0, 1);
298
            timer.Start();
299
        }
300
 
301
        #region init
302
        void _initForm()
303
        {
304
            _readIni();
305
            if (_bSaveWinStateNormal)
306
                _setScaleSliders(false);
307
            cBoxTimingsDebug.ItemsSource =
308
                cBoxTimingsNav.ItemsSource =
309
                cBoxTimingsBl.ItemsSource =
310
                cBoxTimingsOSD.ItemsSource =
311
                iTimings;
312
            cBoxLiPoCells.ItemsSource = sLiPoCells;
313
            cBoxLiPoCells.SelectedItem = _LipoCells.ToString() + "s";
314
            _LipoMinMax();
315
            sliderThresholdVoltageWarn.Value = _dThresholdVoltageWarn;
316
            sliderThresholdVoltageCrit.Value = _dThresholdVoltageCrit;
317
            checkBoxThresholdVoltageVoice.IsChecked = _bVoiceVoltPlay;
2291 - 318
            checkBoxSatfixLost.IsChecked = _bVoiceSatFixPlay;
319
            checkBoxMagneticField.IsChecked = _bVoiceMagneticFieldPlay;
320
            checkBoxThresholdDistanceVoice.IsChecked = _bVoiceDistancePlay;
321
            sliderThresholdDistanceWarn.Value = _dThresholdDistanceWarn;
322
            checkBoxRClevel.IsChecked = _bVoiceRCLevelPlay;
2287 - 323
 
2291 - 324
            sliderThresholdDistanceWarn.Maximum = _dThresholdDistanceMax;
325
 
2287 - 326
            cBoxMotors.ItemsSource = iMotors;
327
            cBoxMotors.SelectedItem = _iMotors;
328
 
329
            serialPortCtrl.PortClosed += serialPortCtrl_PortClosed;
330
            serialPortCtrl.PortOpened += serialPortCtrl_PortOpened;
331
            serialPortCtrl.DataReceived += processMessage;
332
 
333
            chkbAutoBL.IsChecked = _blctrlDataAutorefresh;
334
            chkbAutoDbg.IsChecked = _debugDataAutorefresh;
335
            chkbAutoNav.IsChecked = _navCtrlDataAutorefresh;
336
            chkbAutoOSD.IsChecked = _OSDAutorefresh;
337
 
338
            cBoxTimingsDebug.SelectedItem = debugInterval * 10;
339
            cBoxTimingsNav.SelectedItem = navctrlInterval * 10;
340
            cBoxTimingsBl.SelectedItem = blctrlInterval * 10;
341
            cBoxTimingsOSD.SelectedItem = OSDInterval * 10;
2295 - 342
            checkBoxAutoSetHP.IsChecked = _bAutoHome;
2287 - 343
            checkBoxFollowCopter.IsChecked = _bFollowCopter;
344
 
345
 
346
        }
347
        /// <summary>
348
        /// initialize the datatables
349
        /// with columnnames etc
350
        /// </summary>
351
        void _dataTablesInit()
352
        {
2315 - 353
            dtMotors.Columns.Add("#");
2313 - 354
            if (Thread.CurrentThread.CurrentUICulture.Name == "de-DE")
2315 - 355
                dtMotors.Columns.Add("Strom");
2313 - 356
            else
2315 - 357
                dtMotors.Columns.Add("Current");
358
            dtMotors.Columns.Add("Temp");
359
            dgvMotors1.DataContext = dtMotors.DefaultView;
2287 - 360
            _initDTMotors();
361
 
362
            Setter setter = new Setter(ContentControl.PaddingProperty, new Thickness(5,0,5,0));
363
            Style style = new Style(typeof(System.Windows.Controls.Primitives.DataGridColumnHeader));
364
            style.Setters.Add(setter);
365
            setter = new Setter(ContentControl.BackgroundProperty, new SolidColorBrush(Colors.Transparent));
366
            style.Setters.Add(setter);
367
            setter = new Setter(ContentControl.ForegroundProperty, new SolidColorBrush(Colors.White));
368
            style.Setters.Add(setter);
2313 - 369
 
370
            dtWaypoints.Columns.Add("Index",typeof(int));
2315 - 371
            dtWaypoints.Columns.Add("Type", typeof(int));
2313 - 372
            dtWaypoints.Columns.Add("Name",typeof(string));
2315 - 373
            dtWaypoints.Columns.Add("Latitude",typeof(double));
374
            dtWaypoints.Columns.Add("Longitude",typeof(double));
2313 - 375
            dtWaypoints.Columns.Add("Altitude",typeof(string));
376
            dtWaypoints.Columns.Add("Heading",typeof(string));
377
            dtWaypoints.Columns.Add("Speed",typeof(string));
378
            dtWaypoints.Columns.Add("ClimbRate",typeof(string));
379
            dtWaypoints.Columns.Add("Radius",typeof(string));
380
            dtWaypoints.Columns.Add("HoldTime",typeof(string));
381
            dtWaypoints.Columns.Add("AutoTrigger",typeof(string));
382
            dtWaypoints.Columns.Add("CamAngle",typeof(string));
383
            dtWaypoints.Columns.Add("Event",typeof(string));
384
            dtWaypoints.Columns.Add("Out1Timer",typeof(string));
385
            dtWaypoints.Columns.Add("Status",typeof(string));
386
            dtWaypoints.PrimaryKey = new DataColumn[] { dtWaypoints.Columns["Index"] };
387
            dgvWP.ItemsSource = dtWaypoints.DefaultView;
2287 - 388
            dgvWP.ColumnHeaderStyle = new Style();
389
            dgvWP.ColumnHeaderStyle = style;
2313 - 390
 
391
 
2287 - 392
        }
393
        /// <summary>
2315 - 394
        /// initialize the datatable dtMotors for motor values
2313 - 395
        /// DataGridView dgvMotors1 is bound to dtMotors1
2287 - 396
        /// </summary>
397
        void _initDTMotors()
398
        {
399
            for (int i = 0; i < 12; i++)
400
            {
2315 - 401
                if (dtMotors.Rows.Count < 12)
402
                    dtMotors.Rows.Add((i + 1).ToString(), "NA", "NA");
2287 - 403
                else
404
                {
2315 - 405
                    dtMotors.Rows[i].SetField(1, "NA");
406
                    dtMotors.Rows[i].SetField(2, "NA");
2287 - 407
                }
408
            }
409
        }
410
 
411
        #endregion init
412
 
413
        #region events
414
        private void serialPortCtrl_PortOpened()
415
        {
416
            Dispatcher.Invoke(() => imageWiFi.Source = new BitmapImage(new Uri("Images/WiFi_G.png", UriKind.Relative)));
417
            _getVersion();
418
            Thread.Sleep(100);
419
            //_OSDMenue(0);
420
            //Thread.Sleep(200);
421
            //_sendSerialData();
422
            _readCont(true);
423
        }
424
        private void serialPortCtrl_PortClosed()
425
        {
426
            Dispatcher.Invoke(() => imageWiFi.Source = new BitmapImage(new Uri("Images/WiFi_W.png", UriKind.Relative)));
427
            _readCont(false);
428
        }
429
        void timerEvent(object sender, EventArgs e)
430
        {
431
            if (bReadContinously)
432
            {
433
                if (_debugDataAutorefresh) { _readDebugData(true); Thread.Sleep(10); }
434
 
435
                if (_blctrlDataAutorefresh) { _readBLCtrl(true); Thread.Sleep(10); }
436
 
437
                if (_navCtrlDataAutorefresh && _iCtrlAct == 2) { _readNavData(true); Thread.Sleep(10); }
438
                check_HWError = true;
439
                _getVersion();
440
                Thread.Sleep(10);
441
                if (_OSDAutorefresh)
442
                {
443
                    if (iOSDMax == 0 | cbOSD.Items.Count != iOSDMax)
444
                        _initOSDCB();
445
                    _OSDMenueAutoRefresh();
446
                }
447
                if (_iLifeCounter > 0)
448
                {
449
                    Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_G.png", UriKind.Relative)));
450
                  //  Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGreen));
451
                    _iLifeCounter = 0;
452
                    _bConnErr = false;
453
                }
454
                else
455
                {
456
                    if (!_bConnErr)
457
                    {
458
                        Log(LogMsgType.Error, "No communication to NC/FC!");
459
                        Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_R.png", UriKind.Relative)));
460
                       // Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.Red));
461
                        _bConnErr = true;
462
                    }
463
                }
464
            }
465
        }
466
 
467
        private void labelData_MouseDown(object sender, MouseButtonEventArgs e)
468
        {
469
            GridData.Visibility = GridData.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
470
            GridSettings.Visibility = GridWP.Visibility = Visibility.Collapsed;
471
        }
472
        private void labelMotorData_MouseDown(object sender, MouseButtonEventArgs e)
473
        {
474
            GridMotors.Visibility = GridMotors.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
475
            if (GridMotors.IsVisible)
476
                _setMotorGridSize();
477
        }
478
        private void labelSettings_MouseDown(object sender, MouseButtonEventArgs e)
479
        {
480
            GridData.Visibility = GridWP.Visibility = Visibility.Collapsed;
481
            GridSettings.Visibility = GridSettings.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
482
        }
483
        private void labelLog_MouseDown(object sender, MouseButtonEventArgs e)
484
        {
485
            GridLog.Visibility = GridLog.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
486
        }
487
        private void labelOSD_MouseDown(object sender, MouseButtonEventArgs e)
488
        {
489
            GridOSD.Visibility = GridOSD.Visibility == Visibility.Hidden ? Visibility.Visible : Visibility.Hidden;
490
        }
491
        private void labelWaypoints_MouseDown(object sender, MouseButtonEventArgs e)
492
        {
493
            GridData.Visibility = GridSettings.Visibility = Visibility.Collapsed;
494
            GridWP.Visibility = GridWP.Visibility == Visibility.Collapsed ? Visibility.Visible : Visibility.Collapsed;
495
        }
496
 
497
        private void btnGetWP_Click(object sender, RoutedEventArgs e)
498
        {
499
            Thread t = new Thread(new ThreadStart(_getWP));
500
            t.Start();
501
        }
502
        private void btnSendWPList_Click(object sender, RoutedEventArgs e)
503
        {
2313 - 504
            Thread t = new Thread(new ThreadStart(_sendWPList));
505
            t.Start();
2287 - 506
        }
507
 
508
        private void btnConnectToCopter_Click(object sender, RoutedEventArgs e)
509
        {
510
            if (!serialPortCtrl.Port.IsOpen)
511
                serialPortCtrl.Connect(true);
512
            else
513
                _readCont(!bReadContinously);
514
        }
515
        private void btnSetHP_Click(object sender, RoutedEventArgs e)
516
        {
517
            setHomePos();
518
        }
519
        private void btnClearHP_Click(object sender, RoutedEventArgs e)
520
        {
521
            clearHomePos();
522
        }
523
        private void btnGotoHP_Click(object sender, RoutedEventArgs e)
524
        {
525
            if (home != null && MainMap.Markers.Contains(home))
526
                MainMap.Position = home.Position;
527
        }
2295 - 528
        private void checkBoxAutoSetHP_Click(object sender, RoutedEventArgs e)
529
        {
530
            _bAutoHome = (bool)checkBoxAutoSetHP.IsChecked;
531
        }
2287 - 532
        private void chkBoxSaveNormalState_Click(object sender, RoutedEventArgs e)
533
        {
534
            _bSaveWinStateNormal = (bool)chkBoxSaveNormalState.IsChecked;
535
        }
536
        private void chkBoxSaveFullScreenState_Click(object sender, RoutedEventArgs e)
537
        {
538
            _bSaveWinStateFull = (bool)chkBoxSaveFullScreenState.IsChecked;
539
        }
540
 
2291 - 541
        #region thresholds
2287 - 542
        private void sliderThresholdVoltageWarn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
543
        {
544
            if(!_init)
545
                _dThresholdVoltageWarn = sliderThresholdVoltageWarn.Value;
546
        }
547
        private void sliderThresholdVoltageCrit_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
548
        {
549
            if(!_init)
550
                _dThresholdVoltageCrit = sliderThresholdVoltageCrit.Value;
551
        }
552
        private void checkBoxThresholdVoltageVoice_Click(object sender, RoutedEventArgs e)
553
        {
554
            _bVoiceVoltPlay = (bool)checkBoxThresholdVoltageVoice.IsChecked;
555
        }
2291 - 556
 
557
        private void sliderThresholdDistanceWarn_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
558
        {
559
            if(!_init)
560
                _dThresholdDistanceWarn = sliderThresholdDistanceWarn.Value;
561
        }
562
        private void checkBoxThresholdDistanceVoice_Click(object sender, RoutedEventArgs e)
563
        {
564
            _bVoiceDistancePlay = (bool)checkBoxThresholdDistanceVoice.IsChecked;
565
        }
566
 
567
        private void checkBoxSatfixLost_Click(object sender, RoutedEventArgs e)
568
        {
569
            _bVoiceSatFixPlay = (bool)checkBoxSatfixLost.IsChecked;
570
        }
571
        private void checkBoxMagneticField_Click(object sender, RoutedEventArgs e)
572
        {
573
            _bVoiceMagneticFieldPlay = (bool)checkBoxMagneticField.IsChecked;
574
        }
575
        private void checkBoxRClevel_Click(object sender, RoutedEventArgs e)
576
        {
577
            _bVoiceRCLevelPlay = (bool)checkBoxRClevel.IsChecked;
578
        }
579
        #endregion thresholds
580
 
2287 - 581
        private void buttonSwitchNC_Click(object sender, RoutedEventArgs e)
582
        {
583
            _switchToNC();
584
        }
585
 
586
        private void Window_Loaded(object sender, RoutedEventArgs e)
587
        {
588
            stbVoltageCritAnim = TryFindResource("VoltageCritAnim") as Storyboard;
2291 - 589
            stbSatFixLostAnim = TryFindResource("SatFixLostAnim") as Storyboard;
590
            stbMagneticFieldAnim = TryFindResource("MagneticFieldCritAnim") as Storyboard;
591
            stbDistanceWarnAnim = TryFindResource("DistanceCritAnim") as Storyboard;
592
            stbRCLevelAnim = TryFindResource("RCCritAnim") as Storyboard;
2287 - 593
            _setMotorGridSize();
594
        }
2310 - 595
        private void Window_Closing(object sender, CancelEventArgs e)
596
        {
597
            _writeIni();
598
        }
2287 - 599
        #endregion events
600
 
601
        #region GMap
602
 
603
        void _setupMap()
604
        {
605
            MainMap.Manager.Mode = AccessMode.ServerAndCache;
606
            MainMap.MapProvider = GMapProviders.BingHybridMap;
607
            MainMap.SetPositionByKeywords("Landshut");
608
            MainMap.MinZoom = 0;
609
            MainMap.MaxZoom = 24;
610
            MainMap.Zoom = 16;
611
            MainMap.ShowCenter = true;
612
            MainMap.ShowTileGridLines = false;
613
            sliderMapZoom.Value = 16;
614
            comboBoxMapType.ItemsSource = providerList;
615
            comboBoxMapType.DisplayMemberPath = "Name";
616
            comboBoxMapType.SelectedItem = MainMap.MapProvider;
617
 
618
            // acccess mode
619
            comboBoxMode.ItemsSource = Enum.GetValues(typeof(AccessMode));
620
            comboBoxMode.SelectedItem = MainMap.Manager.Mode;
621
 
622
        }
623
 
624
        /// <summary>
625
        /// selection of relevant map providers --> if You need more, You can change the line:
626
        ///     comboBoxMapType.ItemsSource = providerList; 
627
        /// to:
628
        ///     comboBoxMapType.ItemsSource = GMapProviders.List;
629
        /// in _setupMap()
630
        /// or add items here:
631
        /// </summary>
632
        List<GMap.NET.MapProviders.GMapProvider> providerList = new List<GMap.NET.MapProviders.GMapProvider>
633
        { GMap.NET.MapProviders.GMapProviders.OpenCycleMap, GMap.NET.MapProviders.GMapProviders.OpenCycleLandscapeMap, GMap.NET.MapProviders.GMapProviders.OpenCycleTransportMap,
634
        GMap.NET.MapProviders.GMapProviders.BingMap,GMap.NET.MapProviders.GMapProviders.BingSatelliteMap,GMap.NET.MapProviders.GMapProviders.BingHybridMap,
635
        GMap.NET.MapProviders.GMapProviders.GoogleMap,GMap.NET.MapProviders.GMapProviders.GoogleSatelliteMap,GMap.NET.MapProviders.GMapProviders.GoogleHybridMap,GMap.NET.MapProviders.GMapProviders.GoogleTerrainMap,
636
        GMap.NET.MapProviders.GMapProviders.OviMap,GMap.NET.MapProviders.GMapProviders.OviSatelliteMap,GMap.NET.MapProviders.GMapProviders.OviHybridMap,GMap.NET.MapProviders.GMapProviders.OviTerrainMap};
637
 
638
        private void MainMap_Loaded(object sender, RoutedEventArgs e)
639
        {
640
            MainMap.Manager.Mode = AccessMode.ServerAndCache;
641
            copter = new GMapMarker(MainMap.Position);
2318 - 642
 
643
            copter.Shape = new CustomMarkerCopter(this, copter, MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"),"red");
644
            if (comboBoxCopterColor.SelectionBoxItem != null)
645
            {
646
                string s = comboBoxCopterColor.SelectionBoxItem.ToString();
647
                ((CustomMarkerCopter)(copter.Shape)).setColor(s);
648
            }
2287 - 649
            copter.Offset = new System.Windows.Point(-18, -18);
650
            copter.ZIndex = int.MaxValue;
651
            MainMap.Markers.Add(copter);
652
            copter.Position = MainMap.Position;
653
        }
654
        void setHomePos()
655
        {
656
            pHome = MainMap.Position;
657
            if (!MainMap.Markers.Contains(home))
658
            {
659
                home = new GMapMarker(MainMap.Position);
660
                home.Shape = new CustomMarkerHome(this, home, MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"));
661
                home.Offset = new System.Windows.Point(-18, -18);
662
                // home.ZIndex = int.MaxValue;
663
                MainMap.Markers.Add(home);
664
            }
665
            home.Position = MainMap.Position;
666
            ((CustomMarkerHome)(home.Shape)).setText(MainMap.Position.Lat.ToString("0.#######°") + System.Environment.NewLine + MainMap.Position.Lng.ToString("0.#######°"));
667
        }
668
        void clearHomePos()
669
        {
670
            MainMap.Markers.Remove(home);
671
        }
672
 
673
        // access mode
674
        private void comboBoxMode_DropDownClosed(object sender, EventArgs e)
675
        {
676
            MainMap.Manager.Mode = (AccessMode)comboBoxMode.SelectedItem;
677
            MainMap.ReloadMap();
678
        }
679
        // zoom up
680
        private void czuZoomUp_Click(object sender, RoutedEventArgs e)
681
        {
682
            MainMap.Zoom = ((int)MainMap.Zoom) + 1;
683
        }
684
 
685
        // zoom down
686
        private void czuZoomDown_Click(object sender, RoutedEventArgs e)
687
        {
688
            MainMap.Zoom = ((int)(MainMap.Zoom + 0.99)) - 1;
689
        }
690
 
691
        // prefetch
692
        private void buttonPrefetch_Click(object sender, RoutedEventArgs e)
693
        {
694
            RectLatLng area = MainMap.SelectedArea;
695
            if (!area.IsEmpty)
696
            {
697
                for (int i = (int)MainMap.Zoom; i <= MainMap.MaxZoom; i++)
698
                {
699
                    MessageBoxResult res = MessageBox.Show("Ready ripp at Zoom = " + i + " ?", "GMap.NET", MessageBoxButton.YesNoCancel);
700
 
701
                    if (res == MessageBoxResult.Yes)
702
                    {
703
                        TilePrefetcher obj = new TilePrefetcher();
704
                        obj.Owner = this;
705
                        obj.ShowCompleteMessage = true;
706
                        obj.Start(area, i, MainMap.MapProvider, 100);
707
                    }
708
                    else if (res == MessageBoxResult.No)
709
                    {
710
                        continue;
711
                    }
712
                    else if (res == MessageBoxResult.Cancel)
713
                    {
714
                        break;
715
                    }
716
                }
717
            }
718
            else
719
            {
720
                MessageBox.Show("Select map area holding ALT", "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Exclamation);
721
            }
722
        }
723
 
724
        // goto by geocoder
725
        private void buttonGeoCoding_Click(object sender, RoutedEventArgs e)
726
        {
727
            _goto_byGeoCoder();
728
        }
729
        // goto by geocoder
730
        private void textBoxGeo_KeyUp(object sender, System.Windows.Input.KeyEventArgs e)
731
        {
732
            if (e.Key == System.Windows.Input.Key.Enter)
733
                _goto_byGeoCoder();
734
        }
735
        void _goto_byGeoCoder()
736
        {
737
            GeoCoderStatusCode status = MainMap.SetPositionByKeywords(textBoxGeo.Text);
738
            if (status != GeoCoderStatusCode.G_GEO_SUCCESS)
739
            {
740
                MessageBox.Show("Geocoder can't find: '" + textBoxGeo.Text + "', reason: " + status.ToString(), "GMap.NET", MessageBoxButton.OK, MessageBoxImage.Exclamation);
741
            }
742
        }
743
        private void buttonGeoLoc_Click(object sender, RoutedEventArgs e)
744
        {
745
            try
746
            {
747
                double lat = double.Parse(textBoxLat.Text, System.Globalization.CultureInfo.InvariantCulture);
748
                double lng = double.Parse(textBoxLng.Text, System.Globalization.CultureInfo.InvariantCulture);
749
 
750
                MainMap.Position = new PointLatLng(lat, lng);
751
            }
752
            catch (Exception ex)
753
            {
754
                MessageBox.Show("incorrect coordinate format: " + ex.Message);
755
            }
756
 
757
        }
758
 
759
        private void ReloadMap_Click(object sender, RoutedEventArgs e)
760
        {
761
            MainMap.ReloadMap();
762
        }
763
 
764
        private void MainMap_OnPositionChanged(PointLatLng point)
765
        {
766
            if (_bFollowCopter)
767
                _setCopterData(MainMap.Position);
768
        }
769
 
770
        private void MainMap_OnMapZoomChanged()
771
        {
772
            if (_bFollowCopter)
773
                _setCopterData(MainMap.Position);
774
            if((int)sliderMapZoom.Value != MainMap.Zoom)
775
                sliderMapZoom.Value = MainMap.Zoom;
776
        }
777
 
778
        void _setCopterData(PointLatLng p)
779
        {
780
            Dispatcher.Invoke(() =>
781
            {
782
                copter.Position = p;
783
                ((CustomMarkerCopter)(copter.Shape)).setText(p.Lat.ToString("0.#######°") + System.Environment.NewLine + p.Lng.ToString("0.#######°"));
784
                textBoxLat_currentPos.Text = p.Lat.ToString() + "°";
785
                textBoxLng_currentPos.Text = p.Lng.ToString() + "°";
786
            });
787
            if (home != null && MainMap.Markers.Contains(home))
788
            {
789
                Dispatcher.Invoke(() => ArtHor.rotateHome = GMapProviders.EmptyProvider.Projection.GetBearing(copter.Position, home.Position));
790
                double d = GMapProviders.EmptyProvider.Projection.GetDistance(home.Position, copter.Position);
791
                Dispatcher.Invoke(() => tbTopDistanceHP.Text = (d * 1000).ToString("0.0 m"));
2291 - 792
 
793
                if(d*1000 < _dThresholdDistanceWarn)
794
                {
795
                    _iDistanceJitter = 0; _bVoiceDistanceActive = false;
796
                    if (stbDistanceWarnAnim != null && _bAnimDistanceActive)
797
                    {
798
                        Dispatcher.Invoke(() => stbDistanceWarnAnim.Stop());
799
                        _bAnimDistanceActive = false;
800
                    }
801
                }
802
                else
803
                {
804
                    if (_iDistanceJitter < 20)
805
                    { _iDistanceJitter++; }
806
                    if (_iDistanceJitter == 20)
807
                    {
808
                        if (stbDistanceWarnAnim != null && !_bAnimDistanceActive)
809
                        {
810
                            Dispatcher.Invoke(() => stbDistanceWarnAnim.Begin());
811
                            _bAnimDistanceActive = true;
812
                        }
813
                        if (_bVoiceDistancePlay && !_bVoiceDistanceActive)
814
                        {
2295 - 815
                            Thread t = new Thread(()=>_mediaPlayer("Voice\\Distance.mp3"));
816
                            t.Start();
2291 - 817
                            _bVoiceDistanceActive = true;
818
                        }
819
                        _iDistanceJitter++;
820
                    }
821
                }
2287 - 822
            }
823
        }
824
 
825
        private void checkBoxFollowCopter_Click(object sender, RoutedEventArgs e)
826
        {
827
            _bFollowCopter = (bool)checkBoxFollowCopter.IsChecked;
828
        }
829
 
830
        private void sliderMapZoom_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
831
        {
832
            if (MainMap.Zoom != sliderMapZoom.Value)
833
                MainMap.Zoom = (int)sliderMapZoom.Value;
834
        }
835
        #region Touch zooming hackattack ;) 
836
        /// <summary>
837
        /// inspired by http://www.codeproject.com/Articles/692286/WPF-and-multi-touch
838
        /// </summary>
839
        bool bFirstAccess = true;
840
        double dDistance = 0;
841
        int iZoom;
842
        private void MainMap_StylusDown(object sender, StylusDownEventArgs e)
843
        {
844
            var id = e.StylusDevice.Id;
845
            e.StylusDevice.Capture(MainMap);
846
            if (iFirstStylusID == -1)
847
            {
848
                iFirstStylusID = id;
849
            }
850
            else
851
            {
852
 
853
                MainMap.CanDragMap = false;
854
            }
855
        }
856
        private void MainMap_StylusUp(object sender, StylusEventArgs e)
857
        {
858
            MainMap.ReleaseStylusCapture();
859
            iFirstStylusID = -1;
860
            bFirstAccess = true;
861
            MainMap.CanDragMap = true;
862
            iZoom = 0;
863
        }
864
        private void MainMap_StylusMove(object sender, StylusEventArgs e)
865
        {
866
            var id = e.StylusDevice.Id;
867
            var tp = e.GetPosition(MainMap);
868
 
869
            // This is the first Stylus point; just record its position. 
870
            if (id == iFirstStylusID)
871
            {
872
                pTouch1.X = tp.X;
873
                pTouch1.Y = tp.Y;
874
            }
875
            else
876
            if (iFirstStylusID > -1)
877
            {
878
                pTouch2.X = tp.X;
879
                pTouch2.Y = tp.Y;
880
                double distance = Point.Subtract(pTouch1, pTouch2).Length;
881
                if (!bFirstAccess)
882
                {
883
                    if (distance > dDistance)
884
                        iZoom++;
885
                    else
886
                        if (distance < dDistance)
887
                        iZoom--;
888
                }
889
                if (iZoom > 30)
890
                {
891
                    iZoom = 0;
892
                    Dispatcher.Invoke(() => sliderMapZoom.Value += 1);
893
                }
894
                if (iZoom < -30)
895
                {
896
                    iZoom = 0;
897
                    Dispatcher.Invoke(() => sliderMapZoom.Value -= 1);
898
                }
899
                dDistance = distance;
900
                bFirstAccess = false;
901
            }
902
        }
903
        #endregion Touch zooming hackattack ;)
904
 
905
        #endregion GMap
906
 
907
        #region settings
908
        private void cBoxTimingsDebug_DropDownClosed(object sender, EventArgs e)
909
        {
910
            if(! _bCBInit && cBoxTimingsDebug.SelectedIndex > -1)
911
                debugInterval = (byte)(Convert.ToInt16(cBoxTimingsDebug.SelectedItem) / 10);
912
        }
913
        private void cBoxTimingsNav_DropDownClosed(object sender, EventArgs e)
914
        {
915
            if(! _bCBInit && cBoxTimingsNav.SelectedIndex > -1)
916
                navctrlInterval = (byte)(Convert.ToInt16(cBoxTimingsNav.SelectedItem) / 10);
917
        }
918
        private void cBoxTimingsBl_DropDownClosed(object sender, EventArgs e)
919
        {
920
            if (!_bCBInit && cBoxTimingsBl.SelectedIndex > -1)
921
                blctrlInterval = (byte)(Convert.ToInt16(cBoxTimingsBl.SelectedItem) / 10);
922
        }
923
        private void cBoxTimingsOSD_DropDownClosed(object sender, EventArgs e)
924
        {
925
            if (!_bCBInit && cBoxTimingsOSD.SelectedIndex > -1)
926
                OSDInterval = (byte)(Convert.ToInt16(cBoxTimingsOSD.SelectedItem) / 10);
927
        }
928
        private void chkbAutoDbg_Click(object sender, RoutedEventArgs e)
929
        {
930
            if (!_init) _debugDataAutorefresh = (bool)chkbAutoDbg.IsChecked;
931
        }
932
        private void chkbAutoNav_Click(object sender, RoutedEventArgs e)
933
        {
934
            if (!_init) _navCtrlDataAutorefresh = (bool)chkbAutoNav.IsChecked;
935
        }
936
        private void chkbAutoBL_Click(object sender, RoutedEventArgs e)
937
        {
938
            if (!_init) _blctrlDataAutorefresh = (bool)chkbAutoBL.IsChecked;
939
        }
940
        private void chkbAutoOSD_Click(object sender, RoutedEventArgs e)
941
        {
942
            if (!_init) _OSDAutorefresh = (bool)chkbAutoOSD.IsChecked;
943
        }
944
 
945
        private void cBoxLiPoCells_DropDownClosed(object sender, EventArgs e)
946
        {
947
            if (cBoxLiPoCells.SelectedIndex > -1)
948
            {
949
                _LipoCells = cBoxLiPoCells.SelectedIndex + 3;
950
                _LipoMinMax();
951
            }
952
        }
953
        void _LipoMinMax()
954
        {
955
            _dLipoVMax = (double)(_LipoCells) * 4.22;
956
            _dLipoVMin = (double)_LipoCells * 3;
957
            pbTopVoltage.Maximum = _dLipoVMax;
958
            pbTopVoltage.Minimum = _dLipoVMin;
959
            sliderThresholdVoltageWarn.Maximum = _dLipoVMax;
960
            sliderThresholdVoltageWarn.Minimum = _dLipoVMin;
961
        }
962
        private void cBoxMotors_DropDownClosed(object sender, EventArgs e)
963
        {
964
            if (cBoxMotors.SelectedIndex > -1)
965
            {
966
                _iMotors = cBoxMotors.SelectedIndex + 3;
967
                Dispatcher.Invoke(() =>
968
                {
969
                    dgvMotors1.Height = (272 / 12.6) * (_iMotors + 1);  //272 / 12.6 --> Workaround, cause the headerheight = NaN...?
970
                    GridMotors.Height = dgvMotors1.Height + 10;
971
                });
972
            }
973
        }
974
        void _setMotorGridSize()
975
        {
976
            if (dgvMotors1.Columns.Count > 2)
977
            {
978
                dgvMotors1.Columns[0].Width = 24;
979
                dgvMotors1.Columns[1].Width = 50;
980
                dgvMotors1.Columns[2].Width = 50;
981
                dgvMotors1.Height = (272 / 12.6) * (_iMotors + 1);
982
                GridMotors.Height = dgvMotors1.Height + 10;
983
            }
984
 
985
        }
986
        #endregion settings
987
 
988
        #region functions  
989
 
990
        #region logging      
991
        /// <summary> Log data to the terminal window. </summary>
992
        /// <param name="msgtype"> The type of message to be written. </param>
993
        /// <param name="msg"> The string containing the message to be shown. </param>
994
        private void Log(LogMsgType msgtype, string msg)
995
        {
996
            Dispatcher.Invoke(() =>
997
            {
998
               // rtfTerminal.CaretPosition = rtfTerminal.CaretPosition.DocumentEnd;
999
               // rtfTerminal.Foreground = new SolidColorBrush(LogMsgTypeColor[(int)msgtype]);
1000
//                rtfTerminal.AppendText(msg + "\r");
1001
                TextRange tr = new TextRange(rtfTerminal.Document.ContentEnd,rtfTerminal.Document.ContentEnd);
1002
                tr.Text = msg;
1003
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
1004
                rtfTerminal.AppendText("\r");
1005
                rtfTerminal.ScrollToEnd();
1006
            });
1007
        }
1008
        private void ErrorLog(LogMsgType msgtype, string msg)
1009
        {
1010
            Dispatcher.Invoke(() =>
1011
            {
1012
                TextRange tr = new TextRange(rtfError.Document.ContentEnd, rtfError.Document.ContentEnd);
1013
                tr.Text = msg;
1014
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
1015
                rtfError.AppendText("\r");
1016
                rtfError.ScrollToEnd();
1017
 
1018
                _bErrorLog = true;
1019
            });
1020
        }
1021
        /// <summary>
1022
        /// Clear the line in the  errorlog window 
1023
        /// containing the error string when error has ceased
1024
        /// </summary>
1025
        /// <param name="s">substring of errrormessage</param>
1026
        void _clearErrorLog(string s)
1027
        {
1028
            Dispatcher.Invoke((Action)(() =>
1029
            {
1030
                TextRange searchRange = new TextRange(rtfError.Document.ContentStart, rtfError.Document.ContentEnd);
1031
                TextRange foundRange = FindTextInRange(searchRange, s);
1032
 
1033
                int iStart = searchRange.Text.IndexOf(s, StringComparison.OrdinalIgnoreCase);
1034
 
1035
 
1036
                if (iStart > -1)
1037
                {
1038
                    int iLength = 0;
1039
                    int iEnd = searchRange.Text.IndexOf('\r', iStart);
1040
                    if (iEnd > 0)
1041
                    {
1042
                        iLength = iEnd + 1;
1043
                        int iHttp = searchRange.Text.IndexOf("http", iEnd);
1044
                        if (iHttp == iLength)
1045
                        {
1046
                            int iEnd2 = searchRange.Text.IndexOf('\r', iLength);
1047
                            if (iEnd2 > iLength)
1048
                            {
1049
                                iLength = iEnd2 + 1;
1050
                              //  TextRange result = new TextRange(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
1051
 
1052
                                rtfError.Selection.Select(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
1053
                                rtfError.Selection.Text = string.Empty;
1054
                                if (rtfError.Document.ContentEnd.GetTextRunLength(LogicalDirection.Backward) < 2) _bErrorLog = false;
1055
                            }
1056
 
1057
                        }
1058
                        else
1059
                        {
1060
                            rtfError.Selection.Select(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), GetTextPositionAtOffset(rtfError.Document.ContentStart.GetPositionAtOffset(iStart), iLength));
1061
                            rtfError.Selection.Text = string.Empty;
1062
                            if (rtfError.Document.ContentEnd.GetTextRunLength(LogicalDirection.Backward) < 2) _bErrorLog = false;
1063
                        }
1064
                    }
1065
                }
1066
            }));
1067
 
1068
        }
1069
        public TextRange FindTextInRange(TextRange searchRange, string searchText)
1070
        {
1071
            int offset = searchRange.Text.IndexOf(searchText, StringComparison.OrdinalIgnoreCase);
1072
            if (offset < 0)
1073
                return null;  // Not found
1074
 
1075
            var start = GetTextPositionAtOffset(searchRange.Start, offset);
1076
            TextRange result = new TextRange(start, GetTextPositionAtOffset(start, searchText.Length));
1077
 
1078
            return result;
1079
        }
1080
        TextPointer GetTextPositionAtOffset(TextPointer position, int characterCount)
1081
        {
1082
            while (position != null)
1083
            {
1084
                if (position.GetPointerContext(LogicalDirection.Forward) == TextPointerContext.Text)
1085
                {
1086
                    int count = position.GetTextRunLength(LogicalDirection.Forward);
1087
                    if (characterCount <= count)
1088
                    {
1089
                        return position.GetPositionAtOffset(characterCount);
1090
                    }
1091
 
1092
                    characterCount -= count;
1093
                }
1094
 
1095
                TextPointer nextContextPosition = position.GetNextContextPosition(LogicalDirection.Forward);
1096
                if (nextContextPosition == null)
1097
                    return position;
1098
 
1099
                position = nextContextPosition;
1100
            }
1101
 
1102
            return position;
1103
        }
1104
        #endregion logging
1105
 
1106
        #region processing received data
1107
 
1108
        private void processMessage(byte[] message)
1109
        {
1110
            if (message.Length > 0)
1111
            {
1112
                _iLifeCounter++;
1113
                //Log(LogMsgType.Incoming, BitConverter.ToString(message));
1114
                //Log(LogMsgType.Incoming, message.Length.ToString());
1115
                string s = new string(ASCIIEncoding.ASCII.GetChars(message, 0, message.Length));
1116
                char cmdID;
1117
                byte adr;
1118
                byte[] data;
1119
                byte[] tmp = null;
1120
                if (message[0] != '#')
1121
                {
1122
                    int iFound = -1;
1123
                    for (int i = 0; i < message.Length; i++)   //Sometimes the FC/NC sends strings without termination (like WP messages)
1124
                    {                                   //so this is a workaround to not spam the log box
1125
                        if (message[i] == 35)
1126
                        {
1127
                            iFound = i;
1128
                            break;
1129
                        }
1130
                    }
1131
                    if (iFound > 0)
1132
                    {
1133
                        s = new string(ASCIIEncoding.ASCII.GetChars(message, 0, iFound));
1134
                        tmp = new byte[message.Length - iFound];
1135
                        Buffer.BlockCopy(message, iFound, tmp, 0, message.Length - iFound);
1136
                    }
1137
                    s = s.Trim('\0', '\n', '\r');
1138
                    if (s.Length > 0)
1139
                        Log(LogMsgType.Normal, s);
1140
                    if (tmp != null)
1141
                    {
1142
                        s = new string(ASCIIEncoding.ASCII.GetChars(tmp, 0, tmp.Length));
1143
                        processMessage(tmp);
1144
                    }
1145
                }
1146
                //Debug.Print(s);
1147
                else
1148
                {
1149
                    FlightControllerMessage.ParseMessage(message, out cmdID, out adr, out data);
1150
 
1151
                    if (adr == 255) { crcError++; }
1152
                    else crcError = 0;
1153
                    Dispatcher.Invoke(() => tbCrc.Text = crcError.ToString());
1154
                    //display the active controller (FC / NC) 
1155
                    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...???
1156
                    {
1157
                        _iCtrlAct = adr;
1158
                        switch (adr)
1159
                        {
1160
                            case 1:
1161
                                Dispatcher.Invoke(() => tbCtrl.Text = "FC");
2298 - 1162
                                Dispatcher.Invoke(() => buttonSwitchNC.Visibility = Visibility.Visible);
2287 - 1163
                                //Dispatcher.Invoke(() => labelSwitchToNavi.Visibility = Visibility.Visible);
1164
                              //  _setFieldsNA(); //display fields NA for FC 
1165
                                break;
1166
                            case 2:
1167
                                Dispatcher.Invoke(() => tbCtrl.Text = "NC");
1168
                                //Dispatcher.Invoke(() => buttonSwitchNC.Visibility = Visibility.Hidden);
1169
                                //Dispatcher.Invoke(() => labelSwitchToNavi.Visibility = Visibility.Hidden);
1170
                                break;
1171
                            //case 3:
1172
                            //    lblCtrl.Invoke((Action)(() => lblCtrl.Text = "MK3MAG"));
1173
                            //    break;
1174
                            //case 4:
1175
                            //    lblCtrl.Invoke((Action)(() => lblCtrl.Text = "BL-CTRL"));
1176
                            //    break;
1177
                            default:
1178
                                Dispatcher.Invoke(() => tbCtrl.Text = "NA");
1179
                                break;
1180
                        }
1181
                       // _loadLabelNames();
1182
                    }
1183
                    // else
1184
                    //     Debug.Print("Address == 0?");
1185
 
1186
                    if (data != null && data.Length > 0)
1187
                    {
1188
                        s = new string(ASCIIEncoding.ASCII.GetChars(data, 1, data.Length - 1));
1189
                        s = s.Trim('\0', '\n');
1190
 
1191
                        switch (cmdID)
1192
                        {
1193
                            //case 'A': //Label names
1194
                            //    _processLabelNames(s);
1195
                            //    break;
1196
 
1197
                            case 'D': //Debug data
1198
                                _processDebugVals(adr, data);
1199
                                break;
1200
 
1201
                            case 'V': //Version
1202
                                _processVersion(adr, data);
1203
                                break;
1204
 
1205
                            case 'K'://BL-CTRL data
1206
                                _processBLCtrl(data);
1207
                                break;
1208
 
1209
                            case 'O': //NC Data
1210
                                _processNCData(data);
1211
                                break;
1212
 
1213
                            case 'E': //NC error-string
1214
                                ErrorLog(LogMsgType.Error, "NC Error: " + s);
1215
                                break;
1216
 
1217
                            case 'L': //OSD Menue (called by pagenumber)
1218
                                _processOSDSingle(data);
1219
                                break;
1220
 
1221
                            case 'H': //OSD Menue (with autoupdate - called by Key)
1222
                                _processOSDAuto(data);
1223
                                break;
1224
 
1225
                            case 'X': //Waypoint data
1226
                                _processWPData(data);
1227
                                break;
1228
 
2313 - 1229
                            case 'W': //return new Waypoint items count after sending waypoint to copter
1230
                                _iWPCount = data[0];
1231
                                break;
2287 - 1232
                                //default:
1233
                                //    Log(LogMsgType.Incoming, "cmd: " + cmdID.ToString());
1234
                                //    Log(LogMsgType.Incoming, BitConverter.ToString(data));
1235
                                //    break;
1236
                        }
1237
                    }
1238
                    //else
1239
                    //{
1240
                    //    Log(LogMsgType.Incoming, "cmd: " + cmdID.ToString());
1241
                    //    Log(LogMsgType.Incoming, BitConverter.ToString(data));
1242
                    //}
1243
                }
1244
            }
1245
        }
1246
        /// <summary>
1247
        /// Analog label names 'A'
1248
        /// each label name is returned as a single string 
1249
        /// and added to string array sAnalogLabel[]
1250
        /// and the datatable dtAnalog
1251
        /// </summary>
1252
        /// <param name="s">the label name</param>
1253
        void _processLabelNames(string s)
1254
        {
1255
            //if (iLableIndex < 32)
1256
            //{
1257
            //    sAnalogLabel[iLableIndex] = s;
1258
            //    if (dtAnalog.Rows.Count < 32)
1259
            //        dtAnalog.Rows.Add(s, "");
1260
            //    else
1261
            //        dtAnalog.Rows[iLableIndex].SetField(0, s);
1262
 
1263
            //  //  _getAnalogLabels(iLableIndex + 1);
1264
            //}
1265
            //Debug.Print(s);
1266
        }
1267
        /// <summary>
1268
        /// Debug values 'D'
1269
        /// </summary>
1270
        /// <param name="adr">adress of the active controller (1-FC, 2-NC)</param>
1271
        /// <param name="data">the received byte array to process</param>
1272
        void _processDebugVals(byte adr, byte[] data)
1273
        {
1274
            if (data.Length == 66)
1275
            {
1276
                int[] iAnalogData = new int[32];
1277
                double v;
1278
                int index = 0;
1279
                Int16 i16 = 0;
1280
                double dTemp = 0;
1281
                for (int i = 2; i < 66; i += 2)
1282
                {
1283
                    i16 = data[i + 1];
1284
                    i16 = (Int16)(i16 << 8);
1285
                    iAnalogData[index] = data[i] + i16;
1286
                    sAnalogData[index] = (data[i] + i16).ToString();
1287
                   // dtAnalog.Rows[index].SetField(1, sAnalogData[index]);
1288
 
1289
                    if (adr == 2) //NC
1290
                    {
1291
                        switch (index)
1292
                        {
1293
                            case 0: //pitch (German: nick)
1294
                                Dispatcher.Invoke(() => ArtHor.Pitch = ((double)iAnalogData[index] / (double)10));
1295
                                Dispatcher.Invoke((Action)(() => tbPitch.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0°")));
1296
                                break;
1297
                            case 1: //roll
1298
                                Dispatcher.Invoke(() => ArtHor.Roll = ((double)iAnalogData[index] / (double)10));
1299
                                Dispatcher.Invoke((Action)(() => tbRoll.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0°")));
1300
                                break;
1301
                            case 4: //altitude
1302
                                Dispatcher.Invoke(() => tbAlt.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 m"));
1303
                                Dispatcher.Invoke(() => tbTopHeight.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 m"));
1304
                                break;
1305
                            case 7: //Voltage
1306
                                v = (double)iAnalogData[index] / (double)10;
1307
                                Dispatcher.Invoke(() => tbVolt.Text = v.ToString("0.0 V"));
1308
                                Dispatcher.Invoke(() => tbTopVoltage.Text = v.ToString("0.0 V"));
1309
                                Dispatcher.Invoke(() => pbTopVoltage.Value = v);
1310
                                if (v - _dLipoVMin < 1 | v < _dThresholdVoltageWarn)
1311
                                {
1312
                                    if (v == _dVoltLast)
1313
                                        if(_iVoltJitter < 20) _iVoltJitter++;
1314
                                    else
1315
                                    {
1316
                                        _iVoltJitter = 0;
1317
                                        _dVoltLast = v;
1318
                                    }
1319
                                    if (_iVoltJitter == 20)
1320
                                    {
1321
                                        Dispatcher.Invoke(() => pbTopVoltage.Foreground = Brushes.Orange);
1322
 
1323
                                        if (v - _dLipoVMin < 1 | v < _dThresholdVoltageCrit)
1324
                                        {
1325
                                            Dispatcher.Invoke(() => pbTopVoltage.Foreground = Brushes.Red);
1326
                                            if (stbVoltageCritAnim != null && !_bCritAnimVoltActive)
1327
                                            {
1328
                                                Dispatcher.Invoke(() => stbVoltageCritAnim.Begin());
1329
                                                _bCritAnimVoltActive = true;
1330
                                            }
1331
                                            if (_bVoiceVoltPlay && !_bCritVoiceVoltActive)
1332
                                            {
2295 - 1333
                                                Thread t = new Thread(() => _mediaPlayer("Voice\\CriticalBattery.mp3"));
1334
                                                t.Start();
2287 - 1335
                                                _bCritVoiceVoltActive = true;
1336
                                            }
1337
                                        }
1338
                                        else
1339
                                        {
1340
                                            if (stbVoltageCritAnim != null && _bCritAnimVoltActive)
1341
                                            {
1342
                                                Dispatcher.Invoke(() => stbVoltageCritAnim.Stop());
1343
                                                _bCritAnimVoltActive = false;
1344
                                            }
1345
                                            _bCritVoiceVoltActive = false;
1346
 
2291 - 1347
                                            if (_bVoiceVoltPlay && !_bWarnVoiceVoltActive)
2287 - 1348
                                            {
2295 - 1349
                                                Thread t = new Thread(() => _mediaPlayer("Voice\\LowBattery.mp3"));
1350
                                                t.Start();
2291 - 1351
                                                _bWarnVoiceVoltActive = true;
2287 - 1352
                                            }
1353
                                        }
1354
                                    }
1355
                                }
1356
                                else
1357
                                {
1358
                                    Dispatcher.Invoke(() => pbTopVoltage.Foreground = new SolidColorBrush(Color.FromArgb(255, 107, 195, 123)));
1359
                                    if (stbVoltageCritAnim != null && _bCritAnimVoltActive)
1360
                                    {
1361
                                        Dispatcher.Invoke(() => stbVoltageCritAnim.Stop());
1362
                                        _bCritAnimVoltActive = false;
1363
                                    }
1364
                                    _bCritVoiceVoltActive = false;
2291 - 1365
                                    _bWarnVoiceVoltActive = false;
2287 - 1366
                                    _iVoltJitter = 0;
1367
                                }
1368
                                break;
1369
                            case 8: // Current
1370
                                Dispatcher.Invoke(() => tbCur.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 A"));
1371
                                Dispatcher.Invoke(() => tbTopCurrent.Text = ((double)iAnalogData[index] / (double)10).ToString("0.0 A"));
1372
                                break;
1373
                            case 10: //heading
2291 - 1374
                                Dispatcher.Invoke((Action)(() => tbHeading.Text = sAnalogData[index] + "°"));
2287 - 1375
                                Dispatcher.Invoke(() => ArtHor.rotate = iAnalogData[index]);
1376
                                break;
1377
                            case 12: // SPI error
2291 - 1378
                                Dispatcher.Invoke((Action)(() => tbSPI.Text = sAnalogData[index]));
2287 - 1379
                                break;
1380
                            case 14: //i2c error
2291 - 1381
                                Dispatcher.Invoke((Action)(() => tbI2C.Text = sAnalogData[index]));
2287 - 1382
                                break;
1383
                            case 20: //Earthmagnet field
2291 - 1384
                                Dispatcher.Invoke((Action)(() => tbMagF.Text = sAnalogData[index] + "%"));
1385
                                Dispatcher.Invoke((Action)(() => tbTopEarthMag.Text = sAnalogData[index] + "%"));
1386
 
1387
                                if (Math.Abs(100 - iAnalogData[index]) < _iThresholdMagField)
1388
                                {
1389
                                    Dispatcher.Invoke(() => imageEarthMag.Source = new BitmapImage(new Uri("Images/EarthMag.png", UriKind.Relative)));
1390
                                    _iMagneticFieldJitter = 0; _bVoiceMagneticFieldActive = false;
1391
                                    if (stbMagneticFieldAnim != null && _bAnimMagneticFieldActive)
1392
                                    {
1393
                                        Dispatcher.Invoke(() => stbMagneticFieldAnim.Stop());
1394
                                        _bAnimMagneticFieldActive = false;
1395
                                    }
1396
                                }
1397
                                else
1398
                                {
1399
                                    Dispatcher.Invoke(() => imageEarthMag.Source = new BitmapImage(new Uri("Images/EarthMag_R.png", UriKind.Relative)));
1400
                                    if(_iMagneticFieldLast >= Math.Abs(100 - iAnalogData[index]))
1401
                                    {
1402
                                        if (_iMagneticFieldJitter < 20)
1403
                                            _iMagneticFieldJitter++;
1404
                                    }
1405
                                    else
1406
                                    {
1407
                                        _iMagneticFieldJitter = 0;
1408
                                        _iMagneticFieldLast = Math.Abs(100 - iAnalogData[index]);
1409
                                    }
1410
                                    if(_iMagneticFieldJitter == 20)
1411
                                    {
1412
                                        if (stbMagneticFieldAnim != null && !_bAnimMagneticFieldActive)
1413
                                        {
1414
                                            Dispatcher.Invoke(() => stbMagneticFieldAnim.Begin());
1415
                                            _bAnimMagneticFieldActive = true;
1416
                                        }
1417
                                        if (_bVoiceMagneticFieldPlay && !_bVoiceMagneticFieldActive)
1418
                                        {
2295 - 1419
                                            Thread t = new Thread(() => _mediaPlayer("Voice\\MagneticField.mp3"));
1420
                                            t.Start();
2291 - 1421
                                            _bVoiceMagneticFieldActive = true;
1422
                                        }
1423
                                    }
1424
                                }
2287 - 1425
                                break;
1426
                            case 21: //GroundSpeed
1427
                                     Dispatcher.Invoke((Action)(() => tbSpeed.Text = ((double)iAnalogData[index] / (double)100).ToString("0.00 m/s")));
1428
                                     Dispatcher.Invoke((Action)(() => tbTopSpeed.Text = ((double)iAnalogData[index] / (double)100).ToString("0.00 m/s")));
1429
                                break;
2291 - 1430
 
1431
                            ///**********   needs testing --> not sure what position this is  ***************
2287 - 1432
                            case 28: //Distance East from saved home position -> calculate distance with distance N + height
1433
                                    dTemp = Math.Pow((double)iAnalogData[index], 2) + Math.Pow((double)iAnalogData[index - 1], 2);
1434
                                    dTemp = Math.Sqrt(dTemp) / (double)10; //'flat' distance from HP with N/E
1435
                                                                           //  lblNCDist.Invoke((Action)(() => lblNCDist.Text = dTemp.ToString("0.00")));
1436
                                    dTemp = Math.Pow(dTemp, 2) + Math.Pow(((double)iAnalogData[4] / (double)10), 2); //adding 'height' into calculation
1437
                                    dTemp = Math.Sqrt(dTemp) / (double)10;
1438
                               //     Dispatcher.Invoke((Action)(() => tbTopDistanceHP.Text = dTemp.ToString("0.0 m")));
1439
                                    Dispatcher.Invoke((Action)(() => tbHP1.Text = dTemp.ToString("0.0 m")));
1440
                                break;
2291 - 1441
 
2287 - 1442
                            case 31: //Sats used
1443
                                     Dispatcher.Invoke((Action)(() => tbSats.Text = sAnalogData[index]));
1444
                                    // Dispatcher.Invoke((Action)(() => tbTopSats.Text = sAnalogData[index]));                                   
1445
                                break;
1446
                        }
1447
                    }
1448
                    index++;
1449
                }
1450
            }
1451
            else
1452
                Debug.Print("wrong data-length (66): " + data.Length.ToString());
1453
        }
1454
        /// <summary>
1455
        /// Version string 'V'
1456
        /// </summary>
1457
        /// <param name="adr">adress of the active controller (1-FC, 2-NC)</param>
1458
        /// <param name="data">the received byte array to process</param>
1459
        void _processVersion(byte adr, byte[] data)
1460
        {
1461
            if (data.Length == 12)
1462
            {
1463
                if (!check_HWError)
1464
                {
1465
                    string[] sVersionStruct = new string[10] { "SWMajor: ", "SWMinor: ", "ProtoMajor: ", "LabelTextCRC: ", "SWPatch: ", "HardwareError 1: ", "HardwareError 2: ", "HWMajor: ", "BL_Firmware: ", "Flags: " };
1466
                    string sVersion = "";
1467
                    //sbyte[] signed = Array.ConvertAll(data, b => unchecked((sbyte)b));
1468
                    Log(LogMsgType.Warning, (adr == 1 ? "FC-" : "NC-") + "Version: ");
1469
                    sVersion = "HW V" + (data[7] / 10).ToString() + "." + (data[7] % 10).ToString();
1470
                    Log(LogMsgType.Incoming, sVersion);
1471
                    sVersion = "SW V" + (data[0]).ToString() + "." + (data[1]).ToString() + ((char)(data[4] + 'a')).ToString();
1472
                    Log(LogMsgType.Incoming, sVersion);
1473
                    Log(LogMsgType.Incoming, "BL-Firmware: V" + (data[8] / 100).ToString() + "." + (data[8] % 100).ToString());
1474
                }
1475
                if (data[5] > 0) //error0 
1476
                {
1477
                    if (adr == 1)
1478
                        ErrorLog(LogMsgType.Error, "FC - HW-Error " + data[5].ToString() + ": " + ((FC_HWError0)data[5]).ToString());
1479
                    if (adr == 2)
1480
                        ErrorLog(LogMsgType.Error, "NC - HW-Error " + data[5].ToString() + ": " + ((NC_HWError0)data[5]).ToString());
1481
                }
1482
                if (data[6] > 0) //error1 
1483
                {
1484
                    if (adr == 1)
1485
                        ErrorLog(LogMsgType.Error, "FC - HW-Error " + data[6].ToString() + ": " + ((FC_HWError1)data[6]).ToString());
1486
                    if (adr == 2)
1487
                        ErrorLog(LogMsgType.Error, "NC - Unknown HW-ERROR: " + data[6].ToString()); //@moment NC has only one error field
1488
                }
1489
                if ((data[5] + data[6] == 0) && _bErrorLog)
1490
                    _clearErrorLog(adr == 1 ? "FC - HW-Error" : "NC - HW-Error");
1491
 
1492
            }
1493
            check_HWError = false;
1494
        }
1495
        /// <summary>
1496
        /// BL-Ctrl data 'K'
1497
        /// for FC you have to use a customized firmware
1498
        /// </summary>
1499
        /// <param name="data">the received byte array to process</param>
1500
        void _processBLCtrl(byte[] data)
1501
        {
1502
            if (data.Length % 6 == 0) //data.Length up to 96 (16 motors x 6 byte data) --> new datastruct in FC -> not standard!
1503
            {
1504
                bool bAvailable = false;
1505
                for (int i = 0; i < data.Length && data[i] < _iMotors; i += 6) // data[i] < _iMotors -- only show set number of motors (12 max @ moment)
1506
                {
1507
 
1508
                    if ((data[i + 4] & 128) == 128) //Status bit at pos 7 = 128 dec -- if true, motor is available
1509
                        bAvailable = true;
1510
                    else
1511
                        bAvailable = false;
1512
 
1513
                    if (data[i] < _iMotors)
1514
                    {
1515
                        if (bAvailable)
1516
                        {
2315 - 1517
                            dtMotors.Rows[data[i]].SetField(1, ((double)data[i + 1] / (double)10).ToString("0.0 A"));
1518
                            dtMotors.Rows[data[i]].SetField(2, data[i + 2].ToString("0 °C"));
2287 - 1519
                        }
1520
                        else
1521
                        {
2315 - 1522
                            dtMotors.Rows[data[i]].SetField(1, "NA");
1523
                            dtMotors.Rows[data[i]].SetField(2, "NA");
2287 - 1524
                        }
1525
                    }
1526
                    //if (data[i] > 3 && data[i] < 8)
1527
                    //{
1528
                    //    if (bAvailable)
1529
                    //    {
1530
                    //        dtMotors2.Rows[data[i] - 4].SetField(1, ((double)data[i + 1] / (double)10).ToString("0.0 A"));
1531
                    //        dtMotors2.Rows[data[i] - 4].SetField(2, data[i + 2].ToString("0 °C"));
1532
                    //    }
1533
                    //    else
1534
                    //    {
1535
                    //        dtMotors2.Rows[data[i] - 4].SetField(1, "NA");
1536
                    //        dtMotors2.Rows[data[i] - 4].SetField(2, "NA");
1537
                    //    }
1538
                    //}
1539
                }
1540
            }
1541
        }
1542
        /// <summary>
1543
        /// Navi-Ctrl data 'O'
1544
        /// GPS-Position, capacatiy, flying time...
1545
        /// </summary>
1546
        /// <param name="data">the received byte array to process</param>
1547
        void _processNCData(byte[] data)
1548
        {
1549
            int i_32, i_16, iVal;
1550
            double d;
1551
            i_32 = data[4];
1552
            iVal = i_32 << 24;
1553
            i_32 = data[3];
1554
            iVal += i_32 << 16;
1555
            i_32 = data[2];
1556
            iVal += i_32 << 8;
1557
            iVal += data[1];
1558
            d = (double)iVal / Math.Pow(10, 7);
1559
 
1560
            PointLatLng p = new PointLatLng();
1561
 
1562
            p.Lng = d;
1563
          //  lblNCGPSLong.Invoke((Action)(() => lblNCGPSLong.Text = d.ToString("0.######°"))); //GPS-Position: Longitude in decimal degree
1564
            //lblNCGPSLong.Invoke((Action)(() => lblNCGPSLong.Text = _convertDegree(d))); //GPS-Position: Longitude in minutes, seconds
1565
 
1566
            i_32 = data[8];
1567
            iVal = i_32 << 24;
1568
            i_32 = data[7];
1569
            iVal += i_32 << 16;
1570
            i_32 = data[6];
1571
            iVal += i_32 << 8;
1572
            iVal += data[5];
1573
            d = (double)iVal / Math.Pow(10, 7);
1574
            p.Lat = d;
2291 - 1575
            if (data[50] > 4)//if more than 4 sats in use . otherwise the map would jump and scroll insane at beginning
1576
            {
1577
                _bSatFix = true; _iSatsJitter = 0; _bVoiceSatFixActive = false;
2295 - 1578
                if(_bAutoHome && !_bFirstSatFix)
1579
                {
1580
                    if (_iFirstSatFix < 3)
1581
                        _iFirstSatFix++;
1582
                    else
1583
                    {
1584
                        _bFirstSatFix = true;
1585
                        Dispatcher.Invoke(() => setHomePos());
1586
                    }
1587
                }
2291 - 1588
                if (stbSatFixLostAnim != null && _bAnimSatFixActive)
1589
                {
1590
                    Dispatcher.Invoke(() => stbSatFixLostAnim.Stop());
1591
                    _bAnimSatFixActive = false;
1592
                }
1593
                if (!_bFollowCopter)
1594
                {
1595
                    _setCopterData(p);
1596
                    if (!MainMap.ViewArea.Contains(p))
1597
                        Dispatcher.Invoke(() => MainMap.Position = p);
2287 - 1598
 
2291 - 1599
                }
1600
                else
2287 - 1601
                    Dispatcher.Invoke(() => MainMap.Position = p);
1602
            }
1603
            else
2291 - 1604
            {
1605
                if(_bSatFix)
1606
                {
1607
                    if (data[50] == _iSatsLast)
1608
                    {
1609
                        if (_iSatsJitter < 20) _iSatsJitter++;
1610
                    }
1611
                    else
1612
                    {
1613
                        _iSatsJitter = 0;
1614
                        _iSatsLast = data[50];
1615
                    }
2287 - 1616
 
2291 - 1617
                    if (_iSatsJitter == 20)
1618
                    {
1619
                        if (stbSatFixLostAnim != null && !_bAnimSatFixActive)
1620
                        {
1621
                            Dispatcher.Invoke(() => stbSatFixLostAnim.Begin());
1622
                            _bAnimSatFixActive = true;
1623
                        }
1624
                        if (_bVoiceSatFixPlay && !_bVoiceSatFixActive)
1625
                        {
2295 - 1626
                            Thread th = new Thread(() => _mediaPlayer("Voice\\CriticalBattery.mp3"));
1627
                            th.Start();
2291 - 1628
                            _bVoiceSatFixActive = true;
1629
                        }
1630
 
1631
                        _bSatFix = false;
1632
                    }
1633
                }
1634
            }
1635
 
2287 - 1636
            //  lblNCGPSLat.Invoke((Action)(() => lblNCGPSLat.Text = d.ToString("0.######°"))); //GPS-Position: Latitude in decimal degree
1637
            //lblNCGPSLat.Invoke((Action)(() => lblNCGPSLat.Text = _convertDegree(d))); //GPS-Position: Latitude in minutes, seconds
1638
 
1639
            i_16 = data[28];
1640
            i_16 = (Int16)(i_16 << 8);
1641
            iVal = data[27] + i_16;
1642
            Dispatcher.Invoke((Action)(() => tbWP.Text = ((double)iVal / (double)10).ToString("0.0 m"))); //Distance to next WP
1643
 
1644
            i_16 = data[45];
1645
            i_16 = (Int16)(i_16 << 8);
1646
            iVal = data[44] + i_16;
1647
        //    Dispatcher.Invoke((Action)(() => tbTopDistanceHP.Text = ((double)iVal / (double)10).ToString("0.0 m"))); //Distance to HP set by GPS on
1648
            Dispatcher.Invoke((Action)(() => tbHP.Text = ((double)iVal / (double)10).ToString("0.0 m"))); //Distance to HP set by GPS on
1649
 
1650
            Dispatcher.Invoke((Action)(() => tbWPIndex.Text = data[48].ToString())); //Waypoint index
1651
            Dispatcher.Invoke((Action)(() => tbWPCount.Text = data[49].ToString())); //Waypoints count
1652
 
1653
            Dispatcher.Invoke((Action)(() => tbTopSats.Text = data[50].ToString())); //Satellites
1654
 
1655
 
1656
            //--------------- Capacity used ------------------------
1657
            i_16 = data[81];
1658
            i_16 = (Int16)(i_16 << 8);
1659
            iVal = data[80] + i_16;
1660
            Dispatcher.Invoke((Action)(() => tbCapacity.Text = iVal.ToString() + " mAh"));
1661
            Dispatcher.Invoke((Action)(() => tbTopCapacity.Text = iVal.ToString() + " mAh"));
1662
 
1663
            //--------------- Flying time ------------------------
1664
            i_16 = data[56];
1665
            i_16 = (Int16)(i_16 << 8);
1666
            iVal = data[55] + i_16;
1667
            TimeSpan t = TimeSpan.FromSeconds(iVal);
1668
            string Text = t.Hours.ToString("D2") + ":" + t.Minutes.ToString("D2") + ":" + t.Seconds.ToString("D2");
1669
            Dispatcher.Invoke((Action)(() => tbFTime.Text = Text.ToString()));
1670
            Dispatcher.Invoke((Action)(() => tbTopFTime.Text = Text.ToString()));
1671
 
1672
            //--------------- RC quality ------------------------
1673
            Dispatcher.Invoke((Action)(() => tbRCQ.Text = data[66].ToString()));
1674
            Dispatcher.Invoke((Action)(() => tbTopRC.Text = data[66].ToString()));
1675
 
2291 - 1676
            if(data[66] > _iThresholdRC)
1677
            {
1678
                _iRCLevelJitter = 0; _bVoiceRCLevelActive = false;
1679
                if (stbRCLevelAnim != null && _bAnimRCLevelActive)
1680
                {
1681
                    Dispatcher.Invoke(() => stbRCLevelAnim.Stop());
1682
                    _bAnimRCLevelActive = false;
1683
                }
1684
            }
1685
            else
1686
            {
1687
                if (_iRCLevelJitter < 20) _iRCLevelJitter++;
1688
                if (_iRCLevelJitter == 20)
1689
                {
1690
                    if (stbRCLevelAnim != null && !_bAnimRCLevelActive)
1691
                    {
1692
                        Dispatcher.Invoke(() => stbRCLevelAnim.Begin());
1693
                        _bAnimRCLevelActive = true;
1694
                    }
1695
                    if (_bVoiceRCLevelPlay && !_bVoiceRCLevelActive)
1696
                    {
2295 - 1697
                        Thread th = new Thread(() => _mediaPlayer("Voice\\RCLevel.mp3"));
1698
                        th.Start();
2291 - 1699
                        _bVoiceRCLevelActive = true;
1700
                    }
1701
                        _iRCLevelJitter++;
1702
                }
1703
            }
1704
 
2287 - 1705
            //--------------- NC Error ------------------------
1706
            Dispatcher.Invoke((Action)(() => tbNCErr.Text = data[69].ToString()));  //NC Errornumber
1707
            if (data[69] > 0)
1708
                _readNCError();
1709
            if (data[69] > 0 & data[69] < 44)
1710
                ErrorLog(LogMsgType.Error, "NC Error [" + data[69].ToString() + "]: " + NC_Error[data[69]]);
1711
            else
1712
                if (_bErrorLog) _clearErrorLog("NC Error");
1713
 
2298 - 1714
            //-------------FC / NC Status Flags
1715
            Dispatcher.Invoke((Action)(() => FC1_1.Background = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN                             0x01
1716
            Dispatcher.Invoke((Action)(() => FC1_2.Background = ((data[67] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_FLY                                   0x02
1717
            Dispatcher.Invoke((Action)(() => FC1_3.Background = ((data[67] & 4) ==4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_CALIBRATE                             0x04
1718
            Dispatcher.Invoke((Action)(() => FC1_4.Background = ((data[67] & 8) ==8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_START                                 0x08
1719
            Dispatcher.Invoke((Action)(() => FC1_5.Background = ((data[67] & 16) ==16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING                      0x10
1720
            Dispatcher.Invoke((Action)(() => FC1_6.Background = ((data[67] & 32) ==32) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_LOWBAT                         0x20
1721
 
1722
            Dispatcher.Invoke((Action)(() => FC2_1.Background = ((data[74] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE                             0x01
1723
            Dispatcher.Invoke((Action)(() => FC2_2.Background = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL                     0x02
1724
            Dispatcher.Invoke((Action)(() => FC2_3.Background = ((data[74] & 4) ==4) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_RC_FAILSAVE_ACTIVE                      0x04
1725
            Dispatcher.Invoke((Action)(() => FC2_4.Background = ((data[74] & 8) ==8) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT1_ACTIVE                          0x08
1726
            Dispatcher.Invoke((Action)(() => FC2_5.Background = ((data[74] & 16) ==16) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_OUT2_ACTIVE                        0x10
1727
            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
1728
            Dispatcher.Invoke((Action)(() => FC2_7.Background = ((data[74] & 64) ==64) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_STARTING                              0x40
1729
            Dispatcher.Invoke((Action)(() => FC2_8.Background = ((data[74] & 128) ==128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_AUTO_LANDING                             0x80
1730
 
1731
            Dispatcher.Invoke((Action)(() => NC1_2.Background = ((data[68] & 2) == 2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_PH                                     0x02
1732
            Dispatcher.Invoke((Action)(() => NC1_3.Background = ((data[68] & 4) == 4) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_CH                                     0x04
1733
            Dispatcher.Invoke((Action)(() => NC1_4.Background = ((data[68] & 8) == 8) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_RANGE_LIMIT                               0x08
1734
            Dispatcher.Invoke((Action)(() => NC1_5.Background = ((data[68] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_NOSERIALLINK                            0x10
1735
            Dispatcher.Invoke((Action)(() => NC1_6.Background = ((data[68] & 32) == 32) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_TARGET_REACHED                               0x20
1736
            Dispatcher.Invoke((Action)(() => NC1_7.Background = ((data[68] & 64) == 64) ? new SolidColorBrush(Colors.DodgerBlue) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_MANUAL_CONTROL                          0x40
1737
            Dispatcher.Invoke((Action)(() => NC1_8.Background = ((data[68] & 128) == 128) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// NC_FLAG_GPS_OK                                     0x80
2299 - 1738
 
1739
            //Sidebar StatusSymbols
1740
            Dispatcher.Invoke((Action)(() => tbSideBarStatusMotors.Background = ((data[67] & 1) ==1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_MOTOR_RUN                             0x01
1741
            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
1742
            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
1743
 
1744
            Dispatcher.Invoke((Action)(() => tbSideBarStatusCF.Background = ((data[74] & 1) == 1) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_CAREFREE                                0x01
1745
            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
1746
            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
1747
 
1748
            Dispatcher.Invoke((Action)(() => tbSideBarStatusEmergencyLanding.Background = ((data[67] & 16) == 16) ? new SolidColorBrush(Colors.LightCoral) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS_EMERGENCY_LANDING                   0x10
2304 - 1749
            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
1750
            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
2299 - 1751
 
1752
            Dispatcher.Invoke((Action)(() => tbSideBarStatusAC.Background = ((data[74] & 2) ==2) ? new SolidColorBrush(Colors.LightSeaGreen) : new SolidColorBrush(Colors.Transparent)));// FC_STATUS2_ALTITUDE_CONTROL                         0x02
1753
            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
1754
            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
1755
 
1756
            Dispatcher.Invoke((Action)(() => tbSideBarStatusPH.Text = ((data[68] & 4) == 4) ? "CH" : "PH"));// NC_FLAG_PH 0x02 / NC_FLAG_CH 0x04
2304 - 1757
            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
1758
            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
1759
            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
2299 - 1760
 
2287 - 1761
        }
1762
        /// <summary>
1763
        /// Navi-Ctrl WP data struct 'X'
1764
        /// called by index
1765
        /// </summary>
1766
        /// <param name="data">the received byte array to process</param>
1767
        void _processWPData(byte[] data)
1768
        {
2313 - 1769
            _iWPCount = data[0];
2287 - 1770
            _bGetWPCount = false;
1771
            if (data.Length >= 28)
1772
            {
1773
                Dispatcher.Invoke(() => lblWPIndex.Content = data[1].ToString());
1774
                Dispatcher.Invoke(() => lblWPCount.Content = data[0].ToString());
1775
                if (_bGetWP)
1776
                {
1777
                    if (data[1] == 1)
2315 - 1778
                    {
2287 - 1779
                        dtWaypoints.Rows.Clear();
2318 - 1780
                        Dispatcher.Invoke(() => {
1781
                            for (int k = 0; k < MainMap.Markers.Count;)
1782
                            {
1783
                                GMapMarker p = MainMap.Markers[k];
1784
                                if (p.Shape.GetType() == typeof(CustomMarkerWP))
1785
                                    MainMap.Markers.Remove(p);
1786
                                else
1787
                                    k++;
1788
                            }
1789
                        });
2315 - 1790
                    }
2287 - 1791
                    DataRow dr = dtWaypoints.NewRow();
1792
                    dr = Waypoints.toDataRow(data, dr);
2313 - 1793
                    dtWaypoints.Rows.Add(dr);
2318 - 1794
                    Dispatcher.Invoke(() => {
1795
                        GMapMarker wp = new GMapMarker(new PointLatLng((double)dr[3], (double)dr[4]));
1796
                        wp.Shape = new CustomMarkerWP(this, wp, (string)dr[2],(int)dr[1]);
1797
                        _setMarkerColor(wp, (int)dr[1]);
1798
                        MainMap.Markers.Add(wp);
1799
                    });
2313 - 1800
                    Dispatcher.Invoke(() => dgvWP.Items.Refresh());
1801
                    Dispatcher.Invoke(() => _iWPIndex = data[1]);
2287 - 1802
                    if (data[1] == data[0])
1803
                    {
1804
                        _bGetWP = false;
1805
                        Dispatcher.Invoke(() => dgvWP.Items.Refresh());
1806
                    }
1807
 
1808
                }
1809
            }
1810
            else
1811
            {
1812
                Dispatcher.Invoke(() => lblWPIndex.Content = 0);
1813
                Dispatcher.Invoke(() => lblWPCount.Content = 0);
1814
            }
1815
        }
1816
        /// <summary>
1817
        /// OSD Menue 'L'
1818
        /// single page called by pagenumber
1819
        /// no autoupdate
1820
        /// </summary>
1821
        /// <param name="data">the received byte array to process</param>
1822
        void _processOSDSingle(byte[] data)
1823
        {
1824
            if (data.Length == 84)
1825
            {
1826
                string sMessage = "";
1827
                iOSDPage = data[0];
1828
                iOSDMax = data[1];
1829
                if (cbOSD.Items.Count != iOSDMax) _initOSDCB();
1830
                sMessage = new string(ASCIIEncoding.ASCII.GetChars(data, 2, data.Length - 4));
1831
                OSD(LogMsgType.Incoming, sMessage.Substring(0, 20)+ "\r", true);
1832
                OSD(LogMsgType.Incoming, sMessage.Substring(20, 20)+ "\r", false);
1833
                OSD(LogMsgType.Incoming, sMessage.Substring(40, 20)+ "\r", false);
1834
                OSD(LogMsgType.Incoming, sMessage.Substring(60, 20), false);
1835
                Dispatcher.Invoke(() => { cbOSD.SelectedValue = iOSDPage; });
1836
              //  lblOSDPageNr.Invoke((Action)(() => lblOSDPageNr.Text = iOSDPage.ToString("[0]")));
1837
 
1838
            }
1839
            //else
1840
            //    OSD(LogMsgType.Incoming, "Wrong length: " + data.Length + " (should be 84)");
1841
 
1842
        }
1843
        /// <summary>
1844
        /// OSD Menue 'H'
1845
        /// called by keys (0x01,0x02,0x03,0x04)
1846
        /// autoupdate
1847
        /// </summary>
1848
        /// <param name="data">the received byte array to process</param>
1849
        void _processOSDAuto(byte[] data)
1850
        {
1851
            if (data.Length == 81)
1852
            {
1853
                string sMessage = "";
1854
                sMessage = new string(ASCIIEncoding.ASCII.GetChars(data, 0, data.Length - 1));
1855
                OSD(LogMsgType.Incoming, sMessage.Substring(0, 20)+ "\r", true);
1856
                OSD(LogMsgType.Incoming, sMessage.Substring(20, 20)+ "\r", false);
1857
                OSD(LogMsgType.Incoming, sMessage.Substring(40, 20)+ "\r", false);
1858
                OSD(LogMsgType.Incoming, sMessage.Substring(60, 20), false);
1859
 
1860
            }
1861
            //else
1862
            //    OSD(LogMsgType.Incoming, "Wrong length: " + data.Length + " (should be 81)");
1863
        }
1864
 
1865
        #endregion processing received data
1866
 
1867
        #region controller messages
1868
        /// <summary> send message to controller to request data
1869
        /// for detailed info see http://wiki.mikrokopter.de/en/SerialProtocol/
1870
        /// </summary>
1871
        /// <param name="CMDID"> the command ID </param>
1872
        /// <param name="address"> the address of the controller: 0-any, 1-FC, 2-NC </param>
1873
        private void _sendControllerMessage(char CMDID, byte address)
1874
        {
1875
            if (serialPortCtrl.Port.IsOpen)
1876
            {
1877
                Stream serialStream = serialPortCtrl.Port.BaseStream;
1878
                byte[] bytes = FlightControllerMessage.CreateMessage(CMDID, address);
1879
                serialStream.Write(bytes, 0, bytes.Length);
1880
 
1881
            }
1882
            else
1883
                Log(LogMsgType.Error, "NOT CONNECTED!");
1884
        }
1885
        /// <summary> send message to controller to request data
1886
        /// for detailed info see http://wiki.mikrokopter.de/en/SerialProtocol/
1887
        /// </summary>
1888
        /// <param name="CMDID"> the command ID </param>
1889
        /// <param name="address"> the address of the controller: 0-any, 1-FC, 2-NC </param>
1890
        /// <param name="data"> additional data for the request</param>
1891
        private void _sendControllerMessage(char CMDID, byte address, byte[] data)
1892
        {
1893
            if (serialPortCtrl.Port.IsOpen)
1894
            {
1895
                Stream serialStream = serialPortCtrl.Port.BaseStream;
1896
                byte[] bytes = FlightControllerMessage.CreateMessage(CMDID, address, data);
1897
                serialStream.Write(bytes, 0, bytes.Length);
1898
 
1899
            }
1900
            else
1901
                Log(LogMsgType.Error, "NOT CONNECTED!");
1902
        }
1903
 
1904
        /// <summary>
1905
        /// start/stop continous polling of controller values
1906
        /// </summary>
1907
        /// <param name="b">start/stop switch</param>
1908
        void _readCont(bool b)
1909
        {
1910
            bReadContinously = b;
1911
            if (bReadContinously)
1912
            {
1913
                if (_debugDataAutorefresh) { _readDebugData(true); Thread.Sleep(10); }
1914
                if (_blctrlDataAutorefresh) { _readBLCtrl(true); Thread.Sleep(10); }
1915
                if (_navCtrlDataAutorefresh && _iCtrlAct == 2) { _readNavData(true); Thread.Sleep(10); }
1916
                if (_OSDAutorefresh) { _OSDMenueAutoRefresh(); Thread.Sleep(10); }
1917
                // Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGreen));
1918
                Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_G.png", UriKind.Relative)));
1919
            }
1920
            else
1921
            {
1922
                // Dispatcher.Invoke((Action)(() => rctConnection.Fill = Brushes.LightGray));
1923
                Dispatcher.Invoke(() => imageConn.Source = new BitmapImage(new Uri("Images/Data_W.png", UriKind.Relative)));
1924
                _bConnErr = false;
1925
            }
1926
            _iLifeCounter = 0;
1927
        }
1928
 
1929
        private void _getVersion()
1930
        {
1931
            _sendControllerMessage('v', 0);
1932
        }
1933
        /// <summary>
1934
        /// get FC version struct via NC
1935
        /// by sending '1' as data (not documented in wiki...)
1936
        /// returns HW error 255 (comment in uart1.c : tells the KopterTool that it is the FC-version)
1937
        /// </summary>
1938
        /// <param name="ctrl">controller number 1=FC</param> 
1939
        private void _getVersion(byte ctrl)
1940
        {
1941
            _sendControllerMessage('v', 0, new byte[1] { ctrl });
1942
        }
1943
        /// <summary>
1944
        /// Switch back to NC by sending the 'Magic Packet' 0x1B,0x1B,0x55,0xAA,0x00
1945
        /// </summary>
1946
        private void _switchToNC()
1947
        {
1948
            if (serialPortCtrl.Port.IsOpen)
1949
            {
1950
                Stream serialStream = serialPortCtrl.Port.BaseStream;
1951
                byte[] bytes = new byte[5] { 0x1B, 0x1B, 0x55, 0xAA, 0x00 };
1952
                serialStream.Write(bytes, 0, bytes.Length);
1953
 
1954
                Thread.Sleep(100);
1955
                _getVersion();
1956
                Thread.Sleep(100);
1957
               // _OSDMenue(0);
1958
            }
1959
            else
1960
                Log(LogMsgType.Error, "NOT CONNECTED!");
1961
        }
1962
        /// <summary>
1963
        /// switch to FC
1964
        /// </summary>
1965
        private void _switchToFC()
1966
        {
1967
            _sendControllerMessage('u', 2, new byte[1] { (byte)0 });
1968
            Thread.Sleep(100);
1969
            _getVersion();
1970
            Thread.Sleep(100);
1971
          //  _OSDMenue(0);
1972
        }
1973
        /// <summary>
1974
        /// send RESET signal to FC
1975
        /// </summary>
1976
        private void _resetCtrl()
1977
        {
1978
            _sendControllerMessage('R', 1);
1979
        }
1980
        /// <summary>
1981
        /// poll the debug data (4sec subscription)
1982
        /// </summary>
1983
        /// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
1984
        private void _readDebugData(bool auto)
1985
        {
1986
            byte interval = auto ? debugInterval : (byte)0;
1987
            _sendControllerMessage('d', 0, new byte[1] { debugInterval });
1988
        }
1989
        /// <summary>
1990
        /// poll the BL-CTRL status via NC (4sec subscription)
1991
        /// </summary>
1992
        /// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
1993
        private void _readBLCtrl(bool auto)
1994
        {
1995
            byte interval = auto ? blctrlInterval : (byte)0;
1996
            _sendControllerMessage('k', 0, new byte[1] { interval });
1997
        }
1998
        /// <summary>
1999
        /// poll the NC data struct (4sec subscription)
2000
        /// </summary>
2001
        /// <param name="auto"> onetimequery(false) or autoupdate(true) with set timing interval </param>
2002
        private void _readNavData(bool auto)
2003
        {
2004
            byte interval = auto ? navctrlInterval : (byte)0;
2005
            _sendControllerMessage('o', 2, new byte[1] { interval });
2006
        }
2007
        /// <summary>
2008
        /// get the errortext for pending NC error
2009
        /// </summary>
2010
        private void _readNCError()
2011
        {
2012
            _sendControllerMessage('e', 2);
2013
        }
2014
        /// <summary>
2015
        /// request the Waypoint at index
2016
        /// </summary>
2017
        /// <param name="index"></param>
2018
        void _getpWP(int index)
2019
        {
2020
            if (serialPortCtrl.Port.IsOpen)
2021
            {
2022
                Stream serialStream = serialPortCtrl.Port.BaseStream;
2023
                byte[] bytes = FlightControllerMessage.CreateMessage('x', 2, new byte[1] { (byte)index });
2024
                serialStream.Write(bytes, 0, bytes.Length);
2025
            }
2026
            else
2027
                Log(LogMsgType.Error, "NOT CONNECTED!");
2028
 
2029
        }
2030
        void _getWP()
2031
        {
2032
            _bGetWPCount = true;
2315 - 2033
            _getpWP(1); //get the itemscount of wp
2287 - 2034
            while (_bGetWPCount)
2035
                Thread.Sleep(100);
2313 - 2036
            if (_iWPCount > 0)
2287 - 2037
                _getWPList();
2038
        }
2039
        void _getWPList()
2040
        {
2041
            _bGetWP = true;
2313 - 2042
            int iTimeout=0;
2043
            for (int j = 0; j < _iWPCount; j++)
2287 - 2044
            {
2045
                _getpWP(j + 1);
2313 - 2046
                iTimeout = 0;
2047
                while (_iWPIndex != j + 1 & iTimeout < _iWPTimeout * 5)
2048
                {
2049
                    Thread.Sleep(1);
2050
                    iTimeout++;
2051
                }
2287 - 2052
            }
2053
        }
2313 - 2054
        void _sendWPList()
2055
        {
2056
            if (serialPortCtrl.Port.IsOpen)
2057
            {
2058
                byte[] bData = new byte[30];
2059
                for (int i = 0; i < 30; i++)
2060
                    bData[i] = 0;
2061
                Stream serialStream = serialPortCtrl.Port.BaseStream;
2062
                byte[] bytes = FlightControllerMessage.CreateMessage('w', 2, bData); //delete all WP on Copter by sending 'invalid'(==0) at index 0
2063
                serialStream.Write(bytes, 0, bytes.Length);
2287 - 2064
 
2313 - 2065
                _iWPCount = -1;
2066
                while (_iWPCount == -1)
2067
                    Thread.Sleep(10);
2068
                Dispatcher.Invoke(() => lblWPCount.Content = _iWPCount.ToString());
2287 - 2069
 
2313 - 2070
                int iVal;
2071
                double dVal;
2072
                NumberFormatInfo nfi = new NumberFormatInfo();
2073
                nfi.NumberDecimalSeparator = ",";
2074
                for (int i = 0; i < dtWaypoints.Rows.Count; i++)
2075
                {
2076
                    //longitude
2077
                    dVal = Convert.ToDouble(dtWaypoints.Rows[i][4], nfi);
2078
                    iVal = (int)(dVal * Math.Pow(10, 7));
2079
                    bData[0] = (byte)(iVal & 0xff);
2080
                    bData[1] = (byte)((iVal >> 8) & 0xff);
2081
                    bData[2] = (byte)((iVal >> 16) & 0xff);
2082
                    bData[3] = (byte)(iVal >> 24);
2083
                    //latitude
2084
                    dVal = Convert.ToDouble(dtWaypoints.Rows[i][3], nfi);
2085
                    iVal = (int)(dVal * Math.Pow(10, 7));
2086
                    bData[4] = (byte)(iVal & 0xff);
2087
                    bData[5] = (byte)((iVal >> 8) & 0xff);
2088
                    bData[6] = (byte)((iVal >> 16) & 0xff);
2089
                    bData[7] = (byte)(iVal >> 24);
2090
                    //altitude
2091
                    dVal = Convert.ToDouble(dtWaypoints.Rows[i][5], nfi);
2092
                    iVal = (int)(dVal * 10);
2093
                    bData[8] = (byte)(iVal & 0xff);
2094
                    bData[9] = (byte)((iVal >> 8) & 0xff);
2095
                    bData[10] = (byte)((iVal >> 16) & 0xff);
2096
                    bData[11] = (byte)(iVal >> 24);
2097
                    //Status 'NEWDATA'
2098
                    bData[12] = 1;
2099
                    //heading
2100
                    iVal = Convert.ToInt16(dtWaypoints.Rows[i][6]);
2101
                    bData[13] = (byte)(iVal & 0xff);
2102
                    bData[14] = (byte)((iVal >> 8) & 0xff);
2103
                    //ToleranceRadius
2104
                    bData[15] = Convert.ToByte(dtWaypoints.Rows[i][9]);
2105
                    //HoldTime
2106
                    bData[16] = Convert.ToByte(dtWaypoints.Rows[i][10]);
2107
                    //Event_Flag
2108
                    bData[17] = Convert.ToByte(dtWaypoints.Rows[i][13]);
2109
                    //Index
2110
                    bData[18] = Convert.ToByte((int)dtWaypoints.Rows[i][0]);
2111
                    //Type
2112
                    bData[19] = Convert.ToByte(dtWaypoints.Rows[i][1]);
2113
                    //WP_EventChannelValue
2114
                    bData[20] = Convert.ToByte(dtWaypoints.Rows[i][14]);
2115
                    //AltitudeRate
2116
                    bData[21] = Convert.ToByte(dtWaypoints.Rows[i][8]);
2117
                    //Speed
2118
                    bData[22] = Convert.ToByte(dtWaypoints.Rows[i][7]);
2119
                    //CamAngle
2120
                    bData[23] = (byte)Convert.ToInt16(dtWaypoints.Rows[i][12]);
2121
                    //Name
2122
                    byte[] name = ASCIIEncoding.ASCII.GetBytes((string)dtWaypoints.Rows[i][2]);
2123
                    bData[24] = name.Length > 0 ? name[0] : (byte)0;
2124
                    bData[25] = name.Length > 1 ? name[1] : (byte)0;
2125
                    bData[26] = name.Length > 2 ? name[2] : (byte)0;
2126
                    bData[27] = name.Length > 3 ? name[3] : (byte)0;
2127
                    //Autotrigger
2128
                    bData[28] = Convert.ToByte(dtWaypoints.Rows[i][11]);
2129
 
2130
                    bytes = FlightControllerMessage.CreateMessage('w', 2, bData);
2131
                    serialStream.Write(bytes, 0, bytes.Length);
2132
 
2133
                    _iWPCount = -1;
2134
                    while (_iWPCount == -1)
2135
                        Thread.Sleep(10);
2136
                    Dispatcher.Invoke(() => lblWPCount.Content = _iWPCount.ToString());
2137
                }
2138
            }
2139
            else
2140
                Log(LogMsgType.Error, "NOT CONNECTED!");
2141
 
2142
        }
2143
 
2287 - 2144
        #region OSD-Menue
2145
 
2146
        /// <summary>
2147
        /// one time query of the OSD Menue with pagenumber
2148
        /// </summary>
2149
        /// <param name="iMenue">Menue page</param>
2150
        void _OSDMenue(int iMenue)
2151
        {
2152
            if (serialPortCtrl.Port.IsOpen)
2153
            {
2154
                if (iMenue > iOSDMax)
2155
                    iMenue = 0;
2156
                Stream serialStream = serialPortCtrl.Port.BaseStream;
2157
                byte[] bytes = FlightControllerMessage.CreateMessage('l', 0, new byte[1] { (byte)iMenue });
2158
                serialStream.Write(bytes, 0, bytes.Length);
2159
            }
2160
            else
2161
                Log(LogMsgType.Error, "NOT CONNECTED!");
2162
 
2163
        }
2164
        /// <summary>
2165
        /// call the OSDMenue and start autorefresh
2166
        ///  usually by sending a menuekey
2167
        /// 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)
2168
        /// therefore the value has to be negative (inverted) in order to distinguish from old (2 line) menuestyle
2169
        /// and must not have any bits of the menue keys 0x1 0x2 0x4 0x8 (0x10?) --> 0x20 = -33
2170
        /// </summary>
2171
        void _OSDMenueAutoRefresh()
2172
        {
2173
            _sendControllerMessage('h', 0, new byte[2] { unchecked((byte)(-33)), OSDInterval });
2174
        }
2175
        void _OSDMenueAutoRefresh(byte key)
2176
        {
2177
            _sendControllerMessage('h', 0, new byte[2] { unchecked((byte)~key), OSDInterval });
2178
        }
2179
        /// <summary>
2180
        /// initialize the OSD menue combobox
2181
        /// combox is filled by numbers from 0 to max pagenumber
2182
        /// </summary>
2183
        void _initOSDCB()
2184
        {
2185
            _bCBInit = true;
2186
            if (iOSDMax == 0)
2187
            {
2188
                _OSDMenue(0);
2189
                Thread.Sleep(10);
2190
            }
2191
            Dispatcher.Invoke((Action)(() => cbOSD.Items.Clear()));
2192
            for (int i = 0; i <= iOSDMax; i++)
2193
            {
2194
                Dispatcher.Invoke((Action)(() => cbOSD.Items.Add(i)));
2195
            }
2196
            Dispatcher.Invoke((Action)(() => cbOSD.SelectedItem = iOSDPage));
2197
            _bCBInit = false;
2198
        }
2199
        private void btnOSDForward_Click(object sender, RoutedEventArgs e)
2200
        {
2201
            iOSDPage++;
2202
            if (iOSDPage > iOSDMax)
2203
                iOSDPage = 0;
2204
 
2205
            _OSDMenue(iOSDPage);
2206
        }
2207
        private void btnOSDBackward_Click(object sender, RoutedEventArgs e)
2208
        {
2209
            iOSDPage--;
2210
            if (iOSDPage < 0)
2211
                iOSDPage = iOSDMax;
2212
 
2213
            _OSDMenue(iOSDPage);
2214
        }
2215
        private void btnOSDLeave_Click(object sender, RoutedEventArgs e)
2216
        {
2217
            _OSDMenueAutoRefresh(8);
2218
        }
2219
        private void btnOSDEnter_Click(object sender, RoutedEventArgs e)
2220
        {
2221
            _OSDMenueAutoRefresh(4);
2222
        }
2223
        private void cbOSD_DropDownClosing(object sender, EventArgs e)
2224
        {
2225
            if (!_bCBInit && cbOSD.SelectedIndex > -1)
2226
                _OSDMenue(cbOSD.SelectedIndex);
2227
        }
2228
        private void OSD(LogMsgType msgtype, string msg, bool bNew)
2229
        {
2230
            Dispatcher.Invoke(() =>
2231
            {
2232
                TextRange tr;
2233
                if (bNew)
2234
                {
2235
                    rtfOSD.SelectAll();
2236
                    rtfOSD.Selection.Text = string.Empty;
2237
                }
2238
                tr = new TextRange(rtfOSD.Document.ContentEnd, rtfOSD.Document.ContentEnd);
2239
                tr.Text = msg;
2240
                tr.ApplyPropertyValue(TextElement.ForegroundProperty, new SolidColorBrush(LogMsgTypeColor[(int)msgtype]));
2241
                //     rtfOSD.AppendText("\r");
2242
                rtfOSD.ScrollToEnd();
2243
 
2244
            });
2245
        }
2246
 
2247
        #endregion OSD-Menue
2248
 
2249
        #endregion controller messages
2250
 
2295 - 2251
        void _mediaPlayer(string file)
2252
        {
2253
            if (File.Exists(file))
2254
            {
2255
                MediaPlayer.MediaPlayer mp = new MediaPlayer.MediaPlayer();
2256
                mp.Open(file);
2257
                mp.Play();
2258
            }
2259
        }
2310 - 2260
 
2261
        /// <summary>
2262
        /// Switch between fullscreen and normal window mode
2263
        /// save & restore scaling settings
2264
        /// </summary>
2265
        /// <param name="sender"></param>
2266
        /// <param name="e"></param>
2287 - 2267
        private void imageFullscreen_MouseDown(object sender, MouseButtonEventArgs e)
2268
        {
2269
            if (winState.isMaximized)
2270
            {
2271
                winState.Restore(this);
2272
                imageFullscreen.Source = new BitmapImage(new Uri("Images/Fullscreen.png", UriKind.Relative));
2273
                if(_bSaveWinStateFull)
2274
                    _saveScaleSliders(true);
2275
                if(_bSaveWinStateNormal)
2276
                    _setScaleSliders(false);
2277
            }
2278
            else
2279
            {
2280
                winState.Maximize(this);
2281
                imageFullscreen.Source = new BitmapImage(new Uri("Images/RestoreScreen.png", UriKind.Relative));
2282
                if(_bSaveWinStateNormal)
2283
                    _saveScaleSliders(false);
2284
                if(_bSaveWinStateFull)
2285
                    _setScaleSliders(true);
2286
            }
2287
        }
2288
 
2289
        /// <summary>
2290
        /// reset the scaling of all UI elements to default
2291
        /// </summary>
2292
        /// <param name="sender"></param>
2293
        /// <param name="e"></param>
2294
        private void buttonUIScaleReset_Click(object sender, RoutedEventArgs e)
2295
        {
2296
            UIScaleHorizonSlider.Value =
2297
                UIScaleLOGSlider.Value =
2298
                UIScaleMotorsSlider.Value =
2299
                UIScaleOSDSlider.Value =
2300
                UIScaleSlider.Value =
2301
                UIScaleTopSlider.Value = 1;
2302
        }
2303
        /// <summary>
2304
        /// adjust the top postion of UI elements below the top bar to fit the bottom position of the bar when scaling the top bar
2305
        /// </summary>
2306
        /// <param name="sender"></param>
2307
        /// <param name="e"></param>
2308
        private void UIScaleTopSlider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
2309
        {
2310
            GridSettings.Margin = new Thickness(GridSettings.Margin.Left, 36 * UIScaleTopSlider.Value, GridSettings.Margin.Right, GridSettings.Margin.Bottom);
2311
            if (GridMotors != null)
2312
                GridMotors.Margin = new Thickness(GridMotors.Margin.Left, 36 * UIScaleTopSlider.Value, GridMotors.Margin.Right, GridMotors.Margin.Bottom);
2313
            if (GridSideBar != null)
2314
                GridSideBar.Margin = new Thickness(GridSideBar.Margin.Left, 36 * UIScaleTopSlider.Value, GridSideBar.Margin.Right, GridSideBar.Margin.Bottom);
2315
            if (GridOSD != null)
2316
                GridOSD.Margin = new Thickness(GridOSD.Margin.Left, 36 * UIScaleTopSlider.Value, GridOSD.Margin.Right, GridOSD.Margin.Bottom);
2317
            if (GridData != null)
2318
                GridData.Margin = new Thickness(GridData.Margin.Left, 36 * UIScaleTopSlider.Value, GridData.Margin.Right, GridData.Margin.Bottom);
2319
            if (GridWP != null)
2320
                GridWP.Margin = new Thickness(GridWP.Margin.Left, 36 * UIScaleTopSlider.Value, GridWP.Margin.Right, GridWP.Margin.Bottom);
2321
        }
2310 - 2322
        /// <summary>
2323
        /// restore the saved scalings for the fullscreen/normal window mode
2324
        /// </summary>
2325
        /// <param name="bFull">the mode the window is set to</param>
2287 - 2326
        void _setScaleSliders(bool bFull)
2327
        {
2328
            if(bFull)
2329
            {
2330
                UIScaleSlider.Value = scaleFullAll;
2331
                UIScaleTopSlider.Value = scaleFullTopBar;
2332
                UIScaleMotorsSlider.Value = scaleFullMotors;
2333
                UIScaleOSDSlider.Value = scaleFullOSD;
2334
                UIScaleLOGSlider.Value = scaleFullLOG;
2335
                UIScaleHorizonSlider.Value = scaleFullHorizon;
2336
            }
2337
            else
2338
            {
2339
                UIScaleSlider.Value = scaleNormalAll;
2340
                UIScaleTopSlider.Value = scaleNormalTopBar;
2341
                UIScaleMotorsSlider.Value = scaleNormalMotors;
2342
                UIScaleOSDSlider.Value = scaleNormalOSD;
2343
                UIScaleLOGSlider.Value = scaleNormalLOG;
2344
                UIScaleHorizonSlider.Value = scaleNormalHorizon;
2345
            }
2346
        }
2347
 
2310 - 2348
        /// <summary>
2349
        /// save the scalings for the actual window mode
2350
        /// </summary>
2351
        /// <param name="bFull">the actual window mode</param>
2287 - 2352
        void _saveScaleSliders(bool bFull)
2353
        {
2354
 
2355
            if (bFull)
2356
            {
2357
                scaleFullAll = UIScaleSlider.Value;
2358
                scaleFullTopBar = UIScaleTopSlider.Value;
2359
                scaleFullMotors = UIScaleMotorsSlider.Value;
2360
                scaleFullOSD = UIScaleOSDSlider.Value;
2361
                scaleFullLOG = UIScaleLOGSlider.Value;
2362
                scaleFullHorizon = UIScaleHorizonSlider.Value;
2363
            }
2364
            else
2365
            {
2366
                scaleNormalAll = UIScaleSlider.Value;
2367
                scaleNormalTopBar = UIScaleTopSlider.Value;
2368
                scaleNormalMotors = UIScaleMotorsSlider.Value;
2369
                scaleNormalOSD = UIScaleOSDSlider.Value;
2370
                scaleNormalLOG = UIScaleLOGSlider.Value;
2371
                scaleNormalHorizon = UIScaleHorizonSlider.Value;
2372
            }
2373
        }
2374
 
2375
        /// <summary>
2376
        /// read settings from ini-file
2377
        /// </summary>
2378
        void _readIni()
2379
        {
2380
            if (!File.Exists(filePath + "\\MKLiveViewSettings.ini"))
2381
                _writeIni();
2382
            IniFile ini = new IniFile("MKLiveViewSettings.ini");
2383
            ini.path = filePath + "\\MKLiveViewSettings.ini";
2312 - 2384
            try
2385
            {
2287 - 2386
 
2312 - 2387
                string sVal = ini.IniReadValue("timings", "AutorefreshDebugData");
2388
                if (sVal != "") _debugDataAutorefresh = Convert.ToBoolean(sVal);
2389
                sVal = ini.IniReadValue("timings", "AutorefreshNavCtrlData");
2390
                if (sVal != "") _navCtrlDataAutorefresh = Convert.ToBoolean(sVal);
2391
                sVal = ini.IniReadValue("timings", "AutorefreshBLCtrlData");
2392
                if (sVal != "") _blctrlDataAutorefresh = Convert.ToBoolean(sVal);
2393
                sVal = ini.IniReadValue("timings", "AutorefreshOSDData");
2394
                if (sVal != "") _OSDAutorefresh = Convert.ToBoolean(sVal);
2287 - 2395
 
2312 - 2396
                sVal = ini.IniReadValue("timings", "IntervalDebugData");
2397
                if (sVal != "") debugInterval = (byte)Convert.ToInt16(sVal);
2398
                sVal = ini.IniReadValue("timings", "IntervalNavCtrlData");
2399
                if (sVal != "") navctrlInterval = (byte)Convert.ToInt16(sVal);
2400
                sVal = ini.IniReadValue("timings", "IntervalBLCtrlData");
2401
                if (sVal != "") blctrlInterval = (byte)Convert.ToInt16(sVal);
2402
                sVal = ini.IniReadValue("timings", "IntervalOSDData");
2403
                if (sVal != "") OSDInterval = (byte)Convert.ToInt16(sVal);
2287 - 2404
 
2312 - 2405
                sVal = ini.IniReadValue("topBar", "voltage");
2406
                if (sVal != "") chkBoxTopBarShowVoltage.IsChecked = Convert.ToBoolean(sVal);
2407
                sVal = ini.IniReadValue("topBar", "capacity");
2408
                if (sVal != "") chkBoxTopBarShowCapacity.IsChecked = Convert.ToBoolean(sVal);
2409
                sVal = ini.IniReadValue("topBar", "current");
2410
                if (sVal != "") chkBoxTopBarShowCurrent.IsChecked = Convert.ToBoolean(sVal);
2411
                sVal = ini.IniReadValue("topBar", "flightTime");
2412
                if (sVal != "") chkBoxTopBarShowFlightTime.IsChecked = Convert.ToBoolean(sVal);
2413
                sVal = ini.IniReadValue("topBar", "distanceHP");
2414
                if (sVal != "") chkBoxTopBarShowDistanceHP.IsChecked = Convert.ToBoolean(sVal);
2415
                sVal = ini.IniReadValue("topBar", "height");
2416
                if (sVal != "") chkBoxTopBarShowHeight.IsChecked = Convert.ToBoolean(sVal);
2417
                sVal = ini.IniReadValue("topBar", "speed");
2418
                if (sVal != "") chkBoxTopBarShowSpeed.IsChecked = Convert.ToBoolean(sVal);
2419
                sVal = ini.IniReadValue("topBar", "magneticField");
2420
                if (sVal != "") chkBoxTopBarShowMF.IsChecked = Convert.ToBoolean(sVal);
2421
                sVal = ini.IniReadValue("topBar", "satellites");
2422
                if (sVal != "") chkBoxTopBarShowSatellites.IsChecked = Convert.ToBoolean(sVal);
2423
                sVal = ini.IniReadValue("topBar", "rc");
2424
                if (sVal != "") chkBoxTopBarShowRC.IsChecked = Convert.ToBoolean(sVal);
2287 - 2425
 
2312 - 2426
                sVal = ini.IniReadValue("style", "saveFullScreen");
2427
                if (sVal != "") chkBoxSaveFullScreenState.IsChecked = Convert.ToBoolean(sVal);
2428
                sVal = ini.IniReadValue("style", "saveNormalState");
2429
                if (sVal != "") chkBoxSaveNormalState.IsChecked = Convert.ToBoolean(sVal);
2287 - 2430
 
2312 - 2431
                sVal = ini.IniReadValue("style", "scaleNormalAll");
2432
                if (sVal != "") scaleNormalAll = Convert.ToDouble(sVal);
2433
                sVal = ini.IniReadValue("style", "scaleNormalTopBar");
2434
                if (sVal != "") scaleNormalTopBar = Convert.ToDouble(sVal);
2435
                sVal = ini.IniReadValue("style", "scaleNormalMotors");
2436
                if (sVal != "") scaleNormalMotors = Convert.ToDouble(sVal);
2437
                sVal = ini.IniReadValue("style", "scaleNormalOSD");
2438
                if (sVal != "") scaleNormalOSD = Convert.ToDouble(sVal);
2439
                sVal = ini.IniReadValue("style", "scaleNormalLOG");
2440
                if (sVal != "") scaleNormalLOG = Convert.ToDouble(sVal);
2441
                sVal = ini.IniReadValue("style", "scaleNormalHorizon");
2442
                if (sVal != "") scaleNormalHorizon = Convert.ToDouble(sVal);
2287 - 2443
 
2312 - 2444
                sVal = ini.IniReadValue("style", "scaleFullAll");
2445
                if (sVal != "") scaleFullAll = Convert.ToDouble(sVal);
2446
                sVal = ini.IniReadValue("style", "scaleFullTopBar");
2447
                if (sVal != "") scaleFullTopBar = Convert.ToDouble(sVal);
2448
                sVal = ini.IniReadValue("style", "scaleFullMotors");
2449
                if (sVal != "") scaleFullMotors = Convert.ToDouble(sVal);
2450
                sVal = ini.IniReadValue("style", "scaleFullOSD");
2451
                if (sVal != "") scaleFullOSD = Convert.ToDouble(sVal);
2452
                sVal = ini.IniReadValue("style", "scaleFullLOG");
2453
                if (sVal != "") scaleFullLOG = Convert.ToDouble(sVal);
2454
                sVal = ini.IniReadValue("style", "scaleFullHorizon");
2455
                if (sVal != "") scaleFullHorizon = Convert.ToDouble(sVal);
2287 - 2456
 
2312 - 2457
                sVal = ini.IniReadValue("general", "LiPoCells");
2458
                _LipoCells = Convert.ToInt16(sVal);
2459
                sVal = ini.IniReadValue("general", "Motors");
2460
                if (sVal != "") _iMotors = Convert.ToInt16(sVal);
2287 - 2461
 
2312 - 2462
                sVal = ini.IniReadValue("map", "followMe");
2463
                if (sVal != "") _bFollowCopter = Convert.ToBoolean(sVal);
2464
                sVal = ini.IniReadValue("map", "AutoSetHome");
2465
                if (sVal != "") _bAutoHome = Convert.ToBoolean(sVal);
2287 - 2466
 
2312 - 2467
                sVal = ini.IniReadValue("threshold", "VoltageWarning");
2468
                if(sVal != "") _dThresholdVoltageWarn = Convert.ToDouble(sVal);
2469
                sVal = ini.IniReadValue("threshold", "VoltageCritical");
2470
                if(sVal != "") _dThresholdVoltageCrit = Convert.ToDouble(sVal);
2471
                sVal = ini.IniReadValue("threshold", "VoiceVoltageEnable");
2472
                if(sVal != "") _bVoiceVoltPlay = Convert.ToBoolean(sVal);
2473
                sVal = ini.IniReadValue("threshold", "VoiceSatFixEnable");
2474
                if(sVal != "") _bVoiceSatFixPlay = Convert.ToBoolean(sVal);
2475
                sVal = ini.IniReadValue("threshold", "VoiceMagFieldEnable");
2476
                if(sVal != "") _bVoiceMagneticFieldPlay = Convert.ToBoolean(sVal);
2477
                sVal = ini.IniReadValue("threshold", "DistanceWarning");
2478
                if(sVal != "") _dThresholdDistanceWarn = Convert.ToDouble(sVal);
2479
                sVal = ini.IniReadValue("threshold", "VoiceDistanceWarnEnable");
2480
                if(sVal != "") _bVoiceDistancePlay = Convert.ToBoolean(sVal);
2481
                sVal = ini.IniReadValue("threshold", "VoiceRCLevelWarnEnable");
2482
                if(sVal != "") _bVoiceRCLevelPlay = Convert.ToBoolean(sVal);
2483
                sVal = ini.IniReadValue("threshold", "MaxDistance");
2484
                if(sVal != "") _dThresholdDistanceMax = Convert.ToDouble(sVal);
2485
                sVal = ini.IniReadValue("threshold", "RCThreshold");
2486
                if(sVal != "") _iThresholdRC = Convert.ToInt32(sVal);
2487
                sVal = ini.IniReadValue("threshold", "MagFieldThreshold");
2488
                if(sVal != "") _iThresholdMagField = Convert.ToInt32(sVal);
2489
            }
2490
            catch (Exception e)
2491
            {
2287 - 2492
 
2312 - 2493
                MessageBox.Show("Error parsing ini-file!" + Environment.NewLine + e.Message,"Read ini-file" ,MessageBoxButton.OK,MessageBoxImage.Error);
2494
            }
2495
 
2287 - 2496
        }
2497
 
2498
        /// <summary>
2499
        /// save settings to ini-file
2500
        /// </summary>
2501
        void _writeIni()
2502
        {
2503
 
2504
            IniFile ini = new IniFile("MKLiveViewSettings.ini");
2505
            ini.path = filePath + "\\MKLiveViewSettings.ini";
2506
 
2312 - 2507
            try
2508
            {
2287 - 2509
 
2312 - 2510
                ini.IniWriteValue("timings", "AutorefreshDebugData", _debugDataAutorefresh ? "true" : "false");
2511
                ini.IniWriteValue("timings", "AutorefreshNavCtrlData", _navCtrlDataAutorefresh ? "true" : "false");
2512
                ini.IniWriteValue("timings", "AutorefreshBLCtrlData", _blctrlDataAutorefresh ? "true" : "false");
2513
                ini.IniWriteValue("timings", "AutorefreshOSDData", _OSDAutorefresh ? "true" : "false");
2287 - 2514
 
2312 - 2515
                ini.IniWriteValue("timings", "IntervalDebugData", debugInterval.ToString());
2516
                ini.IniWriteValue("timings", "IntervalNavCtrlData", navctrlInterval.ToString());
2517
                ini.IniWriteValue("timings", "IntervalBLCtrlData", blctrlInterval.ToString());
2518
                ini.IniWriteValue("timings", "IntervalOSDData", OSDInterval.ToString());
2287 - 2519
 
2312 - 2520
                ini.IniWriteValue("general", "LiPoCells", _LipoCells.ToString());
2521
                ini.IniWriteValue("general", "Motors", _iMotors.ToString());
2287 - 2522
 
2312 - 2523
                ini.IniWriteValue("map", "followMe", _bFollowCopter.ToString());
2524
                ini.IniWriteValue("map", "AutoSetHome", _bAutoHome.ToString());
2287 - 2525
 
2312 - 2526
                ini.IniWriteValue("topBar", "voltage", chkBoxTopBarShowVoltage.IsChecked.ToString());
2527
                ini.IniWriteValue("topBar", "capacity", chkBoxTopBarShowCapacity.IsChecked.ToString());
2528
                ini.IniWriteValue("topBar", "current", chkBoxTopBarShowCurrent.IsChecked.ToString());
2529
                ini.IniWriteValue("topBar", "flightTime", chkBoxTopBarShowFlightTime.IsChecked.ToString());
2530
                ini.IniWriteValue("topBar", "distanceHP", chkBoxTopBarShowDistanceHP.IsChecked.ToString());
2531
                ini.IniWriteValue("topBar", "height", chkBoxTopBarShowHeight.IsChecked.ToString());
2532
                ini.IniWriteValue("topBar", "speed", chkBoxTopBarShowSpeed.IsChecked.ToString());
2533
                ini.IniWriteValue("topBar", "magneticField", chkBoxTopBarShowMF.IsChecked.ToString());
2534
                ini.IniWriteValue("topBar", "satellites", chkBoxTopBarShowSatellites.IsChecked.ToString());
2535
                ini.IniWriteValue("topBar", "rc", chkBoxTopBarShowRC.IsChecked.ToString());
2287 - 2536
 
2312 - 2537
                ini.IniWriteValue("style", "saveFullScreen", chkBoxSaveFullScreenState.IsChecked.ToString());
2538
                ini.IniWriteValue("style", "saveNormalState", chkBoxSaveNormalState.IsChecked.ToString());
2287 - 2539
 
2312 - 2540
                ini.IniWriteValue("style", "scaleNormalAll", scaleNormalAll.ToString());
2541
                ini.IniWriteValue("style", "scaleNormalTopBar", scaleNormalTopBar.ToString());
2542
                ini.IniWriteValue("style", "scaleNormalMotors", scaleNormalMotors.ToString());
2543
                ini.IniWriteValue("style", "scaleNormalOSD", scaleNormalOSD.ToString());
2544
                ini.IniWriteValue("style", "scaleNormalLOG", scaleNormalLOG.ToString());
2545
                ini.IniWriteValue("style", "scaleNormalHorizon", scaleNormalHorizon.ToString());
2287 - 2546
 
2312 - 2547
                ini.IniWriteValue("style", "scaleFullAll", scaleFullAll.ToString());
2548
                ini.IniWriteValue("style", "scaleFullTopBar", scaleFullTopBar.ToString());
2549
                ini.IniWriteValue("style", "scaleFullMotors", scaleFullMotors.ToString());
2550
                ini.IniWriteValue("style", "scaleFullOSD", scaleFullOSD.ToString());
2551
                ini.IniWriteValue("style", "scaleFullLOG", scaleFullLOG.ToString());
2552
                ini.IniWriteValue("style", "scaleFullHorizon", scaleFullHorizon.ToString());
2287 - 2553
 
2312 - 2554
                ini.IniWriteValue("style", "horizon", chkBoxShowHorizon.IsChecked.ToString());
2555
 
2556
                ini.IniWriteValue("threshold", "VoltageWarning", _dThresholdVoltageWarn.ToString());
2557
                ini.IniWriteValue("threshold", "VoltageCritical", _dThresholdVoltageCrit.ToString());
2558
                ini.IniWriteValue("threshold", "VoiceVoltageEnable", _bVoiceVoltPlay.ToString());
2559
                ini.IniWriteValue("threshold", "VoiceSatFixEnable", _bVoiceSatFixPlay.ToString());
2560
                ini.IniWriteValue("threshold", "VoiceMagFieldEnable", _bVoiceMagneticFieldPlay.ToString());
2561
                ini.IniWriteValue("threshold", "VoiceDistanceWarnEnable", _bVoiceDistancePlay.ToString());
2562
                ini.IniWriteValue("threshold", "VoiceRCLevelWarnEnable", _bVoiceRCLevelPlay.ToString());
2563
                ini.IniWriteValue("threshold", "DistanceWarning", _dThresholdDistanceWarn.ToString());
2564
                ini.IniWriteValue("threshold", "MaxDistance", _dThresholdDistanceMax.ToString());
2565
                ini.IniWriteValue("threshold", "RCThreshold", _iThresholdRC.ToString());
2566
                ini.IniWriteValue("threshold", "MagFieldThreshold", _iThresholdMagField.ToString());
2567
            }
2568
            catch (Exception e)
2569
            {
2570
 
2571
                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);
2572
            }
2287 - 2573
        }
2312 - 2574
 
2315 - 2575
        #region WP
2312 - 2576
        void _readWPLFile()
2577
        {
2578
            Microsoft.Win32.OpenFileDialog fd = new Microsoft.Win32.OpenFileDialog();
2579
            fd.Filter = "Waypointlists | *.wpl";
2580
            fd.Multiselect = false;
2581
            if (fd.ShowDialog().Value)
2582
            {
2583
                string file = fd.SafeFileName;
2584
                IniFile ini = new IniFile(fd.SafeFileName);
2585
                ini.path = fd.FileName;
2586
 
2587
                try
2588
                {
2589
                    string sVal = ini.IniReadValue("General", "FileVersion");
2590
                    if (sVal == "")
2591
                        MessageBox.Show("The file has no version declared - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
2592
                    else
2593
                    {
2594
                        if (Convert.ToInt16(sVal) < 3)
2595
                            MessageBox.Show("The file version is not supported - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
2596
                        else
2597
                        {
2598
                            sVal = ini.IniReadValue("General", "NumberOfWaypoints");
2599
                            if (sVal == "")
2600
                                MessageBox.Show("The file has no number of waypoints declared - can't go on...", "", MessageBoxButton.OK, MessageBoxImage.Information);
2601
                            else
2602
                            {
2603
                                int wpnum = Convert.ToInt16(sVal);
2604
                                string wp;
2605
                                int i;
2313 - 2606
                                NumberFormatInfo nfi = new NumberFormatInfo();
2607
                                nfi.NumberDecimalSeparator = ".";
2312 - 2608
                                dtWaypoints.Rows.Clear();
2315 - 2609
                                for(int k = 0; k < MainMap.Markers.Count;)
2610
                                {
2611
                                    GMapMarker p = MainMap.Markers[k];
2612
                                    if (p.Shape.GetType() == typeof(CustomMarkerWP))
2613
                                        MainMap.Markers.Remove(p);
2614
                                    else
2615
                                        k++;
2616
                                }
2312 - 2617
                                for (int k = 1; k <= wpnum; k++)
2618
                                {
2619
                                    DataRow dr = dtWaypoints.NewRow();
2620
                                    dr.ItemArray = new object[16];
2621
                                    object[] o = new object[16];
2622
                                    i = 0;
2623
                                    wp = "Point" + k.ToString();
2624
                                    o[i] = k;
2625
                                    i++;
2626
                                    sVal = ini.IniReadValue(wp, "Type");
2627
                                    if (sVal != "")
2315 - 2628
                                        o[i] = Convert.ToInt16(sVal) - 1;
2312 - 2629
                                    i++;
2630
                                    sVal = ini.IniReadValue(wp, "Prefix");
2631
                                    if (sVal != "")
2632
                                        o[i] = sVal == "0" ? "P" + k.ToString() : sVal + k.ToString();
2633
                                    i++;
2313 - 2634
                                    sVal = ini.IniReadValue(wp, "Latitude");
2312 - 2635
                                    if (sVal != "")
2313 - 2636
                                        o[i] = Convert.ToDouble(sVal, nfi);
2312 - 2637
                                    i++;
2313 - 2638
                                    sVal = ini.IniReadValue(wp, "Longitude");
2312 - 2639
                                    if (sVal != "")
2313 - 2640
                                        o[i] = Convert.ToDouble(sVal, nfi);
2312 - 2641
                                    i++;
2642
                                    sVal = ini.IniReadValue(wp, "Altitude");
2643
                                    if (sVal != "")
2313 - 2644
                                        o[i] = Convert.ToDouble(sVal, nfi);
2312 - 2645
                                    i++;
2646
                                    sVal = ini.IniReadValue(wp, "Heading");
2647
                                    if (sVal != "")
2648
                                        o[i] = Convert.ToInt16(sVal);
2649
                                    i++;
2650
                                    sVal = ini.IniReadValue(wp, "Speed");
2651
                                    if (sVal != "")
2315 - 2652
                                        o[i] = Convert.ToInt16(sVal);
2312 - 2653
                                    i++;
2654
                                    sVal = ini.IniReadValue(wp, "ClimbRate");
2655
                                    if (sVal != "")
2656
                                        o[i] = Convert.ToInt16(sVal);
2657
                                    i++;
2658
                                    sVal = ini.IniReadValue(wp, "Radius");
2659
                                    if (sVal != "")
2660
                                        o[i] = Convert.ToInt16(sVal);
2661
                                    i++;
2662
                                    sVal = ini.IniReadValue(wp, "DelayTime");
2663
                                    if (sVal != "")
2664
                                        o[i] = Convert.ToInt16(sVal);
2665
                                    i++;
2666
                                    sVal = ini.IniReadValue(wp, "AutoTrigger");
2667
                                    if (sVal != "")
2668
                                        o[i] = Convert.ToInt16(sVal); ;
2669
                                    i++;
2670
                                    sVal = ini.IniReadValue(wp, "CAM-Nick");
2671
                                    if (sVal != "")
2313 - 2672
                                        o[i] = Convert.ToInt16(sVal);
2312 - 2673
                                    i++;
2674
                                    o[i] = 0;
2675
                                    i++;
2676
                                    sVal = ini.IniReadValue(wp, "WP_Event_Channel_Value");
2677
                                    if (sVal != "")
2678
                                        o[i] = Convert.ToInt16(sVal);
2679
                                    i++;
2680
                                    o[i] = "New";
2681
 
2682
                                    dr.ItemArray = o;
2683
                                    dtWaypoints.Rows.Add(dr);
2315 - 2684
                                    GMapMarker wpMarker = new GMapMarker(new PointLatLng((double)o[3], (double)o[4]));
2685
                                    wpMarker.Shape = new CustomMarkerWP(this, wpMarker, (string)dr[2], (int)o[1]);
2686
                                    _setMarkerColor(wpMarker, (int)o[1]);
2687
                                    MainMap.Markers.Add(wpMarker);
2688
 
2312 - 2689
                                    Dispatcher.Invoke(() => lblWPIndex.Content = k.ToString());
2690
                                    Dispatcher.Invoke(() => lblWPCount.Content = k.ToString());
2691
                                    Dispatcher.Invoke(() => dgvWP.Items.Refresh());
2692
                                    Thread.Sleep(10);
2693
                                }
2694
                            }
2695
                        }
2696
                    }
2697
 
2698
                }
2699
                catch (Exception e)
2700
                {
2701
 
2702
                    MessageBox.Show("Error parsing wpl-file!" + Environment.NewLine + e.Message, "Read wpl-file", MessageBoxButton.OK, MessageBoxImage.Error);
2703
                }
2704
 
2705
            }
2706
        }
2315 - 2707
        void _setMarkerColor(GMapMarker wpMarker,int iType)
2708
        {
2709
            Dispatcher.Invoke(() =>
2710
            {
2711
                switch (iType)
2712
                {
2713
                    case 0:
2714
                        if (comboBoxWPColor.SelectionBoxItem != null)
2715
                        {
2716
                            string s = comboBoxWPColor.SelectionBoxItem.ToString();
2717
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
2718
                        }
2719
                        else
2720
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
2721
                        break;
2722
                    case 1:
2723
                        if (comboBoxPOIColor.SelectionBoxItem != null)
2724
                        {
2725
                            string s = comboBoxPOIColor.SelectionBoxItem.ToString();
2726
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
2727
                        }
2728
                        else
2729
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
2730
                        break;
2731
                    case 2:
2732
                        if (comboBoxFSColor.SelectionBoxItem != null)
2733
                        {
2734
                            string s = comboBoxFSColor.SelectionBoxItem.ToString();
2735
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor(s);
2736
                        }
2737
                        else
2738
                            ((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
2739
                        break;
2740
                    default:
2741
                        ((CustomMarkerWP)(wpMarker.Shape)).setColor("red");
2742
                        break;
2743
                }
2744
            });
2312 - 2745
 
2315 - 2746
        }
2747
        private void comboBoxWPColor_DropDownClosed(object sender, EventArgs e)
2312 - 2748
        {
2315 - 2749
            Dispatcher.Invoke(() =>
2750
            {
2751
                if (comboBoxWPColor.SelectionBoxItem != null)
2752
                {
2753
                    for (int k = 0; k < MainMap.Markers.Count;k++)
2754
                    {
2755
                        GMapMarker p = MainMap.Markers[k];
2756
                        if (p.Shape.GetType() == typeof(CustomMarkerWP))
2757
                        {
2758
                            if (((CustomMarkerWP)p.Shape).WPType == 0)
2759
                            {
2760
                                string s = comboBoxWPColor.SelectionBoxItem.ToString();
2761
                                ((CustomMarkerWP)(p.Shape)).setColor(s);
2762
                            }
2763
                        }
2764
                    }
2765
                }
2766
            });
2312 - 2767
        }
2315 - 2768
        private void comboBoxPOIColor_DropDownClosed(object sender, EventArgs e)
2769
        {
2770
            Dispatcher.Invoke(() =>
2771
            {
2772
                if (comboBoxPOIColor.SelectionBoxItem != null)
2773
                {
2774
                    for (int k = 0; k < MainMap.Markers.Count; k++)
2775
                    {
2776
                        GMapMarker p = MainMap.Markers[k];
2777
                        if (p.Shape.GetType() == typeof(CustomMarkerWP))
2778
                        {
2779
                            if (((CustomMarkerWP)p.Shape).WPType == 1)
2780
                            {
2781
                                string s = comboBoxPOIColor.SelectionBoxItem.ToString();
2782
                                ((CustomMarkerWP)(p.Shape)).setColor(s);
2783
                            }
2784
                        }
2785
                    }
2786
                }
2787
            });
2287 - 2788
 
2315 - 2789
        }
2790
        private void comboBoxFSColor_DropDownClosed(object sender, EventArgs e)
2287 - 2791
        {
2315 - 2792
            Dispatcher.Invoke(() =>
2793
            {
2794
                if (comboBoxFSColor.SelectionBoxItem != null)
2795
                {
2796
                    for (int k = 0; k < MainMap.Markers.Count; k++)
2797
                    {
2798
                        GMapMarker p = MainMap.Markers[k];
2799
                        if (p.Shape.GetType() == typeof(CustomMarkerWP))
2800
                        {
2801
                            if (((CustomMarkerWP)p.Shape).WPType == 2)
2802
                            {
2803
                                string s = comboBoxFSColor.SelectionBoxItem.ToString();
2804
                                ((CustomMarkerWP)(p.Shape)).setColor(s);
2805
                            }
2806
                        }
2807
                    }
2808
                }
2809
            });
2287 - 2810
        }
2318 - 2811
 
2812
        private void comboBoxCopterColor_DropDownClosed(object sender, EventArgs e)
2813
        {
2814
            Dispatcher.Invoke(() => {
2815
                if (comboBoxCopterColor.SelectionBoxItem != null)
2816
                {
2817
                    string s = comboBoxCopterColor.SelectionBoxItem.ToString();
2818
                    ((CustomMarkerCopter)(copter.Shape)).setColor(s);
2819
                }
2820
                else
2821
                    ((CustomMarkerCopter)(copter.Shape)).setColor("red");
2822
            });
2823
        }
2824
 
2315 - 2825
        private void btnLoadWPLFile_Click(object sender, RoutedEventArgs e)
2287 - 2826
        {
2315 - 2827
            _readWPLFile();
2287 - 2828
        }
2315 - 2829
        #endregion WP
2830
 
2831
        #endregion functions
2287 - 2832
    }
2315 - 2833
     /// <summary>
2834
    /// formats the wp datatable values for display in datagrid - this is bound in the datagrid as a converter
2835
    /// </summary>
2313 - 2836
    public class waypointsConverter : IValueConverter
2837
    {
2838
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
2839
        {
2840
            if (value != null)
2841
            {
2842
                switch ((string)parameter)
2843
                {
2844
                    case "Latitude":
2845
                        return value.ToString() + " °";
2846
                    case "Longitude":
2847
                        return value.ToString() + " °";
2848
                    case "Radius":
2849
                        return value.ToString() + " m";
2850
                    case "Altitude":
2851
                        return value.ToString() + " m";
2852
                    case "ClimbRate":
2853
                        return value.ToString() == "255" ? "Auto" : (System.Convert.ToDouble(value) / 10).ToString("0.0 m/s");
2854
                    case "DelayTime":
2855
                        return value.ToString() + " s";
2856
                    case "Heading":
2857
                        return Waypoints.Heading(System.Convert.ToInt32(value));
2858
                    case "Speed":
2859
                        return Waypoints.WPSpeed(System.Convert.ToInt16(value));
2860
                    case "CamAngle":
2861
                        return Waypoints.CAMAngle(System.Convert.ToInt16(value));
2862
                    case "Type":
2863
                        return ((Waypoints.pointType)(System.Convert.ToInt16(value))).ToString();
2864
                    case "AutoTrigger":
2865
                        return value.ToString() == "0" ? "- - -" : value.ToString() + " m";
2866
                    case "Status":
2867
                        return Waypoints.WPSpeed(System.Convert.ToInt16(value));
2868
                }
2869
 
2870
                return value.ToString();
2871
            }
2872
            else return value;
2873
        }
2874
 
2875
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
2876
        {
2877
            throw new NotImplementedException();
2878
        }
2879
    }
2880
 
2287 - 2881
    public class IniFile
2882
    {
2883
        public string path;
2884
 
2885
        [DllImport("kernel32")]
2886
        private static extern long WritePrivateProfileString(string section,
2887
          string key, string val, string filePath);
2888
 
2889
        [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
2890
        static extern uint GetPrivateProfileSectionNames(IntPtr lpszReturnBuffer,
2891
               uint nSize, string lpFileName);
2892
 
2893
        [DllImport("kernel32")]
2894
        private static extern int GetPrivateProfileString(string section,
2895
          string key, string def, StringBuilder retVal,
2896
          int size, string filePath);
2897
 
2898
        public IniFile(string INIPath)
2899
        {
2900
            path = INIPath;
2901
        }
2902
 
2903
        public void IniWriteValue(string Section, string Key, string Value)
2904
        {
2905
            WritePrivateProfileString(Section, Key, Value, this.path);
2906
        }
2907
 
2908
        public string IniReadValue(string Section, string Key)
2909
        {
2910
            StringBuilder temp = new StringBuilder(255);
2911
            int i = GetPrivateProfileString(Section, Key, "", temp, 255, this.path);
2912
            return temp.ToString();
2913
        }
2914
        //Ini_sections auslesen in String-Array
2915
        public string[] IniSectionNames()
2916
        {
2917
 
2918
            //  uint MAX_BUFFER = 32767;
2919
            uint MAX_BUFFER = 8388608;
2920
            IntPtr pReturnedString = Marshal.AllocCoTaskMem((int)MAX_BUFFER);
2921
            uint bytesReturned = GetPrivateProfileSectionNames(pReturnedString, MAX_BUFFER, this.path);
2922
            if (bytesReturned == 0)
2923
            {
2924
                Marshal.FreeCoTaskMem(pReturnedString);
2925
                return null;
2926
            }
2927
            string local = Marshal.PtrToStringAuto(pReturnedString, (int)bytesReturned).ToString();
2928
            Marshal.FreeCoTaskMem(pReturnedString);
2929
            //use of Substring below removes terminating null for split
2930
            return local.Substring(0, local.Length - 1).Split('\0');
2931
 
2932
 
2933
        }
2934
    }
2935
 
2936
    /// <summary>
2937
    /// Selected Win AI Function Calls
2938
    /// </summary>
2939
    public class WinApi
2940
    {
2941
        [DllImport("user32.dll", EntryPoint = "GetSystemMetrics")]
2942
        public static extern int GetSystemMetrics(int which);
2943
        [DllImport("user32.dll")]
2944
        public static extern void
2945
                SetWindowPos(IntPtr hwnd, IntPtr hwndInsertAfter,
2946
                             int X, int Y, int width, int height, uint flags);
2947
 
2948
        private const int SM_CXSCREEN = 0;
2949
        private const int SM_CYSCREEN = 1;
2950
        private static IntPtr HWND_TOP = IntPtr.Zero;
2951
        private const int SWP_SHOWWINDOW = 64; // 0x0040
2952
 
2953
        public static int ScreenX
2954
        {
2955
            get { return GetSystemMetrics(SM_CXSCREEN); }
2956
        }
2957
 
2958
        public static int ScreenY
2959
        {
2960
            get { return GetSystemMetrics(SM_CYSCREEN); }
2961
        }
2962
 
2963
        public static void SetWinFullScreen(IntPtr hwnd)
2964
        {
2965
            SetWindowPos(hwnd, HWND_TOP, -8, -7, ScreenX+15, ScreenY+14, SWP_SHOWWINDOW);
2966
        }
2967
    }
2968
    /// <summary>
2969
    /// Class used to preserve / restore state of the window
2970
    /// </summary>
2971
    public class WinState
2972
    {
2973
        private WindowState winState;
2974
        private WindowStyle brdStyle;
2975
        private bool topMost;
2976
        private Rect restore;
2977
        private bool IsMaximized = false;
2978
 
2979
        public bool isMaximized
2980
        {
2981
            get { return IsMaximized; }
2982
        }
2983
        public void Maximize(Window targetForm)
2984
        {
2985
            if (!IsMaximized)
2986
            {
2987
                IsMaximized = true;
2988
                Save(targetForm);
2989
                targetForm.WindowState = WindowState.Maximized;
2990
                targetForm.WindowStyle = WindowStyle.None;
2991
                targetForm.Topmost = true;
2992
                WinApi.SetWinFullScreen(new WindowInteropHelper(targetForm).Handle);
2993
            }
2994
        }
2995
 
2996
        public void Save(Window targetForm)
2997
        {
2998
            winState = targetForm.WindowState;
2999
            brdStyle = targetForm.WindowStyle;
3000
            topMost = targetForm.Topmost;
3001
            restore = targetForm.RestoreBounds;
3002
        }
3003
        public void Restore(Window targetForm)
3004
        {
3005
            targetForm.WindowState = winState;
3006
            targetForm.WindowStyle = brdStyle;
3007
            targetForm.Topmost = topMost;
3008
 
3009
            targetForm.Left = restore.Left;
3010
            targetForm.Top = restore.Top;
3011
            targetForm.Height = restore.Height;
3012
            targetForm.Width = restore.Width;
3013
            IsMaximized = false;
3014
        }
3015
    }
3016
 
3017
}