Subversion Repositories Projects

Rev

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