From 9847625984d1eaf5410c48e4b569683b434d6b86 Mon Sep 17 00:00:00 2001 From: Randy Mackay Date: Fri, 12 Jan 2024 12:59:29 +0900 Subject: [PATCH 01/44] mavcmd: do-change-speed Type field includes possible values (#3273) --- mavcmd.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mavcmd.xml b/mavcmd.xml index 1977720528..3aa129131e 100644 --- a/mavcmd.xml +++ b/mavcmd.xml @@ -193,7 +193,7 @@ - Type + Type (0:horiz,2:up,3:down) Speed m/s From 25860966d425196aeec56776ff8c82f41efa82c3 Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Fri, 12 Jan 2024 05:00:05 +0100 Subject: [PATCH 02/44] Fix Korean Planner Settings (#3272) --- .../ConfigPlanner.ko-KR.resx | 2058 +---------- GCSViews/ConfigurationView/ConfigPlanner.resx | 3127 +++++++++-------- 2 files changed, 1702 insertions(+), 3483 deletions(-) diff --git a/GCSViews/ConfigurationView/ConfigPlanner.ko-KR.resx b/GCSViews/ConfigurationView/ConfigPlanner.ko-KR.resx index 219966a6e0..6f664d8bd1 100644 --- a/GCSViews/ConfigurationView/ConfigPlanner.ko-KR.resx +++ b/GCSViews/ConfigurationView/ConfigPlanner.ko-KR.resx @@ -117,2303 +117,501 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - NoControl - - 496, 227 - - - 43, 13 - - - - 87 + 496, 256 센서 - - label33 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 31 - - - -1 - - - 0 - - - 1 - - - 2 - - - 3 - - - 4 - - - 5 - - - 6 - - - 7 - - - 8 - - - 9 - - - 10 - - - 25 - - - 50 - - - 100 - - 545, 224 - - - 40, 21 - - - 88 - - - CMB_ratesensors - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 32 - - - True - - - NoControl - - - 9, 38 + 545, 253 - 69, 13 - - - 86 + 54, 16 영상 형식 - - label26 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 33 - - - 107, 35 - - - 408, 21 - - - 44 - - - CMB_videoresolutions - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 34 - - - True - - - NoControl - - 9, 323 + 9, 352 - 31, 13 - - - 84 + 92, 16 투영 영상(HUD) - - label12 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 35 - - - NoControl - - 107, 322 - - - 220, 17 - - - 85 + 107, 351 GDI+ (구형/하드웨어 가속 아님) - - CHK_GDIPlus - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 36 - - - True - - - NoControl - - 9, 300 + 9, 329 - 57, 13 - - - 82 + 54, 16 경로 지점 - - label24 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 37 - - - NoControl - - 107, 299 - - - 177, 17 - - - 83 + 107, 328 연결시 경로 불러오기 - - CHK_loadwponconnect - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 38 - - - True - - - NoControl - - 9, 274 + 9, 303 - 71, 13 - - - 81 + 54, 16 트랙 길이 - - label23 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 39 - - 107, 273 - - - 67, 20 - - - 80 - - - NUM_tracklength - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 40 - - - True - - - NoControl + 107, 302 - 515, 89 + 592, 90 - 81, 17 - - - 79 + 73, 20 고도 경고 - - False - - - CHK_speechaltwarning - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 41 - - - True - - - NoControl - - 9, 251 + 9, 280 - 78, 13 - - - 45 + 65, 16 연결 재설정 - - label108 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 42 - - - NoControl - - 107, 250 - - - 217, 17 - - - 46 + 107, 279 USB 연결시 초기화(DTR 전환) - - CHK_resetapmonconnect - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 43 - - - Bottom, Left - - - NoControl - - 107, 550 + 107, 609 144, 17 - - 47 - MAVLink 메세지 디버깅 - - CHK_mavdebug - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 44 - - - NoControl - - 422, 227 - - - 22, 13 - - - 48 + 422, 256 원격 조종기 - - label107 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 45 - - - -1 - - - 0 - - - 1 - - - 2 - - - 3 - - - 4 - - - 5 - - - 6 - - - 7 - - - 8 - - - 9 - - - 10 - - - 25 - - - 35 - - - 50 - - 450, 224 - - - 40, 21 - - - 49 - - - CMB_raterc - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 46 - - - NoControl + 450, 253 - 301, 227 + 301, 256 69, 13 - - 50 - 모드/상태 - - label104 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 47 - - - NoControl - - 205, 227 + 205, 256 44, 13 - - 51 - 위치 - - label103 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 48 - - - NoControl - - 104, 227 + 104, 256 43, 13 - - 52 - 고도 - - label102 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 49 - - - True - - - NoControl - - 9, 227 + 9, 256 - 84, 13 - - - 53 + 79, 16 원격 측정 속도 - - label101 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 50 - - - -1 - - - 0 - - - 1 - - - 2 - - - 3 - - - 4 - - - 5 - - - 6 - - - 7 - - - 8 - - - 9 - - - 10 - - - 25 - - - 35 - - - 50 - - 376, 224 - - - 40, 21 - - - 54 - - - CMB_ratestatus - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 51 - - - -1 - - - 0 - - - 1 - - - 2 - - - 3 - - - 4 - - - 5 - - - 6 - - - 7 - - - 8 - - - 9 - - - 10 - - - 20 - - - 50 - - - 100 + 376, 253 - 255, 224 - - - 40, 21 - - - 55 - - - CMB_rateposition - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 52 - - - -1 - - - 0 - - - 1 - - - 2 - - - 3 - - - 4 - - - 5 - - - 6 - - - 7 - - - 8 - - - 9 - - - 10 - - - 50 - - - 100 + 255, 253 - 153, 224 - - - 40, 21 - - - 56 - - - CMB_rateattitude - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 53 - - - NoControl + 153, 253 - 480, 171 - - - 241, 31 - - - 57 + 480, 200 참고: 설정 탭에서는 원시 값을 보여주므로 단위를 표시하지 않음. - - label99 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 54 - - - True - - - NoControl - - 9, 198 + 9, 227 - 65, 13 - - - 58 + 54, 16 속력 단위 - - label98 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 55 - - - True - - - NoControl - - 9, 171 + 9, 200 - 52, 13 - - - 59 + 54, 16 거리 단위 - - label97 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 56 - - 107, 195 - - - 138, 21 - - - 60 - - - CMB_speedunits - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 57 + 107, 224 - 107, 168 - - - 138, 21 - - - 61 - - - CMB_distunits - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 58 - - - True - - - NoControl + 107, 197 - 9, 144 + 9, 173 - 45, 13 - - - 62 + 51, 16 조이스틱 - - label96 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 59 - - - True - - - NoControl - - - 9, 90 - - - 44, 13 - - - 63 - 음성 안내 - - label95 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 60 - - - True - - - NoControl - - 412, 89 + 489, 90 - 102, 17 - - - 64 + 84, 20 배터리 경고 - - False - - - CHK_speechbattery - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 61 - - - True - - - NoControl - - 332, 89 + 409, 90 - 81, 17 - - - 65 + 76, 20 30초 간격 - - False - - - CHK_speechcustom - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 62 - - - True - - - NoControl - - 280, 89 + 343, 89 - 56, 17 - - - 66 + 51, 20 모드 - - False - - - CHK_speechmode - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 63 - - - True - - - NoControl - 207, 89 - - 71, 17 - - - 67 - - - 경로 지점 - - - False - - - CHK_speechwaypoint - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 64 - - - True - - - NoControl - - - 9, 65 - - - 57, 13 - - - 68 - - - OSD 색상 - - - label94 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 65 - - - 107, 62 - - - 138, 21 - - - 69 - - - CMB_osdcolor - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 66 - - - 107, 112 - - - 138, 21 - - - 70 - - - CMB_language - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 67 - - - True - - - NoControl - - - 9, 115 - - - 69, 13 - - - 71 - - - 인터페이스 언어 - - - label93 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 68 - - - True - - - NoControl - - - 107, 89 - - - 99, 17 - - - 72 - - - 음성 안내 활성 - - - CHK_enablespeech - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 69 - - - NoControl - - - 520, 10 - - - 125, 17 - - - 73 - - - 투영 영상(HUD) 오버레이 - - - CHK_hudshow - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 70 - - - True - - - NoControl - - - 9, 11 - - - 71, 13 - - - 74 - - - 영상 장치 - - - label92 + + 73, 20 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 경로 지점 - - $this + + 61, 16 - - 71 + + OSD 색상 - - 107, 8 + + 107, 108 - - 245, 21 + + 107, 138 - - 75 + + 9, 141 - - CMB_videosources + + 87, 16 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 인터페이스 언어 - - $this + + 98, 20 - - 72 + + 음성 안내 활성 - - True + + 125, 17 - - NoControl + + 투영 영상(HUD) 오버레이 - - 9, 346 + + 54, 16 - - 61, 13 + + 영상 장치 - - 89 + + 9, 375 지도 따라가기 - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 29 - - - NoControl - - 107, 345 - - - 205, 17 - - - 90 + 107, 374 비행체 방향 따라 지도 회전 - - CHK_maprotation - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 30 - - - NoControl - - 338, 274 - - - 81, 17 - - - 91 + 338, 303 원점 거리 - - label2 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 27 - - - NoControl - - 430, 273 - - - 129, 17 - - - 92 + 430, 302 비행 데이터 표시 - - CHK_disttohomeflightdata - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 28 - - - NoControl - - 107, 139 - - - 99, 23 - - - 76 + 107, 168 조이스틱 설정 - - BUT_Joystick - - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - - $this - - - 73 - - - NoControl - - - 439, 6 - - - 75, 23 - - - 77 - 정지 - - BUT_videostop - - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - - $this - - - 74 - - - NoControl - - - 358, 6 - - - 75, 23 - - - 78 - 시작 - - BUT_videostart - - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - - $this - - - 75 - - - True - - - NoControl - - 9, 371 + 9, 400 - 50, 13 - - - 93 + 79, 16 로그 저장 경로 - - label3 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 26 - - 107, 368 - - - 386, 20 - - - 94 - - - txt_log_dir - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 25 - - - NoControl + 107, 397 - 496, 366 - - - 75, 23 - - - 95 + 496, 395 탐색 - - BUT_logdirbrowse - - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - - $this - - - 24 - - - True - - - NoControl - - 9, 397 + 9, 426 - 40, 13 - - - 96 + 29, 16 테마 - - label4 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 23 - - 107, 394 - - - 138, 21 - - - 97 - - - CMB_theme - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 22 - - - NoControl + 107, 423 - 249, 394 - - - 75, 20 - - - 98 + 249, 423 개별 설정 - - BUT_themecustom - - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - - $this - - - 21 - - - True - - - NoControl - - 594, 89 + 671, 90 - 81, 17 - - - 99 + 74, 20 시동/제동 - - False - - - CHK_speecharmdisarm - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 20 - - - NoControl - - 107, 474 - - - 99, 20 - - - 100 + 107, 503 승강계 켬/끔 - - BUT_Vario - - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - - $this - - - 19 - - - True - - - NoControl - - 107, 500 + 107, 529 - 115, 17 - - - 102 + 98, 20 익명 상황 제외 - - chk_analytics - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 18 - - - True - - - NoControl - - 228, 500 + 228, 529 - 91, 17 - - - 103 + 95, 20 베타 업데이트 - - CHK_beta - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 17 - - - True - - - NoControl - - 340, 477 + 340, 506 - 142, 17 - - - 104 + 98, 20 암호 보호 설정 - - CHK_Password - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 16 - - - True - - - NoControl - - 671, 89 + 748, 90 - 80, 17 - - - 105 + 48, 20 저속 - - False - - - CHK_speechlowspeed - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 15 - - - True - - - NoControl - - 496, 477 + 496, 506 - 91, 17 - - - 107 + 73, 20 공항 표시 - - CHK_showairports - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 14 - - - True - - - NoControl - - 598, 477 - - - 55, 17 - - - 108 - - - ADSB - - - chk_ADSB - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 13 - - - True - - - NoControl + 598, 506 - 496, 500 + 496, 529 - 54, 17 - - - 109 + 73, 20 고도 유지 - - chk_tfr - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 12 - - - Bottom, Left - - - NoControl - - 341, 550 - - - 144, 17 - - - 110 + 341, 609 시험 화면 - - chk_temp - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 11 - - - True - - - NoControl - - 340, 500 + 340, 529 - 104, 17 - - - 111 + 131, 20 원격조종 수신기 없음 - - chk_norcreceiver - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 10 - - 107, 421 - - - 138, 21 - - - 113 - - - CMB_Layout - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 8 - - - True - - - NoControl + 107, 450 - 9, 424 + 9, 453 - 39, 13 - - - 115 + 29, 16 배치 - - label5 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 7 - - - True - - 598, 501 + 598, 530 - 123, 17 - - - 116 + 120, 20 매개변수 자동 반영 - - CHK_AutoParamCommit - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 6 - - - True - - - NoControl - - 671, 477 + 671, 506 - 56, 17 - - - 117 + 73, 20 비행 안함 - - chk_shownofly - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 5 - - - True - - - NoControl - - 249, 171 + 249, 200 - 46, 13 - - - 118 + 54, 16 고도 단위 - - label6 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 3 - - 320, 168 - - - 138, 21 - - - 119 - - - CMB_altunits - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 4 + 320, 197 - 107, 448 - - - 53, 20 - - - 120 - - - num_gcsid - - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 2 - - - True - - - NoControl + 107, 477 - 9, 450 + 9, 479 - 43, 13 - - - 121 + 70, 16 지상 통제 ID - - label7 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 1 - - - True - - - NoControl - - 107, 523 + 107, 552 - 186, 17 - - - 122 + 197, 20 백그라운드에서 매개변수 다운로드 - - CHK_params_bg - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 341, 555 - - $this + + 275, 89 - - 0 - - - True - - - True + + 251, 111 - 816, 576 - - - ConfigPlanner - - - System.Windows.Forms.MyUserControl, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + 816, 635 \ No newline at end of file diff --git a/GCSViews/ConfigurationView/ConfigPlanner.resx b/GCSViews/ConfigurationView/ConfigPlanner.resx index ccd54f6684..fa6d856aea 100644 --- a/GCSViews/ConfigurationView/ConfigPlanner.resx +++ b/GCSViews/ConfigurationView/ConfigPlanner.resx @@ -117,2414 +117,2435 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - NoControl + + + False - - 535, 254 - - - 43, 13 + + 107, 166 - - - 87 + + 144, 17 - - Sensor + + $this - - label33 + + $this - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + NoControl - + $this - - 33 - - - -1 + + 54 - - 0 + + 61 - - 1 + + 340, 504 - - 2 + + 138, 24 - - 3 + + 66 - - 4 + + 44 - - 5 + + $this - - 6 + + label93 - - 7 + + CHK_disttohomeflightdata - - 8 + + 64 - - 9 + + label101 - - 10 + + -1 - - 25 + + 60 - - 50 + + 107, 349 - - 100 + + 56 - - 584, 251 + + 386, 22 - - 40, 20 + + CMB_ratestatus - - 88 + + 56, 13 - - CMB_ratesensors + + CHK_GDIPlus - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 1 - - $this + + Log Path - - 34 + + 53, 22 True - - NoControl + + 32 - - 9, 38 + + 40, 24 - - 74, 12 + + 330, 254 - - 86 + + NoControl - - Video Format + + NoControl - - label26 + + 76 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 38 - - $this + + 6 - - 35 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 107, 35 + + 107, 326 - - 408, 20 + + NOTE: Set the low level of SEVERITY to speak - - 44 + + 949, 591 - - CMB_videoresolutions + + 50 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + label107 - - $this + + NoControl - - 36 + + Low Speed - - True + + 104 - - NoControl + + 123 - - 9, 350 + + 116 - - 29, 12 + + Custom - - 84 + + 62 - - HUD + + $this - - label12 + + CMB_videoresolutions - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - + $this - - 37 + + 23 - - NoControl + + 22, 13 - - 107, 349 + + 77 - - 220, 17 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 85 + + 20 - - GDI+ (old type/no HW acceleration) + + 40 - - CHK_GDIPlus + + 9, 142 - + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + True + + $this - - 38 + + 51, 16 - - True + + 95, 16 - + NoControl - - 9, 327 + + 51 - - 57, 12 + + $this - - 82 + + 88 - - Waypoints + + 496, 527 - - label24 + + 93, 20 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 115 - + + chk_slowMachine + + $this - - 39 + + True - - NoControl + + Joystick Setup - - 107, 326 + + $this - - 177, 17 + + 559, 89 - - 83 + + Enable Speech - - Load Waypoints on connect? + + 9, 424 - - CHK_loadwponconnect + + 81, 17 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + False - - $this + + 21 - - 40 + + System.Windows.Forms.MyUserControl, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - True + + Telemetry Rates - - NoControl + + CHK_maprotation - - 9, 301 + + NoControl - - 72, 12 + + 186, 20 - - 81 + + OptOut Anon Stats - - Track Length + + $this - - label23 + + 42 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - + $this - - 41 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 107, 300 + + MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - 67, 19 + + 9, 373 - - 80 + + True - - NUM_tracklength + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + 9 - - 42 + + 81 - - True + + 9, 327 - - NoControl + + Auto Commit Params - - 671, 89 + + CHK_params_bg - - 83, 16 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 79 + + NoControl - - Alt Warning + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - False + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - CHK_speechaltwarning + + label95 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - + $this - - 43 + + 113 - - True + + 107, 62 - + NoControl - - 9, 278 - - - 81, 12 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 45 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Connect Reset + + Alt Units - - label108 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 39 - - $this + + True - - 44 + + 108, 20 - - NoControl + + 249, 421 - - 107, 277 + + 14 - - 217, 17 + + BUT_videostart - - 46 + + 107, 35 - - Reset on USB Connect (toggle DTR) + + 107, 195 - - CHK_resetapmonconnect + + 50 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 25 - + $this - - 45 + + 9 - - Bottom, Left + + 67 - - NoControl + + 47, 16 - - 106, 571 + + 100 - - 155, 17 + + 3 - - 47 - - - Mavlink Message Debug - - - CHK_mavdebug + + True - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - + $this - - 46 - - - NoControl - 461, 254 - - 22, 13 + + 56, 13 - - 48 + + 16 - - RC + + ConfigPlanner - - label107 + + 87 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 439, 6 - - $this + + CMB_videosources - - 47 + + NoControl - - -1 + + 157, 31 - - 0 + + 37 - - 1 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 2 + + 60, 16 - - 3 + + NoControl - - 4 + + $this - - 5 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 6 + + GDI+ (old type/no HW acceleration) - - 7 + + CMB_speedunits - - 8 + + True - - 9 + + $this - - 10 + + NoControl - - 25 + + 95 - - 35 + + NoControl - - 50 + + 75, 23 - - 489, 251 + + label104 - - 40, 20 + + 9, 477 - - 49 + + NoControl - - CMB_raterc + + 212, 89 - + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + $this - - 48 - - - NoControl - - - 330, 254 + + 75, 23 - - 79, 13 + + 9, 38 - - 50 + + NoControl - - Mode/Status + + CMB_raterc - - label104 + + 129, 17 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - + $this - - 49 - - - NoControl + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 220, 254 - - 56, 13 + + $this - - 51 + + 17 - - Position + + label5 - - label103 + + 241, 31 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CHK_Password + + + label24 $this - - 50 + + 44 - - NoControl + + 107, 222 - - 104, 254 + + $this - - 56, 13 + + 43 - - 52 + + 63, 16 - - Attitude + + CHK_resetapmonconnect - - label102 + + 107, 89 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CHK_speechbattery - + + 92 + + $this - - 51 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True + + label12 - - NoControl + + CMB_rateattitude - - 9, 254 + + Map Follow - - 90, 12 + + False - - 53 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Telemetry Rates + + 99, 23 - - label101 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this + + Runing on a slow computer - - 52 + + 11 - - -1 + + 9, 398 - - 0 + + 228, 20 - - 1 + + 120 - - 2 + + 496, 504 - - 3 + + 138, 24 - - 4 + + 480, 198 - - 5 + + 55 - - 6 + + 671, 504 - - 7 + + label96 - - 8 + + Alt Warning - - 9 + + 100 - - 10 + + 1 - - 25 + + 41 - - 35 + + 119, 20 - - 50 + + 489, 251 - - 415, 251 + + $this - - 40, 20 + + 107, 448 - - 54 + + NoControl - - CMB_ratestatus + + 9, 141 - + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 53 + + 71 - - -1 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 0 + + 584, 251 - - 1 + + 25 - - 2 + + 75, 20 - - 3 + + 83 - - 4 + + Bottom, Left - - 5 + + True - - 6 + + 56 - - 7 + + CMB_osdcolor - - 8 + + 340, 571 - - 9 + + True - - 10 + + NoControl - - 20 + + 520, 10 50 - - 100 + + NoControl - - 282, 251 + + $this - - 40, 20 + + 107, 395 - - 55 + + 8 - - CMB_rateposition + + 29 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - $this + + Show Airports - - 54 + + 35 - - -1 + + CHK_speechaltwarning - - 0 + + Video Device - - 1 + + -1 - - 2 + + True - - 3 + + 760, 89 - - 4 + + 107, 277 - - 5 + + 85 - - 6 + + 48 - - 7 + + 71, 16 - - 8 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 9 + + 65 + + + $this 10 - - 50 - - - 100 + + 45 - - 166, 251 + + 61 - - 40, 20 + + NoControl - - 56 + + 43, 13 - - CMB_rateattitude + + 67, 22 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - - $this + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 55 + + 68 - - NoControl + + True - - 480, 198 + + CMB_Layout - - 241, 31 + + 77 - - 57 + + 24 - - NOTE: The Configuration Tab will NOT display these units, as those are raw values. - + + True - - label99 + + $this - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 105 - + + 127 + + + 40, 24 + + $this - - 56 + + 10 - - True + + 107, 372 - - NoControl + + 78 - - 9, 225 + + 408, 24 - - 67, 12 + + 64, 20 - - 58 + + True - - Speed Units + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - label98 + + 40, 24 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Only when Armed - + $this - - 57 + + CHK_mavdebug - - True + + 55, 16 - - NoControl + + 15 - - 9, 198 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 57, 12 + + NoControl - - 59 + + 72 - - Dist Units + + 172, 20 - - label97 + + label92 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + 332, 89 - - 58 + + 65, 20 - - 107, 222 + + label94 - - 138, 20 + + $this - - 60 + + $this - - CMB_speedunits + + 107, 139 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 9, 11 - + + 8 + + + 75, 23 + + $this - - 59 + + 49 - - 107, 195 + + CMB_rateposition - - 138, 20 + + label3 - - 61 + + 2 - - CMB_distunits + + -1 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + BUT_Vario - + $this - - 60 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - True + + label102 - + NoControl - - 9, 171 + + NoControl - - 49, 12 + + 35 - - 62 + + Browse - - Joystick + + True - - label96 + + $this - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 69 - - $this + + 282, 251 - - 61 + + 37, 16 - - True + + Waypoints - - NoControl + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 9, 90 + + $this - - 42, 12 + + 107, 550 - - 63 + + NoControl - - Speech + + 60 - - label95 + + 46 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Joystick - + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + $this - - 62 + + num_gcsid - - True + + 68 - - NoControl + + Dist to Home - - 559, 89 + + $this - - 106, 16 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 64 - - - Battery Warning + + Enable HUD Overlay - - False + + 7 - - CHK_speechbattery + + 111 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 74 - + $this - - 63 - - - True + + label8 - - NoControl + + 0 - - 469, 89 + + 1 - - 84, 16 + + 2 - - 65 + + 3 - - 30s Interval + + 4 - - False + + 5 - - CHK_speechcustom + + 89, 16 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + HUD - - $this + + 98 - - 64 + + CHK_showairports - - True + + 121, 20 - - NoControl + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 408, 89 + + 57 - - 55, 16 + + 100 - - 66 + + 59 - - Mode + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - False + + CMB_theme - - CHK_speechmode + + 100 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + -1 - + $this - - 65 - - - True + + $this - + NoControl - - 332, 89 - - - 70, 16 - - - 67 - - - Waypoint - - - False + + Connect Reset - - CHK_speechwaypoint + + 97, 20 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + $this - + $this - - 66 + + 340, 550 - - True + + 138, 23 - + NoControl - - 9, 65 - - - 59, 12 + + 4 - - 68 + + 72 - - OSD Color + + $this - - label94 + + 25 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + $this - - 67 + + 138, 24 - - 107, 62 + + NoControl - - 138, 20 + + chk_tfr - - 69 + + 103 - - CMB_osdcolor + + True - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 104, 254 - - $this + + CMB_distunits - - 68 + + NoControl - - 107, 111 + + 109 - - 138, 20 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 125 + + 117 - - CMB_severity + + label99 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 48 - + $this - - 69 + + 134, 20 - - 107, 139 + + $this - - 138, 20 + + NoControl - - 70 + + 62 - - CMB_language + + 27 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 30 - - $this + + 50 - - 70 + + True + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 True - - NoControl + + 245, 24 - - 9, 142 + + $this - - 68, 12 + + 50 - - 71 + + $this - - UI Language + + NoControl - - label93 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 9, 90 - + $this - - 71 + + 4 - - True + + 408, 89 - - NoControl + + $this - - 107, 89 + + Start - - 99, 16 + + 110 - - 72 + + $this - - Enable Speech + + 0 - - CHK_enablespeech + + label6 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CHK_hudshow - - $this + + BUT_logdirbrowse - - 72 + + 18 - - NoControl + + 10 - - 520, 10 + + $this - - 133, 18 + + CHK_beta - - 73 + + $this - - Enable HUD Overlay + + Track Length - - CHK_hudshow + + NoControl - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - - $this + + 63 - - 73 + + 1 True + + 126 + + + True + + + 55 + NoControl - - 9, 11 - - - 73, 12 + + $this - - 74 + + ADSB - - Video Device + + 53 - - label92 + + NoControl - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 106, 571 - - $this + + 10 - - 74 + + False - - 107, 8 + + 9, 451 - - 245, 20 + + 34 - - 75 + + 88, 16 - - CMB_videosources + + 130, 20 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 13 - + $this - - 75 + + OSD Color - + + 71, 16 + + True - - NoControl + + 217, 17 - - 9, 373 + + 138, 24 - - 63, 12 + + $this + + + 9, 225 89 - - Map Follow - - - label1 - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 31 - - + NoControl - - 107, 372 - - - 205, 17 + + 64 - - 90 + + True Map is rotated to follow the plane - - CHK_maprotation + + 90 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 6 - - $this + + 151, 20 - - 32 + + 96 - - NoControl + + 99, 20 - - 180, 303 + + 108 - - 81, 17 + + 3 - - 91 + + 78 - - Dist to Home + + NoControl - - label2 + + 177, 17 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - - $this - - - 29 + + 9, 350 - + NoControl - - 267, 302 + + Mavlink Message Debug - - 129, 17 + + Beta Updates - - 92 + + Speech - - Display in Flightdata + + NoControl - - CHK_disttohomeflightdata + + 9, 301 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - $this + + 52 - - 30 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - NoControl + + Testing Screen - - 107, 166 + + 84 - - 99, 23 + + No RC Receiver - - 76 + + 35 - - Joystick Setup + + 22 - - BUT_Joystick + + 59 - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + 138, 24 - - $this + + 51 - - 76 + + 20 - - NoControl + + $this - - 439, 6 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 75, 23 + + 93 - - 77 + + $this - - Stop + + True - - BUT_videostop + + NoControl - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + Mode - - $this + + 1 - - 77 + + Waypoint - + NoControl - - 358, 6 + + 0 - - 75, 23 + + 5 - - 78 + + 6 - - Start + + 3 - - BUT_videostart + + 4 - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + Layout - - $this + + True - - 78 + + 7 - - True + + 8 - - NoControl + + 107, 300 - - 9, 398 + + 0 - - 50, 12 + + 125 - - 93 + + 6 - - Log Path + + NoControl - - label3 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + 85, 16 - - 28 + + 0 - - 107, 395 + + 69 - - 386, 19 + + 65 - - 94 + + BUT_Joystick - - txt_log_dir + + 74 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 75 - + $this - - 27 + + $this - + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - 496, 393 + + 133, 18 - - 75, 23 + + 58 - - 95 + + 340, 527 - - Browse + + 7 - - BUT_logdirbrowse + + 9, 171 - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + Battery Warning - - $this + + 138, 24 - - 26 + + CMB_ratesensors - - True + + 94 - + NoControl - - 9, 424 + + 8 - - 39, 12 + + 7 - - 96 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Theme + + 535, 254 - - label4 + + 4 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + -1 - - $this + + 6 - - 25 + + 5 - - 107, 421 + + 0 - - 138, 20 + + True - - 97 + + 2 - - CMB_theme + + 1 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + RC - - 24 + + $this - - NoControl + + $this - - 249, 421 + + label9 - - 75, 20 + + 9 - - 98 + + 107 - - Custom + + 81, 16 - - BUT_themecustom + + chk_shownofly - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + 79, 13 - - $this + + 138, 24 - - 23 + + 107, 501 - - True + + 124 - - NoControl + + 47 - - 760, 89 + + 56, 16 - - 87, 16 + + 166, 251 - - 99 + + 52 - - Arm/Disarm + + 228, 527 - - False + + 76 CHK_speecharmdisarm - + + chk_temp + + + 79 + + + 107, 475 + + + 47 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + CMB_severity + + + NoControl + + $this - - 22 + + 102 - + + Video Format + + + 33 + + + label23 + + + Sensor + + + 49 + + NoControl - - 107, 501 + + NoControl - - 99, 20 + + NoControl - - 100 + + 73 - - Start/Stop Vario + + 671, 89 - - BUT_Vario + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + True + + + 66 + + + NoControl + + + label1 + + + 26 + + + $this + + + False - - MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null + + 94, 20 - + $this - - 21 - - - True + + 107, 421 - - NoControl + + 155, 17 - - 107, 527 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 121, 16 + + Params Download in BackGround - - 102 + + 7 - - OptOut Anon Stats + + 31 - - chk_analytics + + 122 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - $this + + CHK_speechcustom - - 20 + + 82 - - True + + 97 - + NoControl - - 228, 527 + + MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - 94, 16 + + 12 - - 103 + + NoControl - - Beta Updates + + 30s Interval - - CHK_beta + + 46 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 598, 528 - - $this + + 63, 20 - - 19 + + 8 - - True + + CHK_loadwponconnect - - NoControl + + Theme - - 340, 504 + + 71 - - 151, 16 + + True - - 104 + + 9 - - Password Protect Config + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - CHK_Password + + 19 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 119 - - $this + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 18 + + 118 - - True + + 2 - + NoControl - - 853, 89 + + 252, 108 - - 79, 16 + + NoControl - - 105 + + Start/Stop Vario - - Low Speed + + 57 - - False + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - CHK_speechlowspeed + + NoControl - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + chk_ADSB - + $this - - 17 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + True - - NoControl + + 10 - - 496, 504 + + UI Language - - 96, 16 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 107 + + Load Waypoints on connect? - - Show Airports + + 249, 198 - - CHK_showairports + + 75 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + $this - - 16 + + 107, 111 - + + 121 + + True - - NoControl + + 70 598, 504 - - 55, 16 + + 109, 20 - - 108 + + 50 - - ADSB + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - chk_ADSB + + 9, 278 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CMB_altunits - - $this + + GCS ID - - 15 + + label108 - - True + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + label33 + + + 58 + + + 94, 20 + + NoControl - - 496, 527 + + 91 + + + False + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 54, 16 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 109 + + 358, 6 TFR's - - chk_tfr - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this + + 86 - - 14 + + 40, 24 - - Bottom, Left + + 9, 65 - - NoControl + + $this - - 340, 571 + + $this - - 144, 17 + + 67 - - 110 + + 9 - - Testing Screen + + Stop - - chk_temp + + True - + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this - - - 13 + + NoControl True - - NoControl - - - 340, 527 - - - 107, 16 + + 63, 20 - - 111 + + $this - - No RC Receiver + + Reset on USB Connect (toggle DTR) - - chk_norcreceiver + + 320, 195 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + 50 - - 12 + + label7 - - 107, 448 + + 107, 16 - - 138, 20 + + label2 - - 113 + + $this - - CMB_Layout + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CHK_speechwaypoint - - $this + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 11 + + Password Protect Config - - True + + 3 - - NoControl + + 36 - - 9, 451 + + label98 - - 39, 12 + + txt_log_dir - - 115 + + 76, 16 - - Layout + + 469, 89 - - label5 + + NoControl - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 180, 303 - - $this + + NUM_tracklength - - 10 + + Display in Flightdata - - True + + CHK_enablespeech - - 598, 528 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 133, 16 + + Position - - 116 + + label97 - - Auto Commit Params + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 CHK_AutoParamCommit - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 80 - - $this + + 107, 8 - - 9 + + 5 - + True - - NoControl + + 107, 527 - - 671, 504 + + 9, 254 - - 58, 16 + + 10 - - 117 + + $this - - No Fly + + 5 - - chk_shownofly + + System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 853, 89 - - $this + + 9 - - 8 + + 9, 198 - + True - - NoControl + + 45 - - 249, 198 + + CHK_speechmode - - 51, 12 + + 8 - - 118 + + 7 - - Alt Units + + 6 - - label6 + + 5 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 4 - - $this + + 3 - - 6 + + 2 - - 320, 195 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 138, 20 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 119 + + 63 - - CMB_altunits + + 220, 17 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 205, 17 - - $this + + 25 - - 7 + + BUT_videostop - - 107, 475 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - 53, 19 + + 53 - - 120 + + 496, 393 - - num_gcsid + + 124, 20 - - System.Windows.Forms.NumericUpDown, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Dist Units - - $this + + Arm/Disarm - - 5 + + 83, 20 - + True - - NoControl - - - 9, 477 + + False - - 43, 12 + + MissionPlanner.Controls.MyButton, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - - 121 + + False - - GCS ID + + True - - label7 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Attitude - + $this - - 4 - - - True + + 40, 24 - + NoControl - - 107, 550 + + chk_norcreceiver - - 194, 16 + + 28 - - 122 + + 2 - - Params Download in BackGround + + CHK_speechlowspeed - - CHK_params_bg + + 50, 16 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + Mode/Status - - $this + + CHK_speechArmedOnly - - 3 + + $this - - True + + BUT_themecustom - - NoControl + + chk_analytics - - 340, 550 + + 54 - - 163, 16 + + 415, 251 - - 123 + + 99 - - Runing on a slow computer + + $this - - chk_slowMachine + + $this - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + CMB_language - - $this + + label103 - - 2 + + 73 - - True + + 267, 302 - - NoControl + + No Fly - - 212, 89 + + 70 - - 114, 16 + + label4 - - 124 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - Only when Armed + + $this - - False + + Speed Units - - CHK_speechArmedOnly + + 84, 16 - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + $this - - 1 + + label26 - + NoControl - - 252, 108 + + True - - 157, 31 + + Bottom, Left - - 126 + + $this - - NOTE: Set the low level of SEVERITY to speak + + 54, 16 - - label8 + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - + $this - + + NOTE: The Configuration Tab will NOT display these units, as those are raw values. + + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0 True - - True - - - 949, 591 - - - ConfigPlanner - - - System.Windows.Forms.MyUserControl, MissionPlanner.Controls, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null - + + ko-KR + \ No newline at end of file From c70e8a9d79e4262bbe0dfaf422d4c280e8ca0767 Mon Sep 17 00:00:00 2001 From: Andrew Tridgell Date: Fri, 12 Jan 2024 15:01:20 +1100 Subject: [PATCH 03/44] prevent target_system=0 in toggle safety switch (#3269) a user tried to toggle safety on an antenna tracker and MissionPlanner sent it to target_system=0, which resulted in toggling safety on a flying aircraft, causing it to crash --- GCSViews/FlightData.cs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/GCSViews/FlightData.cs b/GCSViews/FlightData.cs index 46ae7561bb..74909e1ba7 100644 --- a/GCSViews/FlightData.cs +++ b/GCSViews/FlightData.cs @@ -1692,8 +1692,13 @@ private void BUTactiondo_Click(object sender, EventArgs e) } if (CMB_action.Text == actions.Toggle_Safety_Switch.ToString()) { + var target_system = (byte)MainV2.comPort.sysidcurrent; + if (target_system == 0) { + log.Info("Not toggling safety on sysid 0"); + return; + } var custom_mode = (MainV2.comPort.MAV.cs.sensors_enabled.motor_control && MainV2.comPort.MAV.cs.sensors_enabled.seen) ? 1u : 0u; - var mode = new MAVLink.mavlink_set_mode_t() { custom_mode = custom_mode, target_system = (byte)MainV2.comPort.sysidcurrent }; + var mode = new MAVLink.mavlink_set_mode_t() { custom_mode = custom_mode, target_system = target_system }; MainV2.comPort.setMode(mode, MAVLink.MAV_MODE_FLAG.SAFETY_ARMED); ((Control)sender).Enabled = true; return; From 90a62efe462ab9ce753f78b24bbad23a397ecf76 Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Fri, 12 Jan 2024 05:01:46 +0100 Subject: [PATCH 04/44] Fix:Use VFR_HUD for climbrate IF it is received. (#3267) --- ExtLibs/ArduPilot/CurrentState.cs | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/ExtLibs/ArduPilot/CurrentState.cs b/ExtLibs/ArduPilot/CurrentState.cs index b44500cc68..64516db316 100644 --- a/ExtLibs/ArduPilot/CurrentState.cs +++ b/ExtLibs/ArduPilot/CurrentState.cs @@ -186,6 +186,9 @@ public bool prearmstatus /// private double Wn_fgo; + //It is true when we got a VFR_HUD message, so it can be used to get climbrate, instead of calculating it from time and alt change. + private bool gotVFR = false; + static CurrentState() { // set default telemrates @@ -313,7 +316,11 @@ public float alt if ((datetime - lastalt).TotalSeconds >= 0.2 && oldalt != alt || lastalt > datetime) { - climbrate = (alt - oldalt) / (float)(datetime - lastalt).TotalSeconds; + //Don't update climbrate if we got a VFR_HUD message, because it is more accurate + if (!gotVFR) + { + climbrate = (alt - oldalt) / (float)(datetime - lastalt).TotalSeconds; + } verticalspeed = (alt - oldalt) / (float)(datetime - lastalt).TotalSeconds; if (float.IsInfinity(_verticalspeed)) _verticalspeed = 0; @@ -3498,25 +3505,16 @@ private void Parent_OnPacketReceived(object sender, MAVLink.MAVLinkMessage mavLi var vfr = mavLinkMessage.ToStructure(); groundspeed = vfr.groundspeed; - airspeed = vfr.airspeed; - - //alt = vfr.alt; // this might include baro - ch3percent = vfr.throttle; if (sensors_present.revthrottle && sensors_enabled.revthrottle && sensors_health.revthrottle) if (ch3percent > 0) ch3percent *= -1; - //Console.WriteLine(alt); - - //climbrate = vfr.climb; - - // heading = vfr.heading; - - - //MAVLink.packets[(byte)MAVLink.MSG_NAMES.VFR_HUD); + //This comes from the EKF, so it supposed to be correct + climbrate = vfr.climb; + gotVFR = true; // we have a vfr packet } break; From 196958a389518b28fa9939ed71df111a9328f622 Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Fri, 12 Jan 2024 05:03:04 +0100 Subject: [PATCH 05/44] Fix rotated map not displaying vehicle (#3266) --- .../GMap.NET.WindowsForms/GMapControl.cs | 4 ++-- ExtLibs/Maps/GMapMarkerQuad.cs | 2 +- GCSViews/ConfigurationView/ConfigPlanner.cs | 8 ++++++++ GCSViews/FlightData.cs | 10 +++++++++- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/ExtLibs/GMap.NET.WindowsForms/GMap.NET.WindowsForms/GMapControl.cs b/ExtLibs/GMap.NET.WindowsForms/GMap.NET.WindowsForms/GMapControl.cs index d774c40dde..0a59227923 100644 --- a/ExtLibs/GMap.NET.WindowsForms/GMap.NET.WindowsForms/GMapControl.cs +++ b/ExtLibs/GMap.NET.WindowsForms/GMap.NET.WindowsForms/GMapControl.cs @@ -1439,7 +1439,6 @@ public void doPaint(IGraphics e) { { e.Clear(EmptyMapBackground); - #if !PocketPC if (MapRenderTransform.HasValue) { @@ -1507,8 +1506,9 @@ public void doPaint(IGraphics e) } #endif DrawMap(e); - OnPaintOverlays(e); } + OnPaintOverlays(e); + } } diff --git a/ExtLibs/Maps/GMapMarkerQuad.cs b/ExtLibs/Maps/GMapMarkerQuad.cs index 537960898a..4f7eb4a9b3 100644 --- a/ExtLibs/Maps/GMapMarkerQuad.cs +++ b/ExtLibs/Maps/GMapMarkerQuad.cs @@ -47,8 +47,8 @@ public override void OnRender(IGraphics g) { var temp = g.Transform; g.TranslateTransform(LocalPosition.X, LocalPosition.Y); - // set centerpoint as 0,0 g.TranslateTransform(-Offset.X, -Offset.Y); + g.RotateTransform(-Overlay.Control.Bearing); // anti NaN try diff --git a/GCSViews/ConfigurationView/ConfigPlanner.cs b/GCSViews/ConfigurationView/ConfigPlanner.cs index 5e7fd49b75..4c11bd9ed2 100644 --- a/GCSViews/ConfigurationView/ConfigPlanner.cs +++ b/GCSViews/ConfigurationView/ConfigPlanner.cs @@ -720,6 +720,10 @@ private void CHK_maprotation_CheckedChanged(object sender, EventArgs e) if (startup) return; Settings.Instance["CHK_maprotation"] = CHK_maprotation.Checked.ToString(); + if (CHK_maprotation.Checked) + { + chk_shownofly.Checked = false; + } FlightData.instance.gMapControl1.Bearing = 0; } @@ -987,6 +991,10 @@ private void CHK_AutoParamCommit_CheckedChanged(object sender, EventArgs e) private void chk_shownofly_CheckedChanged(object sender, EventArgs e) { Settings.Instance["ShowNoFly"] = chk_shownofly.Checked.ToString(); + if (chk_shownofly.Checked) + { + CHK_maprotation.Checked = false; + } } private void CMB_altunits_SelectedIndexChanged(object sender, EventArgs e) diff --git a/GCSViews/FlightData.cs b/GCSViews/FlightData.cs index 74909e1ba7..95e6842d26 100644 --- a/GCSViews/FlightData.cs +++ b/GCSViews/FlightData.cs @@ -3593,8 +3593,16 @@ private void mainloop() if (Settings.Instance.GetBoolean("CHK_maprotation")) { - // dont holdinvalidation here + ////Check if we have more than one vehicle connected and disable CHK_maprotation if so + if (MainV2.comPort.MAVlist.Count > 1) + { + Settings.Instance["CHK_maprotation"] = "false"; + //And set maprotation to zero + BeginInvoke((Action)delegate { gMapControl1.Bearing = 0; }); + } + //gMapControl1.HoldInvalidation = true; setMapBearing(); + } if (route == null) From fb6af04b7dd84bf51a61c0200d62dde93d10dd2e Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Fri, 12 Jan 2024 05:04:14 +0100 Subject: [PATCH 06/44] Fix exception when with less than five serial ports (#3265) --- GCSViews/ConfigurationView/ConfigSerial.cs | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/GCSViews/ConfigurationView/ConfigSerial.cs b/GCSViews/ConfigurationView/ConfigSerial.cs index cbc19c3150..eab67d2385 100644 --- a/GCSViews/ConfigurationView/ConfigSerial.cs +++ b/GCSViews/ConfigurationView/ConfigSerial.cs @@ -20,6 +20,7 @@ public partial class ConfigSerial : MyUserControl, IActivate, IDeactivate private bool _gotUARTNames = false; private bool _gotOptionRules = false; + private int serialPorts = 0; private Dictionary _uartNames = new Dictionary(); private Dictionary _optionRules = new Dictionary(); @@ -160,7 +161,7 @@ public void Activate() } //find the largest numbered serialx_baud param - int serialPorts = 0; + serialPorts = 0; foreach (var param in MainV2.comPort.MAV.param.Keys) { if (param.StartsWith("SERIAL") && param.EndsWith("_BAUD")) @@ -408,7 +409,7 @@ private void doApplyRules(string portName, string v) //But this includes the USB port, so we can only have 4 ports set to mavlink int mavlinkPorts = 0; - for (int i = 1; i <= 5; i++) + for (int i = 1; i <= serialPorts; i++) { string protParamName = "SERIAL" + i.ToString() + "_PROTOCOL"; if (MainV2.comPort.MAV.param[protParamName].Value.ToString() == "1" From 75c40eb739b9790dd655760a60a123127db41862 Mon Sep 17 00:00:00 2001 From: Bob Long Date: Fri, 12 Jan 2024 15:07:19 +1100 Subject: [PATCH 07/44] CurrentState: correct unit handling for `radius` (#3262) This fixes the turn radius display on the map when using other speed units --- Common.cs | 4 ++-- ExtLibs/ArduPilot/CurrentState.cs | 2 +- Swarm/Formation.cs | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Common.cs b/Common.cs index e4c6fc87f8..7a226e5a4e 100644 --- a/Common.cs +++ b/Common.cs @@ -42,7 +42,7 @@ public static GMapMarker getMAVMarker(MAVState MAV, GMapOverlay overlay = null) itemp.Cog = MAV.cs.groundcourse; itemp.Target = MAV.cs.target_bearing; itemp.Nav_bearing = MAV.cs.nav_bearing; - itemp.Radius = MAV.cs.radius * CurrentState.multiplierdist; + itemp.Radius = (float)CurrentState.fromDistDisplayUnit(MAV.cs.radius); return null; } else if (item is GMapMarkerQuad) @@ -76,7 +76,7 @@ public static GMapMarker getMAVMarker(MAVState MAV, GMapOverlay overlay = null) { return (new GMapMarkerPlane(MAV.sysid - 1, portlocation, MAV.cs.yaw, MAV.cs.groundcourse, MAV.cs.nav_bearing, MAV.cs.target_bearing, - MAV.cs.radius * CurrentState.multiplierdist) + (float)CurrentState.toDistDisplayUnit(MAV.cs.radius)) { ToolTipText = ArduPilot.Common.speechConversion(MAV, "" + Settings.Instance["mapicondesc"]), ToolTipMode = String.IsNullOrEmpty(Settings.Instance["mapicondesc"]) ? MarkerTooltipMode.Never : MarkerTooltipMode.Always, diff --git a/ExtLibs/ArduPilot/CurrentState.cs b/ExtLibs/ArduPilot/CurrentState.cs index 64516db316..db2c9986ac 100644 --- a/ExtLibs/ArduPilot/CurrentState.cs +++ b/ExtLibs/ArduPilot/CurrentState.cs @@ -1054,7 +1054,7 @@ public float radius get { if (_groundspeed <= 1) return 0; - return (float)(groundspeed * groundspeed / (9.80665 * Math.Tan(roll * MathHelper.deg2rad))); + return (float)toDistDisplayUnit(_groundspeed * _groundspeed / (9.80665 * Math.Tan(roll * MathHelper.deg2rad))); } } [GroupText("Position")] diff --git a/Swarm/Formation.cs b/Swarm/Formation.cs index 3e08a7572d..2628291323 100644 --- a/Swarm/Formation.cs +++ b/Swarm/Formation.cs @@ -191,7 +191,7 @@ public override void SendCommand() if (true) { - var leaderturnrad = Leader.cs.radius; + var leaderturnrad = CurrentState.fromDistDisplayUnit(Leader.cs.radius); var mavturnradius = leaderturnrad - x; { From 1edc52a626d7222be1b61ad91921adeb71af70be Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 12 Jan 2024 15:20:34 +1100 Subject: [PATCH 08/44] MAVLinkParam: remove decimal --- ExtLibs/ArduPilot/parampck.cs | 6 +++--- ExtLibs/Mavlink/MAVLinkParam.cs | 8 ++++---- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/ExtLibs/ArduPilot/parampck.cs b/ExtLibs/ArduPilot/parampck.cs index 969d813843..240eb657d3 100644 --- a/ExtLibs/ArduPilot/parampck.cs +++ b/ExtLibs/ArduPilot/parampck.cs @@ -100,12 +100,12 @@ public static MAVLink.MAVLinkParamList unpack(byte[] data) Array.Copy(data, dataPointer, vdata, 0, mapped.type_len); dataPointer += mapped.type_len; - decimal? default_value = null; + double? default_value = null; if (with_defaults) { if ((flags & 1U) == 0) { - default_value = Convert.ToDecimal(v); + default_value = Convert.ToDouble(v); } else { - default_value = Convert.ToDecimal(decode_value(mapped.type_format, data, dataPointer)); + default_value = Convert.ToDouble(decode_value(mapped.type_format, data, dataPointer)); dataPointer += mapped.type_len; } } diff --git a/ExtLibs/Mavlink/MAVLinkParam.cs b/ExtLibs/Mavlink/MAVLinkParam.cs index 5f1c3962d8..70402aee09 100644 --- a/ExtLibs/Mavlink/MAVLinkParam.cs +++ b/ExtLibs/Mavlink/MAVLinkParam.cs @@ -33,7 +33,7 @@ public double Value /// /// Default value of parameter as a double, readonly, NaN if not available /// - public readonly decimal? default_value = null; + public readonly double? default_value = null; private MAV_PARAM_TYPE _typeap = 0; public MAV_PARAM_TYPE TypeAP { @@ -82,7 +82,7 @@ private MAVLinkParam() /// /// /// - public MAVLinkParam(string name, double value, MAV_PARAM_TYPE wiretype, decimal? _default_value = null) + public MAVLinkParam(string name, double value, MAV_PARAM_TYPE wiretype, double? _default_value = null) { Name = name; Type = wiretype; @@ -97,7 +97,7 @@ public MAVLinkParam(string name, double value, MAV_PARAM_TYPE wiretype, decimal? /// /// /// - public MAVLinkParam(string name, byte[] inputwire, MAV_PARAM_TYPE wiretype, MAV_PARAM_TYPE typeap, decimal? _default_value = null) + public MAVLinkParam(string name, byte[] inputwire, MAV_PARAM_TYPE wiretype, MAV_PARAM_TYPE typeap, double? _default_value = null) { Name = name; Type = wiretype; @@ -129,7 +129,7 @@ public double GetValue() (double)item.float_value 0.800000011920929 */ - return (double)(decimal)float_value; + return Math.Round((double)float_value, 7); } throw new FormatException("invalid type"); From a67d45cde6f00eec60f71ba8930f8c9abce28aa0 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Tue, 12 Dec 2023 15:35:03 +1100 Subject: [PATCH 09/44] Xamarin: fix android 13 startup --- .../Xamarin/Xamarin.Android/MainActivity.cs | 30 +++++++------------ 1 file changed, 11 insertions(+), 19 deletions(-) diff --git a/ExtLibs/Xamarin/Xamarin.Android/MainActivity.cs b/ExtLibs/Xamarin/Xamarin.Android/MainActivity.cs index 612eff086f..f0bf1ae3bb 100644 --- a/ExtLibs/Xamarin/Xamarin.Android/MainActivity.cs +++ b/ExtLibs/Xamarin/Xamarin.Android/MainActivity.cs @@ -89,13 +89,13 @@ namespace Xamarin.Droid { //global::Android.Content.Intent.CategoryLauncher //global::Android.Content.Intent.CategoryHome, [IntentFilter(new[] { global::Android.Content.Intent.ActionMain, global::Android.Content.Intent.ActionAirplaneModeChanged , - global::Android.Content.Intent.ActionBootCompleted , UsbManager.ActionUsbDeviceAttached, UsbManager.ActionUsbDeviceDetached, - global::Android.Bluetooth.BluetoothDevice.ActionFound, global::Android.Bluetooth.BluetoothDevice.ActionAclConnected, UsbManager.ActionUsbAccessoryAttached}, - Categories = new []{ global::Android.Content.Intent.CategoryLauncher})] + global::Android.Content.Intent.ActionBootCompleted , UsbManager.ActionUsbDeviceAttached, UsbManager.ActionUsbDeviceDetached, + global::Android.Bluetooth.BluetoothDevice.ActionFound, global::Android.Bluetooth.BluetoothDevice.ActionAclConnected, UsbManager.ActionUsbAccessoryAttached}, + Categories = new[] { global::Android.Content.Intent.CategoryLauncher })] [IntentFilter(actions: new[] { global::Android.Content.Intent.ActionView }, Categories = new[] { global::Android.Content.Intent.CategoryBrowsable, global::Android.Content.Intent.ActionDefault, global::Android.Content.Intent.CategoryOpenable }, DataHost = "*", DataPathPattern = ".*\\.tlog", DataMimeType = "*/*", DataSchemes = new[] { "file", "http", "https", "content" })] - [IntentFilter(actions: new[] { global::Android.Content.Intent.ActionView }, Categories = new[] { global::Android.Content.Intent.CategoryBrowsable, global::Android.Content.Intent.ActionDefault, global::Android.Content.Intent.CategoryOpenable }, DataHost = "*", DataPathPattern = ".*\\.bin", DataMimeType = "*/*", DataSchemes = new[] { "file", "http", "https", "content" })] + [IntentFilter(actions: new[] { global::Android.Content.Intent.ActionView }, Categories = new[] { global::Android.Content.Intent.CategoryBrowsable, global::Android.Content.Intent.ActionDefault, global::Android.Content.Intent.CategoryOpenable }, DataHost = "*", DataPathPattern = ".*\\.bin", DataMimeType = "*/*", DataSchemes = new[] { "file", "http", "https", "content" })] [MetaData("android.hardware.usb.action.USB_DEVICE_ATTACHED", Resource = "@xml/device_filter")] - [Activity(Label = "Mission Planner", Exported = true, ScreenOrientation = ScreenOrientation.SensorLandscape, Icon = "@mipmap/icon", Theme = "@style/MainTheme", + [Activity(Label = "Mission Planner", Exported = true, ScreenOrientation = ScreenOrientation.SensorLandscape, Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, HardwareAccelerated = true, DirectBootAware = true, Immersive = true, LaunchMode = LaunchMode.SingleInstance)] public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity { @@ -141,7 +141,7 @@ protected override void OnActivityResult(int requestCode, Result resultCode, Int var query = this.ContentResolver.Query(docUriTree, null, null, null, null); query.MoveToFirst(); - var filePath = query.GetString(0); + var filePath = query.GetString(0); query.Close(); pref.Edit().PutString("Directory", filePath).Commit(); @@ -173,7 +173,7 @@ protected override void OnCreate(Bundle savedInstanceState) TabLayoutResource = Resource.Layout.Tabbar; ToolbarResource = Resource.Layout.Toolbar; - SetSupportActionBar((Toolbar) FindViewById(ToolbarResource)); + SetSupportActionBar((Toolbar)FindViewById(ToolbarResource)); this.Window.AddFlags(WindowManagerFlags.Fullscreen | WindowManagerFlags.TurnScreenOn | WindowManagerFlags.HardwareAccelerated); @@ -304,11 +304,11 @@ void ContinueInit() { if (ContextCompat.CheckSelfPermission(this, Manifest.Permission.AccessFineLocation) != - (int) Permission.Granted || + (int)Permission.Granted || ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != - (int) Permission.Granted || + (int)Permission.Granted || ContextCompat.CheckSelfPermission(this, Manifest.Permission.Bluetooth) != - (int) Permission.Granted) + (int)Permission.Granted) { ActivityCompat.RequestPermissions(this, new String[] @@ -318,15 +318,7 @@ void ContinueInit() Manifest.Permission.Bluetooth }, 1); } - - while (ContextCompat.CheckSelfPermission(this, Manifest.Permission.WriteExternalStorage) != - (int) Permission.Granted) - { - Thread.Sleep(1000); - var text = "Checking Permissions - " + DateTime.Now.ToString("T"); - - //DoToastMessage(text); - } + } try { From 21ad2feac1c2d715d69aa9c971584c177a7022a3 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Wed, 17 Jan 2024 14:21:07 +1100 Subject: [PATCH 10/44] AA: fix security issue --- ExtLibs/AltitudeAngelWings/AltitudeAngelWings.csproj | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ExtLibs/AltitudeAngelWings/AltitudeAngelWings.csproj b/ExtLibs/AltitudeAngelWings/AltitudeAngelWings.csproj index bb570dd036..1defef05ba 100644 --- a/ExtLibs/AltitudeAngelWings/AltitudeAngelWings.csproj +++ b/ExtLibs/AltitudeAngelWings/AltitudeAngelWings.csproj @@ -22,7 +22,7 @@ - + From 7971cbabfca02656226892d5abfb66e6a7ffdedb Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Wed, 17 Jan 2024 14:21:50 +1100 Subject: [PATCH 11/44] LogBrowse: fix param double/decimal issue --- Log/LogBrowse.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Log/LogBrowse.cs b/Log/LogBrowse.cs index c2049f7c73..11deed5547 100644 --- a/Log/LogBrowse.cs +++ b/Log/LogBrowse.cs @@ -3763,8 +3763,8 @@ private void chk_params_CheckedChanged(object sender, EventArgs e) foreach (var msg in logdata.GetEnumeratorType("PARM")) { double value = double.Parse(msg["Value"], CultureInfo.InvariantCulture); - decimal tmp; - decimal? default_value = has_defaults && decimal.TryParse(msg["Default"], out tmp) ? (decimal?)tmp : null; + double tmp; + double? default_value = has_defaults && double.TryParse(msg["Default"], out tmp) ? (double?)tmp : null; MAVLink.MAVLinkParam sourceItem = new MAVLink.MAVLinkParam(msg["Name"], value, MAVLink.MAV_PARAM_TYPE.REAL32, default_value); // Lookup the next item in the target list From d03a8f0fd2a91b1bc07ff9e45872478862aeddaa Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Wed, 17 Jan 2024 16:28:47 +1100 Subject: [PATCH 12/44] AA: fix scope function --- .../Clients/Auth/Model/TokenResponseExtensions.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ExtLibs/AltitudeAngelWings/Clients/Auth/Model/TokenResponseExtensions.cs b/ExtLibs/AltitudeAngelWings/Clients/Auth/Model/TokenResponseExtensions.cs index c2f0eaaaa8..634452f11d 100644 --- a/ExtLibs/AltitudeAngelWings/Clients/Auth/Model/TokenResponseExtensions.cs +++ b/ExtLibs/AltitudeAngelWings/Clients/Auth/Model/TokenResponseExtensions.cs @@ -1,3 +1,4 @@ +using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IdentityModel.Tokens.Jwt; @@ -43,7 +44,7 @@ public static string[] AccessTokenScopes(this TokenResponse tokenResponse) scopes.AddRange(values.Select(item => item.ToString())); break; default: - scopes.Add(JsonExtensions.SerializeToJson(value)); + scopes.Add(JsonConvert.SerializeObject(value)); break; } From c41efec937d1af72c5ce6c46dc0695b4cbad2b1d Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Wed, 17 Jan 2024 16:31:33 +1100 Subject: [PATCH 13/44] Mavlink: upstream update --- ExtLibs/Mavlink/Mavlink.cs | 843 +++++++++++++----- ExtLibs/Mavlink/mavlink.lua | 522 ++++++++--- .../message_definitions/ardupilotmega.xml | 5 +- .../Mavlink/message_definitions/common.xml | 318 +++++-- .../Mavlink/message_definitions/csAirLink.xml | 30 + ExtLibs/Mavlink/updatexmls.bat | 2 + 6 files changed, 1292 insertions(+), 428 deletions(-) create mode 100644 ExtLibs/Mavlink/message_definitions/csAirLink.xml diff --git a/ExtLibs/Mavlink/Mavlink.cs b/ExtLibs/Mavlink/Mavlink.cs index c3888f71f6..ed5d08c4cc 100644 --- a/ExtLibs/Mavlink/Mavlink.cs +++ b/ExtLibs/Mavlink/Mavlink.cs @@ -5,7 +5,7 @@ public partial class MAVLink { - public const string MAVLINK_BUILD_DATE = "Sat Jul 15 2023"; + public const string MAVLINK_BUILD_DATE = "Wed Jan 17 2024"; public const string MAVLINK_WIRE_PROTOCOL_VERSION = "2.0"; public const int MAVLINK_MAX_PAYLOAD_LEN = 255; @@ -85,7 +85,7 @@ public partial class MAVLink new message_info(65, "RC_CHANNELS", 118, 42, 42, typeof( mavlink_rc_channels_t )), new message_info(66, "REQUEST_DATA_STREAM", 148, 6, 6, typeof( mavlink_request_data_stream_t )), new message_info(67, "DATA_STREAM", 21, 4, 4, typeof( mavlink_data_stream_t )), - new message_info(69, "MANUAL_CONTROL", 243, 11, 11, typeof( mavlink_manual_control_t )), + new message_info(69, "MANUAL_CONTROL", 243, 11, 30, typeof( mavlink_manual_control_t )), new message_info(70, "RC_CHANNELS_OVERRIDE", 124, 18, 38, typeof( mavlink_rc_channels_override_t )), new message_info(73, "MISSION_ITEM_INT", 38, 37, 38, typeof( mavlink_mission_item_int_t )), new message_info(74, "VFR_HUD", 20, 20, 20, typeof( mavlink_vfr_hud_t )), @@ -112,7 +112,7 @@ public partial class MAVLink new message_info(105, "HIGHRES_IMU", 93, 62, 63, typeof( mavlink_highres_imu_t )), new message_info(106, "OPTICAL_FLOW_RAD", 138, 44, 44, typeof( mavlink_optical_flow_rad_t )), new message_info(107, "HIL_SENSOR", 108, 64, 65, typeof( mavlink_hil_sensor_t )), - new message_info(108, "SIM_STATE", 32, 84, 84, typeof( mavlink_sim_state_t )), + new message_info(108, "SIM_STATE", 32, 84, 92, typeof( mavlink_sim_state_t )), new message_info(109, "RADIO_STATUS", 185, 9, 9, typeof( mavlink_radio_status_t )), new message_info(110, "FILE_TRANSFER_PROTOCOL", 84, 254, 254, typeof( mavlink_file_transfer_protocol_t )), new message_info(111, "TIMESYNC", 34, 16, 16, typeof( mavlink_timesync_t )), @@ -227,7 +227,7 @@ public partial class MAVLink new message_info(256, "SETUP_SIGNING", 71, 42, 42, typeof( mavlink_setup_signing_t )), new message_info(257, "BUTTON_CHANGE", 131, 9, 9, typeof( mavlink_button_change_t )), new message_info(258, "PLAY_TUNE", 187, 32, 232, typeof( mavlink_play_tune_t )), - new message_info(259, "CAMERA_INFORMATION", 92, 235, 235, typeof( mavlink_camera_information_t )), + new message_info(259, "CAMERA_INFORMATION", 92, 235, 236, typeof( mavlink_camera_information_t )), new message_info(260, "CAMERA_SETTINGS", 146, 5, 13, typeof( mavlink_camera_settings_t )), new message_info(261, "STORAGE_INFORMATION", 179, 27, 60, typeof( mavlink_storage_information_t )), new message_info(262, "CAMERA_CAPTURE_STATUS", 12, 18, 22, typeof( mavlink_camera_capture_status_t )), @@ -245,11 +245,12 @@ public partial class MAVLink new message_info(280, "GIMBAL_MANAGER_INFORMATION", 70, 33, 33, typeof( mavlink_gimbal_manager_information_t )), new message_info(281, "GIMBAL_MANAGER_STATUS", 48, 13, 13, typeof( mavlink_gimbal_manager_status_t )), new message_info(282, "GIMBAL_MANAGER_SET_ATTITUDE", 123, 35, 35, typeof( mavlink_gimbal_manager_set_attitude_t )), - new message_info(283, "GIMBAL_DEVICE_INFORMATION", 74, 144, 144, typeof( mavlink_gimbal_device_information_t )), + new message_info(283, "GIMBAL_DEVICE_INFORMATION", 74, 144, 145, typeof( mavlink_gimbal_device_information_t )), new message_info(284, "GIMBAL_DEVICE_SET_ATTITUDE", 99, 32, 32, typeof( mavlink_gimbal_device_set_attitude_t )), - new message_info(285, "GIMBAL_DEVICE_ATTITUDE_STATUS", 137, 40, 40, typeof( mavlink_gimbal_device_attitude_status_t )), - new message_info(286, "AUTOPILOT_STATE_FOR_GIMBAL_DEVICE", 210, 53, 53, typeof( mavlink_autopilot_state_for_gimbal_device_t )), + new message_info(285, "GIMBAL_DEVICE_ATTITUDE_STATUS", 137, 40, 49, typeof( mavlink_gimbal_device_attitude_status_t )), + new message_info(286, "AUTOPILOT_STATE_FOR_GIMBAL_DEVICE", 210, 53, 57, typeof( mavlink_autopilot_state_for_gimbal_device_t )), new message_info(287, "GIMBAL_MANAGER_SET_PITCHYAW", 1, 23, 23, typeof( mavlink_gimbal_manager_set_pitchyaw_t )), + new message_info(288, "GIMBAL_MANAGER_SET_MANUAL_CONTROL", 20, 23, 23, typeof( mavlink_gimbal_manager_set_manual_control_t )), new message_info(299, "WIFI_CONFIG_AP", 19, 96, 96, typeof( mavlink_wifi_config_ap_t )), new message_info(301, "AIS_VESSEL", 243, 58, 58, typeof( mavlink_ais_vessel_t )), new message_info(310, "UAVCAN_NODE_STATUS", 28, 17, 17, typeof( mavlink_uavcan_node_status_t )), @@ -268,6 +269,7 @@ public partial class MAVLink new message_info(370, "SMART_BATTERY_INFO", 75, 87, 109, typeof( mavlink_smart_battery_info_t )), new message_info(373, "GENERATOR_STATUS", 117, 42, 42, typeof( mavlink_generator_status_t )), new message_info(375, "ACTUATOR_OUTPUT_STATUS", 251, 140, 140, typeof( mavlink_actuator_output_status_t )), + new message_info(376, "RELAY_STATUS", 199, 8, 8, typeof( mavlink_relay_status_t )), new message_info(385, "TUNNEL", 147, 133, 133, typeof( mavlink_tunnel_t )), new message_info(386, "CAN_FRAME", 132, 16, 16, typeof( mavlink_can_frame_t )), new message_info(387, "CANFD_FRAME", 4, 72, 72, typeof( mavlink_canfd_frame_t )), @@ -324,6 +326,8 @@ public partial class MAVLink new message_info(50003, "HERELINK_TELEM", 62, 19, 19, typeof( mavlink_herelink_telem_t )), new message_info(50004, "CUBEPILOT_FIRMWARE_UPDATE_START", 240, 10, 10, typeof( mavlink_cubepilot_firmware_update_start_t )), new message_info(50005, "CUBEPILOT_FIRMWARE_UPDATE_RESP", 152, 6, 6, typeof( mavlink_cubepilot_firmware_update_resp_t )), + new message_info(52000, "AIRLINK_AUTH", 13, 100, 100, typeof( mavlink_airlink_auth_t )), + new message_info(52001, "AIRLINK_AUTH_RESPONSE", 239, 1, 1, typeof( mavlink_airlink_auth_response_t )), new message_info(26900, "VIDEO_STREAM_INFORMATION99", 222, 246, 246, typeof( mavlink_video_stream_information99_t )), new message_info(0, "HEARTBEAT", 50, 9, 9, typeof( mavlink_heartbeat_t )), @@ -575,6 +579,7 @@ public enum MAVLINK_MSG_ID GIMBAL_DEVICE_ATTITUDE_STATUS = 285, AUTOPILOT_STATE_FOR_GIMBAL_DEVICE = 286, GIMBAL_MANAGER_SET_PITCHYAW = 287, + GIMBAL_MANAGER_SET_MANUAL_CONTROL = 288, WIFI_CONFIG_AP = 299, AIS_VESSEL = 301, UAVCAN_NODE_STATUS = 310, @@ -593,6 +598,7 @@ public enum MAVLINK_MSG_ID SMART_BATTERY_INFO = 370, GENERATOR_STATUS = 373, ACTUATOR_OUTPUT_STATUS = 375, + RELAY_STATUS = 376, TUNNEL = 385, CAN_FRAME = 386, CANFD_FRAME = 387, @@ -649,6 +655,8 @@ public enum MAVLINK_MSG_ID HERELINK_TELEM = 50003, CUBEPILOT_FIRMWARE_UPDATE_START = 50004, CUBEPILOT_FIRMWARE_UPDATE_RESP = 50005, + AIRLINK_AUTH = 52000, + AIRLINK_AUTH_RESPONSE = 52001, VIDEO_STREAM_INFORMATION99 = 26900, HEARTBEAT = 0, } @@ -696,18 +704,6 @@ public enum HEADING_TYPE: int /*default*/ }; - /// - public enum SPEED_TYPE: int /*default*/ - { - /// | - [Description("")] - AIRSPEED=0, - /// | - [Description("")] - GROUNDSPEED=1, - - }; - /// Commands to be executed by the MAV. They can be executed on user request, or as part of a mission script. If the action is used in a mission, the parameter mapping to the waypoint/mission message is as follows: Param 1, Param 2, Param 3, Param 4, X: Param 5, Y:Param 6, Z:Param 7. This command list is similar what ARINC 424 is for commercial aircraft: A data format how to interpret waypoint/mission data. NaN and INT32_MAX may be used in float/integer params (respectively) to indicate optional/default values (e.g. to use the component's current yaw or latitude rather than a specific value). See https://mavlink.io/en/guide/xml_schema.html#MAV_CMD for information about the structure of the MAV_CMD entries public enum MAV_CMD: ushort { @@ -809,7 +805,7 @@ public enum MAV_CMD: ushort /// Delay mission state machine until within desired distance of next NAV point. |Distance.| Empty| Empty| Empty| Empty| Empty| Empty| [Description("Delay mission state machine until within desired distance of next NAV point.")] CONDITION_DISTANCE=114, - /// Reach a certain target angle. |target angle, 0 is north| angular speed| direction: -1: counter clockwise, 1: clockwise| 0: absolute angle, 1: relative offset| Empty| Empty| Empty| + /// Reach a certain target angle. |target angle [0-360]. Absolute angles: 0 is north. Relative angle: 0 is initial yaw. Direction set by param3.| angular speed| direction: -1: counter clockwise, 0: shortest direction, 1: clockwise| 0: absolute angle, 1: relative offset| Empty| Empty| Empty| [Description("Reach a certain target angle.")] CONDITION_YAW=115, /// NOP - This command is only used to mark the upper limit of the CONDITION commands in the enumeration |Empty| Empty| Empty| Empty| Empty| Empty| Empty| @@ -821,8 +817,8 @@ public enum MAV_CMD: ushort /// Jump to the desired command in the mission list. Repeat this action only the specified number of times |Sequence number| Repeat count| Empty| Empty| Empty| Empty| Empty| [Description("Jump to the desired command in the mission list. Repeat this action only the specified number of times")] DO_JUMP=177, - /// Change speed and/or throttle set points. |Speed type (0=Airspeed, 1=Ground Speed, 2=Climb Speed, 3=Descent Speed)| Speed (-1 indicates no change, -2 indicates return to default vehicle speed)| Throttle (-1 indicates no change, -2 indicates return to default vehicle throttle value)| 0: absolute, 1: relative| Empty| Empty| Empty| - [Description("Change speed and/or throttle set points.")] + /// Change speed and/or throttle set points |Speed type of value set in param2 (such as airspeed, ground speed, and so on)| Speed (-1 indicates no change, -2 indicates return to default vehicle speed)| Throttle (-1 indicates no change, -2 indicates return to default vehicle throttle value)| 0: absolute, 1: relative| Empty| Empty| Empty| + [Description("Change speed and/or throttle set points")] DO_CHANGE_SPEED=178, /// Changes the home location either to the current location or a specified location. |Use current (1=use current location, 0=use specified location)| Empty| Empty| Empty| Latitude| Longitude| Altitude| [Description("Changes the home location either to the current location or a specified location.")] @@ -950,7 +946,7 @@ public enum MAV_CMD: ushort /// Set limits for external control |Timeout - maximum time that external controller will be allowed to control vehicle. 0 means no timeout.| Altitude (MSL) min - if vehicle moves below this alt, the command will be aborted and the mission will continue. 0 means no lower altitude limit.| Altitude (MSL) max - if vehicle moves above this alt, the command will be aborted and the mission will continue. 0 means no upper altitude limit.| Horizontal move limit - if vehicle moves more than this distance from its location at the moment the command was executed, the command will be aborted and the mission will continue. 0 means no horizontal move limit.| Empty| Empty| Empty| [Description("Set limits for external control")] DO_GUIDED_LIMITS=222, - /// Control vehicle engine. This is interpreted by the vehicles engine controller to change the target engine state. It is intended for vehicles with internal combustion engines |0: Stop engine, 1:Start Engine| 0: Warm start, 1:Cold start. Controls use of choke where applicable| Height delay. This is for commanding engine start only after the vehicle has gained the specified height. Used in VTOL vehicles during takeoff to start engine after the aircraft is off the ground. Zero for no delay.| Empty| Empty| Empty| Empty| + /// Control vehicle engine. This is interpreted by the vehicles engine controller to change the target engine state. It is intended for vehicles with internal combustion engines |0: Stop engine, 1:Start Engine| 0: Warm start, 1:Cold start. Controls use of choke where applicable| Height delay. This is for commanding engine start only after the vehicle has gained the specified height. Used in VTOL vehicles during takeoff to start engine after the aircraft is off the ground. Zero for no delay.| A bitmask of options for engine control| Empty| Empty| Empty| [Description("Control vehicle engine. This is interpreted by the vehicles engine controller to change the target engine state. It is intended for vehicles with internal combustion engines")] DO_ENGINE_CONTROL=223, /// Set the mission item with sequence number seq as current item. This means that the MAV will continue to this mission item on the shortest path (not following the mission items in-between). |Mission sequence value to set| Empty| Empty| Empty| Empty| Empty| Empty| @@ -1054,19 +1050,17 @@ public enum MAV_CMD: ushort /// Jump to the matching tag in the mission list. Repeat this action for the specified number of times. A mission should contain a single matching tag for each jump. If this is not the case then a jump to a missing tag should complete the mission, and a jump where there are multiple matching tags should always select the one with the lowest mission sequence number. |Target tag to jump to.| Repeat count.| Reserved (default:0)| Reserved (default:0)| Reserved (default:0)| Reserved (default:0)| Reserved (default:0)| [Description("Jump to the matching tag in the mission list. Repeat this action for the specified number of times. A mission should contain a single matching tag for each jump. If this is not the case then a jump to a missing tag should complete the mission, and a jump where there are multiple matching tags should always select the one with the lowest mission sequence number.")] DO_JUMP_TAG=601, - /// High level setpoint to be sent to a gimbal manager to set a gimbal attitude. It is possible to set combinations of the values below. E.g. an angle as well as a desired angular rate can be used to get to this angle at a certain angular rate, or an angular rate only will result in continuous turning. NaN is to be used to signal unset. Note: a gimbal is never to react to this command but only the gimbal manager. |Pitch angle (positive to pitch up, relative to vehicle for FOLLOW mode, relative to world horizon for LOCK mode).| Yaw angle (positive to yaw to the right, relative to vehicle for FOLLOW mode, absolute to North for LOCK mode).| Pitch rate (positive to pitch up).| Yaw rate (positive to yaw to the right).| Gimbal manager flags to use.| Reserved (default:0)| Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals).| - [Description("High level setpoint to be sent to a gimbal manager to set a gimbal attitude. It is possible to set combinations of the values below. E.g. an angle as well as a desired angular rate can be used to get to this angle at a certain angular rate, or an angular rate only will result in continuous turning. NaN is to be used to signal unset. Note: a gimbal is never to react to this command but only the gimbal manager.")] - [Obsolete] + /// Set gimbal manager pitch/yaw setpoints (low rate command). It is possible to set combinations of the values below. E.g. an angle as well as a desired angular rate can be used to get to this angle at a certain angular rate, or an angular rate only will result in continuous turning. NaN is to be used to signal unset. Note: only the gimbal manager will react to this command - it will be ignored by a gimbal device. Use GIMBAL_MANAGER_SET_PITCHYAW if you need to stream pitch/yaw setpoints at higher rate. |Pitch angle (positive to pitch up, relative to vehicle for FOLLOW mode, relative to world horizon for LOCK mode).| Yaw angle (positive to yaw to the right, relative to vehicle for FOLLOW mode, absolute to North for LOCK mode).| Pitch rate (positive to pitch up).| Yaw rate (positive to yaw to the right).| Gimbal manager flags to use.| Reserved (default:0)| Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals).| + [Description("Set gimbal manager pitch/yaw setpoints (low rate command). It is possible to set combinations of the values below. E.g. an angle as well as a desired angular rate can be used to get to this angle at a certain angular rate, or an angular rate only will result in continuous turning. NaN is to be used to signal unset. Note: only the gimbal manager will react to this command - it will be ignored by a gimbal device. Use GIMBAL_MANAGER_SET_PITCHYAW if you need to stream pitch/yaw setpoints at higher rate. ")] DO_GIMBAL_MANAGER_PITCHYAW=1000, /// Gimbal configuration to set which sysid/compid is in primary and secondary control. |Sysid for primary control (0: no one in control, -1: leave unchanged, -2: set itself in control (for missions where the own sysid is still unknown), -3: remove control if currently in control).| Compid for primary control (0: no one in control, -1: leave unchanged, -2: set itself in control (for missions where the own sysid is still unknown), -3: remove control if currently in control).| Sysid for secondary control (0: no one in control, -1: leave unchanged, -2: set itself in control (for missions where the own sysid is still unknown), -3: remove control if currently in control).| Compid for secondary control (0: no one in control, -1: leave unchanged, -2: set itself in control (for missions where the own sysid is still unknown), -3: remove control if currently in control).| Reserved (default:0)| Reserved (default:0)| Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals).| [Description("Gimbal configuration to set which sysid/compid is in primary and secondary control.")] - [Obsolete] DO_GIMBAL_MANAGER_CONFIGURE=1001, - /// Start image capture sequence. Sends CAMERA_IMAGE_CAPTURED after each capture. Use NaN for reserved values. |Reserved (Set to 0)| Desired elapsed time between two consecutive pictures (in seconds). Minimum values depend on hardware (typically greater than 2 seconds).| Total number of images to capture. 0 to capture forever/until MAV_CMD_IMAGE_STOP_CAPTURE.| Capture sequence number starting from 1. This is only valid for single-capture (param3 == 1), otherwise set to 0. Increment the capture ID for each capture command to prevent double captures when a command is re-transmitted.| Reserved (default:NaN)| Reserved (default:NaN)| Reserved (default:NaN)| - [Description("Start image capture sequence. Sends CAMERA_IMAGE_CAPTURED after each capture. Use NaN for reserved values.")] + /// Start image capture sequence. CAMERA_IMAGE_CAPTURED must be emitted after each capture. Param1 (id) may be used to specify the target camera: 0: all cameras, 1 to 6: autopilot-connected cameras, 7-255: MAVLink camera component ID. It is needed in order to target specific cameras connected to the autopilot, or specific sensors in a multi-sensor camera (neither of which have a distinct MAVLink component ID). It is also needed to specify the target camera in missions. When used in a mission, an autopilot should execute the MAV_CMD for a specified local camera (param1 = 1-6), or resend it as a command if it is intended for a MAVLink camera (param1 = 7 - 255), setting the command's target_component as the param1 value (and setting param1 in the command to zero). If the param1 is 0 the autopilot should do both. When sent in a command the target MAVLink address is set using target_component. If addressed specifically to an autopilot: param1 should be used in the same way as it is for missions (though command should NACK with MAV_RESULT_DENIED if a specified local camera does not exist). If addressed to a MAVLink camera, param 1 can be used to address all cameras (0), or to separately address 1 to 7 individual sensors. Other values should be NACKed with MAV_RESULT_DENIED. If the command is broadcast (target_component is 0) then param 1 should be set to 0 (any other value should be NACKED with MAV_RESULT_DENIED). An autopilot would trigger any local cameras and forward the command to all channels. |Target camera ID. 7 to 255: MAVLink camera component id. 1 to 6 for cameras that don't have a distinct component id (such as autopilot-attached cameras). 0: all cameras. This is used to specifically target autopilot-connected cameras or individual sensors in a multi-sensor MAVLink camera. It is also used to target specific cameras when the MAV_CMD is used in a mission| Desired elapsed time between two consecutive pictures (in seconds). Minimum values depend on hardware (typically greater than 2 seconds).| Total number of images to capture. 0 to capture forever/until MAV_CMD_IMAGE_STOP_CAPTURE.| Capture sequence number starting from 1. This is only valid for single-capture (param3 == 1), otherwise set to 0. Increment the capture ID for each capture command to prevent double captures when a command is re-transmitted.| Reserved (default:NaN)| Reserved (default:NaN)| Reserved (default:NaN)| + [Description("Start image capture sequence. CAMERA_IMAGE_CAPTURED must be emitted after each capture. Param1 (id) may be used to specify the target camera: 0: all cameras, 1 to 6: autopilot-connected cameras, 7-255: MAVLink camera component ID. It is needed in order to target specific cameras connected to the autopilot, or specific sensors in a multi-sensor camera (neither of which have a distinct MAVLink component ID). It is also needed to specify the target camera in missions. When used in a mission, an autopilot should execute the MAV_CMD for a specified local camera (param1 = 1-6), or resend it as a command if it is intended for a MAVLink camera (param1 = 7 - 255), setting the command's target_component as the param1 value (and setting param1 in the command to zero). If the param1 is 0 the autopilot should do both. When sent in a command the target MAVLink address is set using target_component. If addressed specifically to an autopilot: param1 should be used in the same way as it is for missions (though command should NACK with MAV_RESULT_DENIED if a specified local camera does not exist). If addressed to a MAVLink camera, param 1 can be used to address all cameras (0), or to separately address 1 to 7 individual sensors. Other values should be NACKed with MAV_RESULT_DENIED. If the command is broadcast (target_component is 0) then param 1 should be set to 0 (any other value should be NACKED with MAV_RESULT_DENIED). An autopilot would trigger any local cameras and forward the command to all channels. ")] IMAGE_START_CAPTURE=2000, - /// Stop image capture sequence Use NaN for reserved values. |Reserved (Set to 0)| Reserved (default:NaN)| Reserved (default:NaN)| Reserved (default:NaN)| Reserved (default:0)| Reserved (default:0)| Reserved (default:NaN)| - [Description("Stop image capture sequence Use NaN for reserved values.")] + /// Stop image capture sequence. Param1 (id) may be used to specify the target camera: 0: all cameras, 1 to 6: autopilot-connected cameras, 7-255: MAVLink camera component ID. It is needed in order to target specific cameras connected to the autopilot, or specific sensors in a multi-sensor camera (neither of which have a distinct MAVLink component ID). It is also needed to specify the target camera in missions. When used in a mission, an autopilot should execute the MAV_CMD for a specified local camera (param1 = 1-6), or resend it as a command if it is intended for a MAVLink camera (param1 = 7 - 255), setting the command's target_component as the param1 value (and setting param1 in the command to zero). If the param1 is 0 the autopilot should do both. When sent in a command the target MAVLink address is set using target_component. If addressed specifically to an autopilot: param1 should be used in the same way as it is for missions (though command should NACK with MAV_RESULT_DENIED if a specified local camera does not exist). If addressed to a MAVLink camera, param1 can be used to address all cameras (0), or to separately address 1 to 7 individual sensors. Other values should be NACKed with MAV_RESULT_DENIED. If the command is broadcast (target_component is 0) then param 1 should be set to 0 (any other value should be NACKED with MAV_RESULT_DENIED). An autopilot would trigger any local cameras and forward the command to all channels. |Target camera ID. 7 to 255: MAVLink camera component id. 1 to 6 for cameras that don't have a distinct component id (such as autopilot-attached cameras). 0: all cameras. This is used to specifically target autopilot-connected cameras or individual sensors in a multi-sensor MAVLink camera. It is also used to target specific cameras when the MAV_CMD is used in a mission| Reserved (default:NaN)| Reserved (default:NaN)| Reserved (default:NaN)| Reserved (default:0)| Reserved (default:0)| Reserved (default:NaN)| + [Description("Stop image capture sequence. Param1 (id) may be used to specify the target camera: 0: all cameras, 1 to 6: autopilot-connected cameras, 7-255: MAVLink camera component ID. It is needed in order to target specific cameras connected to the autopilot, or specific sensors in a multi-sensor camera (neither of which have a distinct MAVLink component ID). It is also needed to specify the target camera in missions. When used in a mission, an autopilot should execute the MAV_CMD for a specified local camera (param1 = 1-6), or resend it as a command if it is intended for a MAVLink camera (param1 = 7 - 255), setting the command's target_component as the param1 value (and setting param1 in the command to zero). If the param1 is 0 the autopilot should do both. When sent in a command the target MAVLink address is set using target_component. If addressed specifically to an autopilot: param1 should be used in the same way as it is for missions (though command should NACK with MAV_RESULT_DENIED if a specified local camera does not exist). If addressed to a MAVLink camera, param1 can be used to address all cameras (0), or to separately address 1 to 7 individual sensors. Other values should be NACKed with MAV_RESULT_DENIED. If the command is broadcast (target_component is 0) then param 1 should be set to 0 (any other value should be NACKED with MAV_RESULT_DENIED). An autopilot would trigger any local cameras and forward the command to all channels. ")] IMAGE_STOP_CAPTURE=2001, /// Enable or disable on-board camera triggering system. |Trigger enable/disable (0 for disable, 1 for start), -1 to ignore| 1 to reset the trigger sequence, -1 or 0 to ignore| 1 to pause triggering, but without switching the camera off or retracting it. -1 to ignore| Reserved (default:0)| Reserved (default:0)| Reserved (default:0)| Reserved (default:0)| [Description("Enable or disable on-board camera triggering system.")] @@ -2891,46 +2885,52 @@ public enum MAV_MOUNT_MODE: byte }; - /// Gimbal device (low level) capability flags (bitmap) + /// Gimbal device (low level) capability flags (bitmap). [Flags] public enum GIMBAL_DEVICE_CAP_FLAGS: ushort { - /// Gimbal device supports a retracted position | - [Description("Gimbal device supports a retracted position")] + /// Gimbal device supports a retracted position. | + [Description("Gimbal device supports a retracted position.")] HAS_RETRACT=1, - /// Gimbal device supports a horizontal, forward looking position, stabilized | - [Description("Gimbal device supports a horizontal, forward looking position, stabilized")] + /// Gimbal device supports a horizontal, forward looking position, stabilized. | + [Description("Gimbal device supports a horizontal, forward looking position, stabilized.")] HAS_NEUTRAL=2, /// Gimbal device supports rotating around roll axis. | [Description("Gimbal device supports rotating around roll axis.")] HAS_ROLL_AXIS=4, - /// Gimbal device supports to follow a roll angle relative to the vehicle | - [Description("Gimbal device supports to follow a roll angle relative to the vehicle")] + /// Gimbal device supports to follow a roll angle relative to the vehicle. | + [Description("Gimbal device supports to follow a roll angle relative to the vehicle.")] HAS_ROLL_FOLLOW=8, - /// Gimbal device supports locking to an roll angle (generally that's the default with roll stabilized) | - [Description("Gimbal device supports locking to an roll angle (generally that's the default with roll stabilized)")] + /// Gimbal device supports locking to a roll angle (generally that's the default with roll stabilized). | + [Description("Gimbal device supports locking to a roll angle (generally that's the default with roll stabilized).")] HAS_ROLL_LOCK=16, /// Gimbal device supports rotating around pitch axis. | [Description("Gimbal device supports rotating around pitch axis.")] HAS_PITCH_AXIS=32, - /// Gimbal device supports to follow a pitch angle relative to the vehicle | - [Description("Gimbal device supports to follow a pitch angle relative to the vehicle")] + /// Gimbal device supports to follow a pitch angle relative to the vehicle. | + [Description("Gimbal device supports to follow a pitch angle relative to the vehicle.")] HAS_PITCH_FOLLOW=64, - /// Gimbal device supports locking to an pitch angle (generally that's the default with pitch stabilized) | - [Description("Gimbal device supports locking to an pitch angle (generally that's the default with pitch stabilized)")] + /// Gimbal device supports locking to a pitch angle (generally that's the default with pitch stabilized). | + [Description("Gimbal device supports locking to a pitch angle (generally that's the default with pitch stabilized).")] HAS_PITCH_LOCK=128, /// Gimbal device supports rotating around yaw axis. | [Description("Gimbal device supports rotating around yaw axis.")] HAS_YAW_AXIS=256, - /// Gimbal device supports to follow a yaw angle relative to the vehicle (generally that's the default) | - [Description("Gimbal device supports to follow a yaw angle relative to the vehicle (generally that's the default)")] + /// Gimbal device supports to follow a yaw angle relative to the vehicle (generally that's the default). | + [Description("Gimbal device supports to follow a yaw angle relative to the vehicle (generally that's the default).")] HAS_YAW_FOLLOW=512, - /// Gimbal device supports locking to an absolute heading (often this is an option available) | - [Description("Gimbal device supports locking to an absolute heading (often this is an option available)")] + /// Gimbal device supports locking to an absolute heading, i.e., yaw angle relative to North (earth frame, often this is an option available). | + [Description("Gimbal device supports locking to an absolute heading, i.e., yaw angle relative to North (earth frame, often this is an option available).")] HAS_YAW_LOCK=1024, /// Gimbal device supports yawing/panning infinetely (e.g. using slip disk). | [Description("Gimbal device supports yawing/panning infinetely (e.g. using slip disk).")] SUPPORTS_INFINITE_YAW=2048, + /// Gimbal device supports yaw angles and angular velocities relative to North (earth frame). This usually requires support by an autopilot via AUTOPILOT_STATE_FOR_GIMBAL_DEVICE. Support can go on and off during runtime, which is reported by the flag GIMBAL_DEVICE_FLAGS_CAN_ACCEPT_YAW_IN_EARTH_FRAME. | + [Description("Gimbal device supports yaw angles and angular velocities relative to North (earth frame). This usually requires support by an autopilot via AUTOPILOT_STATE_FOR_GIMBAL_DEVICE. Support can go on and off during runtime, which is reported by the flag GIMBAL_DEVICE_FLAGS_CAN_ACCEPT_YAW_IN_EARTH_FRAME.")] + SUPPORTS_YAW_IN_EARTH_FRAME=4096, + /// Gimbal device supports radio control inputs as an alternative input for controlling the gimbal orientation. | + [Description("Gimbal device supports radio control inputs as an alternative input for controlling the gimbal orientation.")] + HAS_RC_INPUTS=8192, }; @@ -2996,18 +2996,33 @@ public enum GIMBAL_DEVICE_FLAGS: ushort /// Set to retracted safe position (no stabilization), takes presedence over all other flags. | [Description("Set to retracted safe position (no stabilization), takes presedence over all other flags.")] RETRACT=1, - /// Set to neutral/default position, taking precedence over all other flags except RETRACT. Neutral is commonly forward-facing and horizontal (pitch=yaw=0) but may be any orientation. | - [Description("Set to neutral/default position, taking precedence over all other flags except RETRACT. Neutral is commonly forward-facing and horizontal (pitch=yaw=0) but may be any orientation.")] + /// Set to neutral/default position, taking precedence over all other flags except RETRACT. Neutral is commonly forward-facing and horizontal (roll=pitch=yaw=0) but may be any orientation. | + [Description("Set to neutral/default position, taking precedence over all other flags except RETRACT. Neutral is commonly forward-facing and horizontal (roll=pitch=yaw=0) but may be any orientation.")] NEUTRAL=2, - /// Lock roll angle to absolute angle relative to horizon (not relative to drone). This is generally the default with a stabilizing gimbal. | - [Description("Lock roll angle to absolute angle relative to horizon (not relative to drone). This is generally the default with a stabilizing gimbal.")] + /// Lock roll angle to absolute angle relative to horizon (not relative to vehicle). This is generally the default with a stabilizing gimbal. | + [Description("Lock roll angle to absolute angle relative to horizon (not relative to vehicle). This is generally the default with a stabilizing gimbal.")] ROLL_LOCK=4, - /// Lock pitch angle to absolute angle relative to horizon (not relative to drone). This is generally the default. | - [Description("Lock pitch angle to absolute angle relative to horizon (not relative to drone). This is generally the default.")] + /// Lock pitch angle to absolute angle relative to horizon (not relative to vehicle). This is generally the default with a stabilizing gimbal. | + [Description("Lock pitch angle to absolute angle relative to horizon (not relative to vehicle). This is generally the default with a stabilizing gimbal.")] PITCH_LOCK=8, - /// Lock yaw angle to absolute angle relative to North (not relative to drone). If this flag is set, the quaternion is in the Earth frame with the x-axis pointing North (yaw absolute). If this flag is not set, the quaternion frame is in the Earth frame rotated so that the x-axis is pointing forward (yaw relative to vehicle). | - [Description("Lock yaw angle to absolute angle relative to North (not relative to drone). If this flag is set, the quaternion is in the Earth frame with the x-axis pointing North (yaw absolute). If this flag is not set, the quaternion frame is in the Earth frame rotated so that the x-axis is pointing forward (yaw relative to vehicle).")] + /// Lock yaw angle to absolute angle relative to North (not relative to vehicle). If this flag is set, the yaw angle and z component of angular velocity are relative to North (earth frame, x-axis pointing North), else they are relative to the vehicle heading (vehicle frame, earth frame rotated so that the x-axis is pointing forward). | + [Description("Lock yaw angle to absolute angle relative to North (not relative to vehicle). If this flag is set, the yaw angle and z component of angular velocity are relative to North (earth frame, x-axis pointing North), else they are relative to the vehicle heading (vehicle frame, earth frame rotated so that the x-axis is pointing forward).")] YAW_LOCK=16, + /// Yaw angle and z component of angular velocity are relative to the vehicle heading (vehicle frame, earth frame rotated such that the x-axis is pointing forward). | + [Description("Yaw angle and z component of angular velocity are relative to the vehicle heading (vehicle frame, earth frame rotated such that the x-axis is pointing forward).")] + YAW_IN_VEHICLE_FRAME=32, + /// Yaw angle and z component of angular velocity are relative to North (earth frame, x-axis is pointing North). | + [Description("Yaw angle and z component of angular velocity are relative to North (earth frame, x-axis is pointing North).")] + YAW_IN_EARTH_FRAME=64, + /// Gimbal device can accept yaw angle inputs relative to North (earth frame). This flag is only for reporting (attempts to set this flag are ignored). | + [Description("Gimbal device can accept yaw angle inputs relative to North (earth frame). This flag is only for reporting (attempts to set this flag are ignored).")] + ACCEPTS_YAW_IN_EARTH_FRAME=128, + /// The gimbal orientation is set exclusively by the RC signals feed to the gimbal's radio control inputs. MAVLink messages for setting the gimbal orientation (GIMBAL_DEVICE_SET_ATTITUDE) are ignored. | + [Description("The gimbal orientation is set exclusively by the RC signals feed to the gimbal's radio control inputs. MAVLink messages for setting the gimbal orientation (GIMBAL_DEVICE_SET_ATTITUDE) are ignored.")] + RC_EXCLUSIVE=256, + /// The gimbal orientation is determined by combining/mixing the RC signals feed to the gimbal's radio control inputs and the MAVLink messages for setting the gimbal orientation (GIMBAL_DEVICE_SET_ATTITUDE). How these two controls are combined or mixed is not defined by the protocol but is up to the implementation. | + [Description("The gimbal orientation is determined by combining/mixing the RC signals feed to the gimbal's radio control inputs and the MAVLink messages for setting the gimbal orientation (GIMBAL_DEVICE_SET_ATTITUDE). How these two controls are combined or mixed is not defined by the protocol but is up to the implementation.")] + RC_MIXED=512, }; @@ -3015,21 +3030,36 @@ public enum GIMBAL_DEVICE_FLAGS: ushort [Flags] public enum GIMBAL_MANAGER_FLAGS: uint { - /// Based on GIMBAL_DEVICE_FLAGS_RETRACT | - [Description("Based on GIMBAL_DEVICE_FLAGS_RETRACT")] + /// Based on GIMBAL_DEVICE_FLAGS_RETRACT. | + [Description("Based on GIMBAL_DEVICE_FLAGS_RETRACT.")] RETRACT=1, - /// Based on GIMBAL_DEVICE_FLAGS_NEUTRAL | - [Description("Based on GIMBAL_DEVICE_FLAGS_NEUTRAL")] + /// Based on GIMBAL_DEVICE_FLAGS_NEUTRAL. | + [Description("Based on GIMBAL_DEVICE_FLAGS_NEUTRAL.")] NEUTRAL=2, - /// Based on GIMBAL_DEVICE_FLAGS_ROLL_LOCK | - [Description("Based on GIMBAL_DEVICE_FLAGS_ROLL_LOCK")] + /// Based on GIMBAL_DEVICE_FLAGS_ROLL_LOCK. | + [Description("Based on GIMBAL_DEVICE_FLAGS_ROLL_LOCK.")] ROLL_LOCK=4, - /// Based on GIMBAL_DEVICE_FLAGS_PITCH_LOCK | - [Description("Based on GIMBAL_DEVICE_FLAGS_PITCH_LOCK")] + /// Based on GIMBAL_DEVICE_FLAGS_PITCH_LOCK. | + [Description("Based on GIMBAL_DEVICE_FLAGS_PITCH_LOCK.")] PITCH_LOCK=8, - /// Based on GIMBAL_DEVICE_FLAGS_YAW_LOCK | - [Description("Based on GIMBAL_DEVICE_FLAGS_YAW_LOCK")] + /// Based on GIMBAL_DEVICE_FLAGS_YAW_LOCK. | + [Description("Based on GIMBAL_DEVICE_FLAGS_YAW_LOCK.")] YAW_LOCK=16, + /// Based on GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME. | + [Description("Based on GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME.")] + YAW_IN_VEHICLE_FRAME=32, + /// Based on GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME. | + [Description("Based on GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME.")] + YAW_IN_EARTH_FRAME=64, + /// Based on GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME. | + [Description("Based on GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME.")] + ACCEPTS_YAW_IN_EARTH_FRAME=128, + /// Based on GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE. | + [Description("Based on GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE.")] + RC_EXCLUSIVE=256, + /// Based on GIMBAL_DEVICE_FLAGS_RC_MIXED. | + [Description("Based on GIMBAL_DEVICE_FLAGS_RC_MIXED.")] + RC_MIXED=512, }; @@ -3052,8 +3082,8 @@ public enum GIMBAL_DEVICE_ERROR_FLAGS: uint /// There is an error with the gimbal power source. | [Description("There is an error with the gimbal power source.")] POWER_ERROR=16, - /// There is an error with the gimbal motor's. | - [Description("There is an error with the gimbal motor's.")] + /// There is an error with the gimbal motors. | + [Description("There is an error with the gimbal motors.")] MOTOR_ERROR=32, /// There is an error with the gimbal's software. | [Description("There is an error with the gimbal's software.")] @@ -3061,9 +3091,12 @@ public enum GIMBAL_DEVICE_ERROR_FLAGS: uint /// There is an error with the gimbal's communication. | [Description("There is an error with the gimbal's communication.")] COMMS_ERROR=128, - /// Gimbal is currently calibrating. | - [Description("Gimbal is currently calibrating.")] + /// Gimbal device is currently calibrating. | + [Description("Gimbal device is currently calibrating.")] CALIBRATION_RUNNING=256, + /// Gimbal device is not assigned to a gimbal manager. | + [Description("Gimbal device is not assigned to a gimbal manager.")] + NO_MANAGER=512, }; @@ -3370,6 +3403,12 @@ public enum MAV_RESULT: byte /// Command is valid and is being executed. This will be followed by further progress updates, i.e. the component may send further COMMAND_ACK messages with result MAV_RESULT_IN_PROGRESS (at a rate decided by the implementation), and must terminate by sending a COMMAND_ACK message with final result of the operation. The COMMAND_ACK.progress field can be used to indicate the progress of the operation. There is no need for the sender to retry the command, but if done during execution, the component will return MAV_RESULT_IN_PROGRESS with an updated progress. | [Description("Command is valid and is being executed. This will be followed by further progress updates, i.e. the component may send further COMMAND_ACK messages with result MAV_RESULT_IN_PROGRESS (at a rate decided by the implementation), and must terminate by sending a COMMAND_ACK message with final result of the operation. The COMMAND_ACK.progress field can be used to indicate the progress of the operation. There is no need for the sender to retry the command, but if done during execution, the component will return MAV_RESULT_IN_PROGRESS with an updated progress.")] IN_PROGRESS=5, + /// Command is only accepted when sent as a COMMAND_LONG. | + [Description("Command is only accepted when sent as a COMMAND_LONG.")] + COMMAND_LONG_ONLY=7, + /// Command is only accepted when sent as a COMMAND_INT. | + [Description("Command is only accepted when sent as a COMMAND_INT.")] + COMMAND_INT_ONLY=8, }; @@ -4181,6 +4220,24 @@ public enum MAV_DO_REPOSITION_FLAGS: int /*default*/ }; + /// Speed setpoint types used in MAV_CMD_DO_CHANGE_SPEED + public enum SPEED_TYPE: int /*default*/ + { + /// Airspeed | + [Description("Airspeed")] + AIRSPEED=0, + /// Groundspeed | + [Description("Groundspeed")] + GROUNDSPEED=1, + /// Climb speed | + [Description("Climb speed")] + CLIMB_SPEED=2, + /// Descent speed | + [Description("Descent speed")] + DESCENT_SPEED=3, + + }; + /// Flags in ESTIMATOR_STATUS message [Flags] public enum ESTIMATOR_STATUS_FLAGS: ushort @@ -4663,6 +4720,15 @@ public enum RC_TYPE: int /*default*/ }; + /// Engine control options + public enum ENGINE_CONTROL_OPTIONS: int /*default*/ + { + /// Allow starting the engine once while disarmed | + [Description("Allow starting the engine once while disarmed")] + ALLOW_START_WHILE_DISARMED=1, + + }; + /// Bitmap to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 9 is set the floats afx afy afz should be interpreted as force instead of acceleration. public enum POSITION_TARGET_TYPEMASK: ushort { @@ -6152,6 +6218,19 @@ public enum ICAROUS_FMS_STATE: byte + /// + public enum AIRLINK_AUTH_RESPONSE_TYPE: byte + { + /// Login or password error | + [Description("Login or password error")] + AIRLINK_ERROR_LOGIN_OR_PASS=0, + /// Auth successful | + [Description("Auth successful")] + AIRLINK_AUTH_OK=1, + + }; + + /// Micro air vehicle / autopilot classes. This identifies the individual model. public enum MAV_AUTOPILOT: byte { @@ -15991,13 +16070,13 @@ public static mavlink_data_stream_t PopulateXMLOrder(byte stream_id,ushort messa }; - /// extensions_start 0 - [StructLayout(LayoutKind.Sequential,Pack=1,Size=11)] + /// extensions_start 6 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=30)] /// This message provides an API for manually controlling the vehicle using standard joystick axes nomenclature, along with a joystick-like input device. Unused axes can be disabled an buttons are also transmit as boolean values of their public struct mavlink_manual_control_t { /// packet ordered constructor - public mavlink_manual_control_t(short x,short y,short z,short r,ushort buttons,byte target) + public mavlink_manual_control_t(short x,short y,short z,short r,ushort buttons,byte target,ushort buttons2,byte enabled_extensions,short s,short t,short aux1,short aux2,short aux3,short aux4,short aux5,short aux6) { this.x = x; this.y = y; @@ -16005,11 +16084,21 @@ public mavlink_manual_control_t(short x,short y,short z,short r,ushort buttons,b this.r = r; this.buttons = buttons; this.target = target; + this.buttons2 = buttons2; + this.enabled_extensions = enabled_extensions; + this.s = s; + this.t = t; + this.aux1 = aux1; + this.aux2 = aux2; + this.aux3 = aux3; + this.aux4 = aux4; + this.aux5 = aux5; + this.aux6 = aux6; } /// packet xml order - public static mavlink_manual_control_t PopulateXMLOrder(byte target,short x,short y,short z,short r,ushort buttons) + public static mavlink_manual_control_t PopulateXMLOrder(byte target,short x,short y,short z,short r,ushort buttons,ushort buttons2,byte enabled_extensions,short s,short t,short aux1,short aux2,short aux3,short aux4,short aux5,short aux6) { var msg = new mavlink_manual_control_t(); @@ -16019,6 +16108,16 @@ public static mavlink_manual_control_t PopulateXMLOrder(byte target,short x,shor msg.z = z; msg.r = r; msg.buttons = buttons; + msg.buttons2 = buttons2; + msg.enabled_extensions = enabled_extensions; + msg.s = s; + msg.t = t; + msg.aux1 = aux1; + msg.aux2 = aux2; + msg.aux3 = aux3; + msg.aux4 = aux4; + msg.aux5 = aux5; + msg.aux6 = aux6; return msg; } @@ -16059,6 +16158,66 @@ public static mavlink_manual_control_t PopulateXMLOrder(byte target,short x,shor [Description("The system to be controlled.")] //[FieldOffset(10)] public byte target; + + /// A bitfield corresponding to the joystick buttons' 16-31 current state, 1 for pressed, 0 for released. The lowest bit corresponds to Button 16. + [Units("")] + [Description("A bitfield corresponding to the joystick buttons' 16-31 current state, 1 for pressed, 0 for released. The lowest bit corresponds to Button 16.")] + //[FieldOffset(11)] + public ushort buttons2; + + /// Set bits to 1 to indicate which of the following extension fields contain valid data: bit 0: pitch, bit 1: roll, bit 2: aux1, bit 3: aux2, bit 4: aux3, bit 5: aux4, bit 6: aux5, bit 7: aux6 + [Units("")] + [Description("Set bits to 1 to indicate which of the following extension fields contain valid data: bit 0: pitch, bit 1: roll, bit 2: aux1, bit 3: aux2, bit 4: aux3, bit 5: aux4, bit 6: aux5, bit 7: aux6")] + //[FieldOffset(13)] + public byte enabled_extensions; + + /// Pitch-only-axis, normalized to the range [-1000,1000]. Generally corresponds to pitch on vehicles with additional degrees of freedom. Valid if bit 0 of enabled_extensions field is set. Set to 0 if invalid. + [Units("")] + [Description("Pitch-only-axis, normalized to the range [-1000,1000]. Generally corresponds to pitch on vehicles with additional degrees of freedom. Valid if bit 0 of enabled_extensions field is set. Set to 0 if invalid.")] + //[FieldOffset(14)] + public short s; + + /// Roll-only-axis, normalized to the range [-1000,1000]. Generally corresponds to roll on vehicles with additional degrees of freedom. Valid if bit 1 of enabled_extensions field is set. Set to 0 if invalid. + [Units("")] + [Description("Roll-only-axis, normalized to the range [-1000,1000]. Generally corresponds to roll on vehicles with additional degrees of freedom. Valid if bit 1 of enabled_extensions field is set. Set to 0 if invalid.")] + //[FieldOffset(16)] + public short t; + + /// Aux continuous input field 1. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 2 of enabled_extensions field is set. 0 if bit 2 is unset. + [Units("")] + [Description("Aux continuous input field 1. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 2 of enabled_extensions field is set. 0 if bit 2 is unset.")] + //[FieldOffset(18)] + public short aux1; + + /// Aux continuous input field 2. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 3 of enabled_extensions field is set. 0 if bit 3 is unset. + [Units("")] + [Description("Aux continuous input field 2. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 3 of enabled_extensions field is set. 0 if bit 3 is unset.")] + //[FieldOffset(20)] + public short aux2; + + /// Aux continuous input field 3. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 4 of enabled_extensions field is set. 0 if bit 4 is unset. + [Units("")] + [Description("Aux continuous input field 3. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 4 of enabled_extensions field is set. 0 if bit 4 is unset.")] + //[FieldOffset(22)] + public short aux3; + + /// Aux continuous input field 4. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 5 of enabled_extensions field is set. 0 if bit 5 is unset. + [Units("")] + [Description("Aux continuous input field 4. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 5 of enabled_extensions field is set. 0 if bit 5 is unset.")] + //[FieldOffset(24)] + public short aux4; + + /// Aux continuous input field 5. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 6 of enabled_extensions field is set. 0 if bit 6 is unset. + [Units("")] + [Description("Aux continuous input field 5. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 6 of enabled_extensions field is set. 0 if bit 6 is unset.")] + //[FieldOffset(26)] + public short aux5; + + /// Aux continuous input field 6. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 7 of enabled_extensions field is set. 0 if bit 7 is unset. + [Units("")] + [Description("Aux continuous input field 6. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 7 of enabled_extensions field is set. 0 if bit 7 is unset.")] + //[FieldOffset(28)] + public short aux6; }; @@ -18192,15 +18351,15 @@ public static mavlink_optical_flow_t PopulateXMLOrder(ulong time_usec,byte senso //[FieldOffset(16)] public float ground_distance; - /// Flow in x-sensor direction [dpix] - [Units("[dpix]")] - [Description("Flow in x-sensor direction")] + /// Flow rate around X-axis (deprecated; use flow_rate_x) [rad/s] + [Units("[rad/s]")] + [Description("Flow rate around X-axis (deprecated; use flow_rate_x)")] //[FieldOffset(20)] public short flow_x; - /// Flow in y-sensor direction [dpix] - [Units("[dpix]")] - [Description("Flow in y-sensor direction")] + /// Flow rate around Y-axis (deprecated; use flow_rate_y) [rad/s] + [Units("[rad/s]")] + [Description("Flow rate around Y-axis (deprecated; use flow_rate_y)")] //[FieldOffset(22)] public short flow_y; @@ -19003,13 +19162,13 @@ public static mavlink_hil_sensor_t PopulateXMLOrder(ulong time_usec,float xacc,f }; - /// extensions_start 0 - [StructLayout(LayoutKind.Sequential,Pack=1,Size=84)] + /// extensions_start 21 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=92)] /// Status of simulation environment, if used public struct mavlink_sim_state_t { /// packet ordered constructor - public mavlink_sim_state_t(float q1,float q2,float q3,float q4,float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro,float lat,float lon,float alt,float std_dev_horz,float std_dev_vert,float vn,float ve,float vd) + public mavlink_sim_state_t(float q1,float q2,float q3,float q4,float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro,float lat,float lon,float alt,float std_dev_horz,float std_dev_vert,float vn,float ve,float vd,int lat_int,int lon_int) { this.q1 = q1; this.q2 = q2; @@ -19032,11 +19191,13 @@ public mavlink_sim_state_t(float q1,float q2,float q3,float q4,float roll,float this.vn = vn; this.ve = ve; this.vd = vd; + this.lat_int = lat_int; + this.lon_int = lon_int; } /// packet xml order - public static mavlink_sim_state_t PopulateXMLOrder(float q1,float q2,float q3,float q4,float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro,float lat,float lon,float alt,float std_dev_horz,float std_dev_vert,float vn,float ve,float vd) + public static mavlink_sim_state_t PopulateXMLOrder(float q1,float q2,float q3,float q4,float roll,float pitch,float yaw,float xacc,float yacc,float zacc,float xgyro,float ygyro,float zgyro,float lat,float lon,float alt,float std_dev_horz,float std_dev_vert,float vn,float ve,float vd,int lat_int,int lon_int) { var msg = new mavlink_sim_state_t(); @@ -19061,6 +19222,8 @@ public static mavlink_sim_state_t PopulateXMLOrder(float q1,float q2,float q3,fl msg.vn = vn; msg.ve = ve; msg.vd = vd; + msg.lat_int = lat_int; + msg.lon_int = lon_int; return msg; } @@ -19191,6 +19354,18 @@ public static mavlink_sim_state_t PopulateXMLOrder(float q1,float q2,float q3,fl [Description("True velocity in down direction in earth-fixed NED frame")] //[FieldOffset(80)] public float vd; + + /// Latitude (higher precision). If 0, recipients should use the lat field value (otherwise this field is preferred). [degE7] + [Units("[degE7]")] + [Description("Latitude (higher precision). If 0, recipients should use the lat field value (otherwise this field is preferred).")] + //[FieldOffset(84)] + public int lat_int; + + /// Longitude (higher precision). If 0, recipients should use the lon field value (otherwise this field is preferred). [degE7] + [Units("[degE7]")] + [Description("Longitude (higher precision). If 0, recipients should use the lon field value (otherwise this field is preferred).")] + //[FieldOffset(88)] + public int lon_int; }; @@ -24978,13 +25153,13 @@ public static mavlink_play_tune_t PopulateXMLOrder(byte target_system,byte targe }; - /// extensions_start 0 - [StructLayout(LayoutKind.Sequential,Pack=1,Size=235)] + /// extensions_start 13 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=236)] /// Information about a camera. Can be requested with a MAV_CMD_REQUEST_MESSAGE command. public struct mavlink_camera_information_t { /// packet ordered constructor - public mavlink_camera_information_t(uint time_boot_ms,uint firmware_version,float focal_length,float sensor_size_h,float sensor_size_v,/*CAMERA_CAP_FLAGS*/uint flags,ushort resolution_h,ushort resolution_v,ushort cam_definition_version,byte[] vendor_name,byte[] model_name,byte lens_id,byte[] cam_definition_uri) + public mavlink_camera_information_t(uint time_boot_ms,uint firmware_version,float focal_length,float sensor_size_h,float sensor_size_v,/*CAMERA_CAP_FLAGS*/uint flags,ushort resolution_h,ushort resolution_v,ushort cam_definition_version,byte[] vendor_name,byte[] model_name,byte lens_id,byte[] cam_definition_uri,byte gimbal_device_id) { this.time_boot_ms = time_boot_ms; this.firmware_version = firmware_version; @@ -24999,11 +25174,12 @@ public mavlink_camera_information_t(uint time_boot_ms,uint firmware_version,floa this.model_name = model_name; this.lens_id = lens_id; this.cam_definition_uri = cam_definition_uri; + this.gimbal_device_id = gimbal_device_id; } /// packet xml order - public static mavlink_camera_information_t PopulateXMLOrder(uint time_boot_ms,byte[] vendor_name,byte[] model_name,uint firmware_version,float focal_length,float sensor_size_h,float sensor_size_v,ushort resolution_h,ushort resolution_v,byte lens_id,/*CAMERA_CAP_FLAGS*/uint flags,ushort cam_definition_version,byte[] cam_definition_uri) + public static mavlink_camera_information_t PopulateXMLOrder(uint time_boot_ms,byte[] vendor_name,byte[] model_name,uint firmware_version,float focal_length,float sensor_size_h,float sensor_size_v,ushort resolution_h,ushort resolution_v,byte lens_id,/*CAMERA_CAP_FLAGS*/uint flags,ushort cam_definition_version,byte[] cam_definition_uri,byte gimbal_device_id) { var msg = new mavlink_camera_information_t(); @@ -25020,6 +25196,7 @@ public static mavlink_camera_information_t PopulateXMLOrder(uint time_boot_ms,by msg.flags = flags; msg.cam_definition_version = cam_definition_version; msg.cam_definition_uri = cam_definition_uri; + msg.gimbal_device_id = gimbal_device_id; return msg; } @@ -25105,6 +25282,12 @@ public static mavlink_camera_information_t PopulateXMLOrder(uint time_boot_ms,by //[FieldOffset(95)] [MarshalAs(UnmanagedType.ByValArray,SizeConst=140)] public byte[] cam_definition_uri; + + /// Gimbal id of a gimbal associated with this camera. This is the component id of the gimbal device, or 1-6 for non mavlink gimbals. Use 0 if no gimbal is associated with the camera. + [Units("")] + [Description("Gimbal id of a gimbal associated with this camera. This is the component id of the gimbal device, or 1-6 for non mavlink gimbals. Use 0 if no gimbal is associated with the camera.")] + //[FieldOffset(235)] + public byte gimbal_device_id; }; @@ -26317,7 +26500,7 @@ public static mavlink_camera_tracking_geo_status_t PopulateXMLOrder(/*CAMERA_TRA public /*CAMERA_TRACKING_STATUS_FLAGS*/byte tracking_status; }; - [Obsolete] + /// extensions_start 0 [StructLayout(LayoutKind.Sequential,Pack=1,Size=33)] /// Information about a high level gimbal manager. This message should be requested by a ground station using MAV_CMD_REQUEST_MESSAGE. @@ -26405,14 +26588,14 @@ public static mavlink_gimbal_manager_information_t PopulateXMLOrder(uint time_bo //[FieldOffset(28)] public float yaw_max; - /// Gimbal device ID that this gimbal manager is responsible for. + /// Gimbal device ID that this gimbal manager is responsible for. Component ID of gimbal device (or 1-6 for non-MAVLink gimbal). [Units("")] - [Description("Gimbal device ID that this gimbal manager is responsible for.")] + [Description("Gimbal device ID that this gimbal manager is responsible for. Component ID of gimbal device (or 1-6 for non-MAVLink gimbal).")] //[FieldOffset(32)] public byte gimbal_device_id; }; - [Obsolete] + /// extensions_start 0 [StructLayout(LayoutKind.Sequential,Pack=1,Size=13)] /// Current status about a high level gimbal manager. This message should be broadcast at a low regular rate (e.g. 5Hz). @@ -26454,15 +26637,15 @@ public static mavlink_gimbal_manager_status_t PopulateXMLOrder(uint time_boot_ms //[FieldOffset(0)] public uint time_boot_ms; - /// High level gimbal manager flags currently applied. GIMBAL_MANAGER_FLAGS + /// High level gimbal manager flags currently applied. GIMBAL_MANAGER_FLAGS bitmask [Units("")] [Description("High level gimbal manager flags currently applied.")] //[FieldOffset(4)] public /*GIMBAL_MANAGER_FLAGS*/uint flags; - /// Gimbal device ID that this gimbal manager is responsible for. + /// Gimbal device ID that this gimbal manager is responsible for. Component ID of gimbal device (or 1-6 for non-MAVLink gimbal). [Units("")] - [Description("Gimbal device ID that this gimbal manager is responsible for.")] + [Description("Gimbal device ID that this gimbal manager is responsible for. Component ID of gimbal device (or 1-6 for non-MAVLink gimbal).")] //[FieldOffset(8)] public byte gimbal_device_id; @@ -26493,12 +26676,100 @@ public static mavlink_gimbal_manager_status_t PopulateXMLOrder(uint time_boot_ms /// extensions_start 0 - [StructLayout(LayoutKind.Sequential,Pack=1,Size=144)] + [StructLayout(LayoutKind.Sequential,Pack=1,Size=35)] + /// High level message to control a gimbal's attitude. This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. + public struct mavlink_gimbal_manager_set_attitude_t + { + /// packet ordered constructor + public mavlink_gimbal_manager_set_attitude_t(/*GIMBAL_MANAGER_FLAGS*/uint flags,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z,byte target_system,byte target_component,byte gimbal_device_id) + { + this.flags = flags; + this.q = q; + this.angular_velocity_x = angular_velocity_x; + this.angular_velocity_y = angular_velocity_y; + this.angular_velocity_z = angular_velocity_z; + this.target_system = target_system; + this.target_component = target_component; + this.gimbal_device_id = gimbal_device_id; + + } + + /// packet xml order + public static mavlink_gimbal_manager_set_attitude_t PopulateXMLOrder(byte target_system,byte target_component,/*GIMBAL_MANAGER_FLAGS*/uint flags,byte gimbal_device_id,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z) + { + var msg = new mavlink_gimbal_manager_set_attitude_t(); + + msg.target_system = target_system; + msg.target_component = target_component; + msg.flags = flags; + msg.gimbal_device_id = gimbal_device_id; + msg.q = q; + msg.angular_velocity_x = angular_velocity_x; + msg.angular_velocity_y = angular_velocity_y; + msg.angular_velocity_z = angular_velocity_z; + + return msg; + } + + + /// High level gimbal manager flags to use. GIMBAL_MANAGER_FLAGS + [Units("")] + [Description("High level gimbal manager flags to use.")] + //[FieldOffset(0)] + public /*GIMBAL_MANAGER_FLAGS*/uint flags; + + /// Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_MANAGER_FLAGS_YAW_LOCK is set) + [Units("")] + [Description("Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_MANAGER_FLAGS_YAW_LOCK is set)")] + //[FieldOffset(4)] + [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] + public float[] q; + + /// X component of angular velocity, positive is rolling to the right, NaN to be ignored. [rad/s] + [Units("[rad/s]")] + [Description("X component of angular velocity, positive is rolling to the right, NaN to be ignored.")] + //[FieldOffset(20)] + public float angular_velocity_x; + + /// Y component of angular velocity, positive is pitching up, NaN to be ignored. [rad/s] + [Units("[rad/s]")] + [Description("Y component of angular velocity, positive is pitching up, NaN to be ignored.")] + //[FieldOffset(24)] + public float angular_velocity_y; + + /// Z component of angular velocity, positive is yawing to the right, NaN to be ignored. [rad/s] + [Units("[rad/s]")] + [Description("Z component of angular velocity, positive is yawing to the right, NaN to be ignored.")] + //[FieldOffset(28)] + public float angular_velocity_z; + + /// System ID + [Units("")] + [Description("System ID")] + //[FieldOffset(32)] + public byte target_system; + + /// Component ID + [Units("")] + [Description("Component ID")] + //[FieldOffset(33)] + public byte target_component; + + /// Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals). + [Units("")] + [Description("Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals).")] + //[FieldOffset(34)] + public byte gimbal_device_id; + }; + + + /// extensions_start 15 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=145)] /// Information about a low level gimbal. This message should be requested by the gimbal manager or a ground station using MAV_CMD_REQUEST_MESSAGE. The maximum angles and rates are the limits by hardware. However, the limits by software used are likely different/smaller and dependent on mode/settings/etc.. public struct mavlink_gimbal_device_information_t { /// packet ordered constructor - public mavlink_gimbal_device_information_t(ulong uid,uint time_boot_ms,uint firmware_version,uint hardware_version,float roll_min,float roll_max,float pitch_min,float pitch_max,float yaw_min,float yaw_max,/*GIMBAL_DEVICE_CAP_FLAGS*/ushort cap_flags,ushort custom_cap_flags,byte[] vendor_name,byte[] model_name,byte[] custom_name) + public mavlink_gimbal_device_information_t(ulong uid,uint time_boot_ms,uint firmware_version,uint hardware_version,float roll_min,float roll_max,float pitch_min,float pitch_max,float yaw_min,float yaw_max,/*GIMBAL_DEVICE_CAP_FLAGS*/ushort cap_flags,ushort custom_cap_flags,byte[] vendor_name,byte[] model_name,byte[] custom_name,byte gimbal_device_id) { this.uid = uid; this.time_boot_ms = time_boot_ms; @@ -26515,11 +26786,12 @@ public mavlink_gimbal_device_information_t(ulong uid,uint time_boot_ms,uint firm this.vendor_name = vendor_name; this.model_name = model_name; this.custom_name = custom_name; + this.gimbal_device_id = gimbal_device_id; } /// packet xml order - public static mavlink_gimbal_device_information_t PopulateXMLOrder(uint time_boot_ms,byte[] vendor_name,byte[] model_name,byte[] custom_name,uint firmware_version,uint hardware_version,ulong uid,/*GIMBAL_DEVICE_CAP_FLAGS*/ushort cap_flags,ushort custom_cap_flags,float roll_min,float roll_max,float pitch_min,float pitch_max,float yaw_min,float yaw_max) + public static mavlink_gimbal_device_information_t PopulateXMLOrder(uint time_boot_ms,byte[] vendor_name,byte[] model_name,byte[] custom_name,uint firmware_version,uint hardware_version,ulong uid,/*GIMBAL_DEVICE_CAP_FLAGS*/ushort cap_flags,ushort custom_cap_flags,float roll_min,float roll_max,float pitch_min,float pitch_max,float yaw_min,float yaw_max,byte gimbal_device_id) { var msg = new mavlink_gimbal_device_information_t(); @@ -26538,6 +26810,7 @@ public static mavlink_gimbal_device_information_t PopulateXMLOrder(uint time_boo msg.pitch_max = pitch_max; msg.yaw_min = yaw_min; msg.yaw_max = yaw_max; + msg.gimbal_device_id = gimbal_device_id; return msg; } @@ -26567,39 +26840,39 @@ public static mavlink_gimbal_device_information_t PopulateXMLOrder(uint time_boo //[FieldOffset(16)] public uint hardware_version; - /// Minimum hardware roll angle (positive: rolling to the right, negative: rolling to the left) [rad] + /// Minimum hardware roll angle (positive: rolling to the right, negative: rolling to the left). NAN if unknown. [rad] [Units("[rad]")] - [Description("Minimum hardware roll angle (positive: rolling to the right, negative: rolling to the left)")] + [Description("Minimum hardware roll angle (positive: rolling to the right, negative: rolling to the left). NAN if unknown.")] //[FieldOffset(20)] public float roll_min; - /// Maximum hardware roll angle (positive: rolling to the right, negative: rolling to the left) [rad] + /// Maximum hardware roll angle (positive: rolling to the right, negative: rolling to the left). NAN if unknown. [rad] [Units("[rad]")] - [Description("Maximum hardware roll angle (positive: rolling to the right, negative: rolling to the left)")] + [Description("Maximum hardware roll angle (positive: rolling to the right, negative: rolling to the left). NAN if unknown.")] //[FieldOffset(24)] public float roll_max; - /// Minimum hardware pitch angle (positive: up, negative: down) [rad] + /// Minimum hardware pitch angle (positive: up, negative: down). NAN if unknown. [rad] [Units("[rad]")] - [Description("Minimum hardware pitch angle (positive: up, negative: down)")] + [Description("Minimum hardware pitch angle (positive: up, negative: down). NAN if unknown.")] //[FieldOffset(28)] public float pitch_min; - /// Maximum hardware pitch angle (positive: up, negative: down) [rad] + /// Maximum hardware pitch angle (positive: up, negative: down). NAN if unknown. [rad] [Units("[rad]")] - [Description("Maximum hardware pitch angle (positive: up, negative: down)")] + [Description("Maximum hardware pitch angle (positive: up, negative: down). NAN if unknown.")] //[FieldOffset(32)] public float pitch_max; - /// Minimum hardware yaw angle (positive: to the right, negative: to the left) [rad] + /// Minimum hardware yaw angle (positive: to the right, negative: to the left). NAN if unknown. [rad] [Units("[rad]")] - [Description("Minimum hardware yaw angle (positive: to the right, negative: to the left)")] + [Description("Minimum hardware yaw angle (positive: to the right, negative: to the left). NAN if unknown.")] //[FieldOffset(36)] public float yaw_min; - /// Maximum hardware yaw angle (positive: to the right, negative: to the left) [rad] + /// Maximum hardware yaw angle (positive: to the right, negative: to the left). NAN if unknown. [rad] [Units("[rad]")] - [Description("Maximum hardware yaw angle (positive: to the right, negative: to the left)")] + [Description("Maximum hardware yaw angle (positive: to the right, negative: to the left). NAN if unknown.")] //[FieldOffset(40)] public float yaw_max; @@ -26635,12 +26908,18 @@ public static mavlink_gimbal_device_information_t PopulateXMLOrder(uint time_boo //[FieldOffset(112)] [MarshalAs(UnmanagedType.ByValArray,SizeConst=32)] public byte[] custom_name; + + /// This field is to be used if the gimbal manager and the gimbal device are the same component and hence have the same component ID. This field is then set to a number between 1-6. If the component ID is separate, this field is not required and must be set to 0. + [Units("")] + [Description("This field is to be used if the gimbal manager and the gimbal device are the same component and hence have the same component ID. This field is then set to a number between 1-6. If the component ID is separate, this field is not required and must be set to 0.")] + //[FieldOffset(144)] + public byte gimbal_device_id; }; - [Obsolete] + /// extensions_start 0 [StructLayout(LayoutKind.Sequential,Pack=1,Size=32)] - /// Low level message to control a gimbal device's attitude. This message is to be sent from the gimbal manager to the gimbal device component. Angles and rates can be set to NaN according to use case. + /// Low level message to control a gimbal device's attitude. This message is to be sent from the gimbal manager to the gimbal device component. The quaternion and angular velocities can be set to NaN according to use case. For the angles encoded in the quaternion and the angular velocities holds: If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME is set, then they are relative to the vehicle heading (vehicle frame). If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME is set, then they are relative to absolute North (earth frame). If neither of these flags are set, then (for backwards compatibility) it holds: If the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set, then they are relative to absolute North (earth frame), else they are relative to the vehicle heading (vehicle frame). Setting both GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME and GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME is not allowed. These rules are to ensure backwards compatibility. New implementations should always set either GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME or GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME. public struct mavlink_gimbal_device_set_attitude_t { /// packet ordered constructor @@ -26673,28 +26952,28 @@ public static mavlink_gimbal_device_set_attitude_t PopulateXMLOrder(byte target_ } - /// Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set, set all fields to NaN if only angular velocity should be used) + /// Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation). The frame is described in the message description. Set fields to NaN to be ignored. [Units("")] - [Description("Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set, set all fields to NaN if only angular velocity should be used)")] + [Description("Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation). The frame is described in the message description. Set fields to NaN to be ignored.")] //[FieldOffset(0)] [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public float[] q; - /// X component of angular velocity, positive is rolling to the right, NaN to be ignored. [rad/s] + /// X component of angular velocity (positive: rolling to the right). The frame is described in the message description. NaN to be ignored. [rad/s] [Units("[rad/s]")] - [Description("X component of angular velocity, positive is rolling to the right, NaN to be ignored.")] + [Description("X component of angular velocity (positive: rolling to the right). The frame is described in the message description. NaN to be ignored.")] //[FieldOffset(16)] public float angular_velocity_x; - /// Y component of angular velocity, positive is pitching up, NaN to be ignored. [rad/s] + /// Y component of angular velocity (positive: pitching up). The frame is described in the message description. NaN to be ignored. [rad/s] [Units("[rad/s]")] - [Description("Y component of angular velocity, positive is pitching up, NaN to be ignored.")] + [Description("Y component of angular velocity (positive: pitching up). The frame is described in the message description. NaN to be ignored.")] //[FieldOffset(20)] public float angular_velocity_y; - /// Z component of angular velocity, positive is yawing to the right, NaN to be ignored. [rad/s] + /// Z component of angular velocity (positive: yawing to the right). The frame is described in the message description. NaN to be ignored. [rad/s] [Units("[rad/s]")] - [Description("Z component of angular velocity, positive is yawing to the right, NaN to be ignored.")] + [Description("Z component of angular velocity (positive: yawing to the right). The frame is described in the message description. NaN to be ignored.")] //[FieldOffset(24)] public float angular_velocity_z; @@ -26717,14 +26996,14 @@ public static mavlink_gimbal_device_set_attitude_t PopulateXMLOrder(byte target_ public byte target_component; }; - [Obsolete] - /// extensions_start 0 - [StructLayout(LayoutKind.Sequential,Pack=1,Size=40)] - /// Message reporting the status of a gimbal device. This message should be broadcasted by a gimbal device component. The angles encoded in the quaternion are relative to absolute North if the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set (roll: positive is rolling to the right, pitch: positive is pitching up, yaw is turn to the right) or relative to the vehicle heading if the flag is not set. This message should be broadcast at a low regular rate (e.g. 10Hz). + + /// extensions_start 9 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=49)] + /// Message reporting the status of a gimbal device. This message should be broadcast by a gimbal device component at a low regular rate (e.g. 5 Hz). For the angles encoded in the quaternion and the angular velocities holds: If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME is set, then they are relative to the vehicle heading (vehicle frame). If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME is set, then they are relative to absolute North (earth frame). If neither of these flags are set, then (for backwards compatibility) it holds: If the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set, then they are relative to absolute North (earth frame), else they are relative to the vehicle heading (vehicle frame). Other conditions of the flags are not allowed. The quaternion and angular velocities in the other frame can be calculated from delta_yaw and delta_yaw_velocity as q_earth = q_delta_yaw * q_vehicle and w_earth = w_delta_yaw_velocity + w_vehicle (if not NaN). If neither the GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME nor the GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME flag is set, then (for backwards compatibility) the data in the delta_yaw and delta_yaw_velocity fields are to be ignored. New implementations should always set either GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME or GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME, and always should set delta_yaw and delta_yaw_velocity either to the proper value or NaN. public struct mavlink_gimbal_device_attitude_status_t { /// packet ordered constructor - public mavlink_gimbal_device_attitude_status_t(uint time_boot_ms,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z,/*GIMBAL_DEVICE_ERROR_FLAGS*/uint failure_flags,/*GIMBAL_DEVICE_FLAGS*/ushort flags,byte target_system,byte target_component) + public mavlink_gimbal_device_attitude_status_t(uint time_boot_ms,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z,/*GIMBAL_DEVICE_ERROR_FLAGS*/uint failure_flags,/*GIMBAL_DEVICE_FLAGS*/ushort flags,byte target_system,byte target_component,float delta_yaw,float delta_yaw_velocity,byte gimbal_device_id) { this.time_boot_ms = time_boot_ms; this.q = q; @@ -26735,11 +27014,14 @@ public mavlink_gimbal_device_attitude_status_t(uint time_boot_ms,float[] q,float this.flags = flags; this.target_system = target_system; this.target_component = target_component; + this.delta_yaw = delta_yaw; + this.delta_yaw_velocity = delta_yaw_velocity; + this.gimbal_device_id = gimbal_device_id; } /// packet xml order - public static mavlink_gimbal_device_attitude_status_t PopulateXMLOrder(byte target_system,byte target_component,uint time_boot_ms,/*GIMBAL_DEVICE_FLAGS*/ushort flags,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z,/*GIMBAL_DEVICE_ERROR_FLAGS*/uint failure_flags) + public static mavlink_gimbal_device_attitude_status_t PopulateXMLOrder(byte target_system,byte target_component,uint time_boot_ms,/*GIMBAL_DEVICE_FLAGS*/ushort flags,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z,/*GIMBAL_DEVICE_ERROR_FLAGS*/uint failure_flags,float delta_yaw,float delta_yaw_velocity,byte gimbal_device_id) { var msg = new mavlink_gimbal_device_attitude_status_t(); @@ -26752,6 +27034,9 @@ public static mavlink_gimbal_device_attitude_status_t PopulateXMLOrder(byte targ msg.angular_velocity_y = angular_velocity_y; msg.angular_velocity_z = angular_velocity_z; msg.failure_flags = failure_flags; + msg.delta_yaw = delta_yaw; + msg.delta_yaw_velocity = delta_yaw_velocity; + msg.gimbal_device_id = gimbal_device_id; return msg; } @@ -26763,28 +27048,28 @@ public static mavlink_gimbal_device_attitude_status_t PopulateXMLOrder(byte targ //[FieldOffset(0)] public uint time_boot_ms; - /// Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set) + /// Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation). The frame is described in the message description. [Units("")] - [Description("Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set)")] + [Description("Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation). The frame is described in the message description.")] //[FieldOffset(4)] [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public float[] q; - /// X component of angular velocity (NaN if unknown) [rad/s] + /// X component of angular velocity (positive: rolling to the right). The frame is described in the message description. NaN if unknown. [rad/s] [Units("[rad/s]")] - [Description("X component of angular velocity (NaN if unknown)")] + [Description("X component of angular velocity (positive: rolling to the right). The frame is described in the message description. NaN if unknown.")] //[FieldOffset(20)] public float angular_velocity_x; - /// Y component of angular velocity (NaN if unknown) [rad/s] + /// Y component of angular velocity (positive: pitching up). The frame is described in the message description. NaN if unknown. [rad/s] [Units("[rad/s]")] - [Description("Y component of angular velocity (NaN if unknown)")] + [Description("Y component of angular velocity (positive: pitching up). The frame is described in the message description. NaN if unknown.")] //[FieldOffset(24)] public float angular_velocity_y; - /// Z component of angular velocity (NaN if unknown) [rad/s] + /// Z component of angular velocity (positive: yawing to the right). The frame is described in the message description. NaN if unknown. [rad/s] [Units("[rad/s]")] - [Description("Z component of angular velocity (NaN if unknown)")] + [Description("Z component of angular velocity (positive: yawing to the right). The frame is described in the message description. NaN if unknown.")] //[FieldOffset(28)] public float angular_velocity_z; @@ -26811,16 +27096,34 @@ public static mavlink_gimbal_device_attitude_status_t PopulateXMLOrder(byte targ [Description("Component ID")] //[FieldOffset(39)] public byte target_component; + + /// Yaw angle relating the quaternions in earth and body frames (see message description). NaN if unknown. [rad] + [Units("[rad]")] + [Description("Yaw angle relating the quaternions in earth and body frames (see message description). NaN if unknown.")] + //[FieldOffset(40)] + public float delta_yaw; + + /// Yaw angular velocity relating the angular velocities in earth and body frames (see message description). NaN if unknown. [rad/s] + [Units("[rad/s]")] + [Description("Yaw angular velocity relating the angular velocities in earth and body frames (see message description). NaN if unknown.")] + //[FieldOffset(44)] + public float delta_yaw_velocity; + + /// This field is to be used if the gimbal manager and the gimbal device are the same component and hence have the same component ID. This field is then set a number between 1-6. If the component ID is separate, this field is not required and must be set to 0. + [Units("")] + [Description("This field is to be used if the gimbal manager and the gimbal device are the same component and hence have the same component ID. This field is then set a number between 1-6. If the component ID is separate, this field is not required and must be set to 0.")] + //[FieldOffset(48)] + public byte gimbal_device_id; }; - /// extensions_start 0 - [StructLayout(LayoutKind.Sequential,Pack=1,Size=53)] - /// Low level message containing autopilot state relevant for a gimbal device. This message is to be sent from the gimbal manager to the gimbal device component. The data of this message server for the gimbal's estimator corrections in particular horizon compensation, as well as the autopilot's control intention e.g. feed forward angular control in z-axis. + /// extensions_start 12 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=57)] + /// Low level message containing autopilot state relevant for a gimbal device. This message is to be sent from the autopilot to the gimbal device component. The data of this message are for the gimbal device's estimator corrections, in particular horizon compensation, as well as indicates autopilot control intentions, e.g. feed forward angular control in the z-axis. public struct mavlink_autopilot_state_for_gimbal_device_t { /// packet ordered constructor - public mavlink_autopilot_state_for_gimbal_device_t(ulong time_boot_us,float[] q,uint q_estimated_delay_us,float vx,float vy,float vz,uint v_estimated_delay_us,float feed_forward_angular_velocity_z,/*ESTIMATOR_STATUS_FLAGS*/ushort estimator_status,byte target_system,byte target_component,/*MAV_LANDED_STATE*/byte landed_state) + public mavlink_autopilot_state_for_gimbal_device_t(ulong time_boot_us,float[] q,uint q_estimated_delay_us,float vx,float vy,float vz,uint v_estimated_delay_us,float feed_forward_angular_velocity_z,/*ESTIMATOR_STATUS_FLAGS*/ushort estimator_status,byte target_system,byte target_component,/*MAV_LANDED_STATE*/byte landed_state,float angular_velocity_z) { this.time_boot_us = time_boot_us; this.q = q; @@ -26834,11 +27137,12 @@ public mavlink_autopilot_state_for_gimbal_device_t(ulong time_boot_us,float[] q, this.target_system = target_system; this.target_component = target_component; this.landed_state = landed_state; + this.angular_velocity_z = angular_velocity_z; } /// packet xml order - public static mavlink_autopilot_state_for_gimbal_device_t PopulateXMLOrder(byte target_system,byte target_component,ulong time_boot_us,float[] q,uint q_estimated_delay_us,float vx,float vy,float vz,uint v_estimated_delay_us,float feed_forward_angular_velocity_z,/*ESTIMATOR_STATUS_FLAGS*/ushort estimator_status,/*MAV_LANDED_STATE*/byte landed_state) + public static mavlink_autopilot_state_for_gimbal_device_t PopulateXMLOrder(byte target_system,byte target_component,ulong time_boot_us,float[] q,uint q_estimated_delay_us,float vx,float vy,float vz,uint v_estimated_delay_us,float feed_forward_angular_velocity_z,/*ESTIMATOR_STATUS_FLAGS*/ushort estimator_status,/*MAV_LANDED_STATE*/byte landed_state,float angular_velocity_z) { var msg = new mavlink_autopilot_state_for_gimbal_device_t(); @@ -26854,6 +27158,7 @@ public static mavlink_autopilot_state_for_gimbal_device_t PopulateXMLOrder(byte msg.feed_forward_angular_velocity_z = feed_forward_angular_velocity_z; msg.estimator_status = estimator_status; msg.landed_state = landed_state; + msg.angular_velocity_z = angular_velocity_z; return msg; } @@ -26872,39 +27177,39 @@ public static mavlink_autopilot_state_for_gimbal_device_t PopulateXMLOrder(byte [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] public float[] q; - /// Estimated delay of the attitude data. [us] + /// Estimated delay of the attitude data. 0 if unknown. [us] [Units("[us]")] - [Description("Estimated delay of the attitude data.")] + [Description("Estimated delay of the attitude data. 0 if unknown.")] //[FieldOffset(24)] public uint q_estimated_delay_us; - /// X Speed in NED (North, East, Down). [m/s] + /// X Speed in NED (North, East, Down). NAN if unknown. [m/s] [Units("[m/s]")] - [Description("X Speed in NED (North, East, Down).")] + [Description("X Speed in NED (North, East, Down). NAN if unknown.")] //[FieldOffset(28)] public float vx; - /// Y Speed in NED (North, East, Down). [m/s] + /// Y Speed in NED (North, East, Down). NAN if unknown. [m/s] [Units("[m/s]")] - [Description("Y Speed in NED (North, East, Down).")] + [Description("Y Speed in NED (North, East, Down). NAN if unknown.")] //[FieldOffset(32)] public float vy; - /// Z Speed in NED (North, East, Down). [m/s] + /// Z Speed in NED (North, East, Down). NAN if unknown. [m/s] [Units("[m/s]")] - [Description("Z Speed in NED (North, East, Down).")] + [Description("Z Speed in NED (North, East, Down). NAN if unknown.")] //[FieldOffset(36)] public float vz; - /// Estimated delay of the speed data. [us] + /// Estimated delay of the speed data. 0 if unknown. [us] [Units("[us]")] - [Description("Estimated delay of the speed data.")] + [Description("Estimated delay of the speed data. 0 if unknown.")] //[FieldOffset(40)] public uint v_estimated_delay_us; - /// Feed forward Z component of angular velocity, positive is yawing to the right, NaN to be ignored. This is to indicate if the autopilot is actively yawing. [rad/s] + /// Feed forward Z component of angular velocity (positive: yawing to the right). NaN to be ignored. This is to indicate if the autopilot is actively yawing. [rad/s] [Units("[rad/s]")] - [Description("Feed forward Z component of angular velocity, positive is yawing to the right, NaN to be ignored. This is to indicate if the autopilot is actively yawing.")] + [Description("Feed forward Z component of angular velocity (positive: yawing to the right). NaN to be ignored. This is to indicate if the autopilot is actively yawing.")] //[FieldOffset(44)] public float feed_forward_angular_velocity_z; @@ -26931,22 +27236,28 @@ public static mavlink_autopilot_state_for_gimbal_device_t PopulateXMLOrder(byte [Description("The landed state. Is set to MAV_LANDED_STATE_UNDEFINED if landed state is unknown.")] //[FieldOffset(52)] public /*MAV_LANDED_STATE*/byte landed_state; + + /// Z component of angular velocity in NED (North, East, Down). NaN if unknown. [rad/s] + [Units("[rad/s]")] + [Description("Z component of angular velocity in NED (North, East, Down). NaN if unknown.")] + //[FieldOffset(53)] + public float angular_velocity_z; }; - [Obsolete] + /// extensions_start 0 - [StructLayout(LayoutKind.Sequential,Pack=1,Size=35)] - /// High level message to control a gimbal's attitude. This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. - public struct mavlink_gimbal_manager_set_attitude_t + [StructLayout(LayoutKind.Sequential,Pack=1,Size=23)] + /// Set gimbal manager pitch and yaw angles (high rate message). This message is to be sent to the gimbal manager (e.g. from a ground station) and will be ignored by gimbal devices. Angles and rates can be set to NaN according to use case. Use MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW for low-rate adjustments that require confirmation. + public struct mavlink_gimbal_manager_set_pitchyaw_t { /// packet ordered constructor - public mavlink_gimbal_manager_set_attitude_t(/*GIMBAL_MANAGER_FLAGS*/uint flags,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z,byte target_system,byte target_component,byte gimbal_device_id) + public mavlink_gimbal_manager_set_pitchyaw_t(/*GIMBAL_MANAGER_FLAGS*/uint flags,float pitch,float yaw,float pitch_rate,float yaw_rate,byte target_system,byte target_component,byte gimbal_device_id) { this.flags = flags; - this.q = q; - this.angular_velocity_x = angular_velocity_x; - this.angular_velocity_y = angular_velocity_y; - this.angular_velocity_z = angular_velocity_z; + this.pitch = pitch; + this.yaw = yaw; + this.pitch_rate = pitch_rate; + this.yaw_rate = yaw_rate; this.target_system = target_system; this.target_component = target_component; this.gimbal_device_id = gimbal_device_id; @@ -26954,18 +27265,18 @@ public mavlink_gimbal_manager_set_attitude_t(/*GIMBAL_MANAGER_FLAGS*/uint flags, } /// packet xml order - public static mavlink_gimbal_manager_set_attitude_t PopulateXMLOrder(byte target_system,byte target_component,/*GIMBAL_MANAGER_FLAGS*/uint flags,byte gimbal_device_id,float[] q,float angular_velocity_x,float angular_velocity_y,float angular_velocity_z) + public static mavlink_gimbal_manager_set_pitchyaw_t PopulateXMLOrder(byte target_system,byte target_component,/*GIMBAL_MANAGER_FLAGS*/uint flags,byte gimbal_device_id,float pitch,float yaw,float pitch_rate,float yaw_rate) { - var msg = new mavlink_gimbal_manager_set_attitude_t(); + var msg = new mavlink_gimbal_manager_set_pitchyaw_t(); msg.target_system = target_system; msg.target_component = target_component; msg.flags = flags; msg.gimbal_device_id = gimbal_device_id; - msg.q = q; - msg.angular_velocity_x = angular_velocity_x; - msg.angular_velocity_y = angular_velocity_y; - msg.angular_velocity_z = angular_velocity_z; + msg.pitch = pitch; + msg.yaw = yaw; + msg.pitch_rate = pitch_rate; + msg.yaw_rate = yaw_rate; return msg; } @@ -26977,58 +27288,57 @@ public static mavlink_gimbal_manager_set_attitude_t PopulateXMLOrder(byte target //[FieldOffset(0)] public /*GIMBAL_MANAGER_FLAGS*/uint flags; - /// Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_MANAGER_FLAGS_YAW_LOCK is set) - [Units("")] - [Description("Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_MANAGER_FLAGS_YAW_LOCK is set)")] + /// Pitch angle (positive: up, negative: down, NaN to be ignored). [rad] + [Units("[rad]")] + [Description("Pitch angle (positive: up, negative: down, NaN to be ignored).")] //[FieldOffset(4)] - [MarshalAs(UnmanagedType.ByValArray,SizeConst=4)] - public float[] q; + public float pitch; - /// X component of angular velocity, positive is rolling to the right, NaN to be ignored. [rad/s] - [Units("[rad/s]")] - [Description("X component of angular velocity, positive is rolling to the right, NaN to be ignored.")] - //[FieldOffset(20)] - public float angular_velocity_x; + /// Yaw angle (positive: to the right, negative: to the left, NaN to be ignored). [rad] + [Units("[rad]")] + [Description("Yaw angle (positive: to the right, negative: to the left, NaN to be ignored).")] + //[FieldOffset(8)] + public float yaw; - /// Y component of angular velocity, positive is pitching up, NaN to be ignored. [rad/s] + /// Pitch angular rate (positive: up, negative: down, NaN to be ignored). [rad/s] [Units("[rad/s]")] - [Description("Y component of angular velocity, positive is pitching up, NaN to be ignored.")] - //[FieldOffset(24)] - public float angular_velocity_y; + [Description("Pitch angular rate (positive: up, negative: down, NaN to be ignored).")] + //[FieldOffset(12)] + public float pitch_rate; - /// Z component of angular velocity, positive is yawing to the right, NaN to be ignored. [rad/s] + /// Yaw angular rate (positive: to the right, negative: to the left, NaN to be ignored). [rad/s] [Units("[rad/s]")] - [Description("Z component of angular velocity, positive is yawing to the right, NaN to be ignored.")] - //[FieldOffset(28)] - public float angular_velocity_z; + [Description("Yaw angular rate (positive: to the right, negative: to the left, NaN to be ignored).")] + //[FieldOffset(16)] + public float yaw_rate; /// System ID [Units("")] [Description("System ID")] - //[FieldOffset(32)] + //[FieldOffset(20)] public byte target_system; /// Component ID [Units("")] [Description("Component ID")] - //[FieldOffset(33)] + //[FieldOffset(21)] public byte target_component; /// Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals). [Units("")] [Description("Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals).")] - //[FieldOffset(34)] + //[FieldOffset(22)] public byte gimbal_device_id; }; - [Obsolete] + /// extensions_start 0 [StructLayout(LayoutKind.Sequential,Pack=1,Size=23)] - /// High level message to control a gimbal's pitch and yaw angles. This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. - public struct mavlink_gimbal_manager_set_pitchyaw_t + /// High level message to control a gimbal manually. The angles or angular rates are unitless; the actual rates will depend on internal gimbal manager settings/configuration (e.g. set by parameters). This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. + public struct mavlink_gimbal_manager_set_manual_control_t { /// packet ordered constructor - public mavlink_gimbal_manager_set_pitchyaw_t(/*GIMBAL_MANAGER_FLAGS*/uint flags,float pitch,float yaw,float pitch_rate,float yaw_rate,byte target_system,byte target_component,byte gimbal_device_id) + public mavlink_gimbal_manager_set_manual_control_t(/*GIMBAL_MANAGER_FLAGS*/uint flags,float pitch,float yaw,float pitch_rate,float yaw_rate,byte target_system,byte target_component,byte gimbal_device_id) { this.flags = flags; this.pitch = pitch; @@ -27042,9 +27352,9 @@ public mavlink_gimbal_manager_set_pitchyaw_t(/*GIMBAL_MANAGER_FLAGS*/uint flags, } /// packet xml order - public static mavlink_gimbal_manager_set_pitchyaw_t PopulateXMLOrder(byte target_system,byte target_component,/*GIMBAL_MANAGER_FLAGS*/uint flags,byte gimbal_device_id,float pitch,float yaw,float pitch_rate,float yaw_rate) + public static mavlink_gimbal_manager_set_manual_control_t PopulateXMLOrder(byte target_system,byte target_component,/*GIMBAL_MANAGER_FLAGS*/uint flags,byte gimbal_device_id,float pitch,float yaw,float pitch_rate,float yaw_rate) { - var msg = new mavlink_gimbal_manager_set_pitchyaw_t(); + var msg = new mavlink_gimbal_manager_set_manual_control_t(); msg.target_system = target_system; msg.target_component = target_component; @@ -27059,33 +27369,33 @@ public static mavlink_gimbal_manager_set_pitchyaw_t PopulateXMLOrder(byte target } - /// High level gimbal manager flags to use. GIMBAL_MANAGER_FLAGS + /// High level gimbal manager flags. GIMBAL_MANAGER_FLAGS [Units("")] - [Description("High level gimbal manager flags to use.")] + [Description("High level gimbal manager flags.")] //[FieldOffset(0)] public /*GIMBAL_MANAGER_FLAGS*/uint flags; - /// Pitch angle (positive: up, negative: down, NaN to be ignored). [rad] - [Units("[rad]")] - [Description("Pitch angle (positive: up, negative: down, NaN to be ignored).")] + /// Pitch angle unitless (-1..1, positive: up, negative: down, NaN to be ignored). + [Units("")] + [Description("Pitch angle unitless (-1..1, positive: up, negative: down, NaN to be ignored).")] //[FieldOffset(4)] public float pitch; - /// Yaw angle (positive: to the right, negative: to the left, NaN to be ignored). [rad] - [Units("[rad]")] - [Description("Yaw angle (positive: to the right, negative: to the left, NaN to be ignored).")] + /// Yaw angle unitless (-1..1, positive: to the right, negative: to the left, NaN to be ignored). + [Units("")] + [Description("Yaw angle unitless (-1..1, positive: to the right, negative: to the left, NaN to be ignored).")] //[FieldOffset(8)] public float yaw; - /// Pitch angular rate (positive: up, negative: down, NaN to be ignored). [rad/s] - [Units("[rad/s]")] - [Description("Pitch angular rate (positive: up, negative: down, NaN to be ignored).")] + /// Pitch angular rate unitless (-1..1, positive: up, negative: down, NaN to be ignored). + [Units("")] + [Description("Pitch angular rate unitless (-1..1, positive: up, negative: down, NaN to be ignored).")] //[FieldOffset(12)] public float pitch_rate; - /// Yaw angular rate (positive: to the right, negative: to the left, NaN to be ignored). [rad/s] - [Units("[rad/s]")] - [Description("Yaw angular rate (positive: to the right, negative: to the left, NaN to be ignored).")] + /// Yaw angular rate unitless (-1..1, positive: to the right, negative: to the left, NaN to be ignored). + [Units("")] + [Description("Yaw angular rate unitless (-1..1, positive: to the right, negative: to the left, NaN to be ignored).")] //[FieldOffset(16)] public float yaw_rate; @@ -28699,6 +29009,53 @@ public static mavlink_actuator_output_status_t PopulateXMLOrder(ulong time_usec, }; + /// extensions_start 0 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=8)] + /// Reports the on/off state of relays, as controlled by MAV_CMD_DO_SET_RELAY. + public struct mavlink_relay_status_t + { + /// packet ordered constructor + public mavlink_relay_status_t(uint time_boot_ms,ushort on,ushort present) + { + this.time_boot_ms = time_boot_ms; + this.on = on; + this.present = present; + + } + + /// packet xml order + public static mavlink_relay_status_t PopulateXMLOrder(uint time_boot_ms,ushort on,ushort present) + { + var msg = new mavlink_relay_status_t(); + + msg.time_boot_ms = time_boot_ms; + msg.on = on; + msg.present = present; + + return msg; + } + + + /// Timestamp (time since system boot). [ms] + [Units("[ms]")] + [Description("Timestamp (time since system boot).")] + //[FieldOffset(0)] + public uint time_boot_ms; + + /// Relay states. Relay instance numbers are represented as individual bits in this mask by offset. bitmask + [Units("")] + [Description("Relay states. Relay instance numbers are represented as individual bits in this mask by offset.")] + //[FieldOffset(4)] + public ushort on; + + /// Relay present. Relay instance numbers are represented as individual bits in this mask by offset. Bits will be true if a relay instance is configured. bitmask + [Units("")] + [Description("Relay present. Relay instance numbers are represented as individual bits in this mask by offset. Bits will be true if a relay instance is configured.")] + //[FieldOffset(6)] + public ushort present; + }; + + /// extensions_start 0 [StructLayout(LayoutKind.Sequential,Pack=1,Size=133)] /// Message for transporting 'arbitrary' variable-length data from one component to another (broadcast is not forbidden, but discouraged). The encoding of the data is usually extension specific, i.e. determined by the source, and is usually not documented as part of the MAVLink specification. @@ -31164,6 +31521,78 @@ public static mavlink_cubepilot_firmware_update_resp_t PopulateXMLOrder(byte tar }; + /// extensions_start 0 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=100)] + /// Authorization package + public struct mavlink_airlink_auth_t + { + /// packet ordered constructor + public mavlink_airlink_auth_t(byte[] login,byte[] password) + { + this.login = login; + this.password = password; + + } + + /// packet xml order + public static mavlink_airlink_auth_t PopulateXMLOrder(byte[] login,byte[] password) + { + var msg = new mavlink_airlink_auth_t(); + + msg.login = login; + msg.password = password; + + return msg; + } + + + /// Login + [Units("")] + [Description("Login")] + //[FieldOffset(0)] + [MarshalAs(UnmanagedType.ByValArray,SizeConst=50)] + public byte[] login; + + /// Password + [Units("")] + [Description("Password")] + //[FieldOffset(50)] + [MarshalAs(UnmanagedType.ByValArray,SizeConst=50)] + public byte[] password; + }; + + + /// extensions_start 0 + [StructLayout(LayoutKind.Sequential,Pack=1,Size=1)] + /// Response to the authorization request + public struct mavlink_airlink_auth_response_t + { + /// packet ordered constructor + public mavlink_airlink_auth_response_t(/*AIRLINK_AUTH_RESPONSE_TYPE*/byte resp_type) + { + this.resp_type = resp_type; + + } + + /// packet xml order + public static mavlink_airlink_auth_response_t PopulateXMLOrder(/*AIRLINK_AUTH_RESPONSE_TYPE*/byte resp_type) + { + var msg = new mavlink_airlink_auth_response_t(); + + msg.resp_type = resp_type; + + return msg; + } + + + /// Response type AIRLINK_AUTH_RESPONSE_TYPE + [Units("")] + [Description("Response type")] + //[FieldOffset(0)] + public /*AIRLINK_AUTH_RESPONSE_TYPE*/byte resp_type; + }; + + /// extensions_start 0 [StructLayout(LayoutKind.Sequential,Pack=1,Size=9)] /// The heartbeat message shows that a system or component is present and responding. The type and autopilot fields (along with the message component id), allow the receiving system to treat further messages from this system appropriately (e.g. by laying out the user interface based on the autopilot). This microservice is documented at https://mavlink.io/en/services/heartbeat.html diff --git a/ExtLibs/Mavlink/mavlink.lua b/ExtLibs/Mavlink/mavlink.lua index 30017a3c44..c6b3556565 100644 --- a/ExtLibs/Mavlink/mavlink.lua +++ b/ExtLibs/Mavlink/mavlink.lua @@ -252,12 +252,13 @@ messageName = { [276] = 'CAMERA_TRACKING_GEO_STATUS', [280] = 'GIMBAL_MANAGER_INFORMATION', [281] = 'GIMBAL_MANAGER_STATUS', + [282] = 'GIMBAL_MANAGER_SET_ATTITUDE', [283] = 'GIMBAL_DEVICE_INFORMATION', [284] = 'GIMBAL_DEVICE_SET_ATTITUDE', [285] = 'GIMBAL_DEVICE_ATTITUDE_STATUS', [286] = 'AUTOPILOT_STATE_FOR_GIMBAL_DEVICE', - [282] = 'GIMBAL_MANAGER_SET_ATTITUDE', [287] = 'GIMBAL_MANAGER_SET_PITCHYAW', + [288] = 'GIMBAL_MANAGER_SET_MANUAL_CONTROL', [299] = 'WIFI_CONFIG_AP', [301] = 'AIS_VESSEL', [310] = 'UAVCAN_NODE_STATUS', @@ -276,6 +277,7 @@ messageName = { [370] = 'SMART_BATTERY_INFO', [373] = 'GENERATOR_STATUS', [375] = 'ACTUATOR_OUTPUT_STATUS', + [376] = 'RELAY_STATUS', [385] = 'TUNNEL', [386] = 'CAN_FRAME', [387] = 'CANFD_FRAME', @@ -308,6 +310,8 @@ messageName = { [50003] = 'HERELINK_TELEM', [50004] = 'CUBEPILOT_FIRMWARE_UPDATE_START', [50005] = 'CUBEPILOT_FIRMWARE_UPDATE_RESP', + [52000] = 'AIRLINK_AUTH', + [52001] = 'AIRLINK_AUTH_RESPONSE', [0] = 'HEARTBEAT', } @@ -326,10 +330,6 @@ local enumEntryName = { [0] = "HEADING_TYPE_COURSE_OVER_GROUND", [1] = "HEADING_TYPE_HEADING", }, - ["SPEED_TYPE"] = { - [0] = "SPEED_TYPE_AIRSPEED", - [1] = "SPEED_TYPE_GROUNDSPEED", - }, ["MAV_CMD"] = { [16] = "MAV_CMD_NAV_WAYPOINT", [17] = "MAV_CMD_NAV_LOITER_UNLIM", @@ -1047,6 +1047,8 @@ local enumEntryName = { [512] = "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW", [1024] = "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK", [2048] = "GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW", + [4096] = "GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_YAW_IN_EARTH_FRAME", + [8192] = "GIMBAL_DEVICE_CAP_FLAGS_HAS_RC_INPUTS", }, ["GIMBAL_MANAGER_CAP_FLAGS"] = { [1] = "GIMBAL_MANAGER_CAP_FLAGS_HAS_RETRACT", @@ -1072,6 +1074,11 @@ local enumEntryName = { [4] = "GIMBAL_DEVICE_FLAGS_ROLL_LOCK", [8] = "GIMBAL_DEVICE_FLAGS_PITCH_LOCK", [16] = "GIMBAL_DEVICE_FLAGS_YAW_LOCK", + [32] = "GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME", + [64] = "GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME", + [128] = "GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", + [256] = "GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE", + [512] = "GIMBAL_DEVICE_FLAGS_RC_MIXED", }, ["GIMBAL_MANAGER_FLAGS"] = { [1] = "GIMBAL_MANAGER_FLAGS_RETRACT", @@ -1079,6 +1086,11 @@ local enumEntryName = { [4] = "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", [8] = "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", [16] = "GIMBAL_MANAGER_FLAGS_YAW_LOCK", + [32] = "GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", + [64] = "GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", + [128] = "GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", + [256] = "GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", + [512] = "GIMBAL_MANAGER_FLAGS_RC_MIXED", }, ["GIMBAL_DEVICE_ERROR_FLAGS"] = { [1] = "GIMBAL_DEVICE_ERROR_FLAGS_AT_ROLL_LIMIT", @@ -1090,6 +1102,7 @@ local enumEntryName = { [64] = "GIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR", [128] = "GIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR", [256] = "GIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING", + [512] = "GIMBAL_DEVICE_ERROR_FLAGS_NO_MANAGER", }, ["GRIPPER_ACTIONS"] = { [0] = "GRIPPER_ACTION_RELEASE", @@ -1192,6 +1205,8 @@ local enumEntryName = { [3] = "MAV_RESULT_UNSUPPORTED", [4] = "MAV_RESULT_FAILED", [5] = "MAV_RESULT_IN_PROGRESS", + [7] = "MAV_RESULT_COMMAND_LONG_ONLY", + [8] = "MAV_RESULT_COMMAND_INT_ONLY", }, ["MAV_MISSION_RESULT"] = { [0] = "MAV_MISSION_ACCEPTED", @@ -1460,6 +1475,12 @@ local enumEntryName = { ["MAV_DO_REPOSITION_FLAGS"] = { [1] = "MAV_DO_REPOSITION_FLAGS_CHANGE_MODE", }, + ["SPEED_TYPE"] = { + [0] = "SPEED_TYPE_AIRSPEED", + [1] = "SPEED_TYPE_GROUNDSPEED", + [2] = "SPEED_TYPE_CLIMB_SPEED", + [3] = "SPEED_TYPE_DESCENT_SPEED", + }, ["ESTIMATOR_STATUS_FLAGS"] = { [1] = "ESTIMATOR_ATTITUDE", [2] = "ESTIMATOR_VELOCITY_HORIZ", @@ -1619,6 +1640,9 @@ local enumEntryName = { [0] = "RC_TYPE_SPEKTRUM_DSM2", [1] = "RC_TYPE_SPEKTRUM_DSMX", }, + ["ENGINE_CONTROL_OPTIONS"] = { + [1] = "ENGINE_CONTROL_OPTIONS_ALLOW_START_WHILE_DISARMED", + }, ["POSITION_TARGET_TYPEMASK"] = { [1] = "POSITION_TARGET_TYPEMASK_X_IGNORE", [2] = "POSITION_TARGET_TYPEMASK_Y_IGNORE", @@ -2113,6 +2137,10 @@ local enumEntryName = { [4] = "ICAROUS_FMS_STATE_APPROACH", [5] = "ICAROUS_FMS_STATE_LAND", }, + ["AIRLINK_AUTH_RESPONSE_TYPE"] = { + [0] = "AIRLINK_ERROR_LOGIN_OR_PASS", + [1] = "AIRLINK_AUTH_OK", + }, ["MAV_AUTOPILOT"] = { [0] = "MAV_AUTOPILOT_GENERIC", [1] = "MAV_AUTOPILOT_RESERVED", @@ -2518,7 +2546,7 @@ f.cmd_MAV_CMD_DO_SET_MODE_param3 = ProtoField.new("param3: Custom Submode (float f.cmd_MAV_CMD_DO_JUMP_param1 = ProtoField.new("param1: Number (float)", "mavlink_proto.cmd_MAV_CMD_DO_JUMP_param1", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_JUMP_param2 = ProtoField.new("param2: Repeat (float)", "mavlink_proto.cmd_MAV_CMD_DO_JUMP_param2", ftypes.FLOAT, nil) -f.cmd_MAV_CMD_DO_CHANGE_SPEED_param1 = ProtoField.new("param1: Speed Type (float)", "mavlink_proto.cmd_MAV_CMD_DO_CHANGE_SPEED_param1", ftypes.FLOAT, nil) +f.cmd_MAV_CMD_DO_CHANGE_SPEED_param1 = ProtoField.new("param1: Speed Type (SPEED_TYPE)", "mavlink_proto.cmd_MAV_CMD_DO_CHANGE_SPEED_param1", ftypes.UINT32, enumEntryName.SPEED_TYPE) f.cmd_MAV_CMD_DO_CHANGE_SPEED_param2 = ProtoField.new("param2: Speed (float)", "mavlink_proto.cmd_MAV_CMD_DO_CHANGE_SPEED_param2", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_CHANGE_SPEED_param3 = ProtoField.new("param3: Throttle (float)", "mavlink_proto.cmd_MAV_CMD_DO_CHANGE_SPEED_param3", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_CHANGE_SPEED_param4 = ProtoField.new("param4: Relative (float)", "mavlink_proto.cmd_MAV_CMD_DO_CHANGE_SPEED_param4", ftypes.FLOAT, nil) @@ -2678,6 +2706,7 @@ f.cmd_MAV_CMD_DO_GUIDED_LIMITS_param4 = ProtoField.new("param4: Horiz. Move Limi f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param1 = ProtoField.new("param1: Start Engine (float)", "mavlink_proto.cmd_MAV_CMD_DO_ENGINE_CONTROL_param1", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param2 = ProtoField.new("param2: Cold Start (float)", "mavlink_proto.cmd_MAV_CMD_DO_ENGINE_CONTROL_param2", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param3 = ProtoField.new("param3: Height Delay (float)", "mavlink_proto.cmd_MAV_CMD_DO_ENGINE_CONTROL_param3", ftypes.FLOAT, nil) +f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param4 = ProtoField.new("param4: Options (ENGINE_CONTROL_OPTIONS)", "mavlink_proto.cmd_MAV_CMD_DO_ENGINE_CONTROL_param4", ftypes.UINT32, enumEntryName.ENGINE_CONTROL_OPTIONS) f.cmd_MAV_CMD_DO_SET_MISSION_CURRENT_param1 = ProtoField.new("param1: Number (float)", "mavlink_proto.cmd_MAV_CMD_DO_SET_MISSION_CURRENT_param1", ftypes.FLOAT, nil) @@ -2785,11 +2814,16 @@ f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param2 = ProtoField.new("param2: Yaw an f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param3 = ProtoField.new("param3: Pitch rate (float)", "mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param3", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param4 = ProtoField.new("param4: Yaw rate (float)", "mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param4", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5 = ProtoField.new("param5: Gimbal manager flags (GIMBAL_MANAGER_FLAGS)", "mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5", ftypes.UINT32, nil) -f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 5, nil, 1) -f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 5, nil, 2) -f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 5, nil, 4) -f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 5, nil, 8) -f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 5, nil, 16) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 10, nil, 1) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 10, nil, 2) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 10, nil, 4) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 10, nil, 8) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 10, nil, 16) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", 10, nil, 32) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", 10, nil, 64) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", 10, nil, 128) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", "GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", 10, nil, 256) +f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5_flagGIMBAL_MANAGER_FLAGS_RC_MIXED = ProtoField.bool("mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param5.GIMBAL_MANAGER_FLAGS_RC_MIXED", "GIMBAL_MANAGER_FLAGS_RC_MIXED", 10, nil, 512) f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param7 = ProtoField.new("param7: Gimbal device ID (float)", "mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW_param7", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE_param1 = ProtoField.new("param1: sysid primary control (float)", "mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE_param1", ftypes.FLOAT, nil) @@ -2798,10 +2832,12 @@ f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE_param3 = ProtoField.new("param3: sysid f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE_param4 = ProtoField.new("param4: compid secondary control (float)", "mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE_param4", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE_param7 = ProtoField.new("param7: Gimbal device ID (float)", "mavlink_proto.cmd_MAV_CMD_DO_GIMBAL_MANAGER_CONFIGURE_param7", ftypes.FLOAT, nil) +f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param1 = ProtoField.new("param1: id (float)", "mavlink_proto.cmd_MAV_CMD_IMAGE_START_CAPTURE_param1", ftypes.FLOAT, nil) f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param2 = ProtoField.new("param2: Interval (float)", "mavlink_proto.cmd_MAV_CMD_IMAGE_START_CAPTURE_param2", ftypes.FLOAT, nil) f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param3 = ProtoField.new("param3: Total Images (float)", "mavlink_proto.cmd_MAV_CMD_IMAGE_START_CAPTURE_param3", ftypes.FLOAT, nil) f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param4 = ProtoField.new("param4: Sequence Number (float)", "mavlink_proto.cmd_MAV_CMD_IMAGE_START_CAPTURE_param4", ftypes.FLOAT, nil) +f.cmd_MAV_CMD_IMAGE_STOP_CAPTURE_param1 = ProtoField.new("param1: id (float)", "mavlink_proto.cmd_MAV_CMD_IMAGE_STOP_CAPTURE_param1", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_TRIGGER_CONTROL_param1 = ProtoField.new("param1: Enable (float)", "mavlink_proto.cmd_MAV_CMD_DO_TRIGGER_CONTROL_param1", ftypes.FLOAT, nil) f.cmd_MAV_CMD_DO_TRIGGER_CONTROL_param2 = ProtoField.new("param2: Reset (float)", "mavlink_proto.cmd_MAV_CMD_DO_TRIGGER_CONTROL_param2", ftypes.FLOAT, nil) @@ -5522,6 +5558,16 @@ f.MANUAL_CONTROL_y = ProtoField.new("y (int16_t)", "mavlink_proto.MANUAL_CONTROL f.MANUAL_CONTROL_z = ProtoField.new("z (int16_t)", "mavlink_proto.MANUAL_CONTROL_z", ftypes.INT16, nil) f.MANUAL_CONTROL_r = ProtoField.new("r (int16_t)", "mavlink_proto.MANUAL_CONTROL_r", ftypes.INT16, nil) f.MANUAL_CONTROL_buttons = ProtoField.new("buttons (uint16_t)", "mavlink_proto.MANUAL_CONTROL_buttons", ftypes.UINT16, nil) +f.MANUAL_CONTROL_buttons2 = ProtoField.new("buttons2 (uint16_t)", "mavlink_proto.MANUAL_CONTROL_buttons2", ftypes.UINT16, nil) +f.MANUAL_CONTROL_enabled_extensions = ProtoField.new("enabled_extensions (uint8_t)", "mavlink_proto.MANUAL_CONTROL_enabled_extensions", ftypes.UINT8, nil) +f.MANUAL_CONTROL_s = ProtoField.new("s (int16_t)", "mavlink_proto.MANUAL_CONTROL_s", ftypes.INT16, nil) +f.MANUAL_CONTROL_t = ProtoField.new("t (int16_t)", "mavlink_proto.MANUAL_CONTROL_t", ftypes.INT16, nil) +f.MANUAL_CONTROL_aux1 = ProtoField.new("aux1 (int16_t)", "mavlink_proto.MANUAL_CONTROL_aux1", ftypes.INT16, nil) +f.MANUAL_CONTROL_aux2 = ProtoField.new("aux2 (int16_t)", "mavlink_proto.MANUAL_CONTROL_aux2", ftypes.INT16, nil) +f.MANUAL_CONTROL_aux3 = ProtoField.new("aux3 (int16_t)", "mavlink_proto.MANUAL_CONTROL_aux3", ftypes.INT16, nil) +f.MANUAL_CONTROL_aux4 = ProtoField.new("aux4 (int16_t)", "mavlink_proto.MANUAL_CONTROL_aux4", ftypes.INT16, nil) +f.MANUAL_CONTROL_aux5 = ProtoField.new("aux5 (int16_t)", "mavlink_proto.MANUAL_CONTROL_aux5", ftypes.INT16, nil) +f.MANUAL_CONTROL_aux6 = ProtoField.new("aux6 (int16_t)", "mavlink_proto.MANUAL_CONTROL_aux6", ftypes.INT16, nil) f.RC_CHANNELS_OVERRIDE_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.RC_CHANNELS_OVERRIDE_target_system", ftypes.UINT8, nil) f.RC_CHANNELS_OVERRIDE_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.RC_CHANNELS_OVERRIDE_target_component", ftypes.UINT8, nil) @@ -6017,6 +6063,8 @@ f.SIM_STATE_std_dev_vert = ProtoField.new("std_dev_vert (float)", "mavlink_proto f.SIM_STATE_vn = ProtoField.new("vn (float)", "mavlink_proto.SIM_STATE_vn", ftypes.FLOAT, nil) f.SIM_STATE_ve = ProtoField.new("ve (float)", "mavlink_proto.SIM_STATE_ve", ftypes.FLOAT, nil) f.SIM_STATE_vd = ProtoField.new("vd (float)", "mavlink_proto.SIM_STATE_vd", ftypes.FLOAT, nil) +f.SIM_STATE_lat_int = ProtoField.new("lat_int (int32_t)", "mavlink_proto.SIM_STATE_lat_int", ftypes.INT32, nil) +f.SIM_STATE_lon_int = ProtoField.new("lon_int (int32_t)", "mavlink_proto.SIM_STATE_lon_int", ftypes.INT32, nil) f.RADIO_STATUS_rssi = ProtoField.new("rssi (uint8_t)", "mavlink_proto.RADIO_STATUS_rssi", ftypes.UINT8, nil) f.RADIO_STATUS_remrssi = ProtoField.new("remrssi (uint8_t)", "mavlink_proto.RADIO_STATUS_remrssi", ftypes.UINT8, nil) @@ -8419,6 +8467,7 @@ f.CAMERA_INFORMATION_flags_flagCAMERA_CAP_FLAGS_HAS_TRACKING_RECTANGLE = ProtoFi f.CAMERA_INFORMATION_flags_flagCAMERA_CAP_FLAGS_HAS_TRACKING_GEO_STATUS = ProtoField.bool("mavlink_proto.CAMERA_INFORMATION_flags.CAMERA_CAP_FLAGS_HAS_TRACKING_GEO_STATUS", "CAMERA_CAP_FLAGS_HAS_TRACKING_GEO_STATUS", 12, nil, 2048) f.CAMERA_INFORMATION_cam_definition_version = ProtoField.new("cam_definition_version (uint16_t)", "mavlink_proto.CAMERA_INFORMATION_cam_definition_version", ftypes.UINT16, nil) f.CAMERA_INFORMATION_cam_definition_uri = ProtoField.new("cam_definition_uri (char)", "mavlink_proto.CAMERA_INFORMATION_cam_definition_uri", ftypes.STRING, nil) +f.CAMERA_INFORMATION_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.CAMERA_INFORMATION_gimbal_device_id", ftypes.UINT8, nil) f.CAMERA_SETTINGS_time_boot_ms = ProtoField.new("time_boot_ms (uint32_t)", "mavlink_proto.CAMERA_SETTINGS_time_boot_ms", ftypes.UINT32, nil) f.CAMERA_SETTINGS_mode_id = ProtoField.new("mode_id (CAMERA_MODE)", "mavlink_proto.CAMERA_SETTINGS_mode_id", ftypes.UINT8, enumEntryName.CAMERA_MODE) @@ -9081,17 +9130,44 @@ f.GIMBAL_MANAGER_INFORMATION_yaw_max = ProtoField.new("yaw_max (float)", "mavlin f.GIMBAL_MANAGER_STATUS_time_boot_ms = ProtoField.new("time_boot_ms (uint32_t)", "mavlink_proto.GIMBAL_MANAGER_STATUS_time_boot_ms", ftypes.UINT32, nil) f.GIMBAL_MANAGER_STATUS_flags = ProtoField.new("flags (GIMBAL_MANAGER_FLAGS)", "mavlink_proto.GIMBAL_MANAGER_STATUS_flags", ftypes.UINT32, nil) -f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 5, nil, 1) -f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 5, nil, 2) -f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 5, nil, 4) -f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 5, nil, 8) -f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 5, nil, 16) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 10, nil, 1) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 10, nil, 2) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 10, nil, 4) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 10, nil, 8) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 10, nil, 16) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", 10, nil, 32) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", 10, nil, 64) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", 10, nil, 128) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", "GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", 10, nil, 256) +f.GIMBAL_MANAGER_STATUS_flags_flagGIMBAL_MANAGER_FLAGS_RC_MIXED = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_STATUS_flags.GIMBAL_MANAGER_FLAGS_RC_MIXED", "GIMBAL_MANAGER_FLAGS_RC_MIXED", 10, nil, 512) f.GIMBAL_MANAGER_STATUS_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_STATUS_gimbal_device_id", ftypes.UINT8, nil) f.GIMBAL_MANAGER_STATUS_primary_control_sysid = ProtoField.new("primary_control_sysid (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_STATUS_primary_control_sysid", ftypes.UINT8, nil) f.GIMBAL_MANAGER_STATUS_primary_control_compid = ProtoField.new("primary_control_compid (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_STATUS_primary_control_compid", ftypes.UINT8, nil) f.GIMBAL_MANAGER_STATUS_secondary_control_sysid = ProtoField.new("secondary_control_sysid (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_STATUS_secondary_control_sysid", ftypes.UINT8, nil) f.GIMBAL_MANAGER_STATUS_secondary_control_compid = ProtoField.new("secondary_control_compid (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_STATUS_secondary_control_compid", ftypes.UINT8, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_target_system", ftypes.UINT8, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_target_component", ftypes.UINT8, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags = ProtoField.new("flags (GIMBAL_MANAGER_FLAGS)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags", ftypes.UINT32, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 10, nil, 1) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 10, nil, 2) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 10, nil, 4) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 10, nil, 8) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 10, nil, 16) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", 10, nil, 32) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", 10, nil, 64) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", 10, nil, 128) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", "GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", 10, nil, 256) +f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_RC_MIXED = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_RC_MIXED", "GIMBAL_MANAGER_FLAGS_RC_MIXED", 10, nil, 512) +f.GIMBAL_MANAGER_SET_ATTITUDE_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_gimbal_device_id", ftypes.UINT8, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_q_0 = ProtoField.new("q[0] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_0", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_q_1 = ProtoField.new("q[1] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_1", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_q_2 = ProtoField.new("q[2] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_2", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_q_3 = ProtoField.new("q[3] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_3", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_x = ProtoField.new("angular_velocity_x (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_x", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_y = ProtoField.new("angular_velocity_y (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_y", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_z = ProtoField.new("angular_velocity_z (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_z", ftypes.FLOAT, nil) + f.GIMBAL_DEVICE_INFORMATION_time_boot_ms = ProtoField.new("time_boot_ms (uint32_t)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_time_boot_ms", ftypes.UINT32, nil) f.GIMBAL_DEVICE_INFORMATION_vendor_name = ProtoField.new("vendor_name (char)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_vendor_name", ftypes.STRING, nil) f.GIMBAL_DEVICE_INFORMATION_model_name = ProtoField.new("model_name (char)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_model_name", ftypes.STRING, nil) @@ -9100,18 +9176,20 @@ f.GIMBAL_DEVICE_INFORMATION_firmware_version = ProtoField.new("firmware_version f.GIMBAL_DEVICE_INFORMATION_hardware_version = ProtoField.new("hardware_version (uint32_t)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_hardware_version", ftypes.UINT32, nil) f.GIMBAL_DEVICE_INFORMATION_uid = ProtoField.new("uid (uint64_t)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_uid", ftypes.UINT64, nil) f.GIMBAL_DEVICE_INFORMATION_cap_flags = ProtoField.new("cap_flags (GIMBAL_DEVICE_CAP_FLAGS)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags", ftypes.UINT16, nil) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_RETRACT", "GIMBAL_DEVICE_CAP_FLAGS_HAS_RETRACT", 12, nil, 1) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_NEUTRAL", "GIMBAL_DEVICE_CAP_FLAGS_HAS_NEUTRAL", 12, nil, 2) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_AXIS = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_AXIS", "GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_AXIS", 12, nil, 4) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_FOLLOW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_FOLLOW", "GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_FOLLOW", 12, nil, 8) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_LOCK", "GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_LOCK", 12, nil, 16) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_AXIS = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_AXIS", "GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_AXIS", 12, nil, 32) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_FOLLOW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_FOLLOW", "GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_FOLLOW", 12, nil, 64) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_LOCK", "GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_LOCK", 12, nil, 128) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_AXIS = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_AXIS", "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_AXIS", 12, nil, 256) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW", "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW", 12, nil, 512) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK", "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK", 12, nil, 1024) -f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW", "GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW", 12, nil, 2048) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_RETRACT", "GIMBAL_DEVICE_CAP_FLAGS_HAS_RETRACT", 14, nil, 1) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_NEUTRAL", "GIMBAL_DEVICE_CAP_FLAGS_HAS_NEUTRAL", 14, nil, 2) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_AXIS = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_AXIS", "GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_AXIS", 14, nil, 4) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_FOLLOW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_FOLLOW", "GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_FOLLOW", 14, nil, 8) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_LOCK", "GIMBAL_DEVICE_CAP_FLAGS_HAS_ROLL_LOCK", 14, nil, 16) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_AXIS = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_AXIS", "GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_AXIS", 14, nil, 32) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_FOLLOW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_FOLLOW", "GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_FOLLOW", 14, nil, 64) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_LOCK", "GIMBAL_DEVICE_CAP_FLAGS_HAS_PITCH_LOCK", 14, nil, 128) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_AXIS = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_AXIS", "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_AXIS", 14, nil, 256) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW", "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW", 14, nil, 512) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK", "GIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK", 14, nil, 1024) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW", "GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW", 14, nil, 2048) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_YAW_IN_EARTH_FRAME", "GIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_YAW_IN_EARTH_FRAME", 14, nil, 4096) +f.GIMBAL_DEVICE_INFORMATION_cap_flags_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_RC_INPUTS = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_INFORMATION_cap_flags.GIMBAL_DEVICE_CAP_FLAGS_HAS_RC_INPUTS", "GIMBAL_DEVICE_CAP_FLAGS_HAS_RC_INPUTS", 14, nil, 8192) f.GIMBAL_DEVICE_INFORMATION_custom_cap_flags = ProtoField.new("custom_cap_flags (uint16_t)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_custom_cap_flags", ftypes.UINT16, nil) f.GIMBAL_DEVICE_INFORMATION_roll_min = ProtoField.new("roll_min (float)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_roll_min", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_INFORMATION_roll_max = ProtoField.new("roll_max (float)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_roll_max", ftypes.FLOAT, nil) @@ -9119,15 +9197,21 @@ f.GIMBAL_DEVICE_INFORMATION_pitch_min = ProtoField.new("pitch_min (float)", "mav f.GIMBAL_DEVICE_INFORMATION_pitch_max = ProtoField.new("pitch_max (float)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_pitch_max", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_INFORMATION_yaw_min = ProtoField.new("yaw_min (float)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_yaw_min", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_INFORMATION_yaw_max = ProtoField.new("yaw_max (float)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_yaw_max", ftypes.FLOAT, nil) +f.GIMBAL_DEVICE_INFORMATION_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.GIMBAL_DEVICE_INFORMATION_gimbal_device_id", ftypes.UINT8, nil) f.GIMBAL_DEVICE_SET_ATTITUDE_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_target_system", ftypes.UINT8, nil) f.GIMBAL_DEVICE_SET_ATTITUDE_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_target_component", ftypes.UINT8, nil) f.GIMBAL_DEVICE_SET_ATTITUDE_flags = ProtoField.new("flags (GIMBAL_DEVICE_FLAGS)", "mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags", ftypes.UINT16, nil) -f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_RETRACT", "GIMBAL_DEVICE_FLAGS_RETRACT", 5, nil, 1) -f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_NEUTRAL", "GIMBAL_DEVICE_FLAGS_NEUTRAL", 5, nil, 2) -f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_ROLL_LOCK", "GIMBAL_DEVICE_FLAGS_ROLL_LOCK", 5, nil, 4) -f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_PITCH_LOCK", "GIMBAL_DEVICE_FLAGS_PITCH_LOCK", 5, nil, 8) -f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_YAW_LOCK", "GIMBAL_DEVICE_FLAGS_YAW_LOCK", 5, nil, 16) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_RETRACT", "GIMBAL_DEVICE_FLAGS_RETRACT", 10, nil, 1) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_NEUTRAL", "GIMBAL_DEVICE_FLAGS_NEUTRAL", 10, nil, 2) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_ROLL_LOCK", "GIMBAL_DEVICE_FLAGS_ROLL_LOCK", 10, nil, 4) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_PITCH_LOCK", "GIMBAL_DEVICE_FLAGS_PITCH_LOCK", 10, nil, 8) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_YAW_LOCK", "GIMBAL_DEVICE_FLAGS_YAW_LOCK", 10, nil, 16) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME", "GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME", 10, nil, 32) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME", "GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME", 10, nil, 64) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", "GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", 10, nil, 128) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE", "GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE", 10, nil, 256) +f.GIMBAL_DEVICE_SET_ATTITUDE_flags_flagGIMBAL_DEVICE_FLAGS_RC_MIXED = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_flags.GIMBAL_DEVICE_FLAGS_RC_MIXED", "GIMBAL_DEVICE_FLAGS_RC_MIXED", 10, nil, 512) f.GIMBAL_DEVICE_SET_ATTITUDE_q_0 = ProtoField.new("q[0] (float)", "mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_q_0", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_SET_ATTITUDE_q_1 = ProtoField.new("q[1] (float)", "mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_q_1", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_SET_ATTITUDE_q_2 = ProtoField.new("q[2] (float)", "mavlink_proto.GIMBAL_DEVICE_SET_ATTITUDE_q_2", ftypes.FLOAT, nil) @@ -9140,11 +9224,16 @@ f.GIMBAL_DEVICE_ATTITUDE_STATUS_target_system = ProtoField.new("target_system (u f.GIMBAL_DEVICE_ATTITUDE_STATUS_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_target_component", ftypes.UINT8, nil) f.GIMBAL_DEVICE_ATTITUDE_STATUS_time_boot_ms = ProtoField.new("time_boot_ms (uint32_t)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_time_boot_ms", ftypes.UINT32, nil) f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags = ProtoField.new("flags (GIMBAL_DEVICE_FLAGS)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags", ftypes.UINT16, nil) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_RETRACT", "GIMBAL_DEVICE_FLAGS_RETRACT", 5, nil, 1) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_NEUTRAL", "GIMBAL_DEVICE_FLAGS_NEUTRAL", 5, nil, 2) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_ROLL_LOCK", "GIMBAL_DEVICE_FLAGS_ROLL_LOCK", 5, nil, 4) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_PITCH_LOCK", "GIMBAL_DEVICE_FLAGS_PITCH_LOCK", 5, nil, 8) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_YAW_LOCK", "GIMBAL_DEVICE_FLAGS_YAW_LOCK", 5, nil, 16) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_RETRACT", "GIMBAL_DEVICE_FLAGS_RETRACT", 10, nil, 1) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_NEUTRAL", "GIMBAL_DEVICE_FLAGS_NEUTRAL", 10, nil, 2) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_ROLL_LOCK", "GIMBAL_DEVICE_FLAGS_ROLL_LOCK", 10, nil, 4) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_PITCH_LOCK", "GIMBAL_DEVICE_FLAGS_PITCH_LOCK", 10, nil, 8) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_YAW_LOCK", "GIMBAL_DEVICE_FLAGS_YAW_LOCK", 10, nil, 16) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME", "GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME", 10, nil, 32) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME", "GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME", 10, nil, 64) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", "GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", 10, nil, 128) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE", "GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE", 10, nil, 256) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_flags_flagGIMBAL_DEVICE_FLAGS_RC_MIXED = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_flags.GIMBAL_DEVICE_FLAGS_RC_MIXED", "GIMBAL_DEVICE_FLAGS_RC_MIXED", 10, nil, 512) f.GIMBAL_DEVICE_ATTITUDE_STATUS_q_0 = ProtoField.new("q[0] (float)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_q_0", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_ATTITUDE_STATUS_q_1 = ProtoField.new("q[1] (float)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_q_1", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_ATTITUDE_STATUS_q_2 = ProtoField.new("q[2] (float)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_q_2", ftypes.FLOAT, nil) @@ -9153,15 +9242,19 @@ f.GIMBAL_DEVICE_ATTITUDE_STATUS_angular_velocity_x = ProtoField.new("angular_vel f.GIMBAL_DEVICE_ATTITUDE_STATUS_angular_velocity_y = ProtoField.new("angular_velocity_y (float)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_angular_velocity_y", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_ATTITUDE_STATUS_angular_velocity_z = ProtoField.new("angular_velocity_z (float)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_angular_velocity_z", ftypes.FLOAT, nil) f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags = ProtoField.new("failure_flags (GIMBAL_DEVICE_ERROR_FLAGS)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags", ftypes.UINT32, nil) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_AT_ROLL_LIMIT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_AT_ROLL_LIMIT", "GIMBAL_DEVICE_ERROR_FLAGS_AT_ROLL_LIMIT", 9, nil, 1) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_AT_PITCH_LIMIT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_AT_PITCH_LIMIT", "GIMBAL_DEVICE_ERROR_FLAGS_AT_PITCH_LIMIT", 9, nil, 2) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_AT_YAW_LIMIT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_AT_YAW_LIMIT", "GIMBAL_DEVICE_ERROR_FLAGS_AT_YAW_LIMIT", 9, nil, 4) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_ENCODER_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_ENCODER_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_ENCODER_ERROR", 9, nil, 8) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_POWER_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_POWER_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_POWER_ERROR", 9, nil, 16) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_MOTOR_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_MOTOR_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_MOTOR_ERROR", 9, nil, 32) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR", 9, nil, 64) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR", 9, nil, 128) -f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING", "GIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING", 9, nil, 256) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_AT_ROLL_LIMIT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_AT_ROLL_LIMIT", "GIMBAL_DEVICE_ERROR_FLAGS_AT_ROLL_LIMIT", 10, nil, 1) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_AT_PITCH_LIMIT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_AT_PITCH_LIMIT", "GIMBAL_DEVICE_ERROR_FLAGS_AT_PITCH_LIMIT", 10, nil, 2) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_AT_YAW_LIMIT = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_AT_YAW_LIMIT", "GIMBAL_DEVICE_ERROR_FLAGS_AT_YAW_LIMIT", 10, nil, 4) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_ENCODER_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_ENCODER_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_ENCODER_ERROR", 10, nil, 8) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_POWER_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_POWER_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_POWER_ERROR", 10, nil, 16) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_MOTOR_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_MOTOR_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_MOTOR_ERROR", 10, nil, 32) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR", 10, nil, 64) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR", "GIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR", 10, nil, 128) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING", "GIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING", 10, nil, 256) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags_flagGIMBAL_DEVICE_ERROR_FLAGS_NO_MANAGER = ProtoField.bool("mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags.GIMBAL_DEVICE_ERROR_FLAGS_NO_MANAGER", "GIMBAL_DEVICE_ERROR_FLAGS_NO_MANAGER", 10, nil, 512) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_delta_yaw = ProtoField.new("delta_yaw (float)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_delta_yaw", ftypes.FLOAT, nil) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_delta_yaw_velocity = ProtoField.new("delta_yaw_velocity (float)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_delta_yaw_velocity", ftypes.FLOAT, nil) +f.GIMBAL_DEVICE_ATTITUDE_STATUS_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.GIMBAL_DEVICE_ATTITUDE_STATUS_gimbal_device_id", ftypes.UINT8, nil) f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_target_system", ftypes.UINT8, nil) f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_target_component", ftypes.UINT8, nil) @@ -9190,38 +9283,46 @@ f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_estimator_status_flagESTIMATOR_PRED_POS_HORI f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_estimator_status_flagESTIMATOR_GPS_GLITCH = ProtoField.bool("mavlink_proto.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_estimator_status.ESTIMATOR_GPS_GLITCH", "ESTIMATOR_GPS_GLITCH", 12, nil, 1024) f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_estimator_status_flagESTIMATOR_ACCEL_ERROR = ProtoField.bool("mavlink_proto.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_estimator_status.ESTIMATOR_ACCEL_ERROR", "ESTIMATOR_ACCEL_ERROR", 12, nil, 2048) f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_landed_state = ProtoField.new("landed_state (MAV_LANDED_STATE)", "mavlink_proto.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_landed_state", ftypes.UINT8, enumEntryName.MAV_LANDED_STATE) - -f.GIMBAL_MANAGER_SET_ATTITUDE_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_target_system", ftypes.UINT8, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_target_component", ftypes.UINT8, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_flags = ProtoField.new("flags (GIMBAL_MANAGER_FLAGS)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags", ftypes.UINT32, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 5, nil, 1) -f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 5, nil, 2) -f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 5, nil, 4) -f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 5, nil, 8) -f.GIMBAL_MANAGER_SET_ATTITUDE_flags_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_flags.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 5, nil, 16) -f.GIMBAL_MANAGER_SET_ATTITUDE_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_gimbal_device_id", ftypes.UINT8, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_q_0 = ProtoField.new("q[0] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_0", ftypes.FLOAT, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_q_1 = ProtoField.new("q[1] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_1", ftypes.FLOAT, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_q_2 = ProtoField.new("q[2] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_2", ftypes.FLOAT, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_q_3 = ProtoField.new("q[3] (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_q_3", ftypes.FLOAT, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_x = ProtoField.new("angular_velocity_x (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_x", ftypes.FLOAT, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_y = ProtoField.new("angular_velocity_y (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_y", ftypes.FLOAT, nil) -f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_z = ProtoField.new("angular_velocity_z (float)", "mavlink_proto.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_z", ftypes.FLOAT, nil) +f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_angular_velocity_z = ProtoField.new("angular_velocity_z (float)", "mavlink_proto.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_angular_velocity_z", ftypes.FLOAT, nil) f.GIMBAL_MANAGER_SET_PITCHYAW_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_target_system", ftypes.UINT8, nil) f.GIMBAL_MANAGER_SET_PITCHYAW_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_target_component", ftypes.UINT8, nil) f.GIMBAL_MANAGER_SET_PITCHYAW_flags = ProtoField.new("flags (GIMBAL_MANAGER_FLAGS)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags", ftypes.UINT32, nil) -f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 5, nil, 1) -f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 5, nil, 2) -f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 5, nil, 4) -f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 5, nil, 8) -f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 5, nil, 16) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 10, nil, 1) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 10, nil, 2) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 10, nil, 4) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 10, nil, 8) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 10, nil, 16) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", 10, nil, 32) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", 10, nil, 64) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", 10, nil, 128) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", "GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", 10, nil, 256) +f.GIMBAL_MANAGER_SET_PITCHYAW_flags_flagGIMBAL_MANAGER_FLAGS_RC_MIXED = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_flags.GIMBAL_MANAGER_FLAGS_RC_MIXED", "GIMBAL_MANAGER_FLAGS_RC_MIXED", 10, nil, 512) f.GIMBAL_MANAGER_SET_PITCHYAW_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_gimbal_device_id", ftypes.UINT8, nil) f.GIMBAL_MANAGER_SET_PITCHYAW_pitch = ProtoField.new("pitch (float)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_pitch", ftypes.FLOAT, nil) f.GIMBAL_MANAGER_SET_PITCHYAW_yaw = ProtoField.new("yaw (float)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_yaw", ftypes.FLOAT, nil) f.GIMBAL_MANAGER_SET_PITCHYAW_pitch_rate = ProtoField.new("pitch_rate (float)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_pitch_rate", ftypes.FLOAT, nil) f.GIMBAL_MANAGER_SET_PITCHYAW_yaw_rate = ProtoField.new("yaw_rate (float)", "mavlink_proto.GIMBAL_MANAGER_SET_PITCHYAW_yaw_rate", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_target_system", ftypes.UINT8, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_target_component", ftypes.UINT8, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags = ProtoField.new("flags (GIMBAL_MANAGER_FLAGS)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags", ftypes.UINT32, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_RETRACT = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_RETRACT", "GIMBAL_MANAGER_FLAGS_RETRACT", 10, nil, 1) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_NEUTRAL = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_NEUTRAL", "GIMBAL_MANAGER_FLAGS_NEUTRAL", 10, nil, 2) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_ROLL_LOCK", "GIMBAL_MANAGER_FLAGS_ROLL_LOCK", 10, nil, 4) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_PITCH_LOCK", "GIMBAL_MANAGER_FLAGS_PITCH_LOCK", 10, nil, 8) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_YAW_LOCK", "GIMBAL_MANAGER_FLAGS_YAW_LOCK", 10, nil, 16) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME", 10, nil, 32) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME", 10, nil, 64) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", "GIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME", 10, nil, 128) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", "GIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE", 10, nil, 256) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags_flagGIMBAL_MANAGER_FLAGS_RC_MIXED = ProtoField.bool("mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags.GIMBAL_MANAGER_FLAGS_RC_MIXED", "GIMBAL_MANAGER_FLAGS_RC_MIXED", 10, nil, 512) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_gimbal_device_id = ProtoField.new("gimbal_device_id (uint8_t)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_gimbal_device_id", ftypes.UINT8, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_pitch = ProtoField.new("pitch (float)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_pitch", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_yaw = ProtoField.new("yaw (float)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_yaw", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_pitch_rate = ProtoField.new("pitch_rate (float)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_pitch_rate", ftypes.FLOAT, nil) +f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_yaw_rate = ProtoField.new("yaw_rate (float)", "mavlink_proto.GIMBAL_MANAGER_SET_MANUAL_CONTROL_yaw_rate", ftypes.FLOAT, nil) + f.WIFI_CONFIG_AP_ssid = ProtoField.new("ssid (char)", "mavlink_proto.WIFI_CONFIG_AP_ssid", ftypes.STRING, nil) f.WIFI_CONFIG_AP_password = ProtoField.new("password (char)", "mavlink_proto.WIFI_CONFIG_AP_password", ftypes.STRING, nil) @@ -9662,6 +9763,10 @@ f.ACTUATOR_OUTPUT_STATUS_actuator_29 = ProtoField.new("actuator[29] (float)", "m f.ACTUATOR_OUTPUT_STATUS_actuator_30 = ProtoField.new("actuator[30] (float)", "mavlink_proto.ACTUATOR_OUTPUT_STATUS_actuator_30", ftypes.FLOAT, nil) f.ACTUATOR_OUTPUT_STATUS_actuator_31 = ProtoField.new("actuator[31] (float)", "mavlink_proto.ACTUATOR_OUTPUT_STATUS_actuator_31", ftypes.FLOAT, nil) +f.RELAY_STATUS_time_boot_ms = ProtoField.new("time_boot_ms (uint32_t)", "mavlink_proto.RELAY_STATUS_time_boot_ms", ftypes.UINT32, nil) +f.RELAY_STATUS_on = ProtoField.new("on (uint16_t)", "mavlink_proto.RELAY_STATUS_on", ftypes.UINT16, nil) +f.RELAY_STATUS_present = ProtoField.new("present (uint16_t)", "mavlink_proto.RELAY_STATUS_present", ftypes.UINT16, nil) + f.TUNNEL_target_system = ProtoField.new("target_system (uint8_t)", "mavlink_proto.TUNNEL_target_system", ftypes.UINT8, nil) f.TUNNEL_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.TUNNEL_target_component", ftypes.UINT8, nil) f.TUNNEL_payload_type = ProtoField.new("payload_type (MAV_TUNNEL_PAYLOAD_TYPE)", "mavlink_proto.TUNNEL_payload_type", ftypes.UINT16, enumEntryName.MAV_TUNNEL_PAYLOAD_TYPE) @@ -10598,6 +10703,11 @@ f.CUBEPILOT_FIRMWARE_UPDATE_RESP_target_system = ProtoField.new("target_system ( f.CUBEPILOT_FIRMWARE_UPDATE_RESP_target_component = ProtoField.new("target_component (uint8_t)", "mavlink_proto.CUBEPILOT_FIRMWARE_UPDATE_RESP_target_component", ftypes.UINT8, nil) f.CUBEPILOT_FIRMWARE_UPDATE_RESP_offset = ProtoField.new("offset (uint32_t)", "mavlink_proto.CUBEPILOT_FIRMWARE_UPDATE_RESP_offset", ftypes.UINT32, nil) +f.AIRLINK_AUTH_login = ProtoField.new("login (char)", "mavlink_proto.AIRLINK_AUTH_login", ftypes.STRING, nil) +f.AIRLINK_AUTH_password = ProtoField.new("password (char)", "mavlink_proto.AIRLINK_AUTH_password", ftypes.STRING, nil) + +f.AIRLINK_AUTH_RESPONSE_resp_type = ProtoField.new("resp_type (AIRLINK_AUTH_RESPONSE_TYPE)", "mavlink_proto.AIRLINK_AUTH_RESPONSE_resp_type", ftypes.UINT8, enumEntryName.AIRLINK_AUTH_RESPONSE_TYPE) + f.HEARTBEAT_type = ProtoField.new("type (MAV_TYPE)", "mavlink_proto.HEARTBEAT_type", ftypes.UINT8, enumEntryName.MAV_TYPE) f.HEARTBEAT_autopilot = ProtoField.new("autopilot (MAV_AUTOPILOT)", "mavlink_proto.HEARTBEAT_autopilot", ftypes.UINT8, enumEntryName.MAV_AUTOPILOT) f.HEARTBEAT_base_mode = ProtoField.new("base_mode (MAV_MODE_FLAG)", "mavlink_proto.HEARTBEAT_base_mode", ftypes.UINT8, nil) @@ -10713,6 +10823,8 @@ function dissect_flags_GIMBAL_DEVICE_CAP_FLAGS(tree, name, tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_FOLLOW"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_YAW_LOCK"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_INFINITE_YAW"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_CAP_FLAGS_SUPPORTS_YAW_IN_EARTH_FRAME"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_CAP_FLAGS_HAS_RC_INPUTS"], tvbrange, value) end -- dissect flag field function dissect_flags_GIMBAL_MANAGER_CAP_FLAGS(tree, name, tvbrange, value) @@ -10740,6 +10852,11 @@ function dissect_flags_GIMBAL_DEVICE_FLAGS(tree, name, tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_ROLL_LOCK"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_PITCH_LOCK"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_YAW_LOCK"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_FLAGS_RC_MIXED"], tvbrange, value) end -- dissect flag field function dissect_flags_GIMBAL_MANAGER_FLAGS(tree, name, tvbrange, value) @@ -10748,6 +10865,11 @@ function dissect_flags_GIMBAL_MANAGER_FLAGS(tree, name, tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_ROLL_LOCK"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_PITCH_LOCK"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_YAW_LOCK"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_YAW_IN_VEHICLE_FRAME"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_YAW_IN_EARTH_FRAME"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_RC_EXCLUSIVE"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_MANAGER_FLAGS_RC_MIXED"], tvbrange, value) end -- dissect flag field function dissect_flags_GIMBAL_DEVICE_ERROR_FLAGS(tree, name, tvbrange, value) @@ -10760,6 +10882,7 @@ function dissect_flags_GIMBAL_DEVICE_ERROR_FLAGS(tree, name, tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_ERROR_FLAGS_SOFTWARE_ERROR"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_ERROR_FLAGS_COMMS_ERROR"], tvbrange, value) tree:add_le(f[name .. "_flagGIMBAL_DEVICE_ERROR_FLAGS_CALIBRATION_RUNNING"], tvbrange, value) + tree:add_le(f[name .. "_flagGIMBAL_DEVICE_ERROR_FLAGS_NO_MANAGER"], tvbrange, value) end -- dissect flag field function dissect_flags_AUTOTUNE_AXIS(tree, name, tvbrange, value) @@ -19142,9 +19265,9 @@ end -- dissect payload of message type MANUAL_CONTROL function payload_fns.payload_69(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange - if (offset + 11 > limit) then + if (offset + 30 > limit) then padded = buffer(0, limit):bytes() - padded:set_size(offset + 11) + padded:set_size(offset + 30) padded = padded:tvb("Untruncated payload") else padded = buffer @@ -19167,6 +19290,36 @@ function payload_fns.payload_69(buffer, tree, msgid, offset, limit, pinfo) tvbrange = padded(offset + 8, 2) value = tvbrange:le_uint() subtree = tree:add_le(f.MANUAL_CONTROL_buttons, tvbrange, value) + tvbrange = padded(offset + 11, 2) + value = tvbrange:le_uint() + subtree = tree:add_le(f.MANUAL_CONTROL_buttons2, tvbrange, value) + tvbrange = padded(offset + 13, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.MANUAL_CONTROL_enabled_extensions, tvbrange, value) + tvbrange = padded(offset + 14, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_s, tvbrange, value) + tvbrange = padded(offset + 16, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_t, tvbrange, value) + tvbrange = padded(offset + 18, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_aux1, tvbrange, value) + tvbrange = padded(offset + 20, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_aux2, tvbrange, value) + tvbrange = padded(offset + 22, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_aux3, tvbrange, value) + tvbrange = padded(offset + 24, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_aux4, tvbrange, value) + tvbrange = padded(offset + 26, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_aux5, tvbrange, value) + tvbrange = padded(offset + 28, 2) + value = tvbrange:le_int() + subtree = tree:add_le(f.MANUAL_CONTROL_aux6, tvbrange, value) end -- dissect payload of message type RC_CHANNELS_OVERRIDE function payload_fns.payload_70(buffer, tree, msgid, offset, limit, pinfo) @@ -22965,7 +23118,7 @@ function payload_fns.payload_75_cmd223(buffer, tree, msgid, offset, limit, pinfo subtree = tree:add_le(f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param3, tvbrange, value) tvbrange = padded(offset + 12, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.COMMAND_INT_param4, tvbrange, value) + subtree = tree:add_le(f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param4, tvbrange, value) tvbrange = padded(offset + 16, 4) value = tvbrange:le_int() subtree = tree:add_le(f.COMMAND_INT_x, tvbrange, value) @@ -24657,7 +24810,7 @@ function payload_fns.payload_75_cmd2000(buffer, tree, msgid, offset, limit, pinf subtree = tree:add_le(f.COMMAND_INT_autocontinue, tvbrange, value) tvbrange = padded(offset + 0, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.COMMAND_INT_param1, tvbrange, value) + subtree = tree:add_le(f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param1, tvbrange, value) tvbrange = padded(offset + 4, 4) value = tvbrange:le_float() subtree = tree:add_le(f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param2, tvbrange, value) @@ -24707,7 +24860,7 @@ function payload_fns.payload_75_cmd2001(buffer, tree, msgid, offset, limit, pinf subtree = tree:add_le(f.COMMAND_INT_autocontinue, tvbrange, value) tvbrange = padded(offset + 0, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.COMMAND_INT_param1, tvbrange, value) + subtree = tree:add_le(f.cmd_MAV_CMD_IMAGE_STOP_CAPTURE_param1, tvbrange, value) tvbrange = padded(offset + 4, 4) value = tvbrange:le_float() subtree = tree:add_le(f.COMMAND_INT_param2, tvbrange, value) @@ -31790,7 +31943,7 @@ function payload_fns.payload_76_cmd223(buffer, tree, msgid, offset, limit, pinfo subtree = tree:add_le(f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param3, tvbrange, value) tvbrange = padded(offset + 12, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.COMMAND_LONG_param4, tvbrange, value) + subtree = tree:add_le(f.cmd_MAV_CMD_DO_ENGINE_CONTROL_param4, tvbrange, value) tvbrange = padded(offset + 16, 4) value = tvbrange:le_float() subtree = tree:add_le(f.COMMAND_LONG_param5, tvbrange, value) @@ -33278,7 +33431,7 @@ function payload_fns.payload_76_cmd2000(buffer, tree, msgid, offset, limit, pinf subtree = tree:add_le(f.COMMAND_LONG_confirmation, tvbrange, value) tvbrange = padded(offset + 0, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.COMMAND_LONG_param1, tvbrange, value) + subtree = tree:add_le(f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param1, tvbrange, value) tvbrange = padded(offset + 4, 4) value = tvbrange:le_float() subtree = tree:add_le(f.cmd_MAV_CMD_IMAGE_START_CAPTURE_param2, tvbrange, value) @@ -33322,7 +33475,7 @@ function payload_fns.payload_76_cmd2001(buffer, tree, msgid, offset, limit, pinf subtree = tree:add_le(f.COMMAND_LONG_confirmation, tvbrange, value) tvbrange = padded(offset + 0, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.COMMAND_LONG_param1, tvbrange, value) + subtree = tree:add_le(f.cmd_MAV_CMD_IMAGE_STOP_CAPTURE_param1, tvbrange, value) tvbrange = padded(offset + 4, 4) value = tvbrange:le_float() subtree = tree:add_le(f.COMMAND_LONG_param2, tvbrange, value) @@ -37934,9 +38087,9 @@ end -- dissect payload of message type SIM_STATE function payload_fns.payload_108(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange - if (offset + 84 > limit) then + if (offset + 92 > limit) then padded = buffer(0, limit):bytes() - padded:set_size(offset + 84) + padded:set_size(offset + 92) padded = padded:tvb("Untruncated payload") else padded = buffer @@ -38004,6 +38157,12 @@ function payload_fns.payload_108(buffer, tree, msgid, offset, limit, pinfo) tvbrange = padded(offset + 80, 4) value = tvbrange:le_float() subtree = tree:add_le(f.SIM_STATE_vd, tvbrange, value) + tvbrange = padded(offset + 84, 4) + value = tvbrange:le_int() + subtree = tree:add_le(f.SIM_STATE_lat_int, tvbrange, value) + tvbrange = padded(offset + 88, 4) + value = tvbrange:le_int() + subtree = tree:add_le(f.SIM_STATE_lon_int, tvbrange, value) end -- dissect payload of message type RADIO_STATUS function payload_fns.payload_109(buffer, tree, msgid, offset, limit, pinfo) @@ -45220,9 +45379,9 @@ end -- dissect payload of message type CAMERA_INFORMATION function payload_fns.payload_259(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange - if (offset + 235 > limit) then + if (offset + 236 > limit) then padded = buffer(0, limit):bytes() - padded:set_size(offset + 235) + padded:set_size(offset + 236) padded = padded:tvb("Untruncated payload") else padded = buffer @@ -45453,6 +45612,9 @@ function payload_fns.payload_259(buffer, tree, msgid, offset, limit, pinfo) tvbrange = padded(offset + 95, 140) value = tvbrange:string() subtree = tree:add_le(f.CAMERA_INFORMATION_cam_definition_uri, tvbrange, value) + tvbrange = padded(offset + 235, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.CAMERA_INFORMATION_gimbal_device_id, tvbrange, value) end -- dissect payload of message type CAMERA_SETTINGS function payload_fns.payload_260(buffer, tree, msgid, offset, limit, pinfo) @@ -47519,12 +47681,57 @@ function payload_fns.payload_281(buffer, tree, msgid, offset, limit, pinfo) value = tvbrange:le_uint() subtree = tree:add_le(f.GIMBAL_MANAGER_STATUS_secondary_control_compid, tvbrange, value) end +-- dissect payload of message type GIMBAL_MANAGER_SET_ATTITUDE +function payload_fns.payload_282(buffer, tree, msgid, offset, limit, pinfo) + local padded, field_offset, value, subtree, tvbrange + if (offset + 35 > limit) then + padded = buffer(0, limit):bytes() + padded:set_size(offset + 35) + padded = padded:tvb("Untruncated payload") + else + padded = buffer + end + tvbrange = padded(offset + 32, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_target_system, tvbrange, value) + tvbrange = padded(offset + 33, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_target_component, tvbrange, value) + tvbrange = padded(offset + 0, 4) + value = tvbrange:le_uint() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_flags, tvbrange, value) + dissect_flags_GIMBAL_MANAGER_FLAGS(subtree, "GIMBAL_MANAGER_SET_ATTITUDE_flags", tvbrange, value) + tvbrange = padded(offset + 34, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_gimbal_device_id, tvbrange, value) + tvbrange = padded(offset + 4, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_0, tvbrange, value) + tvbrange = padded(offset + 8, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_1, tvbrange, value) + tvbrange = padded(offset + 12, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_2, tvbrange, value) + tvbrange = padded(offset + 16, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_3, tvbrange, value) + tvbrange = padded(offset + 20, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_x, tvbrange, value) + tvbrange = padded(offset + 24, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_y, tvbrange, value) + tvbrange = padded(offset + 28, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_z, tvbrange, value) +end -- dissect payload of message type GIMBAL_DEVICE_INFORMATION function payload_fns.payload_283(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange - if (offset + 144 > limit) then + if (offset + 145 > limit) then padded = buffer(0, limit):bytes() - padded:set_size(offset + 144) + padded:set_size(offset + 145) padded = padded:tvb("Untruncated payload") else padded = buffer @@ -47575,6 +47782,9 @@ function payload_fns.payload_283(buffer, tree, msgid, offset, limit, pinfo) tvbrange = padded(offset + 40, 4) value = tvbrange:le_float() subtree = tree:add_le(f.GIMBAL_DEVICE_INFORMATION_yaw_max, tvbrange, value) + tvbrange = padded(offset + 144, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.GIMBAL_DEVICE_INFORMATION_gimbal_device_id, tvbrange, value) end -- dissect payload of message type GIMBAL_DEVICE_SET_ATTITUDE function payload_fns.payload_284(buffer, tree, msgid, offset, limit, pinfo) @@ -47621,9 +47831,9 @@ end -- dissect payload of message type GIMBAL_DEVICE_ATTITUDE_STATUS function payload_fns.payload_285(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange - if (offset + 40 > limit) then + if (offset + 49 > limit) then padded = buffer(0, limit):bytes() - padded:set_size(offset + 40) + padded:set_size(offset + 49) padded = padded:tvb("Untruncated payload") else padded = buffer @@ -47666,13 +47876,22 @@ function payload_fns.payload_285(buffer, tree, msgid, offset, limit, pinfo) value = tvbrange:le_uint() subtree = tree:add_le(f.GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags, tvbrange, value) dissect_flags_GIMBAL_DEVICE_ERROR_FLAGS(subtree, "GIMBAL_DEVICE_ATTITUDE_STATUS_failure_flags", tvbrange, value) + tvbrange = padded(offset + 40, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_DEVICE_ATTITUDE_STATUS_delta_yaw, tvbrange, value) + tvbrange = padded(offset + 44, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.GIMBAL_DEVICE_ATTITUDE_STATUS_delta_yaw_velocity, tvbrange, value) + tvbrange = padded(offset + 48, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.GIMBAL_DEVICE_ATTITUDE_STATUS_gimbal_device_id, tvbrange, value) end -- dissect payload of message type AUTOPILOT_STATE_FOR_GIMBAL_DEVICE function payload_fns.payload_286(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange - if (offset + 53 > limit) then + if (offset + 57 > limit) then padded = buffer(0, limit):bytes() - padded:set_size(offset + 53) + padded:set_size(offset + 57) padded = padded:tvb("Untruncated payload") else padded = buffer @@ -47723,54 +47942,48 @@ function payload_fns.payload_286(buffer, tree, msgid, offset, limit, pinfo) tvbrange = padded(offset + 52, 1) value = tvbrange:le_uint() subtree = tree:add_le(f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_landed_state, tvbrange, value) + tvbrange = padded(offset + 53, 4) + value = tvbrange:le_float() + subtree = tree:add_le(f.AUTOPILOT_STATE_FOR_GIMBAL_DEVICE_angular_velocity_z, tvbrange, value) end --- dissect payload of message type GIMBAL_MANAGER_SET_ATTITUDE -function payload_fns.payload_282(buffer, tree, msgid, offset, limit, pinfo) +-- dissect payload of message type GIMBAL_MANAGER_SET_PITCHYAW +function payload_fns.payload_287(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange - if (offset + 35 > limit) then + if (offset + 23 > limit) then padded = buffer(0, limit):bytes() - padded:set_size(offset + 35) + padded:set_size(offset + 23) padded = padded:tvb("Untruncated payload") else padded = buffer end - tvbrange = padded(offset + 32, 1) + tvbrange = padded(offset + 20, 1) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_target_system, tvbrange, value) - tvbrange = padded(offset + 33, 1) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_target_system, tvbrange, value) + tvbrange = padded(offset + 21, 1) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_target_component, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_target_component, tvbrange, value) tvbrange = padded(offset + 0, 4) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_flags, tvbrange, value) - dissect_flags_GIMBAL_MANAGER_FLAGS(subtree, "GIMBAL_MANAGER_SET_ATTITUDE_flags", tvbrange, value) - tvbrange = padded(offset + 34, 1) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_flags, tvbrange, value) + dissect_flags_GIMBAL_MANAGER_FLAGS(subtree, "GIMBAL_MANAGER_SET_PITCHYAW_flags", tvbrange, value) + tvbrange = padded(offset + 22, 1) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_gimbal_device_id, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_gimbal_device_id, tvbrange, value) tvbrange = padded(offset + 4, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_0, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_pitch, tvbrange, value) tvbrange = padded(offset + 8, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_1, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_yaw, tvbrange, value) tvbrange = padded(offset + 12, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_2, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_pitch_rate, tvbrange, value) tvbrange = padded(offset + 16, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_q_3, tvbrange, value) - tvbrange = padded(offset + 20, 4) - value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_x, tvbrange, value) - tvbrange = padded(offset + 24, 4) - value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_y, tvbrange, value) - tvbrange = padded(offset + 28, 4) - value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_ATTITUDE_angular_velocity_z, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_yaw_rate, tvbrange, value) end --- dissect payload of message type GIMBAL_MANAGER_SET_PITCHYAW -function payload_fns.payload_287(buffer, tree, msgid, offset, limit, pinfo) +-- dissect payload of message type GIMBAL_MANAGER_SET_MANUAL_CONTROL +function payload_fns.payload_288(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange if (offset + 23 > limit) then padded = buffer(0, limit):bytes() @@ -47781,29 +47994,29 @@ function payload_fns.payload_287(buffer, tree, msgid, offset, limit, pinfo) end tvbrange = padded(offset + 20, 1) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_target_system, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_target_system, tvbrange, value) tvbrange = padded(offset + 21, 1) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_target_component, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_target_component, tvbrange, value) tvbrange = padded(offset + 0, 4) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_flags, tvbrange, value) - dissect_flags_GIMBAL_MANAGER_FLAGS(subtree, "GIMBAL_MANAGER_SET_PITCHYAW_flags", tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags, tvbrange, value) + dissect_flags_GIMBAL_MANAGER_FLAGS(subtree, "GIMBAL_MANAGER_SET_MANUAL_CONTROL_flags", tvbrange, value) tvbrange = padded(offset + 22, 1) value = tvbrange:le_uint() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_gimbal_device_id, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_gimbal_device_id, tvbrange, value) tvbrange = padded(offset + 4, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_pitch, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_pitch, tvbrange, value) tvbrange = padded(offset + 8, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_yaw, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_yaw, tvbrange, value) tvbrange = padded(offset + 12, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_pitch_rate, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_pitch_rate, tvbrange, value) tvbrange = padded(offset + 16, 4) value = tvbrange:le_float() - subtree = tree:add_le(f.GIMBAL_MANAGER_SET_PITCHYAW_yaw_rate, tvbrange, value) + subtree = tree:add_le(f.GIMBAL_MANAGER_SET_MANUAL_CONTROL_yaw_rate, tvbrange, value) end -- dissect payload of message type WIFI_CONFIG_AP function payload_fns.payload_299(buffer, tree, msgid, offset, limit, pinfo) @@ -49140,6 +49353,26 @@ function payload_fns.payload_375(buffer, tree, msgid, offset, limit, pinfo) value = tvbrange:le_float() subtree = tree:add_le(f.ACTUATOR_OUTPUT_STATUS_actuator_31, tvbrange, value) end +-- dissect payload of message type RELAY_STATUS +function payload_fns.payload_376(buffer, tree, msgid, offset, limit, pinfo) + local padded, field_offset, value, subtree, tvbrange + if (offset + 8 > limit) then + padded = buffer(0, limit):bytes() + padded:set_size(offset + 8) + padded = padded:tvb("Untruncated payload") + else + padded = buffer + end + tvbrange = padded(offset + 0, 4) + value = tvbrange:le_uint() + subtree = tree:add_le(f.RELAY_STATUS_time_boot_ms, tvbrange, value) + tvbrange = padded(offset + 4, 2) + value = tvbrange:le_uint() + subtree = tree:add_le(f.RELAY_STATUS_on, tvbrange, value) + tvbrange = padded(offset + 6, 2) + value = tvbrange:le_uint() + subtree = tree:add_le(f.RELAY_STATUS_present, tvbrange, value) +end -- dissect payload of message type TUNNEL function payload_fns.payload_385(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange @@ -52107,6 +52340,37 @@ function payload_fns.payload_50005(buffer, tree, msgid, offset, limit, pinfo) value = tvbrange:le_uint() subtree = tree:add_le(f.CUBEPILOT_FIRMWARE_UPDATE_RESP_offset, tvbrange, value) end +-- dissect payload of message type AIRLINK_AUTH +function payload_fns.payload_52000(buffer, tree, msgid, offset, limit, pinfo) + local padded, field_offset, value, subtree, tvbrange + if (offset + 100 > limit) then + padded = buffer(0, limit):bytes() + padded:set_size(offset + 100) + padded = padded:tvb("Untruncated payload") + else + padded = buffer + end + tvbrange = padded(offset + 0, 50) + value = tvbrange:string() + subtree = tree:add_le(f.AIRLINK_AUTH_login, tvbrange, value) + tvbrange = padded(offset + 50, 50) + value = tvbrange:string() + subtree = tree:add_le(f.AIRLINK_AUTH_password, tvbrange, value) +end +-- dissect payload of message type AIRLINK_AUTH_RESPONSE +function payload_fns.payload_52001(buffer, tree, msgid, offset, limit, pinfo) + local padded, field_offset, value, subtree, tvbrange + if (offset + 1 > limit) then + padded = buffer(0, limit):bytes() + padded:set_size(offset + 1) + padded = padded:tvb("Untruncated payload") + else + padded = buffer + end + tvbrange = padded(offset + 0, 1) + value = tvbrange:le_uint() + subtree = tree:add_le(f.AIRLINK_AUTH_RESPONSE_resp_type, tvbrange, value) +end -- dissect payload of message type HEARTBEAT function payload_fns.payload_0(buffer, tree, msgid, offset, limit, pinfo) local padded, field_offset, value, subtree, tvbrange @@ -52233,9 +52497,9 @@ function mavlink_proto.dissector(buffer,pinfo,tree) offset = offset + 1 else -- handle truncated header - local hsize = buffer:len() - 2 - offset - subtree:add(f.rawheader, buffer(offset, hsize)) - offset = offset + hsize + pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT + pinfo.desegment_offset = offset + break end elseif (version == 0xfd) then if (buffer:len() - 2 - offset > 10) then @@ -52267,9 +52531,9 @@ function mavlink_proto.dissector(buffer,pinfo,tree) offset = offset + 3 else -- handle truncated header - local hsize = buffer:len() - 2 - offset - subtree:add(f.rawheader, buffer(offset, hsize)) - offset = offset + hsize + pinfo.desegment_len = DESEGMENT_ONE_MORE_SEGMENT + pinfo.desegment_offset = offset + break end end diff --git a/ExtLibs/Mavlink/message_definitions/ardupilotmega.xml b/ExtLibs/Mavlink/message_definitions/ardupilotmega.xml index d059979191..44369afc76 100644 --- a/ExtLibs/Mavlink/message_definitions/ardupilotmega.xml +++ b/ExtLibs/Mavlink/message_definitions/ardupilotmega.xml @@ -6,6 +6,7 @@ icarous.xml loweheiser.xml cubepilot.xml + csAirLink.xml 2 @@ -23,10 +24,6 @@ - - - - diff --git a/ExtLibs/Mavlink/message_definitions/common.xml b/ExtLibs/Mavlink/message_definitions/common.xml index 84b29c5202..769078adbf 100644 --- a/ExtLibs/Mavlink/message_definitions/common.xml +++ b/ExtLibs/Mavlink/message_definitions/common.xml @@ -400,43 +400,49 @@ - Gimbal device (low level) capability flags (bitmap) + Gimbal device (low level) capability flags (bitmap). - Gimbal device supports a retracted position + Gimbal device supports a retracted position. - Gimbal device supports a horizontal, forward looking position, stabilized + Gimbal device supports a horizontal, forward looking position, stabilized. Gimbal device supports rotating around roll axis. - Gimbal device supports to follow a roll angle relative to the vehicle + Gimbal device supports to follow a roll angle relative to the vehicle. - Gimbal device supports locking to an roll angle (generally that's the default with roll stabilized) + Gimbal device supports locking to a roll angle (generally that's the default with roll stabilized). Gimbal device supports rotating around pitch axis. - Gimbal device supports to follow a pitch angle relative to the vehicle + Gimbal device supports to follow a pitch angle relative to the vehicle. - Gimbal device supports locking to an pitch angle (generally that's the default with pitch stabilized) + Gimbal device supports locking to a pitch angle (generally that's the default with pitch stabilized). Gimbal device supports rotating around yaw axis. - Gimbal device supports to follow a yaw angle relative to the vehicle (generally that's the default) + Gimbal device supports to follow a yaw angle relative to the vehicle (generally that's the default). - Gimbal device supports locking to an absolute heading (often this is an option available) + Gimbal device supports locking to an absolute heading, i.e., yaw angle relative to North (earth frame, often this is an option available). Gimbal device supports yawing/panning infinetely (e.g. using slip disk). + + Gimbal device supports yaw angles and angular velocities relative to North (earth frame). This usually requires support by an autopilot via AUTOPILOT_STATE_FOR_GIMBAL_DEVICE. Support can go on and off during runtime, which is reported by the flag GIMBAL_DEVICE_FLAGS_CAN_ACCEPT_YAW_IN_EARTH_FRAME. + + + Gimbal device supports radio control inputs as an alternative input for controlling the gimbal orientation. + Gimbal manager high level capability flags (bitmap). The first 16 bits are identical to the GIMBAL_DEVICE_CAP_FLAGS. However, the gimbal manager does not need to copy the flags from the gimbal but can also enhance the capabilities and thus add flags. @@ -495,34 +501,64 @@ Set to retracted safe position (no stabilization), takes presedence over all other flags. - Set to neutral/default position, taking precedence over all other flags except RETRACT. Neutral is commonly forward-facing and horizontal (pitch=yaw=0) but may be any orientation. + Set to neutral/default position, taking precedence over all other flags except RETRACT. Neutral is commonly forward-facing and horizontal (roll=pitch=yaw=0) but may be any orientation. - Lock roll angle to absolute angle relative to horizon (not relative to drone). This is generally the default with a stabilizing gimbal. + Lock roll angle to absolute angle relative to horizon (not relative to vehicle). This is generally the default with a stabilizing gimbal. - Lock pitch angle to absolute angle relative to horizon (not relative to drone). This is generally the default. + Lock pitch angle to absolute angle relative to horizon (not relative to vehicle). This is generally the default with a stabilizing gimbal. - Lock yaw angle to absolute angle relative to North (not relative to drone). If this flag is set, the quaternion is in the Earth frame with the x-axis pointing North (yaw absolute). If this flag is not set, the quaternion frame is in the Earth frame rotated so that the x-axis is pointing forward (yaw relative to vehicle). + Lock yaw angle to absolute angle relative to North (not relative to vehicle). If this flag is set, the yaw angle and z component of angular velocity are relative to North (earth frame, x-axis pointing North), else they are relative to the vehicle heading (vehicle frame, earth frame rotated so that the x-axis is pointing forward). + + + Yaw angle and z component of angular velocity are relative to the vehicle heading (vehicle frame, earth frame rotated such that the x-axis is pointing forward). + + + Yaw angle and z component of angular velocity are relative to North (earth frame, x-axis is pointing North). + + + Gimbal device can accept yaw angle inputs relative to North (earth frame). This flag is only for reporting (attempts to set this flag are ignored). + + + The gimbal orientation is set exclusively by the RC signals feed to the gimbal's radio control inputs. MAVLink messages for setting the gimbal orientation (GIMBAL_DEVICE_SET_ATTITUDE) are ignored. + + + The gimbal orientation is determined by combining/mixing the RC signals feed to the gimbal's radio control inputs and the MAVLink messages for setting the gimbal orientation (GIMBAL_DEVICE_SET_ATTITUDE). How these two controls are combined or mixed is not defined by the protocol but is up to the implementation. Flags for high level gimbal manager operation The first 16 bits are identical to the GIMBAL_DEVICE_FLAGS. - Based on GIMBAL_DEVICE_FLAGS_RETRACT + Based on GIMBAL_DEVICE_FLAGS_RETRACT. - Based on GIMBAL_DEVICE_FLAGS_NEUTRAL + Based on GIMBAL_DEVICE_FLAGS_NEUTRAL. - Based on GIMBAL_DEVICE_FLAGS_ROLL_LOCK + Based on GIMBAL_DEVICE_FLAGS_ROLL_LOCK. - Based on GIMBAL_DEVICE_FLAGS_PITCH_LOCK + Based on GIMBAL_DEVICE_FLAGS_PITCH_LOCK. - Based on GIMBAL_DEVICE_FLAGS_YAW_LOCK + Based on GIMBAL_DEVICE_FLAGS_YAW_LOCK. + + + Based on GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME. + + + Based on GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME. + + + Based on GIMBAL_DEVICE_FLAGS_ACCEPTS_YAW_IN_EARTH_FRAME. + + + Based on GIMBAL_DEVICE_FLAGS_RC_EXCLUSIVE. + + + Based on GIMBAL_DEVICE_FLAGS_RC_MIXED. @@ -543,7 +579,7 @@ There is an error with the gimbal power source. - There is an error with the gimbal motor's. + There is an error with the gimbal motors. There is an error with the gimbal's software. @@ -552,7 +588,10 @@ There is an error with the gimbal's communication. - Gimbal is currently calibrating. + Gimbal device is currently calibrating. + + + Gimbal device is not assigned to a gimbal manager. @@ -964,9 +1003,9 @@ Reach a certain target angle. - target angle, 0 is north - angular speed - direction: -1: counter clockwise, 1: clockwise + target angle [0-360]. Absolute angles: 0 is north. Relative angle: 0 is initial yaw. Direction set by param3. + angular speed + direction: -1: counter clockwise, 0: shortest direction, 1: clockwise 0: absolute angle, 1: relative offset Empty Empty @@ -1003,8 +1042,8 @@ Empty - Change speed and/or throttle set points. - Speed type (0=Airspeed, 1=Ground Speed, 2=Climb Speed, 3=Descent Speed) + Change speed and/or throttle set points + Speed type of value set in param2 (such as airspeed, ground speed, and so on) Speed (-1 indicates no change, -2 indicates return to default vehicle speed) Throttle (-1 indicates no change, -2 indicates return to default vehicle throttle value) 0: absolute, 1: relative @@ -1378,7 +1417,7 @@ 0: Stop engine, 1:Start Engine 0: Warm start, 1:Cold start. Controls use of choke where applicable Height delay. This is for commanding engine start only after the vehicle has gained the specified height. Used in VTOL vehicles during takeoff to start engine after the aircraft is off the ground. Zero for no delay. - Empty + A bitmask of options for engine control Empty Empty Empty @@ -1612,9 +1651,7 @@ - - - High level setpoint to be sent to a gimbal manager to set a gimbal attitude. It is possible to set combinations of the values below. E.g. an angle as well as a desired angular rate can be used to get to this angle at a certain angular rate, or an angular rate only will result in continuous turning. NaN is to be used to signal unset. Note: a gimbal is never to react to this command but only the gimbal manager. + Set gimbal manager pitch/yaw setpoints (low rate command). It is possible to set combinations of the values below. E.g. an angle as well as a desired angular rate can be used to get to this angle at a certain angular rate, or an angular rate only will result in continuous turning. NaN is to be used to signal unset. Note: only the gimbal manager will react to this command - it will be ignored by a gimbal device. Use GIMBAL_MANAGER_SET_PITCHYAW if you need to stream pitch/yaw setpoints at higher rate. Pitch angle (positive to pitch up, relative to vehicle for FOLLOW mode, relative to world horizon for LOCK mode). Yaw angle (positive to yaw to the right, relative to vehicle for FOLLOW mode, absolute to North for LOCK mode). Pitch rate (positive to pitch up). @@ -1623,8 +1660,6 @@ Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals). - - Gimbal configuration to set which sysid/compid is in primary and secondary control. Sysid for primary control (0: no one in control, -1: leave unchanged, -2: set itself in control (for missions where the own sysid is still unknown), -3: remove control if currently in control). Compid for primary control (0: no one in control, -1: leave unchanged, -2: set itself in control (for missions where the own sysid is still unknown), -3: remove control if currently in control). @@ -1633,8 +1668,21 @@ Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals). - Start image capture sequence. Sends CAMERA_IMAGE_CAPTURED after each capture. Use NaN for reserved values. - Reserved (Set to 0) + Start image capture sequence. CAMERA_IMAGE_CAPTURED must be emitted after each capture. + + Param1 (id) may be used to specify the target camera: 0: all cameras, 1 to 6: autopilot-connected cameras, 7-255: MAVLink camera component ID. + It is needed in order to target specific cameras connected to the autopilot, or specific sensors in a multi-sensor camera (neither of which have a distinct MAVLink component ID). + It is also needed to specify the target camera in missions. + + When used in a mission, an autopilot should execute the MAV_CMD for a specified local camera (param1 = 1-6), or resend it as a command if it is intended for a MAVLink camera (param1 = 7 - 255), setting the command's target_component as the param1 value (and setting param1 in the command to zero). + If the param1 is 0 the autopilot should do both. + + When sent in a command the target MAVLink address is set using target_component. + If addressed specifically to an autopilot: param1 should be used in the same way as it is for missions (though command should NACK with MAV_RESULT_DENIED if a specified local camera does not exist). + If addressed to a MAVLink camera, param 1 can be used to address all cameras (0), or to separately address 1 to 7 individual sensors. Other values should be NACKed with MAV_RESULT_DENIED. + If the command is broadcast (target_component is 0) then param 1 should be set to 0 (any other value should be NACKED with MAV_RESULT_DENIED). An autopilot would trigger any local cameras and forward the command to all channels. + + Target camera ID. 7 to 255: MAVLink camera component id. 1 to 6 for cameras that don't have a distinct component id (such as autopilot-attached cameras). 0: all cameras. This is used to specifically target autopilot-connected cameras or individual sensors in a multi-sensor MAVLink camera. It is also used to target specific cameras when the MAV_CMD is used in a mission Desired elapsed time between two consecutive pictures (in seconds). Minimum values depend on hardware (typically greater than 2 seconds). Total number of images to capture. 0 to capture forever/until MAV_CMD_IMAGE_STOP_CAPTURE. Capture sequence number starting from 1. This is only valid for single-capture (param3 == 1), otherwise set to 0. Increment the capture ID for each capture command to prevent double captures when a command is re-transmitted. @@ -1643,8 +1691,21 @@ - Stop image capture sequence Use NaN for reserved values. - Reserved (Set to 0) + Stop image capture sequence. + + Param1 (id) may be used to specify the target camera: 0: all cameras, 1 to 6: autopilot-connected cameras, 7-255: MAVLink camera component ID. + It is needed in order to target specific cameras connected to the autopilot, or specific sensors in a multi-sensor camera (neither of which have a distinct MAVLink component ID). + It is also needed to specify the target camera in missions. + + When used in a mission, an autopilot should execute the MAV_CMD for a specified local camera (param1 = 1-6), or resend it as a command if it is intended for a MAVLink camera (param1 = 7 - 255), setting the command's target_component as the param1 value (and setting param1 in the command to zero). + If the param1 is 0 the autopilot should do both. + + When sent in a command the target MAVLink address is set using target_component. + If addressed specifically to an autopilot: param1 should be used in the same way as it is for missions (though command should NACK with MAV_RESULT_DENIED if a specified local camera does not exist). + If addressed to a MAVLink camera, param1 can be used to address all cameras (0), or to separately address 1 to 7 individual sensors. Other values should be NACKed with MAV_RESULT_DENIED. + If the command is broadcast (target_component is 0) then param 1 should be set to 0 (any other value should be NACKED with MAV_RESULT_DENIED). An autopilot would trigger any local cameras and forward the command to all channels. + + Target camera ID. 7 to 255: MAVLink camera component id. 1 to 6 for cameras that don't have a distinct component id (such as autopilot-attached cameras). 0: all cameras. This is used to specifically target autopilot-connected cameras or individual sensors in a multi-sensor MAVLink camera. It is also used to target specific cameras when the MAV_CMD is used in a mission @@ -2217,6 +2278,12 @@ Command is valid and is being executed. This will be followed by further progress updates, i.e. the component may send further COMMAND_ACK messages with result MAV_RESULT_IN_PROGRESS (at a rate decided by the implementation), and must terminate by sending a COMMAND_ACK message with final result of the operation. The COMMAND_ACK.progress field can be used to indicate the progress of the operation. There is no need for the sender to retry the command, but if done during execution, the component will return MAV_RESULT_IN_PROGRESS with an updated progress. + + Command is only accepted when sent as a COMMAND_LONG. + + + Command is only accepted when sent as a COMMAND_INT. + Result of mission operation (in a MISSION_ACK message). @@ -2894,6 +2961,21 @@ The aircraft should immediately transition into guided. This should not be set for follow me applications + + Speed setpoint types used in MAV_CMD_DO_CHANGE_SPEED + + Airspeed + + + Groundspeed + + + Climb speed + + + Descent speed + + Flags in ESTIMATOR_STATUS message @@ -3304,6 +3386,12 @@ Spektrum DSMX + + Engine control options + + Allow starting the engine once while disarmed + + Bitmap to indicate which dimensions should be ignored by the vehicle: a value of 0b0000000000000000 or 0b0000001000000000 indicates that none of the setpoint dimensions should be ignored. If bit 9 is set the floats afx afy afz should be interpreted as force instead of acceleration. @@ -4545,6 +4633,17 @@ Z-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to a separate slider movement with maximum being 1000 and minimum being -1000 on a joystick and the thrust of a vehicle. Positive values are positive thrust, negative values are negative thrust. R-axis, normalized to the range [-1000,1000]. A value of INT16_MAX indicates that this axis is invalid. Generally corresponds to a twisting of the joystick, with counter-clockwise being 1000 and clockwise being -1000, and the yaw of a vehicle. A bitfield corresponding to the joystick buttons' current state, 1 for pressed, 0 for released. The lowest bit corresponds to Button 1. + + A bitfield corresponding to the joystick buttons' 16-31 current state, 1 for pressed, 0 for released. The lowest bit corresponds to Button 16. + Set bits to 1 to indicate which of the following extension fields contain valid data: bit 0: pitch, bit 1: roll, bit 2: aux1, bit 3: aux2, bit 4: aux3, bit 5: aux4, bit 6: aux5, bit 7: aux6 + Pitch-only-axis, normalized to the range [-1000,1000]. Generally corresponds to pitch on vehicles with additional degrees of freedom. Valid if bit 0 of enabled_extensions field is set. Set to 0 if invalid. + Roll-only-axis, normalized to the range [-1000,1000]. Generally corresponds to roll on vehicles with additional degrees of freedom. Valid if bit 1 of enabled_extensions field is set. Set to 0 if invalid. + Aux continuous input field 1. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 2 of enabled_extensions field is set. 0 if bit 2 is unset. + Aux continuous input field 2. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 3 of enabled_extensions field is set. 0 if bit 3 is unset. + Aux continuous input field 3. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 4 of enabled_extensions field is set. 0 if bit 4 is unset. + Aux continuous input field 4. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 5 of enabled_extensions field is set. 0 if bit 5 is unset. + Aux continuous input field 5. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 6 of enabled_extensions field is set. 0 if bit 6 is unset. + Aux continuous input field 6. Normalized in the range [-1000,1000]. Purpose defined by recipient. Valid data if bit 7 of enabled_extensions field is set. 0 if bit 7 is unset. The RAW values of the RC channels sent to the MAV to override info received from the RC radio. The standard PPM modulation is as follows: 1000 microseconds: 0%, 2000 microseconds: 100%. Individual receivers/transmitters might violate this specification. Note carefully the semantic differences between the first 8 channels and the subsequent channels @@ -4815,8 +4914,8 @@ Optical flow from a flow sensor (e.g. optical mouse sensor) Timestamp (UNIX Epoch time or time since system boot). The receiving end can infer timestamp format (since 1.1.1970 or since system boot) by checking for the magnitude of the number. Sensor ID - Flow in x-sensor direction - Flow in y-sensor direction + Flow rate around X-axis (deprecated; use flow_rate_x) + Flow rate around Y-axis (deprecated; use flow_rate_y) Flow in x-sensor direction, angular-speed compensated Flow in y-sensor direction, angular-speed compensated Optical flow quality / confidence. 0: bad, 255: maximum quality @@ -4951,6 +5050,9 @@ True velocity in north direction in earth-fixed NED frame True velocity in east direction in earth-fixed NED frame True velocity in down direction in earth-fixed NED frame + + Latitude (higher precision). If 0, recipients should use the lat field value (otherwise this field is preferred). + Longitude (higher precision). If 0, recipients should use the lon field value (otherwise this field is preferred). Status generated by radio and injected into MAVLink stream. @@ -5721,6 +5823,8 @@ Bitmap of camera capability flags. Camera definition version (iteration). Use 0 if not known. Camera definition URI (if any, otherwise only basic functions will be available). HTTP- (http://) and MAVLink FTP- (mavlinkftp://) formatted URIs are allowed (and both must be supported by any GCS that implements the Camera Protocol). The definition file may be xz compressed, which will be indicated by the file extension .xml.xz (a GCS that implements the protocol must support decompressing the file). The string needs to be zero terminated. Use a zero-length string if not known. + + Gimbal id of a gimbal associated with this camera. This is the component id of the gimbal device, or 1-6 for non mavlink gimbals. Use 0 if no gimbal is associated with the camera. Settings of a camera. Can be requested with a MAV_CMD_REQUEST_MESSAGE command. @@ -5879,12 +5983,10 @@ Accuracy of heading, in NED. NAN if unknown - - Information about a high level gimbal manager. This message should be requested by a ground station using MAV_CMD_REQUEST_MESSAGE. Timestamp (time since system boot). Bitmap of gimbal capability flags. - Gimbal device ID that this gimbal manager is responsible for. + Gimbal device ID that this gimbal manager is responsible for. Component ID of gimbal device (or 1-6 for non-MAVLink gimbal). Minimum hardware roll angle (positive: rolling to the right, negative: rolling to the left) Maximum hardware roll angle (positive: rolling to the right, negative: rolling to the left) Minimum pitch angle (positive: up, negative: down) @@ -5893,17 +5995,26 @@ Maximum yaw angle (positive: to the right, negative: to the left) - - Current status about a high level gimbal manager. This message should be broadcast at a low regular rate (e.g. 5Hz). Timestamp (time since system boot). - High level gimbal manager flags currently applied. - Gimbal device ID that this gimbal manager is responsible for. + High level gimbal manager flags currently applied. + Gimbal device ID that this gimbal manager is responsible for. Component ID of gimbal device (or 1-6 for non-MAVLink gimbal). System ID of MAVLink component with primary control, 0 for none. Component ID of MAVLink component with primary control, 0 for none. System ID of MAVLink component with secondary control, 0 for none. Component ID of MAVLink component with secondary control, 0 for none. + + High level message to control a gimbal's attitude. This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. + System ID + Component ID + High level gimbal manager flags to use. + Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals). + Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_MANAGER_FLAGS_YAW_LOCK is set) + X component of angular velocity, positive is rolling to the right, NaN to be ignored. + Y component of angular velocity, positive is pitching up, NaN to be ignored. + Z component of angular velocity, positive is yawing to the right, NaN to be ignored. + Information about a low level gimbal. This message should be requested by the gimbal manager or a ground station using MAV_CMD_REQUEST_MESSAGE. The maximum angles and rates are the limits by hardware. However, the limits by software used are likely different/smaller and dependent on mode/settings/etc.. Timestamp (time since system boot). @@ -5915,71 +6026,85 @@ UID of gimbal hardware (0 if unknown). Bitmap of gimbal capability flags. Bitmap for use for gimbal-specific capability flags. - Minimum hardware roll angle (positive: rolling to the right, negative: rolling to the left) - Maximum hardware roll angle (positive: rolling to the right, negative: rolling to the left) - Minimum hardware pitch angle (positive: up, negative: down) - Maximum hardware pitch angle (positive: up, negative: down) - Minimum hardware yaw angle (positive: to the right, negative: to the left) - Maximum hardware yaw angle (positive: to the right, negative: to the left) + Minimum hardware roll angle (positive: rolling to the right, negative: rolling to the left). NAN if unknown. + Maximum hardware roll angle (positive: rolling to the right, negative: rolling to the left). NAN if unknown. + Minimum hardware pitch angle (positive: up, negative: down). NAN if unknown. + Maximum hardware pitch angle (positive: up, negative: down). NAN if unknown. + Minimum hardware yaw angle (positive: to the right, negative: to the left). NAN if unknown. + Maximum hardware yaw angle (positive: to the right, negative: to the left). NAN if unknown. + + This field is to be used if the gimbal manager and the gimbal device are the same component and hence have the same component ID. This field is then set to a number between 1-6. If the component ID is separate, this field is not required and must be set to 0. - - - Low level message to control a gimbal device's attitude. This message is to be sent from the gimbal manager to the gimbal device component. Angles and rates can be set to NaN according to use case. + Low level message to control a gimbal device's attitude. + This message is to be sent from the gimbal manager to the gimbal device component. + The quaternion and angular velocities can be set to NaN according to use case. + For the angles encoded in the quaternion and the angular velocities holds: + If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME is set, then they are relative to the vehicle heading (vehicle frame). + If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME is set, then they are relative to absolute North (earth frame). + If neither of these flags are set, then (for backwards compatibility) it holds: + If the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set, then they are relative to absolute North (earth frame), + else they are relative to the vehicle heading (vehicle frame). + Setting both GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME and GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME is not allowed. + These rules are to ensure backwards compatibility. + New implementations should always set either GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME or GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME. System ID Component ID Low level gimbal flags. - Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set, set all fields to NaN if only angular velocity should be used) - X component of angular velocity, positive is rolling to the right, NaN to be ignored. - Y component of angular velocity, positive is pitching up, NaN to be ignored. - Z component of angular velocity, positive is yawing to the right, NaN to be ignored. + Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation). The frame is described in the message description. Set fields to NaN to be ignored. + X component of angular velocity (positive: rolling to the right). The frame is described in the message description. NaN to be ignored. + Y component of angular velocity (positive: pitching up). The frame is described in the message description. NaN to be ignored. + Z component of angular velocity (positive: yawing to the right). The frame is described in the message description. NaN to be ignored. - - - Message reporting the status of a gimbal device. This message should be broadcasted by a gimbal device component. The angles encoded in the quaternion are relative to absolute North if the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set (roll: positive is rolling to the right, pitch: positive is pitching up, yaw is turn to the right) or relative to the vehicle heading if the flag is not set. This message should be broadcast at a low regular rate (e.g. 10Hz). + Message reporting the status of a gimbal device. + This message should be broadcast by a gimbal device component at a low regular rate (e.g. 5 Hz). + For the angles encoded in the quaternion and the angular velocities holds: + If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME is set, then they are relative to the vehicle heading (vehicle frame). + If the flag GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME is set, then they are relative to absolute North (earth frame). + If neither of these flags are set, then (for backwards compatibility) it holds: + If the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set, then they are relative to absolute North (earth frame), + else they are relative to the vehicle heading (vehicle frame). + Other conditions of the flags are not allowed. + The quaternion and angular velocities in the other frame can be calculated from delta_yaw and delta_yaw_velocity as + q_earth = q_delta_yaw * q_vehicle and w_earth = w_delta_yaw_velocity + w_vehicle (if not NaN). + If neither the GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME nor the GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME flag is set, + then (for backwards compatibility) the data in the delta_yaw and delta_yaw_velocity fields are to be ignored. + New implementations should always set either GIMBAL_DEVICE_FLAGS_YAW_IN_VEHICLE_FRAME or GIMBAL_DEVICE_FLAGS_YAW_IN_EARTH_FRAME, + and always should set delta_yaw and delta_yaw_velocity either to the proper value or NaN. System ID Component ID Timestamp (time since system boot). Current gimbal flags set. - Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_DEVICE_FLAGS_YAW_LOCK is set) - X component of angular velocity (NaN if unknown) - Y component of angular velocity (NaN if unknown) - Z component of angular velocity (NaN if unknown) - Failure flags (0 for no failure) + Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation). The frame is described in the message description. + X component of angular velocity (positive: rolling to the right). The frame is described in the message description. NaN if unknown. + Y component of angular velocity (positive: pitching up). The frame is described in the message description. NaN if unknown. + Z component of angular velocity (positive: yawing to the right). The frame is described in the message description. NaN if unknown. + Failure flags (0 for no failure) + + Yaw angle relating the quaternions in earth and body frames (see message description). NaN if unknown. + Yaw angular velocity relating the angular velocities in earth and body frames (see message description). NaN if unknown. + This field is to be used if the gimbal manager and the gimbal device are the same component and hence have the same component ID. This field is then set a number between 1-6. If the component ID is separate, this field is not required and must be set to 0. - Low level message containing autopilot state relevant for a gimbal device. This message is to be sent from the gimbal manager to the gimbal device component. The data of this message server for the gimbal's estimator corrections in particular horizon compensation, as well as the autopilot's control intention e.g. feed forward angular control in z-axis. + Low level message containing autopilot state relevant for a gimbal device. This message is to be sent from the autopilot to the gimbal device component. The data of this message are for the gimbal device's estimator corrections, in particular horizon compensation, as well as indicates autopilot control intentions, e.g. feed forward angular control in the z-axis. System ID Component ID Timestamp (time since system boot). Quaternion components of autopilot attitude: w, x, y, z (1 0 0 0 is the null-rotation, Hamilton convention). - Estimated delay of the attitude data. - X Speed in NED (North, East, Down). - Y Speed in NED (North, East, Down). - Z Speed in NED (North, East, Down). - Estimated delay of the speed data. - Feed forward Z component of angular velocity, positive is yawing to the right, NaN to be ignored. This is to indicate if the autopilot is actively yawing. + Estimated delay of the attitude data. 0 if unknown. + X Speed in NED (North, East, Down). NAN if unknown. + Y Speed in NED (North, East, Down). NAN if unknown. + Z Speed in NED (North, East, Down). NAN if unknown. + Estimated delay of the speed data. 0 if unknown. + Feed forward Z component of angular velocity (positive: yawing to the right). NaN to be ignored. This is to indicate if the autopilot is actively yawing. Bitmap indicating which estimator outputs are valid. The landed state. Is set to MAV_LANDED_STATE_UNDEFINED if landed state is unknown. - - - - - High level message to control a gimbal's attitude. This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. - System ID - Component ID - High level gimbal manager flags to use. - Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals). - Quaternion components, w, x, y, z (1 0 0 0 is the null-rotation, the frame is depends on whether the flag GIMBAL_MANAGER_FLAGS_YAW_LOCK is set) - X component of angular velocity, positive is rolling to the right, NaN to be ignored. - Y component of angular velocity, positive is pitching up, NaN to be ignored. - Z component of angular velocity, positive is yawing to the right, NaN to be ignored. + + Z component of angular velocity in NED (North, East, Down). NaN if unknown. - - - High level message to control a gimbal's pitch and yaw angles. This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. + Set gimbal manager pitch and yaw angles (high rate message). This message is to be sent to the gimbal manager (e.g. from a ground station) and will be ignored by gimbal devices. Angles and rates can be set to NaN according to use case. Use MAV_CMD_DO_GIMBAL_MANAGER_PITCHYAW for low-rate adjustments that require confirmation. System ID Component ID High level gimbal manager flags to use. @@ -5989,6 +6114,17 @@ Pitch angular rate (positive: up, negative: down, NaN to be ignored). Yaw angular rate (positive: to the right, negative: to the left, NaN to be ignored). + + High level message to control a gimbal manually. The angles or angular rates are unitless; the actual rates will depend on internal gimbal manager settings/configuration (e.g. set by parameters). This message is to be sent to the gimbal manager (e.g. from a ground station). Angles and rates can be set to NaN according to use case. + System ID + Component ID + High level gimbal manager flags. + Component ID of gimbal device to address (or 1-6 for non-MAVLink gimbal), 0 for all gimbal device components. Send command multiple times for more than one gimbal (but not all gimbals). + Pitch angle unitless (-1..1, positive: up, negative: down, NaN to be ignored). + Yaw angle unitless (-1..1, positive: to the right, negative: to the left, NaN to be ignored). + Pitch angular rate unitless (-1..1, positive: up, negative: down, NaN to be ignored). + Yaw angular rate unitless (-1..1, positive: to the right, negative: to the left, NaN to be ignored). + Configure WiFi AP SSID, password, and mode. This message is re-emitted as an acknowledgement by the AP. The message may also be explicitly requested using MAV_CMD_REQUEST_MESSAGE Name of Wi-Fi network (SSID). Blank to leave it unchanged when setting. Current SSID when sent back as a response. @@ -6195,6 +6331,12 @@ Active outputs Servo / motor output array values. Zero values indicate unused channels. + + Reports the on/off state of relays, as controlled by MAV_CMD_DO_SET_RELAY. + Timestamp (time since system boot). + Relay states. Relay instance numbers are represented as individual bits in this mask by offset. + Relay present. Relay instance numbers are represented as individual bits in this mask by offset. Bits will be true if a relay instance is configured. + Message for transporting "arbitrary" variable-length data from one component to another (broadcast is not forbidden, but discouraged). The encoding of the data is usually extension specific, i.e. determined by the source, and is usually not documented as part of the MAVLink specification. System ID (can be 0 for broadcast, but this is discouraged) diff --git a/ExtLibs/Mavlink/message_definitions/csAirLink.xml b/ExtLibs/Mavlink/message_definitions/csAirLink.xml new file mode 100644 index 0000000000..063d76367e --- /dev/null +++ b/ExtLibs/Mavlink/message_definitions/csAirLink.xml @@ -0,0 +1,30 @@ + + + + + + + 3 + + + + Login or password error + + + Auth successful + + + + + + Authorization package + Login + Password + + + Response to the authorization request + Response type + + + + diff --git a/ExtLibs/Mavlink/updatexmls.bat b/ExtLibs/Mavlink/updatexmls.bat index 59614334c4..bafde026ac 100644 --- a/ExtLibs/Mavlink/updatexmls.bat +++ b/ExtLibs/Mavlink/updatexmls.bat @@ -13,4 +13,6 @@ python -c "import urllib.request; print(urllib.request.urlopen('https://github.c python -c "import urllib.request; print(urllib.request.urlopen('https://github.com/ArduPilot/mavlink/raw/master/message_definitions/v1.0/cubepilot.xml').read().decode('utf-8') )" > message_definitions\cubepilot.xml +python -c "import urllib.request; print(urllib.request.urlopen('https://github.com/ArduPilot/mavlink/raw/master/message_definitions/v1.0/csAirLink.xml').read().decode('utf-8') )" > message_definitions\csAirLink.xml + pause \ No newline at end of file From 8d9fbaf3f5a1d58c16fb5e8dc05f60506a9fb511 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Mon, 22 Jan 2024 12:28:47 +1100 Subject: [PATCH 14/44] px4uploader: fix extf crc generation - no padding --- ExtLibs/px4uploader/Firmware.cs | 4 ---- 1 file changed, 4 deletions(-) diff --git a/ExtLibs/px4uploader/Firmware.cs b/ExtLibs/px4uploader/Firmware.cs index c7e77983f5..6f521a4826 100644 --- a/ExtLibs/px4uploader/Firmware.cs +++ b/ExtLibs/px4uploader/Firmware.cs @@ -180,10 +180,6 @@ public int extf_crc(int padlen) { uint state = __crc32(extf_imagebyte, 0); - for (int i = extf_imagebyte.Length; i < (padlen - 1); i += 4) - { - state = __crc32(crcpad, state); - } return (int)state; } } From 789ba847cd0fc74a7f2825dbe3b22f3d1c023c93 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Mon, 22 Jan 2024 12:32:36 +1100 Subject: [PATCH 15/44] MissionPlanner sln remove x86 --- MissionPlanner.sln | 342 +-------------------------------------------- 1 file changed, 2 insertions(+), 340 deletions(-) diff --git a/MissionPlanner.sln b/MissionPlanner.sln index 0a43b51d4d..071bcefbd6 100644 --- a/MissionPlanner.sln +++ b/MissionPlanner.sln @@ -228,669 +228,331 @@ EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU - Debug|x86 = Debug|x86 Release|Any CPU = Release|Any CPU - Release|x86 = Release|x86 EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Debug|x86.ActiveCfg = Debug|Any CPU - {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Debug|x86.Build.0 = Debug|Any CPU {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Release|Any CPU.ActiveCfg = Release|Any CPU {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Release|Any CPU.Build.0 = Release|Any CPU - {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Release|x86.ActiveCfg = Release|Any CPU - {A2E22272-95FE-47B6-B050-9AE7E2055BF5}.Release|x86.Build.0 = Release|Any CPU {E64A1A41-A5B0-458E-8284-BB63705354DA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E64A1A41-A5B0-458E-8284-BB63705354DA}.Debug|x86.ActiveCfg = Debug|Any CPU - {E64A1A41-A5B0-458E-8284-BB63705354DA}.Debug|x86.Build.0 = Debug|Any CPU {E64A1A41-A5B0-458E-8284-BB63705354DA}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E64A1A41-A5B0-458E-8284-BB63705354DA}.Release|x86.ActiveCfg = Release|Any CPU - {E64A1A41-A5B0-458E-8284-BB63705354DA}.Release|x86.Build.0 = Release|Any CPU {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Debug|Any CPU.Build.0 = Debug|Any CPU - {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Debug|x86.ActiveCfg = Debug|Any CPU - {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Debug|x86.Build.0 = Debug|Any CPU {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Release|Any CPU.ActiveCfg = Release|Any CPU {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Release|Any CPU.Build.0 = Release|Any CPU - {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Release|x86.ActiveCfg = Release|Any CPU - {76374F95-C343-4ACC-B86F-7ECFDD668F46}.Release|x86.Build.0 = Release|Any CPU {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Debug|x86.ActiveCfg = Debug|Any CPU - {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Debug|x86.Build.0 = Debug|Any CPU {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Release|Any CPU.ActiveCfg = Release|Any CPU {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Release|Any CPU.Build.0 = Release|Any CPU - {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Release|x86.ActiveCfg = Release|Any CPU - {6A6F4345-0A45-413E-B6D6-FD73660DAD4C}.Release|x86.Build.0 = Release|Any CPU {94C380C1-566A-4D86-855B-2E987851BF0A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {94C380C1-566A-4D86-855B-2E987851BF0A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {94C380C1-566A-4D86-855B-2E987851BF0A}.Debug|x86.ActiveCfg = Debug|Any CPU - {94C380C1-566A-4D86-855B-2E987851BF0A}.Debug|x86.Build.0 = Debug|Any CPU {94C380C1-566A-4D86-855B-2E987851BF0A}.Release|Any CPU.ActiveCfg = Release|Any CPU {94C380C1-566A-4D86-855B-2E987851BF0A}.Release|Any CPU.Build.0 = Release|Any CPU - {94C380C1-566A-4D86-855B-2E987851BF0A}.Release|x86.ActiveCfg = Release|Any CPU - {94C380C1-566A-4D86-855B-2E987851BF0A}.Release|x86.Build.0 = Release|Any CPU {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Debug|x86.ActiveCfg = Debug|Any CPU - {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Debug|x86.Build.0 = Debug|Any CPU {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Release|Any CPU.Build.0 = Release|Any CPU - {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Release|x86.ActiveCfg = Release|Any CPU - {28D0BEF6-D69C-43AB-A22C-724F116D50EA}.Release|x86.Build.0 = Release|Any CPU {A7AA6037-BF11-473E-94F9-717276FE080C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A7AA6037-BF11-473E-94F9-717276FE080C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A7AA6037-BF11-473E-94F9-717276FE080C}.Debug|x86.ActiveCfg = Debug|Any CPU - {A7AA6037-BF11-473E-94F9-717276FE080C}.Debug|x86.Build.0 = Debug|Any CPU {A7AA6037-BF11-473E-94F9-717276FE080C}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7AA6037-BF11-473E-94F9-717276FE080C}.Release|Any CPU.Build.0 = Release|Any CPU - {A7AA6037-BF11-473E-94F9-717276FE080C}.Release|x86.ActiveCfg = Release|Any CPU - {A7AA6037-BF11-473E-94F9-717276FE080C}.Release|x86.Build.0 = Release|Any CPU {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Debug|x86.ActiveCfg = Debug|Any CPU - {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Debug|x86.Build.0 = Debug|Any CPU {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Release|Any CPU.ActiveCfg = Release|Any CPU {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Release|Any CPU.Build.0 = Release|Any CPU - {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Release|x86.ActiveCfg = Release|Any CPU - {ABB32A29-AF50-47FA-B243-5FD75A5ABA54}.Release|x86.Build.0 = Release|Any CPU {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Debug|Any CPU.Build.0 = Debug|Any CPU - {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Debug|x86.ActiveCfg = Debug|Any CPU - {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Debug|x86.Build.0 = Debug|Any CPU {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Release|Any CPU.ActiveCfg = Release|Any CPU {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Release|Any CPU.Build.0 = Release|Any CPU - {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Release|x86.ActiveCfg = Release|Any CPU - {59129078-7B12-4198-B93E-0AA08D0BB7ED}.Release|x86.Build.0 = Release|Any CPU {29976BA4-A04D-4A80-A866-098C879C2FDE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {29976BA4-A04D-4A80-A866-098C879C2FDE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {29976BA4-A04D-4A80-A866-098C879C2FDE}.Debug|x86.ActiveCfg = Debug|Any CPU - {29976BA4-A04D-4A80-A866-098C879C2FDE}.Debug|x86.Build.0 = Debug|Any CPU {29976BA4-A04D-4A80-A866-098C879C2FDE}.Release|Any CPU.ActiveCfg = Release|Any CPU {29976BA4-A04D-4A80-A866-098C879C2FDE}.Release|Any CPU.Build.0 = Release|Any CPU - {29976BA4-A04D-4A80-A866-098C879C2FDE}.Release|x86.ActiveCfg = Release|Any CPU - {29976BA4-A04D-4A80-A866-098C879C2FDE}.Release|x86.Build.0 = Release|Any CPU {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Debug|x86.ActiveCfg = Debug|Any CPU - {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Debug|x86.Build.0 = Debug|Any CPU {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Release|Any CPU.ActiveCfg = Release|Any CPU {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Release|Any CPU.Build.0 = Release|Any CPU - {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Release|x86.ActiveCfg = Release|Any CPU - {53F12A60-E9CC-44BC-8366-1AE3AB2B547D}.Release|x86.Build.0 = Release|Any CPU {2541686B-1673-43BF-AF89-3163945DB009}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2541686B-1673-43BF-AF89-3163945DB009}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2541686B-1673-43BF-AF89-3163945DB009}.Debug|x86.ActiveCfg = Debug|Any CPU - {2541686B-1673-43BF-AF89-3163945DB009}.Debug|x86.Build.0 = Debug|Any CPU {2541686B-1673-43BF-AF89-3163945DB009}.Release|Any CPU.ActiveCfg = Release|Any CPU {2541686B-1673-43BF-AF89-3163945DB009}.Release|Any CPU.Build.0 = Release|Any CPU - {2541686B-1673-43BF-AF89-3163945DB009}.Release|x86.ActiveCfg = Release|Any CPU - {2541686B-1673-43BF-AF89-3163945DB009}.Release|x86.Build.0 = Release|Any CPU {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Debug|x86.ActiveCfg = Debug|Any CPU - {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Debug|x86.Build.0 = Debug|Any CPU {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Release|Any CPU.ActiveCfg = Release|Any CPU {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Release|Any CPU.Build.0 = Release|Any CPU - {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Release|x86.ActiveCfg = Release|Any CPU - {9CA367B8-0B98-49D1-84FB-735E612E3BA9}.Release|x86.Build.0 = Release|Any CPU {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Debug|x86.ActiveCfg = Debug|Any CPU - {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Debug|x86.Build.0 = Debug|Any CPU {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Release|Any CPU.ActiveCfg = Release|Any CPU {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Release|Any CPU.Build.0 = Release|Any CPU - {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Release|x86.ActiveCfg = Release|Any CPU - {B46F6C6C-9184-41AF-8F8B-E0084752CA7C}.Release|x86.Build.0 = Release|Any CPU {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Debug|x86.ActiveCfg = Debug|Any CPU - {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Debug|x86.Build.0 = Debug|Any CPU {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Release|Any CPU.ActiveCfg = Release|Any CPU {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Release|Any CPU.Build.0 = Release|Any CPU - {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Release|x86.ActiveCfg = Release|Any CPU - {2A8E8AF5-74E7-49DB-A42E-9360FA7A6CC4}.Release|x86.Build.0 = Release|Any CPU {C8B88795-6D01-494D-83AD-6944BD4C5023}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {C8B88795-6D01-494D-83AD-6944BD4C5023}.Debug|Any CPU.Build.0 = Debug|Any CPU - {C8B88795-6D01-494D-83AD-6944BD4C5023}.Debug|x86.ActiveCfg = Debug|Any CPU - {C8B88795-6D01-494D-83AD-6944BD4C5023}.Debug|x86.Build.0 = Debug|Any CPU {C8B88795-6D01-494D-83AD-6944BD4C5023}.Release|Any CPU.ActiveCfg = Release|Any CPU {C8B88795-6D01-494D-83AD-6944BD4C5023}.Release|Any CPU.Build.0 = Release|Any CPU - {C8B88795-6D01-494D-83AD-6944BD4C5023}.Release|x86.ActiveCfg = Release|Any CPU - {C8B88795-6D01-494D-83AD-6944BD4C5023}.Release|x86.Build.0 = Release|Any CPU {825E7A10-390C-4A2B-B3A8-491D14966912}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {825E7A10-390C-4A2B-B3A8-491D14966912}.Debug|Any CPU.Build.0 = Debug|Any CPU - {825E7A10-390C-4A2B-B3A8-491D14966912}.Debug|x86.ActiveCfg = Debug|Any CPU - {825E7A10-390C-4A2B-B3A8-491D14966912}.Debug|x86.Build.0 = Debug|Any CPU {825E7A10-390C-4A2B-B3A8-491D14966912}.Release|Any CPU.ActiveCfg = Release|Any CPU {825E7A10-390C-4A2B-B3A8-491D14966912}.Release|Any CPU.Build.0 = Release|Any CPU - {825E7A10-390C-4A2B-B3A8-491D14966912}.Release|x86.ActiveCfg = Release|Any CPU - {825E7A10-390C-4A2B-B3A8-491D14966912}.Release|x86.Build.0 = Release|Any CPU {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Debug|x86.ActiveCfg = Debug|Any CPU - {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Debug|x86.Build.0 = Debug|Any CPU {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Release|Any CPU.ActiveCfg = Release|Any CPU {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Release|Any CPU.Build.0 = Release|Any CPU - {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Release|x86.ActiveCfg = Release|Any CPU - {1378A66C-38E4-46F5-A05F-DC04EF7D4D16}.Release|x86.Build.0 = Release|Any CPU {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Debug|x86.ActiveCfg = Debug|Any CPU - {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Debug|x86.Build.0 = Debug|Any CPU {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Release|Any CPU.ActiveCfg = Release|Any CPU {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Release|Any CPU.Build.0 = Release|Any CPU - {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Release|x86.ActiveCfg = Release|Any CPU - {7F7994CE-823F-4A04-BBEA-D0A3808FF56D}.Release|x86.Build.0 = Release|Any CPU {664FC484-2A94-4B0D-808F-A71F88E06B11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {664FC484-2A94-4B0D-808F-A71F88E06B11}.Debug|Any CPU.Build.0 = Debug|Any CPU - {664FC484-2A94-4B0D-808F-A71F88E06B11}.Debug|x86.ActiveCfg = Debug|Any CPU - {664FC484-2A94-4B0D-808F-A71F88E06B11}.Debug|x86.Build.0 = Debug|Any CPU {664FC484-2A94-4B0D-808F-A71F88E06B11}.Release|Any CPU.ActiveCfg = Release|Any CPU {664FC484-2A94-4B0D-808F-A71F88E06B11}.Release|Any CPU.Build.0 = Release|Any CPU - {664FC484-2A94-4B0D-808F-A71F88E06B11}.Release|x86.ActiveCfg = Release|Any CPU - {664FC484-2A94-4B0D-808F-A71F88E06B11}.Release|x86.Build.0 = Release|Any CPU {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Debug|x86.ActiveCfg = Debug|Any CPU - {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Debug|x86.Build.0 = Debug|Any CPU {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Release|Any CPU.ActiveCfg = Release|Any CPU {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Release|Any CPU.Build.0 = Release|Any CPU - {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Release|x86.ActiveCfg = Release|Any CPU - {D0C39D9D-BED0-418B-9A5E-713176CAF40C}.Release|x86.Build.0 = Release|Any CPU {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Debug|x86.ActiveCfg = Debug|Any CPU - {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Debug|x86.Build.0 = Debug|Any CPU {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Release|Any CPU.ActiveCfg = Release|Any CPU {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Release|Any CPU.Build.0 = Release|Any CPU - {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Release|x86.ActiveCfg = Release|Any CPU - {E06DEF77-F933-42FB-AFD7-DB2D0D8D6A98}.Release|x86.Build.0 = Release|Any CPU {ABA78B2E-77C3-4377-8568-9542AC227971}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {ABA78B2E-77C3-4377-8568-9542AC227971}.Debug|Any CPU.Build.0 = Debug|Any CPU - {ABA78B2E-77C3-4377-8568-9542AC227971}.Debug|x86.ActiveCfg = Debug|Any CPU - {ABA78B2E-77C3-4377-8568-9542AC227971}.Debug|x86.Build.0 = Debug|Any CPU {ABA78B2E-77C3-4377-8568-9542AC227971}.Release|Any CPU.ActiveCfg = Release|Any CPU {ABA78B2E-77C3-4377-8568-9542AC227971}.Release|Any CPU.Build.0 = Release|Any CPU - {ABA78B2E-77C3-4377-8568-9542AC227971}.Release|x86.ActiveCfg = Release|Any CPU - {ABA78B2E-77C3-4377-8568-9542AC227971}.Release|x86.Build.0 = Release|Any CPU {B5211B56-CA30-4B2A-843B-832849F18CEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B5211B56-CA30-4B2A-843B-832849F18CEA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B5211B56-CA30-4B2A-843B-832849F18CEA}.Debug|x86.ActiveCfg = Debug|Any CPU - {B5211B56-CA30-4B2A-843B-832849F18CEA}.Debug|x86.Build.0 = Debug|Any CPU {B5211B56-CA30-4B2A-843B-832849F18CEA}.Release|Any CPU.ActiveCfg = Release|Any CPU {B5211B56-CA30-4B2A-843B-832849F18CEA}.Release|Any CPU.Build.0 = Release|Any CPU - {B5211B56-CA30-4B2A-843B-832849F18CEA}.Release|x86.ActiveCfg = Release|Any CPU - {B5211B56-CA30-4B2A-843B-832849F18CEA}.Release|x86.Build.0 = Release|Any CPU {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Debug|x86.ActiveCfg = Debug|Any CPU - {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Debug|x86.Build.0 = Debug|Any CPU {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Release|Any CPU.ActiveCfg = Release|Any CPU {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Release|Any CPU.Build.0 = Release|Any CPU - {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Release|x86.ActiveCfg = Release|Any CPU - {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Release|x86.Build.0 = Release|Any CPU {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Debug|x86.ActiveCfg = Debug|Any CPU - {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Debug|x86.Build.0 = Debug|Any CPU {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Release|Any CPU.Build.0 = Release|Any CPU - {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Release|x86.ActiveCfg = Release|Any CPU - {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Release|x86.Build.0 = Release|Any CPU {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Debug|x86.ActiveCfg = Debug|Any CPU - {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Debug|x86.Build.0 = Debug|Any CPU {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Release|Any CPU.ActiveCfg = Release|Any CPU {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Release|Any CPU.Build.0 = Release|Any CPU - {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Release|x86.ActiveCfg = Release|Any CPU - {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Release|x86.Build.0 = Release|Any CPU {65473257-E70F-410B-9269-D0C0F771EA87}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {65473257-E70F-410B-9269-D0C0F771EA87}.Debug|Any CPU.Build.0 = Debug|Any CPU - {65473257-E70F-410B-9269-D0C0F771EA87}.Debug|x86.ActiveCfg = Debug|Any CPU - {65473257-E70F-410B-9269-D0C0F771EA87}.Debug|x86.Build.0 = Debug|Any CPU {65473257-E70F-410B-9269-D0C0F771EA87}.Release|Any CPU.ActiveCfg = Release|Any CPU {65473257-E70F-410B-9269-D0C0F771EA87}.Release|Any CPU.Build.0 = Release|Any CPU - {65473257-E70F-410B-9269-D0C0F771EA87}.Release|x86.ActiveCfg = Release|Any CPU - {65473257-E70F-410B-9269-D0C0F771EA87}.Release|x86.Build.0 = Release|Any CPU {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Debug|x86.ActiveCfg = Debug|Any CPU - {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Debug|x86.Build.0 = Debug|Any CPU {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Release|Any CPU.ActiveCfg = Release|Any CPU {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Release|Any CPU.Build.0 = Release|Any CPU - {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Release|x86.ActiveCfg = Release|Any CPU - {098F542C-7C70-4B9C-B2E2-AC5DC5E0294B}.Release|x86.Build.0 = Release|Any CPU {CF402948-A3F4-4962-8A57-E40B46759D25}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CF402948-A3F4-4962-8A57-E40B46759D25}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CF402948-A3F4-4962-8A57-E40B46759D25}.Debug|x86.ActiveCfg = Debug|Any CPU - {CF402948-A3F4-4962-8A57-E40B46759D25}.Debug|x86.Build.0 = Debug|Any CPU {CF402948-A3F4-4962-8A57-E40B46759D25}.Release|Any CPU.ActiveCfg = Release|Any CPU {CF402948-A3F4-4962-8A57-E40B46759D25}.Release|Any CPU.Build.0 = Release|Any CPU - {CF402948-A3F4-4962-8A57-E40B46759D25}.Release|x86.ActiveCfg = Release|Any CPU - {CF402948-A3F4-4962-8A57-E40B46759D25}.Release|x86.Build.0 = Release|Any CPU {766FCF85-4809-44DB-B316-6C4902C65245}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {766FCF85-4809-44DB-B316-6C4902C65245}.Debug|Any CPU.Build.0 = Debug|Any CPU - {766FCF85-4809-44DB-B316-6C4902C65245}.Debug|x86.ActiveCfg = Debug|Any CPU - {766FCF85-4809-44DB-B316-6C4902C65245}.Debug|x86.Build.0 = Debug|Any CPU {766FCF85-4809-44DB-B316-6C4902C65245}.Release|Any CPU.ActiveCfg = Release|Any CPU {766FCF85-4809-44DB-B316-6C4902C65245}.Release|Any CPU.Build.0 = Release|Any CPU - {766FCF85-4809-44DB-B316-6C4902C65245}.Release|x86.ActiveCfg = Release|Any CPU - {766FCF85-4809-44DB-B316-6C4902C65245}.Release|x86.Build.0 = Release|Any CPU {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Debug|Any CPU.Build.0 = Debug|Any CPU - {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Debug|x86.ActiveCfg = Debug|Any CPU - {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Debug|x86.Build.0 = Debug|Any CPU {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Release|Any CPU.ActiveCfg = Release|Any CPU {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Release|Any CPU.Build.0 = Release|Any CPU - {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Release|x86.ActiveCfg = Release|Any CPU - {13D2EC90-C41F-48A1-AADA-859B6DC24EDC}.Release|x86.Build.0 = Release|Any CPU {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Debug|x86.ActiveCfg = Debug|Any CPU - {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Debug|x86.Build.0 = Debug|Any CPU {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Release|Any CPU.ActiveCfg = Release|Any CPU {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Release|Any CPU.Build.0 = Release|Any CPU - {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Release|x86.ActiveCfg = Release|Any CPU - {DFA3C3B7-F098-4567-A780-A37DC52CA577}.Release|x86.Build.0 = Release|Any CPU {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Debug|x86.ActiveCfg = Debug|Any CPU - {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Debug|x86.Build.0 = Debug|Any CPU {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Release|Any CPU.ActiveCfg = Release|Any CPU {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Release|Any CPU.Build.0 = Release|Any CPU - {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Release|x86.ActiveCfg = Release|Any CPU - {F4B60F03-F4C8-42CD-A46D-712838DC184B}.Release|x86.Build.0 = Release|Any CPU {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Debug|x86.ActiveCfg = Debug|Any CPU - {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Debug|x86.Build.0 = Debug|Any CPU {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Release|Any CPU.ActiveCfg = Release|Any CPU {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Release|Any CPU.Build.0 = Release|Any CPU - {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Release|x86.ActiveCfg = Release|Any CPU - {FF6AA762-7AD3-4F38-94B1-EA75D7B1F217}.Release|x86.Build.0 = Release|Any CPU {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Debug|Any CPU.Build.0 = Debug|Any CPU - {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Debug|x86.ActiveCfg = Debug|Any CPU - {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Debug|x86.Build.0 = Debug|Any CPU {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Release|Any CPU.ActiveCfg = Release|Any CPU {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Release|Any CPU.Build.0 = Release|Any CPU - {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Release|x86.ActiveCfg = Release|Any CPU - {624AFC60-565F-4F01-BD51-BCCE7AA09BE9}.Release|x86.Build.0 = Release|Any CPU {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Debug|Any CPU.Build.0 = Debug|Any CPU - {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Debug|x86.ActiveCfg = Debug|Any CPU - {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Debug|x86.Build.0 = Debug|Any CPU {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Release|Any CPU.ActiveCfg = Release|Any CPU {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Release|Any CPU.Build.0 = Release|Any CPU - {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Release|x86.ActiveCfg = Release|Any CPU - {BB4C8021-B5E1-4DE2-82CB-14BDFB9837E4}.Release|x86.Build.0 = Release|Any CPU {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Debug|x86.ActiveCfg = Debug|Any CPU - {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Debug|x86.Build.0 = Debug|Any CPU {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Release|Any CPU.ActiveCfg = Release|Any CPU {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Release|Any CPU.Build.0 = Release|Any CPU - {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Release|x86.ActiveCfg = Release|Any CPU - {6C4FF9C3-7AFF-4274-B8FC-4A93A1FAADEA}.Release|x86.Build.0 = Release|Any CPU {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Debug|x86.ActiveCfg = Debug|Any CPU - {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Debug|x86.Build.0 = Debug|Any CPU {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Release|Any CPU.ActiveCfg = Release|Any CPU {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Release|Any CPU.Build.0 = Release|Any CPU - {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Release|x86.ActiveCfg = Release|Any CPU - {CA6345D3-7A6D-478B-A0ED-A58E50DCAA83}.Release|x86.Build.0 = Release|Any CPU {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Debug|x86.ActiveCfg = Debug|Any CPU - {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Debug|x86.Build.0 = Debug|Any CPU {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Release|Any CPU.Build.0 = Release|Any CPU - {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Release|x86.ActiveCfg = Release|Any CPU - {A0DE147B-144C-4A34-8D46-9394570AD7E8}.Release|x86.Build.0 = Release|Any CPU {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Debug|x86.ActiveCfg = Debug|Any CPU - {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Debug|x86.Build.0 = Debug|Any CPU {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Release|Any CPU.ActiveCfg = Release|Any CPU {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Release|Any CPU.Build.0 = Release|Any CPU - {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Release|x86.ActiveCfg = Release|Any CPU - {785380E0-CEB9-4C34-82E5-60D0E33E848E}.Release|x86.Build.0 = Release|Any CPU {B994D8D2-C052-4616-9D20-386640C7387F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B994D8D2-C052-4616-9D20-386640C7387F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B994D8D2-C052-4616-9D20-386640C7387F}.Debug|x86.ActiveCfg = Debug|Any CPU - {B994D8D2-C052-4616-9D20-386640C7387F}.Debug|x86.Build.0 = Debug|Any CPU {B994D8D2-C052-4616-9D20-386640C7387F}.Release|Any CPU.ActiveCfg = Release|Any CPU {B994D8D2-C052-4616-9D20-386640C7387F}.Release|Any CPU.Build.0 = Release|Any CPU - {B994D8D2-C052-4616-9D20-386640C7387F}.Release|x86.ActiveCfg = Release|Any CPU - {B994D8D2-C052-4616-9D20-386640C7387F}.Release|x86.Build.0 = Release|Any CPU {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Debug|x86.ActiveCfg = Debug|Any CPU - {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Debug|x86.Build.0 = Debug|Any CPU {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Release|Any CPU.ActiveCfg = Release|Any CPU {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Release|Any CPU.Build.0 = Release|Any CPU - {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Release|x86.ActiveCfg = Release|Any CPU - {6D4F97A1-D0A0-44EC-B2A3-F5C954209444}.Release|x86.Build.0 = Release|Any CPU {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Debug|x86.ActiveCfg = Debug|Any CPU - {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Debug|x86.Build.0 = Debug|Any CPU {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Release|Any CPU.ActiveCfg = Release|Any CPU {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Release|Any CPU.Build.0 = Release|Any CPU - {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Release|x86.ActiveCfg = Release|Any CPU - {993DB853-EC9F-45D5-AD2C-BA008B72995B}.Release|x86.Build.0 = Release|Any CPU {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Debug|Any CPU.Build.0 = Debug|Any CPU - {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Debug|x86.ActiveCfg = Debug|Any CPU - {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Debug|x86.Build.0 = Debug|Any CPU {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Release|Any CPU.ActiveCfg = Release|Any CPU {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Release|Any CPU.Build.0 = Release|Any CPU - {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Release|x86.ActiveCfg = Release|Any CPU - {78AC6375-28AF-4175-9F20-B5099C92EA2B}.Release|x86.Build.0 = Release|Any CPU {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Debug|x86.ActiveCfg = Debug|Any CPU - {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Debug|x86.Build.0 = Debug|Any CPU {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Release|Any CPU.ActiveCfg = Release|Any CPU {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Release|Any CPU.Build.0 = Release|Any CPU - {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Release|x86.ActiveCfg = Release|Any CPU - {B6054E5B-362C-4298-8F20-6BA5BF1A859E}.Release|x86.Build.0 = Release|Any CPU {E2CE55F4-53FB-48C3-A8BE-34161961FD2A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {E2CE55F4-53FB-48C3-A8BE-34161961FD2A}.Debug|x86.ActiveCfg = Debug|Any CPU - {E2CE55F4-53FB-48C3-A8BE-34161961FD2A}.Debug|x86.Build.0 = Debug|Any CPU {E2CE55F4-53FB-48C3-A8BE-34161961FD2A}.Release|Any CPU.ActiveCfg = Release|Any CPU - {E2CE55F4-53FB-48C3-A8BE-34161961FD2A}.Release|x86.ActiveCfg = Release|Any CPU - {E2CE55F4-53FB-48C3-A8BE-34161961FD2A}.Release|x86.Build.0 = Release|Any CPU {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Debug|x86.ActiveCfg = Debug|Any CPU - {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Debug|x86.Build.0 = Debug|Any CPU {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Release|Any CPU.ActiveCfg = Release|Any CPU {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Release|Any CPU.Build.0 = Release|Any CPU - {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Release|x86.ActiveCfg = Release|Any CPU - {A7C98A7E-1BCB-4A38-AAC4-2EEC63A5BC5C}.Release|x86.Build.0 = Release|Any CPU {94836116-0CD5-4EA9-8049-447FEA886406}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {94836116-0CD5-4EA9-8049-447FEA886406}.Debug|Any CPU.Build.0 = Debug|Any CPU - {94836116-0CD5-4EA9-8049-447FEA886406}.Debug|x86.ActiveCfg = Debug|Any CPU - {94836116-0CD5-4EA9-8049-447FEA886406}.Debug|x86.Build.0 = Debug|Any CPU {94836116-0CD5-4EA9-8049-447FEA886406}.Release|Any CPU.ActiveCfg = Release|Any CPU {94836116-0CD5-4EA9-8049-447FEA886406}.Release|Any CPU.Build.0 = Release|Any CPU - {94836116-0CD5-4EA9-8049-447FEA886406}.Release|x86.ActiveCfg = Release|Any CPU - {94836116-0CD5-4EA9-8049-447FEA886406}.Release|x86.Build.0 = Release|Any CPU {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Debug|Any CPU.Build.0 = Debug|Any CPU - {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Debug|x86.ActiveCfg = Debug|Any CPU - {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Debug|x86.Build.0 = Debug|Any CPU {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Release|Any CPU.ActiveCfg = Release|Any CPU {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Release|Any CPU.Build.0 = Release|Any CPU - {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Release|x86.ActiveCfg = Release|Any CPU - {077E19BA-4129-4AAE-8FCD-34D6FAF85B78}.Release|x86.Build.0 = Release|Any CPU {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Debug|x86.ActiveCfg = Debug|Any CPU - {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Debug|x86.Build.0 = Debug|Any CPU {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Release|Any CPU.ActiveCfg = Release|Any CPU {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Release|Any CPU.Build.0 = Release|Any CPU - {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Release|x86.ActiveCfg = Release|Any CPU - {1442B805-D6B1-4729-89F8-3A5A1C7547AD}.Release|x86.Build.0 = Release|Any CPU {3A413E59-A20E-477C-997E-64B1398E0E80}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3A413E59-A20E-477C-997E-64B1398E0E80}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3A413E59-A20E-477C-997E-64B1398E0E80}.Debug|x86.ActiveCfg = Debug|Any CPU - {3A413E59-A20E-477C-997E-64B1398E0E80}.Debug|x86.Build.0 = Debug|Any CPU {3A413E59-A20E-477C-997E-64B1398E0E80}.Release|Any CPU.ActiveCfg = Release|Any CPU {3A413E59-A20E-477C-997E-64B1398E0E80}.Release|Any CPU.Build.0 = Release|Any CPU - {3A413E59-A20E-477C-997E-64B1398E0E80}.Release|x86.ActiveCfg = Release|Any CPU - {3A413E59-A20E-477C-997E-64B1398E0E80}.Release|x86.Build.0 = Release|Any CPU {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Debug|x86.ActiveCfg = Debug|x86 - {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Debug|x86.Build.0 = Debug|x86 - {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Debug|x86.Deploy.0 = Debug|x86 {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Release|Any CPU.ActiveCfg = Release|Any CPU - {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Release|x86.ActiveCfg = Release|x86 - {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Release|x86.Build.0 = Release|x86 - {AADFFE7F-44CE-4FCA-BDB1-17C3F7020DCD}.Release|x86.Deploy.0 = Release|x86 {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Debug|Any CPU.Build.0 = Debug|Any CPU - {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Debug|x86.ActiveCfg = Debug|Any CPU - {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Debug|x86.Build.0 = Debug|Any CPU {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Release|Any CPU.Build.0 = Release|Any CPU - {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Release|x86.ActiveCfg = Release|Any CPU - {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Release|x86.Build.0 = Release|Any CPU {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Debug|x86.ActiveCfg = Debug|Any CPU - {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Debug|x86.Build.0 = Debug|Any CPU {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Release|x86.ActiveCfg = Release|Any CPU - {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Release|x86.Build.0 = Release|Any CPU {9BA6FC55-148D-4481-B9E6-B31A1D4BCD0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9BA6FC55-148D-4481-B9E6-B31A1D4BCD0F}.Debug|x86.ActiveCfg = Debug|Any CPU {9BA6FC55-148D-4481-B9E6-B31A1D4BCD0F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9BA6FC55-148D-4481-B9E6-B31A1D4BCD0F}.Release|x86.ActiveCfg = Release|Any CPU {DFCB0240-50CF-4F56-92C7-05941569231D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DFCB0240-50CF-4F56-92C7-05941569231D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DFCB0240-50CF-4F56-92C7-05941569231D}.Debug|x86.ActiveCfg = Debug|Any CPU - {DFCB0240-50CF-4F56-92C7-05941569231D}.Debug|x86.Build.0 = Debug|Any CPU {DFCB0240-50CF-4F56-92C7-05941569231D}.Release|Any CPU.ActiveCfg = Release|Any CPU {DFCB0240-50CF-4F56-92C7-05941569231D}.Release|Any CPU.Build.0 = Release|Any CPU - {DFCB0240-50CF-4F56-92C7-05941569231D}.Release|x86.ActiveCfg = Release|Any CPU - {DFCB0240-50CF-4F56-92C7-05941569231D}.Release|x86.Build.0 = Release|Any CPU {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Debug|Any CPU.Build.0 = Debug|Any CPU - {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Debug|x86.ActiveCfg = Debug|Any CPU - {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Debug|x86.Build.0 = Debug|Any CPU {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Release|Any CPU.ActiveCfg = Release|Any CPU {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Release|Any CPU.Build.0 = Release|Any CPU - {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Release|x86.ActiveCfg = Release|Any CPU - {183631BD-EC15-47AD-9ABE-CD8DB748C066}.Release|x86.Build.0 = Release|Any CPU {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Debug|Any CPU.Build.0 = Debug|Any CPU - {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Debug|x86.ActiveCfg = Debug|Any CPU - {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Debug|x86.Build.0 = Debug|Any CPU {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Release|Any CPU.ActiveCfg = Release|Any CPU {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Release|Any CPU.Build.0 = Release|Any CPU - {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Release|x86.ActiveCfg = Release|Any CPU - {1117EFD6-3A46-47F7-9BEB-02792D213B8D}.Release|x86.Build.0 = Release|Any CPU {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Debug|x86.ActiveCfg = Debug|Any CPU - {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Debug|x86.Build.0 = Debug|Any CPU {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Release|Any CPU.ActiveCfg = Release|Any CPU {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Release|Any CPU.Build.0 = Release|Any CPU - {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Release|x86.ActiveCfg = Release|Any CPU - {E634EFE6-FEA0-4BB9-A7B9-D8809C33BCC8}.Release|x86.Build.0 = Release|Any CPU {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Debug|x86.ActiveCfg = Debug|Any CPU - {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Debug|x86.Build.0 = Debug|Any CPU {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Release|Any CPU.ActiveCfg = Release|Any CPU {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Release|Any CPU.Build.0 = Release|Any CPU - {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Release|x86.ActiveCfg = Release|Any CPU - {FD4D2994-9BEA-41A1-8C51-2E02D1E8503E}.Release|x86.Build.0 = Release|Any CPU {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Debug|x86.ActiveCfg = Debug|Any CPU - {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Debug|x86.Build.0 = Debug|Any CPU {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Release|Any CPU.Build.0 = Release|Any CPU - {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Release|x86.ActiveCfg = Release|Any CPU - {B8C24868-6811-4FED-82DF-0C8CB607B00F}.Release|x86.Build.0 = Release|Any CPU {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Debug|x86.ActiveCfg = Debug|Any CPU - {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Debug|x86.Build.0 = Debug|Any CPU {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Release|Any CPU.ActiveCfg = Release|Any CPU {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Release|Any CPU.Build.0 = Release|Any CPU - {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Release|x86.ActiveCfg = Release|Any CPU - {DF86AFC2-CA79-4137-9BB5-70AA529C3B79}.Release|x86.Build.0 = Release|Any CPU {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Debug|Any CPU.Build.0 = Debug|Any CPU - {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Debug|x86.ActiveCfg = Debug|Any CPU - {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Debug|x86.Build.0 = Debug|Any CPU {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Release|Any CPU.ActiveCfg = Release|Any CPU {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Release|Any CPU.Build.0 = Release|Any CPU - {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Release|x86.ActiveCfg = Release|Any CPU - {6974D22C-EDE6-4BB2-AAD2-FF23ED6EC165}.Release|x86.Build.0 = Release|Any CPU {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Debug|x86.ActiveCfg = Debug|Any CPU - {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Debug|x86.Build.0 = Debug|Any CPU {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Release|Any CPU.ActiveCfg = Release|Any CPU {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Release|Any CPU.Build.0 = Release|Any CPU - {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Release|x86.ActiveCfg = Release|Any CPU - {A0B60830-D1C0-4E1F-9E44-793A71C5D720}.Release|x86.Build.0 = Release|Any CPU {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Debug|x86.ActiveCfg = Debug|Any CPU - {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Debug|x86.Build.0 = Debug|Any CPU {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Release|Any CPU.ActiveCfg = Release|Any CPU {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Release|Any CPU.Build.0 = Release|Any CPU - {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Release|x86.ActiveCfg = Release|Any CPU - {3D787D5F-1DCA-4C2E-8D3A-93353E7BB62A}.Release|x86.Build.0 = Release|Any CPU {CBB78367-91B7-4D53-AD31-429B71F867D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CBB78367-91B7-4D53-AD31-429B71F867D2}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CBB78367-91B7-4D53-AD31-429B71F867D2}.Debug|x86.ActiveCfg = Debug|Any CPU - {CBB78367-91B7-4D53-AD31-429B71F867D2}.Debug|x86.Build.0 = Debug|Any CPU {CBB78367-91B7-4D53-AD31-429B71F867D2}.Release|Any CPU.ActiveCfg = Release|Any CPU {CBB78367-91B7-4D53-AD31-429B71F867D2}.Release|Any CPU.Build.0 = Release|Any CPU - {CBB78367-91B7-4D53-AD31-429B71F867D2}.Release|x86.ActiveCfg = Release|Any CPU - {CBB78367-91B7-4D53-AD31-429B71F867D2}.Release|x86.Build.0 = Release|Any CPU {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Debug|x86.ActiveCfg = Debug|Any CPU - {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Debug|x86.Build.0 = Debug|Any CPU {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Release|Any CPU.ActiveCfg = Release|Any CPU {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Release|Any CPU.Build.0 = Release|Any CPU - {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Release|x86.ActiveCfg = Release|Any CPU - {DC7BAD19-540A-4407-8E89-C15C899D74DF}.Release|x86.Build.0 = Release|Any CPU {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Debug|x86.ActiveCfg = Debug|Any CPU - {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Debug|x86.Build.0 = Debug|Any CPU {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Release|Any CPU.ActiveCfg = Release|Any CPU {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Release|Any CPU.Build.0 = Release|Any CPU - {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Release|x86.ActiveCfg = Release|Any CPU - {E4902330-74FE-45F6-86C3-0A5F73A1EEC0}.Release|x86.Build.0 = Release|Any CPU {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Debug|Any CPU.Build.0 = Debug|Any CPU - {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Debug|x86.ActiveCfg = Debug|Any CPU - {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Debug|x86.Build.0 = Debug|Any CPU {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Release|Any CPU.ActiveCfg = Release|Any CPU {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Release|Any CPU.Build.0 = Release|Any CPU - {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Release|x86.ActiveCfg = Release|Any CPU - {637A5D55-908E-4AEE-B061-3981B66F1B9F}.Release|x86.Build.0 = Release|Any CPU {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Debug|Any CPU.Build.0 = Debug|Any CPU - {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Debug|x86.ActiveCfg = Debug|Any CPU - {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Debug|x86.Build.0 = Debug|Any CPU {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Release|Any CPU.ActiveCfg = Release|Any CPU {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Release|Any CPU.Build.0 = Release|Any CPU - {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Release|x86.ActiveCfg = Release|Any CPU - {3566E9FD-591D-4E42-BA38-11DBE2F13E82}.Release|x86.Build.0 = Release|Any CPU {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Debug|Any CPU.Build.0 = Debug|Any CPU - {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Debug|x86.ActiveCfg = Debug|Any CPU - {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Debug|x86.Build.0 = Debug|Any CPU {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Release|Any CPU.ActiveCfg = Release|Any CPU {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Release|Any CPU.Build.0 = Release|Any CPU - {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Release|x86.ActiveCfg = Release|Any CPU - {563D7C2E-14E2-47EC-95E4-4EA0BBA75C18}.Release|x86.Build.0 = Release|Any CPU {B66F428C-0419-438F-9303-C20A5E925257}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {B66F428C-0419-438F-9303-C20A5E925257}.Debug|Any CPU.Build.0 = Debug|Any CPU - {B66F428C-0419-438F-9303-C20A5E925257}.Debug|x86.ActiveCfg = Debug|Any CPU - {B66F428C-0419-438F-9303-C20A5E925257}.Debug|x86.Build.0 = Debug|Any CPU {B66F428C-0419-438F-9303-C20A5E925257}.Release|Any CPU.ActiveCfg = Release|Any CPU {B66F428C-0419-438F-9303-C20A5E925257}.Release|Any CPU.Build.0 = Release|Any CPU - {B66F428C-0419-438F-9303-C20A5E925257}.Release|x86.ActiveCfg = Release|Any CPU - {B66F428C-0419-438F-9303-C20A5E925257}.Release|x86.Build.0 = Release|Any CPU {E51283DC-7090-479E-B723-01C0953F18EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {E51283DC-7090-479E-B723-01C0953F18EA}.Debug|Any CPU.Build.0 = Debug|Any CPU - {E51283DC-7090-479E-B723-01C0953F18EA}.Debug|x86.ActiveCfg = Debug|Any CPU - {E51283DC-7090-479E-B723-01C0953F18EA}.Debug|x86.Build.0 = Debug|Any CPU {E51283DC-7090-479E-B723-01C0953F18EA}.Release|Any CPU.ActiveCfg = Release|Any CPU {E51283DC-7090-479E-B723-01C0953F18EA}.Release|Any CPU.Build.0 = Release|Any CPU - {E51283DC-7090-479E-B723-01C0953F18EA}.Release|x86.ActiveCfg = Release|Any CPU - {E51283DC-7090-479E-B723-01C0953F18EA}.Release|x86.Build.0 = Release|Any CPU {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Debug|Any CPU.Build.0 = Debug|Any CPU - {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Debug|x86.ActiveCfg = Debug|Any CPU - {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Debug|x86.Build.0 = Debug|Any CPU {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Release|Any CPU.ActiveCfg = Release|Any CPU {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Release|Any CPU.Build.0 = Release|Any CPU - {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Release|x86.ActiveCfg = Release|Any CPU - {A157AD69-59D4-49DE-94B3-DB883B2BEAA5}.Release|x86.Build.0 = Release|Any CPU {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Debug|x86.Build.0 = Debug|Any CPU {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Release|Any CPU.Build.0 = Release|Any CPU - {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Release|x86.ActiveCfg = Release|Any CPU - {CA8C83FC-FCDC-4F8F-9384-A2C9C5B2F7DD}.Release|x86.Build.0 = Release|Any CPU {9A702625-FB81-4400-ADAC-053553109F64}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {9A702625-FB81-4400-ADAC-053553109F64}.Debug|Any CPU.Build.0 = Debug|Any CPU - {9A702625-FB81-4400-ADAC-053553109F64}.Debug|x86.ActiveCfg = Debug|Any CPU - {9A702625-FB81-4400-ADAC-053553109F64}.Debug|x86.Build.0 = Debug|Any CPU {9A702625-FB81-4400-ADAC-053553109F64}.Release|Any CPU.ActiveCfg = Release|Any CPU {9A702625-FB81-4400-ADAC-053553109F64}.Release|Any CPU.Build.0 = Release|Any CPU - {9A702625-FB81-4400-ADAC-053553109F64}.Release|x86.ActiveCfg = Release|Any CPU - {9A702625-FB81-4400-ADAC-053553109F64}.Release|x86.Build.0 = Release|Any CPU {FB690197-2695-489C-A47C-439FF3AEF7A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {FB690197-2695-489C-A47C-439FF3AEF7A8}.Debug|x86.ActiveCfg = Debug|Any CPU - {FB690197-2695-489C-A47C-439FF3AEF7A8}.Debug|x86.Build.0 = Debug|Any CPU {FB690197-2695-489C-A47C-439FF3AEF7A8}.Release|Any CPU.ActiveCfg = Release|Any CPU - {FB690197-2695-489C-A47C-439FF3AEF7A8}.Release|x86.ActiveCfg = Release|Any CPU - {FB690197-2695-489C-A47C-439FF3AEF7A8}.Release|x86.Build.0 = Release|Any CPU {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Debug|x86.ActiveCfg = Debug|Any CPU - {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Debug|x86.Build.0 = Debug|Any CPU {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Release|Any CPU.ActiveCfg = Release|Any CPU - {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Release|x86.ActiveCfg = Release|Any CPU - {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Release|x86.Build.0 = Release|Any CPU {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Debug|Any CPU.Build.0 = Debug|Any CPU - {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Debug|x86.ActiveCfg = Debug|Any CPU - {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Debug|x86.Build.0 = Debug|Any CPU {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Release|Any CPU.ActiveCfg = Release|Any CPU {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Release|Any CPU.Build.0 = Release|Any CPU - {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Release|x86.ActiveCfg = Release|Any CPU - {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Release|x86.Build.0 = Release|Any CPU {DED183CA-5591-4CE5-A89D-987035BAC553}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DED183CA-5591-4CE5-A89D-987035BAC553}.Debug|Any CPU.Build.0 = Debug|Any CPU - {DED183CA-5591-4CE5-A89D-987035BAC553}.Debug|x86.ActiveCfg = Debug|Any CPU - {DED183CA-5591-4CE5-A89D-987035BAC553}.Debug|x86.Build.0 = Debug|Any CPU {DED183CA-5591-4CE5-A89D-987035BAC553}.Release|Any CPU.ActiveCfg = Release|Any CPU {DED183CA-5591-4CE5-A89D-987035BAC553}.Release|Any CPU.Build.0 = Release|Any CPU - {DED183CA-5591-4CE5-A89D-987035BAC553}.Release|x86.ActiveCfg = Release|Any CPU - {DED183CA-5591-4CE5-A89D-987035BAC553}.Release|x86.Build.0 = Release|Any CPU {FBE658B3-684D-46E6-8668-50DEF0778538}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FBE658B3-684D-46E6-8668-50DEF0778538}.Debug|Any CPU.Build.0 = Debug|Any CPU - {FBE658B3-684D-46E6-8668-50DEF0778538}.Debug|x86.ActiveCfg = Debug|Any CPU - {FBE658B3-684D-46E6-8668-50DEF0778538}.Debug|x86.Build.0 = Debug|Any CPU {FBE658B3-684D-46E6-8668-50DEF0778538}.Release|Any CPU.ActiveCfg = Release|Any CPU {FBE658B3-684D-46E6-8668-50DEF0778538}.Release|Any CPU.Build.0 = Release|Any CPU - {FBE658B3-684D-46E6-8668-50DEF0778538}.Release|x86.ActiveCfg = Release|Any CPU - {FBE658B3-684D-46E6-8668-50DEF0778538}.Release|x86.Build.0 = Release|Any CPU - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|Any CPU.ActiveCfg = Debug|x86 - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|Any CPU.Build.0 = Debug|x86 - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|x86.ActiveCfg = Debug|x86 - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|x86.Build.0 = Debug|x86 + {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|Any CPU.Build.0 = Debug|Any CPU {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.ActiveCfg = Release|x86 {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.Build.0 = Release|x86 - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|x86.ActiveCfg = Release|x86 - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|x86.Build.0 = Release|x86 {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|x86.ActiveCfg = Debug|Any CPU - {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|x86.Build.0 = Debug|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Release|Any CPU.ActiveCfg = Release|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Release|Any CPU.Build.0 = Release|Any CPU - {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Release|x86.ActiveCfg = Release|Any CPU - {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Release|x86.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE From 23f6048e74679eba37f6d103463747595ddd62cc Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Mon, 22 Jan 2024 15:49:55 +1100 Subject: [PATCH 16/44] Bulb: any cpu --- ExtLibs/LEDBulb/Bulb/Bulb.csproj | 95 +++----------------------------- MissionPlanner.sln | 4 +- 2 files changed, 10 insertions(+), 89 deletions(-) diff --git a/ExtLibs/LEDBulb/Bulb/Bulb.csproj b/ExtLibs/LEDBulb/Bulb/Bulb.csproj index a7a8e17775..ba380ecabc 100644 --- a/ExtLibs/LEDBulb/Bulb/Bulb.csproj +++ b/ExtLibs/LEDBulb/Bulb/Bulb.csproj @@ -1,100 +1,21 @@ - - + - Debug - x86 - 8.0.30703 - 2.0 - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107} + net472 Library - Properties - Bulb - Bulb - v4.7.2 - - - 512 - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - false - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - false + false + true + true - - - - - - - - - - - - - - Form - - - Form1.cs - - + Component - - - - Form1.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - True - - - PublicSettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - + + - - \ No newline at end of file diff --git a/MissionPlanner.sln b/MissionPlanner.sln index 071bcefbd6..7cfe456fc5 100644 --- a/MissionPlanner.sln +++ b/MissionPlanner.sln @@ -547,8 +547,8 @@ Global {FBE658B3-684D-46E6-8668-50DEF0778538}.Release|Any CPU.Build.0 = Release|Any CPU {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Debug|Any CPU.Build.0 = Debug|Any CPU - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.ActiveCfg = Release|x86 - {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.Build.0 = Release|x86 + {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.ActiveCfg = Release|Any CPU + {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.Build.0 = Release|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Release|Any CPU.ActiveCfg = Release|Any CPU From 12817f82c4b3fa388b8eb43c02d9ff1afda49aba Mon Sep 17 00:00:00 2001 From: Tatsuya Yamaguchi Date: Mon, 5 Feb 2024 10:19:32 +0900 Subject: [PATCH 17/44] CurrentState: handle GIMBAL_DEVICE_ATTITUDE_STATUS message --- ExtLibs/ArduPilot/CurrentState.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/ExtLibs/ArduPilot/CurrentState.cs b/ExtLibs/ArduPilot/CurrentState.cs index db2c9986ac..2815f62f85 100644 --- a/ExtLibs/ArduPilot/CurrentState.cs +++ b/ExtLibs/ArduPilot/CurrentState.cs @@ -3644,6 +3644,16 @@ private void Parent_OnPacketReceived(object sender, MAVLink.MAVLinkMessage mavLi } break; + case (uint)MAVLink.MAVLINK_MSG_ID.GIMBAL_DEVICE_ATTITUDE_STATUS: + { + var status = mavLinkMessage.ToStructure(); + Quaternion q = new Quaternion(status.q[0], status.q[1], status.q[2], status.q[3]); + campointa = (float)(q.get_euler_pitch() * (180.0 / Math.PI)); + campointb = (float)(q.get_euler_roll() * (180.0 / Math.PI)); + campointc = (float)(q.get_euler_yaw() * (180.0 / Math.PI)); + if (campointc < 0) campointc += 360; //normalization + } + break; case (uint)MAVLink.MAVLINK_MSG_ID.UAVIONIX_ADSB_OUT_STATUS: { var status = mavLinkMessage.ToStructure(); From c9c41e93f1d56bbd7308a43af963517caf95eab1 Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Sat, 10 Feb 2024 12:50:53 +0100 Subject: [PATCH 18/44] Make QuickView Add window fixed size and scrollable. --- GCSViews/FlightData.cs | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/GCSViews/FlightData.cs b/GCSViews/FlightData.cs index 95e6842d26..9ae6b7f43f 100644 --- a/GCSViews/FlightData.cs +++ b/GCSViews/FlightData.cs @@ -4353,14 +4353,15 @@ private void quickView_DoubleClick(object sender, EventArgs e) Form selectform = new Form { Name = "select", - Width = 50, - Height = 50, + Width = MainV2.instance.Width - 100, + Height = MainV2.instance.Height - 100, Text = "Display This", - AutoSize = true, + AutoSize = false, StartPosition = FormStartPosition.CenterParent, MaximizeBox = false, MinimizeBox = false, - AutoScroll = true + AutoScroll = true, + FormBorderStyle = FormBorderStyle.FixedDialog }; ThemeManager.ApplyThemeTo(selectform); From 63d57c4aff57018d1058d1b3a6b638e69ba00fa4 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Tue, 23 Jan 2024 10:22:26 +1100 Subject: [PATCH 19/44] px4uploader: extf crc exclude padding --- ExtLibs/px4uploader/Firmware.cs | 2 +- build - debug.bat | 10 ++++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) create mode 100644 build - debug.bat diff --git a/ExtLibs/px4uploader/Firmware.cs b/ExtLibs/px4uploader/Firmware.cs index 6f521a4826..975abb6484 100644 --- a/ExtLibs/px4uploader/Firmware.cs +++ b/ExtLibs/px4uploader/Firmware.cs @@ -178,7 +178,7 @@ public int crc(int padlen) public int extf_crc(int padlen) { - uint state = __crc32(extf_imagebyte, 0); + uint state = __crc32(extf_imagebyte.Take(padlen).ToArray(), 0); return (int)state; } diff --git a/build - debug.bat b/build - debug.bat new file mode 100644 index 0000000000..073e05a559 --- /dev/null +++ b/build - debug.bat @@ -0,0 +1,10 @@ + +set PATH=%PATH%;C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin;C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin;C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\15.0\Bin;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin + +del bin\release\MissionPlannerBeta.zip + +.nuget\nuget.exe restore MissionPlanner.sln + +MSBuild.exe MissionPlanner.sln /restore /m /p:Configuration=Debug /verbosity:n + +pause \ No newline at end of file From 5cfc428562d5bd408c8c2673d790dda89a7bbddc Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Mon, 29 Jan 2024 09:56:28 +1100 Subject: [PATCH 20/44] Solution cleanup --- MissionPlanner.sln | 67 +++++----------------------------------------- 1 file changed, 6 insertions(+), 61 deletions(-) diff --git a/MissionPlanner.sln b/MissionPlanner.sln index 7cfe456fc5..2517a875cb 100644 --- a/MissionPlanner.sln +++ b/MissionPlanner.sln @@ -221,7 +221,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AltitudeAngelWings.Plugin", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "OpenDroneID_Plugin", "Plugins\OpenDroneID2\OpenDroneID_Plugin.csproj", "{FBE658B3-684D-46E6-8668-50DEF0778538}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Bulb", "ExtLibs\LEDBulb\Bulb\Bulb.csproj", "{AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Bulb", "ExtLibs\LEDBulb\Bulb\Bulb.csproj", "{AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MissionPlannerTests", "MissionPlannerTests\MissionPlannerTests.csproj", "{0B99EBF2-B964-4AAC-9EC5-76353610AAAE}" EndProject @@ -330,7 +330,6 @@ Global {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Release|Any CPU.ActiveCfg = Release|Any CPU {BB06DFF7-4F41-4B9D-A3C3-3B6D2B8702B6}.Release|Any CPU.Build.0 = Release|Any CPU {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Debug|Any CPU.Build.0 = Debug|Any CPU {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Release|Any CPU.ActiveCfg = Release|Any CPU {B8943726-04B0-4477-BFDA-E156A0CD98A4}.Release|Any CPU.Build.0 = Release|Any CPU {CCE510F7-1DA6-40F2-8921-B86ED41BB85E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU @@ -442,9 +441,9 @@ Global {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Release|Any CPU.ActiveCfg = Release|Any CPU {D773ACCD-9C2D-4E94-A967-FAA7EA2D21CB}.Release|Any CPU.Build.0 = Release|Any CPU {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Debug|Any CPU.Build.0 = Debug|Any CPU {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Release|Any CPU.ActiveCfg = Release|Any CPU - {9BA6FC55-148D-4481-B9E6-B31A1D4BCD0F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {9BA6FC55-148D-4481-B9E6-B31A1D4BCD0F}.Release|Any CPU.ActiveCfg = Release|Any CPU + {EECDFE74-6CDC-45E0-AA39-34FF55FFB49F}.Release|Any CPU.Build.0 = Release|Any CPU {DFCB0240-50CF-4F56-92C7-05941569231D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {DFCB0240-50CF-4F56-92C7-05941569231D}.Debug|Any CPU.Build.0 = Debug|Any CPU {DFCB0240-50CF-4F56-92C7-05941569231D}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -532,7 +531,9 @@ Global {FB690197-2695-489C-A47C-439FF3AEF7A8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {FB690197-2695-489C-A47C-439FF3AEF7A8}.Release|Any CPU.ActiveCfg = Release|Any CPU {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Debug|Any CPU.Build.0 = Debug|Any CPU {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6609C54A-71B9-4349-8E79-1DF3293BC7D0}.Release|Any CPU.Build.0 = Release|Any CPU {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Debug|Any CPU.Build.0 = Debug|Any CPU {63F10356-A09B-46B0-9AFA-FAB8326A52DD}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -550,9 +551,7 @@ Global {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.ActiveCfg = Release|Any CPU {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107}.Release|Any CPU.Build.0 = Release|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Debug|Any CPU.Build.0 = Debug|Any CPU {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0B99EBF2-B964-4AAC-9EC5-76353610AAAE}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -640,60 +639,6 @@ Global {AF81C41B-06E6-4CA5-9FD4-A4E7042F1107} = {7E264F12-9EC3-4CDC-A187-6879C2B2BFCF} EndGlobalSection GlobalSection(ExtensibilityGlobals) = postSolution - SolutionGuid = {F7AF94B5-83B0-46CD-B258-67F2404F82FC} - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(Performance) = preSolution - HasPerformanceSessions = true - EndGlobalSection - GlobalSection(MonoDevelopProperties) = preSolution - StartupItem = MissionPlanner.csproj + SolutionGuid = {FD2C9507-1A09-4F5B-98AB-B6B194A4B260} EndGlobalSection EndGlobal From 36597765d7aa494243ae37f2d1d14a45559639c4 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Mon, 29 Jan 2024 15:02:39 +1100 Subject: [PATCH 21/44] CameraProtocol: update to REQUEST_MESSAGE --- ExtLibs/ArduPilot/Mavlink/CameraProtocol.cs | 20 +++++++++++++------- 1 file changed, 13 insertions(+), 7 deletions(-) diff --git a/ExtLibs/ArduPilot/Mavlink/CameraProtocol.cs b/ExtLibs/ArduPilot/Mavlink/CameraProtocol.cs index c6cc37bb13..334e96b105 100644 --- a/ExtLibs/ArduPilot/Mavlink/CameraProtocol.cs +++ b/ExtLibs/ArduPilot/Mavlink/CameraProtocol.cs @@ -40,15 +40,21 @@ public async Task StartID(MAVState mavState) { Task.Run(async () => { - if ((CameraInformation.flags & (int) MAVLink.CAMERA_CAP_FLAGS.CAPTURE_IMAGE) > 0) + if ((CameraInformation.flags & (int)MAVLink.CAMERA_CAP_FLAGS.CAPTURE_IMAGE) > 0) + { await parent.parent.doCommandAsync(parent.sysid, parent.compid, - MAVLink.MAV_CMD.REQUEST_CAMERA_SETTINGS, 0, 0, 0, 0, 0, 0, 0).ConfigureAwait(false); - if ((CameraInformation.flags & (int) MAVLink.CAMERA_CAP_FLAGS.CAPTURE_VIDEO) > 0) + MAVLink.MAV_CMD.REQUEST_MESSAGE, (int)MAVLink.MAVLINK_MSG_ID.CAMERA_SETTINGS, 0, 0, 0, 0, 0, 0).ConfigureAwait(false); + } + if ((CameraInformation.flags & (int)MAVLink.CAMERA_CAP_FLAGS.CAPTURE_VIDEO) > 0) + { await parent.parent.doCommandAsync(parent.sysid, parent.compid, - MAVLink.MAV_CMD.REQUEST_VIDEO_STREAM_INFORMATION, 0, 0, 0, 0, 0, 0, 0).ConfigureAwait(false); - if ((CameraInformation.flags & (int) MAVLink.CAMERA_CAP_FLAGS.CAPTURE_VIDEO) > 0) + MAVLink.MAV_CMD.REQUEST_MESSAGE, (int)MAVLink.MAVLINK_MSG_ID.VIDEO_STREAM_INFORMATION, 0, 0, 0, 0, 0, 0).ConfigureAwait(false); + } + if ((CameraInformation.flags & (int)MAVLink.CAMERA_CAP_FLAGS.CAPTURE_VIDEO) > 0) + { await parent.parent.doCommandAsync(parent.sysid, parent.compid, - MAVLink.MAV_CMD.REQUEST_STORAGE_INFORMATION, 0, 0, 0, 0, 0, 0, 0).ConfigureAwait(false); + MAVLink.MAV_CMD.REQUEST_MESSAGE, (int)MAVLink.MAVLINK_MSG_ID.STORAGE_INFORMATION, 0, 0, 0, 0, 0, 0).ConfigureAwait(false); + } }); } catch (Exception ex) @@ -100,7 +106,7 @@ await parent.parent.doCommandAsync(parent.sysid, parent.compid, try { var resp = await parent.parent.doCommandAsync(parent.sysid, parent.compid, - MAVLink.MAV_CMD.REQUEST_CAMERA_INFORMATION, 0, 0, 0, 0, 0, 0, 0); + MAVLink.MAV_CMD.REQUEST_MESSAGE, (int)MAVLink.MAVLINK_MSG_ID.CAMERA_INFORMATION, 0, 0, 0, 0, 0, 0); if (resp) { // no use From 8438f56d2fd6d97025330c5328c270c49dea46f1 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Tue, 30 Jan 2024 12:38:41 +1100 Subject: [PATCH 22/44] wasm: webserial --- ExtLibs/wasm/wasm.csproj | 30 ++--- ExtLibs/wasm/wwwroot/console.js | 8 -- ExtLibs/wasm/wwwroot/serial.js | 194 ++++++++++++++++++-------------- 3 files changed, 125 insertions(+), 107 deletions(-) diff --git a/ExtLibs/wasm/wasm.csproj b/ExtLibs/wasm/wasm.csproj index b66f407076..cb8f325ffa 100644 --- a/ExtLibs/wasm/wasm.csproj +++ b/ExtLibs/wasm/wasm.csproj @@ -1,15 +1,16 @@  - net7.0 - + net8.0 + 3.0 false true true - - false + true + false + false @@ -36,26 +37,25 @@ - + - - - - - + + + + - + - - - + + + - + diff --git a/ExtLibs/wasm/wwwroot/console.js b/ExtLibs/wasm/wwwroot/console.js index 943aeb17ee..98592fcc7d 100644 --- a/ExtLibs/wasm/wwwroot/console.js +++ b/ExtLibs/wasm/wwwroot/console.js @@ -73,13 +73,5 @@ } }); - serial.getPorts().then(ports => { - if (ports.length == 0) { - t.io.println('No devices found.'); - } else { - port = ports[0]; - connect(); - } - }); }); })(); \ No newline at end of file diff --git a/ExtLibs/wasm/wwwroot/serial.js b/ExtLibs/wasm/wwwroot/serial.js index 2efc47bb44..6fd121892a 100644 --- a/ExtLibs/wasm/wwwroot/serial.js +++ b/ExtLibs/wasm/wwwroot/serial.js @@ -1,101 +1,127 @@ var serial = {}; -(function() { - 'use strict'; +(function () { + 'use strict'; - serial.getPorts = function() { - return navigator.usb.getDevices().then(devices => { - return devices.map(device => new serial.Port(device)); - }); - }; - - serial.requestPort = function() { - const filters = [ - /* { 'vendorId': 0x2341, 'productId': 0x8036 }, // Arduino Leonardo - { 'vendorId': 0x2341, 'productId': 0x8037 }, // Arduino Micro - { 'vendorId': 0x2341, 'productId': 0x804d }, // Arduino/Genuino Zero - { 'vendorId': 0x2341, 'productId': 0x804e }, // Arduino/Genuino MKR1000 - { 'vendorId': 0x2341, 'productId': 0x804f }, // Arduino MKRZERO - { 'vendorId': 0x2341, 'productId': 0x8050 }, // Arduino MKR FOX 1200 - { 'vendorId': 0x2341, 'productId': 0x8052 }, // Arduino MKR GSM 1400 - { 'vendorId': 0x2341, 'productId': 0x8053 }, // Arduino MKR WAN 1300 - { 'vendorId': 0x2341, 'productId': 0x8054 }, // Arduino MKR WiFi 1010 - { 'vendorId': 0x2341, 'productId': 0x8055 }, // Arduino MKR NB 1500 - { 'vendorId': 0x2341, 'productId': 0x8056 }, // Arduino MKR Vidor 4000 - { 'vendorId': 0x2341, 'productId': 0x8057 }, // Arduino NANO 33 IoT - { 'vendorId': 0x239A }, // Adafruit Boards!*/ - { 'vendorId': 0x2dae }, // Hex Boards! - ]; - return navigator.usb.requestDevice({ 'filters': filters }).then( - device => new serial.Port(device) - ); - } + serial.getPorts = function () { + return navigator.usb.getDevices().then(devices => { + return devices.map(device => new serial.Port(device)); + }); + }; - serial.Port = function(device) { - this.device_ = device; - this.interfaceNumber_ = 2; // original interface number of WebUSB Arduino demo - this.endpointIn_ = 5; // original in endpoint ID of WebUSB Arduino demo - this.endpointOut_ = 4; // original out endpoint ID of WebUSB Arduino demo - }; + serial.requestPort = function () { + const filters = [ + /* { 'vendorId': 0x2341, 'productId': 0x8036 }, // Arduino Leonardo + { 'vendorId': 0x2341, 'productId': 0x8037 }, // Arduino Micro + { 'vendorId': 0x2341, 'productId': 0x804d }, // Arduino/Genuino Zero + { 'vendorId': 0x2341, 'productId': 0x804e }, // Arduino/Genuino MKR1000 + { 'vendorId': 0x2341, 'productId': 0x804f }, // Arduino MKRZERO + { 'vendorId': 0x2341, 'productId': 0x8050 }, // Arduino MKR FOX 1200 + { 'vendorId': 0x2341, 'productId': 0x8052 }, // Arduino MKR GSM 1400 + { 'vendorId': 0x2341, 'productId': 0x8053 }, // Arduino MKR WAN 1300 + { 'vendorId': 0x2341, 'productId': 0x8054 }, // Arduino MKR WiFi 1010 + { 'vendorId': 0x2341, 'productId': 0x8055 }, // Arduino MKR NB 1500 + { 'vendorId': 0x2341, 'productId': 0x8056 }, // Arduino MKR Vidor 4000 + { 'vendorId': 0x2341, 'productId': 0x8057 }, // Arduino NANO 33 IoT + { 'vendorId': 0x239A }, // Adafruit Boards!*/ + { 'vendorId': 0x2dae }, // Hex Boards! + ]; + return navigator.serial.requestPort({ 'filter': filters }).then( + device => new serial.Port(device) + ); + /* + await comm.open({ baudRate: 115200, bufferSize: 64 }); + reader = comm.readable.getReader(); + writer = comm.writable.getWriter(); + return navigator.usb.requestDevice({ 'filters': filters }).then( + device => new serial.Port(device) + );*/ + } - serial.Port.prototype.connect = function() { - let readLoop = () => { - this.device_.transferIn(this.endpointIn_, 64).then(result => { - this.onReceive(result.data); - readLoop(); - }, error => { - this.onReceiveError(error); - }); + serial.Port = function (device) { + this.device_ = device; + this.run = false; + //this.interfaceNumber_ = 1; // original interface number of WebUSB Arduino demo + //this.endpointIn_ = 2; // original in endpoint ID of WebUSB Arduino demo + //this.endpointOut_ = 2; // original out endpoint ID of WebUSB Arduino demo }; - return this.device_.open() - .then(() => { - if (this.device_.configuration === null) { - return this.device_.selectConfiguration(1); - } - }) - .then(() => { - var configurationInterfaces = this.device_.configuration.interfaces; - configurationInterfaces.forEach(element => { - element.alternates.forEach(elementalt => { - if (elementalt.interfaceClass==0xff) { - this.interfaceNumber_ = element.interfaceNumber; - elementalt.endpoints.forEach(elementendpoint => { - if (elementendpoint.direction == "out") { - this.endpointOut_ = elementendpoint.endpointNumber; - } - if (elementendpoint.direction=="in") { - this.endpointIn_ =elementendpoint.endpointNumber; + serial.Port.prototype.connect = function () { + return this.device_.open({ baudRate: 115200 }).then(() => { + this.run = true; + this.reader = this.device_.readable.getReader(); + this.writer = this.device_.writable.getWriter(); + + let readLoop = () => { + this.reader.read().then(result => { + this.onReceive(result.value); + if (this.run) + setTimeout(readLoop, 10); + }); + /*this.device_.transferIn(this.endpointIn_, 64).then(result => { + this.onReceive(result.data); + readLoop(); + }, error => { + this.onReceiveError(error); + });*/ + }; + + setTimeout(readLoop, 10); + }); + /* + return this.device_.open() + .then(() => { + if (this.device_.configuration === null) { + return this.device_.selectConfiguration(1); + } + }) + .then(() => { + var configurationInterfaces = this.device_.configuration.interfaces; + configurationInterfaces.forEach(element => { + element.alternates.forEach(elementalt => { + if (elementalt.interfaceClass==0xff) { + this.interfaceNumber_ = element.interfaceNumber; + elementalt.endpoints.forEach(elementendpoint => { + if (elementendpoint.direction == "out") { + this.endpointOut_ = elementendpoint.endpointNumber; + } + if (elementendpoint.direction=="in") { + this.endpointIn_ =elementendpoint.endpointNumber; + } + }) } }) - } + }) }) - }) - }) - .then(() => this.device_.claimInterface(this.interfaceNumber_)) - .then(() => this.device_.selectAlternateInterface(this.interfaceNumber_, 0)) - .then(() => this.device_.controlTransferOut({ - 'requestType': 'class', - 'recipient': 'interface', - 'request': 0x22, - 'value': 0x01, - 'index': this.interfaceNumber_})) - .then(() => { - readLoop(); - }); - }; + .then(() => this.device_.claimInterface(this.interfaceNumber_)) + .then(() => this.device_.selectAlternateInterface(this.interfaceNumber_, 0)) + .then(() => this.device_.controlTransferOut({ + 'requestType': 'class', + 'recipient': 'interface', + 'request': 0x22, + 'value': 0x01, + 'index': this.interfaceNumber_})) + .then(() => { + readLoop(); + });*/ + }; - serial.Port.prototype.disconnect = function() { - return this.device_.controlTransferOut({ + serial.Port.prototype.disconnect = function () { + /*return this.device_.controlTransferOut({ 'requestType': 'class', 'recipient': 'interface', 'request': 0x22, 'value': 0x00, - 'index': this.interfaceNumber_}) - .then(() => this.device_.close()); - }; + 'index': this.interfaceNumber_ + }) + .then(() => this.device_.close()); + */ + this.run = false; + return this.device_.close(); + }; - serial.Port.prototype.send = function(data) { - return this.device_.transferOut(this.endpointOut_, data); - }; + serial.Port.prototype.send = function (data) { + return this.writer.write(data); + //return this.device_.transferOut(this.endpointOut_, data); + }; })(); From 349391e2d8b0c22e528dace0de6d3bf640bf4253 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Tue, 30 Jan 2024 16:38:28 +1100 Subject: [PATCH 23/44] wasm: add serialport --- ExtLibs/wasm/Pages/Websocket.razor | 105 ++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 32 deletions(-) diff --git a/ExtLibs/wasm/Pages/Websocket.razor b/ExtLibs/wasm/Pages/Websocket.razor index d0b1160f99..9d333ae878 100644 --- a/ExtLibs/wasm/Pages/Websocket.razor +++ b/ExtLibs/wasm/Pages/Websocket.razor @@ -87,6 +87,7 @@ Raw MAVLink website url (wss:// for https)

+ @@ -120,7 +121,7 @@ } } - + @functions { @@ -184,6 +185,7 @@ string wsuri { get; set; } = "ws://localhost:56781/websocket/raw"; bool pageloadvisible = true; + static Websocket Instance; private void Log(string message) => Console.WriteLine($"{DateTime.UtcNow.ToString("O")} - {message}"); @@ -194,6 +196,8 @@ init = false; + Instance = this; + Console.WriteLine("OnInitialized Done"); } @@ -201,11 +205,42 @@ //protected WebSocketHelper WebSocketHelper1; + public async Task serialconnect() + { + pageloadvisible = false; + running = false; + StateHasChanged(); + + await JSRuntime.InvokeAsync("evalline", new object[] { @" +serial.requestPort() + .then(port => { + port.connect().then(()=>{ + console.log('connected'); + window.serialport = port; + port.onReceive = (data) => { DotNet.invokeMethodAsync('wasm', 'ProcessPacketStatic', '', data);} + }); + }); +" }).ConfigureAwait(false); + + mavbasestream.ReadBufferUpdate += (sender, i) => { }; + mavbasestream.WriteCallback += async (sender, bytes) => + { + if (bytes.Count() == 0) + return; + await JS.InvokeAsync("window.serialport.send", bytes.ToArray()); + }; + + + JSRuntime.InvokeAsync("startChart"); + + StateHasChanged(); + } + public async Task wsconnect() { - - ClientWebSocket webSocket = new ClientWebSocket(); - Console.WriteLine(wsuri); + + ClientWebSocket webSocket = new ClientWebSocket(); + Console.WriteLine(wsuri); await webSocket.ConnectAsync(new Uri(wsuri), CancellationToken.None).ContinueWith(async (a) => { pageloadvisible = false; @@ -213,22 +248,22 @@ ArraySegment bytesReceived = new ArraySegment (new byte[1024]); - Toaster.Info(webSocket.State.ToString()); + Toaster.Info(webSocket.State.ToString()); while (webSocket.State == WebSocketState.Open) { //Console.WriteLine("webSocket.ReceiveAsync"); await webSocket.ReceiveAsync(bytesReceived, CancellationToken.None); - ProcessPacket("", bytesReceived.Array.ToArray()); + this.ProcessPacket("", bytesReceived.Array.ToArray()); } }); - mavbasestream.ReadBufferUpdate += (sender, i) => { }; - mavbasestream.WriteCallback += async (sender, bytes) => { await webSocket.SendAsync(new ArraySegment - (bytes.ToArray()), WebSocketMessageType.Binary, true, CancellationToken.None); }; + mavbasestream.ReadBufferUpdate += (sender, i) => { }; + mavbasestream.WriteCallback += async (sender, bytes) => { await webSocket.SendAsync(new ArraySegment + (bytes.ToArray()), WebSocketMessageType.Binary, true, CancellationToken.None); }; + - //JSRuntime.InvokeAsync("initWebSocket", wsuri); JSRuntime.InvokeAsync("startChart"); @@ -239,30 +274,30 @@ /* private void WsOnError(string obj) { - SpeechSynthesis.Speak(obj); - Toaster.Error(obj); - StateHasChanged(); + SpeechSynthesis.Speak(obj); + Toaster.Error(obj); + StateHasChanged(); } private void WsOnMessage(BwsMessage obj) { - ProcessPacket("", obj.MessageBinary); + ProcessPacket("", obj.MessageBinary); } private void WsOnStateChange(short obj) { - if (WebSocketHelper1.bwsState == BwsState.Open) - { - pageloadvisible = false; - } - else + if (WebSocketHelper1.bwsState == BwsState.Open) + { + pageloadvisible = false; + } + else { - pageloadvisible = true; - } - SpeechSynthesis.Speak(WebSocketHelper1.bwsState.ToString()); - Toaster.Info(WebSocketHelper1.bwsState.ToString()); - StateHasChanged(); + pageloadvisible = true; + } + SpeechSynthesis.Speak(WebSocketHelper1.bwsState.ToString()); + Toaster.Info(WebSocketHelper1.bwsState.ToString()); + StateHasChanged(); } */ @@ -270,12 +305,10 @@ protected override async Task OnAfterRenderAsync(bool firstRender) { - Log("OnAfterRenderAsync"); - if (init) return; - + Log("OnAfterRenderAsync"); init = true; @@ -297,6 +330,7 @@ _hud.Height = (int)_canvasReference.Height; } } + protected BECanvasComponent _canvasReference; protected override void OnParametersSet() @@ -314,9 +348,13 @@ } + [JSInvokable] + public static async void ProcessPacketStatic(string json, byte[] data = null) + { + Instance.ProcessPacket(json, data); + } - //[JSInvokable] public async void ProcessPacket(string json, byte[] data = null) { //Console.WriteLine(DateTime.Now + " JS to C# " + json.ToArray().Length); @@ -363,7 +401,7 @@ mavbasestream.AppendBuffer(data); - /* + /* var pos = mav.logplaybackfile.BaseStream.Position; mav.logplaybackfile.BaseStream.Seek(0, SeekOrigin.End); @@ -379,7 +417,7 @@ mav.logplaybackfile.BaseStream.Seek(pos, SeekOrigin.Begin); mav.logreadmode = true; - */ + */ //Console.WriteLine("open {0} btr {1} type {2} type {3}", mav.BaseStream.IsOpen, mav.BaseStream.BytesToRead, mav.BaseStream.GetType(), mav.BaseStream.BaseStream?.GetType()); var check1 = DateTime.Now; @@ -575,8 +613,11 @@ // once a second if (second != DateTime.Now.Second) { - second = DateTime.Now.Second; - StateHasChanged(); + if (mode == modes.map) + { + second = DateTime.Now.Second; + StateHasChanged(); + } } return true; From ca87f8cf311f50afcebaaf23667538712e1f549b Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Wed, 31 Jan 2024 12:27:51 +1100 Subject: [PATCH 24/44] ZeroConf: run even under debugger --- ExtLibs/Utilities/ZeroConf.cs | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/ExtLibs/Utilities/ZeroConf.cs b/ExtLibs/Utilities/ZeroConf.cs index 1758d76c6f..ec4d0d75ab 100644 --- a/ExtLibs/Utilities/ZeroConf.cs +++ b/ExtLibs/Utilities/ZeroConf.cs @@ -18,8 +18,7 @@ public class ZeroConf public static void ProbeForRTSP() { - if(!System.Diagnostics.Debugger.IsAttached) - resolverAsync(); + resolverAsync(); } private static async Task resolverAsync() @@ -60,8 +59,7 @@ public static async Task EnumerateAllServicesFromAllHosts() public static void ProbeForMavlink() { - if (!System.Diagnostics.Debugger.IsAttached) - resolverMavlinkAsync(); + resolverMavlinkAsync(); } private static async Task resolverMavlinkAsync() From f78abda8b8443bfb8efc00bc384fe36afe165fd7 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Wed, 31 Jan 2024 16:49:55 +1100 Subject: [PATCH 25/44] MainV2: invoke video detection dialog - modal --- MainV2.cs | 83 ++++++++++++++++++++++++++++++++----------------------- 1 file changed, 48 insertions(+), 35 deletions(-) diff --git a/MainV2.cs b/MainV2.cs index 107958546a..d29e07f09e 100644 --- a/MainV2.cs +++ b/MainV2.cs @@ -3309,36 +3309,39 @@ protected override void OnLoad(EventArgs e) }; AutoConnect.NewVideoStream += (sender, gststring) => { - try + MainV2.instance.BeginInvoke((Action)delegate { - log.Info("AutoConnect.NewVideoStream " + gststring); - GStreamer.gstlaunch = GStreamer.LookForGstreamer(); - - if (!GStreamer.gstlaunchexists) + try { - if (CustomMessageBox.Show( - "A video stream has been detected, but gstreamer has not been configured/installed.\nDo you want to install/config it now?", - "GStreamer", System.Windows.Forms.MessageBoxButtons.YesNo) == - (int) System.Windows.Forms.DialogResult.Yes) + log.Info("AutoConnect.NewVideoStream " + gststring); + GStreamer.gstlaunch = GStreamer.LookForGstreamer(); + + if (!GStreamer.gstlaunchexists) { - GStreamerUI.DownloadGStreamer(); - if (!GStreamer.gstlaunchexists) + if (CustomMessageBox.Show( + "A video stream has been detected, but gstreamer has not been configured/installed.\nDo you want to install/config it now?", + "GStreamer", System.Windows.Forms.MessageBoxButtons.YesNo) == + (int)System.Windows.Forms.DialogResult.Yes) + { + GStreamerUI.DownloadGStreamer(); + if (!GStreamer.gstlaunchexists) + { + return; + } + } + else { return; } } - else - { - return; - } - } - GStreamer.StartA(gststring); - } - catch (Exception ex) - { - log.Error(ex); - } + GStreamer.StartA(gststring); + } + catch (Exception ex) + { + log.Error(ex); + } + }); }; AutoConnect.Start(); @@ -3354,22 +3357,32 @@ protected override void OnLoad(EventArgs e) return; } - if (!videourlseen.Contains(s) && videodetect.Wait(0)) + MainV2.instance.BeginInvoke((Action)delegate { - videourlseen.Add(s); - if (CustomMessageBox.Show( - "A video stream has been detected, Do you want to connect to it? " + s, - "Mavlink Camera", System.Windows.Forms.MessageBoxButtons.YesNo) == - (int) System.Windows.Forms.DialogResult.Yes) + try { - AutoConnect.RaiseNewVideoStream(sender, - String.Format( - "rtspsrc location={0} latency=41 udp-reconnect=1 timeout=0 do-retransmission=false ! application/x-rtp ! decodebin3 ! queue leaky=2 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink sync=false", - s)); - } + if (!videourlseen.Contains(s) && videodetect.Wait(0)) + { + videourlseen.Add(s); + if (CustomMessageBox.Show( + "A video stream has been detected, Do you want to connect to it? " + s, + "Mavlink Camera", System.Windows.Forms.MessageBoxButtons.YesNo) == + (int)System.Windows.Forms.DialogResult.Yes) + { + AutoConnect.RaiseNewVideoStream(sender, + String.Format( + "rtspsrc location={0} latency=41 udp-reconnect=1 timeout=0 do-retransmission=false ! application/x-rtp ! decodebin3 ! queue leaky=2 ! videoconvert ! video/x-raw,format=BGRA ! appsink name=outsink sync=false", + s)); + } - videodetect.Release(); - } + videodetect.Release(); + } + } + catch (Exception ex) + { + log.Error(ex); + } + }); }; From 93d827f0f64e01560a96def2a50a16b1ef7cc2ab Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Thu, 25 Jan 2024 12:11:23 +1100 Subject: [PATCH 26/44] Android: fix apk build --- .github/workflows/android.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index ecda3b35e7..4e31cdbad9 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -135,7 +135,7 @@ jobs: ForEach($i in $apks) { echo $i.FullName Move-Item -path $i.FullName temp.apk - C:\Android\android-sdk\build-tools\29.0.3\zipalign.exe -p -f -v 4 temp.apk $i.FullName + C:\Android\android-sdk\build-tools\31.0.0\zipalign.exe -p -f -v 4 temp.apk $i.FullName Remove-Item temp.apk } @@ -149,6 +149,8 @@ jobs: alias: ${{ secrets.ALIAS }} keyStorePassword: ${{ secrets.KEY_STORE_PASSWORD }} keyPassword: ${{ secrets.KEY_PASSWORD }} + env: + BUILD_TOOLS_VERSION: "31.0.0" - uses: actions/upload-artifact@v2 with: From af5a6878f4cc32423471213ed5aaa88e819703aa Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 16 Feb 2024 09:12:10 +1100 Subject: [PATCH 27/44] JoystickBase: make lost joystick overrideable --- ExtLibs/ArduPilot/Joystick/JoystickBase.cs | 83 +++++++++++++--------- build - Clean.bat | 2 +- 2 files changed, 50 insertions(+), 35 deletions(-) diff --git a/ExtLibs/ArduPilot/Joystick/JoystickBase.cs b/ExtLibs/ArduPilot/Joystick/JoystickBase.cs index d9332d0ed0..e067a60cca 100644 --- a/ExtLibs/ArduPilot/Joystick/JoystickBase.cs +++ b/ExtLibs/ArduPilot/Joystick/JoystickBase.cs @@ -42,6 +42,8 @@ public abstract class JoystickBase: IDisposable private Func _Interface; + private Action _LostAction; + protected SynchronizationContext _context; protected MAVLinkInterface Interface @@ -49,6 +51,12 @@ protected MAVLinkInterface Interface get { return _Interface(); } } + public Action LostAction + { + get { if(_LostAction != null) return _LostAction; return delegate () { }; } + set { _LostAction = value; } + } + public JoystickBase(Func currentInterface) { this._Interface = currentInterface; @@ -84,6 +92,14 @@ public JoystickBase(Func currentInterface) { loadconfig(); } + + _LostAction = new Action(delegate + { + _context.Send(delegate + { + CustomMessageBox.Show("Lost Joystick", "Lost Joystick"); + }, null); + }); } public void loadconfig(string joystickconfigbuttonin = "joystickbuttons.xml", @@ -604,38 +620,38 @@ void ProcessButtonEvent(JoyButton but, bool buttondown) const int RESXul = 1024; const int RESXl = 1024; const int RESKul = 100; - /* - - ushort expou(ushort x, ushort k) - { - // k*x*x*x + (1-k)*x - return ((ulong)x*x*x/0x10000*k/(RESXul*RESXul/0x10000) + (RESKul-k)*x+RESKul/2)/RESKul; - } - // expo-funktion: - // --------------- - // kmplot - // f(x,k)=exp(ln(x)*k/10) ;P[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] - // f(x,k)=x*x*x*k/10 + x*(1-k/10) ;P[0,1,2,3,4,5,6,7,8,9,10] - // f(x,k)=x*x*k/10 + x*(1-k/10) ;P[0,1,2,3,4,5,6,7,8,9,10] - // f(x,k)=1+(x-1)*(x-1)*(x-1)*k/10 + (x-1)*(1-k/10) ;P[0,1,2,3,4,5,6,7,8,9,10] - - short expo(short x, short k) - { - if (k == 0) return x; - short y; - bool neg = x < 0; - if (neg) x = -x; - if (k < 0) - { - y = RESXu - expou((ushort)(RESXu - x), (ushort)-k); - } - else - { - y = expou((ushort)x, (ushort)k); - } - return neg ? -y : y; - } - + /* + + ushort expou(ushort x, ushort k) + { + // k*x*x*x + (1-k)*x + return ((ulong)x*x*x/0x10000*k/(RESXul*RESXul/0x10000) + (RESKul-k)*x+RESKul/2)/RESKul; + } + // expo-funktion: + // --------------- + // kmplot + // f(x,k)=exp(ln(x)*k/10) ;P[0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20] + // f(x,k)=x*x*x*k/10 + x*(1-k/10) ;P[0,1,2,3,4,5,6,7,8,9,10] + // f(x,k)=x*x*k/10 + x*(1-k/10) ;P[0,1,2,3,4,5,6,7,8,9,10] + // f(x,k)=1+(x-1)*(x-1)*(x-1)*k/10 + (x-1)*(1-k/10) ;P[0,1,2,3,4,5,6,7,8,9,10] + + short expo(short x, short k) + { + if (k == 0) return x; + short y; + bool neg = x < 0; + if (neg) x = -x; + if (k < 0) + { + y = RESXu - expou((ushort)(RESXu - x), (ushort)-k); + } + else + { + y = expou((ushort)x, (ushort)k); + } + return neg ? -y : y; + } + */ @@ -1113,8 +1129,7 @@ protected virtual void mainloop() { log.Error(ex); clearRCOverride(); - _context.Send( - delegate { CustomMessageBox.Show("Lost Joystick", "Lost Joystick"); }, null); + LostAction(); return; } catch (Exception ex) diff --git a/build - Clean.bat b/build - Clean.bat index 7746652e16..d19d5116ec 100644 --- a/build - Clean.bat +++ b/build - Clean.bat @@ -1,4 +1,4 @@ -set PATH=%PATH%;C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin;C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\15.0\Bin;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin +set PATH=%PATH%;C:\Program Files\Microsoft Visual Studio\2022\Community\Msbuild\Current\Bin;C:\Program Files (x86)\Microsoft Visual Studio\2019\Preview\MSBuild\Current\Bin;C:\Program Files (x86)\Microsoft Visual Studio\Preview\Community\MSBuild\15.0\Bin;C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\MSBuild\15.0\Bin "MSBuild.exe" MissionPlanner.sln /m /p:Configuration=Debug /verbosity:d /t:Clean "MSBuild.exe" MissionPlanner.sln /m /p:Configuration=Release /verbosity:d /t:Clean From 76e91a7b5dc24d58924f0fccdb904b7f9c9c7886 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Thu, 22 Feb 2024 16:01:34 +1100 Subject: [PATCH 28/44] DFLogBuffer: move to longs --- ExtLibs/Utilities/DFLogBuffer.cs | 35 ++++++++++++++++---------------- 1 file changed, 18 insertions(+), 17 deletions(-) diff --git a/ExtLibs/Utilities/DFLogBuffer.cs b/ExtLibs/Utilities/DFLogBuffer.cs index 472dbaf7bd..79af620475 100644 --- a/ExtLibs/Utilities/DFLogBuffer.cs +++ b/ExtLibs/Utilities/DFLogBuffer.cs @@ -8,6 +8,7 @@ using System.Text; using System.Text.RegularExpressions; using System.Threading.Tasks; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Newtonsoft.Json; namespace MissionPlanner.Utilities @@ -21,23 +22,23 @@ public class DFLogBuffer : IEnumerable, IDisposable public DFLog dflog { get; } Stream basestream; - private int _count; - List linestartoffset = new List(); + private long _count; + List linestartoffset = new List(); /// /// Type and offsets /// - List[] messageindex = new List[256]; + List[] messageindex = new List[256]; /// /// Type and line numbers /// - List[] messageindexline = new List[256]; + List[] messageindexline = new List[256]; bool binary = false; object locker = new object(); - int indexcachelineno = -1; + long indexcachelineno = -1; String currentindexcache = null; public DFLogBuffer(string filename) : this(File.Open(filename,FileMode.Open,FileAccess.Read,FileShare.Read)) @@ -49,8 +50,8 @@ public DFLogBuffer(Stream instream) dflog = new DFLog(this); for (int a = 0; a < messageindex.Length; a++) { - messageindex[a] = new List(); - messageindexline[a] = new List(); + messageindex[a] = new List(); + messageindexline[a] = new List(); } if (instream.CanSeek) @@ -90,7 +91,7 @@ void setlinecount() byte[] buffer = new byte[1024*1024]; - var lineCount = 0; + var lineCount = 0l; if (binary) { @@ -103,10 +104,10 @@ void setlinecount() continue; byte type = ans.Item1; - messageindex[type].Add((uint)(ans.Item2)); - messageindexline[type].Add((uint) lineCount); + messageindex[type].Add(ans.Item2); + messageindexline[type].Add(lineCount); - linestartoffset.Add((uint)(ans.Item2)); + linestartoffset.Add(ans.Item2); lineCount++; if (lineCount % 1000000 == 0) @@ -359,6 +360,9 @@ public DFLog.DFItem this[long indexin] { get { + if (indexin > int.MaxValue) + throw new Exception("index too large"); + var index = (int)indexin; long startoffset = linestartoffset[index]; @@ -464,7 +468,7 @@ public void Clear() public int Count { - get { return _count; } + get { if (_count > int.MaxValue) Console.WriteLine("log line count is too large"); return (int)_count; } } public bool IsReadOnly @@ -549,6 +553,8 @@ public bool IsReadOnly progress = DateTime.Now.Second; } var ans = this[(long) l]; + if (!instances.ContainsKey(ans.msgtype)) + continue; var inst = instances[ans.msgtype]; // instance was requested, and its not a match //if (inst != "" && ans.instance != inst) @@ -606,11 +612,6 @@ public List SeenMessageTypes } } - public String ReadLine() - { - return this[indexcachelineno+1]; - } - public Tuple GetUnit(string type, string header) { var answer = UnitMultiList.Where(tuple => tuple.Item1 == type && tuple.Item2 == header); From 33166e1e2f9cc712511027d8a05cb5b54658586f Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Thu, 22 Feb 2024 22:46:30 +1100 Subject: [PATCH 29/44] LogBrowse: improve performance slightly. --- Log/LogBrowse.cs | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Log/LogBrowse.cs b/Log/LogBrowse.cs index 11deed5547..b6f9a2250d 100644 --- a/Log/LogBrowse.cs +++ b/Log/LogBrowse.cs @@ -3649,9 +3649,19 @@ private void chk_datagrid_CheckedChanged(object sender1, EventArgs e) } else { + dataGridView1.Visible = false; dataGridView1.VirtualMode = true; dataGridView1.ColumnCount = colcount; + for(int u=0;u < dataGridView1.ColumnCount; u++) + { + dataGridView1.Columns[u].Visible = false; + } dataGridView1.RowCount = logdata.Count; + for (int u = 0; u < dataGridView1.ColumnCount; u++) + { + dataGridView1.Columns[u].Visible = true; + } + dataGridView1.Visible = true; log.Info("datagrid size set " + (GC.GetTotalMemory(false) / 1024.0 / 1024.0)); } From 1e820e7a6377339207af6d2f80069761d102bdea Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Mon, 15 Jan 2024 20:31:02 +0100 Subject: [PATCH 30/44] Update SerialOptionRules.json --- SerialOptionRules.json | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/SerialOptionRules.json b/SerialOptionRules.json index 73ae39e81e..d4bd0be3e3 100644 --- a/SerialOptionRules.json +++ b/SerialOptionRules.json @@ -8,15 +8,5 @@ "PresetBaudRate": -1, "PresetOptionsByte": 0, "Comment": "If connecting a Mavlink sensor, consider setting 'Do not forward Mavlink to/from'" - }, - "10": { - "PresetBaudRate": -1, - "PresetOptionsByte": 7, - "Comment": "If not using inverter, remove 'Half Duplex' if not a H7 board remove 'invert Tx/RX' and add 'Pullup' if neccessary" - }, - "23": { - "PresetBaudRate": -1, - "PresetOptionsByte": 7, - "Comment": "If not using inverter, remove 'Half Duplex' if not a H7 board remove 'invert Tx/RX' and add 'Pullup' if neccessary" } -} \ No newline at end of file +} From ed086e60a7f030fc816fc8696d677484aaf71d7a Mon Sep 17 00:00:00 2001 From: Andras Schaffer Date: Mon, 15 Jan 2024 10:18:22 +0100 Subject: [PATCH 31/44] Disable ConfigStandardParams and ConfigAdvancedParams pages and enable ConfigFullParamList. --- ExtLibs/Utilities/DisplayView.cs | 19 ++++++++++--------- GCSViews/SoftwareConfig.cs | 4 ++-- MainV2.cs | 4 ++++ 3 files changed, 16 insertions(+), 11 deletions(-) diff --git a/ExtLibs/Utilities/DisplayView.cs b/ExtLibs/Utilities/DisplayView.cs index 8b935879c2..b8472ab1a1 100644 --- a/ExtLibs/Utilities/DisplayView.cs +++ b/ExtLibs/Utilities/DisplayView.cs @@ -1,4 +1,5 @@ -using System; +using org.mariuszgromada.math.mxparser.mathcollection; +using System; using System.Collections; using System.Collections.Generic; using System.IO; @@ -196,10 +197,10 @@ public DisplayView() //config tuning displayBasicTuning = true; displayExtendedTuning = true; - displayStandardParams = true; + displayStandardParams = false; displayAdvancedParams = false; - displayFullParamList = false; - displayFullParamTree = false; + displayFullParamList = true; + displayFullParamTree = true; displayParamCommitButton = false; displayBaudCMB = true; standardFlightModesOnly = false; @@ -322,10 +323,10 @@ public static DisplayView Basic(this DisplayView v) //config tuning displayBasicTuning = true, displayExtendedTuning = true, - displayStandardParams = true, + displayStandardParams = false, displayAdvancedParams = false, - displayFullParamList = false, - displayFullParamTree = false, + displayFullParamList = true, + displayFullParamTree = true, displayParamCommitButton = false, displayBaudCMB = true, displaySerialPortCMB = true, @@ -404,8 +405,8 @@ public static DisplayView Advanced(this DisplayView v) //config tuning displayBasicTuning = true, displayExtendedTuning = true, - displayStandardParams = true, - displayAdvancedParams = true, + displayStandardParams = false, + displayAdvancedParams = false, displayFullParamList = true, displayFullParamTree = true, displayParamCommitButton = false, diff --git a/GCSViews/SoftwareConfig.cs b/GCSViews/SoftwareConfig.cs index 764279f5c9..9cb0bf9199 100644 --- a/GCSViews/SoftwareConfig.cs +++ b/GCSViews/SoftwareConfig.cs @@ -94,7 +94,7 @@ private void SoftwareConfig_Load(object sender, EventArgs e) start = AddBackstageViewPage(typeof(ConfigAntennaTracker), Strings.ExtendedTuning); } - if (MainV2.DisplayConfiguration.displayBasicTuning) + if (MainV2.DisplayConfiguration.displayStandardParams) { AddBackstageViewPage(typeof(ConfigFriendlyParams), Strings.StandardParams); } @@ -122,7 +122,7 @@ private void SoftwareConfig_Load(object sender, EventArgs e) if (MainV2.DisplayConfiguration.displayFullParamList) { if(!MainV2.comPort.BaseStream.IsOpen || gotAllParams) - AddBackstageViewPage(typeof(ConfigRawParams), Strings.FullParameterList, null, true); + AddBackstageViewPage(typeof(ConfigRawParams), Strings.FullParameterList, null, false); } if (MainV2.comPort.BaseStream.IsOpen) { diff --git a/MainV2.cs b/MainV2.cs index d29e07f09e..1d9175092a 100644 --- a/MainV2.cs +++ b/MainV2.cs @@ -974,6 +974,10 @@ public MainV2() try { DisplayConfiguration = Settings.Instance.GetDisplayView("displayview"); + //Force new view in case of saved view in config.xml + DisplayConfiguration.displayAdvancedParams = false; + DisplayConfiguration.displayStandardParams = false; + DisplayConfiguration.displayFullParamList = true; } catch { From 0e2a913a671b8a403376e72ceac2d3fc0d4dd8bc Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Sat, 24 Feb 2024 21:35:28 +1100 Subject: [PATCH 32/44] DFLogBuffer: add SplitLog --- ExtLibs/Utilities/DFLogBuffer.cs | 90 +++++++++++++++++++++++++++++++- 1 file changed, 89 insertions(+), 1 deletion(-) diff --git a/ExtLibs/Utilities/DFLogBuffer.cs b/ExtLibs/Utilities/DFLogBuffer.cs index 79af620475..db786a7d4d 100644 --- a/ExtLibs/Utilities/DFLogBuffer.cs +++ b/ExtLibs/Utilities/DFLogBuffer.cs @@ -43,10 +43,14 @@ public class DFLogBuffer : IEnumerable, IDisposable public DFLogBuffer(string filename) : this(File.Open(filename,FileMode.Open,FileAccess.Read,FileShare.Read)) { + _filename = filename; } public DFLogBuffer(Stream instream) { + if (instream is FileStream) + _filename = ((FileStream)instream).Name; + dflog = new DFLog(this); for (int a = 0; a < messageindex.Length; a++) { @@ -117,7 +121,7 @@ void setlinecount() _count = lineCount; // build fmt line database to pre seed the FMT message - messageindexline[128].ForEach(a => dflog.FMTLine(this[(int) a])); + messageindexline[128].ForEach(a => dflog.FMTLine(this[(int)a])); try { @@ -303,6 +307,89 @@ void setlinecount() indexcachelineno = -1; } + + public void SplitLog(int pieces = 0) + { + long length = basestream.Length; + + if (pieces > 0) + { + long sizeofpiece = length / pieces; + + for(int i = 0; i < pieces; i++) + { + long start = i * sizeofpiece; + long end = start + sizeofpiece; + + using (var file = File.OpenWrite(_filename + "_split" + i + ".bin")) + { + var type = dflog.logformat["FMT"]; + + var buffer = new byte[1024*256]; + + // fmt from entire file + messageindex[type.Id].ForEach(a => { + basestream.Seek(a, SeekOrigin.Begin); + int read = basestream.Read(buffer, 0, type.Length); + file.Write(buffer, 0, read); + }); + + type = dflog.logformat["FMTU"]; + + messageindex[type.Id].ForEach(a => { + basestream.Seek(a, SeekOrigin.Begin); + int read = basestream.Read(buffer, 0, type.Length); + file.Write(buffer, 0, read); + }); + + type = dflog.logformat["UNIT"]; + + messageindex[type.Id].ForEach(a => { + basestream.Seek(a, SeekOrigin.Begin); + int read = basestream.Read(buffer, 0, type.Length); + file.Write(buffer, 0, read); + }); + + type = dflog.logformat["MULT"]; + + messageindex[type.Id].ForEach(a => { + basestream.Seek(a, SeekOrigin.Begin); + int read = basestream.Read(buffer, 0, type.Length); + file.Write(buffer, 0, read); + }); + + + + var min = long.MaxValue; + var max = long.MinValue; + + // got min and max valid + linestartoffset.ForEach(a => + { + if (a >= start && a < end) + { + min = Math.Min(min, a); + max = Math.Max(max, a); + } + }); + + basestream.Seek(min, SeekOrigin.Begin); + + while (basestream.Position < max) + { + int readsize = (int)Math.Min((end - basestream.Position), buffer.Length); + int read = basestream.Read(buffer, 0, readsize); + file.Write(buffer, 0, read); + } + } + } + } + else + { + throw new Exception("Invalid pieces parameters"); + } + } + private void BuildUnitMultiList() { foreach (var msgtype in FMT) @@ -348,6 +435,7 @@ private void BuildUnitMultiList() public List> UnitMultiList = new List>(); public Dictionary value)> InstanceType = new Dictionary value)>(); + private string _filename; public Dictionary FMT { get; set; } = new Dictionary(); From 60ffda9895aedf612438f5d216146c37d32dde91 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Sat, 24 Feb 2024 21:35:56 +1100 Subject: [PATCH 33/44] temp: add SplitLog as button --- temp.Designer.cs | 108 ++++++++++++++++++++++++++++++++--------- temp.cs | 107 +++++----------------------------------- temp.resx | 124 +++++++++++++++++++++++------------------------ 3 files changed, 159 insertions(+), 180 deletions(-) diff --git a/temp.Designer.cs b/temp.Designer.cs index fa8da2fd04..6c2550f4b3 100644 --- a/temp.Designer.cs +++ b/temp.Designer.cs @@ -30,6 +30,8 @@ private void InitializeComponent() { System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(temp)); this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel(); + this.BUT_forcecal_accel = new MissionPlanner.Controls.MyButton(); + this.BUT_forcecal_mag = new MissionPlanner.Controls.MyButton(); this.but_apjtool = new MissionPlanner.Controls.MyButton(); this.BUT_CoT = new MissionPlanner.Controls.MyButton(); this.but_proximity = new MissionPlanner.Controls.MyButton(); @@ -145,13 +147,11 @@ private void InitializeComponent() this.label12 = new System.Windows.Forms.Label(); this.but_ManageCMDList = new MissionPlanner.Controls.MyButton(); this.label28 = new System.Windows.Forms.Label(); - this.controlSensorsStatus1 = new MissionPlanner.Controls.ControlSensorsStatus(); this.but_dfumode = new MissionPlanner.Controls.MyButton(); this.label56 = new System.Windows.Forms.Label(); - this.BUT_forcecal_mag = new MissionPlanner.Controls.MyButton(); - this.BUT_forcecal_accel = new MissionPlanner.Controls.MyButton(); this.label57 = new System.Windows.Forms.Label(); this.label58 = new System.Windows.Forms.Label(); + this.controlSensorsStatus1 = new MissionPlanner.Controls.ControlSensorsStatus(); this.tableLayoutPanel1.SuspendLayout(); this.SuspendLayout(); // @@ -282,10 +282,27 @@ private void InitializeComponent() this.tableLayoutPanel1.Controls.Add(this.label58, 1, 31); this.tableLayoutPanel1.Name = "tableLayoutPanel1"; // + // BUT_forcecal_accel + // + resources.ApplyResources(this.BUT_forcecal_accel, "BUT_forcecal_accel"); + this.BUT_forcecal_accel.Name = "BUT_forcecal_accel"; + this.BUT_forcecal_accel.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); + this.BUT_forcecal_accel.UseVisualStyleBackColor = true; + this.BUT_forcecal_accel.Click += new System.EventHandler(this.BUT_forcecal_accel_Click); + // + // BUT_forcecal_mag + // + resources.ApplyResources(this.BUT_forcecal_mag, "BUT_forcecal_mag"); + this.BUT_forcecal_mag.Name = "BUT_forcecal_mag"; + this.BUT_forcecal_mag.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); + this.BUT_forcecal_mag.UseVisualStyleBackColor = true; + this.BUT_forcecal_mag.Click += new System.EventHandler(this.BUT_forcecal_mag_Click); + // // but_apjtool // resources.ApplyResources(this.but_apjtool, "but_apjtool"); this.but_apjtool.Name = "but_apjtool"; + this.but_apjtool.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_apjtool.UseVisualStyleBackColor = true; this.but_apjtool.Click += new System.EventHandler(this.but_signfw_Click); // @@ -293,6 +310,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_CoT, "BUT_CoT"); this.BUT_CoT.Name = "BUT_CoT"; + this.BUT_CoT.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_CoT.UseVisualStyleBackColor = true; this.BUT_CoT.Click += new System.EventHandler(this.BUT_CoT_Click); // @@ -300,6 +318,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_proximity, "but_proximity"); this.but_proximity.Name = "but_proximity"; + this.but_proximity.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_proximity.UseVisualStyleBackColor = true; this.but_proximity.Click += new System.EventHandler(this.but_proximity_Click); // @@ -307,6 +326,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_followswarm, "but_followswarm"); this.but_followswarm.Name = "but_followswarm"; + this.but_followswarm.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_followswarm.UseVisualStyleBackColor = true; this.but_followswarm.Click += new System.EventHandler(this.but_followswarm_Click); // @@ -319,6 +339,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_lockup, "but_lockup"); this.but_lockup.Name = "but_lockup"; + this.but_lockup.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_lockup.UseVisualStyleBackColor = true; this.but_lockup.Click += new System.EventHandler(this.but_lockup_Click); // @@ -326,6 +347,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_td, "but_td"); this.but_td.Name = "but_td"; + this.but_td.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_td.UseVisualStyleBackColor = true; this.but_td.Click += new System.EventHandler(this.but_td_Click); // @@ -333,6 +355,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_gpsinj, "but_gpsinj"); this.but_gpsinj.Name = "but_gpsinj"; + this.but_gpsinj.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_gpsinj.UseVisualStyleBackColor = true; this.but_gpsinj.Click += new System.EventHandler(this.but_gpsinj_Click); // @@ -340,6 +363,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_dem, "but_dem"); this.but_dem.Name = "but_dem"; + this.but_dem.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_dem.UseVisualStyleBackColor = true; this.but_dem.Click += new System.EventHandler(this.but_dem_Click); // @@ -347,6 +371,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_magfit2, "BUT_magfit2"); this.BUT_magfit2.Name = "BUT_magfit2"; + this.BUT_magfit2.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_magfit2.UseVisualStyleBackColor = true; this.BUT_magfit2.Click += new System.EventHandler(this.BUT_magfit2_Click); // @@ -354,6 +379,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_GDAL, "but_GDAL"); this.but_GDAL.Name = "but_GDAL"; + this.but_GDAL.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_GDAL.UseVisualStyleBackColor = true; this.but_GDAL.Click += new System.EventHandler(this.but_GDAL_Click); // @@ -361,6 +387,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_sortlogs, "but_sortlogs"); this.but_sortlogs.Name = "but_sortlogs"; + this.but_sortlogs.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_sortlogs.UseVisualStyleBackColor = true; this.but_sortlogs.Click += new System.EventHandler(this.but_sortlogs_Click); // @@ -368,6 +395,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_optflowcalib, "but_optflowcalib"); this.but_optflowcalib.Name = "but_optflowcalib"; + this.but_optflowcalib.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_optflowcalib.UseVisualStyleBackColor = true; this.but_optflowcalib.Click += new System.EventHandler(this.but_optflowcalib_Click); // @@ -375,6 +403,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_logdlscp, "but_logdlscp"); this.but_logdlscp.Name = "but_logdlscp"; + this.but_logdlscp.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_logdlscp.UseVisualStyleBackColor = true; this.but_logdlscp.Click += new System.EventHandler(this.but_logdlscp_Click); // @@ -382,6 +411,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_signkey, "but_signkey"); this.but_signkey.Name = "but_signkey"; + this.but_signkey.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_signkey.UseVisualStyleBackColor = true; this.but_signkey.Click += new System.EventHandler(this.but_signkey_Click); // @@ -389,6 +419,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_acbarohight, "but_acbarohight"); this.but_acbarohight.Name = "but_acbarohight"; + this.but_acbarohight.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_acbarohight.UseVisualStyleBackColor = true; this.but_acbarohight.Click += new System.EventHandler(this.but_acbarohight_Click); // @@ -396,6 +427,7 @@ private void InitializeComponent() // resources.ApplyResources(this.myButton1, "myButton1"); this.myButton1.Name = "myButton1"; + this.myButton1.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.myButton1.UseVisualStyleBackColor = true; this.myButton1.Click += new System.EventHandler(this.myButton1_Click_2); // @@ -403,6 +435,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_driverclean, "but_driverclean"); this.but_driverclean.Name = "but_driverclean"; + this.but_driverclean.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_driverclean.UseVisualStyleBackColor = true; this.but_driverclean.Click += new System.EventHandler(this.BUT_driverclean_Click); // @@ -410,6 +443,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_agemapdata, "but_agemapdata"); this.but_agemapdata.Name = "but_agemapdata"; + this.but_agemapdata.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_agemapdata.UseVisualStyleBackColor = true; this.but_agemapdata.Click += new System.EventHandler(this.but_agemapdata_Click); // @@ -417,6 +451,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_packetbytes, "but_packetbytes"); this.but_packetbytes.Name = "but_packetbytes"; + this.but_packetbytes.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_packetbytes.UseVisualStyleBackColor = true; this.but_packetbytes.Click += new System.EventHandler(this.but_packetbytes_Click); // @@ -424,6 +459,7 @@ private void InitializeComponent() // resources.ApplyResources(this.myButton_vlc, "myButton_vlc"); this.myButton_vlc.Name = "myButton_vlc"; + this.myButton_vlc.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.myButton_vlc.UseVisualStyleBackColor = true; this.myButton_vlc.Click += new System.EventHandler(this.myButton_vlc_Click); // @@ -436,6 +472,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_trimble, "but_trimble"); this.but_trimble.Name = "but_trimble"; + this.but_trimble.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_trimble.UseVisualStyleBackColor = true; this.but_trimble.Click += new System.EventHandler(this.but_trimble_Click); // @@ -443,6 +480,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_hwids, "but_hwids"); this.but_hwids.Name = "but_hwids"; + this.but_hwids.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_hwids.UseVisualStyleBackColor = true; this.but_hwids.Click += new System.EventHandler(this.but_hwids_Click); // @@ -450,6 +488,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_QNH, "BUT_QNH"); this.BUT_QNH.Name = "BUT_QNH"; + this.BUT_QNH.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_QNH.UseVisualStyleBackColor = true; this.BUT_QNH.Click += new System.EventHandler(this.BUT_QNH_Click); // @@ -457,6 +496,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_reboot, "but_reboot"); this.but_reboot.Name = "but_reboot"; + this.but_reboot.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_reboot.UseVisualStyleBackColor = true; this.but_reboot.Click += new System.EventHandler(this.but_reboot_Click); // @@ -464,6 +504,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_3dmap, "but_3dmap"); this.but_3dmap.Name = "but_3dmap"; + this.but_3dmap.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_3dmap.UseVisualStyleBackColor = true; this.but_3dmap.Click += new System.EventHandler(this.but_3dmap_Click); // @@ -471,6 +512,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_messageinterval, "but_messageinterval"); this.but_messageinterval.Name = "but_messageinterval"; + this.but_messageinterval.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_messageinterval.UseVisualStyleBackColor = true; this.but_messageinterval.Click += new System.EventHandler(this.but_messageinterval_Click); // @@ -478,6 +520,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_blupdate, "but_blupdate"); this.but_blupdate.Name = "but_blupdate"; + this.but_blupdate.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_blupdate.UseVisualStyleBackColor = true; this.but_blupdate.Click += new System.EventHandler(this.but_blupdate_Click); // @@ -485,6 +528,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_fft, "BUT_fft"); this.BUT_fft.Name = "BUT_fft"; + this.BUT_fft.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_fft.UseVisualStyleBackColor = true; this.BUT_fft.Click += new System.EventHandler(this.BUT_fft_Click); // @@ -492,6 +536,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_disablearmswitch, "but_disablearmswitch"); this.but_disablearmswitch.Name = "but_disablearmswitch"; + this.but_disablearmswitch.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_disablearmswitch.UseVisualStyleBackColor = true; this.but_disablearmswitch.Click += new System.EventHandler(this.but_disablearmswitch_Click); // @@ -499,6 +544,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_paramrestore, "but_paramrestore"); this.but_paramrestore.Name = "but_paramrestore"; + this.but_paramrestore.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_paramrestore.UseVisualStyleBackColor = true; this.but_paramrestore.Click += new System.EventHandler(this.but_paramrestore_Click); // @@ -506,6 +552,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_mavinspector, "but_mavinspector"); this.but_mavinspector.Name = "but_mavinspector"; + this.but_mavinspector.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_mavinspector.UseVisualStyleBackColor = true; this.but_mavinspector.Click += new System.EventHandler(this.but_mavinspector_Click); // @@ -513,6 +560,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_sitl_comb, "but_sitl_comb"); this.but_sitl_comb.Name = "but_sitl_comb"; + this.but_sitl_comb.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_sitl_comb.UseVisualStyleBackColor = true; this.but_sitl_comb.Click += new System.EventHandler(this.but_sitl_comb_Click); // @@ -520,6 +568,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_anonlog, "but_anonlog"); this.but_anonlog.Name = "but_anonlog"; + this.but_anonlog.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_anonlog.UseVisualStyleBackColor = true; this.but_anonlog.Click += new System.EventHandler(this.but_anonlog_Click); // @@ -527,6 +576,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_dashware, "but_dashware"); this.but_dashware.Name = "but_dashware"; + this.but_dashware.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_dashware.UseVisualStyleBackColor = true; this.but_dashware.Click += new System.EventHandler(this.but_dashware_Click); // @@ -574,6 +624,7 @@ private void InitializeComponent() // resources.ApplyResources(this.butlogindex, "butlogindex"); this.butlogindex.Name = "butlogindex"; + this.butlogindex.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.butlogindex.UseVisualStyleBackColor = true; this.butlogindex.Click += new System.EventHandler(this.butlogindex_Click); // @@ -581,12 +632,14 @@ private void InitializeComponent() // resources.ApplyResources(this.but_armandtakeoff, "but_armandtakeoff"); this.but_armandtakeoff.Name = "but_armandtakeoff"; + this.but_armandtakeoff.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_armandtakeoff.Click += new System.EventHandler(this.but_armandtakeoff_Click); // // but_maplogs // resources.ApplyResources(this.but_maplogs, "but_maplogs"); this.but_maplogs.Name = "but_maplogs"; + this.but_maplogs.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_maplogs.UseVisualStyleBackColor = true; this.but_maplogs.Click += new System.EventHandler(this.but_maplogs_Click); // @@ -599,6 +652,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_gimbaltest, "but_gimbaltest"); this.but_gimbaltest.Name = "but_gimbaltest"; + this.but_gimbaltest.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_gimbaltest.UseVisualStyleBackColor = true; this.but_gimbaltest.Click += new System.EventHandler(this.but_gimbaltest_Click); // @@ -606,6 +660,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_structtest, "but_structtest"); this.but_structtest.Name = "but_structtest"; + this.but_structtest.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_structtest.UseVisualStyleBackColor = true; this.but_structtest.Click += new System.EventHandler(this.but_structtest_Click); // @@ -643,6 +698,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_clearcustommaps, "BUT_clearcustommaps"); this.BUT_clearcustommaps.Name = "BUT_clearcustommaps"; + this.BUT_clearcustommaps.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_clearcustommaps.UseVisualStyleBackColor = true; this.BUT_clearcustommaps.Click += new System.EventHandler(this.BUT_clearcustommaps_Click); // @@ -650,6 +706,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_getfw, "but_getfw"); this.but_getfw.Name = "but_getfw"; + this.but_getfw.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_getfw.UseVisualStyleBackColor = true; this.but_getfw.Click += new System.EventHandler(this.but_getfw_Click); // @@ -657,6 +714,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_geinjection, "BUT_geinjection"); this.BUT_geinjection.Name = "BUT_geinjection"; + this.BUT_geinjection.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_geinjection.UseVisualStyleBackColor = true; this.BUT_geinjection.Click += new System.EventHandler(this.BUT_geinjection_Click); // @@ -674,6 +732,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_sorttlogs, "BUT_sorttlogs"); this.BUT_sorttlogs.Name = "BUT_sorttlogs"; + this.BUT_sorttlogs.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_sorttlogs.UseVisualStyleBackColor = true; this.BUT_sorttlogs.Click += new System.EventHandler(this.BUT_sorttlogs_Click); // @@ -706,6 +765,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_outputMavlink, "BUT_outputMavlink"); this.BUT_outputMavlink.Name = "BUT_outputMavlink"; + this.BUT_outputMavlink.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_outputMavlink.UseVisualStyleBackColor = true; this.BUT_outputMavlink.Click += new System.EventHandler(this.BUT_outputMavlink_Click); // @@ -713,6 +773,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_outputMD, "BUT_outputMD"); this.BUT_outputMD.Name = "BUT_outputMD"; + this.BUT_outputMD.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_outputMD.UseVisualStyleBackColor = true; this.BUT_outputMD.Click += new System.EventHandler(this.myButton1_Click); // @@ -720,6 +781,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_outputnmea, "BUT_outputnmea"); this.BUT_outputnmea.Name = "BUT_outputnmea"; + this.BUT_outputnmea.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_outputnmea.UseVisualStyleBackColor = true; this.BUT_outputnmea.Click += new System.EventHandler(this.BUT_outputnmea_Click); // @@ -727,12 +789,14 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_georefimage, "BUT_georefimage"); this.BUT_georefimage.Name = "BUT_georefimage"; + this.BUT_georefimage.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_georefimage.Click += new System.EventHandler(this.BUT_georefimage_Click); // // button3 // resources.ApplyResources(this.button3, "button3"); this.button3.Name = "button3"; + this.button3.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.button3.UseVisualStyleBackColor = true; this.button3.Click += new System.EventHandler(this.button3_Click); // @@ -740,6 +804,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_lang_edit, "BUT_lang_edit"); this.BUT_lang_edit.Name = "BUT_lang_edit"; + this.BUT_lang_edit.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_lang_edit.UseVisualStyleBackColor = true; this.BUT_lang_edit.Click += new System.EventHandler(this.BUT_lang_edit_Click); // @@ -747,6 +812,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_follow_me, "BUT_follow_me"); this.BUT_follow_me.Name = "BUT_follow_me"; + this.BUT_follow_me.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_follow_me.UseVisualStyleBackColor = true; this.BUT_follow_me.Click += new System.EventHandler(this.BUT_follow_me_Click); // @@ -754,6 +820,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_paramgen, "BUT_paramgen"); this.BUT_paramgen.Name = "BUT_paramgen"; + this.BUT_paramgen.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_paramgen.UseVisualStyleBackColor = true; this.BUT_paramgen.Click += new System.EventHandler(this.BUT_paramgen_Click); // @@ -761,6 +828,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_osdvideo, "but_osdvideo"); this.but_osdvideo.Name = "but_osdvideo"; + this.but_osdvideo.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_osdvideo.UseVisualStyleBackColor = true; this.but_osdvideo.Click += new System.EventHandler(this.but_osdvideo_Click); // @@ -768,6 +836,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_movingbase, "BUT_movingbase"); this.BUT_movingbase.Name = "BUT_movingbase"; + this.BUT_movingbase.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_movingbase.UseVisualStyleBackColor = true; this.BUT_movingbase.Click += new System.EventHandler(this.BUT_movingbase_Click); // @@ -775,6 +844,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_shptopoly, "BUT_shptopoly"); this.BUT_shptopoly.Name = "BUT_shptopoly"; + this.BUT_shptopoly.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_shptopoly.UseVisualStyleBackColor = true; this.BUT_shptopoly.Click += new System.EventHandler(this.BUT_shptopoly_Click); // @@ -782,6 +852,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_swarm, "BUT_swarm"); this.BUT_swarm.Name = "BUT_swarm"; + this.BUT_swarm.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_swarm.UseVisualStyleBackColor = true; this.BUT_swarm.Click += new System.EventHandler(this.BUT_swarm_Click); // @@ -789,6 +860,7 @@ private void InitializeComponent() // resources.ApplyResources(this.BUT_followleader, "BUT_followleader"); this.BUT_followleader.Name = "BUT_followleader"; + this.BUT_followleader.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.BUT_followleader.UseVisualStyleBackColor = true; this.BUT_followleader.Click += new System.EventHandler(this.BUT_followleader_Click); // @@ -801,6 +873,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_mavserialport, "but_mavserialport"); this.but_mavserialport.Name = "but_mavserialport"; + this.but_mavserialport.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_mavserialport.UseVisualStyleBackColor = true; this.but_mavserialport.Click += new System.EventHandler(this.but_mavserialport_Click); // @@ -808,6 +881,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_hexmavlink, "but_hexmavlink"); this.but_hexmavlink.Name = "but_hexmavlink"; + this.but_hexmavlink.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_hexmavlink.UseVisualStyleBackColor = true; this.but_hexmavlink.Click += new System.EventHandler(this.but_hexmavlink_Click); // @@ -955,6 +1029,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_remotedflogger, "but_remotedflogger"); this.but_remotedflogger.Name = "but_remotedflogger"; + this.but_remotedflogger.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_remotedflogger.UseVisualStyleBackColor = true; this.but_remotedflogger.Click += new System.EventHandler(this.but_remotedflogger_Click); // @@ -967,6 +1042,7 @@ private void InitializeComponent() // resources.ApplyResources(this.but_ManageCMDList, "but_ManageCMDList"); this.but_ManageCMDList.Name = "but_ManageCMDList"; + this.but_ManageCMDList.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_ManageCMDList.UseVisualStyleBackColor = true; this.but_ManageCMDList.Click += new System.EventHandler(this.but_ManageCMDList_Click); // @@ -975,15 +1051,11 @@ private void InitializeComponent() resources.ApplyResources(this.label28, "label28"); this.label28.Name = "label28"; // - // controlSensorsStatus1 - // - resources.ApplyResources(this.controlSensorsStatus1, "controlSensorsStatus1"); - this.controlSensorsStatus1.Name = "controlSensorsStatus1"; - // // but_dfumode // resources.ApplyResources(this.but_dfumode, "but_dfumode"); this.but_dfumode.Name = "but_dfumode"; + this.but_dfumode.TextColorNotEnabled = System.Drawing.Color.FromArgb(((int)(((byte)(64)))), ((int)(((byte)(87)))), ((int)(((byte)(4))))); this.but_dfumode.UseVisualStyleBackColor = true; this.but_dfumode.Click += new System.EventHandler(this.but_dfumode_Click); // @@ -992,21 +1064,6 @@ private void InitializeComponent() resources.ApplyResources(this.label56, "label56"); this.label56.Name = "label56"; // - // - // BUT_forcecal_mag - // - resources.ApplyResources(this.BUT_forcecal_mag, "BUT_forcecal_mag"); - this.BUT_forcecal_mag.Name = "BUT_forcecal_mag"; - this.BUT_forcecal_mag.UseVisualStyleBackColor = true; - this.BUT_forcecal_mag.Click += new System.EventHandler(this.BUT_forcecal_mag_Click); - // - // BUT_forcecal_accel - // - resources.ApplyResources(this.BUT_forcecal_accel, "BUT_forcecal_accel"); - this.BUT_forcecal_accel.Name = "BUT_forcecal_accel"; - this.BUT_forcecal_accel.UseVisualStyleBackColor = true; - this.BUT_forcecal_accel.Click += new System.EventHandler(this.BUT_forcecal_accel_Click); - // // label57 // resources.ApplyResources(this.label57, "label57"); @@ -1017,6 +1074,11 @@ private void InitializeComponent() resources.ApplyResources(this.label58, "label58"); this.label58.Name = "label58"; // + // controlSensorsStatus1 + // + resources.ApplyResources(this.controlSensorsStatus1, "controlSensorsStatus1"); + this.controlSensorsStatus1.Name = "controlSensorsStatus1"; + // // temp // resources.ApplyResources(this, "$this"); diff --git a/temp.cs b/temp.cs index 9576ae13e8..0283f4a2bf 100644 --- a/temp.cs +++ b/temp.cs @@ -719,101 +719,18 @@ private void but_agemapdata_Click(object sender, EventArgs e) private void myButton1_Click_2(object sender, EventArgs e) { - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduCopter-2.8.1/ArduCopter/Parameters.pde" - , "ArduCopter2.8.1.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduCopter-2.9.1/ArduCopter/Parameters.pde" - , "ArduCopter2.9.1.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduCopter-3.0/ArduCopter/Parameters.pde" - , "ArduCopter3.0.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduCopter-3.1.5/ArduCopter/Parameters.pde" - , "ArduCopter3.1.5.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduCopter-3.2.1/ArduCopter/Parameters.pde" - , "ArduCopter3.2.1.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/Copter-3.3.2/ArduCopter/Parameters.cpp" - , "ArduCopter3.3.2.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/Copter-3.3/ArduCopter/Parameters.cpp" - , "ArduCopter3.3.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/Copter-3.4/ArduCopter/Parameters.cpp" - , "ArduCopter3.4.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/Copter-3.4.6/ArduCopter/Parameters.cpp" - , "ArduCopter3.4.6.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/Copter-3.5.0/ArduCopter/Parameters.cpp" - , "ArduCopter3.5.0.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/Copter-3.5.2/ArduCopter/Parameters.cpp" - , "ArduCopter3.5.2.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/Copter-3.5.4/ArduCopter/Parameters.cpp" - , "ArduCopter3.5.4.xml"); - - - - // plane - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.8.3/ArduPlane/Parameters.cpp" - , "ArduPlane3.8.3.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.7.1/ArduPlane/Parameters.cpp" - , "ArduPlane3.7.1.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.7.0/ArduPlane/Parameters.cpp" - , "ArduPlane3.7.0.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.6.0/ArduPlane/Parameters.cpp" - , "ArduPlane3.6.0.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.5.2/ArduPlane/Parameters.cpp" - , "ArduPlane3.5.2.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.3.0/ArduPlane/Parameters.pde" - , "ArduPlane3.3.0.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.2.2/ArduPlane/Parameters.pde" - , "ArduPlane3.2.2.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.1.0/ArduPlane/Parameters.pde" - , "ArduPlane3.1.0.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-3.0.3/ArduPlane/Parameters.pde" - , "ArduPlane3.0.3.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-2.78b/ArduPlane/Parameters.pde" - , "ArduPlane2.78b.xml"); - - ParameterMetaDataParser.GetParameterInformation( - "https://raw.githubusercontent.com/ArduPilot/ardupilot/ArduPlane-2.75/ArduPlane/Parameters.pde" - , "ArduPlane2.75.xml"); + + OpenFileDialog openFileDialog1 = new OpenFileDialog(); + openFileDialog1.Filter = "Log Files|*.log;*.bin;*.BIN;*.LOG"; + openFileDialog1.FilterIndex = 2; + openFileDialog1.Multiselect = true; + openFileDialog1.InitialDirectory = Settings.Instance.LogDir; + if (openFileDialog1.ShowDialog() == DialogResult.OK) + { + int a = 10; + InputBox.Show("How Many", "Enter how many pieces to split into", ref a); + new DFLogBuffer(openFileDialog1.FileName).SplitLog(a); + } } private void but_signkey_Click(object sender, EventArgs e) diff --git a/temp.resx b/temp.resx index d663b5c60d..7822986588 100644 --- a/temp.resx +++ b/temp.resx @@ -310,7 +310,7 @@ 557, 475 - 185, 16 + 149, 13 92 @@ -676,7 +676,7 @@ 73 - Param gen cust + Split DFLog myButton1 @@ -820,7 +820,7 @@ 134, 399 - 190, 16 + 153, 13 98 @@ -1270,7 +1270,7 @@ 134, 475 - 80, 16 + 64, 13 72 @@ -1300,7 +1300,7 @@ 134, 456 - 216, 16 + 171, 13 71 @@ -1330,7 +1330,7 @@ 134, 437 - 170, 16 + 136, 13 70 @@ -1360,7 +1360,7 @@ 134, 418 - 136, 16 + 111, 13 69 @@ -1390,7 +1390,7 @@ 134, 380 - 173, 16 + 140, 13 67 @@ -1420,7 +1420,7 @@ 134, 361 - 133, 16 + 105, 13 66 @@ -1450,7 +1450,7 @@ 134, 342 - 165, 16 + 130, 13 65 @@ -1480,7 +1480,7 @@ 134, 323 - 151, 16 + 123, 13 64 @@ -1600,7 +1600,7 @@ 134, 304 - 211, 19 + 214, 13 63 @@ -1690,7 +1690,7 @@ 134, 266 - 256, 19 + 252, 13 61 @@ -1720,7 +1720,7 @@ 134, 247 - 146, 16 + 117, 13 60 @@ -1750,7 +1750,7 @@ 134, 228 - 159, 16 + 128, 13 59 @@ -1780,7 +1780,7 @@ 134, 190 - 193, 16 + 156, 13 57 @@ -1810,7 +1810,7 @@ 134, 171 - 231, 19 + 226, 19 56 @@ -1840,7 +1840,7 @@ 134, 152 - 253, 16 + 202, 13 55 @@ -1960,7 +1960,7 @@ 134, 133 - 165, 16 + 131, 13 54 @@ -1990,7 +1990,7 @@ 134, 114 - 254, 16 + 201, 13 53 @@ -2050,7 +2050,7 @@ 134, 95 - 258, 16 + 203, 13 52 @@ -2080,7 +2080,7 @@ 134, 76 - 237, 19 + 221, 13 51 @@ -2110,7 +2110,7 @@ 134, 57 - 200, 16 + 163, 13 50 @@ -2140,7 +2140,7 @@ 134, 38 - 176, 16 + 141, 13 49 @@ -2170,7 +2170,7 @@ 134, 19 - 186, 16 + 149, 13 48 @@ -2590,7 +2590,7 @@ 134, 0 - 143, 16 + 115, 13 47 @@ -2680,7 +2680,7 @@ 134, 532 - 160, 16 + 128, 13 106 @@ -2710,7 +2710,7 @@ 134, 494 - 263, 19 + 263, 13 108 @@ -2740,7 +2740,7 @@ 557, 19 - 150, 16 + 117, 13 109 @@ -2770,7 +2770,7 @@ 557, 38 - 175, 16 + 142, 13 110 @@ -2800,7 +2800,7 @@ 557, 57 - 208, 19 + 212, 13 111 @@ -2830,7 +2830,7 @@ 557, 76 - 207, 19 + 218, 13 112 @@ -2860,7 +2860,7 @@ 557, 95 - 139, 16 + 111, 13 113 @@ -2890,7 +2890,7 @@ 557, 114 - 94, 16 + 76, 13 114 @@ -2920,7 +2920,7 @@ 557, 133 - 236, 19 + 196, 13 115 @@ -2950,7 +2950,7 @@ 557, 152 - 209, 16 + 169, 13 116 @@ -2980,7 +2980,7 @@ 557, 171 - 172, 16 + 137, 13 117 @@ -3010,7 +3010,7 @@ 557, 190 - 176, 16 + 144, 13 118 @@ -3040,7 +3040,7 @@ 557, 209 - 233, 19 + 222, 19 119 @@ -3070,7 +3070,7 @@ 557, 228 - 217, 16 + 172, 13 120 @@ -3100,7 +3100,7 @@ 557, 247 - 216, 19 + 200, 13 121 @@ -3130,7 +3130,7 @@ 557, 266 - 209, 19 + 196, 13 122 @@ -3160,7 +3160,7 @@ 557, 304 - 19, 16 + 19, 13 123 @@ -3190,7 +3190,7 @@ 557, 323 - 19, 16 + 19, 13 124 @@ -3220,7 +3220,7 @@ 557, 342 - 16, 16 + 16, 13 125 @@ -3250,7 +3250,7 @@ 557, 361 - 121, 16 + 98, 13 126 @@ -3280,7 +3280,7 @@ 557, 380 - 89, 16 + 74, 13 127 @@ -3310,7 +3310,7 @@ 557, 399 - 51, 16 + 41, 13 128 @@ -3340,7 +3340,7 @@ 557, 418 - 214, 19 + 212, 19 129 @@ -3370,7 +3370,7 @@ 557, 437 - 233, 16 + 184, 13 130 @@ -3400,13 +3400,13 @@ 557, 456 - 168, 16 + 113, 13 131 - generate aged param data + split dflog into x pieces label52 @@ -3430,7 +3430,7 @@ 557, 494 - 158, 16 + 129, 13 132 @@ -3460,7 +3460,7 @@ 557, 513 - 141, 16 + 111, 13 133 @@ -3490,7 +3490,7 @@ 557, 532 - 77, 16 + 61, 13 134 @@ -3544,7 +3544,7 @@ 134, 551 - 157, 16 + 126, 13 137 @@ -3598,7 +3598,7 @@ 557, 551 - 204, 16 + 161, 13 139 @@ -3649,7 +3649,7 @@ 557, 570 - 73, 16 + 59, 13 141 @@ -3679,7 +3679,7 @@ 134, 570 - 239, 16 + 190, 13 144 @@ -3709,7 +3709,7 @@ 134, 589 - 233, 16 + 184, 13 145 @@ -3772,7 +3772,7 @@ controlSensorsStatus1 - MissionPlanner.Controls.ControlSensorsStatus, MissionPlanner, Version=1.3.8446.38353, Culture=neutral, PublicKeyToken=null + MissionPlanner.Controls.ControlSensorsStatus, MissionPlanner, Version=1.3.8820.14861, Culture=neutral, PublicKeyToken=null $this @@ -3790,7 +3790,7 @@ True - 1027, 628 + 1044, 628 temp From 2dd3602d76407fb0094c22e65d0cab7331f41446 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Sat, 24 Feb 2024 22:27:29 +1100 Subject: [PATCH 34/44] Spectrogram: mod divisor on large data sets --- ExtLibs/Utilities/Spectrogram.cs | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/ExtLibs/Utilities/Spectrogram.cs b/ExtLibs/Utilities/Spectrogram.cs index c7ec415419..da48c303bf 100644 --- a/ExtLibs/Utilities/Spectrogram.cs +++ b/ExtLibs/Utilities/Spectrogram.cs @@ -23,10 +23,12 @@ public static Image GenerateImage(DFLogBuffer cb, out double[] freqtout, out List<(double timeus, double[] value)> allfftdata, string type = "ACC1", string field = "AccX", string timeus = "TimeUS", int min = -80, int max = -20) { + Console.WriteLine("GenerateImage " + type + " " + field); allfftdata = new List<(double timeus, double[] value)>(); if (cb.SeenMessageTypes.Contains("ISBH")) { + Console.WriteLine("GenerateImage seen ISBH"); int sensorno = (type.Contains("1") ? 0 : (type.Contains("2") ? 1 : 2)); int sensor = type.Contains("ACC") ? 0 : 1; int Ns = -1; @@ -117,6 +119,8 @@ public static Image GenerateImage(DFLogBuffer cb, out double[] freqtout, int done = 0; // 50% overlap int divisor = 4; + if (count > 2048) + divisor = 1; count *= divisor; var img = new Image(count, freqt.Length); log.Debug("done and count "); @@ -183,7 +187,10 @@ public static Image GenerateImage(DFLogBuffer cb, out double[] freqtout, double timedelta = 0; // 50% overlap int divisor = 4; + if (count > 2048) + divisor = 1; count *= divisor; + Console.WriteLine("Image Size " + count + " " + N / 2); var img = new Image(count, N / 2); log.Debug("done and count "); From f1ec82395218e98b2d717c941491475de976bfed Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Sat, 24 Feb 2024 22:47:47 +1100 Subject: [PATCH 35/44] Extensions: Windowed improve performance by removing linq --- ExtLibs/Utilities/Extensions.cs | 29 ++++++++++++++++++++++++++--- 1 file changed, 26 insertions(+), 3 deletions(-) diff --git a/ExtLibs/Utilities/Extensions.cs b/ExtLibs/Utilities/Extensions.cs index 06f5592083..897f3929d3 100644 --- a/ExtLibs/Utilities/Extensions.cs +++ b/ExtLibs/Utilities/Extensions.cs @@ -196,10 +196,33 @@ public static IEnumerable> Windowed(this IEnumerable source int index = 0; int cnt = source.Count(); - while (index < cnt) + if (source is Array) { - yield return source.Skip(index).Take(chunksize).ToArray(); - index += chunksize / divisorinc; + T[] data = (T[])source; + while (index < cnt) + { + chunksize = Math.Min(chunksize, cnt - index); + yield return new Span(data, index, chunksize).ToArray(); + index += chunksize / divisorinc; + } + } + else if (source is List) + { + List data = ((List)source); + while (index < cnt) + { + chunksize = Math.Min(chunksize, cnt - index); + yield return data.AsSpan().Slice(index, chunksize).ToArray(); + index += chunksize / divisorinc; + } + } + else + { + while (index < cnt) + { + yield return source.Skip(index).Take(chunksize).ToArray(); + index += chunksize / divisorinc; + } } } From b6f7e4a7a15dbc4cba3630c51d9d9ad2899f65ef Mon Sep 17 00:00:00 2001 From: StevenHAtRFDesign Date: Sun, 25 Feb 2024 13:58:32 +1000 Subject: [PATCH 36/44] Sik radio update 2024-1-18 (#3277) * RFD900 tools 2.12 - Fixed tooltip text for GPI1_1R/CIN and GPI1_1R/COUT * RFD900 tools 2.13 - Now if a parameter fails to load, that same parameter is not saved back to the modem. * RFD900 Tools 2.14 - Resolved issue in which modem firmware could not be reprogrammed immediately after programming. * RFD900x restrictions for firmware programming for modems locked to country now appears to work well. However, programming RFD900+ seems to have regressed. * Resolved issues with RFD900+ modem in which it couldn't load settings immediately after programming firmware. * Now parses freq/band and antenna options from RFD900x * 2.15 - Added firmware programming certified check for RFD900X/UX. Added SBUS, freq/band and antenna parameters * for RFD900x. * 2.16 - Resolved issue in which it was looking for the country string in the wrong part of the ATI command response. * 2.17 - Resolved issue in which pin wasn't being set to output/input when RC out / SBUS out checked / unchecked. * RFD900 Tools 2.18 - Added text boxes to settings view for local and remote modems to display country code if locked to a country, * as requested by Moreton. * 2.19 - Fixed bug in which programming RFD900x firmware whose file size was a multiple of 128 bytes failed. * 2.20 - Made changes so that it could update firmware and load settings from a modem with multipoint firmware. * 2.21 - Now for modems which use the xmodem protocol for firmware updates (RFD900x and RFD900ux), it waits for * and acknowledgement of the EOT packet before sending the BOOTNEW command. This may or may not * resolve the intermittent issue in which firmware update results in the modem staying in bootloader mode. * Now programs version 3.01 as the reference firmware for RFD900x to check certified (instead of 3.00). * 2.21 - Now for modems which use the xmodem protocol for firmware updates (RFD900x and RFD900ux), it waits for * and acknowledgement of the EOT packet before sending the BOOTNEW command. This may or may not * resolve the intermittent issue in which firmware update results in the modem staying in bootloader mode. * Now programs version 3.01 as the reference firmware for RFD900x to check certified (instead of 3.00). * RFD900 Tools 2.22 - Changed "Set PPM Fail safe" feature so there is one button per local/remote modem. Made it so it is enabled * depending on GPO1_1R/COUT being set. * Now has better handling of the case in which it can't put the modem into RSSI reprting mode. * 2.24 - Improved instructions to user in message boxes. Improved handling of cases where it was unable to communicate * RFD900 Tools 2.25 - Now does auto disconnect/reconnect of serial port after every firmware programming regardless of success or failure. * 2.26 - Now sets status text to "Programming Failed. (Try Again?)" if it fails to determine which mode the modem is in when trying to program firmware. * 2.28 - Now has a manufacturing page/tab for locking down modems to a country. * 2.29 - Resolved bug in which the value ranges available from the remote modem weren't being parsed and used in the combo box e.g. for the min and max frequency ranges. Also, added a work-around for an issue in the RFDSiK RFD900x 3.07 firmware in which it didn't return the complete set of parameters in response to an RTI5? command. * 2.30 - For RFD900x multipoint firmware, now allows correct broadcast id for nodedestination parameter. * RFD900 tools 2.32 - Supports programming of RFD900ux modems. * 2.33 - Corrected available frequency ranges for RFD900+ * 2.34 - Now handles new settings GPO1_1SBUSIN, GPO1_1SBUSOUT, GPO1_3STATLED, and GPO1_0TXEN485 * 2.35 - Fixed bug in which re-loading settings when AES was previously enabled would cause it to disable AES. * 2.36 - Added a retry option message window for when programming firmware fails. * 2.37 - Resolved issue in which a MAX_WINDOW setting value which wasn't a multiple of 20 failed to be set in the settings GUI. * 2.38 - Manufacturing tab now includes lockdown for EU and India. * 2.39 - For checkbox settings for which the modem specifies (in the ATI5? query response) only one option, it now greys-out the checkbox. This was to cater to the X modem 3.15 firmware in which the ECC paramater can't be changed and is always false. * 2.40 - Now for remote modems which do not specify valid settings ranges, if the remote modem has the same firmware version as the * 2.42 - Now gets valid parameter ranges out of remote modem for newer firmware which doesn't support the RTI5? query. Now supports the * 2.43 - Resolved freezing-up issue which happened for older or non-SiK modem firmware which doesn't yet have ATI10/RTI10 command. Tidied up GUI layout. * 2.44 - Resolved mavlink setting problem. * 2.45 - There is now a 50ms delay between '+' characters transmitted to modem when doing the +++ sequence to change mode from transparent to AT command mode, * 2.46 - A command line switch is now available to force programming of firmware into modems regardless of type of modem. Removed 50ms delay between '+' characters transmitted to modem when doing the +++ sequence to change mode from transparent to AT command mode, as this is not required by any firmware. * 2.47 - Added GPIO1_1FUNC settings for RFD900x async firmware 2.69. * 2.48 - RSSI page now writes log to the user's documents folder, instead of the program folder, to prevent exception. * 2.49 - Hardened up code to reduce crashes when switching between terminal, RSSI and settings pages. * 2.50 - Added support for FSFRAMELOSS, GPI1_2AUXIN and GPO1_3AUXOUT parameters. * RFDTools 2.51 - Fixed error message problem when used with multipoint firmware 2.90. * RFDTools 2.52 - Now uses a more reliable means of reading country code from modems than looking at the string returned by ATI command. * 2.53 - For multipoint firmware, made 255 available as an option for destination node ID. * 2.54 - Changed encryption key text box max length from 32 to 64 hex numerals (for 256 bit encryption). * 2.55 - Changed encryption key text box max length from 32 to 64 hex numerals (for 256 bit encryption). * 2.56 - Now recognises country code 255 as not locked to country. * RFDTools 2.57 - Now before programming firmware, checks whether modem says it is DINIO. If it says it is DINIO, only allows DINIO firmware to be programmed into modem. * 2.58 - Now supports RFD X rev 2. Now checks that band is compatible with country before locking to a country. * RFDTools 2.60 - Now supports RFD X rev 2 programming firmware when baud rate other than 57600bps is used. * 2.61 - Now supports RFD UX rev 2. * 2.63 - Settings GUI can now dynamically shows settings read from the modem which are unknown to this software. Supports the RSSI_IN_DBM, AUXSER_SPEED and AIR_FRAMELEN settings. * RFDTools 2.64 - Can now save settings to file and load settings from file. * 2.65 - Now checks whether min freq is greater than max freq before saving settings to modem(s). Resolved issue in which itshowed erroneous "Set command error" message when saving encryption key to modem. * RFD Tools 2.66 - Fixed bug for multipoint firmware in which it showed an error message of 'Encryption key not valid hex number <=32[/64] hex numerals' when saving change to encryption level setting to the modem. * Fix firmware download bug where if the firmware file were read only (or in a read only directory) trying to download it would result in an error because the file could not be opened. Resolved by making the file stream open the file in read only mode. --------- Co-authored-by: Martin Keeling --- MissionPlanner.csproj | 5 + Radio/ComPort.cs | 31 + Radio/Models.cs | 62 +- Radio/Sikradio.Designer.cs | 1072 +++-- Radio/Sikradio.cs | 2040 ++++++--- Radio/Sikradio.resx | 4098 +++++++++++------- Radio/Sikradio.zh-Hant.resx | 1128 ++++- Radio/Sikradio.zh-TW.resx | 1128 ++++- Radio/Uploader.cs | 3 + Radio/XModem.cs | 142 +- SikRadio/ComPort.cs | 18 + SikRadio/Config.cs | 58 +- SikRadio/Config.resx | 6 +- SikRadio/ISikRadioForm.cs | 1 + SikRadio/Program.cs | 34 +- SikRadio/Properties/AssemblyInfo.cs | 2 +- SikRadio/Properties/Resources.Designer.cs | 10 + SikRadio/Properties/Resources.resx | 3 + SikRadio/RFD900.cs | 2405 ++++++++-- SikRadio/RFDLib/Array.cs | 24 + SikRadio/RFDLib/Collections.cs | 36 + SikRadio/RFDLib/GUI/Settings.cs | 262 ++ SikRadio/RFDLib/IO/ATCommand.cs | 209 + SikRadio/RFDLib/IO/SerialPort/SerialPort.cs | 137 + SikRadio/RFDLib/RFDLib.cs | 49 + SikRadio/RFDLib/Text.cs | 18 +- SikRadio/Resources/RFDSiK V3.00 rfd900x.bin | Bin 0 -> 110288 bytes SikRadio/Resources/RFDSiK V3.01 rfd900x.bin | Bin 0 -> 100864 bytes SikRadio/Resources/RFDSiK V3.08 rfd900ux.bin | Bin 0 -> 103708 bytes SikRadio/Rssi.Designer.cs | 35 +- SikRadio/Rssi.cs | 150 +- SikRadio/SikRadio.csproj | 9 + SikRadio/Terminal.cs | 36 +- 33 files changed, 10040 insertions(+), 3171 deletions(-) create mode 100644 Radio/ComPort.cs create mode 100644 SikRadio/ComPort.cs create mode 100644 SikRadio/RFDLib/Collections.cs create mode 100644 SikRadio/RFDLib/GUI/Settings.cs create mode 100644 SikRadio/RFDLib/IO/ATCommand.cs create mode 100644 SikRadio/RFDLib/IO/SerialPort/SerialPort.cs create mode 100644 SikRadio/RFDLib/RFDLib.cs create mode 100644 SikRadio/Resources/RFDSiK V3.00 rfd900x.bin create mode 100644 SikRadio/Resources/RFDSiK V3.01 rfd900x.bin create mode 100644 SikRadio/Resources/RFDSiK V3.08 rfd900ux.bin diff --git a/MissionPlanner.csproj b/MissionPlanner.csproj index a33c1dcda6..a26bfdbb6f 100644 --- a/MissionPlanner.csproj +++ b/MissionPlanner.csproj @@ -1022,7 +1022,11 @@ + + + + Form Splash.cs @@ -1576,6 +1580,7 @@ Form + UserControl diff --git a/Radio/ComPort.cs b/Radio/ComPort.cs new file mode 100644 index 0000000000..043272b30a --- /dev/null +++ b/Radio/ComPort.cs @@ -0,0 +1,31 @@ +using System; +using MissionPlanner.Comms; + +namespace MissionPlanner.Radio +{ + public static class ComPort + { + static ICommsSerial _Port; + + public static ICommsSerial GetComPortForSiKRadio() + { + if (_Port == null) + { + MainV2.comPort.Close(); + MissionPlanner.Radio.Sikradio.Connect(ref _Port); + } + + return _Port; + } + + public static void FinishedWithComPortForSiKRadio() + { + if (_Port != null) + { + _Port.Dispose(); + _Port = null; + } + } + } + +} \ No newline at end of file diff --git a/Radio/Models.cs b/Radio/Models.cs index 9832f02390..eae4eda095 100644 --- a/Radio/Models.cs +++ b/Radio/Models.cs @@ -37,6 +37,7 @@ class ExtraParamControlsSet LabelComboBoxPair TXENCAP; LabelComboBoxPair RXENCAP; LabelComboBoxPair MAX_DATA; + LabelComboBoxPair MAX_RETRIES; IEnumerable Others; bool Remote; @@ -45,6 +46,7 @@ public ExtraParamControlsSet(Label lblNodeID, ComboBox cmbNodeID, Label lblTXENCAP, ComboBox cmbTXENCAP, Label lblRXENCAP, ComboBox cmbRXENCAP, Label lblMAX_DATA, ComboBox cmbMAX_DATA, + Label lblMAX_RETRIES, ComboBox cmbMAX_RETRIES, Control[] Others, bool Remote) { NodeID = new LabelComboBoxPair(lblNodeID, cmbNodeID); @@ -52,12 +54,25 @@ public ExtraParamControlsSet(Label lblNodeID, ComboBox cmbNodeID, TXENCAP = new LabelComboBoxPair(lblTXENCAP, cmbTXENCAP); RXENCAP = new LabelComboBoxPair(lblRXENCAP, cmbRXENCAP); MAX_DATA = new LabelComboBoxPair(lblMAX_DATA, cmbMAX_DATA); + MAX_RETRIES = new LabelComboBoxPair(lblMAX_RETRIES, cmbMAX_RETRIES); this.Others = Others; this.Remote = Remote; } - public void SetModel(Model M) + /// + /// Reconfigure the GUI for the given modem firmware type + /// + /// The modem firmware type. + /// The settings retrieved from the modem. Must not be null. + public void SetModel(Model M, Dictionary Settings) { + NodeID.Reset(); + DestID.Reset(); + TXENCAP.Reset(); + RXENCAP.Reset(); + MAX_DATA.Reset(); + MAX_RETRIES.Reset(); + string Prefix = Remote ? "R" : ""; switch (M) @@ -73,7 +88,7 @@ public void SetModel(Model M) RXENCAP.ComboBox.Name = Prefix + "NODECOUNT"; RXENCAP.Label.Text = "Node Count"; NodeID.ComboBox.DataSource = Sikradio.Range(0, 1, 29); - var Temp = (List)Sikradio.Range(0, 1, 29); + var Temp = new List(Sikradio.Range(0, 1, 29)); Temp.Add(65535); DestID.ComboBox.DataSource = Temp; TXENCAP.ComboBox.DataSource = Sikradio.Range(0, 1, 1); @@ -103,14 +118,27 @@ public void SetModel(Model M) case Model.MULTIPOINT_X: { DestID.ComboBox.Name = Prefix + "NODEDESTINATION"; - TXENCAP.ComboBox.Name = Prefix + "NODECOUNT"; - TXENCAP.Label.Text = "Node Count"; + if (Settings.ContainsKey("NETCOUNT")) + { + TXENCAP.ComboBox.Name = Prefix + "NETCOUNT"; + TXENCAP.Label.Text = "Net Count"; + } + else + { + TXENCAP.ComboBox.Name = Prefix + "NODECOUNT"; + TXENCAP.Label.Text = "Node Count"; + } RXENCAP.ComboBox.Name = Prefix + "SERBREAKMS10"; RXENCAP.Label.Text = "Ser. brk. x10ms"; - MAX_DATA.ComboBox.Name = "GPO1_3STATLED"; - MAX_DATA.Label.Text = "GPO1_\n3STATLED"; + if (Settings.ContainsKey("MASTERBACKUP")) + { + MAX_DATA.ComboBox.Name = Prefix + "MASTERBACKUP"; + MAX_DATA.Label.Text = "Master Bckp"; + } + MAX_RETRIES.ComboBox.Name = Prefix + "RXFRAME"; + MAX_RETRIES.Label.Text = "Rx Frame"; NodeID.ComboBox.DataSource = Sikradio.Range(0, 1, 29); - var Temp = (List)Sikradio.Range(0, 1, 29); + var Temp = new List(Sikradio.Range(0, 1, 29)); Temp.Add(65535); DestID.ComboBox.DataSource = Temp; TXENCAP.ComboBox.DataSource = Sikradio.Range(0, 1, 1); @@ -121,7 +149,14 @@ public void SetModel(Model M) DestID.Visible = true; TXENCAP.Visible = true; RXENCAP.Visible = true; - MAX_DATA.Visible = true; + if (Settings.ContainsKey("MASTERBACKUP")) + { + MAX_DATA.Visible = true; + } + if (Settings.ContainsKey("RXFRAME")) + { + MAX_RETRIES.Visible = true; + } } break; } @@ -134,6 +169,7 @@ void SetAllVisible(bool V) TXENCAP.Visible = V; RXENCAP.Visible = V; MAX_DATA.Visible = V; + MAX_RETRIES.Visible = V; foreach (var x in Others) { x.Visible = V; @@ -145,11 +181,15 @@ class LabelComboBoxPair { public readonly Label Label; public readonly ComboBox ComboBox; + public readonly string OrigName; + public readonly string OrigLabel; public LabelComboBoxPair(Label L, ComboBox C) { this.Label = L; this.ComboBox = C; + OrigName = C.Name; + OrigLabel = L.Text; } public bool Visible @@ -164,5 +204,11 @@ public bool Visible ComboBox.Visible = value; } } + + public void Reset() + { + Label.Text = OrigLabel; + ComboBox.Name = OrigName; + } } } \ No newline at end of file diff --git a/Radio/Sikradio.Designer.cs b/Radio/Sikradio.Designer.cs index cf06b1f7f4..c0a7ae9118 100644 --- a/Radio/Sikradio.Designer.cs +++ b/Radio/Sikradio.Designer.cs @@ -66,6 +66,16 @@ private void InitializeComponent() this.TXPOWER = new System.Windows.Forms.ComboBox(); this.ECC = new System.Windows.Forms.CheckBox(); this.OPPRESEND = new System.Windows.Forms.CheckBox(); + this.ENCRYPTION_LEVEL = new System.Windows.Forms.ComboBox(); + this.RENCRYPTION_LEVEL = new System.Windows.Forms.ComboBox(); + this.FSFRAMELOSS = new System.Windows.Forms.ComboBox(); + this.RFSFRAMELOSS = new System.Windows.Forms.ComboBox(); + this.GPO1_3SBUSIN = new System.Windows.Forms.CheckBox(); + this.RGPO1_3SBUSIN = new System.Windows.Forms.CheckBox(); + this.GPO1_3STATLED = new System.Windows.Forms.CheckBox(); + this.GPO1_0TXEN485 = new System.Windows.Forms.CheckBox(); + this.RGPO1_0TXEN485 = new System.Windows.Forms.CheckBox(); + this.RGPO1_3STATLED = new System.Windows.Forms.CheckBox(); this.RTI = new System.Windows.Forms.TextBox(); this.ATI = new System.Windows.Forms.TextBox(); this.label11 = new System.Windows.Forms.Label(); @@ -73,6 +83,22 @@ private void InitializeComponent() this.lbl_status = new System.Windows.Forms.Label(); this.ATI3 = new System.Windows.Forms.TextBox(); this.groupBoxLocal = new System.Windows.Forms.GroupBox(); + this.label54 = new System.Windows.Forms.Label(); + this.GPO1_3AUXOUT = new System.Windows.Forms.CheckBox(); + this.lblGPO1_3AUXOUT = new System.Windows.Forms.Label(); + this.GPI1_2AUXIN = new System.Windows.Forms.CheckBox(); + this.lblGPI1_2AUXIN = new System.Windows.Forms.Label(); + this.lblGPIO1_1FUNC = new System.Windows.Forms.Label(); + this.GPIO1_1FUNC = new System.Windows.Forms.ComboBox(); + this.lblGPO1_0TXEN485 = new System.Windows.Forms.Label(); + this.lblGPO1_3STATLED = new System.Windows.Forms.Label(); + this.GPO1_3SBUSOUT = new System.Windows.Forms.ComboBox(); + this.label49 = new System.Windows.Forms.Label(); + this.txtCountry = new System.Windows.Forms.TextBox(); + this.label45 = new System.Windows.Forms.Label(); + this.RATE_FREQBAND = new System.Windows.Forms.ComboBox(); + this.lblSBUSOUT = new System.Windows.Forms.Label(); + this.lblSBUSIN = new System.Windows.Forms.Label(); this.btnRandom = new System.Windows.Forms.Button(); this.lblRX_ENCAP_METHOD = new System.Windows.Forms.Label(); this.RX_ENCAP_METHOD = new System.Windows.Forms.ComboBox(); @@ -82,17 +108,17 @@ private void InitializeComponent() this.lblNODEID = new System.Windows.Forms.Label(); this.DESTID = new System.Windows.Forms.ComboBox(); this.NODEID = new System.Windows.Forms.ComboBox(); - this.label40 = new System.Windows.Forms.Label(); - this.label39 = new System.Windows.Forms.Label(); + this.lblGPO1_1R_COUT = new System.Windows.Forms.Label(); + this.lblGPI1_1R_CIN = new System.Windows.Forms.Label(); this.label2 = new System.Windows.Forms.Label(); this.label1 = new System.Windows.Forms.Label(); this.FORMAT = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); - this.label4 = new System.Windows.Forms.Label(); - this.label5 = new System.Windows.Forms.Label(); - this.label6 = new System.Windows.Forms.Label(); - this.label8 = new System.Windows.Forms.Label(); - this.label7 = new System.Windows.Forms.Label(); + this.lblNETID = new System.Windows.Forms.Label(); + this.lblTXPOWER = new System.Windows.Forms.Label(); + this.lblECC = new System.Windows.Forms.Label(); + this.lblOPPRESEND = new System.Windows.Forms.Label(); + this.lblMAVLINK = new System.Windows.Forms.Label(); this.lblANT_MODE = new System.Windows.Forms.Label(); this.ANT_MODE = new System.Windows.Forms.ComboBox(); this.lblSER_BRK_DETMS = new System.Windows.Forms.Label(); @@ -103,21 +129,36 @@ private void InitializeComponent() this.MAX_RETRIES = new System.Windows.Forms.ComboBox(); this.MAX_DATA = new System.Windows.Forms.ComboBox(); this.lblMAX_DATA = new System.Windows.Forms.Label(); - this.ENCRYPTION_LEVEL = new System.Windows.Forms.CheckBox(); - this.label36 = new System.Windows.Forms.Label(); + this.lblENCRYPTION_LEVEL = new System.Windows.Forms.Label(); this.label35 = new System.Windows.Forms.Label(); - this.txt_aeskey = new System.Windows.Forms.TextBox(); - this.label19 = new System.Windows.Forms.Label(); + this.AESKEY = new System.Windows.Forms.TextBox(); + this.lblRTSCTS = new System.Windows.Forms.Label(); this.linkLabel_mavlink = new System.Windows.Forms.LinkLabel(); this.linkLabel_lowlatency = new System.Windows.Forms.LinkLabel(); - this.label18 = new System.Windows.Forms.Label(); - this.label13 = new System.Windows.Forms.Label(); - this.label17 = new System.Windows.Forms.Label(); - this.label16 = new System.Windows.Forms.Label(); - this.label15 = new System.Windows.Forms.Label(); - this.label14 = new System.Windows.Forms.Label(); + this.lblMAX_WINDOW = new System.Windows.Forms.Label(); + this.lblMIN_FREQ = new System.Windows.Forms.Label(); + this.lblLBT_RSSI = new System.Windows.Forms.Label(); + this.lblDUTY_CYCLE = new System.Windows.Forms.Label(); + this.lblNUM_CHANNELS = new System.Windows.Forms.Label(); + this.lblMAX_FREQ = new System.Windows.Forms.Label(); this.ATI2 = new System.Windows.Forms.TextBox(); this.groupBoxRemote = new System.Windows.Forms.GroupBox(); + this.lblRFSFRAMELOSS = new System.Windows.Forms.Label(); + this.RGPO1_3AUXOUT = new System.Windows.Forms.CheckBox(); + this.lblRGPO1_3AUXOUT = new System.Windows.Forms.Label(); + this.RGPI1_2AUXIN = new System.Windows.Forms.CheckBox(); + this.lblRGPI1_2AUXIN = new System.Windows.Forms.Label(); + this.lblRGPIO1_1FUNC = new System.Windows.Forms.Label(); + this.RGPIO1_1FUNC = new System.Windows.Forms.ComboBox(); + this.lblRGPO1_0TXEN485 = new System.Windows.Forms.Label(); + this.lblRGPO1_3STATLED = new System.Windows.Forms.Label(); + this.RGPO1_3SBUSOUT = new System.Windows.Forms.ComboBox(); + this.label50 = new System.Windows.Forms.Label(); + this.txtRCountry = new System.Windows.Forms.TextBox(); + this.lblRSBUSOUT = new System.Windows.Forms.Label(); + this.lblRSBUSIN = new System.Windows.Forms.Label(); + this.label46 = new System.Windows.Forms.Label(); + this.RRATE_FREQBAND = new System.Windows.Forms.ComboBox(); this.lblRRX_ENCAP_METHOD = new System.Windows.Forms.Label(); this.RRX_ENCAP_METHOD = new System.Windows.Forms.ComboBox(); this.lblRTX_ENCAP_METHOD = new System.Windows.Forms.Label(); @@ -126,14 +167,14 @@ private void InitializeComponent() this.lblRNODEID = new System.Windows.Forms.Label(); this.RDESTID = new System.Windows.Forms.ComboBox(); this.RNODEID = new System.Windows.Forms.ComboBox(); - this.label41 = new System.Windows.Forms.Label(); + this.lblRGPO1_1R_COUT = new System.Windows.Forms.Label(); this.RFORMAT = new System.Windows.Forms.TextBox(); - this.label42 = new System.Windows.Forms.Label(); - this.label25 = new System.Windows.Forms.Label(); - this.label26 = new System.Windows.Forms.Label(); - this.label27 = new System.Windows.Forms.Label(); - this.label28 = new System.Windows.Forms.Label(); - this.label29 = new System.Windows.Forms.Label(); + this.lblRGPI1_1R_CIN = new System.Windows.Forms.Label(); + this.lblROPPRESEND = new System.Windows.Forms.Label(); + this.lblRMAVLINK = new System.Windows.Forms.Label(); + this.lblRECC = new System.Windows.Forms.Label(); + this.lblRTXPOWER = new System.Windows.Forms.Label(); + this.lblRNETID = new System.Windows.Forms.Label(); this.label32 = new System.Windows.Forms.Label(); this.label30 = new System.Windows.Forms.Label(); this.label31 = new System.Windows.Forms.Label(); @@ -148,26 +189,32 @@ private void InitializeComponent() this.RMAX_DATA = new System.Windows.Forms.ComboBox(); this.lblRMAX_DATA = new System.Windows.Forms.Label(); this.label38 = new System.Windows.Forms.Label(); - this.RENCRYPTION_LEVEL = new System.Windows.Forms.CheckBox(); - this.txt_Raeskey = new System.Windows.Forms.TextBox(); - this.label37 = new System.Windows.Forms.Label(); - this.label33 = new System.Windows.Forms.Label(); - this.label34 = new System.Windows.Forms.Label(); - this.label24 = new System.Windows.Forms.Label(); - this.label23 = new System.Windows.Forms.Label(); - this.label22 = new System.Windows.Forms.Label(); - this.label21 = new System.Windows.Forms.Label(); - this.label20 = new System.Windows.Forms.Label(); + this.RAESKEY = new System.Windows.Forms.TextBox(); + this.lblRENCRYPTION_LEVEL = new System.Windows.Forms.Label(); + this.lblRRTSCTS = new System.Windows.Forms.Label(); + this.lblRMAX_WINDOW = new System.Windows.Forms.Label(); + this.lblRMIN_FREQ = new System.Windows.Forms.Label(); + this.lblRMAX_FREQ = new System.Windows.Forms.Label(); + this.lblRNUM_CHANNELS = new System.Windows.Forms.Label(); + this.lblRDUTY_CYCLE = new System.Windows.Forms.Label(); + this.lblRLBT_RSSI = new System.Windows.Forms.Label(); this.RTI2 = new System.Windows.Forms.TextBox(); this.label9 = new System.Windows.Forms.Label(); this.label10 = new System.Windows.Forms.Label(); - this.BUT_SetPPMFailSafe = new MissionPlanner.Controls.MyButton(); + this.dlgSave = new System.Windows.Forms.SaveFileDialog(); + this.dlgOpen = new System.Windows.Forms.OpenFileDialog(); this.BUT_loadcustom = new MissionPlanner.Controls.MyButton(); this.BUT_resettodefault = new MissionPlanner.Controls.MyButton(); + this.btnRemoteLoadFromFile = new MissionPlanner.Controls.MyButton(); + this.btnRemoteSaveToFile = new MissionPlanner.Controls.MyButton(); + this.BUT_SetPPMFailSafeRemote = new MissionPlanner.Controls.MyButton(); + this.BUT_SetPPMFailSafe = new MissionPlanner.Controls.MyButton(); this.BUT_savesettings = new MissionPlanner.Controls.MyButton(); this.BUT_getcurrent = new MissionPlanner.Controls.MyButton(); this.BUT_upload = new MissionPlanner.Controls.MyButton(); this.BUT_Syncoptions = new MissionPlanner.Controls.MyButton(); + this.btnSaveToFile = new MissionPlanner.Controls.MyButton(); + this.btnLoadFromFile = new MissionPlanner.Controls.MyButton(); this.groupBoxLocal.SuspendLayout(); this.groupBoxRemote.SuspendLayout(); this.SuspendLayout(); @@ -237,7 +284,6 @@ private void InitializeComponent() resources.GetString("RMAX_WINDOW.Items29"), resources.GetString("RMAX_WINDOW.Items30")}); this.RMAX_WINDOW.Name = "RMAX_WINDOW"; - this.toolTip1.SetToolTip(this.RMAX_WINDOW, resources.GetString("RMAX_WINDOW.ToolTip")); // // RMAX_FREQ // @@ -344,7 +390,6 @@ private void InitializeComponent() resources.ApplyResources(this.RMAVLINK, "RMAVLINK"); this.RMAVLINK.FormattingEnabled = true; this.RMAVLINK.Name = "RMAVLINK"; - this.toolTip1.SetToolTip(this.RMAVLINK, resources.GetString("RMAVLINK.ToolTip")); // // RGPO1_1R_COUT // @@ -510,7 +555,6 @@ private void InitializeComponent() resources.GetString("MAX_WINDOW.Items29"), resources.GetString("MAX_WINDOW.Items30")}); this.MAX_WINDOW.Name = "MAX_WINDOW"; - this.toolTip1.SetToolTip(this.MAX_WINDOW, resources.GetString("MAX_WINDOW.ToolTip")); // // MAX_FREQ // @@ -742,6 +786,70 @@ private void InitializeComponent() this.OPPRESEND.Name = "OPPRESEND"; this.toolTip1.SetToolTip(this.OPPRESEND, resources.GetString("OPPRESEND.ToolTip")); // + // ENCRYPTION_LEVEL + // + this.ENCRYPTION_LEVEL.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.ENCRYPTION_LEVEL, "ENCRYPTION_LEVEL"); + this.ENCRYPTION_LEVEL.FormattingEnabled = true; + this.ENCRYPTION_LEVEL.Name = "ENCRYPTION_LEVEL"; + this.toolTip1.SetToolTip(this.ENCRYPTION_LEVEL, resources.GetString("ENCRYPTION_LEVEL.ToolTip")); + this.ENCRYPTION_LEVEL.SelectedValueChanged += new System.EventHandler(this.ENCRYPTION_LEVEL_CheckedChanged); + // + // RENCRYPTION_LEVEL + // + this.RENCRYPTION_LEVEL.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.RENCRYPTION_LEVEL, "RENCRYPTION_LEVEL"); + this.RENCRYPTION_LEVEL.FormattingEnabled = true; + this.RENCRYPTION_LEVEL.Name = "RENCRYPTION_LEVEL"; + this.toolTip1.SetToolTip(this.RENCRYPTION_LEVEL, resources.GetString("RENCRYPTION_LEVEL.ToolTip")); + this.RENCRYPTION_LEVEL.SelectedValueChanged += new System.EventHandler(this.RENCRYPTION_LEVEL_CheckedChanged); + // + // FSFRAMELOSS + // + this.FSFRAMELOSS.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.FSFRAMELOSS, "FSFRAMELOSS"); + this.FSFRAMELOSS.FormattingEnabled = true; + this.FSFRAMELOSS.Name = "FSFRAMELOSS"; + this.toolTip1.SetToolTip(this.FSFRAMELOSS, resources.GetString("FSFRAMELOSS.ToolTip")); + // + // RFSFRAMELOSS + // + this.RFSFRAMELOSS.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.RFSFRAMELOSS, "RFSFRAMELOSS"); + this.RFSFRAMELOSS.FormattingEnabled = true; + this.RFSFRAMELOSS.Name = "RFSFRAMELOSS"; + this.toolTip1.SetToolTip(this.RFSFRAMELOSS, resources.GetString("RFSFRAMELOSS.ToolTip")); + // + // GPO1_3SBUSIN + // + resources.ApplyResources(this.GPO1_3SBUSIN, "GPO1_3SBUSIN"); + this.GPO1_3SBUSIN.Name = "GPO1_3SBUSIN"; + // + // RGPO1_3SBUSIN + // + resources.ApplyResources(this.RGPO1_3SBUSIN, "RGPO1_3SBUSIN"); + this.RGPO1_3SBUSIN.Name = "RGPO1_3SBUSIN"; + // + // GPO1_3STATLED + // + resources.ApplyResources(this.GPO1_3STATLED, "GPO1_3STATLED"); + this.GPO1_3STATLED.Name = "GPO1_3STATLED"; + // + // GPO1_0TXEN485 + // + resources.ApplyResources(this.GPO1_0TXEN485, "GPO1_0TXEN485"); + this.GPO1_0TXEN485.Name = "GPO1_0TXEN485"; + // + // RGPO1_0TXEN485 + // + resources.ApplyResources(this.RGPO1_0TXEN485, "RGPO1_0TXEN485"); + this.RGPO1_0TXEN485.Name = "RGPO1_0TXEN485"; + // + // RGPO1_3STATLED + // + resources.ApplyResources(this.RGPO1_3STATLED, "RGPO1_3STATLED"); + this.RGPO1_3STATLED.Name = "RGPO1_3STATLED"; + // // RTI // resources.ApplyResources(this.RTI, "RTI"); @@ -766,8 +874,10 @@ private void InitializeComponent() // // lbl_status // + this.lbl_status.BackColor = System.Drawing.Color.Transparent; resources.ApplyResources(this.lbl_status, "lbl_status"); this.lbl_status.Name = "lbl_status"; + this.lbl_status.UseMnemonic = false; // // ATI3 // @@ -777,6 +887,30 @@ private void InitializeComponent() // // groupBoxLocal // + this.groupBoxLocal.Controls.Add(this.btnLoadFromFile); + this.groupBoxLocal.Controls.Add(this.btnSaveToFile); + this.groupBoxLocal.Controls.Add(this.label54); + this.groupBoxLocal.Controls.Add(this.FSFRAMELOSS); + this.groupBoxLocal.Controls.Add(this.GPO1_3AUXOUT); + this.groupBoxLocal.Controls.Add(this.lblGPO1_3AUXOUT); + this.groupBoxLocal.Controls.Add(this.GPI1_2AUXIN); + this.groupBoxLocal.Controls.Add(this.lblGPI1_2AUXIN); + this.groupBoxLocal.Controls.Add(this.lblGPIO1_1FUNC); + this.groupBoxLocal.Controls.Add(this.GPIO1_1FUNC); + this.groupBoxLocal.Controls.Add(this.ENCRYPTION_LEVEL); + this.groupBoxLocal.Controls.Add(this.GPO1_0TXEN485); + this.groupBoxLocal.Controls.Add(this.lblGPO1_0TXEN485); + this.groupBoxLocal.Controls.Add(this.GPO1_3STATLED); + this.groupBoxLocal.Controls.Add(this.lblGPO1_3STATLED); + this.groupBoxLocal.Controls.Add(this.GPO1_3SBUSOUT); + this.groupBoxLocal.Controls.Add(this.label49); + this.groupBoxLocal.Controls.Add(this.BUT_SetPPMFailSafe); + this.groupBoxLocal.Controls.Add(this.txtCountry); + this.groupBoxLocal.Controls.Add(this.label45); + this.groupBoxLocal.Controls.Add(this.RATE_FREQBAND); + this.groupBoxLocal.Controls.Add(this.lblSBUSOUT); + this.groupBoxLocal.Controls.Add(this.lblSBUSIN); + this.groupBoxLocal.Controls.Add(this.GPO1_3SBUSIN); this.groupBoxLocal.Controls.Add(this.btnRandom); this.groupBoxLocal.Controls.Add(this.lblRX_ENCAP_METHOD); this.groupBoxLocal.Controls.Add(this.RX_ENCAP_METHOD); @@ -786,9 +920,9 @@ private void InitializeComponent() this.groupBoxLocal.Controls.Add(this.lblNODEID); this.groupBoxLocal.Controls.Add(this.DESTID); this.groupBoxLocal.Controls.Add(this.NODEID); - this.groupBoxLocal.Controls.Add(this.label40); + this.groupBoxLocal.Controls.Add(this.lblGPO1_1R_COUT); this.groupBoxLocal.Controls.Add(this.GPO1_1R_COUT); - this.groupBoxLocal.Controls.Add(this.label39); + this.groupBoxLocal.Controls.Add(this.lblGPI1_1R_CIN); this.groupBoxLocal.Controls.Add(this.GPI1_1R_CIN); this.groupBoxLocal.Controls.Add(this.MAVLINK); this.groupBoxLocal.Controls.Add(this.label2); @@ -798,14 +932,14 @@ private void InitializeComponent() this.groupBoxLocal.Controls.Add(this.AIR_SPEED); this.groupBoxLocal.Controls.Add(this.label3); this.groupBoxLocal.Controls.Add(this.NETID); - this.groupBoxLocal.Controls.Add(this.label4); + this.groupBoxLocal.Controls.Add(this.lblNETID); this.groupBoxLocal.Controls.Add(this.TXPOWER); - this.groupBoxLocal.Controls.Add(this.label5); + this.groupBoxLocal.Controls.Add(this.lblTXPOWER); this.groupBoxLocal.Controls.Add(this.ECC); - this.groupBoxLocal.Controls.Add(this.label6); - this.groupBoxLocal.Controls.Add(this.label8); + this.groupBoxLocal.Controls.Add(this.lblECC); + this.groupBoxLocal.Controls.Add(this.lblOPPRESEND); this.groupBoxLocal.Controls.Add(this.OPPRESEND); - this.groupBoxLocal.Controls.Add(this.label7); + this.groupBoxLocal.Controls.Add(this.lblMAVLINK); this.groupBoxLocal.Controls.Add(this.lblANT_MODE); this.groupBoxLocal.Controls.Add(this.ANT_MODE); this.groupBoxLocal.Controls.Add(this.lblSER_BRK_DETMS); @@ -816,25 +950,24 @@ private void InitializeComponent() this.groupBoxLocal.Controls.Add(this.MAX_RETRIES); this.groupBoxLocal.Controls.Add(this.MAX_DATA); this.groupBoxLocal.Controls.Add(this.lblMAX_DATA); - this.groupBoxLocal.Controls.Add(this.ENCRYPTION_LEVEL); - this.groupBoxLocal.Controls.Add(this.label36); + this.groupBoxLocal.Controls.Add(this.lblENCRYPTION_LEVEL); this.groupBoxLocal.Controls.Add(this.label35); - this.groupBoxLocal.Controls.Add(this.txt_aeskey); + this.groupBoxLocal.Controls.Add(this.AESKEY); this.groupBoxLocal.Controls.Add(this.RTSCTS); - this.groupBoxLocal.Controls.Add(this.label19); + this.groupBoxLocal.Controls.Add(this.lblRTSCTS); this.groupBoxLocal.Controls.Add(this.linkLabel_mavlink); this.groupBoxLocal.Controls.Add(this.linkLabel_lowlatency); - this.groupBoxLocal.Controls.Add(this.label18); + this.groupBoxLocal.Controls.Add(this.lblMAX_WINDOW); this.groupBoxLocal.Controls.Add(this.MAX_WINDOW); - this.groupBoxLocal.Controls.Add(this.label13); + this.groupBoxLocal.Controls.Add(this.lblMIN_FREQ); this.groupBoxLocal.Controls.Add(this.MAX_FREQ); this.groupBoxLocal.Controls.Add(this.NUM_CHANNELS); - this.groupBoxLocal.Controls.Add(this.label17); + this.groupBoxLocal.Controls.Add(this.lblLBT_RSSI); this.groupBoxLocal.Controls.Add(this.LBT_RSSI); - this.groupBoxLocal.Controls.Add(this.label16); + this.groupBoxLocal.Controls.Add(this.lblDUTY_CYCLE); this.groupBoxLocal.Controls.Add(this.MIN_FREQ); - this.groupBoxLocal.Controls.Add(this.label15); - this.groupBoxLocal.Controls.Add(this.label14); + this.groupBoxLocal.Controls.Add(this.lblNUM_CHANNELS); + this.groupBoxLocal.Controls.Add(this.lblMAX_FREQ); this.groupBoxLocal.Controls.Add(this.DUTY_CYCLE); this.groupBoxLocal.Controls.Add(this.ATI2); this.groupBoxLocal.Controls.Add(this.ATI3); @@ -846,6 +979,93 @@ private void InitializeComponent() this.groupBoxLocal.Name = "groupBoxLocal"; this.groupBoxLocal.TabStop = false; // + // label54 + // + resources.ApplyResources(this.label54, "label54"); + this.label54.Name = "label54"; + // + // GPO1_3AUXOUT + // + resources.ApplyResources(this.GPO1_3AUXOUT, "GPO1_3AUXOUT"); + this.GPO1_3AUXOUT.Name = "GPO1_3AUXOUT"; + // + // lblGPO1_3AUXOUT + // + resources.ApplyResources(this.lblGPO1_3AUXOUT, "lblGPO1_3AUXOUT"); + this.lblGPO1_3AUXOUT.Name = "lblGPO1_3AUXOUT"; + // + // GPI1_2AUXIN + // + resources.ApplyResources(this.GPI1_2AUXIN, "GPI1_2AUXIN"); + this.GPI1_2AUXIN.Name = "GPI1_2AUXIN"; + // + // lblGPI1_2AUXIN + // + resources.ApplyResources(this.lblGPI1_2AUXIN, "lblGPI1_2AUXIN"); + this.lblGPI1_2AUXIN.Name = "lblGPI1_2AUXIN"; + // + // lblGPIO1_1FUNC + // + resources.ApplyResources(this.lblGPIO1_1FUNC, "lblGPIO1_1FUNC"); + this.lblGPIO1_1FUNC.Name = "lblGPIO1_1FUNC"; + // + // GPIO1_1FUNC + // + this.GPIO1_1FUNC.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.GPIO1_1FUNC, "GPIO1_1FUNC"); + this.GPIO1_1FUNC.FormattingEnabled = true; + this.GPIO1_1FUNC.Name = "GPIO1_1FUNC"; + // + // lblGPO1_0TXEN485 + // + resources.ApplyResources(this.lblGPO1_0TXEN485, "lblGPO1_0TXEN485"); + this.lblGPO1_0TXEN485.Name = "lblGPO1_0TXEN485"; + // + // lblGPO1_3STATLED + // + resources.ApplyResources(this.lblGPO1_3STATLED, "lblGPO1_3STATLED"); + this.lblGPO1_3STATLED.Name = "lblGPO1_3STATLED"; + // + // GPO1_3SBUSOUT + // + this.GPO1_3SBUSOUT.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.GPO1_3SBUSOUT, "GPO1_3SBUSOUT"); + this.GPO1_3SBUSOUT.FormattingEnabled = true; + this.GPO1_3SBUSOUT.Name = "GPO1_3SBUSOUT"; + // + // label49 + // + resources.ApplyResources(this.label49, "label49"); + this.label49.Name = "label49"; + // + // txtCountry + // + resources.ApplyResources(this.txtCountry, "txtCountry"); + this.txtCountry.Name = "txtCountry"; + this.txtCountry.ReadOnly = true; + // + // label45 + // + resources.ApplyResources(this.label45, "label45"); + this.label45.Name = "label45"; + // + // RATE_FREQBAND + // + this.RATE_FREQBAND.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.RATE_FREQBAND, "RATE_FREQBAND"); + this.RATE_FREQBAND.FormattingEnabled = true; + this.RATE_FREQBAND.Name = "RATE_FREQBAND"; + // + // lblSBUSOUT + // + resources.ApplyResources(this.lblSBUSOUT, "lblSBUSOUT"); + this.lblSBUSOUT.Name = "lblSBUSOUT"; + // + // lblSBUSIN + // + resources.ApplyResources(this.lblSBUSIN, "lblSBUSIN"); + this.lblSBUSIN.Name = "lblSBUSIN"; + // // btnRandom // resources.ApplyResources(this.btnRandom, "btnRandom"); @@ -901,15 +1121,15 @@ private void InitializeComponent() this.NODEID.FormattingEnabled = true; this.NODEID.Name = "NODEID"; // - // label40 + // lblGPO1_1R_COUT // - resources.ApplyResources(this.label40, "label40"); - this.label40.Name = "label40"; + resources.ApplyResources(this.lblGPO1_1R_COUT, "lblGPO1_1R_COUT"); + this.lblGPO1_1R_COUT.Name = "lblGPO1_1R_COUT"; // - // label39 + // lblGPI1_1R_CIN // - resources.ApplyResources(this.label39, "label39"); - this.label39.Name = "label39"; + resources.ApplyResources(this.lblGPI1_1R_CIN, "lblGPI1_1R_CIN"); + this.lblGPI1_1R_CIN.Name = "lblGPI1_1R_CIN"; // // label2 // @@ -932,30 +1152,30 @@ private void InitializeComponent() resources.ApplyResources(this.label3, "label3"); this.label3.Name = "label3"; // - // label4 + // lblNETID // - resources.ApplyResources(this.label4, "label4"); - this.label4.Name = "label4"; + resources.ApplyResources(this.lblNETID, "lblNETID"); + this.lblNETID.Name = "lblNETID"; // - // label5 + // lblTXPOWER // - resources.ApplyResources(this.label5, "label5"); - this.label5.Name = "label5"; + resources.ApplyResources(this.lblTXPOWER, "lblTXPOWER"); + this.lblTXPOWER.Name = "lblTXPOWER"; // - // label6 + // lblECC // - resources.ApplyResources(this.label6, "label6"); - this.label6.Name = "label6"; + resources.ApplyResources(this.lblECC, "lblECC"); + this.lblECC.Name = "lblECC"; // - // label8 + // lblOPPRESEND // - resources.ApplyResources(this.label8, "label8"); - this.label8.Name = "label8"; + resources.ApplyResources(this.lblOPPRESEND, "lblOPPRESEND"); + this.lblOPPRESEND.Name = "lblOPPRESEND"; // - // label7 + // lblMAVLINK // - resources.ApplyResources(this.label7, "label7"); - this.label7.Name = "label7"; + resources.ApplyResources(this.lblMAVLINK, "lblMAVLINK"); + this.lblMAVLINK.Name = "lblMAVLINK"; // // lblANT_MODE // @@ -1017,75 +1237,67 @@ private void InitializeComponent() resources.ApplyResources(this.lblMAX_DATA, "lblMAX_DATA"); this.lblMAX_DATA.Name = "lblMAX_DATA"; // - // ENCRYPTION_LEVEL - // - resources.ApplyResources(this.ENCRYPTION_LEVEL, "ENCRYPTION_LEVEL"); - this.ENCRYPTION_LEVEL.Name = "ENCRYPTION_LEVEL"; - this.ENCRYPTION_LEVEL.CheckedChanged += new System.EventHandler(this.ENCRYPTION_LEVEL_CheckedChanged); + // lblENCRYPTION_LEVEL // - // label36 - // - resources.ApplyResources(this.label36, "label36"); - this.label36.Name = "label36"; + resources.ApplyResources(this.lblENCRYPTION_LEVEL, "lblENCRYPTION_LEVEL"); + this.lblENCRYPTION_LEVEL.Name = "lblENCRYPTION_LEVEL"; // // label35 // resources.ApplyResources(this.label35, "label35"); this.label35.Name = "label35"; // - // txt_aeskey + // txt_aeskeyraeskey // - resources.ApplyResources(this.txt_aeskey, "txt_aeskey"); - this.txt_aeskey.Name = "txt_aeskey"; + resources.ApplyResources(this.AESKEY, "txt_aeskey"); + this.AESKEY.Name = "AESKEY"; // - // label19 + // lblRTSCTS // - resources.ApplyResources(this.label19, "label19"); - this.label19.Name = "label19"; + resources.ApplyResources(this.lblRTSCTS, "lblRTSCTS"); + this.lblRTSCTS.Name = "lblRTSCTS"; // // linkLabel_mavlink // resources.ApplyResources(this.linkLabel_mavlink, "linkLabel_mavlink"); this.linkLabel_mavlink.Name = "linkLabel_mavlink"; this.linkLabel_mavlink.TabStop = true; - this.linkLabel_mavlink.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_mavlink_LinkClicked); // // linkLabel_lowlatency // resources.ApplyResources(this.linkLabel_lowlatency, "linkLabel_lowlatency"); this.linkLabel_lowlatency.Name = "linkLabel_lowlatency"; this.linkLabel_lowlatency.TabStop = true; - this.linkLabel_lowlatency.LinkClicked += new System.Windows.Forms.LinkLabelLinkClickedEventHandler(this.linkLabel_lowlatency_LinkClicked); // - // label18 + // lblMAX_WINDOW // - resources.ApplyResources(this.label18, "label18"); - this.label18.Name = "label18"; + resources.ApplyResources(this.lblMAX_WINDOW, "lblMAX_WINDOW"); + this.lblMAX_WINDOW.Name = "lblMAX_WINDOW"; // - // label13 + // lblMIN_FREQ // - resources.ApplyResources(this.label13, "label13"); - this.label13.Name = "label13"; + resources.ApplyResources(this.lblMIN_FREQ, "lblMIN_FREQ"); + this.lblMIN_FREQ.Name = "lblMIN_FREQ"; // - // label17 + // lblLBT_RSSI // - resources.ApplyResources(this.label17, "label17"); - this.label17.Name = "label17"; + resources.ApplyResources(this.lblLBT_RSSI, "lblLBT_RSSI"); + this.lblLBT_RSSI.Name = "lblLBT_RSSI"; // - // label16 + // lblDUTY_CYCLE // - resources.ApplyResources(this.label16, "label16"); - this.label16.Name = "label16"; + resources.ApplyResources(this.lblDUTY_CYCLE, "lblDUTY_CYCLE"); + this.lblDUTY_CYCLE.Name = "lblDUTY_CYCLE"; // - // label15 + // lblNUM_CHANNELS // - resources.ApplyResources(this.label15, "label15"); - this.label15.Name = "label15"; + resources.ApplyResources(this.lblNUM_CHANNELS, "lblNUM_CHANNELS"); + this.lblNUM_CHANNELS.Name = "lblNUM_CHANNELS"; // - // label14 + // lblMAX_FREQ // - resources.ApplyResources(this.label14, "label14"); - this.label14.Name = "label14"; + resources.ApplyResources(this.lblMAX_FREQ, "lblMAX_FREQ"); + this.lblMAX_FREQ.Name = "lblMAX_FREQ"; // // ATI2 // @@ -1095,6 +1307,30 @@ private void InitializeComponent() // // groupBoxRemote // + this.groupBoxRemote.Controls.Add(this.btnRemoteLoadFromFile); + this.groupBoxRemote.Controls.Add(this.btnRemoteSaveToFile); + this.groupBoxRemote.Controls.Add(this.lblRFSFRAMELOSS); + this.groupBoxRemote.Controls.Add(this.RFSFRAMELOSS); + this.groupBoxRemote.Controls.Add(this.RGPO1_3AUXOUT); + this.groupBoxRemote.Controls.Add(this.lblRGPO1_3AUXOUT); + this.groupBoxRemote.Controls.Add(this.RGPI1_2AUXIN); + this.groupBoxRemote.Controls.Add(this.lblRGPI1_2AUXIN); + this.groupBoxRemote.Controls.Add(this.lblRGPIO1_1FUNC); + this.groupBoxRemote.Controls.Add(this.RGPIO1_1FUNC); + this.groupBoxRemote.Controls.Add(this.RENCRYPTION_LEVEL); + this.groupBoxRemote.Controls.Add(this.RGPO1_0TXEN485); + this.groupBoxRemote.Controls.Add(this.lblRGPO1_0TXEN485); + this.groupBoxRemote.Controls.Add(this.RGPO1_3STATLED); + this.groupBoxRemote.Controls.Add(this.lblRGPO1_3STATLED); + this.groupBoxRemote.Controls.Add(this.RGPO1_3SBUSOUT); + this.groupBoxRemote.Controls.Add(this.BUT_SetPPMFailSafeRemote); + this.groupBoxRemote.Controls.Add(this.label50); + this.groupBoxRemote.Controls.Add(this.txtRCountry); + this.groupBoxRemote.Controls.Add(this.lblRSBUSOUT); + this.groupBoxRemote.Controls.Add(this.lblRSBUSIN); + this.groupBoxRemote.Controls.Add(this.RGPO1_3SBUSIN); + this.groupBoxRemote.Controls.Add(this.label46); + this.groupBoxRemote.Controls.Add(this.RRATE_FREQBAND); this.groupBoxRemote.Controls.Add(this.lblRRX_ENCAP_METHOD); this.groupBoxRemote.Controls.Add(this.RRX_ENCAP_METHOD); this.groupBoxRemote.Controls.Add(this.lblRTX_ENCAP_METHOD); @@ -1103,23 +1339,23 @@ private void InitializeComponent() this.groupBoxRemote.Controls.Add(this.lblRNODEID); this.groupBoxRemote.Controls.Add(this.RDESTID); this.groupBoxRemote.Controls.Add(this.RNODEID); - this.groupBoxRemote.Controls.Add(this.label41); + this.groupBoxRemote.Controls.Add(this.lblRGPO1_1R_COUT); this.groupBoxRemote.Controls.Add(this.RMAVLINK); this.groupBoxRemote.Controls.Add(this.RGPO1_1R_COUT); this.groupBoxRemote.Controls.Add(this.RFORMAT); - this.groupBoxRemote.Controls.Add(this.label42); + this.groupBoxRemote.Controls.Add(this.lblRGPI1_1R_CIN); this.groupBoxRemote.Controls.Add(this.RGPI1_1R_CIN); this.groupBoxRemote.Controls.Add(this.RSERIAL_SPEED); this.groupBoxRemote.Controls.Add(this.RAIR_SPEED); this.groupBoxRemote.Controls.Add(this.RNETID); - this.groupBoxRemote.Controls.Add(this.label25); + this.groupBoxRemote.Controls.Add(this.lblROPPRESEND); this.groupBoxRemote.Controls.Add(this.RTXPOWER); - this.groupBoxRemote.Controls.Add(this.label26); + this.groupBoxRemote.Controls.Add(this.lblRMAVLINK); this.groupBoxRemote.Controls.Add(this.RECC); - this.groupBoxRemote.Controls.Add(this.label27); - this.groupBoxRemote.Controls.Add(this.label28); + this.groupBoxRemote.Controls.Add(this.lblRECC); + this.groupBoxRemote.Controls.Add(this.lblRTXPOWER); this.groupBoxRemote.Controls.Add(this.ROPPRESEND); - this.groupBoxRemote.Controls.Add(this.label29); + this.groupBoxRemote.Controls.Add(this.lblRNETID); this.groupBoxRemote.Controls.Add(this.label32); this.groupBoxRemote.Controls.Add(this.label30); this.groupBoxRemote.Controls.Add(this.label31); @@ -1134,23 +1370,22 @@ private void InitializeComponent() this.groupBoxRemote.Controls.Add(this.RMAX_DATA); this.groupBoxRemote.Controls.Add(this.lblRMAX_DATA); this.groupBoxRemote.Controls.Add(this.label38); - this.groupBoxRemote.Controls.Add(this.RENCRYPTION_LEVEL); - this.groupBoxRemote.Controls.Add(this.txt_Raeskey); - this.groupBoxRemote.Controls.Add(this.label37); + this.groupBoxRemote.Controls.Add(this.RAESKEY); + this.groupBoxRemote.Controls.Add(this.lblRENCRYPTION_LEVEL); this.groupBoxRemote.Controls.Add(this.RRTSCTS); - this.groupBoxRemote.Controls.Add(this.label33); - this.groupBoxRemote.Controls.Add(this.label34); + this.groupBoxRemote.Controls.Add(this.lblRRTSCTS); + this.groupBoxRemote.Controls.Add(this.lblRMAX_WINDOW); this.groupBoxRemote.Controls.Add(this.RMAX_WINDOW); - this.groupBoxRemote.Controls.Add(this.label24); + this.groupBoxRemote.Controls.Add(this.lblRMIN_FREQ); this.groupBoxRemote.Controls.Add(this.RMAX_FREQ); this.groupBoxRemote.Controls.Add(this.RNUM_CHANNELS); this.groupBoxRemote.Controls.Add(this.RDUTY_CYCLE); this.groupBoxRemote.Controls.Add(this.RLBT_RSSI); this.groupBoxRemote.Controls.Add(this.RMIN_FREQ); - this.groupBoxRemote.Controls.Add(this.label23); - this.groupBoxRemote.Controls.Add(this.label22); - this.groupBoxRemote.Controls.Add(this.label21); - this.groupBoxRemote.Controls.Add(this.label20); + this.groupBoxRemote.Controls.Add(this.lblRMAX_FREQ); + this.groupBoxRemote.Controls.Add(this.lblRNUM_CHANNELS); + this.groupBoxRemote.Controls.Add(this.lblRDUTY_CYCLE); + this.groupBoxRemote.Controls.Add(this.lblRLBT_RSSI); this.groupBoxRemote.Controls.Add(this.RTI2); this.groupBoxRemote.Controls.Add(this.label9); this.groupBoxRemote.Controls.Add(this.RTI); @@ -1158,6 +1393,93 @@ private void InitializeComponent() this.groupBoxRemote.Name = "groupBoxRemote"; this.groupBoxRemote.TabStop = false; // + // lblRFSFRAMELOSS + // + resources.ApplyResources(this.lblRFSFRAMELOSS, "lblRFSFRAMELOSS"); + this.lblRFSFRAMELOSS.Name = "lblRFSFRAMELOSS"; + // + // RGPO1_3AUXOUT + // + resources.ApplyResources(this.RGPO1_3AUXOUT, "RGPO1_3AUXOUT"); + this.RGPO1_3AUXOUT.Name = "RGPO1_3AUXOUT"; + // + // lblRGPO1_3AUXOUT + // + resources.ApplyResources(this.lblRGPO1_3AUXOUT, "lblRGPO1_3AUXOUT"); + this.lblRGPO1_3AUXOUT.Name = "lblRGPO1_3AUXOUT"; + // + // RGPI1_2AUXIN + // + resources.ApplyResources(this.RGPI1_2AUXIN, "RGPI1_2AUXIN"); + this.RGPI1_2AUXIN.Name = "RGPI1_2AUXIN"; + // + // lblRGPI1_2AUXIN + // + resources.ApplyResources(this.lblRGPI1_2AUXIN, "lblRGPI1_2AUXIN"); + this.lblRGPI1_2AUXIN.Name = "lblRGPI1_2AUXIN"; + // + // lblRGPIO1_1FUNC + // + resources.ApplyResources(this.lblRGPIO1_1FUNC, "lblRGPIO1_1FUNC"); + this.lblRGPIO1_1FUNC.Name = "lblRGPIO1_1FUNC"; + // + // RGPIO1_1FUNC + // + this.RGPIO1_1FUNC.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.RGPIO1_1FUNC, "RGPIO1_1FUNC"); + this.RGPIO1_1FUNC.FormattingEnabled = true; + this.RGPIO1_1FUNC.Name = "RGPIO1_1FUNC"; + // + // lblRGPO1_0TXEN485 + // + resources.ApplyResources(this.lblRGPO1_0TXEN485, "lblRGPO1_0TXEN485"); + this.lblRGPO1_0TXEN485.Name = "lblRGPO1_0TXEN485"; + // + // lblRGPO1_3STATLED + // + resources.ApplyResources(this.lblRGPO1_3STATLED, "lblRGPO1_3STATLED"); + this.lblRGPO1_3STATLED.Name = "lblRGPO1_3STATLED"; + // + // RGPO1_3SBUSOUT + // + this.RGPO1_3SBUSOUT.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.RGPO1_3SBUSOUT, "RGPO1_3SBUSOUT"); + this.RGPO1_3SBUSOUT.FormattingEnabled = true; + this.RGPO1_3SBUSOUT.Name = "RGPO1_3SBUSOUT"; + // + // label50 + // + resources.ApplyResources(this.label50, "label50"); + this.label50.Name = "label50"; + // + // txtRCountry + // + resources.ApplyResources(this.txtRCountry, "txtRCountry"); + this.txtRCountry.Name = "txtRCountry"; + this.txtRCountry.ReadOnly = true; + // + // lblRSBUSOUT + // + resources.ApplyResources(this.lblRSBUSOUT, "lblRSBUSOUT"); + this.lblRSBUSOUT.Name = "lblRSBUSOUT"; + // + // lblRSBUSIN + // + resources.ApplyResources(this.lblRSBUSIN, "lblRSBUSIN"); + this.lblRSBUSIN.Name = "lblRSBUSIN"; + // + // label46 + // + resources.ApplyResources(this.label46, "label46"); + this.label46.Name = "label46"; + // + // RRATE_FREQBAND + // + this.RRATE_FREQBAND.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; + resources.ApplyResources(this.RRATE_FREQBAND, "RRATE_FREQBAND"); + this.RRATE_FREQBAND.FormattingEnabled = true; + this.RRATE_FREQBAND.Name = "RRATE_FREQBAND"; + // // lblRRX_ENCAP_METHOD // resources.ApplyResources(this.lblRRX_ENCAP_METHOD, "lblRRX_ENCAP_METHOD"); @@ -1206,10 +1528,10 @@ private void InitializeComponent() resources.ApplyResources(this.RNODEID, "RNODEID"); this.RNODEID.Name = "RNODEID"; // - // label41 + // lblRGPO1_1R_COUT // - resources.ApplyResources(this.label41, "label41"); - this.label41.Name = "label41"; + resources.ApplyResources(this.lblRGPO1_1R_COUT, "lblRGPO1_1R_COUT"); + this.lblRGPO1_1R_COUT.Name = "lblRGPO1_1R_COUT"; // // RFORMAT // @@ -1217,35 +1539,35 @@ private void InitializeComponent() this.RFORMAT.Name = "RFORMAT"; this.RFORMAT.ReadOnly = true; // - // label42 + // lblRGPI1_1R_CIN // - resources.ApplyResources(this.label42, "label42"); - this.label42.Name = "label42"; + resources.ApplyResources(this.lblRGPI1_1R_CIN, "lblRGPI1_1R_CIN"); + this.lblRGPI1_1R_CIN.Name = "lblRGPI1_1R_CIN"; // - // label25 + // lblROPPRESEND // - resources.ApplyResources(this.label25, "label25"); - this.label25.Name = "label25"; + resources.ApplyResources(this.lblROPPRESEND, "lblROPPRESEND"); + this.lblROPPRESEND.Name = "lblROPPRESEND"; // - // label26 + // lblRMAVLINK // - resources.ApplyResources(this.label26, "label26"); - this.label26.Name = "label26"; + resources.ApplyResources(this.lblRMAVLINK, "lblRMAVLINK"); + this.lblRMAVLINK.Name = "lblRMAVLINK"; // - // label27 + // lblRECC // - resources.ApplyResources(this.label27, "label27"); - this.label27.Name = "label27"; + resources.ApplyResources(this.lblRECC, "lblRECC"); + this.lblRECC.Name = "lblRECC"; // - // label28 + // lblRTXPOWER // - resources.ApplyResources(this.label28, "label28"); - this.label28.Name = "label28"; + resources.ApplyResources(this.lblRTXPOWER, "lblRTXPOWER"); + this.lblRTXPOWER.Name = "lblRTXPOWER"; // - // label29 + // lblRNETID // - resources.ApplyResources(this.label29, "label29"); - this.label29.Name = "label29"; + resources.ApplyResources(this.lblRNETID, "lblRNETID"); + this.lblRNETID.Name = "lblRNETID"; // // label32 // @@ -1270,8 +1592,8 @@ private void InitializeComponent() // RANT_MODE // this.RANT_MODE.DropDownStyle = System.Windows.Forms.ComboBoxStyle.DropDownList; - this.RANT_MODE.FormattingEnabled = true; resources.ApplyResources(this.RANT_MODE, "RANT_MODE"); + this.RANT_MODE.FormattingEnabled = true; this.RANT_MODE.Name = "RANT_MODE"; // // lblRSER_BRK_DETMS @@ -1327,56 +1649,50 @@ private void InitializeComponent() resources.ApplyResources(this.label38, "label38"); this.label38.Name = "label38"; // - // RENCRYPTION_LEVEL - // - resources.ApplyResources(this.RENCRYPTION_LEVEL, "RENCRYPTION_LEVEL"); - this.RENCRYPTION_LEVEL.Name = "RENCRYPTION_LEVEL"; - this.RENCRYPTION_LEVEL.CheckedChanged += new System.EventHandler(this.RENCRYPTION_LEVEL_CheckedChanged); - // // txt_Raeskey // - resources.ApplyResources(this.txt_Raeskey, "txt_Raeskey"); - this.txt_Raeskey.Name = "txt_Raeskey"; + resources.ApplyResources(this.RAESKEY, "txt_Raeskey"); + this.RAESKEY.Name = "RAESKEY"; // - // label37 + // lblRENCRYPTION_LEVEL // - resources.ApplyResources(this.label37, "label37"); - this.label37.Name = "label37"; + resources.ApplyResources(this.lblRENCRYPTION_LEVEL, "lblRENCRYPTION_LEVEL"); + this.lblRENCRYPTION_LEVEL.Name = "lblRENCRYPTION_LEVEL"; // - // label33 + // lblRRTSCTS // - resources.ApplyResources(this.label33, "label33"); - this.label33.Name = "label33"; + resources.ApplyResources(this.lblRRTSCTS, "lblRRTSCTS"); + this.lblRRTSCTS.Name = "lblRRTSCTS"; // - // label34 + // lblRMAX_WINDOW // - resources.ApplyResources(this.label34, "label34"); - this.label34.Name = "label34"; + resources.ApplyResources(this.lblRMAX_WINDOW, "lblRMAX_WINDOW"); + this.lblRMAX_WINDOW.Name = "lblRMAX_WINDOW"; // - // label24 + // lblRMIN_FREQ // - resources.ApplyResources(this.label24, "label24"); - this.label24.Name = "label24"; + resources.ApplyResources(this.lblRMIN_FREQ, "lblRMIN_FREQ"); + this.lblRMIN_FREQ.Name = "lblRMIN_FREQ"; // - // label23 + // lblRMAX_FREQ // - resources.ApplyResources(this.label23, "label23"); - this.label23.Name = "label23"; + resources.ApplyResources(this.lblRMAX_FREQ, "lblRMAX_FREQ"); + this.lblRMAX_FREQ.Name = "lblRMAX_FREQ"; // - // label22 + // lblRNUM_CHANNELS // - resources.ApplyResources(this.label22, "label22"); - this.label22.Name = "label22"; + resources.ApplyResources(this.lblRNUM_CHANNELS, "lblRNUM_CHANNELS"); + this.lblRNUM_CHANNELS.Name = "lblRNUM_CHANNELS"; // - // label21 + // lblRDUTY_CYCLE // - resources.ApplyResources(this.label21, "label21"); - this.label21.Name = "label21"; + resources.ApplyResources(this.lblRDUTY_CYCLE, "lblRDUTY_CYCLE"); + this.lblRDUTY_CYCLE.Name = "lblRDUTY_CYCLE"; // - // label20 + // lblRLBT_RSSI // - resources.ApplyResources(this.label20, "label20"); - this.label20.Name = "label20"; + resources.ApplyResources(this.lblRLBT_RSSI, "lblRLBT_RSSI"); + this.lblRLBT_RSSI.Name = "lblRLBT_RSSI"; // // RTI2 // @@ -1394,13 +1710,15 @@ private void InitializeComponent() resources.ApplyResources(this.label10, "label10"); this.label10.Name = "label10"; // - // BUT_SetPPMFailSafe + // dlgSave // - resources.ApplyResources(this.BUT_SetPPMFailSafe, "BUT_SetPPMFailSafe"); - this.BUT_SetPPMFailSafe.Name = "BUT_SetPPMFailSafe"; - this.toolTip1.SetToolTip(this.BUT_SetPPMFailSafe, resources.GetString("BUT_SetPPMFailSafe.ToolTip")); - this.BUT_SetPPMFailSafe.UseVisualStyleBackColor = true; - this.BUT_SetPPMFailSafe.Click += new System.EventHandler(this.BUT_SetPPMFailSafe_Click); + this.dlgSave.FileName = "*.ini"; + resources.ApplyResources(this.dlgSave, "dlgSave"); + // + // dlgOpen + // + this.dlgOpen.FileName = "*.ini"; + resources.ApplyResources(this.dlgOpen, "dlgOpen"); // // BUT_loadcustom // @@ -1416,6 +1734,36 @@ private void InitializeComponent() this.BUT_resettodefault.UseVisualStyleBackColor = true; this.BUT_resettodefault.Click += new System.EventHandler(this.BUT_resettodefault_Click); // + // btnRemoteLoadFromFile + // + resources.ApplyResources(this.btnRemoteLoadFromFile, "btnRemoteLoadFromFile"); + this.btnRemoteLoadFromFile.Name = "btnRemoteLoadFromFile"; + this.btnRemoteLoadFromFile.UseVisualStyleBackColor = true; + this.btnRemoteLoadFromFile.Click += new System.EventHandler(this.btnRemoteLoadFromFile_Click); + // + // btnRemoteSaveToFile + // + resources.ApplyResources(this.btnRemoteSaveToFile, "btnRemoteSaveToFile"); + this.btnRemoteSaveToFile.Name = "btnRemoteSaveToFile"; + this.btnRemoteSaveToFile.UseVisualStyleBackColor = true; + this.btnRemoteSaveToFile.Click += new System.EventHandler(this.btnRemoteSaveToFile_Click); + // + // BUT_SetPPMFailSafeRemote + // + resources.ApplyResources(this.BUT_SetPPMFailSafeRemote, "BUT_SetPPMFailSafeRemote"); + this.BUT_SetPPMFailSafeRemote.Name = "BUT_SetPPMFailSafeRemote"; + this.toolTip1.SetToolTip(this.BUT_SetPPMFailSafeRemote, resources.GetString("BUT_SetPPMFailSafeRemote.ToolTip")); + this.BUT_SetPPMFailSafeRemote.UseVisualStyleBackColor = true; + this.BUT_SetPPMFailSafeRemote.Click += new System.EventHandler(this.BUT_SetPPMFailSafeRemote_Click); + // + // BUT_SetPPMFailSafe + // + resources.ApplyResources(this.BUT_SetPPMFailSafe, "BUT_SetPPMFailSafe"); + this.BUT_SetPPMFailSafe.Name = "BUT_SetPPMFailSafe"; + this.toolTip1.SetToolTip(this.BUT_SetPPMFailSafe, resources.GetString("BUT_SetPPMFailSafe.ToolTip")); + this.BUT_SetPPMFailSafe.UseVisualStyleBackColor = true; + this.BUT_SetPPMFailSafe.Click += new System.EventHandler(this.BUT_SetPPMFailSafe_Click); + // // BUT_savesettings // resources.ApplyResources(this.BUT_savesettings, "BUT_savesettings"); @@ -1444,11 +1792,24 @@ private void InitializeComponent() this.BUT_Syncoptions.UseVisualStyleBackColor = true; this.BUT_Syncoptions.Click += new System.EventHandler(this.BUT_Syncoptions_Click); // + // btnSaveToFile + // + resources.ApplyResources(this.btnSaveToFile, "btnSaveToFile"); + this.btnSaveToFile.Name = "btnSaveToFile"; + this.btnSaveToFile.UseVisualStyleBackColor = true; + this.btnSaveToFile.Click += new System.EventHandler(this.btnSaveToFile_Click); + // + // btnLoadFromFile + // + resources.ApplyResources(this.btnLoadFromFile, "btnLoadFromFile"); + this.btnLoadFromFile.Name = "btnLoadFromFile"; + this.btnLoadFromFile.UseVisualStyleBackColor = true; + this.btnLoadFromFile.Click += new System.EventHandler(this.btnLoadFromFile_Click); + // // Sikradio // this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.None; this.Controls.Add(this.Progressbar); - this.Controls.Add(this.BUT_SetPPMFailSafe); this.Controls.Add(this.BUT_loadcustom); this.Controls.Add(this.BUT_resettodefault); this.Controls.Add(this.linkLabel1); @@ -1469,147 +1830,194 @@ private void InitializeComponent() this.ResumeLayout(false); this.PerformLayout(); - } - - #endregion - - private Controls.MyButton BUT_upload; - private System.Windows.Forms.ProgressBar Progressbar; - private System.Windows.Forms.Label lbl_status; - private Controls.MyButton BUT_getcurrent; - private Controls.MyButton BUT_savesettings; - private System.Windows.Forms.ToolTip toolTip1; - private System.Windows.Forms.TextBox RTI; - private System.Windows.Forms.TextBox ATI; - private System.Windows.Forms.TextBox RSSI; - private System.Windows.Forms.Label label11; - private System.Windows.Forms.Label label12; - private Controls.MyButton BUT_Syncoptions; - private System.Windows.Forms.TextBox ATI3; - private System.Windows.Forms.GroupBox groupBoxLocal; - private System.Windows.Forms.GroupBox groupBoxRemote; - private System.Windows.Forms.Label label9; - private System.Windows.Forms.Label label10; - private System.Windows.Forms.LinkLabel linkLabel1; - private Controls.MyButton BUT_resettodefault; - private System.Windows.Forms.TextBox ATI2; - private System.Windows.Forms.TextBox RTI2; - private Controls.MyButton BUT_loadcustom; - private Controls.MyButton BUT_SetPPMFailSafe; - private System.Windows.Forms.Label lblRX_ENCAP_METHOD; - private System.Windows.Forms.ComboBox RX_ENCAP_METHOD; - private System.Windows.Forms.Label lblTX_ENCAP_METHOD; - private System.Windows.Forms.ComboBox TX_ENCAP_METHOD; - private System.Windows.Forms.Label lblDESTID; - private System.Windows.Forms.Label lblNODEID; - private System.Windows.Forms.ComboBox DESTID; - private System.Windows.Forms.ComboBox NODEID; - private System.Windows.Forms.Label label40; - private System.Windows.Forms.CheckBox GPO1_1R_COUT; - private System.Windows.Forms.Label label39; - private System.Windows.Forms.CheckBox GPI1_1R_CIN; - private System.Windows.Forms.ComboBox MAVLINK; - private System.Windows.Forms.Label label2; - private System.Windows.Forms.ComboBox SERIAL_SPEED; - private System.Windows.Forms.Label label1; - private System.Windows.Forms.TextBox FORMAT; - private System.Windows.Forms.ComboBox AIR_SPEED; - private System.Windows.Forms.Label label3; - private System.Windows.Forms.ComboBox NETID; - private System.Windows.Forms.Label label4; - private System.Windows.Forms.ComboBox TXPOWER; - private System.Windows.Forms.Label label5; - private System.Windows.Forms.CheckBox ECC; - private System.Windows.Forms.Label label6; - private System.Windows.Forms.Label label8; - private System.Windows.Forms.CheckBox OPPRESEND; - private System.Windows.Forms.Label label7; - private System.Windows.Forms.Label lblANT_MODE; - private System.Windows.Forms.ComboBox ANT_MODE; - private System.Windows.Forms.Label lblSER_BRK_DETMS; - private System.Windows.Forms.Label lblGLOBAL_RETRIES; - private System.Windows.Forms.Label lblMAX_RETRIES; - private System.Windows.Forms.ComboBox SER_BRK_DETMS; - private System.Windows.Forms.ComboBox GLOBAL_RETRIES; - private System.Windows.Forms.ComboBox MAX_RETRIES; - private System.Windows.Forms.ComboBox MAX_DATA; - private System.Windows.Forms.Label lblMAX_DATA; - private System.Windows.Forms.CheckBox ENCRYPTION_LEVEL; - private System.Windows.Forms.Label label36; - private System.Windows.Forms.Label label35; - private System.Windows.Forms.TextBox txt_aeskey; - private System.Windows.Forms.CheckBox RTSCTS; - private System.Windows.Forms.Label label19; - private System.Windows.Forms.LinkLabel linkLabel_mavlink; - private System.Windows.Forms.LinkLabel linkLabel_lowlatency; - private System.Windows.Forms.Label label18; - private System.Windows.Forms.ComboBox MAX_WINDOW; - private System.Windows.Forms.Label label13; - private System.Windows.Forms.ComboBox MAX_FREQ; - private System.Windows.Forms.ComboBox NUM_CHANNELS; - private System.Windows.Forms.Label label17; - private System.Windows.Forms.ComboBox LBT_RSSI; - private System.Windows.Forms.Label label16; - private System.Windows.Forms.ComboBox MIN_FREQ; - private System.Windows.Forms.Label label15; - private System.Windows.Forms.Label label14; - private System.Windows.Forms.ComboBox DUTY_CYCLE; - private System.Windows.Forms.Label lblRRX_ENCAP_METHOD; - private System.Windows.Forms.ComboBox RRX_ENCAP_METHOD; - private System.Windows.Forms.Label lblRTX_ENCAP_METHOD; - private System.Windows.Forms.ComboBox RTX_ENCAP_METHOD; - private System.Windows.Forms.Label lblRDESTID; - private System.Windows.Forms.Label lblRNODEID; - private System.Windows.Forms.ComboBox RDESTID; - private System.Windows.Forms.ComboBox RNODEID; - private System.Windows.Forms.Label label41; - private System.Windows.Forms.ComboBox RMAVLINK; - private System.Windows.Forms.CheckBox RGPO1_1R_COUT; - private System.Windows.Forms.TextBox RFORMAT; - private System.Windows.Forms.Label label42; - private System.Windows.Forms.CheckBox RGPI1_1R_CIN; - private System.Windows.Forms.ComboBox RSERIAL_SPEED; - private System.Windows.Forms.ComboBox RAIR_SPEED; - private System.Windows.Forms.ComboBox RNETID; - private System.Windows.Forms.Label label25; - private System.Windows.Forms.ComboBox RTXPOWER; - private System.Windows.Forms.Label label26; - private System.Windows.Forms.CheckBox RECC; - private System.Windows.Forms.Label label27; - private System.Windows.Forms.Label label28; - private System.Windows.Forms.CheckBox ROPPRESEND; - private System.Windows.Forms.Label label29; - private System.Windows.Forms.Label label32; - private System.Windows.Forms.Label label30; - private System.Windows.Forms.Label label31; - private System.Windows.Forms.Label lblRANT_MODE; - private System.Windows.Forms.ComboBox RANT_MODE; - private System.Windows.Forms.Label lblRSER_BRK_DETMS; - private System.Windows.Forms.Label lblRGLOBAL_RETRIES; - private System.Windows.Forms.Label lblRMAX_RETRIES; - private System.Windows.Forms.ComboBox RSER_BRK_DETMS; - private System.Windows.Forms.ComboBox RGLOBAL_RETRIES; - private System.Windows.Forms.ComboBox RMAX_RETRIES; - private System.Windows.Forms.ComboBox RMAX_DATA; - private System.Windows.Forms.Label lblRMAX_DATA; - private System.Windows.Forms.Label label38; - private System.Windows.Forms.CheckBox RENCRYPTION_LEVEL; - private System.Windows.Forms.TextBox txt_Raeskey; - private System.Windows.Forms.Label label37; - private System.Windows.Forms.CheckBox RRTSCTS; - private System.Windows.Forms.Label label33; - private System.Windows.Forms.Label label34; - private System.Windows.Forms.ComboBox RMAX_WINDOW; - private System.Windows.Forms.Label label24; - private System.Windows.Forms.ComboBox RMAX_FREQ; - private System.Windows.Forms.ComboBox RNUM_CHANNELS; - private System.Windows.Forms.ComboBox RDUTY_CYCLE; - private System.Windows.Forms.ComboBox RLBT_RSSI; - private System.Windows.Forms.ComboBox RMIN_FREQ; - private System.Windows.Forms.Label label23; - private System.Windows.Forms.Label label22; - private System.Windows.Forms.Label label21; - private System.Windows.Forms.Label label20; - private System.Windows.Forms.Button btnRandom; - } + } + + #endregion + + private Controls.MyButton BUT_upload; + private System.Windows.Forms.ProgressBar Progressbar; + private System.Windows.Forms.Label lbl_status; + private Controls.MyButton BUT_getcurrent; + private Controls.MyButton BUT_savesettings; + private System.Windows.Forms.ToolTip toolTip1; + private System.Windows.Forms.TextBox RTI; + private System.Windows.Forms.TextBox ATI; + private System.Windows.Forms.TextBox RSSI; + private System.Windows.Forms.Label label11; + private System.Windows.Forms.Label label12; + private Controls.MyButton BUT_Syncoptions; + private System.Windows.Forms.TextBox ATI3; + private System.Windows.Forms.GroupBox groupBoxLocal; + private System.Windows.Forms.GroupBox groupBoxRemote; + private System.Windows.Forms.Label label9; + private System.Windows.Forms.Label label10; + private System.Windows.Forms.LinkLabel linkLabel1; + private Controls.MyButton BUT_resettodefault; + private System.Windows.Forms.TextBox ATI2; + private System.Windows.Forms.TextBox RTI2; + private Controls.MyButton BUT_loadcustom; + private Controls.MyButton BUT_SetPPMFailSafe; + private System.Windows.Forms.Label lblRX_ENCAP_METHOD; + private System.Windows.Forms.ComboBox RX_ENCAP_METHOD; + private System.Windows.Forms.Label lblTX_ENCAP_METHOD; + private System.Windows.Forms.ComboBox TX_ENCAP_METHOD; + private System.Windows.Forms.Label lblDESTID; + private System.Windows.Forms.Label lblNODEID; + private System.Windows.Forms.ComboBox DESTID; + private System.Windows.Forms.ComboBox NODEID; + private System.Windows.Forms.Label lblGPO1_1R_COUT; + private System.Windows.Forms.CheckBox GPO1_1R_COUT; + private System.Windows.Forms.Label lblGPI1_1R_CIN; + private System.Windows.Forms.CheckBox GPI1_1R_CIN; + private System.Windows.Forms.ComboBox MAVLINK; + private System.Windows.Forms.Label label2; + private System.Windows.Forms.ComboBox SERIAL_SPEED; + private System.Windows.Forms.Label label1; + private System.Windows.Forms.TextBox FORMAT; + private System.Windows.Forms.ComboBox AIR_SPEED; + private System.Windows.Forms.Label label3; + private System.Windows.Forms.ComboBox NETID; + private System.Windows.Forms.Label lblNETID; + private System.Windows.Forms.ComboBox TXPOWER; + private System.Windows.Forms.Label lblTXPOWER; + private System.Windows.Forms.CheckBox ECC; + private System.Windows.Forms.Label lblECC; + private System.Windows.Forms.Label lblOPPRESEND; + private System.Windows.Forms.CheckBox OPPRESEND; + private System.Windows.Forms.Label lblMAVLINK; + private System.Windows.Forms.Label lblANT_MODE; + private System.Windows.Forms.ComboBox ANT_MODE; + private System.Windows.Forms.Label lblSER_BRK_DETMS; + private System.Windows.Forms.Label lblGLOBAL_RETRIES; + private System.Windows.Forms.Label lblMAX_RETRIES; + private System.Windows.Forms.ComboBox SER_BRK_DETMS; + private System.Windows.Forms.ComboBox GLOBAL_RETRIES; + private System.Windows.Forms.ComboBox MAX_RETRIES; + private System.Windows.Forms.ComboBox MAX_DATA; + private System.Windows.Forms.Label lblMAX_DATA; + private System.Windows.Forms.Label lblENCRYPTION_LEVEL; + private System.Windows.Forms.Label label35; + private System.Windows.Forms.TextBox AESKEY; + private System.Windows.Forms.CheckBox RTSCTS; + private System.Windows.Forms.Label lblRTSCTS; + private System.Windows.Forms.LinkLabel linkLabel_mavlink; + private System.Windows.Forms.LinkLabel linkLabel_lowlatency; + private System.Windows.Forms.Label lblMAX_WINDOW; + private System.Windows.Forms.ComboBox MAX_WINDOW; + private System.Windows.Forms.Label lblMIN_FREQ; + private System.Windows.Forms.ComboBox MAX_FREQ; + private System.Windows.Forms.ComboBox NUM_CHANNELS; + private System.Windows.Forms.Label lblLBT_RSSI; + private System.Windows.Forms.ComboBox LBT_RSSI; + private System.Windows.Forms.Label lblDUTY_CYCLE; + private System.Windows.Forms.ComboBox MIN_FREQ; + private System.Windows.Forms.Label lblNUM_CHANNELS; + private System.Windows.Forms.Label lblMAX_FREQ; + private System.Windows.Forms.ComboBox DUTY_CYCLE; + private System.Windows.Forms.Label lblRRX_ENCAP_METHOD; + private System.Windows.Forms.ComboBox RRX_ENCAP_METHOD; + private System.Windows.Forms.Label lblRTX_ENCAP_METHOD; + private System.Windows.Forms.ComboBox RTX_ENCAP_METHOD; + private System.Windows.Forms.Label lblRDESTID; + private System.Windows.Forms.Label lblRNODEID; + private System.Windows.Forms.ComboBox RDESTID; + private System.Windows.Forms.ComboBox RNODEID; + private System.Windows.Forms.Label lblRGPO1_1R_COUT; + private System.Windows.Forms.ComboBox RMAVLINK; + private System.Windows.Forms.CheckBox RGPO1_1R_COUT; + private System.Windows.Forms.TextBox RFORMAT; + private System.Windows.Forms.Label lblRGPI1_1R_CIN; + private System.Windows.Forms.CheckBox RGPI1_1R_CIN; + private System.Windows.Forms.ComboBox RSERIAL_SPEED; + private System.Windows.Forms.ComboBox RAIR_SPEED; + private System.Windows.Forms.ComboBox RNETID; + private System.Windows.Forms.Label lblROPPRESEND; + private System.Windows.Forms.ComboBox RTXPOWER; + private System.Windows.Forms.Label lblRMAVLINK; + private System.Windows.Forms.CheckBox RECC; + private System.Windows.Forms.Label lblRECC; + private System.Windows.Forms.Label lblRTXPOWER; + private System.Windows.Forms.CheckBox ROPPRESEND; + private System.Windows.Forms.Label lblRNETID; + private System.Windows.Forms.Label label32; + private System.Windows.Forms.Label label30; + private System.Windows.Forms.Label label31; + private System.Windows.Forms.Label lblRANT_MODE; + private System.Windows.Forms.ComboBox RANT_MODE; + private System.Windows.Forms.Label lblRSER_BRK_DETMS; + private System.Windows.Forms.Label lblRGLOBAL_RETRIES; + private System.Windows.Forms.Label lblRMAX_RETRIES; + private System.Windows.Forms.ComboBox RSER_BRK_DETMS; + private System.Windows.Forms.ComboBox RGLOBAL_RETRIES; + private System.Windows.Forms.ComboBox RMAX_RETRIES; + private System.Windows.Forms.ComboBox RMAX_DATA; + private System.Windows.Forms.Label lblRMAX_DATA; + private System.Windows.Forms.Label label38; + private System.Windows.Forms.TextBox RAESKEY; + private System.Windows.Forms.Label lblRENCRYPTION_LEVEL; + private System.Windows.Forms.CheckBox RRTSCTS; + private System.Windows.Forms.Label lblRRTSCTS; + private System.Windows.Forms.Label lblRMAX_WINDOW; + private System.Windows.Forms.ComboBox RMAX_WINDOW; + private System.Windows.Forms.Label lblRMIN_FREQ; + private System.Windows.Forms.ComboBox RMAX_FREQ; + private System.Windows.Forms.ComboBox RNUM_CHANNELS; + private System.Windows.Forms.ComboBox RDUTY_CYCLE; + private System.Windows.Forms.ComboBox RLBT_RSSI; + private System.Windows.Forms.ComboBox RMIN_FREQ; + private System.Windows.Forms.Label lblRMAX_FREQ; + private System.Windows.Forms.Label lblRNUM_CHANNELS; + private System.Windows.Forms.Label lblRDUTY_CYCLE; + private System.Windows.Forms.Label lblRLBT_RSSI; + private System.Windows.Forms.Button btnRandom; + private System.Windows.Forms.Label lblSBUSIN; + private System.Windows.Forms.CheckBox GPO1_3SBUSIN; + private System.Windows.Forms.Label lblSBUSOUT; + private System.Windows.Forms.Label label45; + private System.Windows.Forms.ComboBox RATE_FREQBAND; + private System.Windows.Forms.Label label46; + private System.Windows.Forms.ComboBox RRATE_FREQBAND; + private System.Windows.Forms.Label lblRSBUSOUT; + private System.Windows.Forms.Label lblRSBUSIN; + private System.Windows.Forms.CheckBox RGPO1_3SBUSIN; + private System.Windows.Forms.TextBox txtCountry; + private System.Windows.Forms.Label label49; + private System.Windows.Forms.Label label50; + private System.Windows.Forms.TextBox txtRCountry; + private Controls.MyButton BUT_SetPPMFailSafeRemote; + private System.Windows.Forms.ComboBox GPO1_3SBUSOUT; + private System.Windows.Forms.ComboBox RGPO1_3SBUSOUT; + private System.Windows.Forms.CheckBox GPO1_0TXEN485; + private System.Windows.Forms.Label lblGPO1_0TXEN485; + private System.Windows.Forms.CheckBox GPO1_3STATLED; + private System.Windows.Forms.Label lblGPO1_3STATLED; + private System.Windows.Forms.CheckBox RGPO1_0TXEN485; + private System.Windows.Forms.Label lblRGPO1_0TXEN485; + private System.Windows.Forms.CheckBox RGPO1_3STATLED; + private System.Windows.Forms.Label lblRGPO1_3STATLED; + private System.Windows.Forms.ComboBox ENCRYPTION_LEVEL; + private System.Windows.Forms.ComboBox RENCRYPTION_LEVEL; + private System.Windows.Forms.Label lblGPIO1_1FUNC; + private System.Windows.Forms.ComboBox GPIO1_1FUNC; + private System.Windows.Forms.Label lblRGPIO1_1FUNC; + private System.Windows.Forms.ComboBox RGPIO1_1FUNC; + private System.Windows.Forms.CheckBox GPO1_3AUXOUT; + private System.Windows.Forms.Label lblGPO1_3AUXOUT; + private System.Windows.Forms.CheckBox GPI1_2AUXIN; + private System.Windows.Forms.Label lblGPI1_2AUXIN; + private System.Windows.Forms.Label label54; + private System.Windows.Forms.ComboBox FSFRAMELOSS; + private System.Windows.Forms.Label lblRFSFRAMELOSS; + private System.Windows.Forms.ComboBox RFSFRAMELOSS; + private System.Windows.Forms.CheckBox RGPO1_3AUXOUT; + private System.Windows.Forms.Label lblRGPO1_3AUXOUT; + private System.Windows.Forms.CheckBox RGPI1_2AUXIN; + private System.Windows.Forms.Label lblRGPI1_2AUXIN; + private Controls.MyButton btnSaveToFile; + private System.Windows.Forms.SaveFileDialog dlgSave; + private Controls.MyButton btnRemoteSaveToFile; + private Controls.MyButton btnLoadFromFile; + private System.Windows.Forms.OpenFileDialog dlgOpen; + private Controls.MyButton btnRemoteLoadFromFile; + } } \ No newline at end of file diff --git a/Radio/Sikradio.cs b/Radio/Sikradio.cs index 688fb4d8a6..e4d5b04610 100644 --- a/Radio/Sikradio.cs +++ b/Radio/Sikradio.cs @@ -1,6 +1,3 @@ -using log4net; -using MissionPlanner.Comms; -using MissionPlanner.Utilities; using System; using System.Collections.Generic; using System.Globalization; @@ -11,6 +8,13 @@ using System.Text.RegularExpressions; using System.Threading; using System.Windows.Forms; +using log4net; +using MissionPlanner.Comms; +using MissionPlanner.Controls; +using MissionPlanner.MsgBox; +using MissionPlanner.Radio; +using MissionPlanner.Utilities; +using Microsoft.VisualBasic; namespace MissionPlanner.Radio { @@ -20,23 +24,32 @@ public partial class Sikradio : UserControl, SikRadio.ISikRadioForm public delegate void ProgressEventHandler(double completed); - /// - /// An alternative function for getting the serial port. Can be left as null - /// if no alternative. - /// - public Func GetCommsSerialAlt; - private static readonly ILog log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private bool beta; - private readonly string firmwarefile = Path.GetTempFileName(); + private string firmwarefile = Path.GetTempFileName(); private Dictionary _DefaultLocalEnabled = new Dictionary(); private Dictionary _DefaultCBObjects = new Dictionary(); RFD.RFD900.TSession _Session; ExtraParamControlsSet _LocalExtraParams; ExtraParamControlsSet _RemoteExtraParams; + RFDLib.GUI.Settings.TDynamicLabelEditorPairRegister _DynamicLabelEditorPairRegister; + + RFDLib.GUI.Settings.TLabelEditorPairRegister _LocalLabelEditorPairs = new RFDLib.GUI.Settings.TLabelEditorPairRegister(); + RFDLib.GUI.Settings.TLabelEditorPairRegister _RemoteLabelEditorPairs = new RFDLib.GUI.Settings.TLabelEditorPairRegister(); + Dictionary _KnownNameDescriptions = new Dictionary() + { + {"RSSI_IN_DBM", "RSSI in dBm"}, + {"AUXSER_SPEED", "Aux Baud"}, + {"AIR_FRAMELEN", "Air Frame Length"}, + }; + + RFD.RFD900.TSettings _LocalSettings, _RemoteSettings; + + public event Action DoDisconnectReconnect; + /* ATI5 S0: FORMAT=25 @@ -67,17 +80,15 @@ public Sikradio() _LocalExtraParams = new ExtraParamControlsSet(lblNODEID, NODEID, lblDESTID, DESTID, lblTX_ENCAP_METHOD, TX_ENCAP_METHOD, lblRX_ENCAP_METHOD, RX_ENCAP_METHOD, - lblMAX_DATA, MAX_DATA, - new Control[] {lblMAX_RETRIES, MAX_RETRIES, - lblGLOBAL_RETRIES, GLOBAL_RETRIES, lblSER_BRK_DETMS, SER_BRK_DETMS, - lblANT_MODE, ANT_MODE}, false); + lblMAX_DATA, MAX_DATA, lblMAX_RETRIES, MAX_RETRIES, + new Control[] { + lblGLOBAL_RETRIES, GLOBAL_RETRIES, lblSER_BRK_DETMS, SER_BRK_DETMS}, false); _RemoteExtraParams = new ExtraParamControlsSet(lblRNODEID, RNODEID, lblRDESTID, RDESTID, lblRTX_ENCAP_METHOD, RTX_ENCAP_METHOD, lblRRX_ENCAP_METHOD, RRX_ENCAP_METHOD, - lblRMAX_DATA, RMAX_DATA, - new Control[] {lblRMAX_RETRIES, RMAX_RETRIES, - lblRGLOBAL_RETRIES, RGLOBAL_RETRIES, lblRSER_BRK_DETMS, RSER_BRK_DETMS, - lblRANT_MODE, RANT_MODE}, true); + lblRMAX_DATA, RMAX_DATA, lblRMAX_RETRIES, RMAX_RETRIES, + new Control[] { + lblRGLOBAL_RETRIES, RGLOBAL_RETRIES, lblRSER_BRK_DETMS, RSER_BRK_DETMS}, true); // setup netid NETID.DataSource = Enumerable.Range(0, 500).ToArray(); @@ -117,9 +128,148 @@ public Sikradio() SaveDefaultCBObjects(MAX_WINDOW); SaveDefaultCBObjects(RMAX_WINDOW); + RFDLib.GUI.Settings.TDynamicLabelEditorPair SBUSIN = new RFDLib.GUI.Settings.TDynamicLabelEditorPair(lblSBUSIN, GPO1_3SBUSIN, + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair[] + { + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("GPO1_3SBUSIN", "GPO1_3SBUSIN"), + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("GPO1_1SBUSIN", "GPO1_1SBUSIN"), + }); + RFDLib.GUI.Settings.TDynamicLabelEditorPair RSBUSIN = new RFDLib.GUI.Settings.TDynamicLabelEditorPair(lblRSBUSIN, RGPO1_3SBUSIN, + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair[] + { + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("RGPO1_3SBUSIN", "GPO1_3SBUSIN"), + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("RGPO1_1SBUSIN", "GPO1_1SBUSIN"), + }); + RFDLib.GUI.Settings.TDynamicLabelEditorPair SBUSOUT = new RFDLib.GUI.Settings.TDynamicLabelEditorPair(lblSBUSOUT, GPO1_3SBUSOUT, + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair[] + { + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("GPO1_3SBUSOUT", "GPO1_3SBUSOUT"), + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("GPO1_1SBUSOUT", "GPO1_1SBUSOUT"), + }); + RFDLib.GUI.Settings.TDynamicLabelEditorPair RSBUSOUT = new RFDLib.GUI.Settings.TDynamicLabelEditorPair(lblRSBUSOUT, RGPO1_3SBUSOUT, + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair[] + { + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("RGPO1_3SBUSOUT", "GPO1_3SBUSOUT"), + new RFDLib.GUI.Settings.TDynamicLabelEditorPair.TSettingNameLabelTextPair("RGPO1_1SBUSOUT", "GPO1_1SBUSOUT"), + }); + _DynamicLabelEditorPairRegister = new RFDLib.GUI.Settings.TDynamicLabelEditorPairRegister(new RFDLib.GUI.Settings.TDynamicLabelEditorPair[] + { + SBUSIN, RSBUSIN, SBUSOUT, RSBUSOUT, + }); + + _LocalLabelEditorPairs.Add(lblNODEID, NODEID, toolTip1); + _LocalLabelEditorPairs.Add(lblDESTID, DESTID, toolTip1); + _LocalLabelEditorPairs.Add(lblTX_ENCAP_METHOD, TX_ENCAP_METHOD, toolTip1); + _LocalLabelEditorPairs.Add(lblRX_ENCAP_METHOD, RX_ENCAP_METHOD, toolTip1); + _LocalLabelEditorPairs.Add(lblMAX_DATA, MAX_DATA, toolTip1); + _LocalLabelEditorPairs.Add(lblMAX_RETRIES, MAX_RETRIES, toolTip1); + _LocalLabelEditorPairs.Add(lblGLOBAL_RETRIES, GLOBAL_RETRIES, toolTip1); + _LocalLabelEditorPairs.Add(lblSER_BRK_DETMS, SER_BRK_DETMS, toolTip1); + _LocalLabelEditorPairs.Add(label54, FSFRAMELOSS, toolTip1); + _LocalLabelEditorPairs.Add(lblNETID, NETID, toolTip1); + _LocalLabelEditorPairs.Add(lblTXPOWER, TXPOWER, toolTip1); + _LocalLabelEditorPairs.Add(lblECC, ECC, toolTip1); + _LocalLabelEditorPairs.Add(lblMAVLINK, MAVLINK, toolTip1); + _LocalLabelEditorPairs.Add(lblOPPRESEND, OPPRESEND, toolTip1); + _LocalLabelEditorPairs.Add(lblGPI1_1R_CIN, GPI1_1R_CIN, toolTip1); + _LocalLabelEditorPairs.Add(lblGPO1_1R_COUT, GPO1_1R_COUT, toolTip1); + _LocalLabelEditorPairs.Add(lblGPO1_3STATLED, GPO1_3STATLED, toolTip1); + _LocalLabelEditorPairs.Add(lblGPI1_2AUXIN, GPI1_2AUXIN, toolTip1); + _LocalLabelEditorPairs.Add(lblGPO1_3AUXOUT, GPO1_3AUXOUT, toolTip1); + _LocalLabelEditorPairs.Add(lblMIN_FREQ, MIN_FREQ, toolTip1); + _LocalLabelEditorPairs.Add(lblMAX_FREQ, MAX_FREQ, toolTip1); + _LocalLabelEditorPairs.Add(lblNUM_CHANNELS, NUM_CHANNELS, toolTip1); + _LocalLabelEditorPairs.Add(lblDUTY_CYCLE, DUTY_CYCLE, toolTip1); + _LocalLabelEditorPairs.Add(lblLBT_RSSI, LBT_RSSI, toolTip1); + _LocalLabelEditorPairs.Add(lblRTSCTS, RTSCTS, toolTip1); + _LocalLabelEditorPairs.Add(lblMAX_WINDOW, MAX_WINDOW, toolTip1); + _LocalLabelEditorPairs.Add(lblENCRYPTION_LEVEL, ENCRYPTION_LEVEL, toolTip1); + _LocalLabelEditorPairs.Add(lblGPO1_0TXEN485, GPO1_0TXEN485, toolTip1); + _LocalLabelEditorPairs.Add(lblGPIO1_1FUNC, GPIO1_1FUNC, toolTip1); + + _RemoteLabelEditorPairs.Add(lblRNODEID, RNODEID, toolTip1); + _RemoteLabelEditorPairs.Add(lblRDESTID, RDESTID, toolTip1); + _RemoteLabelEditorPairs.Add(lblRTX_ENCAP_METHOD, RTX_ENCAP_METHOD, toolTip1); + _RemoteLabelEditorPairs.Add(lblRRX_ENCAP_METHOD, RRX_ENCAP_METHOD, toolTip1); + _RemoteLabelEditorPairs.Add(lblRMAX_DATA, RMAX_DATA, toolTip1); + _RemoteLabelEditorPairs.Add(lblRMAX_RETRIES, RMAX_RETRIES, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGLOBAL_RETRIES, RGLOBAL_RETRIES, toolTip1); + _RemoteLabelEditorPairs.Add(lblRSER_BRK_DETMS, RSER_BRK_DETMS, toolTip1); + _RemoteLabelEditorPairs.Add(lblRFSFRAMELOSS, RFSFRAMELOSS, toolTip1); + _RemoteLabelEditorPairs.Add(lblRNETID, RNETID, toolTip1); + _RemoteLabelEditorPairs.Add(lblRTXPOWER, RTXPOWER, toolTip1); + _RemoteLabelEditorPairs.Add(lblRECC, RECC, toolTip1); + _RemoteLabelEditorPairs.Add(lblRMAVLINK, RMAVLINK, toolTip1); + _RemoteLabelEditorPairs.Add(lblROPPRESEND, ROPPRESEND, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGPI1_1R_CIN, RGPI1_1R_CIN, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGPO1_1R_COUT, RGPO1_1R_COUT, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGPO1_3STATLED, RGPO1_3STATLED, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGPI1_2AUXIN, RGPI1_2AUXIN, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGPO1_3AUXOUT, RGPO1_3AUXOUT, toolTip1); + _RemoteLabelEditorPairs.Add(lblRMIN_FREQ, RMIN_FREQ, toolTip1); + _RemoteLabelEditorPairs.Add(lblRMAX_FREQ, RMAX_FREQ, toolTip1); + _RemoteLabelEditorPairs.Add(lblRNUM_CHANNELS, RNUM_CHANNELS, toolTip1); + _RemoteLabelEditorPairs.Add(lblRDUTY_CYCLE, RDUTY_CYCLE, toolTip1); + _RemoteLabelEditorPairs.Add(lblRLBT_RSSI, RLBT_RSSI, toolTip1); + _RemoteLabelEditorPairs.Add(lblRRTSCTS, RRTSCTS, toolTip1); + _RemoteLabelEditorPairs.Add(lblRMAX_WINDOW, RMAX_WINDOW, toolTip1); + _RemoteLabelEditorPairs.Add(lblRENCRYPTION_LEVEL, RENCRYPTION_LEVEL, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGPO1_0TXEN485, RGPO1_0TXEN485, toolTip1); + _RemoteLabelEditorPairs.Add(lblRGPIO1_1FUNC, RGPIO1_1FUNC, toolTip1); + this.Disposed += DisposedEvtHdlr; } + static void getTelemPortWithRadio(ref ICommsSerial comPort) + { + // try telem1 + + comPort = new MAVLinkSerialPort(MainV2.comPort, (int)MAVLink.SERIAL_CONTROL_DEV.TELEM1); + + comPort.ReadTimeout = 4000; + + comPort.Open(); + } + + public static bool Connect(ref ICommsSerial Port) + { + try + { + if (MainV2.comPort.BaseStream.PortName.Contains("TCP")) + { + Port = new TcpSerial(); + Port.BaudRate = MainV2.comPort.BaseStream.BaudRate; + Port.ReadTimeout = 4000; + Port.Open(); + } + else + { + Port = new SerialPort(); + + if (MainV2.comPort.BaseStream.IsOpen) + { + getTelemPortWithRadio(ref Port); + } + else + { + Port.PortName = MainV2.comPort.BaseStream.PortName; + Port.BaudRate = MainV2.comPort.BaseStream.BaudRate; + } + + Port.ReadTimeout = 4000; + + Port.Open(); + } + + return true; + } + catch + { + return false; + } + } + + public void Connect() { var S = GetSession(); @@ -128,11 +278,12 @@ public void Connect() public void Disconnect() { var S = _Session; - if (S != null) + if ((S != null) && S.Port.IsOpen) { S.PutIntoTransparentMode(); } EndSession(); + MissionPlanner.Radio.ComPort.FinishedWithComPortForSiKRadio(); } void DisposedEvtHdlr(object sender, EventArgs e) @@ -178,63 +329,56 @@ private void RestoreAllDefaultCBObjects() } } - private bool getFirmware(Uploader.Board device, bool custom = false) + private bool getFirmware(Uploader.Board device, RFD.RFD900.RFD900 RFD900, bool custom = false) { if (custom) { - return getFirmwareLocal(device == Uploader.Board.DEVICE_ID_RFD900X); + return getFirmwareLocal(RFD900); } + + firmwarefile = Path.GetTempFileName(); - if (device == Uploader.Board.DEVICE_ID_HB1060) - { - if (beta) - { - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/beta/radio~hb1060.ihx", firmwarefile); - } - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/stable/radio~hb1060.ihx", - firmwarefile); - } if (device == Uploader.Board.DEVICE_ID_HM_TRP) { if (beta) { - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/beta/radio~hm_trp.ihx", firmwarefile); + return Download.getFilefromNet("http://firmware.ardupilot.org/SiK/beta/radio~hm_trp.ihx", firmwarefile); } - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/stable/radio~hm_trp.ihx", + return Download.getFilefromNet("http://firmware.ardupilot.org/SiK/stable/radio~hm_trp.ihx", firmwarefile); } if (device == Uploader.Board.DEVICE_ID_RFD900) { if (beta) { - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/beta/radio~rfd900.ihx", firmwarefile); + return Download.getFilefromNet("http://firmware.ardupilot.org/SiK/beta/radio~rfd900.ihx", firmwarefile); } - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/stable/radio~rfd900.ihx", firmwarefile); + return Download.getFilefromNet("http://firmware.ardupilot.org/SiK/stable/radio~rfd900.ihx", firmwarefile); } if (device == Uploader.Board.DEVICE_ID_RFD900A) { if (beta) { - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/beta/radio~rfd900a.ihx", + return Download.getFilefromNet("http://firmware.ardupilot.org/SiK/beta/radio~rfd900a.ihx", firmwarefile); } - return Download.getFilefromNet("https://firmware.ardupilot.org/SiK/stable/radio~rfd900a.ihx", firmwarefile); + return Download.getFilefromNet("http://firmware.ardupilot.org/SiK/stable/radio~rfd900a.ihx", firmwarefile); } if (device == Uploader.Board.DEVICE_ID_RFD900U) { if (beta) { - return Download.getFilefromNet("https://files.rfdesign.com.au/Files/firmware/MPSiK%20V2.6%20rfd900u.ihx", firmwarefile); + return Download.getFilefromNet("http://files.rfdesign.com.au/Files/firmware/MPSiK%20V2.6%20rfd900u.ihx", firmwarefile); } - return Download.getFilefromNet("https://files.rfdesign.com.au/Files/firmware/RFDSiK%20V1.9%20rfd900u.ihx", firmwarefile); + return Download.getFilefromNet("http://files.rfdesign.com.au/Files/firmware/RFDSiK%20V1.9%20rfd900u.ihx", firmwarefile); } if (device == Uploader.Board.DEVICE_ID_RFD900P) { if (beta) { - return Download.getFilefromNet("https://files.rfdesign.com.au/Files/firmware/MPSiK%20V2.6%20rfd900p.ihx", firmwarefile); + return Download.getFilefromNet("http://files.rfdesign.com.au/Files/firmware/MPSiK%20V2.6%20rfd900p.ihx", firmwarefile); } - return Download.getFilefromNet("https://files.rfdesign.com.au/Files/firmware/RFDSiK%20V1.9%20rfd900p.ihx", firmwarefile); + return Download.getFilefromNet("http://files.rfdesign.com.au/Files/firmware/RFDSiK%20V1.9%20rfd900p.ihx", firmwarefile); } if (device == Uploader.Board.DEVICE_ID_RFD900X) { @@ -247,11 +391,22 @@ private bool getFirmware(Uploader.Board device, bool custom = false) /// Loads a local firmware file after prompting user for file. /// /// - private bool getFirmwareLocal(bool Bin) + private bool getFirmwareLocal(RFD.RFD900.RFD900 RFD900) { using (var openFileDialog1 = new OpenFileDialog()) { - openFileDialog1.Filter = Bin ? "Firmware|*.bin" : "Firmware|*.hex;*.ihx"; + string Filter = "Firmware|"; + string[] Exts = RFD900.FirmwareFileNameExtensions; + for (int n = 0; n < Exts.Length; n++) + { + if (n != 0) + { + Filter += ";"; + } + Filter += "*." + Exts[n]; + } + + openFileDialog1.Filter = Filter; openFileDialog1.RestoreDirectory = true; openFileDialog1.Multiselect = false; @@ -259,7 +414,8 @@ private bool getFirmwareLocal(bool Bin) { try { - File.Copy(openFileDialog1.FileName, firmwarefile, true); + firmwarefile = openFileDialog1.FileName; + //File.Copy(openFileDialog1.FileName, firmwarefile, true); } catch (Exception ex) { @@ -291,76 +447,6 @@ private void Sleep(int mstimeout, ICommsSerial comPort = null) } } - /// - /// Tries to upload firmware to the modem using xmodem mode (after prompting user for file) - /// - /// - /// - bool upload_xmodem(ICommsSerial comPort) - { - // try xmodem mode - // xmodem - short cts to ground - try - { - uploader_LogEvent("Trying XModem Mode"); - //comPort.BaudRate = 57600; - comPort.BaudRate = MainV2.comPort.BaseStream.BaudRate; - comPort.ReadTimeout = 1000; - - Thread.Sleep(2000); - var tempd = comPort.ReadExisting(); - Console.WriteLine(tempd); - comPort.Write("U"); - Thread.Sleep(1000); - var resp1 = Serial_ReadLine(comPort); // echo - var resp2 = Serial_ReadLine(comPort); // echo 2 - var tempd2 = comPort.ReadExisting(); // posibly bootloader info / use to sync - // identify - comPort.Write("i"); - // responce is rfd900.... - var resp3 = Serial_ReadLine(comPort); //echo - var resp4 = Serial_ReadLine(comPort); // newline - var resp5 = Serial_ReadLine(comPort); // bootloader info - uploader_LogEvent(resp5); - if (resp5.Contains("RFD900")) - { - // start upload - comPort.Write("u"); - var resp6 = Serial_ReadLine(comPort); // echo - var resp7 = Serial_ReadLine(comPort); // Ready - if (resp7.Contains("Ready")) - { - comPort.ReadTimeout = 3500; - // responce is C - var isC = comPort.ReadByte(); - var temp = comPort.ReadExisting(); - if (isC == 'C') - { - if (getFirmwareLocal(false)) - { - - XModem.LogEvent += uploader_LogEvent; - XModem.ProgressEvent += uploader_ProgressEvent; - // start file send - XModem.Upload(firmwarefile, - comPort); - XModem.LogEvent -= uploader_LogEvent; - XModem.ProgressEvent -= uploader_ProgressEvent; - return true; - } - return false; - } - } - } - } - catch (Exception ex2) - { - log.Error(ex2); - } - - return false; - } - private void BUT_upload_Click(object sender, EventArgs e) { ProgramFirmware(false); @@ -370,7 +456,7 @@ private void iHex_ProgressEvent(double completed) { try { - Progressbar.Value = (int)(completed * 100); + Progressbar.Value = (int) (completed*100); Application.DoEvents(); } catch @@ -420,7 +506,7 @@ private void uploader_ProgressEvent(double completed) { try { - Progressbar.Value = (int)Math.Min(completed * 100, 100); + Progressbar.Value = (int)Math.Min (completed*100,100); Application.DoEvents(); } catch @@ -435,305 +521,493 @@ string GetParamNumber(string Part1) return Part1.Substring(S + 1); } - private void BUT_savesettings_Click(object sender, EventArgs e) + int GetValueFromControl(Control control) { - //EndSession(); - var Session = GetSession(); - - if (Session == null) + if (control.GetType() == typeof(CheckBox)) { - return; + return ((CheckBox)control).Checked ? 1 : 0; } + else if (control is ComboBox) + { + string CBValue = GetCBValue((ComboBox)control); - EnableConfigControls(false); - EnableProgrammingControls(false); - lbl_status.Text = "Connecting"; + int Result; - if (Session.PutIntoATCommandMode() == RFD.RFD900.TSession.TMode.AT_COMMAND) + if (int.TryParse(CBValue, out Result)) + { + return Result; + } + else + { + return 0; + } + } + else { - // cleanup - doCommand(Session.Port, "AT&T", false, 1); + return 0; + } + } - Session.Port.DiscardInBuffer(); + class TBaseSetting + { + } - lbl_status.Text = "Doing Command"; + class TSetting : TBaseSetting + { + public T Value; + public TSetting(T Value) + { + this.Value = Value; + } + } - if (RTI.Text != "") + TBaseSetting GetSettingFromControl(Control control) + { + if (control.GetType() == typeof(CheckBox)) + { + return new TSetting(((CheckBox)control).Checked ? 1 : 0); + } + else if (control is TextBox) + { + return new TSetting(control.Text); + } + else if (control is ComboBox) + { + int x; + + if (int.TryParse(GetCBValue((ComboBox)control), out x)) { - // remote - var answer = doCommand(Session.Port, "RTI5", true); + return new TSetting(x); + } + } - var items = answer.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); + return null; + } - foreach (var item in items) + /// + /// Returns whether x is different to y. + /// + /// + /// + /// + bool GetIsDifferent(RFD.RFD900.TBaseSetting x, TBaseSetting y) + { + if (y is TSetting) + { + return x is RFD.RFD900.TSetting && ((RFD.RFD900.TSetting)x).Value != ((TSetting)y).Value; + } + else if (y is TSetting) + { + return x is RFD.RFD900.TTextSetting && ((RFD.RFD900.TTextSetting)x).Text != ((TSetting)y).Value; + } + else + { + return false; + } + } + + /// + /// Make a clone of the given original setting. Update it's value with Value, and return it. + /// + /// The original setting. Must not be null. + /// The new value for the setting. Must not be null. + /// The new cloned setting with updated value. Never null. + RFD.RFD900.TBaseSetting UpdateSetting(RFD.RFD900.TBaseSetting Orig, TBaseSetting Value) + { + if (Value is TSetting) + { + RFD.RFD900.TSetting y = (RFD.RFD900.TSetting)Orig.Clone(); + y.Value = ((TSetting)Value).Value; + return y; + } + else + { + RFD.RFD900.TTextSetting y = (RFD.RFD900.TTextSetting)Orig.Clone(); + y.Text = ((TSetting)Value).Value; + return y; + } + } + + /// + /// Figure out which settings in the GUI have different values to the given original settings. + /// Return a list of the settings which have changed, and their new values. + /// + /// The original settings and their values. Must not be null. + /// The relevant groupbox. Must not be null. + /// true if the remote modem, false if the local modem. + /// + Dictionary GetUpdatedSettingsFromGroupBox( + Dictionary Orig, GroupBox GB, + bool Remote) + { + Dictionary Result = new Dictionary(); + + foreach (var kvp in Orig) + { + var control = FindControlInGroupBox(GB, (Remote ? "R" : "") + kvp.Key); + + if (control != null) + { + var S = GetSettingFromControl(control); + + if (S != null) { - //if (item.StartsWith("S")) + if (GetIsDifferent(kvp.Value, S)) { - int multipoint_fix = -1; - if (item.StartsWith("[")) + Result[kvp.Key] = UpdateSetting(kvp.Value, S); + } + } + } + } + + return Result; + } + + /// + /// Check that the settings in the given groupbox are valid. If invalid, shows a message box listing the issues. + /// + /// + /// Whether it's for the remote modem. + /// The settings read from the modem. Must not be null. + /// true if valid, false if invalid. + bool CheckSettingsValid(GroupBox GB, bool Remote, + Dictionary Orig) + { + var Changed = GetUpdatedSettingsFromGroupBox(Orig, GB, Remote); + + Dictionary NewSettings = new Dictionary(Orig); + RFDLib.Collections.Update(NewSettings, Changed); + + RFD.RFD900.TSettings Settings = new RFD.RFD900.TSettings(NewSettings); + + var Errors = Settings.CheckValid(); + + if (Errors.Length == 0) + { + return true; + } + else + { + string ErrorMsg = Remote ? "Remote" : "Local" + " settings invalid, operation aborted:"; + + foreach (var em in Errors) + { + ErrorMsg += "\n\t" + em; + } + + MsgBox.CustomMessageBox.Show(ErrorMsg); + + return false; + } + } + + /// + /// Save settings from GUI to a modem. + /// + /// The relevant groupbox. Must not be null. + /// true if remote modem, false if local. + /// The serial port to use. Must not be null. + /// The settings read from the modem. These are not modified by this function. Must not be null. + void SaveSettingsFromGroupBox(GroupBox GB, bool Remote, ICommsSerial Port, + Dictionary Orig) + { + var Changed = GetUpdatedSettingsFromGroupBox(Orig, GB, Remote); + string CommandPrefix = Remote ? "R" : "A"; + + foreach (var kvp in Changed) + { + if (!kvp.Key.Contains("FORMAT")) + { + var cmdanswer = doCommand(Port, + CommandPrefix + "T" + kvp.Value.Designator + "=" + kvp.Value.GetValueAsString(), + kvp.Value.Designator.Contains("&E")); + + if (cmdanswer.Contains("OK")) + { + if (kvp.Key.Contains("GPO1_1R_COUT") || + kvp.Key.Contains("GPO1_3SBUSOUT")) + { + if (kvp.Value is RFD.RFD900.TSetting && ((RFD.RFD900.TSetting)kvp.Value).Value == 1) { - multipoint_fix = item.IndexOf(']') + 1; + //Also need to set RTPO. + cmdanswer = doCommand(Port, + CommandPrefix + "TPO=1"); } - var mod_item = item; - if (multipoint_fix > 0 && item.Length > multipoint_fix) + else { - mod_item = item.Substring(multipoint_fix).Trim(); + cmdanswer = doCommand(Port, + CommandPrefix + "TPI=1"); } - var values = mod_item.Split(':', '='); + } + else if (kvp.Key.Contains("GPI1_1R_CIN") || + kvp.Key.Contains("GPO1_3SBUSIN")) + { + //Also need to set RTPI. + cmdanswer = doCommand(Port, + CommandPrefix + "TPI=1"); + } + if (!cmdanswer.Contains("OK")) + { + MsgBox.CustomMessageBox.Show("Set Command error"); + } - if (values.Length == 3) - { - values[1] = values[1].Replace("/", "_"); - - var controls = groupBoxRemote.Controls.Find("R" + values[1].Trim(), true); - - if (controls.Length > 0) - { - if (controls[0].GetType() == typeof(CheckBox)) - { - var value = ((CheckBox)controls[0]).Checked ? "1" : "0"; - - if (value != values[2].Trim()) - { - var cmdanswer = doCommand(Session.Port, - "RTS" + values[0].Trim().TrimStart('S') + "=" + value); - - if (cmdanswer.Contains("OK")) - { - } - else - { - if (values[1] == "ENCRYPTION_LEVEL") - { - // set this on the local radio as well. - doCommand(Session.Port, "ATS" + values[0].Trim().TrimStart('S') + "=" + value); - // both radios should now be using the default key - } - else - { - MsgBox.CustomMessageBox.Show("Set Command error"); - } - } - } - } - else if (!controls[0].Name.Contains("FORMAT") && controls[0] is TextBox) - { - if (controls[0].Text != values[2].Trim()) - { - var cmdanswer = doCommand(Session.Port, - "RTS" + values[0].Trim().TrimStart('S') + "=" + controls[0].Text); - - if (cmdanswer.Contains("OK")) - { - } - else - { - MsgBox.CustomMessageBox.Show("Set Command error"); - } - } - } - else if (controls[0].Name.Contains("MAVLINK")) // - { - if (((ComboBox)controls[0]).SelectedValue.ToString() != values[2].Trim()) - { - var cmdanswer = doCommand(Session.Port, - "RTS" + values[0].Trim().TrimStart('S') + "=" + ((ComboBox) controls[0]).SelectedValue); - - if (cmdanswer.Contains("OK")) - { - } - else - { - MsgBox.CustomMessageBox.Show("Set Command error"); - } - } - } - else if (controls[0] is ComboBox) - { - string CBValue = GetCBValue((ComboBox)controls[0]); - if (CBValue != values[2].Trim()) - { - var cmdanswer = doCommand(Session.Port, - "RTS" + values[0].Trim().TrimStart('S') + "=" + CBValue); - - if (cmdanswer.Contains("OK")) - { - } - else - { - MsgBox.CustomMessageBox.Show("Set Command error"); - } - } - } - } - } + } + else + { + if (Remote && (kvp.Key == "ENCRYPTION_LEVEL")) + { + // set this on the local radio as well. + doCommand(Port, "AT" + kvp.Value.Designator + "=" + kvp.Value.GetValueAsString()); + // both radios should now be using the default key + } + else + { + MsgBox.CustomMessageBox.Show("Set Command error"); } } + } + } + } - Sleep(100); + /// + /// Returns whether encryption is enabled, as per the given combo box. + /// + /// The combo box which is used to set encryption level. Must not be null. + /// true if enabled, otherwise false. + bool GetIsEncryptionEnabled(ComboBox CB) + { + return GetEncryptionLevelValue(CB) != 0; + } + + /// + /// Get the max encryption key length in hex numerals. + /// + /// The encryption level setting combo box. Must not be null. + /// The max encryption key length, in hex numerals. + int GetEncryptionMaxKeyLength(ComboBox CB) + { + if (CB.Text.Contains("b")) + { + var Parts = CB.Text.Split('b'); + if (Parts.Length >= 1) + { + int QTYBits; + + if (int.TryParse(Parts[0], out QTYBits)) + { + return QTYBits / 4; + } } - Session.Port.DiscardInBuffer(); + return 0; + } + else + { + if (CB.Text == "0") + { + return 0; + } + else { - //local - string answer = ""; - for (int n = 0; n < 5; n++) + return 32; + } + } + } + + /// + /// Get the encryption level setting number value. + /// + /// The combo box to get number value for. Must not be null. + /// The level setting number value. + int GetEncryptionLevelValue(ComboBox CB) + { + if (CB.Tag != null) + { + RFD.RFD900.TSetting Setting = (RFD.RFD900.TSetting)CB.Tag; + + if (Setting.Options != null) + { + foreach (var O in Setting.Options) { - answer = doCommand(Session.Port, "ATI5", true); - if (answer.Length != 0) + if (O.OptionName == CB.Text) { - break; + return O.Value; } } + } + } + + int Result; + if (int.TryParse(CB.Text, out Result)) + { + return Result; + } + return 0; + } + + private void BUT_savesettings_Click(object sender, EventArgs e) + { + if ( + ( + (RTI.Text == "") || + CheckSettingsValid + ( + groupBoxRemote, true, + RFDLib.Collections.Translate(_RemoteSettings.Settings, (x) => (RFD.RFD900.TBaseSetting)x) + ) + ) + && + CheckSettingsValid + ( + groupBoxLocal, false, + RFDLib.Collections.Translate(_LocalSettings.Settings, (x) => (RFD.RFD900.TBaseSetting)x) + ) + ) + { + + //EndSession(); + var Session = GetSession(); + + if (Session == null) + { + return; + } + + List EnabledControls = new List(); + foreach (Control C in groupBoxLocal.Controls) + { + if (C.Enabled) + { + EnabledControls.Add(C); + } + } + foreach (Control C in groupBoxRemote.Controls) + { + if (C.Enabled) + { + EnabledControls.Add(C); + } + } + + EnableConfigControls(false, false); + EnableProgrammingControls(false); + lbl_status.Text = "Connecting"; + + if (Session.PutIntoATCommandMode() == RFD.RFD900.TSession.TMode.AT_COMMAND) + { + // cleanup + doCommand(Session.Port, "AT&T", false, 1); + + Session.Port.DiscardInBuffer(); + + lbl_status.Text = "Doing Command"; - var items = answer.Split(new[] { '\n' }, StringSplitOptions.RemoveEmptyEntries); - foreach (var item in items) + if (RTI.Text != "") { - //if (item.StartsWith("S")) - { - var values = item.Split(':', '='); + // remote + var answer = doCommand(Session.Port, "RTI5", true); - if (values.Length == 3) - { - values[1] = values[1].Replace("/", "_"); - - var controls = groupBoxLocal.Controls.Find(values[1].Trim(), true); - - if (controls.Length > 0) - { - if (controls[0].GetType() == typeof(CheckBox)) - { - var value = ((CheckBox)controls[0]).Checked ? "1" : "0"; - - if (value != values[2].Trim()) - { - var cmdanswer = doCommand(Session.Port, - "ATS" + GetParamNumber(values[0]) + "=" + value); - - if (cmdanswer.Contains("OK")) - { - } - else - { - MsgBox.CustomMessageBox.Show("Set Command error"); - } - } - } - else if (controls[0] is TextBox) - { - } - else if (controls[0].Name.Contains("MAVLINK")) // - { - if (((ComboBox)controls[0]).SelectedValue.ToString() != values[2].Trim()) - { - var cmdanswer = doCommand(Session.Port, - "ATS" + GetParamNumber(values[0]) + "=" + ((ComboBox) controls[0]).SelectedValue); - - if (cmdanswer.Contains("OK")) - { - } - else - { - MsgBox.CustomMessageBox.Show("Set Command error"); - } - } - } - else if (controls[0] is ComboBox) - { - string CBValue = GetCBValue((ComboBox)controls[0]); - if (CBValue != values[2].Trim()) - { - var cmdanswer = doCommand(Session.Port, - "ATS" + GetParamNumber(values[0]) + "=" + CBValue); - - if (cmdanswer.Contains("OK")) - { - } - else - { - MsgBox.CustomMessageBox.Show("Set Command error"); - } - } - } - } - } - } + SaveSettingsFromGroupBox(groupBoxRemote, true, Session.Port, + RFDLib.Collections.Translate(_RemoteSettings.Settings, (x) => (RFD.RFD900.TBaseSetting)x)); + + Sleep(100); } - // set encryption keys at the same time, so if we are enabled we dont lose comms. - // we have set encryption to on for both radios, they will be using the default key atm - if (RENCRYPTION_LEVEL.Checked) + Session.Port.DiscardInBuffer(); { - if (System.Text.RegularExpressions.Regex.IsMatch(txt_Raeskey.Text, @"\A\b[0-9a-fA-F]+\b\Z") - && (txt_Raeskey.Text.Length <= 32)) + //local + string answer = ""; + for (int n = 0; n < 5; n++) { - doCommand(Session.Port, "RT&E=" + txt_Raeskey.Text.PadRight(32, '0'), true); + answer = doCommand(Session.Port, "ATI5", true); + if (answer.Length != 0) + { + break; + } } - else + + SaveSettingsFromGroupBox(groupBoxLocal, false, Session.Port, + RFDLib.Collections.Translate(_LocalSettings.Settings, (x) => (RFD.RFD900.TBaseSetting)x)); + + // set encryption keys at the same time, so if we are enabled we dont lose comms. + // we have set encryption to on for both radios, they will be using the default key atm + if (GetIsEncryptionEnabled(RENCRYPTION_LEVEL)) { - //Complain that encryption key invalid. - lbl_status.Text = "Fail"; - MsgBox.CustomMessageBox.Show("Encryption key not valid hex number <= 32 hex numerals"); + int MaxKeyLength = GetEncryptionMaxKeyLength(RENCRYPTION_LEVEL); + RAESKEY.Text = RAESKEY.Text.Trim(); + + if (System.Text.RegularExpressions.Regex.IsMatch(RAESKEY.Text, @"\A\b[0-9a-fA-F]+\b\Z") + && (RAESKEY.Text.Length <= MaxKeyLength)) + { + doCommand(Session.Port, "RT&E=" + RAESKEY.Text.PadRight(MaxKeyLength, '0'), true); + } + else + { + //Complain that encryption key invalid. + lbl_status.Text = "Fail"; + MsgBox.CustomMessageBox.Show("Encryption key not valid hex number <= " + MaxKeyLength.ToString() + " hex numerals"); + } } - } - if (ENCRYPTION_LEVEL.Checked) - { - if (System.Text.RegularExpressions.Regex.IsMatch(txt_aeskey.Text, @"\A\b[0-9a-fA-F]+\b\Z") - && (txt_aeskey.Text.Length <= 32)) + if (GetIsEncryptionEnabled(ENCRYPTION_LEVEL)) { - doCommand(Session.Port, "AT&E=" + txt_aeskey.Text.PadRight(32, '0'), true); + int MaxKeyLength = GetEncryptionMaxKeyLength(ENCRYPTION_LEVEL); + AESKEY.Text = AESKEY.Text.Trim(); + + if (System.Text.RegularExpressions.Regex.IsMatch(AESKEY.Text, @"\A\b[0-9a-fA-F]+\b\Z") + && (AESKEY.Text.Length <= MaxKeyLength)) + { + doCommand(Session.Port, "AT&E=" + AESKEY.Text.PadRight(MaxKeyLength, '0'), true); + } + else + { + //Complain that encryption key invalid. + lbl_status.Text = "Fail"; + MsgBox.CustomMessageBox.Show("Encryption key not valid hex number <= " + MaxKeyLength.ToString() + " hex numerals"); + } } - else + + + if (RTI.Text != "") { - //Complain that encryption key invalid. - lbl_status.Text = "Fail"; - MsgBox.CustomMessageBox.Show("Encryption key not valid hex number <= 32 hex numerals"); - } - } + // write it + doCommand(Session.Port, "RT&W"); + // return to normal mode + doCommand(Session.Port, "RTZ"); + } - if (RTI.Text != "") - { // write it - doCommand(Session.Port, "RT&W"); + var cmdwriteanswer = doCommand(Session.Port, "AT&W"); + if (!cmdwriteanswer.Contains("OK")) + { + MsgBox.CustomMessageBox.Show("Failed to save parameters"); + } // return to normal mode - doCommand(Session.Port, "RTZ"); - } - - // write it - var cmdwriteanswer = doCommand(Session.Port, "AT&W"); - if (!cmdwriteanswer.Contains("OK")) - { - MsgBox.CustomMessageBox.Show("Failed to save parameters"); + doCommand(Session.Port, "ATZ"); } + lbl_status.Text = "Done"; + EnableConfigControls(true, true); + } + else + { // return to normal mode doCommand(Session.Port, "ATZ"); - } - - lbl_status.Text = "Done"; - } - else - { - // return to normal mode - doCommand(Session.Port, "ATZ"); - lbl_status.Text = "Fail"; - MsgBox.CustomMessageBox.Show("Failed to enter command mode"); - } + lbl_status.Text = "Fail"; + MsgBox.CustomMessageBox.Show("Failed to enter command mode"); + EnableConfigControls(true, false); + } - //Need to do this because modem rebooted. - Session.PutIntoATCommandModeAssumingInTransparentMode(); + //Need to do this because modem rebooted. + Session.PutIntoATCommandModeAssumingInTransparentMode(); - EnableConfigControls(true); - EnableProgrammingControls(true); + EnableProgrammingControls(true); - if (GetCommsSerialAlt == null) - { - EndSessionClosePort(); + UpdateSetPPMFailSafeButtons(); } } @@ -798,23 +1072,29 @@ public static IEnumerable Range(int start, int step, int end) } } - - private bool SetupCBWithSetting(ComboBox CB, Dictionary Settings, - string Value, bool Remote) + private void SetupCBWithDefaultEncryptionOptions(ComboBox CB) { - string SettingName; + CB.Tag = null; + CB.DataSource = Range(0, 1, 1); + CB.Text = "0"; + } - if (Remote) - { - SettingName = CB.Name.Substring(1); - } - else - { - SettingName = CB.Name; - } - if (Settings.ContainsKey(SettingName)) + /// + /// Set the given combo box to use the corresponding setting in the given dictionary of + /// settings. If no corresponding setting exists in that dictionary, just set it to the + /// given value. + /// + /// The combo box. Must not be null. + /// The settings. Must not be null. + /// The string value representation to set it to. Must not be null. + /// true if it is a remote modem setting, false if local. + /// + private bool SetupCBWithSetting(ComboBox CB, Dictionary Settings, + string Value, bool Remote, string SettingName) + { + if (Settings.ContainsKey(SettingName) && Settings[SettingName] is RFD.RFD900.TSetting) { - var Setting = Settings[SettingName]; + var Setting = (RFD.RFD900.TSetting)Settings[SettingName]; if (Setting.Options != null) { //Use options. @@ -826,7 +1106,7 @@ private bool SetupCBWithSetting(ComboBox CB, Dictionary dict; + if (Simple) + { + dict = Enum.GetValues(typeof(mavlink_option_simple)) + .Cast() + .ToDictionary(t => (int)t, t => t.ToString()); + } + else + { + dict = Enum.GetValues(typeof(mavlink_option)) + .Cast() + .ToDictionary(t => (int)t, t => t.ToString()); + } + + CB.DataSource = dict.ToArray(); + } + + /// + /// Given an array of lines returned from ATI5 command from a modem, + /// remove the "[n]" from the start of the lines. The "[n]" is returned + /// from a modem at the start of the lines if it is running multipoint firmware. + /// + /// The raw lines returned from the modem. Must not be null. + /// The character index into the string immediately after + /// the initial "[n]", or -1 if not multipoint. + /// The modified lines. Never null. + string[] ModifyReturnedStringsForMultipoint(string[] items, int multipoint_fix) + { + string[] Result = new string[items.Length]; + + for (int n = 0; n < items.Length; n++) + { + Result[n] = items[n]; + if (multipoint_fix > 0 && items[n].Length > multipoint_fix) + { + Result[n] = items[n].Substring(multipoint_fix).Trim(); + } + } + + return Result; + } + + Control FindControlInGroupBox(GroupBox GB, string Name) + { + Control Result = _DynamicLabelEditorPairRegister.FindAndSetUpEditorWithSettingName(Name); + if (Result == null) + { + var Array = GB.Controls.Find(Name, true); + + if (Array.Length == 0) + { + return null; + } + else + { + return Array[0]; + } + } + else + { + return Result; + } + } + + /// + /// Returns whether it can be determined that the setting (from the given Settings) with the given + /// SettingName only has one value/option available (i.e. setting can't be changed). + /// + /// The dictionary of settings for the modem. Must not be null. + /// The setting name. Must not be null. + /// Returns true if it can be determined that the setting can only have one value, otherwise false. + bool GetDoesCheckboxHaveOnlyOneOption(Dictionary Settings, string SettingName) + { + if (Settings.ContainsKey(SettingName)) + { + var BaseSetting = Settings[SettingName]; + + if (BaseSetting is RFD.RFD900.TSetting) + { + RFD.RFD900.TSetting Setting = (RFD.RFD900.TSetting)BaseSetting; + + if (Setting.Options != null) + { + if (Setting.Options.Length == 1) + { + return true; + } + } + if (Setting.Range != null) + { + if (Setting.Range.GetOptions().Length == 1) + { + return true; + } + } + } + } + + return false; + } + + /// + /// Configure and return a spare editor if one is available. + /// + /// The name of the setting to get the editor for. Must not be null. + /// The setting to get the editor for. Must not be null. + /// Whether it is the remote set of settings. + /// A control to use, or null if none available. + Control GetSpareEditor(string ThisSetting, RFD.RFD900.TSetting Setting, bool Remote) + { + RFDLib.GUI.Settings.TLabelEditorPairRegister Reg = Remote ? _RemoteLabelEditorPairs : _LocalLabelEditorPairs; + Control Result = null; + string Description = Remote ? ThisSetting.Substring(1) : ThisSetting; + + if (_KnownNameDescriptions.ContainsKey(Description)) + { + Description = _KnownNameDescriptions[Description]; + } + + if (Setting.GetIsFlag()) + { + Result = Reg.GetSpareCheckbox(ThisSetting, Description); + } + + if (Result == null) + { + Result = Reg.GetSpareComboBox(ThisSetting, Description); + } + + return Result; + } + + /// + /// Update the given setting control with the given setting value + /// + /// The control to update. Must not be null. + /// All of the settings read from the modem. Must not be null. + /// The name of the setting the control is for. Must not be null. + /// The setting value as text. Must not be null. + /// true if remote modem, false if local modem. + /// true if failed, false if successful. + bool UpdateControlWithValue(Control control, + Dictionary Settings, + string SettingName, + string Value, + bool Remote) + { + bool SomeSettingsInvalid = false; + control.Parent.Enabled = true; + control.Enabled = true; + + if (control is CheckBox) + { + ((CheckBox)control).Checked = Value == "1"; + //If the setting can only have one option/value... + if (GetDoesCheckboxHaveOnlyOneOption(Settings, SettingName)) + { + //Disable the control + control.Enabled = false; + } + } + else if (control is TextBox) + { + ((TextBox)control).Text = Value; + } + else if (Settings.ContainsKey(SettingName) && Settings[SettingName] is RFD.RFD900.TSetting) + { + if (control.Name.Contains("MAVLINK") && + !(Settings.ContainsKey("MAVLINK") && + (Settings["MAVLINK"] is RFD.RFD900.TSetting && + ((RFD.RFD900.TSetting)Settings["MAVLINK"]).Options != null))) // + { + var ans = Enum.Parse(typeof(mavlink_option), Value); + ((ComboBox)control).Text = ans.ToString(); + } + else if (control is ComboBox) + { + if (!SetupCBWithSetting((ComboBox)control, Settings, + Value, Remote, SettingName)) + { + ((ComboBox)control).Text = Value; + if (((ComboBox)control).Text != Value) + { + SomeSettingsInvalid = true; + } + } + } + } + + return SomeSettingsInvalid; + } + + /// + /// Update the settings controls in the given groupbox with the given set of settings. + /// + /// The group box. Must not be null. + /// true if it is for the remote modem, false if for the local modem. + /// The settings. Must not be null. + void UpdateControlsWithValues(GroupBox GB, bool Remote, Dictionary Settings) + { + foreach (var kvp in Settings) + { + string EditorName = (Remote ? "R" : "") + kvp.Key; + + var control = FindControlInGroupBox(GB, EditorName); + + if (control != null) + { + UpdateControlWithValue(control, Settings, EditorName, kvp.Value.GetValueAsString(), Remote); + } + } + } + + /// + /// Given a groupbox containing a set of controls, load them with the given values and settings. + /// + /// The groupbox. Must not be null. + /// true if it is the remote groupbox, false if it is the local groupbox. + /// The lines returned by ATI5 command. Must not be null. + /// The settings parsed from the modem. Must not be null. + /// true if at least one setting had an invalid value, otherwise false. + bool SetUpControlsWithValues(GroupBox GB, bool Remote, string[] items, Dictionary Settings) + { + /*RFD900Tools.GUI.frmCfgTest frm = new RFD900Tools.GUI.frmCfgTest(); + RFD900Tools.GUI.TConfig Cfg = new RFD900Tools.GUI.TConfig(frm.GetControl()); + Cfg.Update(Settings, items); + frm.Show();*/ + + _LocalLabelEditorPairs.SetUp(new List(Settings.Keys)); + _RemoteLabelEditorPairs.SetUp(new List( + RFDLib.Array.CherryPickArray(Settings.Keys.ToArray(), + (n) => "R" + n))); + + bool SomeSettingsInvalid = false; + + foreach (var item in items) + { + var values = item.Split(new char[] { ':', '=' }, StringSplitOptions.RemoveEmptyEntries); + + if (item.Contains("ANT_MODE")) + { + System.Diagnostics.Debug.WriteLine("Ant mode"); + } + + if (values.Length == 3) + { + string SettingName = values[1].Trim(); + string EditorName = values[1].Replace("/", "_").Trim(); + + var control = FindControlInGroupBox(GB, (Remote ? "R" : "") + EditorName); + + if (control == null) + { + if (Settings.ContainsKey(SettingName) && Settings[SettingName] is RFD.RFD900.TSetting) + { + var Setting = (RFD.RFD900.TSetting)Settings[SettingName]; + if (Setting.Range != null || Setting.Options != null) + { + control = GetSpareEditor((Remote ? "R" : "") + EditorName, Setting, Remote); + } + } + } + + if (control != null) + { + GB.Enabled = true; + SomeSettingsInvalid |= UpdateControlWithValue(control, + RFDLib.Collections.Translate(Settings, (x) => (RFD.RFD900.TBaseSetting)x), + SettingName, values[2].Trim(), Remote); + } + } + else + { + log.Info("Odd config line :" + item); + } + } + + return SomeSettingsInvalid; } - void SetupComboForMavlink(ComboBox CB, bool Simple) + /// + /// Get the country code from the modem as a string, or "--" if unknown or not locked to country. + /// + /// The session. Must not be null. + /// The function to get the country code, given the modem object. Must not be null. + /// The country code string. + string GetCountryCodeFromSession(RFD.RFD900.TSession Session, + Func GetCC) { - Dictionary dict; - if (Simple) + RFD.RFD900.RFD900xux.TCountry CC; + var Mdm = Session.GetModemObject(); + + if (Mdm == null || !(Mdm is RFD.RFD900.RFD900xuxRevN) || + !RFD.RFD900.RFD900xux.GetIsCountryLocked(CC = GetCC((RFD.RFD900.RFD900xuxRevN)Mdm))) { - dict = Enum.GetValues(typeof(mavlink_option_simple)) - .Cast() - .ToDictionary(t => (int)t, t => t.ToString()); + return "--"; } else { - dict = Enum.GetValues(typeof(mavlink_option)) - .Cast() - .ToDictionary(t => (int)t, t => t.ToString()); + return CC.ToString(); } - - CB.DataSource = dict.ToArray(); } /// @@ -888,6 +1466,8 @@ void SetupComboForMavlink(ComboBox CB, bool Simple) /// private void BUT_getcurrent_Click(object sender, EventArgs e) { + //System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch(); + //SW.Start(); //EndSession(); var Session = GetSession(); @@ -896,38 +1476,62 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) return; } + _AlreadyInEncCheckChangedEvtHdlr = true; + ResetAllControls(groupBoxLocal); ResetAllControls(groupBoxRemote); + SetupCBWithDefaultEncryptionOptions(ENCRYPTION_LEVEL); + SetupCBWithDefaultEncryptionOptions(RENCRYPTION_LEVEL); - EnableConfigControls(false); + EnableConfigControls(false, false); EnableProgrammingControls(false); lbl_status.Text = "Connecting"; + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Putting into AT CMD mode"); + try { if (Session.PutIntoATCommandMode() == RFD.RFD900.TSession.TMode.AT_COMMAND) { + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done putting into AT CMD mode"); + bool SomeSettingsInvalid = false; // cleanup doCommand(Session.Port, "AT&T", false, 1); + /*Session.ATCClient.Timeout = 100; + Session.ATCClient.DoCommand("AT&T"); + Session.ATCClient.Timeout = 1000;*/ + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done AT&T cmd"); Session.Port.DiscardInBuffer(); lbl_status.Text = "Doing Command ATI & RTI"; //Set the text box to show the radio version - int multipoint_fix = -1; - var ati_str = doCommand(Session.Port, "ATI").Trim(); + int multipoint_fix = -1; //If this radio has multipoint firmware, the index within returned strings to use for returned values, otherwise -1. + var ati_str = doCommand(Session.Port, "ATI").Trim(); //Session.ATCClient.DoQuery("ATI", true);// doCommand(Session.Port, "ATI").Trim(); + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done ATI cmd"); + if (ati_str.StartsWith("[")) { multipoint_fix = ati_str.IndexOf(']') + 1; } ATI.Text = ati_str; + string LocalFWVer = RFD.RFD900.RFD900.ATIResponseToFWVersion(ati_str); + NumberStyles style = NumberStyles.Any; //Get the board frequency. - var freqstring = doCommand(Session.Port, "ATI3").Trim(); + var freqstring = doCommand(Session.Port, "ATI3").Trim(); //Session.ATCClient.DoQuery("ATI3", true);// doCommand(Session.Port, "ATI3").Trim(); + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done ATI3 cmd"); + + //Some multipoint firmware versions don't reply to ATI command with [n] at start of reply, but they do for ATI3 command, so check for [n] again... + if (multipoint_fix < 0 && freqstring.StartsWith("[")) + { + multipoint_fix = freqstring.IndexOf(']') + 1; + } + if (multipoint_fix > 0) { freqstring = freqstring.Substring(multipoint_fix).Trim(); @@ -938,15 +1542,16 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) var freq = (Uploader.Frequency) - Enum.Parse(typeof(Uploader.Frequency), - int.Parse(freqstring.ToLower().Replace("x", ""), style, CultureInfo.InvariantCulture) - .ToString()); + Enum.Parse(typeof (Uploader.Frequency), + int.Parse(freqstring.ToLower().Replace("x", ""), style).ToString()); ATI3.Text = freq.ToString(); style = NumberStyles.Any; - var boardstring = doCommand(Session.Port, "ATI2").Trim(); + var boardstring = doCommand(Session.Port, "ATI2").Trim(); //Session.ATCClient.DoQuery("ATI2", true);// doCommand(Session.Port, "ATI2").Trim(); + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done ATI2 cmd"); + if (multipoint_fix > 0) { boardstring = boardstring.Substring(multipoint_fix).Trim(); @@ -957,8 +1562,11 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) Session.Board = (Uploader.Board) - Enum.Parse(typeof(Uploader.Board), - int.Parse(boardstring.ToLower().Replace("x", ""), style, CultureInfo.InvariantCulture).ToString()); + Enum.Parse(typeof (Uploader.Board), + int.Parse(boardstring.ToLower().Replace("x", ""), style).ToString()); + + txtCountry.Text = GetCountryCodeFromSession(Session, + (m) => m.GetCountryCode()); ATI2.Text = Session.Board.ToString(); @@ -1003,19 +1611,19 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) // 8 and 9 if (freq == Uploader.Frequency.FREQ_915) { - MIN_FREQ.DataSource = Range(895000, 1000, 935000); - RMIN_FREQ.DataSource = Range(895000, 1000, 935000); + MIN_FREQ.DataSource = Range(902000, 1000, 927000); + RMIN_FREQ.DataSource = Range(902000, 1000, 927000); - MAX_FREQ.DataSource = Range(895000, 1000, 935000); - RMAX_FREQ.DataSource = Range(895000, 1000, 935000); + MAX_FREQ.DataSource = Range(903000, 1000, 928000); + RMAX_FREQ.DataSource = Range(903000, 1000, 928000); } else if (freq == Uploader.Frequency.FREQ_433) { - MIN_FREQ.DataSource = Range(414000, 10, 460000); - RMIN_FREQ.DataSource = Range(414000, 10, 460000); + MIN_FREQ.DataSource = Range(414000, 50, 460000); + RMIN_FREQ.DataSource = Range(414000, 50, 460000); - MAX_FREQ.DataSource = Range(414000, 10, 460000); - RMAX_FREQ.DataSource = Range(414000, 10, 460000); + MAX_FREQ.DataSource = Range(414000, 50, 460000); + RMAX_FREQ.DataSource = Range(414000, 50, 460000); } else if (freq == Uploader.Frequency.FREQ_868) { @@ -1053,35 +1661,44 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) if (multipoint_fix == -1) { - var AESKey = doCommand(Session.Port, "AT&E?").Trim(); + var AESKey = doCommand(Session.Port, "AT&E?").Trim(); //Session.ATCClient.DoQuery("AT&E?", true);// doCommand(Session.Port, "AT&E?").Trim(); if (AESKey.Contains("ERROR")) { - txt_aeskey.Text = ""; - txt_aeskey.Enabled = false; + AESKEY.Text = ""; + AESKEY.Enabled = false; } else { - txt_aeskey.Text = AESKey; - txt_aeskey.Enabled = true; + AESKEY.Text = AESKey; + AESKEY.Enabled = true; } SetupComboForMavlink(MAVLINK, false); } else { - txt_aeskey.Text = ""; - txt_aeskey.Enabled = false; + AESKEY.Text = ""; + AESKEY.Enabled = false; SetupComboForMavlink(MAVLINK, true); } - RSSI.Text = doCommand(Session.Port, "ATI7").Trim(); + RSSI.Text = doCommand(Session.Port, "ATI7").Trim(); //Session.ATCClient.DoQuery("ATI7", true);// doCommand(Session.Port, "ATI7").Trim(); + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done ATI7 cmd"); + lbl_status.Text = "Doing Command ATI5"; - var answer = doCommand(Session.Port, "ATI5", true); + var answer = doCommand(Session.Port, "ATI5", true); //Session.ATCClient.DoQueryWithMultiLineResponse("ATI5");// doCommand(Session.Port, "ATI5", true); + + bool Junk; + + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Parsing local settings"); - var Settings = Session.GetSettings( - doCommand(Session.Port, "ATI5?", true), - Session.Board); + var Settings = Session.GetSettings(false, + Session.Board, answer, null, out Junk); + + _LocalSettings = new RFD.RFD900.TSettings( + RFDLib.Collections.Translate( + Settings, (x) => (RFD.RFD900.TBaseSetting)x)); DisableRFD900xControls(); @@ -1092,90 +1709,45 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) kvp.Key.Enabled = kvp.Value; } + btnSaveToFile.Enabled = true; + btnLoadFromFile.Enabled = true; + + _LocalLabelEditorPairs.Reset(); + if (ATI.Text.Contains("ASYNC")) { - _LocalExtraParams.SetModel(Model.ASYNC); + _LocalExtraParams.SetModel(Model.ASYNC, Settings); } else { - if ((items.Length > 0) && items[0].StartsWith("[")) + if (ATI.Text.Contains("MP on") && (Session.Board == Uploader.Board.DEVICE_ID_RFD900X)) { //This is multipoint firmware. - _LocalExtraParams.SetModel(Model.MULTIPOINT); + _LocalExtraParams.SetModel(Model.MULTIPOINT_X, Settings); } - else if (ATI.Text.Contains("MP on") && (Session.Board == Uploader.Board.DEVICE_ID_RFD900X)) + else if ((items.Length > 0) && items[0].StartsWith("[")) { - _LocalExtraParams.SetModel(Model.MULTIPOINT_X); + _LocalExtraParams.SetModel(Model.MULTIPOINT, Settings); } else { //This is p2p firmware. - _LocalExtraParams.SetModel(Model.P2P); + _LocalExtraParams.SetModel(Model.P2P, Settings); } } + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done getting info out of local modem"); + //For each of the settings returned by the radio... - foreach (var item in items) - { - //if (item.StartsWith("S")) - { - var mod_item = item; - if (multipoint_fix > 0 && item.Length > multipoint_fix) - { - mod_item = item.Substring(multipoint_fix).Trim(); - } - var values = mod_item.Split(new char[] { ':', '=' }, StringSplitOptions.RemoveEmptyEntries); + SetUpControlsWithValues(groupBoxLocal, false, ModifyReturnedStringsForMultipoint(items, multipoint_fix), Settings); - if (values.Length == 3) - { - values[1] = values[1].Replace("/", "_"); - - var controls = groupBoxLocal.Controls.Find(values[1].Trim(), true); - - //If there's a control with the same name as the setting... - if (controls.Length > 0) - { - groupBoxLocal.Enabled = true; - controls[0].Parent.Enabled = true; - controls[0].Enabled = true; - - if (controls[0] is CheckBox) - { - ((CheckBox)controls[0]).Checked = values[2].Trim() == "1"; - } - else if (controls[0] is TextBox) - { - ((TextBox)controls[0]).Text = values[2].Trim(); - } - else if (controls[0].Name.Contains("MAVLINK")) // - { - var ans = Enum.Parse(typeof(mavlink_option), values[2].Trim()); - ((ComboBox)controls[0]).Text = ans.ToString(); - } - else if (controls[0] is ComboBox) - { - if (!SetupCBWithSetting((ComboBox)controls[0], Settings, - values[2].Trim(), false)) - { - ((ComboBox)controls[0]).Text = values[2].Trim(); - if (((ComboBox)controls[0]).Text != values[2].Trim()) - { - SomeSettingsInvalid = true; - - } - - } - - } - } - } - } - } + btnRandom.Enabled = GetIsEncryptionEnabled(ENCRYPTION_LEVEL); + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done setting up controls for local modem"); // remote foreach (Control ctl in groupBoxRemote.Controls) { - if ((ctl.Name != "RSSI")&& (!(ctl is Label))) + if ((ctl.Name != "RSSI")&& (!(ctl is Label)) && !(ctl is Button)) { ctl.ResetText(); } @@ -1183,7 +1755,20 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) Session.Port.DiscardInBuffer(); - RTI.Text = doCommand(Session.Port, "RTI"); + string RTIText = doCommand(Session.Port, "RTI"); + + if ((RTIText.Length < 5) || RTIText.Substring(0, 5) == "ERROR") + { + RTI.Text = ""; + } + else + { + RTI.Text = RTIText; + } + + string RemoteFWVer = RFD.RFD900.RFD900.ATIResponseToFWVersion(RTI.Text); + + txtRCountry.Text = GetCountryCodeFromSession(Session, (m) => m.GetRemoteCountryCode()); if (RTI.Text != "") { @@ -1204,20 +1789,20 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) var AESKey = doCommand(Session.Port, "RT&E?").Trim(); if (AESKey.Contains("ERROR")) { - txt_Raeskey.Text = ""; - txt_Raeskey.Enabled = false; + RAESKEY.Text = ""; + RAESKEY.Enabled = false; } else { - txt_Raeskey.Text = AESKey; - txt_Raeskey.Enabled = true; + RAESKEY.Text = AESKey; + RAESKEY.Enabled = true; } SetupComboForMavlink(RMAVLINK, false); } else { - txt_Raeskey.Text = ""; - txt_Raeskey.Enabled = false; + RAESKEY.Text = ""; + RAESKEY.Enabled = false; SetupComboForMavlink(RMAVLINK, true); } @@ -1225,92 +1810,53 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) answer = doCommand(Session.Port, "RTI5", true); + bool UsedAltRanges; + + var RemoteSettings = Session.GetSettings(true, Session.Board, answer, (LocalFWVer == RemoteFWVer) ? Settings : null, out UsedAltRanges); + + _RemoteSettings = new RFD.RFD900.TSettings( + RFDLib.Collections.Translate( + RemoteSettings, (x) => (RFD.RFD900.TBaseSetting)x)); + + if ((RemoteFWVer != null) && (LocalFWVer != RemoteFWVer) && UsedAltRanges) + { + MsgBox.CustomMessageBox.Show("The ranges and options shown for the remote modem may not be accurate. To ensure accurate, use the same firmware version in both the local and remote modems"); + } + items = answer.Split('\n'); + _RemoteLabelEditorPairs.Reset(); + + btnRemoteSaveToFile.Enabled = true; + btnRemoteLoadFromFile.Enabled = true; if (RTI.Text.Contains("ASYNC")) { - _RemoteExtraParams.SetModel(Model.ASYNC); + _RemoteExtraParams.SetModel(Model.ASYNC, RemoteSettings); } else { - if ((items.Length > 0) && items[0].StartsWith("[")) + if (RTI.Text.Contains("MP on") && (Session.Board == Uploader.Board.DEVICE_ID_RFD900X)) { - //This is multipoint firmware. - _RemoteExtraParams.SetModel(Model.MULTIPOINT); + _RemoteExtraParams.SetModel(Model.MULTIPOINT_X, RemoteSettings); } - else if (RTI.Text.Contains("MP on") && (Session.Board == Uploader.Board.DEVICE_ID_RFD900X)) + else if ((items.Length > 0) && items[0].StartsWith("[")) { - _RemoteExtraParams.SetModel(Model.MULTIPOINT_X); + //This is multipoint firmware. + _RemoteExtraParams.SetModel(Model.MULTIPOINT, RemoteSettings); } else { //This is 2-point firmware. - _RemoteExtraParams.SetModel(Model.P2P); + _RemoteExtraParams.SetModel(Model.P2P, RemoteSettings); } } - foreach (var item in items) - { - //if (item.StartsWith("S")) - { - var values = item.Split(new char[] { ':', '=' }, StringSplitOptions.RemoveEmptyEntries); - - if (values.Length == 3) - { - values[1] = values[1].Replace("/", "_"); - - var controls = groupBoxRemote.Controls.Find("R" + values[1].Trim(), true); - - if (controls.Length == 0) - continue; - - - controls[0].Enabled = true; - - if (controls[0] is CheckBox) - { - ((CheckBox)controls[0]).Checked = values[2].Trim() == "1"; - } - else if (controls[0] is TextBox) - { - ((TextBox)controls[0]).Text = values[2].Trim(); - } - else if (controls[0].Name.Contains("MAVLINK")) // - { - var ans = Enum.Parse(typeof(mavlink_option), values[2].Trim()); - ((ComboBox)controls[0]).Text = ans.ToString(); - } - else if (controls[0] is ComboBox) - { - if (!SetupCBWithSetting((ComboBox)controls[0], Settings, - values[2].Trim(), true)) - { - ((ComboBox)controls[0]).Text = values[2].Trim(); - if (((ComboBox)controls[0]).Text != values[2].Trim()) - { - SomeSettingsInvalid = true; - } - } - } - } - else - { - /* - if (item.Contains("S15")) - { - answer = doCommand(comPort, "RTS15?"); - int rts15 = 0; - if (int.TryParse(answer, out rts15)) - { - RS15.Enabled = true; - RS15.Text = rts15.ToString(); - } - } - */ - log.Info("Odd config line :" + item); - } - } - } + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done getting info from remote modem"); + + SomeSettingsInvalid |= SetUpControlsWithValues(groupBoxRemote, true, items, RemoteSettings); + + //System.Diagnostics.Debug.WriteLine(SW.ElapsedMilliseconds.ToString() + ": Done setting up controls for remote modem"); + } // off hook @@ -1324,6 +1870,9 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) { lbl_status.Text = "Done"; } + EnableConfigControls(true, true); + + } else { @@ -1331,7 +1880,8 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) Session.PutIntoTransparentMode(); lbl_status.Text = "Fail"; - MsgBox.CustomMessageBox.Show("Failed to enter command mode"); + MsgBox.CustomMessageBox.Show("Failed to enter command mode. Try power-cycling modem."); + EnableConfigControls(true, false); } //BUT_Syncoptions.Enabled = true; @@ -1339,8 +1889,6 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) //BUT_savesettings.Enabled = true; //BUT_SetPPMFailSafe.Enabled = true; - - EnableConfigControls(true); EnableProgrammingControls(true); } @@ -1349,11 +1897,15 @@ private void BUT_getcurrent_Click(object sender, EventArgs e) lbl_status.Text = "Error"; MsgBox.CustomMessageBox.Show("Error during read " + ex); } + _AlreadyInEncCheckChangedEvtHdlr = false; - if (GetCommsSerialAlt == null) - { - EndSessionClosePort(); - } + UpdateSetPPMFailSafeButtons(); + } + + void UpdateSetPPMFailSafeButtons() + { + BUT_SetPPMFailSafe.Enabled = GPO1_1R_COUT.Enabled && GPO1_1R_COUT.Checked; + BUT_SetPPMFailSafeRemote.Enabled = RGPO1_1R_COUT.Enabled && RGPO1_1R_COUT.Checked; } private string Serial_ReadLine(ICommsSerial comPort) @@ -1365,8 +1917,8 @@ private string Serial_ReadLine(ICommsSerial comPort) { if (comPort.BytesToRead > 0) { - var data = (byte)comPort.ReadByte(); - sb.Append((char)data); + var data = (byte) comPort.ReadByte(); + sb.Append((char) data); if (data == '\n') break; } @@ -1463,7 +2015,7 @@ public bool doConnect(ICommsSerial comPort) // setup a known enviroment comPort.Write("ATO\r\n"); - retry: + retry: // wait Sleep(1500, comPort); @@ -1531,8 +2083,8 @@ private void BUT_Syncoptions_Click(object sender, EventArgs e) RMAX_FREQ.Text = MAX_FREQ.Text; RNUM_CHANNELS.Text = NUM_CHANNELS.Text; RMAX_WINDOW.Text = MAX_WINDOW.Text; - RENCRYPTION_LEVEL.Checked = ENCRYPTION_LEVEL.Checked; - txt_Raeskey.Text = txt_aeskey.Text; + RENCRYPTION_LEVEL.SelectedIndex = ENCRYPTION_LEVEL.SelectedIndex; + RAESKEY.Text = AESKEY.Text; } private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e) @@ -1608,11 +2160,7 @@ private void BUT_resettodefault_Click(object sender, EventArgs e) Session.PutIntoTransparentMode(); lbl_status.Text = "Fail"; - MsgBox.CustomMessageBox.Show("Failed to enter command mode"); - } - if (GetCommsSerialAlt == null) - { - EndSessionClosePort(); + MsgBox.CustomMessageBox.Show("Failed to enter command mode. Try power-cycling modem."); } } @@ -1623,14 +2171,26 @@ void UpdateStatus(string Status) Application.DoEvents(); } - void EnableConfigControls(bool Enable) + void UpdateStatusCallback(string Status, double Progress) + { + if (Status != null) + { + UpdateStatus(Status); + } + if (!double.IsNaN(Progress)) + { + ProgressEvtHdlr(Progress); + } + } + + void EnableConfigControls(bool Enable, bool SaveSettingsEnable) { - groupBoxLocal.Enabled = Enable; - groupBoxRemote.Enabled = Enable; + groupBoxLocal.Enabled = SaveSettingsEnable; + groupBoxRemote.Enabled = SaveSettingsEnable; BUT_Syncoptions.Enabled = Enable; BUT_SetPPMFailSafe.Enabled = Enable; BUT_getcurrent.Enabled = Enable; - BUT_savesettings.Enabled = Enable; + BUT_savesettings.Enabled = SaveSettingsEnable; BUT_resettodefault.Enabled = Enable; } public static void ResetAllControls(Control form) @@ -1688,7 +2248,7 @@ private void BUT_loadcustom_Click(object sender, EventArgs e) void ProgramFirmware(bool Custom) { EnableProgrammingControls(false); - EnableConfigControls(false); + EnableConfigControls(false, false); try { @@ -1700,23 +2260,13 @@ void ProgramFirmware(bool Custom) //Console.WriteLine("Mode is " + Mode.ToString()); //port.Close(); - RFD.RFD900.RFD900 RFD900 = null; - UpdateStatus("Putting in to bootloader mode"); - switch (Session.PutIntoBootloaderMode()) - { - case RFD.RFD900.TSession.TMode.BOOTLOADER: - RFD900 = RFD.RFD900.RFD900APU.GetObjectForModem(Session); - break; - case RFD.RFD900.TSession.TMode.BOOTLOADER_X: - RFD900 = RFD.RFD900.RFD900xux.GetObjectForModem(Session); - break; - default: - break; - } + RFD.RFD900.RFD900 RFD900 = _Session.GetModemObject(); if (RFD900 == null) { - UpdateStatus("Could not put in to bootloader mode"); + UpdateStatus("Unknown modem"); + MsgBox.CustomMessageBox.Show("Couldn't communicate with modem. Try power-cycling modem."); + EndSession(); } else { @@ -1728,10 +2278,10 @@ void ProgramFirmware(bool Custom) { UpdateStatus("Getting firmware from internet"); } - if (getFirmware(RFD900.Board, Custom)) + if (getFirmware(RFD900.Board, RFD900, Custom)) { UpdateStatus("Programming firmware into device"); - if (RFD900.ProgramFirmware(firmwarefile, ProgressEvtHdlr)) + if (RFD900.ProgramFirmware(firmwarefile, UpdateStatusCallback)) { UpdateStatus("Programmed firmware into device"); } @@ -1739,6 +2289,7 @@ void ProgramFirmware(bool Custom) { UpdateStatus("Programming failed. (Try again?)"); } + EndSession(); } else { @@ -1748,15 +2299,18 @@ void ProgramFirmware(bool Custom) } catch { - + try + { + UpdateStatus("Programming failed. (Try again?)"); + EndSession(); + } + catch + { + } } EnableProgrammingControls(true); - EnableConfigControls(true); + EnableConfigControls(true, false); //UploadFW(true); - if (GetCommsSerialAlt == null) - { - EndSessionClosePort(); - } } void ProgressEvtHdlr(double Completed) @@ -1799,7 +2353,7 @@ private void linkLabel_lowlatency_LinkClicked(object sender, LinkLabelLinkClicke RMAX_WINDOW.Text = 33.ToString(); } - private enum mavlink_option + public enum mavlink_option { RawData = 0, Mavlink = 1, @@ -1819,15 +2373,14 @@ private void txt_aeskey_TextChanged(object sender, EventArgs e) string item = txt.Text; if (!(Regex.IsMatch(item, "^[0-9a-fA-F]+$"))) { - if (item.Length != 0) + if(item.Length != 0) txt.Text = item.Remove(item.Length - 1, 1); txt.SelectionStart = txt.Text.Length; } } - private void BUT_SetPPMFailSafe_Click(object sender, EventArgs e) + private void SetPPMFailSafe(string SetCmd, string SaveCmd) { - lbl_status.Text = "Connecting"; RFD.RFD900.TSession Session = GetSession(); @@ -1839,18 +2392,21 @@ private void BUT_SetPPMFailSafe_Click(object sender, EventArgs e) if (Session.PutIntoATCommandMode() == RFD.RFD900.TSession.TMode.AT_COMMAND) { // cleanup - doCommand(Session.Port, "AT&T", false, 1); - - Session.Port.DiscardInBuffer(); + //Session.Port.DiscardInBuffer(); + //doCommand(Session.Port, "AT&T", false, 1); lbl_status.Text = "Doing Command"; - string Result = doCommand(Session.Port, "RT&R"); + Session.Port.DiscardInBuffer(); + bool Result = Session.ATCClient.DoCommand(SetCmd); + + Session.Port.DiscardInBuffer(); + Session.ATCClient.DoCommand(SaveCmd); // off hook //doCommand(Session.Port, "ATO"); - if (Result.Contains("OK")) + if (Result) { lbl_status.Text = "Done"; } @@ -1867,85 +2423,26 @@ private void BUT_SetPPMFailSafe_Click(object sender, EventArgs e) lbl_status.Text = "Fail"; MsgBox.CustomMessageBox.Show("Failed to enter command mode"); } - - if (GetCommsSerialAlt == null) - { - EndSessionClosePort(); - } } - void getTelemPortWithRadio(ref ICommsSerial comPort) - { - // try telem1 - - comPort = new MAVLinkSerialPort(MainV2.comPort, (int)MAVLink.SERIAL_CONTROL_DEV.TELEM1); - - comPort.ReadTimeout = 4000; - - comPort.Open(); - } - /// - /// returns null if failed - /// - /// - ICommsSerial GetComPort() + private void BUT_SetPPMFailSafe_Click(object sender, EventArgs e) { - if (GetCommsSerialAlt == null) - { - ICommsSerial comPort; - - try - { - if (MainV2.comPort.BaseStream.PortName.Contains("TCP")) - { - comPort = new TcpSerial(); - comPort.BaudRate = MainV2.comPort.BaseStream.BaudRate; - comPort.ReadTimeout = 4000; - comPort.Open(); - } - else - { - comPort = new SerialPort(); - if (MainV2.comPort.BaseStream.IsOpen) - { - getTelemPortWithRadio(ref comPort); - } - else - { - comPort.PortName = MainV2.comPortName; - comPort.BaudRate = MainV2.comPortBaud; - } - - comPort.ReadTimeout = 4000; - - comPort.Open(); - } - - return comPort; - } - catch - { - MsgBox.CustomMessageBox.Show("Invalid ComPort or in use"); - return null; - } - } - else - { - return GetCommsSerialAlt(); - } + SetPPMFailSafe("AT&R", "AT&W"); } RFD.RFD900.TSession GetSession() { + if (_Session == null) { try { - var p = GetComPort(); + var p = MissionPlanner.Radio.ComPort.GetComPortForSiKRadio(); + if (p != null) { - _Session = new RFD.RFD900.TSession(p); + _Session = new RFD.RFD900.TSession(p, MainV2.comPort.BaseStream.BaudRate); } } catch @@ -1964,29 +2461,16 @@ RFD.RFD900.TSession GetSession() return _Session; } - /// - /// Put the modem into transparent mode and close the comms port. - /// - private void EndSessionClosePort() + private void EndSession() { if (_Session != null) { - try - { - _Session.PutIntoTransparentMode(); - } catch{} _Session.Dispose(); - _Session.Port.Close(); _Session = null; } - } - - private void EndSession() - { - if (_Session != null) + if (DoDisconnectReconnect != null) { - _Session.Dispose(); - _Session = null; + DoDisconnectReconnect(); } } @@ -2012,8 +2496,11 @@ bool SetSetting(string Designator, int Value, bool Remote) /// ignored private void ENCRYPTION_LEVEL_CheckedChanged(object sender, EventArgs e) { - EncryptionCheckChangedEvtHdlr(ENCRYPTION_LEVEL, "ATI5", "AT&E?", txt_aeskey, false); - btnRandom.Enabled = ENCRYPTION_LEVEL.Checked; + if (ENCRYPTION_LEVEL.Enabled) + { + EncryptionCheckChangedEvtHdlr(ENCRYPTION_LEVEL, "ATI5", "AT&E?", AESKEY, false, "ATI5"); + } + btnRandom.Enabled = GetIsEncryptionEnabled(ENCRYPTION_LEVEL); } /// @@ -2023,19 +2510,38 @@ private void ENCRYPTION_LEVEL_CheckedChanged(object sender, EventArgs e) /// ignored private void RENCRYPTION_LEVEL_CheckedChanged(object sender, EventArgs e) { - EncryptionCheckChangedEvtHdlr(RENCRYPTION_LEVEL, "RTI5", "RT&E?", txt_Raeskey, true); + if (RENCRYPTION_LEVEL.Enabled) + { + EncryptionCheckChangedEvtHdlr(RENCRYPTION_LEVEL, "RTI5", "RT&E?", RAESKEY, true, "RTI5"); + } } bool _AlreadyInEncCheckChangedEvtHdlr = false; + string RemoveMultiPointLocalNodeID(string ATCReply) + { + ATCReply = ATCReply.Trim(); + + if ((ATCReply.Length > 1) && (ATCReply[0] == '[') && ATCReply.Contains(']')) + { + int StartIndex = ATCReply.IndexOf(']') + 1; + + return ATCReply.Substring(StartIndex); + } + else + { + return ATCReply; + } + } + /// /// Handles a change of an encryption level check box. /// /// The checkbox which was changed. Must not be null. /// The AT command to use to get the settings /// from the relevant modem. Must not be null. - void EncryptionCheckChangedEvtHdlr(CheckBox CB, string ATCommand, string EncKeyQuery, - TextBox EncKeyTextBox, bool Remote) + void EncryptionCheckChangedEvtHdlr(ComboBox CB, string ATCommand, string EncKeyQuery, + TextBox EncKeyTextBox, bool Remote, string ATI5Command) { if (_AlreadyInEncCheckChangedEvtHdlr) { @@ -2052,12 +2558,15 @@ void EncryptionCheckChangedEvtHdlr(CheckBox CB, string ATCommand, string EncKeyQ return; } Session.PutIntoATCommandMode(); - var answer = doCommand(Session.Port, ATCommand, true); - var Settings = Session.GetSettings(answer, Session.Board); + var ATI5answer = doCommand(Session.Port, ATI5Command, true); + + bool Junk; + + var Settings = Session.GetSettings(Remote, Session.Board, ATI5answer, null, out Junk); if (Settings.ContainsKey("ENCRYPTION_LEVEL")) { var Setting = Settings["ENCRYPTION_LEVEL"]; - if (!SetSetting(Setting.Designator, CB.Checked ? 1 : 0, Remote)) + if (!SetSetting(Setting.Designator, GetEncryptionLevelValue(CB), Remote)) { return; } @@ -2070,11 +2579,7 @@ void EncryptionCheckChangedEvtHdlr(CheckBox CB, string ATCommand, string EncKeyQ //Read AES key back out of modem and display it. //BUT_getcurrent_Click(this, null); //txt_aeskey.Text = doCommand(Session.Port, "AT&E?").Trim(); - EncKeyTextBox.Text = doCommand(Session.Port, EncKeyQuery).Trim(); - if (CB.Checked && EncKeyTextBox.Text.Length == 0) - { - //Console.WriteLine("Something wrong here"); - } + EncKeyTextBox.Text = RemoveMultiPointLocalNodeID(doCommand(Session.Port, EncKeyQuery).Trim()).Trim(); lbl_status.Text = "Done."; } finally @@ -2083,27 +2588,144 @@ void EncryptionCheckChangedEvtHdlr(CheckBox CB, string ATCommand, string EncKeyQ } } - string GetRandom32BitKey() + /// + /// Get a random key as a hex numeral string, with the given QTY of hex numerals. + /// + /// The QTY of hex numerals. + /// The key. Never null. + string GetRandomKey(int QTYHexDigits) { + string Result = ""; + System.Random R = new Random((int)(System.DateTime.Now.Ticks & 0xFFFFFFFF)); - return R.Next().ToString("X8"); - } - string GetRandomKey() - { - return GetRandom32BitKey() + GetRandom32BitKey() + GetRandom32BitKey() + GetRandom32BitKey(); + for (; QTYHexDigits > 0; QTYHexDigits--) + { + Result += (((UInt32)R.Next()) & 0xF).ToString("X1"); + } + + return Result; } private void btnRandom_Click(object sender, EventArgs e) { - //Key is 16 binary bytes (32 hex digits) - txt_aeskey.Text = GetRandomKey(); - txt_Raeskey.Text = txt_aeskey.Text; + AESKEY.Text = GetRandomKey(GetEncryptionMaxKeyLength(ENCRYPTION_LEVEL)); + RAESKEY.Text = AESKEY.Text; } private void btnCommsLog_Click(object sender, EventArgs e) { } + + private void BUT_SetPPMFailSafeRemote_Click(object sender, EventArgs e) + { + SetPPMFailSafe("RT&R", "RT&W"); + } + + /// + /// Save settings from GUI to file. + /// + /// The settings read from the modem. Must not be null. + /// The relevant GUI groupbox. + /// true if remote modem, false if local modem. + void SaveToFile(RFD.RFD900.TSettings S, GroupBox GB, + bool Remote) + { + //Get the settings which have changed in the GUI, and their values. + var Updated = GetUpdatedSettingsFromGroupBox( + RFDLib.Collections.Translate(S.Settings, (x) => (RFD.RFD900.TBaseSetting)x), + GB, Remote); + + //Include the settings which haven't changed. + foreach (var kvp in S.Settings) + { + if (!Updated.ContainsKey(kvp.Key)) + { + Updated[kvp.Key] = kvp.Value; + } + } + + //Save to file... + RFD.RFD900.TSettings ToSave = new RFD.RFD900.TSettings(Updated); + + if (dlgSave.ShowDialog() == DialogResult.OK) + { + if (ToSave.SaveToFile(dlgSave.FileName)) + { + System.Windows.Forms.MessageBox.Show("Saved settings to " + dlgSave.FileName + " OK"); + } + else + { + System.Windows.Forms.MessageBox.Show("Failed to save settings to " + dlgSave.FileName); + } + } + } + + private void btnSaveToFile_Click(object sender, EventArgs e) + { + SaveToFile(_LocalSettings, groupBoxLocal, false); + } + + /// + /// Load settings from file into the GUI. + /// + /// The settings loaded from the modem. These aren't modified by this function. Must not be null. + /// The relevant GUI groupbox. Must not be null. + /// true if for the remote modem, false if for the local modem. + private void LoadFromFile(RFD.RFD900.TSettings S, GroupBox GB, bool Remote) + { + if (dlgOpen.ShowDialog() == DialogResult.OK) + { + S = S.Clone(); + + var x = S.LoadFromFile(dlgOpen.FileName); + + if (x == null) + { + System.Windows.Forms.MessageBox.Show("Failed to load settings from " + dlgOpen.FileName); + } + else + { + UpdateControlsWithValues(GB, Remote, S.Settings); + + string Temp = "Loaded\n"; + + foreach (var kvp in x) + { + Temp += kvp.Value.Name + " = " + kvp.Value.Value.ToString() + "\n"; + } + + Temp += "from " + dlgOpen.FileName + " OK"; + + System.Windows.Forms.MessageBox.Show(Temp); + } + } + } + + + private void btnLoadFromFile_Click(object sender, EventArgs e) + { + LoadFromFile(_LocalSettings, groupBoxLocal, false); + } + + private void btnRemoteLoadFromFile_Click(object sender, EventArgs e) + { + LoadFromFile(_RemoteSettings, groupBoxRemote, true); + } + + private void btnRemoteSaveToFile_Click(object sender, EventArgs e) + { + SaveToFile(_RemoteSettings, groupBoxRemote, true); + } + + public string Header + { + get + { + return "Settings"; + } + } + } } \ No newline at end of file diff --git a/Radio/Sikradio.resx b/Radio/Sikradio.resx index bc9078141d..aad3baa0cf 100644 --- a/Radio/Sikradio.resx +++ b/Radio/Sikradio.resx @@ -123,7 +123,7 @@ - 12, 447 + 12, 561 1072, 36 @@ -179,7 +179,7 @@ which result in a valid packet CRC groupBoxLocal - 63 + 86 True @@ -216,7 +216,7 @@ red LED solid - in firmware update mode $this - 4 + 3 False @@ -225,7 +225,7 @@ red LED solid - in firmware update mode NoControl - 266, 217 + 266, 207 80, 20 @@ -246,7 +246,7 @@ red LED solid - in firmware update mode groupBoxRemote - 42 + 65 False @@ -345,7 +345,7 @@ red LED solid - in firmware update mode 30 - 266, 244 + 266, 232 80, 21 @@ -353,9 +353,6 @@ red LED solid - in firmware update mode 96 - - Node ID. Base node ID is 0. One node must be acting as a base for a multipoint environment to work. - RMAX_WINDOW @@ -366,7 +363,7 @@ red LED solid - in firmware update mode groupBoxRemote - 45 + 68 False @@ -399,7 +396,7 @@ red LED solid - in firmware update mode 435000 - 266, 108 + 266, 107 80, 21 @@ -420,7 +417,7 @@ red LED solid - in firmware update mode groupBoxRemote - 47 + 70 False @@ -483,7 +480,7 @@ red LED solid - in firmware update mode 50 - 266, 135 + 266, 132 80, 21 @@ -504,7 +501,7 @@ red LED solid - in firmware update mode groupBoxRemote - 48 + 71 False @@ -540,7 +537,7 @@ red LED solid - in firmware update mode 100 - 266, 162 + 266, 157 80, 21 @@ -561,7 +558,7 @@ red LED solid - in firmware update mode groupBoxRemote - 49 + 72 False @@ -588,7 +585,7 @@ red LED solid - in firmware update mode 250 - 266, 189 + 266, 182 80, 21 @@ -609,7 +606,7 @@ red LED solid - in firmware update mode groupBoxRemote - 50 + 73 False @@ -642,7 +639,7 @@ red LED solid - in firmware update mode 435000 - 266, 83 + 266, 82 80, 21 @@ -663,13 +660,13 @@ red LED solid - in firmware update mode groupBoxRemote - 51 + 74 False - 88, 243 + 88, 232 80, 21 @@ -677,9 +674,6 @@ red LED solid - in firmware update mode 111 - - AIR_SPEED is the inter-radio data rate in rounded kbps. So 128 means 128kbps. Max is 192, min is 2. I would not recommend values below 16 as the frequency hopping and tdm sync times get too long. - RMAVLINK @@ -690,7 +684,7 @@ red LED solid - in firmware update mode groupBoxRemote - 9 + 33 False @@ -699,17 +693,16 @@ red LED solid - in firmware update mode NoControl - 102, 323 + 148, 307 - 66, 20 + 20, 20 119 - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. - + GPI1_1R/COUT Sets GPIO 1.1 as R/C(PPM) output RGPO1_1R_COUT @@ -721,7 +714,7 @@ red LED solid - in firmware update mode groupBoxRemote - 10 + 34 False @@ -730,17 +723,16 @@ red LED solid - in firmware update mode NoControl - 88, 297 + 148, 282 - 80, 20 + 20, 20 115 - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. - + GPI1_1R/CIN Sets GPIO 1.1 as R/C(PPM) input RGPI1_1R_CIN @@ -752,7 +744,7 @@ red LED solid - in firmware update mode groupBoxRemote - 13 + 37 False @@ -785,7 +777,7 @@ red LED solid - in firmware update mode 1 - 88, 109 + 88, 107 80, 21 @@ -807,7 +799,7 @@ red LED solid - in firmware update mode groupBoxRemote - 14 + 38 False @@ -852,7 +844,7 @@ red LED solid - in firmware update mode 2 - 88, 136 + 88, 132 80, 21 @@ -873,7 +865,7 @@ red LED solid - in firmware update mode groupBoxRemote - 15 + 39 False @@ -969,7 +961,7 @@ red LED solid - in firmware update mode 30 - 88, 163 + 88, 157 80, 21 @@ -990,7 +982,7 @@ red LED solid - in firmware update mode groupBoxRemote - 16 + 40 False @@ -1020,7 +1012,7 @@ red LED solid - in firmware update mode 20 - 88, 191 + 88, 182 80, 21 @@ -1042,7 +1034,7 @@ red LED solid - in firmware update mode groupBoxRemote - 18 + 42 False @@ -1051,7 +1043,7 @@ red LED solid - in firmware update mode NoControl - 88, 217 + 88, 207 80, 20 @@ -1073,7 +1065,7 @@ red LED solid - in firmware update mode groupBoxRemote - 20 + 44 False @@ -1082,10 +1074,10 @@ red LED solid - in firmware update mode NoControl - 88, 271 + 148, 257 - 80, 20 + 20, 20 120 @@ -1104,7 +1096,7 @@ red LED solid - in firmware update mode groupBoxRemote - 23 + 47 False @@ -1113,7 +1105,7 @@ red LED solid - in firmware update mode NoControl - 274, 216 + 274, 207 80, 20 @@ -1134,7 +1126,7 @@ red LED solid - in firmware update mode groupBoxLocal - 43 + 66 False @@ -1233,7 +1225,7 @@ red LED solid - in firmware update mode 30 - 274, 243 + 274, 232 80, 21 @@ -1241,9 +1233,6 @@ red LED solid - in firmware update mode 92 - - Node ID. Base node ID is 0. One node must be acting as a base for a multipoint environment to work. - MAX_WINDOW @@ -1254,7 +1243,7 @@ red LED solid - in firmware update mode groupBoxLocal - 48 + 71 False @@ -1308,7 +1297,7 @@ red LED solid - in firmware update mode groupBoxLocal - 50 + 73 False @@ -1371,7 +1360,7 @@ red LED solid - in firmware update mode 50 - 274, 134 + 274, 132 80, 21 @@ -1392,7 +1381,7 @@ red LED solid - in firmware update mode groupBoxLocal - 51 + 74 False @@ -1419,7 +1408,7 @@ red LED solid - in firmware update mode 250 - 274, 188 + 274, 182 80, 21 @@ -1440,7 +1429,7 @@ red LED solid - in firmware update mode groupBoxLocal - 53 + 76 False @@ -1503,7 +1492,7 @@ red LED solid - in firmware update mode groupBoxLocal - 55 + 78 False @@ -1539,7 +1528,7 @@ red LED solid - in firmware update mode 100 - 274, 161 + 274, 157 80, 21 @@ -1560,7 +1549,7 @@ red LED solid - in firmware update mode groupBoxLocal - 58 + 81 False @@ -1569,17 +1558,16 @@ red LED solid - in firmware update mode NoControl - 110, 323 + 154, 307 - 66, 20 + 23, 20 129 - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. - + GPI1_1R/COUT Sets GPIO 1.1 as R/C(PPM) output GPO1_1R_COUT @@ -1591,7 +1579,7 @@ red LED solid - in firmware update mode groupBoxLocal - 10 + 34 False @@ -1600,17 +1588,16 @@ red LED solid - in firmware update mode NoControl - 96, 297 + 154, 282 - 80, 20 + 23, 20 127 - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. - + GPI1_1R/CIN Sets GPIO 1.1 as R/C(PPM) input GPI1_1R_CIN @@ -1622,13 +1609,13 @@ red LED solid - in firmware update mode groupBoxLocal - 12 + 36 False - 96, 244 + 96, 232 80, 21 @@ -1637,7 +1624,7 @@ red LED solid - in firmware update mode 126 - AIR_SPEED is the inter-radio data rate in rounded kbps. So 128 means 128kbps. Max is 192, min is 2. I would not recommend values below 16 as the frequency hopping and tdm sync times get too long. + Mavlink MAVLINK @@ -1649,7 +1636,7 @@ red LED solid - in firmware update mode groupBoxLocal - 13 + 37 False @@ -1682,7 +1669,7 @@ red LED solid - in firmware update mode 1 - 96, 109 + 96, 107 80, 21 @@ -1704,7 +1691,7 @@ red LED solid - in firmware update mode groupBoxLocal - 15 + 39 False @@ -1749,7 +1736,7 @@ red LED solid - in firmware update mode 2 - 96, 136 + 96, 132 80, 21 @@ -1770,7 +1757,7 @@ red LED solid - in firmware update mode groupBoxLocal - 18 + 42 False @@ -1866,7 +1853,7 @@ red LED solid - in firmware update mode 30 - 96, 163 + 96, 157 80, 21 @@ -1887,7 +1874,7 @@ red LED solid - in firmware update mode groupBoxLocal - 20 + 44 False @@ -1917,7 +1904,7 @@ red LED solid - in firmware update mode 20 - 96, 191 + 96, 182 80, 21 @@ -1939,7 +1926,7 @@ red LED solid - in firmware update mode groupBoxLocal - 22 + 46 False @@ -1948,7 +1935,7 @@ red LED solid - in firmware update mode NoControl - 96, 217 + 96, 207 80, 20 @@ -1970,7 +1957,7 @@ red LED solid - in firmware update mode groupBoxLocal - 24 + 48 False @@ -1979,10 +1966,10 @@ red LED solid - in firmware update mode NoControl - 96, 271 + 154, 257 - 80, 20 + 23, 20 124 @@ -2001,710 +1988,1832 @@ red LED solid - in firmware update mode groupBoxLocal - 27 + 51 - - 60, 12 + + False - - 147, 20 + + 0 - - 33 + + 1 - - RTI + + 2 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 3 - - groupBoxRemote + + 4 - - 58 + + 5 - - 59, 12 + + 6 - - 147, 20 + + 7 - - 32 + + 8 - - ATI + + 9 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 10 - - groupBoxLocal + + 11 - - 62 + + 12 - - True + + 13 - - NoControl + + 14 - - 14, 15 + + 15 - - 42, 13 + + 16 - - 36 + + 17 - - Version + + 18 - - label11 + + 19 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 20 - - groupBoxLocal + + 21 - - 61 + + 22 - - True + + 23 - - NoControl + + 24 - - 18, 50 + + 25 - - 32, 13 + + 26 - - 37 + + 27 - - RSSI + + 28 - - label12 + + 29 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 30 - - groupBoxLocal + + 274, 257 - - 64 + + 80, 21 - - NoControl + + 154 - - 9, 412 + + AES Encryption Level - - 442, 28 + + ENCRYPTION_LEVEL - - 3 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - NOTE: Always click "Copy required to remote" when modifying -this ensures you wont lose radio link + + groupBoxLocal - - lbl_status + + 10 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + False - - $this + + 0 - - 11 + + 1 - - 207, 12 + + 2 - - 102, 20 + + 3 - - 79 + + 4 - - ATI3 + + 5 - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 6 - - groupBoxLocal + + 7 - - 60 + + 8 - - btnRandom + + 9 - - System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 10 - - groupBoxLocal + + 11 - - 0 + + 12 - - lblRX_ENCAP_METHOD + + 13 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 14 - - groupBoxLocal + + 15 - - 1 + + 16 - + + 17 + + + 18 + + + 19 + + + 20 + + + 21 + + + 22 + + + 23 + + + 24 + + + 25 + + + 26 + + + 27 + + + 28 + + + 29 + + + 30 + + + 266, 257 + + + 80, 21 + + + 160 + + + AES Encryption Level + + + RENCRYPTION_LEVEL + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxRemote + + + 10 + + + False + + + 447, 403 + + + 80, 21 + + + 161 + + + The number of output frames for SBUS or PPM missing before enters failsafe. + + + FSFRAMELOSS + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 3 + + + False + + + 447, 403 + + + 80, 21 + + + 167 + + + The number of output frames for SBUS or PPM missing before enters failsafe. + + + RFSFRAMELOSS + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxRemote + + + 3 + + + False + + + NoControl + + + 154, 332 + + + 23, 20 + + + 141 + + + GPO1_3SBUSIN + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 23 + + + False + + + NoControl + + + 148, 332 + + + 36, 20 + + + 149 + + + RGPO1_3SBUSIN + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxRemote + + + 21 + + + False + + + NoControl + + + 154, 382 + + + 23, 20 + + + 151 + + + GPO1_3STATLED + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 13 + + + False + + + NoControl + + + 283, 382 + + + 23, 20 + + + 153 + + + GPO1_0TXEN485 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 11 + + + False + + + NoControl + + + 275, 382 + + + 23, 20 + + + 159 + + + RGPO1_0TXEN485 + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxRemote + + + 11 + + + False + + + NoControl + + + 148, 382 + + + 23, 20 + + + 157 + + + RGPO1_3STATLED + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxRemote + + + 13 + + + 60, 12 + + + 147, 20 + + + 33 + + + RTI + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxRemote + + + 81 + + + 59, 12 + + + 147, 20 + + + 32 + + + ATI + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 85 + + + True + + + NoControl + + + 14, 15 + + + 42, 13 + + + 36 + + + Version + + + label11 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 84 + + + True + + + NoControl + + + 18, 50 + + + 32, 13 + + + 37 + + + RSSI + + + label12 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 87 + + + NoControl + + + 9, 518 + + + 442, 28 + + + 3 + + + NOTE: Always click "Copy required to remote" when modifying +this ensures you wont lose radio link + + + lbl_status + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 10 + + + 207, 12 + + + 102, 20 + + + 79 + + + ATI3 + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 83 + + + btnLoadFromFile + + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null + + + groupBoxLocal + + + 0 + + + btnSaveToFile + + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null + + + groupBoxLocal + + + 1 + + + label54 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 2 + + + GPO1_3AUXOUT + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 4 + + + lblGPO1_3AUXOUT + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 5 + + + GPI1_2AUXIN + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 6 + + + lblGPI1_2AUXIN + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 7 + + + lblGPIO1_1FUNC + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 8 + + + GPIO1_1FUNC + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 9 + + + lblGPO1_0TXEN485 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 12 + + + lblGPO1_3STATLED + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 14 + + + GPO1_3SBUSOUT + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 15 + + + label49 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 16 + + + BUT_SetPPMFailSafe + + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null + + + groupBoxLocal + + + 17 + + + txtCountry + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 18 + + + label45 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 19 + + + RATE_FREQBAND + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 20 + + + lblSBUSOUT + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 21 + + + lblSBUSIN + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 22 + + + btnRandom + + + System.Windows.Forms.Button, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 24 + + + lblRX_ENCAP_METHOD + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 25 + + RX_ENCAP_METHOD - + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 26 + + + lblTX_ENCAP_METHOD + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 27 + + + TX_ENCAP_METHOD + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 28 + + + lblDESTID + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 29 + + + lblNODEID + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 30 + + + DESTID + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 31 + + + NODEID + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 32 + + + lblGPO1_1R_COUT + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 33 + + + lblGPI1_1R_CIN + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 35 + + + label2 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 38 + + + label1 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 40 + + + FORMAT + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 41 + + + label3 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 43 + + + lblNETID + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 45 + + + lblTXPOWER + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 47 + + + lblECC + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 49 + + + lblOPPRESEND + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 50 + + + lblMAVLINK + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 52 + + + lblANT_MODE + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 53 + + + ANT_MODE + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 2 + + 54 - - lblTX_ENCAP_METHOD + + lblSER_BRK_DETMS - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 3 + + 55 - - TX_ENCAP_METHOD + + lblGLOBAL_RETRIES - + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 56 + + + lblMAX_RETRIES + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 57 + + + SER_BRK_DETMS + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + + groupBoxLocal + + + 58 + + + GLOBAL_RETRIES + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 59 + + + MAX_RETRIES + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 60 + + + MAX_DATA + + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 61 + + + lblMAX_DATA + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 62 + + + lblENCRYPTION_LEVEL + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 63 + + + label35 + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 64 + + + txt_aeskey + + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 65 + + + lblRTSCTS + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 67 + + + linkLabel_mavlink + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + groupBoxLocal + + + 68 + + + linkLabel_lowlatency + + + System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBoxLocal - - 4 + + 69 - - lblDESTID + + lblMAX_WINDOW - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 5 + + 70 - - lblNODEID + + lblMIN_FREQ - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 6 + + 72 - - DESTID + + lblLBT_RSSI - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 7 + + 75 - - NODEID + + lblDUTY_CYCLE - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 8 + + 77 - - label40 + + lblNUM_CHANNELS - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 9 + + 79 - - label39 + + lblMAX_FREQ - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 11 + + 80 - - label2 + + ATI2 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 14 + + 82 - - label1 + + 12, 48 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 533, 463 - + + 80 + + + Local + + groupBoxLocal - - 16 + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - FORMAT + + $this - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 6 - - groupBoxLocal + + True - - 17 + + NoControl - - label3 + + 427, 387 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 100, 13 - - groupBoxLocal + + 162 - - 19 + + Failsafe Frame Loss - - label4 + + label54 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 21 + + 2 - - label5 + + False - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 154, 432 - - 23 + + 23, 20 - - label6 + + 160 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GPO1_3AUXOUT + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 25 + + 4 + + + True - - label8 + + NoControl - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 18, 436 - - groupBoxLocal + + 93, 13 - - 26 + + 159 + + + GPO1_3AUXOUT - - label7 + + lblGPO1_3AUXOUT - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 28 + + 5 - - lblANT_MODE + + False - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 154, 407 - - 29 + + 23, 20 - - ANT_MODE + + 158 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GPI1_2AUXIN - + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBoxLocal - - 30 + + 6 - - lblSER_BRK_DETMS + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 18, 411 - - 31 + + 76, 13 - - lblGLOBAL_RETRIES + + 157 - + + GPI1_2AUXIN + + + lblGPI1_2AUXIN + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 32 + + 7 - - lblMAX_RETRIES + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 182, 411 - - 33 + + 80, 13 - - SER_BRK_DETMS + + 156 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GPIO1_1FUNC - + + lblGPIO1_1FUNC + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBoxLocal - - 34 + + 8 - - GLOBAL_RETRIES + + False - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 274, 406 - - groupBoxLocal + + 80, 21 - - 35 + + 155 - - MAX_RETRIES + + GPIO1_1FUNC - + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 36 + + 9 - - MAX_DATA + + True - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 182, 386 - - 37 + + 95, 13 - - lblMAX_DATA + + 152 - + + GPO1_0TXEN485 + + + lblGPO1_0TXEN485 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 38 + + 12 - - ENCRYPTION_LEVEL + + True - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 18, 386 - - 39 + + 97, 13 + + + 150 - - label36 + + GPO1_3STATLED - + + lblGPO1_3STATLED + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 40 + + 14 - - label35 + + False - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 425, 332 - - groupBoxLocal + + 102, 21 - - 41 + + 149 - - txt_aeskey + + GPO1_3SBUSOUT - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 42 + + 15 + + + True + + + NoControl + + + 377, 18 + + + 46, 13 + + + 148 - - label19 + + Country: - + + label49 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 44 + + 16 - - linkLabel_mavlink + + 380, 38 - - System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - - groupBoxLocal + + 61, 39 - - 45 + + 147 - - linkLabel_lowlatency + + txtCountry - - System.Windows.Forms.LinkLabel, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 46 + + 18 - - label18 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 18, 361 - - 47 + + 81, 13 + + + 146 - - label13 + + Rate/FreqBand - + + label45 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 49 + + 19 - - label17 + + False - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 128, 357 - - groupBoxLocal + + 399, 21 - - 52 + + 145 - - label16 + + RATE_FREQBAND - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 54 + + 20 + + + True - - label15 + + NoControl - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 360, 311 - - groupBoxLocal + + 103, 13 - - 56 + + 144 + + + GPO1_3SBUSOUT: - - label14 + + lblSBUSOUT - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 57 + + 21 - - ATI2 + + True - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxLocal + + 18, 336 - - 59 + + 88, 13 - - 12, 48 + + 142 - - 533, 361 + + GPO1_3SBUSIN - - 80 + + lblSBUSIN - - Local + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - $this - - - 7 + + 22 False @@ -2713,10 +3822,10 @@ this ensures you wont lose radio link NoControl - 242, 291 + 242, 282 - 111, 24 + 113, 24 140 @@ -2734,7 +3843,7 @@ this ensures you wont lose radio link groupBoxLocal - 0 + 24 True @@ -2743,7 +3852,7 @@ this ensures you wont lose radio link NoControl - 360, 196 + 360, 186 58, 13 @@ -2767,13 +3876,13 @@ this ensures you wont lose radio link groupBoxLocal - 1 + 25 False - 447, 193 + 447, 182 80, 21 @@ -2794,7 +3903,7 @@ this ensures you wont lose radio link groupBoxLocal - 2 + 26 True @@ -2803,7 +3912,7 @@ this ensures you wont lose radio link NoControl - 360, 168 + 360, 161 57, 13 @@ -2827,13 +3936,13 @@ this ensures you wont lose radio link groupBoxLocal - 3 + 27 False - 447, 165 + 447, 157 80, 21 @@ -2854,7 +3963,7 @@ this ensures you wont lose radio link groupBoxLocal - 4 + 28 True @@ -2863,7 +3972,7 @@ this ensures you wont lose radio link NoControl - 360, 140 + 360, 136 43, 13 @@ -2887,7 +3996,7 @@ this ensures you wont lose radio link groupBoxLocal - 5 + 29 True @@ -2896,7 +4005,7 @@ this ensures you wont lose radio link NoControl - 360, 112 + 360, 111 47, 13 @@ -2920,13 +4029,13 @@ this ensures you wont lose radio link groupBoxLocal - 6 + 30 False - 447, 137 + 447, 132 80, 21 @@ -2947,13 +4056,13 @@ this ensures you wont lose radio link groupBoxLocal - 7 + 31 False - 447, 109 + 447, 107 80, 21 @@ -2974,67 +4083,67 @@ this ensures you wont lose radio link groupBoxLocal - 8 + 32 - + True - + NoControl - - 18, 326 + + 18, 311 - - 86, 13 + + 91, 13 - + 130 - - GPI1_1R/COUT + + GPO1_1R/COUT - - label40 + + lblGPO1_1R_COUT - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 9 + + 33 - + True - + NoControl - - 18, 300 + + 18, 286 - + 74, 13 - + 128 - + GPI1_1R/CIN - - label39 + + lblGPI1_1R_CIN - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 11 + + 35 True @@ -3043,7 +4152,7 @@ this ensures you wont lose radio link NoControl - 18, 87 + 18, 86 39, 13 @@ -3064,7 +4173,7 @@ this ensures you wont lose radio link groupBoxLocal - 14 + 38 True @@ -3073,7 +4182,7 @@ this ensures you wont lose radio link NoControl - 18, 113 + 18, 111 32, 13 @@ -3094,10 +4203,10 @@ this ensures you wont lose radio link groupBoxLocal - 16 + 40 - 96, 83 + 96, 82 80, 20 @@ -3115,7 +4224,7 @@ this ensures you wont lose radio link groupBoxLocal - 17 + 41 True @@ -3124,7 +4233,7 @@ this ensures you wont lose radio link NoControl - 18, 139 + 18, 136 53, 13 @@ -3145,157 +4254,157 @@ this ensures you wont lose radio link groupBoxLocal - 19 + 43 - + True - + NoControl - - 18, 166 + + 18, 161 - + 38, 13 - + 118 - + Net ID - - label4 + + lblNETID - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 21 + + 45 - + True - + NoControl - - 18, 193 + + 18, 186 - + 52, 13 - + 120 - + Tx Power - - label5 + + lblTXPOWER - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 23 + + 47 - + True - + NoControl - - 18, 218 + + 18, 211 - + 28, 13 - + 122 - + ECC - - label6 + + lblECC - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 25 + + 49 - + True - + NoControl - - 18, 274 + + 18, 261 - + 61, 13 - + 125 - + Op Resend - - label8 + + lblOPPRESEND - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 26 + + 50 - + True - + NoControl - - 18, 247 + + 18, 236 - + 44, 13 - + 123 - + Mavlink - - label7 + + lblMAVLINK - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 28 + + 52 True @@ -3304,7 +4413,7 @@ this ensures you wont lose radio link NoControl - 362, 335 + 360, 86 77, 13 @@ -3315,9 +4424,6 @@ this ensures you wont lose radio link Antenna Mode - - False - lblANT_MODE @@ -3328,13 +4434,13 @@ this ensures you wont lose radio link groupBoxLocal - 29 + 53 False - 447, 335 + 447, 82 80, 21 @@ -3342,9 +4448,6 @@ this ensures you wont lose radio link 109 - - False - ANT_MODE @@ -3355,7 +4458,7 @@ this ensures you wont lose radio link groupBoxLocal - 30 + 54 True @@ -3364,7 +4467,7 @@ this ensures you wont lose radio link NoControl - 360, 310 + 360, 286 84, 13 @@ -3388,7 +4491,7 @@ this ensures you wont lose radio link groupBoxLocal - 31 + 55 True @@ -3397,7 +4500,7 @@ this ensures you wont lose radio link NoControl - 360, 282 + 360, 261 73, 13 @@ -3421,7 +4524,7 @@ this ensures you wont lose radio link groupBoxLocal - 32 + 56 True @@ -3430,7 +4533,7 @@ this ensures you wont lose radio link NoControl - 360, 254 + 360, 236 63, 13 @@ -3454,13 +4557,13 @@ this ensures you wont lose radio link groupBoxLocal - 33 + 57 False - 447, 307 + 447, 282 80, 21 @@ -3481,13 +4584,13 @@ this ensures you wont lose radio link groupBoxLocal - 34 + 58 False - 447, 279 + 447, 257 80, 21 @@ -3508,13 +4611,13 @@ this ensures you wont lose radio link groupBoxLocal - 35 + 59 False - 447, 251 + 447, 232 80, 21 @@ -3535,13 +4638,13 @@ this ensures you wont lose radio link groupBoxLocal - 36 + 60 False - 447, 223 + 447, 207 80, 21 @@ -3562,7 +4665,7 @@ this ensures you wont lose radio link groupBoxLocal - 37 + 61 True @@ -3571,7 +4674,7 @@ this ensures you wont lose radio link NoControl - 360, 226 + 360, 211 53, 13 @@ -3595,64 +4698,37 @@ this ensures you wont lose radio link groupBoxLocal - 38 - - - False - - - NoControl - - - 274, 270 - - - 80, 20 - - - 99 - - - ENCRYPTION_LEVEL - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxLocal - - - 39 + 62 - + True - + NoControl - - 181, 271 + + 181, 261 - + 81, 13 - + 100 - + AES Encryption - - label36 + + lblENCRYPTION_LEVEL - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 40 + + 63 True @@ -3661,7 +4737,7 @@ this ensures you wont lose radio link NoControl - 182, 299 + 182, 286 49, 13 @@ -3682,13 +4758,13 @@ this ensures you wont lose radio link groupBoxLocal - 41 + 64 - 180, 316 + 180, 307 - 32 + 64 174, 20 @@ -3706,37 +4782,37 @@ this ensures you wont lose radio link groupBoxLocal - 42 + 65 - + True - + NoControl - - 181, 217 + + 181, 211 - + 53, 13 - + 97 - + RTS CTS - - label19 + + lblRTSCTS - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 44 + + 67 True @@ -3745,7 +4821,7 @@ this ensures you wont lose radio link NoControl - 183, 333 + 183, 327 146, 13 @@ -3766,7 +4842,7 @@ this ensures you wont lose radio link groupBoxLocal - 45 + 68 True @@ -3775,7 +4851,7 @@ this ensures you wont lose radio link NoControl - 182, 346 + 182, 340 124, 13 @@ -3796,187 +4872,187 @@ this ensures you wont lose radio link groupBoxLocal - 46 + 69 - + True - + NoControl - - 182, 246 + + 182, 236 - + 91, 13 - + 93 - + Max Window (ms) - - label18 + + lblMAX_WINDOW - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 47 + + 70 - + True - + NoControl - + 182, 86 - + 48, 13 - + 87 - + Min Freq - - label13 + + lblMIN_FREQ - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 49 + + 72 - + True - + NoControl - - 182, 191 + + 182, 186 - + 50, 13 - + 91 - + LBT Rssi - - label17 + + lblLBT_RSSI - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 52 + + 75 - + True - + NoControl - - 182, 164 + + 182, 161 - + 58, 13 - + 90 - + Duty Cycle - - label16 + + lblDUTY_CYCLE - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 54 + + 77 - + True - + NoControl - - 182, 138 + + 182, 136 - + 73, 13 - + 89 - + # of Channels - - label15 + + lblNUM_CHANNELS - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 56 + + 79 - + True - + NoControl - - 182, 110 + + 182, 111 - + 51, 13 - + 88 - + Max Freq - - label14 + + lblMAX_FREQ - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxLocal - - 57 + + 80 315, 12 @@ -4000,535 +5076,550 @@ this ensures you wont lose radio link groupBoxLocal - 59 - - - lblRRX_ENCAP_METHOD - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + 82 - - groupBoxRemote + + False - - 0 + + NoControl - - RRX_ENCAP_METHOD + + 209, 428 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 102, 29 - - groupBoxRemote + + 170 - - 1 + + Load from File... - - lblRTX_ENCAP_METHOD + + btnRemoteLoadFromFile - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null - + groupBoxRemote - - 2 - - - RTX_ENCAP_METHOD - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 0 - - groupBoxRemote + + False - - 3 + + NoControl - - lblRDESTID + + 317, 428 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 102, 29 - - groupBoxRemote + + 169 - - 4 + + Save to File... - - lblRNODEID + + btnRemoteSaveToFile - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null - + groupBoxRemote - - 5 - - - RDESTID - - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxRemote + + 1 - - 6 + + True - - RNODEID + + NoControl - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 427, 387 - - groupBoxRemote + + 100, 13 - - 7 + + 168 - - label41 + + Failsafe Frame Loss - + + lblRFSFRAMELOSS + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 8 + + 2 - - RFORMAT + + False - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 148, 432 - - 11 + + 23, 20 - - label42 + + 166 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + RGPO1_3AUXOUT - + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBoxRemote - - 12 + + 4 - - label25 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 10, 436 - - 17 + + 93, 13 + + + 165 - - label26 + + GPO1_3AUXOUT - + + lblRGPO1_3AUXOUT + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 19 + + 5 - - label27 + + False - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 148, 407 - - 21 + + 23, 20 - - label28 + + 164 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + RGPI1_2AUXIN + + + System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 22 + + 6 + + + True - - label29 + + NoControl - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 10, 411 - - groupBoxRemote + + 76, 13 - - 24 + + 163 - - label32 + + GPI1_2AUXIN - + + lblRGPI1_2AUXIN + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 25 + + 7 - - label30 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 174, 408 - - 26 + + 80, 13 - - label31 + + 162 - + + GPIO1_1FUNC + + + lblRGPIO1_1FUNC + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 27 + + 8 - - lblRANT_MODE + + False - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 266, 405 - - groupBoxRemote + + 80, 21 - - 28 + + 161 - - RANT_MODE + + RGPIO1_1FUNC - + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 29 - - - lblRSER_BRK_DETMS - - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 9 - - groupBoxRemote + + True - - 30 + + NoControl - - lblRGLOBAL_RETRIES + + 174, 386 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 95, 13 - - groupBoxRemote + + 158 - - 31 + + GPO1_0TXEN485 - - lblRMAX_RETRIES + + lblRGPO1_0TXEN485 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 32 + + 12 - - RSER_BRK_DETMS + + True - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 10, 386 - - 33 + + 97, 13 - - RGLOBAL_RETRIES + + 156 - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + GPO1_3STATLED - + + lblRGPO1_3STATLED + + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + groupBoxRemote - - 34 + + 14 - - RMAX_RETRIES + + False - - System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 425, 332 - - groupBoxRemote + + 102, 21 - - 35 + + 155 - - RMAX_DATA + + RGPO1_3SBUSOUT - + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 36 - - - lblRMAX_DATA + + 15 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + False - - groupBoxRemote + + NoControl - - 37 + + 425, 428 - - label38 + + 102, 29 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 87 - - groupBoxRemote + + Set PPM Fail Safe - - 38 + + Record default PPM stream for PPM output (vehicle side) - - RENCRYPTION_LEVEL + + BUT_SetPPMFailSafeRemote - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null - + groupBoxRemote - - 39 - - - txt_Raeskey - - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 16 - - groupBoxRemote + + True - - 40 + + NoControl - - label37 + + 364, 18 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + 46, 13 - - groupBoxRemote + + 154 - - 41 + + Country: - - label33 + + label50 - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 43 + + 17 - - label34 + + 367, 38 - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + True - - groupBoxRemote + + 61, 39 - - 44 + + 153 - - label24 + + txtRCountry - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 46 + + 18 - - label23 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 357, 311 - - 52 + + 103, 13 + + + 152 + + + GPO1_3SBUSOUT: - - label22 + + lblRSBUSOUT - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 53 + + 19 - - label21 + + True - - System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 10, 336 - - 54 + + 88, 13 + + + 150 + + + GPO1_3SBUSIN - - label20 + + lblRSBUSIN - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 55 + + 20 - - RTI2 + + True - - System.Windows.Forms.TextBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + NoControl - - groupBoxRemote + + 10, 361 - - 56 + + 81, 13 - - label9 + + 148 - + + Rate/FreqBand + + + label46 + + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 57 + + 22 - - 551, 48 + + False - - 533, 361 + + 121, 357 - - 81 + + 406, 21 - - Remote + + 147 - - groupBoxRemote + + RRATE_FREQBAND - - System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + System.Windows.Forms.ComboBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - $this + + groupBoxRemote - - 6 + + 23 True @@ -4537,7 +5628,7 @@ this ensures you wont lose radio link NoControl - 352, 195 + 357, 186 58, 13 @@ -4561,10 +5652,10 @@ this ensures you wont lose radio link groupBoxRemote - 0 + 24 - 442, 188 + 447, 182 80, 21 @@ -4585,7 +5676,7 @@ this ensures you wont lose radio link groupBoxRemote - 1 + 25 True @@ -4594,7 +5685,7 @@ this ensures you wont lose radio link NoControl - 352, 167 + 357, 161 57, 13 @@ -4618,10 +5709,10 @@ this ensures you wont lose radio link groupBoxRemote - 2 + 26 - 442, 160 + 447, 157 80, 21 @@ -4642,7 +5733,7 @@ this ensures you wont lose radio link groupBoxRemote - 3 + 27 True @@ -4651,7 +5742,7 @@ this ensures you wont lose radio link NoControl - 352, 139 + 357, 136 43, 13 @@ -4675,7 +5766,7 @@ this ensures you wont lose radio link groupBoxRemote - 4 + 28 True @@ -4684,7 +5775,7 @@ this ensures you wont lose radio link NoControl - 352, 111 + 357, 111 47, 13 @@ -4708,10 +5799,10 @@ this ensures you wont lose radio link groupBoxRemote - 5 + 29 - 442, 132 + 447, 132 80, 21 @@ -4732,10 +5823,10 @@ this ensures you wont lose radio link groupBoxRemote - 6 + 30 - 442, 104 + 447, 107 80, 21 @@ -4756,40 +5847,40 @@ this ensures you wont lose radio link groupBoxRemote - 7 + 31 - + True - + NoControl - - 10, 326 + + 10, 311 - - 86, 13 + + 91, 13 - + 121 - - GPI1_1R/COUT + + GPO1_1R/COUT - - label41 + + lblRGPO1_1R_COUT - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 8 + + 32 - 88, 83 + 88, 82 80, 20 @@ -4807,187 +5898,187 @@ this ensures you wont lose radio link groupBoxRemote - 11 + 35 - + True - + NoControl - - 10, 300 + + 10, 286 - + 74, 13 - + 118 - + GPI1_1R/CIN - - label42 + + lblRGPI1_1R_CIN - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 12 + + 36 - + True - + NoControl - - 11, 274 + + 11, 261 - + 61, 13 - + 129 - + Op Resend - - label25 + + lblROPPRESEND - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 17 + + 41 - + True - + NoControl - - 11, 247 + + 11, 236 - + 44, 13 - + 128 - + Mavlink - - label26 + + lblRMAVLINK - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 19 + + 43 - + True - + NoControl - - 11, 220 + + 11, 211 - + 28, 13 - + 127 - + ECC - - label27 + + lblRECC - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 21 + + 45 - + True - + NoControl - - 11, 193 + + 11, 186 - + 52, 13 - + 126 - + Tx Power - - label28 + + lblRTXPOWER - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 22 + + 46 - + True - + NoControl - - 11, 166 + + 11, 161 - + 38, 13 - + 125 - + Net ID - - label29 + + lblRNETID - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 24 + + 48 True @@ -4996,7 +6087,7 @@ this ensures you wont lose radio link NoControl - 11, 113 + 11, 111 32, 13 @@ -5017,7 +6108,7 @@ this ensures you wont lose radio link groupBoxRemote - 25 + 49 True @@ -5026,7 +6117,7 @@ this ensures you wont lose radio link NoControl - 11, 139 + 11, 136 53, 13 @@ -5047,7 +6138,7 @@ this ensures you wont lose radio link groupBoxRemote - 26 + 50 True @@ -5056,7 +6147,7 @@ this ensures you wont lose radio link NoControl - 11, 87 + 11, 86 39, 13 @@ -5077,7 +6168,7 @@ this ensures you wont lose radio link groupBoxRemote - 27 + 51 True @@ -5086,7 +6177,7 @@ this ensures you wont lose radio link NoControl - 354, 332 + 357, 86 77, 13 @@ -5097,9 +6188,6 @@ this ensures you wont lose radio link Antenna Mode - - False - lblRANT_MODE @@ -5110,10 +6198,13 @@ this ensures you wont lose radio link groupBoxRemote - 28 + 52 + + + False - 442, 328 + 447, 82 80, 21 @@ -5121,9 +6212,6 @@ this ensures you wont lose radio link 108 - - False - RANT_MODE @@ -5134,7 +6222,7 @@ this ensures you wont lose radio link groupBoxRemote - 29 + 53 True @@ -5143,7 +6231,7 @@ this ensures you wont lose radio link NoControl - 352, 307 + 357, 286 84, 13 @@ -5167,7 +6255,7 @@ this ensures you wont lose radio link groupBoxRemote - 30 + 54 True @@ -5176,7 +6264,7 @@ this ensures you wont lose radio link NoControl - 352, 279 + 357, 261 73, 13 @@ -5200,7 +6288,7 @@ this ensures you wont lose radio link groupBoxRemote - 31 + 55 True @@ -5209,7 +6297,7 @@ this ensures you wont lose radio link NoControl - 352, 251 + 357, 236 63, 13 @@ -5233,10 +6321,10 @@ this ensures you wont lose radio link groupBoxRemote - 32 + 56 - 442, 300 + 447, 282 80, 21 @@ -5257,10 +6345,10 @@ this ensures you wont lose radio link groupBoxRemote - 33 + 57 - 442, 272 + 447, 257 80, 21 @@ -5281,10 +6369,10 @@ this ensures you wont lose radio link groupBoxRemote - 34 + 58 - 442, 244 + 447, 232 80, 21 @@ -5305,10 +6393,10 @@ this ensures you wont lose radio link groupBoxRemote - 35 + 59 - 442, 216 + 447, 207 80, 21 @@ -5329,7 +6417,7 @@ this ensures you wont lose radio link groupBoxRemote - 36 + 60 True @@ -5338,7 +6426,7 @@ this ensures you wont lose radio link NoControl - 352, 223 + 357, 211 53, 13 @@ -5362,7 +6450,7 @@ this ensures you wont lose radio link groupBoxRemote - 37 + 61 True @@ -5371,7 +6459,7 @@ this ensures you wont lose radio link NoControl - 174, 300 + 174, 286 49, 13 @@ -5392,40 +6480,13 @@ this ensures you wont lose radio link groupBoxRemote - 38 - - - False - - - NoControl - - - 266, 271 - - - 80, 20 - - - 90 - - - RENCRYPTION_LEVEL - - - System.Windows.Forms.CheckBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - groupBoxRemote - - - 39 + 62 - 168, 316 + 168, 307 - 32 + 64 180, 20 @@ -5443,247 +6504,247 @@ this ensures you wont lose radio link groupBoxRemote - 40 + 63 - + True - + NoControl - - 173, 272 + + 173, 261 - + 81, 13 - + 92 - + AES Encryption - - label37 + + lblRENCRYPTION_LEVEL - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 41 + + 64 - + True - + NoControl - - 173, 218 + + 173, 211 - + 53, 13 - + 99 - + RTS CTS - - label33 + + lblRRTSCTS - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 43 + + 66 - + True - + NoControl - - 174, 247 + + 174, 236 - + 91, 13 - + 97 - + Max Window (ms) - - label34 + + lblRMAX_WINDOW - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 44 + + 67 - + True - + NoControl - - 174, 87 + + 174, 86 - + 48, 13 - + 87 - + Min Freq - - label24 + + lblRMIN_FREQ - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 46 + + 69 - + True - + NoControl - + 174, 111 - + 51, 13 - + 88 - + Max Freq - - label23 + + lblRMAX_FREQ - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 52 + + 75 - + True - + NoControl - - 174, 139 + + 174, 136 - + 73, 13 - + 89 - + # of Channels - - label22 + + lblRNUM_CHANNELS - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 53 + + 76 - + True - + NoControl - - 174, 165 + + 174, 161 - + 58, 13 - + 93 - + Duty Cycle - - label21 + + lblRDUTY_CYCLE - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 54 + + 77 - + True - + NoControl - - 174, 192 + + 174, 186 - + 50, 13 - + 95 - + LBT Rssi - - label20 + + lblRLBT_RSSI - + System.Windows.Forms.Label, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - + groupBoxRemote - - 55 + + 78 300, 12 @@ -5707,7 +6768,7 @@ this ensures you wont lose radio link groupBoxRemote - 56 + 79 True @@ -5737,7 +6798,31 @@ this ensures you wont lose radio link groupBoxRemote - 57 + 80 + + + 551, 48 + + + 533, 463 + + + 81 + + + Remote + + + groupBoxRemote + + + System.Windows.Forms.GroupBox, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + $this + + + 5 True @@ -5764,40 +6849,19 @@ this ensures you wont lose radio link $this - 5 - - - False - - - NoControl - - - 551, 411 - - - 102, 29 - - - 86 - - - Set PPM Fail Safe - - - Record default PPM stream for PPM output (vehicle side) - - - BUT_SetPPMFailSafe - - - MissionPlanner.Controls.MyButton, SikRadio, Version=0.0.7428.29620, Culture=neutral, PublicKeyToken=null + 4 - - $this + + 114, 17 + + + INI Files|*.ini - - 1 + + 208, 17 + + + INI Files|*.ini NoControl @@ -5818,13 +6882,13 @@ this ensures you wont lose radio link BUT_loadcustom - MissionPlanner.Controls.MyButton, SikRadio, Version=0.0.7428.29620, Culture=neutral, PublicKeyToken=null + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null $this - 2 + 1 NoControl @@ -5845,13 +6909,46 @@ this ensures you wont lose radio link BUT_resettodefault - MissionPlanner.Controls.MyButton, SikRadio, Version=0.0.7428.29620, Culture=neutral, PublicKeyToken=null + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null $this - 3 + 2 + + + False + + + NoControl + + + 425, 428 + + + 102, 29 + + + 86 + + + Set PPM Fail Safe + + + Record default PPM stream for PPM output (vehicle side) + + + BUT_SetPPMFailSafe + + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null + + + groupBoxLocal + + + 17 False @@ -5875,13 +6972,13 @@ this ensures you wont lose radio link BUT_savesettings - MissionPlanner.Controls.MyButton, SikRadio, Version=0.0.7428.29620, Culture=neutral, PublicKeyToken=null + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null $this - 9 + 8 NoControl @@ -5902,13 +6999,13 @@ this ensures you wont lose radio link BUT_getcurrent - MissionPlanner.Controls.MyButton, SikRadio, Version=0.0.7428.29620, Culture=neutral, PublicKeyToken=null + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null $this - 10 + 9 NoControl @@ -5925,17 +7022,20 @@ this ensures you wont lose radio link Upload Firmware (Local) + + False + BUT_upload - MissionPlanner.Controls.MyButton, SikRadio, Version=0.0.7428.29620, Culture=neutral, PublicKeyToken=null + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null $this - 12 + 11 False @@ -5944,7 +7044,7 @@ this ensures you wont lose radio link NoControl - 443, 412 + 457, 518 102, 29 @@ -5959,13 +7059,73 @@ this ensures you wont lose radio link BUT_Syncoptions - MissionPlanner.Controls.MyButton, SikRadio, Version=0.0.7428.29620, Culture=neutral, PublicKeyToken=null + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null $this - 8 + 7 + + + False + + + NoControl + + + 317, 428 + + + 102, 29 + + + 163 + + + Save to File... + + + btnSaveToFile + + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null + + + groupBoxLocal + + + 1 + + + False + + + NoControl + + + 209, 428 + + + 102, 29 + + + 164 + + + Load from File... + + + btnLoadFromFile + + + MissionPlanner.Controls.MyButton, RFD900Tools, Version=0.2.63.0, Culture=neutral, PublicKeyToken=null + + + groupBoxLocal + + + 0 True @@ -5977,7 +7137,7 @@ this ensures you wont lose radio link 781, 492 - 1096, 492 + 1096, 608 toolTip1 @@ -5985,6 +7145,18 @@ this ensures you wont lose radio link System.Windows.Forms.ToolTip, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + dlgSave + + + System.Windows.Forms.SaveFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + dlgOpen + + + System.Windows.Forms.OpenFileDialog, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + Sikradio diff --git a/Radio/Sikradio.zh-Hant.resx b/Radio/Sikradio.zh-Hant.resx index 1fc40fb9c6..00fad60940 100644 --- a/Radio/Sikradio.zh-Hant.resx +++ b/Radio/Sikradio.zh-Hant.resx @@ -117,6 +117,23 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 12, 389 + + + 755, 36 + + + + 2 + + + 17, 17 + + + False + 115 @@ -144,18 +161,75 @@ 1 + + 81, 29 + + + 80, 21 + + + 4 + 鮑率的單位為 kbps. 所以 57 表示為 57600. + + True + + + 3, 32 + + + 32, 13 + + + 5 + 鮑率 + + 81, 3 + + + 80, 20 + + + 7 + + + True + + + 3, 6 + + + 39, 13 + + + 8 + 格式版本 + + True + + + 3, 59 + + + 53, 13 + + + 10 + 速率(空中) + + False + 250 @@ -195,12 +269,36 @@ 2 + + 81, 56 + + + 80, 21 + + + 9 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + True + + + 3, 86 + + + 38, 13 + + + 12 + 網路 ID + + False + 1 @@ -291,12 +389,36 @@ 30 + + 81, 83 + + + 80, 21 + + + 11 + "網路 ID" 由 16 位元組成。這被用於發送跳頻順序並確保資料來自正確的無線電。請確保您和其他人是使用不同的"網路 ID" 除非你想要在同一個區域使用相同網域的無線電。 + + True + + + 3, 113 + + + 52, 13 + + + 14 + 發射功率 + + False + 1 @@ -321,32 +443,128 @@ 20 + + 81, 110 + + + 80, 21 + + + 13 + 發射功率的單位為 dBm。 20dBm 就是 100mW。這個值的設定對於較低階的短距離測試非常有用。 + + True + + + 3, 138 + + + 28, 13 + + + 16 + ECC 校檢 + + False + + + 81, 137 + + + 80, 20 + + + 15 + ECC 是設定啟用/關閉格雷的糾正碼。預設為關閉。如果啟用它你的資料會需要多一倍的字節發送,所以你會損失一半的頻寬,但是它最多能糾正每12位的數據中3位的錯誤。使用於遠距離時通常需配合較低的無線數據傳輸率。格雷解碼每個字節需要20微秒(每位元組則需要40微秒),也就是說在較高的傳輸速率時你的 CPU 會受到限制。所以速率最好不要超過 128kbps。 + + True + + + 3, 167 + + + 44, 13 + + + 18 + Mavlink 協議 + + True + + + 3, 194 + + + 61, 13 + + + 20 + 伺機重送 + + False + + + 81, 191 + + + 80, 20 + + + 19 + - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + + False + + + 83, 191 + + + 80, 20 + + + 29 + - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + + False + + + 83, 137 + + + 80, 20 + + + 27 + ECC 是設定啟用/關閉格雷的糾正碼。預設為關閉。如果啟用它你的資料會需要多一倍的字節發送,所以你會損失一半的頻寬,但是它最多能糾正每12位的數據中3位的錯誤。使用於遠距離時通常需配合較低的無線數據傳輸率。格雷解碼每個字節需要20微秒(每位元組則需要40微秒),也就是說在較高的傳輸速率時你的 CPU 會受到限制。所以速率最好不要超過 128kbps。 + + False + 1 @@ -371,10 +589,22 @@ 20 + + 83, 110 + + + 80, 21 + + + 26 + - 發射功率的單位為 dBm。 20dBm 就是 100mW。這個值的設定對於較低階的短距離測試非常有用。 + 發射功率的單位為 dBm。 20dBm 就是 100mW。這個值的設定對於較低階的短距離測試非常有用。 + + False + 1 @@ -465,9 +695,21 @@ 30 + + 83, 83 + + + 80, 21 + + + 25 + "網路 ID" 由 16 位元組成。這被用於發送跳頻順序並確保資料來自正確的無線電。請確保您和其他人是使用不同的"網路 ID" 除非你想要在同一個區域使用相同網域的無線電。 + + False + 250 @@ -507,9 +749,21 @@ 2 + + 83, 56 + + + 80, 21 + + + 24 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + False + 115 @@ -537,20 +791,44 @@ 1 + + 83, 29 + + + 80, 21 + + + 22 + - 鮑率的單位為 kbps. 所以 57 表示為 57600. + 鮑率的單位為 kbps. 所以 57 表示為 57600. + + 59, 38 + + + True + + + 250, 39 + + + 34 + - see the spec for a RSSI to dBm graph. The numbers at the end are: -txe: 發射端錯誤代碼 (eg. transmit timeouts) -rxe: 接收端錯誤代碼 (crc error, framing error etc) -stx: 發射端溢位錯誤代碼 -rrx: 接收端溢位錯誤代碼 -ecc: number of 12 bit words successfully corrected by the golay code -which result in a valid packet CRC + see the spec for a RSSI to dBm graph. The numbers at the end are: +txe: 發射端錯誤代碼 (eg. transmit timeouts) +rxe: 接收端錯誤代碼 (crc error, framing error etc) +stx: 發射端溢位錯誤代碼 +rrx: 接收端溢位錯誤代碼 +ecc: number of 12 bit words successfully corrected by the golay code +which result in a valid packet CRC + + False + 5 @@ -608,9 +886,21 @@ which result in a valid packet CRC 50 + + 96, 55 + + + 80, 21 + + + 42 + 跳頻的頻道數 + + False + 10 @@ -641,27 +931,63 @@ which result in a valid packet CRC 100 + + 96, 82 + + + 80, 21 + + + 43 + 允許傳送的時間百分比 + + False + 0 25 + + 96, 109 + + + 80, 21 + + + 44 + 先接收後傳送 + + False + 0 25 + + 97, 109 + + + 80, 21 + + + 56 + 先接收後傳送 + + False + 10 @@ -692,9 +1018,21 @@ which result in a valid packet CRC 100 + + 97, 82 + + + 80, 21 + + + 55 + 允許傳送的時間百分比 + + False + 5 @@ -752,9 +1090,21 @@ which result in a valid packet CRC 50 + + 97, 55 + + + 80, 21 + + + 54 + 跳頻的頻道數 + + False + 902000 @@ -782,9 +1132,21 @@ which result in a valid packet CRC 435000 + + 96, 28 + + + 80, 21 + + + 41 + 終止頻率的單位 kHz + + False + 902000 @@ -821,9 +1183,21 @@ which result in a valid packet CRC + + 96, 3 + + + 80, 21 + + + 46 + 起始頻率的單位 kHz + + False + 902000 @@ -851,9 +1225,21 @@ which result in a valid packet CRC 435000 + + 97, 3 + + + 80, 21 + + + 58 + 起始頻率的單位 kHz + + False + 902000 @@ -881,19 +1267,43 @@ which result in a valid packet CRC 435000 + + 97, 28 + + + 80, 21 + + + 53 + 終止頻率的單位 kHz + + True + + + 689, 11 + + + 63, 13 + + + 83 + Led 狀態說明 - 3DR 數傳有 2 個狀態指示燈, 一紅一綠。 -綠色 LED 閃爍 - 尋找另一個數傳中 -綠色 LED 恆亮 - 已連結另一個數傳 -紅色 LED 閃爍 - 資料傳輸中 + 3DR 數傳有 2 個狀態指示燈, 一紅一綠。 +綠色 LED 閃爍 - 尋找另一個數傳中 +綠色 LED 恆亮 - 已連結另一個數傳 +紅色 LED 閃爍 - 資料傳輸中 紅色 LED 恆亮 - 韌體更新中 + + False + 0 @@ -987,9 +1397,21 @@ which result in a valid packet CRC 30 + + 96, 164 + + + 80, 21 + + + 52 + 節點 ID。預設 ID 為 0。在多點作業的環境需要有一點為基礎點 。 + + False + 0 @@ -1083,124 +1505,800 @@ which result in a valid packet CRC 30 + + 97, 164 + + + 80, 21 + + + 64 + 節點 ID。預設 ID 為 0。在多點作業的環境需要有一點為基礎點 。 + + False + + + 81, 164 + + + 80, 21 + + + 21 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + False + + + 83, 163 + + + 80, 21 + + + 22 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + False + + + + NoControl + + + 96, 136 + + + 80, 20 + + + 56 + 開啟或關閉硬體流量控制 + + False + + + NoControl + + + 97, 136 + + + 80, 20 + + + 66 + 開啟或關閉硬體流量控制 + + 83, 3 + + + 80, 20 + + + 23 + + + 138, 12 + + + 102, 20 + + + 33 + + + 59, 12 + + + 147, 20 + + + 32 + + + True + + + 14, 15 + + + 42, 13 + + + 36 + 韌體版本 + + True + + + 18, 50 + + + 32, 13 + + + 37 + 信號強度 + + False + + + 237, 3 + + + 69, 39 + + + 21 + 儲存設定 + + 162, 3 + + + 69, 39 + + + 6 + 載入設定 + + 12, 361 + + + 310, 22 + + + 3 + + + 312, 3 + + + 121, 39 + + + 0 + 更新韌體 (地面端) + + True + + + NoControl + + + 4, 6 + + + 48, 13 + + + 47 + 跳頻 起始頻率 + + True + + + NoControl + + + 4, 31 + + + 51, 13 + + + 48 + 跳頻 終止頻率 + + True + + + NoControl + + + 4, 58 + + + 73, 13 + + + 49 + 跳頻 頻道數 + + True + + + NoControl + + + 4, 85 + + + 58, 13 + + + 50 + 允許發射時間% + + True + + + NoControl + + + 4, 112 + + + 50, 13 + + + 51 + 避開已用頻率 + + True + + + NoControl + + + 5, 112 + + + 50, 13 + + + 63 + 避開已用頻率 + + True + + + NoControl + + + 5, 85 + + + 58, 13 + + + 62 + 允許發射時間% + + True + + + NoControl + + + 5, 58 + + + 73, 13 + + + 61 + 跳頻 頻道數 + + True + + + NoControl + + + 5, 31 + + + 51, 13 + + + 60 + 跳頻 終止頻率 + + True + + + NoControl + + + 5, 6 + + + 48, 13 + + + 59 + 跳頻 起始頻率 + + True + + + NoControl + + + 6, 199 + + + 61, 13 + + + 72 + 伺機重送 + + True + + + NoControl + + + 6, 167 + + + 44, 13 + + + 71 + Mavlink 協議 + + True + + + NoControl + + + 6, 140 + + + 28, 13 + + + 70 + ECC 校檢 + + True + + + NoControl + + + 6, 113 + + + 52, 13 + + + 69 + 發射功率 + + True + + + NoControl + + + 6, 86 + + + 38, 13 + + + 68 + 網路 ID + + True + + + NoControl + + + 6, 59 + + + 53, 13 + + + 67 + 速率(空中) + + True + + + NoControl + + + 6, 6 + + + 39, 13 + + + 66 + 格式版本 + + True + + + NoControl + + + 6, 32 + + + 32, 13 + + + 65 + 鮑率 + + True + + + 4, 81 + + + True + + + NoControl + + + 3, 138 + + + 53, 13 + + + 57 + 流量管制 + + True + + + NoControl + + + 7, 189 + + + 146, 13 + + + 55 + 重設為標準 Mavlink 協議 + + True + + + 7, 202 + + + 124, 13 + + + 54 + 重設為最小延遲 + + True + + + NoControl + + + 4, 167 + + + 91, 13 + + + 53 + 最大窗口 (ms) + + 374, 221 + + + 172 + + + 1 + + + 0 + + + True + + + 4, 81 + + + True + + + NoControl + + + 4, 138 + + + 53, 13 + + + 67 + 流量管制 + + True + + + NoControl + + + 5, 167 + + + 91, 13 + + + 65 + 最大窗口 (ms) + + 357, 221 + + + 170 + + + 1 + + + 0 + + + False + + + NoControl + + + 346, 355 + + + 102, 29 + + + 78 + 複製設定至機上端 + + 207, 12 + + + 102, 20 + + + 79 + + + 12, 48 + + + 382, 306 + + + 80 + 地面端 + + 315, 12 + + + True + + + 61, 65 + + + 80 + + + 400, 48 + + + 367, 306 + + + 81 + 機上端 + + 246, 12 + + + True + + + 61, 65 + + + 81 + + + True + + + NoControl + + + 12, 15 + + + 42, 13 + + + 37 + 韌體版本 + + True + + + NoControl + + + 9, 11 + + + 0, 13 + + + 82 + + + NoControl + + + 439, 3 + + + 82, 39 + + + 84 + 還原出廠值 + + NoControl + + + 527, 3 + + + 96, 39 + + + 85 + 更新客制化韌體 + + True + + + 6, 13 + + + 781, 433 + \ No newline at end of file diff --git a/Radio/Sikradio.zh-TW.resx b/Radio/Sikradio.zh-TW.resx index 1fc40fb9c6..00fad60940 100644 --- a/Radio/Sikradio.zh-TW.resx +++ b/Radio/Sikradio.zh-TW.resx @@ -117,6 +117,23 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + 12, 389 + + + 755, 36 + + + + 2 + + + 17, 17 + + + False + 115 @@ -144,18 +161,75 @@ 1 + + 81, 29 + + + 80, 21 + + + 4 + 鮑率的單位為 kbps. 所以 57 表示為 57600. + + True + + + 3, 32 + + + 32, 13 + + + 5 + 鮑率 + + 81, 3 + + + 80, 20 + + + 7 + + + True + + + 3, 6 + + + 39, 13 + + + 8 + 格式版本 + + True + + + 3, 59 + + + 53, 13 + + + 10 + 速率(空中) + + False + 250 @@ -195,12 +269,36 @@ 2 + + 81, 56 + + + 80, 21 + + + 9 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + True + + + 3, 86 + + + 38, 13 + + + 12 + 網路 ID + + False + 1 @@ -291,12 +389,36 @@ 30 + + 81, 83 + + + 80, 21 + + + 11 + "網路 ID" 由 16 位元組成。這被用於發送跳頻順序並確保資料來自正確的無線電。請確保您和其他人是使用不同的"網路 ID" 除非你想要在同一個區域使用相同網域的無線電。 + + True + + + 3, 113 + + + 52, 13 + + + 14 + 發射功率 + + False + 1 @@ -321,32 +443,128 @@ 20 + + 81, 110 + + + 80, 21 + + + 13 + 發射功率的單位為 dBm。 20dBm 就是 100mW。這個值的設定對於較低階的短距離測試非常有用。 + + True + + + 3, 138 + + + 28, 13 + + + 16 + ECC 校檢 + + False + + + 81, 137 + + + 80, 20 + + + 15 + ECC 是設定啟用/關閉格雷的糾正碼。預設為關閉。如果啟用它你的資料會需要多一倍的字節發送,所以你會損失一半的頻寬,但是它最多能糾正每12位的數據中3位的錯誤。使用於遠距離時通常需配合較低的無線數據傳輸率。格雷解碼每個字節需要20微秒(每位元組則需要40微秒),也就是說在較高的傳輸速率時你的 CPU 會受到限制。所以速率最好不要超過 128kbps。 + + True + + + 3, 167 + + + 44, 13 + + + 18 + Mavlink 協議 + + True + + + 3, 194 + + + 61, 13 + + + 20 + 伺機重送 + + False + + + 81, 191 + + + 80, 20 + + + 19 + - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + + False + + + 83, 191 + + + 80, 20 + + + 29 + - OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + OPPRESEND enables/disables "opportunistic resend". When enabled the radio will send a packet twice if the serial input buffer has less than 256 bytes in it. The 2nd send is marked as a resend and discarded by the receiving radio if it got the first packet OK. This makes a big difference to the link quality, especially for uplink commands. + + False + + + 83, 137 + + + 80, 20 + + + 27 + ECC 是設定啟用/關閉格雷的糾正碼。預設為關閉。如果啟用它你的資料會需要多一倍的字節發送,所以你會損失一半的頻寬,但是它最多能糾正每12位的數據中3位的錯誤。使用於遠距離時通常需配合較低的無線數據傳輸率。格雷解碼每個字節需要20微秒(每位元組則需要40微秒),也就是說在較高的傳輸速率時你的 CPU 會受到限制。所以速率最好不要超過 128kbps。 + + False + 1 @@ -371,10 +589,22 @@ 20 + + 83, 110 + + + 80, 21 + + + 26 + - 發射功率的單位為 dBm。 20dBm 就是 100mW。這個值的設定對於較低階的短距離測試非常有用。 + 發射功率的單位為 dBm。 20dBm 就是 100mW。這個值的設定對於較低階的短距離測試非常有用。 + + False + 1 @@ -465,9 +695,21 @@ 30 + + 83, 83 + + + 80, 21 + + + 25 + "網路 ID" 由 16 位元組成。這被用於發送跳頻順序並確保資料來自正確的無線電。請確保您和其他人是使用不同的"網路 ID" 除非你想要在同一個區域使用相同網域的無線電。 + + False + 250 @@ -507,9 +749,21 @@ 2 + + 83, 56 + + + 80, 21 + + + 24 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + False + 115 @@ -537,20 +791,44 @@ 1 + + 83, 29 + + + 80, 21 + + + 22 + - 鮑率的單位為 kbps. 所以 57 表示為 57600. + 鮑率的單位為 kbps. 所以 57 表示為 57600. + + 59, 38 + + + True + + + 250, 39 + + + 34 + - see the spec for a RSSI to dBm graph. The numbers at the end are: -txe: 發射端錯誤代碼 (eg. transmit timeouts) -rxe: 接收端錯誤代碼 (crc error, framing error etc) -stx: 發射端溢位錯誤代碼 -rrx: 接收端溢位錯誤代碼 -ecc: number of 12 bit words successfully corrected by the golay code -which result in a valid packet CRC + see the spec for a RSSI to dBm graph. The numbers at the end are: +txe: 發射端錯誤代碼 (eg. transmit timeouts) +rxe: 接收端錯誤代碼 (crc error, framing error etc) +stx: 發射端溢位錯誤代碼 +rrx: 接收端溢位錯誤代碼 +ecc: number of 12 bit words successfully corrected by the golay code +which result in a valid packet CRC + + False + 5 @@ -608,9 +886,21 @@ which result in a valid packet CRC 50 + + 96, 55 + + + 80, 21 + + + 42 + 跳頻的頻道數 + + False + 10 @@ -641,27 +931,63 @@ which result in a valid packet CRC 100 + + 96, 82 + + + 80, 21 + + + 43 + 允許傳送的時間百分比 + + False + 0 25 + + 96, 109 + + + 80, 21 + + + 44 + 先接收後傳送 + + False + 0 25 + + 97, 109 + + + 80, 21 + + + 56 + 先接收後傳送 + + False + 10 @@ -692,9 +1018,21 @@ which result in a valid packet CRC 100 + + 97, 82 + + + 80, 21 + + + 55 + 允許傳送的時間百分比 + + False + 5 @@ -752,9 +1090,21 @@ which result in a valid packet CRC 50 + + 97, 55 + + + 80, 21 + + + 54 + 跳頻的頻道數 + + False + 902000 @@ -782,9 +1132,21 @@ which result in a valid packet CRC 435000 + + 96, 28 + + + 80, 21 + + + 41 + 終止頻率的單位 kHz + + False + 902000 @@ -821,9 +1183,21 @@ which result in a valid packet CRC + + 96, 3 + + + 80, 21 + + + 46 + 起始頻率的單位 kHz + + False + 902000 @@ -851,9 +1225,21 @@ which result in a valid packet CRC 435000 + + 97, 3 + + + 80, 21 + + + 58 + 起始頻率的單位 kHz + + False + 902000 @@ -881,19 +1267,43 @@ which result in a valid packet CRC 435000 + + 97, 28 + + + 80, 21 + + + 53 + 終止頻率的單位 kHz + + True + + + 689, 11 + + + 63, 13 + + + 83 + Led 狀態說明 - 3DR 數傳有 2 個狀態指示燈, 一紅一綠。 -綠色 LED 閃爍 - 尋找另一個數傳中 -綠色 LED 恆亮 - 已連結另一個數傳 -紅色 LED 閃爍 - 資料傳輸中 + 3DR 數傳有 2 個狀態指示燈, 一紅一綠。 +綠色 LED 閃爍 - 尋找另一個數傳中 +綠色 LED 恆亮 - 已連結另一個數傳 +紅色 LED 閃爍 - 資料傳輸中 紅色 LED 恆亮 - 韌體更新中 + + False + 0 @@ -987,9 +1397,21 @@ which result in a valid packet CRC 30 + + 96, 164 + + + 80, 21 + + + 52 + 節點 ID。預設 ID 為 0。在多點作業的環境需要有一點為基礎點 。 + + False + 0 @@ -1083,124 +1505,800 @@ which result in a valid packet CRC 30 + + 97, 164 + + + 80, 21 + + + 64 + 節點 ID。預設 ID 為 0。在多點作業的環境需要有一點為基礎點 。 + + False + + + 81, 164 + + + 80, 21 + + + 21 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + False + + + 83, 163 + + + 80, 21 + + + 22 + 速率是無線資料傳輸率單位為 kbps。128 表示 128kbps。 最大值為 192,最小值為 2。我不建議這個頻率低於 16 這樣會造成 tdm 同步時間太久。 + + False + + + + NoControl + + + 96, 136 + + + 80, 20 + + + 56 + 開啟或關閉硬體流量控制 + + False + + + NoControl + + + 97, 136 + + + 80, 20 + + + 66 + 開啟或關閉硬體流量控制 + + 83, 3 + + + 80, 20 + + + 23 + + + 138, 12 + + + 102, 20 + + + 33 + + + 59, 12 + + + 147, 20 + + + 32 + + + True + + + 14, 15 + + + 42, 13 + + + 36 + 韌體版本 + + True + + + 18, 50 + + + 32, 13 + + + 37 + 信號強度 + + False + + + 237, 3 + + + 69, 39 + + + 21 + 儲存設定 + + 162, 3 + + + 69, 39 + + + 6 + 載入設定 + + 12, 361 + + + 310, 22 + + + 3 + + + 312, 3 + + + 121, 39 + + + 0 + 更新韌體 (地面端) + + True + + + NoControl + + + 4, 6 + + + 48, 13 + + + 47 + 跳頻 起始頻率 + + True + + + NoControl + + + 4, 31 + + + 51, 13 + + + 48 + 跳頻 終止頻率 + + True + + + NoControl + + + 4, 58 + + + 73, 13 + + + 49 + 跳頻 頻道數 + + True + + + NoControl + + + 4, 85 + + + 58, 13 + + + 50 + 允許發射時間% + + True + + + NoControl + + + 4, 112 + + + 50, 13 + + + 51 + 避開已用頻率 + + True + + + NoControl + + + 5, 112 + + + 50, 13 + + + 63 + 避開已用頻率 + + True + + + NoControl + + + 5, 85 + + + 58, 13 + + + 62 + 允許發射時間% + + True + + + NoControl + + + 5, 58 + + + 73, 13 + + + 61 + 跳頻 頻道數 + + True + + + NoControl + + + 5, 31 + + + 51, 13 + + + 60 + 跳頻 終止頻率 + + True + + + NoControl + + + 5, 6 + + + 48, 13 + + + 59 + 跳頻 起始頻率 + + True + + + NoControl + + + 6, 199 + + + 61, 13 + + + 72 + 伺機重送 + + True + + + NoControl + + + 6, 167 + + + 44, 13 + + + 71 + Mavlink 協議 + + True + + + NoControl + + + 6, 140 + + + 28, 13 + + + 70 + ECC 校檢 + + True + + + NoControl + + + 6, 113 + + + 52, 13 + + + 69 + 發射功率 + + True + + + NoControl + + + 6, 86 + + + 38, 13 + + + 68 + 網路 ID + + True + + + NoControl + + + 6, 59 + + + 53, 13 + + + 67 + 速率(空中) + + True + + + NoControl + + + 6, 6 + + + 39, 13 + + + 66 + 格式版本 + + True + + + NoControl + + + 6, 32 + + + 32, 13 + + + 65 + 鮑率 + + True + + + 4, 81 + + + True + + + NoControl + + + 3, 138 + + + 53, 13 + + + 57 + 流量管制 + + True + + + NoControl + + + 7, 189 + + + 146, 13 + + + 55 + 重設為標準 Mavlink 協議 + + True + + + 7, 202 + + + 124, 13 + + + 54 + 重設為最小延遲 + + True + + + NoControl + + + 4, 167 + + + 91, 13 + + + 53 + 最大窗口 (ms) + + 374, 221 + + + 172 + + + 1 + + + 0 + + + True + + + 4, 81 + + + True + + + NoControl + + + 4, 138 + + + 53, 13 + + + 67 + 流量管制 + + True + + + NoControl + + + 5, 167 + + + 91, 13 + + + 65 + 最大窗口 (ms) + + 357, 221 + + + 170 + + + 1 + + + 0 + + + False + + + NoControl + + + 346, 355 + + + 102, 29 + + + 78 + 複製設定至機上端 + + 207, 12 + + + 102, 20 + + + 79 + + + 12, 48 + + + 382, 306 + + + 80 + 地面端 + + 315, 12 + + + True + + + 61, 65 + + + 80 + + + 400, 48 + + + 367, 306 + + + 81 + 機上端 + + 246, 12 + + + True + + + 61, 65 + + + 81 + + + True + + + NoControl + + + 12, 15 + + + 42, 13 + + + 37 + 韌體版本 + + True + + + NoControl + + + 9, 11 + + + 0, 13 + + + 82 + + + NoControl + + + 439, 3 + + + 82, 39 + + + 84 + 還原出廠值 + + NoControl + + + 527, 3 + + + 96, 39 + + + 85 + 更新客制化韌體 + + True + + + 6, 13 + + + 781, 433 + \ No newline at end of file diff --git a/Radio/Uploader.cs b/Radio/Uploader.cs index cb1609121c..e4395bf678 100644 --- a/Radio/Uploader.cs +++ b/Radio/Uploader.cs @@ -24,6 +24,9 @@ public enum Board : byte DEVICE_ID_RFD900U = 0X80 | 0x01, DEVICE_ID_RFD900P = 0x80 | 0x02, DEVICE_ID_RFD900X = 0x80 | 0x03, + DEVICE_ID_RFD900X2 = 0x80 | 0x04, + DEVICE_ID_RFD900UX2 = 0x80 | 0x05, + DEVICE_ID_RFD900UX = 0x80 | 0x08, FAILED = 0x11 diff --git a/Radio/XModem.cs b/Radio/XModem.cs index 027de004aa..90b81ea475 100644 --- a/Radio/XModem.cs +++ b/Radio/XModem.cs @@ -54,75 +54,135 @@ public static void SendBlock(FileStream fs, ICommsSerial Serial, int bNumber) var bytesRead = fs.Read(bits, 0, bits.Length); - if (bytesRead == bits.Length) - { - CRC = CRC_calc(bits, 128); - System.Buffer.BlockCopy(bits, 0, packet, 3, 128); - packet[131] = (byte)(CRC >> 8); - packet[132] = (byte)(CRC); - Serial.Write(packet, 0, packet.Length); - } - else if (bytesRead > 0) + CRC = CRC_calc(bits, 128); + System.Buffer.BlockCopy(bits, 0, packet, 3, 128); + packet[131] = (byte)(CRC >> 8); + packet[132] = (byte)(CRC); + Serial.Write(packet, 0, packet.Length); + } + + /// + /// + /// + /// Must be no more than 128 bytes in length. Must not be null. + /// + /// + public static void SendBlock(byte[] data, int DataLength, ICommsSerial Serial, int bNumber) + { + byte[] packet = new byte[133]; + byte[] bits = new byte[128]; + UInt16 CRC = 0; + + for (int i = 0; i < bits.Length; i++) { bits[i] = 0x26; } + + packet[0] = SOH; + packet[1] = (byte)(bNumber % 256); + packet[2] = (byte)(255 - (bNumber % 256)); + + Array.Copy(data, bits, DataLength); + + CRC = CRC_calc(bits, 128); + System.Buffer.BlockCopy(bits, 0, packet, 3, 128); + packet[131] = (byte)(CRC >> 8); + packet[132] = (byte)(CRC); + Serial.DiscardInBuffer(); + Serial.Write(packet, 0, packet.Length); + } + + static void SendEOT(ICommsSerial Serial) + { + Serial.Write(new byte[] { EOT }, 0, 1); + ProgressEvent?.Invoke(100); + } + + static bool UploadBlock(ICommsSerial comPort, byte[] Data, int DataLength, int bNumber) + { + for (int Retry = 0; Retry < 10; Retry++) { - CRC = CRC_calc(bits, 128); - System.Buffer.BlockCopy(bits, 0, packet, 3, 128); - packet[131] = (byte)(CRC >> 8); - packet[132] = (byte)(CRC); - Serial.Write(packet, 0, packet.Length); - Serial.Write(new byte[] { EOT }, 0, 1); - ProgressEvent?.Invoke(100); + //comPort.DiscardInBuffer(); + SendBlock(Data, DataLength, comPort, bNumber); + // responce ACK + var ack = comPort.ReadByte(); + while (ack == 'C') + { + ack = comPort.ReadByte(); + } + + if (ack == ACK) + { + return true; + } + + //Thread.Sleep(1000); } - else if (bytesRead == 0) + + return false; + } + + static bool UploadEnd(ICommsSerial comPort) + { + for (int Retry = 0; Retry < 10; Retry++) { - Serial.Write(new byte[] { EOT }, 0, 1); - ProgressEvent?.Invoke(100); + SendEOT(comPort); + + var ack = comPort.ReadByte(); + while (ack == 'C') + ack = comPort.ReadByte(); + + if (ack == ACK) + { + return true; + } + + //Thread.Sleep(1000); } + + /*MsgBox.CustomMessageBox.Show("Corrupted packet. Please power cycle and try again.\r\n", "Warning", + MessageBoxButtons.OK, MessageBoxIcon.Warning);*/ + return false; } - public static void Upload(string firmwarebin, ICommsSerial comPort) + public static bool Upload(string firmwarebin, ICommsSerial comPort) { comPort.ReadTimeout = 2000; - using (var fs = new FileStream(firmwarebin, FileMode.Open)) + using (var fs = new FileStream(firmwarebin, FileMode.OpenOrCreate,FileAccess.Read)) { var len = (int)fs.Length; len = (len % 128) == 0 ? len / 128 : (len / 128) + 1; var startlen = len; int a = 1; - int NoAckCount = 0; while (len > 0) { LogEvent?.Invoke("Uploading block " + a + "/" + startlen); - SendBlock(fs, comPort, a); - // responce ACK - var ack = comPort.ReadByte(); - while (ack == 'C') - ack = comPort.ReadByte(); + byte[] Data = new byte[128]; - if (ack == ACK) + var bytesRead = fs.Read(Data, 0, Data.Length); + + if (UploadBlock(comPort, Data, bytesRead, a)) { - NoAckCount = 0; len--; a++; - ProgressEvent?.Invoke(1 - ((double)len / (double)startlen)); } - else if (ack == NAK) - { - MsgBox.CustomMessageBox.Show("Corrupted packet. Please power cycle and try again.\r\n", "Warning", - MessageBoxButtons.OK, MessageBoxIcon.Warning); - len = 0; - } else { - NoAckCount++; - if (NoAckCount >= 10) - { - } + /*MsgBox.CustomMessageBox.Show("Corrupted packet. Please power cycle and try again.\r\n", "Warning", + MessageBoxButtons.OK, MessageBoxIcon.Warning);*/ + len = 0; + + return false; } } + + if (!UploadEnd(comPort)) + { + return false; + } + + //Console.WriteLine("Finished " + len.ToString()); } // boot @@ -131,6 +191,8 @@ public static void Upload(string firmwarebin, ICommsSerial comPort) Thread.Sleep(100); comPort.Write("BOOTNEW\r\n"); Thread.Sleep(100); + + return true; } } } diff --git a/SikRadio/ComPort.cs b/SikRadio/ComPort.cs new file mode 100644 index 0000000000..5dd3ce8ef1 --- /dev/null +++ b/SikRadio/ComPort.cs @@ -0,0 +1,18 @@ +using System; +using MissionPlanner.Comms; + +namespace MissionPlanner.Radio +{ + public static class ComPort + { + public static ICommsSerial GetComPortForSiKRadio() + { + return SikRadio.Config.comPort; + } + + public static void FinishedWithComPortForSiKRadio() + { + } + } + +} \ No newline at end of file diff --git a/SikRadio/Config.cs b/SikRadio/Config.cs index d11c1cf25d..898307b654 100644 --- a/SikRadio/Config.cs +++ b/SikRadio/Config.cs @@ -64,7 +64,7 @@ private ISikRadioForm loadSettings() var form = new Sikradio(); form.Enabled = false; - form.GetCommsSerialAlt = () => SikRadio.Config.comPort; + form.DoDisconnectReconnect += DoDisconnectReconnect; panel1.Controls.Add(form); @@ -113,6 +113,15 @@ private ISikRadioForm loadRssi() return form; } + void DoDisconnectReconnect() + { + if (_Connected) + { + Disconnect(); + Connect(); + } + } + private void CMB_SerialPort_SelectedIndexChanged(object sender, EventArgs e) { MainV2.comPort.BaseStream.PortName = CMB_SerialPort.Text; @@ -152,6 +161,7 @@ void ShowForm(Func Constructor) } _CurrentForm = Constructor(); _CurrentForm.Enabled = _Connected; + groupBox2.Text = _CurrentForm.Header; _CurrentForm.Show(); if (_Connected) { @@ -174,53 +184,9 @@ private void rssiToolStripMenuItem_Click(object sender, EventArgs e) ShowForm(loadRssi); } - void getTelemPortWithRadio(ref ICommsSerial comPort) - { - // try telem1 - - comPort = new MAVLinkSerialPort(MainV2.comPort, (int)MAVLink.SERIAL_CONTROL_DEV.TELEM1); - - comPort.ReadTimeout = 4000; - - comPort.Open(); - } - bool Connect() { - try - { - if (MainV2.comPort.BaseStream.PortName.Contains("TCP")) - { - _comPort = new TcpSerial(); - _comPort.BaudRate = MainV2.comPort.BaseStream.BaudRate; - _comPort.ReadTimeout = 4000; - _comPort.Open(); - } - else - { - _comPort = new SerialPort(); - - if (MainV2.comPort.BaseStream.IsOpen) - { - getTelemPortWithRadio(ref _comPort); - } - else - { - _comPort.PortName = MainV2.comPort.BaseStream.PortName; - _comPort.BaudRate = MainV2.comPort.BaseStream.BaudRate; - } - - _comPort.ReadTimeout = 4000; - - _comPort.Open(); - } - - return true; - } - catch - { - return false; - } + return Sikradio.Connect(ref _comPort); } bool Disconnect() diff --git a/SikRadio/Config.resx b/SikRadio/Config.resx index ee1684c823..16a68d4a7e 100644 --- a/SikRadio/Config.resx +++ b/SikRadio/Config.resx @@ -205,7 +205,7 @@ 781, 433 - 1127, 502 + 1127, 622 2 @@ -313,7 +313,7 @@ 12, 108 - 1132, 527 + 1132, 631 8 @@ -454,7 +454,7 @@ 42 - 1156, 639 + 1156, 743 diff --git a/SikRadio/ISikRadioForm.cs b/SikRadio/ISikRadioForm.cs index eeab6dc8ef..ec67d03385 100644 --- a/SikRadio/ISikRadioForm.cs +++ b/SikRadio/ISikRadioForm.cs @@ -8,5 +8,6 @@ public interface ISikRadioForm : IDisposable void Disconnect(); void Show(); bool Enabled { get; set; } + string Header { get; } } } \ No newline at end of file diff --git a/SikRadio/Program.cs b/SikRadio/Program.cs index 826e388b06..7e681fccca 100644 --- a/SikRadio/Program.cs +++ b/SikRadio/Program.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Windows.Forms; using log4net; using log4net.Config; @@ -8,6 +8,26 @@ namespace SikRadio internal static class Program { private static readonly ILog log = LogManager.GetLogger("Program"); + private const string MANUFACTURER_PASSWORD = "--manufacturing"; + private const string ALLOW_DIFF_PROG = "--allowdiffprog"; + private static bool _Manufacturer = false; + private static bool _AllowDiffProg = false; + + public static bool Manufacturer + { + get + { + return _Manufacturer; + } + } + + public static bool AllowDiffProg + { + get + { + return _AllowDiffProg; + } + } /// /// The main entry point for the application. @@ -15,6 +35,18 @@ internal static class Program [STAThread] private static void Main(string[] args) { + foreach (var arg in args) + { + if (RFDLib.Text.Contains(arg, MANUFACTURER_PASSWORD)) + { + _Manufacturer = true; + } + if (RFDLib.Text.Contains(arg, ALLOW_DIFF_PROG)) + { + _AllowDiffProg = true; + } + } + log.Info("App Start"); XmlConfigurator.Configure(); diff --git a/SikRadio/Properties/AssemblyInfo.cs b/SikRadio/Properties/AssemblyInfo.cs index 84f9190bfa..133ed2071e 100644 --- a/SikRadio/Properties/AssemblyInfo.cs +++ b/SikRadio/Properties/AssemblyInfo.cs @@ -36,4 +36,4 @@ // [assembly: AssemblyVersion("1.0.*")] [assembly: AssemblyVersion("0.0.*")] -[assembly: AssemblyFileVersion("0.0.0.0")] \ No newline at end of file +[assembly: AssemblyFileVersion("0.0.0.0")] diff --git a/SikRadio/Properties/Resources.Designer.cs b/SikRadio/Properties/Resources.Designer.cs index 127522ddce..ebf5a332ba 100644 --- a/SikRadio/Properties/Resources.Designer.cs +++ b/SikRadio/Properties/Resources.Designer.cs @@ -60,6 +60,16 @@ internal Resources() { } } + /// + /// Looks up a localized resource of type System.Byte[]. + /// + internal static byte[] RFDSiK_V3_00_rfd900x { + get { + object obj = ResourceManager.GetObject("RFDSiK_V3_00_rfd900x", resourceCulture); + return ((byte[])(obj)); + } + } + /// /// Looks up a localized resource of type System.Drawing.Bitmap. /// diff --git a/SikRadio/Properties/Resources.resx b/SikRadio/Properties/Resources.resx index 780715af2f..81432cbd0c 100644 --- a/SikRadio/Properties/Resources.resx +++ b/SikRadio/Properties/Resources.resx @@ -118,6 +118,9 @@ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + ..\Resources\RFDSiK V3.00 rfd900x.bin;System.Byte[], mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + ..\Resources\sik.png;System.Drawing.Bitmap, System.Drawing, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a diff --git a/SikRadio/RFD900.cs b/SikRadio/RFD900.cs index 14da57b4d5..18f82e16d1 100644 --- a/SikRadio/RFD900.cs +++ b/SikRadio/RFD900.cs @@ -2,6 +2,8 @@ using System.Collections.Generic; using System.Threading; using MissionPlanner.Radio; +using System.IO; +using System.Reflection; namespace RFD.RFD900 { @@ -13,11 +15,47 @@ public class TSession : IDisposable TMode _Mode = TMode.INIT; MissionPlanner.Comms.ICommsSerial _Port; public Uploader.Board Board = Uploader.Board.FAILED; + RFDLib.IO.ATCommand.TClient _ATCClient; + RFD900 _ModemObject; + int _MainFirmwareBaud; + /// + /// This is a work-around for radio firmware bugs in which not all settings + /// are described by an RTI5? command. + /// + Dictionary _DefaultSettings = new Dictionary(); + const int BOOTLOADERX_BAUD = 57600; const int BOOTLOADER_BAUD = 115200; + const string NODEID = "NODEID"; + const string NODEDESTINATION = "NODEDESTINATION"; - public TSession(MissionPlanner.Comms.ICommsSerial Port) + public TSession(MissionPlanner.Comms.ICommsSerial Port, int MainFirmwareBaud) { _Port = Port; + _ATCClient = new TATCClient(new TMissionPlannerSerialPort(Port)); + _ATCClient.Echoes = true; + _ATCClient.Terminator = "\r\n"; + _ATCClient.Timeout = 1000; + _MainFirmwareBaud = MainFirmwareBaud; + + // This is a work-around for radio firmware bugs in which not all settings + // are described by an RTI5? command. + AddDefaultSetting("S21:GPO1_3STATLED(N)[0..1]=0{Off,On,}\r\n"); + AddDefaultSetting("S22:GPO1_0TXEN485(N)[0..1]=0{Off,On,}\r\n"); + AddDefaultSetting("S23:RATE/FREQBAND(N)[0..3]=0{LoAus,HiAus,StdNZ,LoUSA,HiUSA,StdEU,LbtEU,StdPRC,StdINS,HiLbtJAP,HiStdJAP,LoLbtJAP,LoStdJAP,}\r\n"); + AddDefaultSetting("S20:ANT_MODE(N)[0..3]=0{Ant1&2,Ant1,Ant2,Ant1=TX;2=RX,}\r\n"); + } + + /// + /// Add a setting to the _DefaultSettings which is generated by parsing the given ATI5? query response line. + /// + /// The ATI5? query response line + void AddDefaultSetting(string ATI5QueryResponseLine) + { + var S = TSession.ParseATI5QueryResponseLine(ATI5QueryResponseLine); + if (S != null) + { + _DefaultSettings[S.Name] = S; + } } public enum TMode @@ -28,6 +66,11 @@ public enum TMode BOOTLOADER, //For a,u,+ BOOTLOADER_X, //For x UNKNOWN + } + + public void WriteToPort(string ToWrite) + { + _Port.Write(ToWrite); } public void Dispose() @@ -40,13 +83,13 @@ public bool WaitForToken(string Token, int MaxWait) return WaitForAnyOfTheseTokens(new string[] { Token }, MaxWait) >= 0; } - /// - /// Wait for any of these tokens to be received on the port. - /// Wait up to MaxWait milliseconds. If a token was received, return the array index of - /// the token. If no tokens received, return -1. - /// - /// The tokens to wait for. Must not be null. - /// The max wait time in milliseconds. + /// + /// Wait for any of these tokens to be received on the port. + /// Wait up to MaxWait milliseconds. If a token was received, return the array index of + /// the token. If no tokens received, return -1. + /// + /// The tokens to wait for. Must not be null. + /// The max wait time in milliseconds. /// The token array index of the token received, or -1 is none of the tokens received. public int WaitForAnyOfTheseTokens(string[] Tokens, int MaxWait) { @@ -58,20 +101,37 @@ public int WaitForAnyOfTheseTokens(string[] Tokens, int MaxWait) while (SW.ElapsedMilliseconds < MaxWait) { - string x = _Port.ReadExisting(); - Temp += x; - - for (int n = 0; n < Tokens.Length; n++) - { - if (Temp.Contains(Tokens[n])) - { - _Port.ReadTimeout = Timeout; - return n; + try + { + int Byte; + while (((Byte = _Port.ReadByte()) != -1) && (SW.ElapsedMilliseconds < MaxWait)) + { + //string x = _Port.ReadExisting(); + Temp += ((char)Byte); + + for (int n = 0; n < Tokens.Length; n++) + { + if (Temp.Contains(Tokens[n])) + { + _Port.ReadTimeout = Timeout; + return n; + } + } } + + Thread.Sleep(50); } + catch (Exception e) + { + //System.Diagnostics.Debug.WriteLine(e.Message); + //System.Diagnostics.Debug.WriteLine("No tokens, got " + Temp); - Thread.Sleep(50); + return -1; + } } + + //Console.WriteLine("Failed to get token, got this instead: " + Temp); + _Port.ReadTimeout = Timeout; return -1; } @@ -84,7 +144,6 @@ void WriteBootloaderCode(Uploader.Code Code) bool IsInBootloaderMode() { - int PrevBaud = _Port.BaudRate; _Port.BaudRate = BOOTLOADER_BAUD; Thread.Sleep(100); WriteBootloaderCode(Uploader.Code.EOC); @@ -103,7 +162,7 @@ bool IsInBootloaderMode() } if (!Result) { - _Port.BaudRate = PrevBaud; + _Port.BaudRate = _MainFirmwareBaud; } return Result; } @@ -114,6 +173,9 @@ bool IsInBootloaderMode() /// bool IsInBootloaderXMode() { + int PrevBaud = _Port.BaudRate; + _Port.BaudRate = BOOTLOADERX_BAUD; + //for (int n = 0; n < 3; n++) { Thread.Sleep(200); @@ -125,19 +187,16 @@ bool IsInBootloaderXMode() _Port.Write("CHIPID\r\n"); if (WaitForToken("RFD", 200)) { + //Leave baud rate at bootloader X baud rate. return true; } } + _Port.BaudRate = PrevBaud; return false; } - TMode DetermineMode() - { - if (IsInBootloaderXMode()) - { - return TMode.BOOTLOADER_X; - } - + bool TryEscapeFromTransparent() + { _Port.ReadTimeout = 2000; //Console.WriteLine("Waiting 1500ms"); Thread.Sleep(1500); @@ -145,10 +204,16 @@ TMode DetermineMode() //Console.WriteLine("Sending +++"); _Port.Write("+++"); //Console.WriteLine("Waiting up to 1.5s for OK"); - if (WaitForToken("OK\r\n", 1500)) + return WaitForToken("OK\r\n", 1500); + } + + TMode DetermineMode() + { + if (IsInBootloaderXMode()) { - return TMode.AT_COMMAND; + return TMode.BOOTLOADER_X; } + //Check if already in AT command mode. _Port.DiscardInBuffer(); _Port.Write("\r\n"); @@ -158,6 +223,12 @@ TMode DetermineMode() { return TMode.AT_COMMAND; } + + if (TryEscapeFromTransparent() || TryEscapeFromTransparent()) + { + return TMode.AT_COMMAND; + } + //Not in transparent or at command mode. Probably in bootloader mode. Need to verify. if (IsInBootloaderXMode()) { @@ -182,6 +253,14 @@ void CheckIfInBootloaderMode() } } + public RFDLib.IO.ATCommand.TClient ATCClient + { + get + { + return _ATCClient; + } + } + public MissionPlanner.Comms.ICommsSerial Port { get @@ -190,6 +269,79 @@ public MissionPlanner.Comms.ICommsSerial Port } } + /// + /// Get the modem object, assuming it can be put into AT command mode, or already is in AT command mode. + /// Returns null if could not get modem object. + /// + /// + public RFD900 GetModemObject() + { + if (_ModemObject == null) + { + switch (GetMode()) + { + case TMode.TRANSPARENT: + if (PutIntoATCommandMode() != TMode.AT_COMMAND) + { + return null; + } + goto case TMode.AT_COMMAND; + case TMode.AT_COMMAND: + string Result = _ATCClient.DoQuery("ATI2", true); + try + { + int Code = int.Parse(Result); + Uploader.Board Board = (Uploader.Board)Code; + switch (Board) + { + case Uploader.Board.DEVICE_ID_RFD900A: + _ModemObject = new RFD900a(this); + break; + case Uploader.Board.DEVICE_ID_RFD900P: + _ModemObject = new RFD900p(this); + break; + case Uploader.Board.DEVICE_ID_RFD900U: + _ModemObject = new RFD900u(this); + break; + case Uploader.Board.DEVICE_ID_RFD900UX: + _ModemObject = new RFD900ux(this); + break; + case Uploader.Board.DEVICE_ID_RFD900X: + _ModemObject = new RFD900x(this); + break; + case Uploader.Board.DEVICE_ID_RFD900X2: + _ModemObject = new RFD900X2(this); + break; + case Uploader.Board.DEVICE_ID_RFD900UX2: + _ModemObject = new RFD900UX2(this); + break; + } + } + catch + { + + } + + if (_ModemObject != null) + { + string ATIResponse = _ATCClient.DoQuery("ATI", true); + if (ATIResponse != null && ATIResponse.Contains("DINIO")) + { + _ModemObject.SetDINIO(); + } + } + break; + case TMode.BOOTLOADER: + _ModemObject = RFD900APU.GetObjectForModem(this); + break; + case TMode.BOOTLOADER_X: + _ModemObject = RFD900xux.GetObjectForModem(this); + break; + } + } + return _ModemObject; + } + public TMode GetMode() { if (_Mode == TMode.INIT) @@ -202,22 +354,22 @@ public TMode GetMode() public TMode PutIntoBootloaderMode() { var CurrentMode = GetMode(); - switch (CurrentMode) - { - case TMode.BOOTLOADER: - case TMode.BOOTLOADER_X: - break; - default: - CurrentMode = PutIntoATCommandMode(); - if (CurrentMode == TMode.AT_COMMAND) - { - _Port.Write("\r\n"); - Thread.Sleep(100); - _Port.Write("AT&UPDATE\r\n"); - Thread.Sleep(100); - CheckIfInBootloaderMode(); - } - break; + switch (CurrentMode) + { + case TMode.BOOTLOADER: + case TMode.BOOTLOADER_X: + break; + default: + CurrentMode = PutIntoATCommandMode(); + if (CurrentMode == TMode.AT_COMMAND) + { + _Port.Write("\r\n"); + Thread.Sleep(100); + _Port.Write("AT&UPDATE\r\n"); + Thread.Sleep(100); + CheckIfInBootloaderMode(); + } + break; } return GetMode(); @@ -231,10 +383,9 @@ public TMode PutIntoATCommandMode() case TMode.TRANSPARENT: return PutIntoATCommandModeAssumingInTransparentMode(); case TMode.BOOTLOADER: - int PrevBaud = _Port.BaudRate; _Port.BaudRate = BOOTLOADER_BAUD; WriteBootloaderCode(Uploader.Code.REBOOT); - _Port.BaudRate = PrevBaud; + _Port.BaudRate = _MainFirmwareBaud; _Mode = TMode.INIT; break; case TMode.BOOTLOADER_X: @@ -242,102 +393,130 @@ public TMode PutIntoATCommandMode() Thread.Sleep(100); _Port.Write("\r\n"); Thread.Sleep(100); - _Port.Write("BOOTNEW\r\n"); + _Port.Write("RESET\r\n"); Thread.Sleep(100); + _Port.BaudRate = _MainFirmwareBaud; _Mode = TMode.INIT; break; } return GetMode(); } - /// - /// Assuming in transparent mode, try to put it into AT command mode. - /// If fails, determine mode and then try again. + /// + /// Assuming in transparent mode, try to put it into AT command mode. + /// If fails, determine mode and then try again. /// - public TMode PutIntoATCommandModeAssumingInTransparentMode() - { + public TMode PutIntoATCommandModeAssumingInTransparentMode() + { _Port.ReadTimeout = 2000; //Console.WriteLine("Waiting 1500ms"); Thread.Sleep(1500); _Port.DiscardInBuffer(); //Console.WriteLine("Sending +++"); - _Port.Write("+++"); + _Port.Write("+++"); //Console.WriteLine("Waiting up to 3s for OK"); if (WaitForToken("OK\r\n", 3000)) { _Mode = TMode.AT_COMMAND; - return TMode.AT_COMMAND; - } - - _Mode = TMode.INIT; - return PutIntoATCommandMode(); + return TMode.AT_COMMAND; + } + + _Mode = TMode.INIT; + return PutIntoATCommandMode(); + } + + /// + /// Put into transparent mode. + /// + /// + public TMode PutIntoTransparentMode() + { + if (GetMode() == TMode.TRANSPARENT) + { + System.Diagnostics.Debug.WriteLine("Already in transparent mode"); + return TMode.TRANSPARENT; + } + else + { + if (PutIntoATCommandMode() == TMode.AT_COMMAND) + { + _Port.Write("\r\n"); + Thread.Sleep(100); + _Port.Write("ATO\r\n"); + Thread.Sleep(100); + if (WaitForToken("ATO\r\n", 100)) + { + System.Diagnostics.Debug.WriteLine("Put into transparent mode OK"); + } + else + { + System.Diagnostics.Debug.WriteLine("Failed to put into transparent mode"); + } + _Mode = TMode.TRANSPARENT; + return TMode.TRANSPARENT; + } + else + { + System.Diagnostics.Debug.WriteLine("Failed to put into AT cmd mode"); + return TMode.UNKNOWN; + } + } + } + + public void AssumeMode(TMode Mode) + { + if (Mode == TMode.BOOTLOADER_X) + { + _Port.BaudRate = BOOTLOADERX_BAUD; + } + else + { + _Port.BaudRate = _MainFirmwareBaud; + } + _Mode = Mode; } /// - /// Put into transparent mode. + /// Skip over the multipoint node number in an ATI5 or ATI5? response line. /// - /// - public TMode PutIntoTransparentMode() + /// The response line + /// The character index of the designator. + static int SkipMultipointNodeNumber(string Line) { - if (GetMode() == TMode.TRANSPARENT) - { - System.Diagnostics.Debug.WriteLine("Already in transparent mode"); - return TMode.TRANSPARENT; - } - else + int n = 0; + + for (; n < Line.Length; n++) { - if (PutIntoATCommandMode() == TMode.AT_COMMAND) - { - _Port.Write("\r\n"); - Thread.Sleep(100); - _Port.Write("ATO\r\n"); - Thread.Sleep(100); - if (WaitForToken("ATO\r\n", 100)) - { - System.Diagnostics.Debug.WriteLine("Put into transparent mode OK"); - } - else - { - System.Diagnostics.Debug.WriteLine("Failed to put into transparent mode"); - } - _Mode = TMode.TRANSPARENT; - return TMode.TRANSPARENT; - } - else + if (RFDLib.Text.CheckIsLetter(Line[n])) { - System.Diagnostics.Debug.WriteLine("Failed to put into AT cmd mode"); - return TMode.UNKNOWN; + return n; } } - } - - public void AssumeMode(TMode Mode) - { - _Mode = Mode; - } + return 0; + } + /// /// Parse the setting designator from the given Line and character positon. /// /// The ATI5? line. Must not be null. /// The current character position. /// - string ParseDesignator(string Line, ref int n) + static string ParseDesignator(string Line, ref int n) { - n = 0; + n = SkipMultipointNodeNumber(Line); string Designator = ""; - - if (RFDLib.Text.CheckIsLetter(Line[0])) + + if (RFDLib.Text.CheckIsLetter(Line[n])) { - Designator += Line[0]; + Designator += Line[n]; + n++; } else { return null; } - n = 1; - while (Line[n] != ':') { if (RFDLib.Text.CheckIsNumeral(Line[n])) @@ -354,7 +533,7 @@ string ParseDesignator(string Line, ref int n) return Designator; } - string ParseName(string Line, ref int n) + static string ParseName(string Line, ref int n) { string Name = ""; while (true) @@ -371,7 +550,7 @@ string ParseName(string Line, ref int n) } } - bool ParseType(string Line, ref int n) + static bool ParseType(string Line, ref int n) { for (; Line[n] != ')'; n++) { @@ -380,34 +559,60 @@ bool ParseType(string Line, ref int n) return true; } - bool ParseIntUntil(string Line, ref int n, string Delimiter, out int Value) + /// + /// Parse an integer from the given string, starting at the given character index until a delimiter + /// is reached. + /// + /// The string to parse from. Must not be null. + /// The start character index, to be updated to be at the end of the value + /// and/or delimiter. + /// The delimiter to end at. Can be null if not applicable. + /// The value parsed. + /// true if parsed, otherwise false. + static bool ParseIntUntil(string Line, ref int n, string Delimiter, out int Value) { string Temp = ""; + //Copy all the characters which are decimal numerals to Temp, incrementing + //n until it is at a non-numeral character. while ((n < Line.Length) && RFDLib.Text.CheckIsNumeral(Line[n])) { Temp += Line[n]; n++; } + //Parse Temp. Value = int.Parse(Temp); + //If no delimiter specified... if (Delimiter == null) { + //Just return now. return true; } else { + //If the delimiter exists in the string and it's at the current character index... if (Line.IndexOf(Delimiter, n) == n) { + //Move the character index to character after the end of it. n += Delimiter.Length; return true; } else { + //The delimiter doesn't exist. Return that failed. return false; } } } - TSetting.TRange ParseRange(string Line, ref int n) + /// + /// Parse a [min..max] range + /// + /// The ATI5? response line to parse from. Must not be null. + /// The index of the character to start parsing from. This is also updated to be + /// just after the end of the range. + /// The parameter name. Must not be null. + /// The range if successfully parsed, otherwise null. + static TSetting.TRange ParseRange(string Line, ref int n, string Name) { if (Line[n] != '[') { @@ -424,15 +629,15 @@ TSetting.TRange ParseRange(string Line, ref int n) { return null; } - return new TSetting.TRange(Min, Max); + return new TSetting.TSimpleRange(Min, Max, GetIncrement(Name)); } - bool ParseValue(string Line, ref int n, out int Value) + static bool ParseValue(string Line, ref int n, out int Value) { return ParseIntUntil(Line, ref n, null, out Value); } - bool CharArrayContains(char[] Array, char x) + static bool CharArrayContains(char[] Array, char x) { foreach (var c in Array) { @@ -444,7 +649,7 @@ bool CharArrayContains(char[] Array, char x) return false; } - string GetStringUntil(string Line, ref int n, char[] Tokens) + static string GetStringUntil(string Line, ref int n, char[] Tokens) { string Result = ""; while (!CharArrayContains(Tokens, Line[n])) @@ -455,7 +660,7 @@ string GetStringUntil(string Line, ref int n, char[] Tokens) return Result; } - string[] ParseOptions(string Line, ref int n) + static string[] ParseOptions(string Line, ref int n) { if (Line[n] != '{') { @@ -483,7 +688,13 @@ string[] ParseOptions(string Line, ref int n) return Options.ToArray(); } - int[] CheckIfAllIntegers(string[] Options) + /// + /// Try to parse every element in the given array of strings to integers. + /// If successful, return the corresponding array of integers, otherwise return null. + /// + /// The array of strings to convert. Must not be null. + /// The array of integers, or null if unsuccessful. + static int[] CheckIfAllIntegers(string[] Options) { int[] Result = new int[Options.Length]; @@ -497,18 +708,84 @@ int[] CheckIfAllIntegers(string[] Options) return Result; } - float GetScaleFactor(string Name) + static float GetScaleFactor(string Name, int[] Ints, int Value) { switch (Name) { case "SERIAL_SPEED": + foreach (var i in Ints) + { + if (i < 1000) + { + return 1; + } + } return 0.001F; + default: + if (Value != 0) + { + //Check if value matches one of the options divided by 1000. + foreach (var i in Ints) + { + if (i == Value) + { + return 1; + } + } + foreach (var i in Ints) + { + if ((i / 1000) == Value) + { + return 0.001F; + } + } + } + break; } return 1; } - TSetting.TOption[] CreateOptions(TSetting.TRange Range, string[] Options, - string Name) + static bool IsCapitalLetter(char Letter) + { + return (Letter >= 'A') && (Letter <= 'Z'); + } + + /* + * A new word starts when it goes from a lower case to upper case, + * or the character before the transition from upper case to lower. + */ + static string[] SplitOptionName(string OptionName) + { + int LastStart = 0; + List Result = new List(); + + for (int n = 1; n < OptionName.Length; n++) + { + if (IsCapitalLetter(OptionName[n]) && !IsCapitalLetter(OptionName[n-1])) + { + Result.Add(OptionName.Substring(LastStart, n - LastStart)); + LastStart = n; + } + else if (IsCapitalLetter(OptionName[n-1]) && !IsCapitalLetter(OptionName[n])) + { + if (LastStart != (n-1)) + { + Result.Add(OptionName.Substring(LastStart, n - LastStart-1)); + LastStart = n-1; + } + } + } + + if (LastStart < OptionName.Length) + { + Result.Add(OptionName.Substring(LastStart, OptionName.Length - LastStart)); + } + + return Result.ToArray(); + } + + static TSetting.TOption[] CreateOptions(TSetting.TRange Range, string[] Options, + string Name, int Value) { if (Range == null || Options == null) { @@ -516,10 +793,11 @@ TSetting.TOption[] CreateOptions(TSetting.TRange Range, string[] Options, } int[] Ints = CheckIfAllIntegers(Options); + //If all of the strings were integers... if (Ints != null) { TSetting.TOption[] Result = new TSetting.TOption[Ints.Length]; - float SF = GetScaleFactor(Name); + float SF = GetScaleFactor(Name, Ints, Value); for (int n = 0; n < Result.Length; n++) { Result[n] = new TSetting.TOption((int)(SF * Ints[n]), Options[n]); @@ -527,26 +805,95 @@ TSetting.TOption[] CreateOptions(TSetting.TRange Range, string[] Options, return Result; } - //Not all integers. - if (Range == null) - { - return null; - } + int[] RO = Range.GetOptionsIncludingValue(Value); if (Options.Length == 2) { //Match up with min and max. TSetting.TOption[] Result = new TSetting.TOption[2]; - Result[0] = new TSetting.TOption(Range.Min, Options[0]); - Result[1] = new TSetting.TOption(Range.Max, Options[1]); + + Result[0] = new TSetting.TOption(RO[0], Options[0]); + Result[1] = new TSetting.TOption(RO[RO.Length-1], Options[1]); return Result; } + else if (RO.Length == Options.Length) + { + TSetting.TOption[] Result = new TSetting.TOption[RO.Length]; + for (int n = 0; n < (RO.Length); n++) + { + Result[n] = new TSetting.TOption(RO[n], Options[n]); + } + return Result; + } + else if (RO.Length < Options.Length) + { + //Account for the freq/band setting. + string[] ResultOptionStrings = new string[RO.Length]; + string CountryCode = null; + int OptionIndex = 0; + bool GotToMax = false; + + //For each option... + foreach (var O in Options) + { + string[] Temp = SplitOptionName(O); + if (Temp.Length != 0) + { + //Extract country code from option name + string CCTemp = Temp[Temp.Length - 1]; + //If we're still on the same contry code... + if (CCTemp == CountryCode) + { + OptionIndex++; + if (OptionIndex >= (ResultOptionStrings.Length - 1)) + { + GotToMax = true; + } + } + else + { + OptionIndex = 0; + CountryCode = CCTemp; + } + + if (OptionIndex < ResultOptionStrings.Length) + { + if (ResultOptionStrings[OptionIndex] == null) + { + ResultOptionStrings[OptionIndex] = ""; + } + if (OptionIndex < ResultOptionStrings.Length) + { + if (ResultOptionStrings[OptionIndex].Length != 0) + { + ResultOptionStrings[OptionIndex] += "/"; + } + ResultOptionStrings[OptionIndex] += O; + } + } + } + } + + if (GotToMax) + { + TSetting.TOption[] Result = new TSetting.TOption[RO.Length]; + for (int n = 0; n < RO.Length; n++) + { + Result[n] = new TSetting.TOption(RO[n], ResultOptionStrings[n]); + } + return Result; + } + else + { + return null; + } + } else { return null; } } - int GetIncrement(string Name) + static int GetIncrement(string Name) { switch (Name) { @@ -569,7 +916,7 @@ int GetIncrement(string Name) /// /// The line. Must not be null. /// The setting parsed, or null if could not parse setting. - TSetting ParseATI5QueryResponseLine(string Line) + public static TSetting ParseATI5QueryResponseLine(string Line) { try { @@ -585,7 +932,9 @@ TSetting ParseATI5QueryResponseLine(string Line) n++; string Name = ParseName(Line, ref n); - if (Name == null || Name.Length == 0) + + //Ignore "reserved" setting (it's not a setting, just a reserved place for a setting). + if (Name == null || Name.Length == 0 || Name == "RESERVED") { return null; } @@ -596,7 +945,7 @@ TSetting ParseATI5QueryResponseLine(string Line) { return null; } - Range = ParseRange(Line, ref n); + Range = ParseRange(Line, ref n, Name); if (Range == null) { return null; @@ -631,7 +980,7 @@ TSetting ParseATI5QueryResponseLine(string Line) } return new TSetting(Designator, Name, Range, Value, - CreateOptions(Range, Options, Name), GetIncrement(Name)); + CreateOptions(Range, Options, Name, Value), GetIncrement(Name)); } catch { @@ -639,6 +988,47 @@ TSetting ParseATI5QueryResponseLine(string Line) } } + /// + /// Parse an ATI5 response line to a TShortSetting. + /// + /// + /// + TShortSetting ParseATI5ResponseLine(string Line) + { + try + { + int n = 0; + string Designator = ParseDesignator(Line, ref n); + if (Designator == null) + { + return null; + } + + n++; + string Name = ParseName(Line, ref n); + if (Name == null || Name.Length == 0) + { + return null; + } + if (Line[n] != '=') + { + return null; + } + n++; + + int Value; + if (!ParseValue(Line, ref n, out Value)) + { + return null; + } + return new TShortSetting(Designator, Name, Value); + } + catch + { + return null; + } + } + TSetting.TOption[] GetBaudRateOptionsGivenRawBaudRates(int[] Rates) { List Options = new List(); @@ -668,8 +1058,8 @@ TSetting.TOption[] GetDefaultBaudRateSettingForBoard(Uploader.Board Board) /// /// The full ATI5 query response. Must not be null. /// A dictionary of settings found, with name as key. Never null. - Dictionary ParseATI5QueryResponse(string ATI5Response, - Dictionary Dict) + Dictionary ParseATI5QueryResponse(string ATI5Response, + Dictionary Dict) { foreach (var Line in ATI5Response.Split('\n', '\r')) { @@ -683,32 +1073,456 @@ Dictionary ParseATI5QueryResponse(string ATI5Response, return Dict; } - public Dictionary GetSettings(string ATI5Response, - Uploader.Board Board) + Dictionary ParseATI5Response(string ATI5Response, + Dictionary Dict) { - Dictionary Result = new Dictionary(); - ParseATI5QueryResponse(ATI5Response, Result); - string SerialName = "SERIAL_SPEED"; - if (Result.ContainsKey(SerialName)) + foreach (var Line in ATI5Response.Split('\n', '\r')) { - if (Result[SerialName].Options == null) + var S = ParseATI5ResponseLine(Line); + if (S != null) { - Result[SerialName].Options = GetDefaultBaudRateSettingForBoard(Board); + Dict[S.Name] = S; } } - return Result; + + return Dict; } - } - public class TSetting - { + TTextSetting GetEncryptionKey(bool Remote) + { + string Temp = _ATCClient.DoQuery((Remote ? "R" : "A") + "T&E?", true); + + if (!Temp.Contains("OK") && !Temp.Contains("ERROR")) + { + foreach (char c in Temp) + { + if (!RFDLib.Text.CheckIsHexNumeral(c)) + { + return null; + } + } + + var Result = new TTextSetting(); + Result.Designator = "&E"; + Result.Name = ENC_KEY_SETTING_NAME; + Result.Text = Temp; + + return Result; + } + + return null; + } + + /// + /// Parse the ATI5? and ATI5 responses to get a set of settings objects. Settings are only returned if they're + /// in the ATI5QResponse, or Ranges. + /// + /// The ATI5? response + /// The board + /// The ATI5 response + /// A previous set of settings received to use the ranges from, in the + /// case that they can't be ascertained from ATI5QResponse. Can be null if not specified. + /// Never null + public Dictionary GetSettings(string ATI5QResponse, + Uploader.Board Board, string ATI5Response, + Dictionary Ranges, out bool UseRanges) + { + UseRanges = false; + + Dictionary Result = new Dictionary(); + ParseATI5QueryResponse(ATI5QResponse, Result); + + if (Result.Count == 0) + { + UseRanges = true; + } + else + { + string SerialName = "SERIAL_SPEED"; + if (Result.ContainsKey(SerialName) && Result[SerialName] is TSetting) + { + if (((TSetting)Result[SerialName]).Options == null) + { + ((TSetting)Result[SerialName]).Options = GetDefaultBaudRateSettingForBoard(Board); + } + } + } + + //The code below is all done to work-around the case of SiK RFD900x 3.07 bug in + //which are RTI5? commands response is cut-off for settings S21 through S23. + Dictionary ShortSettings = new Dictionary(); + ParseATI5Response(ATI5Response, ShortSettings); + + if (UseRanges && (Ranges != null)) + { + Result = CopySettingsButUseDifferentRanges(ShortSettings, Ranges); + } + + foreach (var kvp in _DefaultSettings) + { + if (ShortSettings.ContainsKey(kvp.Key) && !Result.ContainsKey(kvp.Key)) + { + kvp.Value.Value = ShortSettings[kvp.Key].Value; + Result[kvp.Key] = kvp.Value; + } + } + + //If the result contains a nodeid and nodedestination parameter, it's multipoint firmware + //and it needs its settings ranges modified... + //We want the node dest to have the same options as node id, except we want the + //last value parsed for node dest to be appended to the end for the node dest. + if (Result.ContainsKey(NODEID) && Result.ContainsKey(NODEDESTINATION) && + Result[NODEID] is TSetting && Result[NODEDESTINATION] is TSetting) + { + var NodeIDRange = ((TSetting)Result[NODEID]).Range; + var NodeDestRange = ((TSetting)Result[NODEDESTINATION]).Range; + //If the destination id range is null... + if (NodeDestRange == null) + { + //Do nothing + } + else if (NodeIDRange != null) + { + //Both parameters have parsed ranges... + if (NodeIDRange is TSetting.TSimpleRange) + { + //The node id range is a simple range. + var NodeIDOptions = NodeIDRange.GetOptionsIncludingValue(((TSetting)Result[NODEID]).Value); + var NodeDestOptions = NodeDestRange.GetOptionsIncludingValue(((TSetting)Result[NODEDESTINATION]).Value); + if (NodeDestOptions[NodeDestOptions.Length-1] > NodeIDOptions[NodeIDOptions.Length-1]) + { + ((TSetting)Result[NODEDESTINATION]).Range = new TSetting.TMultiRange(new TSetting.TSimpleRange[] + { + (TSetting.TSimpleRange)NodeIDRange, + new TSetting.TSimpleRange(NodeDestOptions[NodeDestOptions.Length-1], NodeDestOptions[NodeDestOptions.Length-1], 1) + } + ); + } + } + } + } + + return Result; + } + + /// + /// Copy the given dictionary of Values, but use the specified valid ranges/options + /// in the given Settings dictionary if they exist in there. + /// + /// This is useful for the case + /// of a local modem returning a full "ATI5?" reply, but the remote modem only returning + /// an "RTI5" reply. In this case, the values returned from RTI5 can be used, but the + /// ATI5? reply is used to assume the valid ranges of the settings of the remote modem. + /// + /// The values to use in the result. + /// The ranges/options to use in the result. + /// The resulting settings which contains the same values as Values, but has ranges/options + /// as specified in Settings (if they exist in there) + public Dictionary CopySettingsButUseDifferentRanges( + Dictionary Values, + Dictionary Settings) + { + Dictionary Result = new Dictionary(); + + foreach (var kvp in Values) + { + if (Settings.ContainsKey(kvp.Key) && Settings[kvp.Key] is TSetting) + { + var S = (TSetting)Settings[kvp.Key].Clone(); + S.Value = kvp.Value.Value; + Result[kvp.Key] = S; + } + } + + return Result; + } + + /// + /// Use the newer ATI10 command to assemble the same format string as the old ATI5? command. + /// ATI5? command has been deprecated, and ATI10 is used in its place. Returns the complete string, + /// or null if unsuccessful. + /// + /// The complete string, or null if unsuccessful. + public string UseATI10ToGetATI5QueryResponse(bool Remote) + { + int ParamIndex; + string Result = ""; + string Prefix = Remote ? "RTI10:" : "ATI10:"; + + for (ParamIndex = 0; ; ParamIndex++) + { + string Line = ATCClient.DoQuery(Prefix + ParamIndex.ToString(), true); + if (RFDLib.Text.Contains(Line, "error") || (Line.Length == 0)) + { + return null; + } + else if (RFDLib.Text.Contains(Line, "eof") || !Line.Contains("=")) + { + return Result; + } + else + { + Result += Line + "\r\n"; + } + } + } + + /// + /// Query the remote modem for its settings valid ranges and parse the given RTI5 response to get a set of settings objects. + /// + /// The board + /// The RTI5 response + /// A previous set of settings received to use the ranges from, in the + /// case that they can't be ascertained from querying the modem. Can be null if not specified. + /// Never null + public Dictionary GetSettings(bool Remote, Uploader.Board Board, string ATI5Response, + Dictionary Ranges, out bool UseRanges) + { + string ATI5QR = UseATI10ToGetATI5QueryResponse(Remote); + if (ATI5QR == null || (ATI5QR.Length == 0)) + { + ATI5QR = ATCClient.DoQueryWithMultiLineResponse(Remote ? "RTI5?" : "ATI5?"); + } + + var Result = GetSettings(ATI5QR, Board, ATI5Response, Ranges, out UseRanges); + + var EncKey = GetEncryptionKey(Remote); + + if (EncKey != null) + { + Result[ENC_KEY_SETTING_NAME] = EncKey; + } + + return Result; + } + + const string ENC_KEY_SETTING_NAME = "AESKEY"; + } + + public class TSettings + { + Dictionary _Settings = new Dictionary(); + const string MIN_FREQ = "MIN_FREQ"; + const string MAX_FREQ = "MAX_FREQ"; + + public TSettings(Dictionary Settings) + { + _Settings = Settings; + } + + public Dictionary Settings + { + get + { + return _Settings; + } + } + + public TSettings Clone() + { + Dictionary Temp = new Dictionary(); + + foreach (var kvp in _Settings) + { + Temp[kvp.Key] = (TBaseSetting)kvp.Value.Clone(); + } + + return new TSettings(Temp); + } + + public bool SaveToFile(string Path) + { + try + { + using (StreamWriter Writer = File.CreateText(Path)) + { + //Save in alphabetical order... + List Names = new List(_Settings.Keys); + Names.Sort(); + + foreach (var N in Names) + { + Writer.WriteLine(N + " = " + _Settings[N].GetValueAsString()); + } + } + + return true; + } + catch + { + return false; + } + } + + TNameAndValue ParseINILine(string Line) + { + if (!Line.Trim().StartsWith(";") && !Line.Trim().StartsWith("#")) + { + string[] ContentAndComment = Line.Split(';', '#'); + + if (ContentAndComment.Length >= 1) + { + string Content = ContentAndComment[0]; + + if (Content.Contains("=")) + { + string[] NameAndValue = Content.Split('='); + + if (NameAndValue.Length == 2) + { + string Name = NameAndValue[0].Trim(); + + return new TNameAndValue(Name, NameAndValue[1].Trim()); + } + } + } + } + + return null; + } + + /// + /// Update these settings from a file. + /// + /// The path of the settings file. Must not be null. + /// The names and values loaded. Null if failed. + public Dictionary LoadFromFile(string Path) + { + Dictionary Result = new Dictionary(); + + try + { + using (StreamReader Reader = File.OpenText(Path)) + { + string Line; + + while ((Line = Reader.ReadLine()) != null) + { + var NV = ParseINILine(Line); + if (NV != null && _Settings.ContainsKey(NV.Name)) + { + _Settings[NV.Name].SetValueFromString(NV.Value); + Result[NV.Name] = NV; + } + } + } + + return Result; + } + catch + { + return null; + } + } + + /// + /// Check if this set of settings is valid. Return a list of error descriptions. + /// If returned array is zero-length, settings are valid. + /// + /// + public string[] CheckValid() + { + List Result = new List(); + + if (_Settings.ContainsKey(MIN_FREQ) && _Settings.ContainsKey(MAX_FREQ)) + { + var Min = _Settings[MIN_FREQ]; + var Max = _Settings[MAX_FREQ]; + + if (Min is TShortSetting && Max is TShortSetting) + { + if (((TShortSetting)Min).Value > ((TShortSetting)Max).Value) + { + Result.Add("MIN_FREQ can't be more than MAX_FREQ"); + } + } + } + + return Result.ToArray(); + } + + public class TNameAndValue + { + public readonly string Name; + public readonly string Value; + + public TNameAndValue(string Name, string Value) + { + this.Name = Name; + this.Value = Value; + } + } + } + + public abstract class TBaseSetting : ICloneable + { public string Designator; public string Name; + + public abstract string GetValueAsString(); + public abstract void SetValueFromString(string Text); + public abstract object Clone(); + } + + public class TTextSetting : TBaseSetting + { + public string Text; + + public override string GetValueAsString() + { + return Text; + } + + public override void SetValueFromString(string Text) + { + this.Text = Text; + } + + public override object Clone() + { + TTextSetting Result = new TTextSetting(); + Result.Designator = Designator; + Result.Name = Name; + Result.Text = Text; + + return Result; + } + } + + + public class TShortSetting : TBaseSetting + { + public int Value; + + public TShortSetting(string Designator, string Name, int Value) + { + this.Designator = Designator; + this.Name = Name; + this.Value = Value; + } + + public override object Clone() + { + return new TShortSetting(Designator, Name, Value); + } + + public override string GetValueAsString() + { + return Value.ToString(); + } + + public override void SetValueFromString(string Text) + { + int.TryParse(Text, out this.Value); + } + } + + public class TSetting : TShortSetting + { /// /// null if range unknown /// public TRange Range; - public int Value; /// /// null if options unknown /// @@ -717,6 +1531,7 @@ public class TSetting public TSetting(string Designator, string Name, TRange Range, int Value, TOption[] Options, int Increment) + : base(Designator, Name, Value) { this.Designator = Designator; this.Name = Name; @@ -726,279 +1541,991 @@ public TSetting(string Designator, string Name, TRange Range, int Value, TOption this.Increment = Increment; } - public string[] GetOptionNames() + public override object Clone() + { + return new TSetting(Designator, Name, Range, Value, Options, Increment); + } + + public string[] GetOptionNames() + { + if (Options == null) + { + return null; + } + else + { + return RFDLib.Array.CherryPickArray(Options, (x) => x.OptionName); + } + } + + public string GetOptionNameForValue(string Value) + { + if (Options != null) + { + foreach (var O in Options) + { + if (O.Value.ToString() == Value) + { + return O.OptionName; + } + } + } + return null; + } + + /// + /// Returns whether this setting is a flag/boolean. + /// + /// + public bool GetIsFlag() + { + return (Range != null) && Range.GetOptions().Length == 2 && + Range.GetOptions()[0] == 0 && Range.GetOptions()[1] == 1; + } + + public abstract class TRange + { + public abstract int[] GetOptions(); + + /// + /// Get the list of options and include the option with the given value if it doesnt exist. + /// + /// The value to include. + /// The options. Never null. + public int[] GetOptionsIncludingValue(int Value) + { + List Result = new List(); + bool GotValue = false; + + foreach (var n in GetOptions()) + { + if (n == Value) + { + GotValue = true; + } + if (!GotValue) + { + if (n > Value) + { + Result.Add(Value); + GotValue = true; + } + } + + Result.Add(n); + } + + if (!GotValue) + { + Result.Add(Value); + } + + return Result.ToArray(); + } + } + + public class TSimpleRange : TRange + { + public readonly int Min; + public readonly int Max; + public readonly int Increment; + + public TSimpleRange(int Min, int Max, int Increment) + { + this.Min = Min; + this.Max = Max; + this.Increment = Increment; + } + + public override int[] GetOptions() + { + int[] list; + int index = 0; + bool GotEnd = false; + + int Min = this.Min; + int Max = this.Max; + + //Prevent exception for the case of the modem firmware erroneously specifiying a range in which max is less than min. + if (Max < Min) + { + Max = Min; + } + + if (Min == Max) + { + list = new int[1]; + } + else + { + list = new int[((Max - Min - 1) / Increment) + 2]; + } + + for (var a = Min; a <= Max; a += Increment) + { + if (a == Max) + { + GotEnd = true; + } + list[index++] = a; + } + + if (!GotEnd) + { + list[index++] = Max; + } + + return list; + } + } + + public class TMultiRange : TRange + { + TSimpleRange[] _SimpleRanges; + + public TMultiRange(TSimpleRange[] SimpleRanges) + { + _SimpleRanges = SimpleRanges; + } + + public override int[] GetOptions() + { + int TotalLength = 0; + int SRIndex; + + for (SRIndex = 0; SRIndex < _SimpleRanges.Length; SRIndex++) + { + TotalLength += _SimpleRanges[SRIndex].GetOptions().Length; + } + + int[] Result = new int[TotalLength]; + int ResultIndex = 0; + + for (SRIndex = 0; SRIndex < _SimpleRanges.Length; SRIndex++) + { + int[] SubResult = _SimpleRanges[SRIndex].GetOptions(); + Array.Copy(SubResult, 0, Result, ResultIndex, SubResult.Length); + ResultIndex += SubResult.Length; + } + + return Result; + } + } + + public class TOption + { + public readonly int Value; + public readonly string OptionName; + + public TOption(int Value, string OptionName) + { + this.Value = Value; + this.OptionName = OptionName; + } + } + } + + public abstract class RFD900 + { + protected TSession _Session; + bool _IsDINIO = false; + + public RFD900(TSession Session) + { + _Session = Session; + } + + /// + /// Returns whether the firmware model is allowed to be different to the connected modem model. + /// + /// + bool FirmwareDiffExempt() + { + return false; + } + + bool CheckFirmwareIncludingFileNameOK(string FilePath) + { + try + { + return (!IsDINIO || System.IO.Path.GetFileName(FilePath).Contains("DINIO")) && CheckFirmwareOK(FilePath); + } + catch + { + return CheckFirmwareOK(FilePath); + } + } + + public Uploader.Frequency GetBand() + { + try + { + var FreqString = _Session.ATCClient.DoQuery("ATI3", true); + if (FreqString.Contains("]")) + { + FreqString = FreqString.Split(']')[1]; + } + + System.Globalization.NumberStyles style = System.Globalization.NumberStyles.Any; + + if (FreqString.ToLower().Contains("x")) + { + style = System.Globalization.NumberStyles.AllowHexSpecifier; + } + + var freq = + (Uploader.Frequency) + Enum.Parse(typeof(Uploader.Frequency), + int.Parse(FreqString.ToLower().Replace("x", ""), style).ToString()); + + return freq; + } + catch + { + return Uploader.Frequency.FREQ_NONE; + } + } + + /// + /// Program firmware into modem, firstly doing necessary checks. + /// + /// The path of the firmware. Must not be null. + /// A callback to report progress. + /// true if succeeded, false if failed. + public virtual bool ProgramFirmware(string FilePath, Action Progress) + { + if (CheckFirmwareIncludingFileNameOK(FilePath) || FirmwareDiffExempt()) + { + Progress("Putting into bootloader mode.", double.NaN); + var Mode = _Session.PutIntoBootloaderMode(); + switch (Mode) + { + case TSession.TMode.BOOTLOADER: + case TSession.TMode.BOOTLOADER_X: + Progress("Programming selected firmware into modem.", double.NaN); + return DoFirmwareProgramming(FilePath, Progress); + default: + Progress("Failed to put into bootloader mode.", double.NaN); + return false; + } + } + else + { + Progress("Incorrect firmware selected.", double.NaN); + System.Threading.Thread.Sleep(2000); + return false; + } + } + + /// + /// The function which actually programs the firmware, doesn't check the firmware first, etc. + /// + /// The firmware file path. Must not be null. + /// The programming progress callback. Must not be null. + /// true if successful, false if failed. + protected abstract bool DoFirmwareProgramming(string FilePath, Action Progress); + protected abstract bool CheckFirmwareOK(string FilePath); + + static bool SearchTokenUpdate(byte[] Token, ref int TokenIndex, byte NextByte) + { + if (NextByte == Token[TokenIndex]) + { + if (++TokenIndex >= Token.Length) + { + //Found it. + return true; + } + } + else + { + TokenIndex = 0; + } + return false; + } + + /// + /// Search the given binary file for the given tokens + /// + /// The binary file path. Must not be null. + /// The tokens. Must not be null. + /// true if at least one token found, false if not. + protected static bool SearchBinary(string BinFilePath, string[] Tokens) + { + foreach (var Token in Tokens) + { + byte[] BinToken = System.Text.ASCIIEncoding.ASCII.GetBytes(Token); + + using (System.IO.FileStream FS = new System.IO.FileStream(BinFilePath, System.IO.FileMode.Open)) + { + int Byte; + int TokenIndex = 0; + while ((Byte = FS.ReadByte()) != -1) + { + if (SearchTokenUpdate(BinToken, ref TokenIndex, (byte)Byte)) + { + return true; + } + } + } + } + + return false; + } + + /// + /// Search the given hex file for the given tokens. + /// + /// The file to search. Must not be null. + /// The tokens to search for. Must not be null. + /// true if at least one found, false if not found. + protected static bool SearchHex(IHex File, string[] Tokens) + { + foreach (var Token in Tokens) + { + int TokenIndex = 0; + byte[] BinToken = System.Text.ASCIIEncoding.ASCII.GetBytes(Token); + + foreach (var Part in File.Values) + { + foreach (byte b in Part) + { + if (SearchTokenUpdate(BinToken, ref TokenIndex, b)) + { + return true; + } + } + } + } + return false; + } + + protected abstract string[] GetFirmwareSearchTokens(); + + protected void ShowWrongFirmwareMessageBox() + { + { + string S = "File doesn't appear to be valid for this radio. Could not find "; + var Tokens = GetFirmwareSearchTokens(); + for (int n = 0; n < Tokens.Length; n++) + { + if (n != 0) + { + if (n >= (Tokens.Length - 1)) + { + S += " or "; + } + else + { + S += ", "; + } + } + S += "\"" + Tokens[n] + "\""; + } + + S += " in File."; + + System.Windows.Forms.MessageBox.Show(S); + } + } + + public abstract Uploader.Board Board { get; } + + public bool IsDINIO + { + get + { + return _IsDINIO; + } + } + + public abstract string[] FirmwareFileNameExtensions { get; } + + public void SetDINIO() + { + _IsDINIO = true; + } + + /// + /// Tries to extract the firmware version string from the ATI command response. + /// + /// ATI(/RTI) command response. Must not be null. + /// The version string, if found, otherwise null. + public static string ATIResponseToFWVersion(string ATIResponse) + { + if (ATIResponse.Contains("RFD") && ATIResponse.Contains("on")) + { + int RFD = ATIResponse.IndexOf("RFD"); + int on = ATIResponse.IndexOf("on"); + + if (on > RFD) + { + return ATIResponse.Substring(RFD + 3, on - RFD - 3).Trim(); + } + } + + return null; + } + } + + public abstract class RFD900APU : RFD900 + { + public RFD900APU(TSession Session) + : base(Session) + { + + } + + /// + /// Check whether the firmware in the given path is suitable for this modem. + /// + /// The path to the firmware. Must not be null. + /// true if OK, false if not. + protected override bool CheckFirmwareOK(string FilePath) + { + try + { + IHex Hex = new IHex(); + Hex.load(FilePath); + + if (SearchHex(Hex, GetFirmwareSearchTokens())) + { + return true; + } + else + { + ShowWrongFirmwareMessageBox(); + return false; + } + } + catch + { + return false; + } + } + + /// + /// Do the firmware programming without doing any checks. + /// + /// The path of the firmware file to program. Must not be null. + /// A callback for progress. + /// true if succeeded, false if failed. + protected override bool DoFirmwareProgramming(string FilePath, Action Progress) { - if (Options == null) + try { - return null; + IHex Hex = new IHex(); + Hex.load(FilePath); + + Uploader UL = new Uploader(); + UL.ProgressEvent += (d) => Progress(null, d); + UL.upload(_Session.Port, Hex); + _Session.AssumeMode(TSession.TMode.TRANSPARENT); + return true; } - else + catch { - return RFDLib.Array.CherryPickArray(Options, (x) => x.OptionName); + return false; } } - public string GetOptionNameForValue(string Value) + public override string[] FirmwareFileNameExtensions + { + get + { + return new string[] { "hex", "ihx" }; + } + } + + /// + /// Get the correct object for the modem which is in bootloader mode. + /// + /// The session. Must not be null. + /// null if could not generate modem object + public static RFD900APU GetObjectForModem(TSession Session) { - if (Options != null) + Uploader U = new Uploader(); + U.port = Session.Port; + Uploader.Board Board = Uploader.Board.FAILED; + Uploader.Frequency Freq = Uploader.Frequency.FAILED; + + U.getDevice(ref Board, ref Freq); + switch (Board) { - foreach (var O in Options) - { - if (O.Value.ToString() == Value) - { - return O.OptionName; - } - } + case Uploader.Board.DEVICE_ID_RFD900A: + return new RFD900a(Session); + case Uploader.Board.DEVICE_ID_RFD900P: + return new RFD900p(Session); + case Uploader.Board.DEVICE_ID_RFD900U: + return new RFD900u(Session); + default: + return null; } - return null; } + } - public class TRange + public class RFD900a : RFD900APU + { + public RFD900a(TSession Session) + : base(Session) { - public readonly int Min; - public readonly int Max; - public TRange(int Min, int Max) - { - this.Min = Min; - this.Max = Max; - } } - public class TOption + protected override string[] GetFirmwareSearchTokens() { - public readonly int Value; - public readonly string OptionName; + return new string[] { "RFD900A" }; + } - public TOption(int Value, string OptionName) + public override Uploader.Board Board + { + get { - this.Value = Value; - this.OptionName = OptionName; + return Uploader.Board.DEVICE_ID_RFD900A; } } } - public abstract class RFD900 + public class RFD900p : RFD900APU { - protected TSession _Session; - - public RFD900(TSession Session) + public RFD900p(TSession Session) + : base(Session) { - _Session = Session; + } - public abstract bool ProgramFirmware(string FilePath, Action Progress); + protected override string[] GetFirmwareSearchTokens() + { + return new string[] { "RFD900P" }; + } - static bool SearchTokenUpdate(byte[] Token, ref int TokenIndex, byte NextByte) + public override Uploader.Board Board { - if (NextByte == Token[TokenIndex]) + get { - if (++TokenIndex >= Token.Length) - { - //Found it. - return true; - } + return Uploader.Board.DEVICE_ID_RFD900P; } - else + } + } + + public class RFD900u : RFD900APU + { + public RFD900u(TSession Session) + : base(Session) + { + + } + + protected override string[] GetFirmwareSearchTokens() + { + return new string[] { "RFD900U" }; + } + + public override Uploader.Board Board + { + get { - TokenIndex = 0; + return Uploader.Board.DEVICE_ID_RFD900U; } - return false; + } + } + + public abstract class RFD900xuxRevN : RFD900 + { + public RFD900xuxRevN(TSession Session) + : base(Session) + { } /// - /// Search the given binary file for the given tokens + /// Get the correct object for the modem which is in bootloader mode. /// - /// The binary file path. Must not be null. - /// The tokens. Must not be null. - /// true if at least one token found, false if not. - protected static bool SearchBinary(string BinFilePath, string[] Tokens) - { - foreach (var Token in Tokens) + /// The session. Must not be null. + /// null if could not generate modem object + public static RFD900xuxRevN GetObjectForModem(TSession Session) + { + Session.Port.Write("\r\n"); + Thread.Sleep(200); + Session.Port.DiscardInBuffer(); + Session.Port.Write("CHIPID\r\n"); + int TokenIndex = Session.WaitForAnyOfTheseTokens(new string[] { "RFD900xSub:1", "RFD900uxSub:1", "RFD900xSub:2", "RFD900uxSub:2"}, 200); + switch (TokenIndex) + { + case 0: + return new RFD900x(Session); + case 1: + return new RFD900ux(Session); + case 2: + return new RFD900X2(Session); + case 3: + return new RFD900UX2(Session); + default: + return null; + } + } + + static bool GetIsLetter(char x) + { + return (((x >= 'a') && (x <= 'z')) || ((x >= 'A') && (x <= 'Z'))); + } + + /// + /// Gets remote country code. + /// + /// + public TCountry GetRemoteCountryCode() + { + return GetCountryCode("R"); + } + + protected abstract int GetCountryCodeRegPosition(); + + TCountry GetCountryCode(string AorR) + { + string Reply = _Session.ATCClient.DoQuery(AorR + "T+C" + GetCountryCodeRegPosition().ToString() + "?", true); + + int CCInt; + + if (int.TryParse(Reply, out CCInt)) { - byte[] BinToken = System.Text.ASCIIEncoding.ASCII.GetBytes(Token); - - using (System.IO.FileStream FS = new System.IO.FileStream(BinFilePath, System.IO.FileMode.Open)) - { - int Byte; - int TokenIndex = 0; - while ((Byte = FS.ReadByte()) != -1) - { - if (SearchTokenUpdate(BinToken, ref TokenIndex, (byte)Byte)) - { - return true; - } - } - } + return (TCountry)CCInt; + } + else + { + return TCountry.NONE; } + } - return false; + public static TCountry[] GetValidCountryLockOptionsForBand(Uploader.Frequency Band) + { + switch (Band) + { + case Uploader.Frequency.FREQ_868: + return new TCountry[] { TCountry.EU, TCountry.India }; + case Uploader.Frequency.FREQ_915: + return new TCountry[] { TCountry.AU, TCountry.US, TCountry.NZ }; + default: + return new TCountry[0]; + } } - /// - /// Search the given hex file for the given tokens. - /// - /// The file to search. Must not be null. - /// The tokens to search for. Must not be null. - /// true if at least one found, false if not found. - protected static bool SearchHex(IHex File, string[] Tokens) + public TCountry[] GetValidCountryLockOptions() + { + return GetValidCountryLockOptionsForBand(GetBand()); + } + + public static bool GetCanBeLockedToCountry(Uploader.Frequency Band, TCountry C) + { + return (new List(GetValidCountryLockOptionsForBand(Band))).Contains(C); + } + + /// + /// Gets local country code. Assumes in AT command mode already. Returns null if no country code detected. + /// + /// + public TCountry GetCountryCode() + { + return GetCountryCode("A"); + } + + public virtual bool WriteCounty(TCountry C) + { + return _Session.ATCClient.DoCommand("AT+C" + GetCountryCodeRegPosition().ToString() + "=" + ((int)C).ToString()); + } + + + /// + protected bool GetIsThisLockedToCountry() { - foreach (var Token in Tokens) + return GetIsCountryLocked(GetCountryCode()); + } + + public static bool GetIsCountryLocked(TCountry C) + { + switch (C) { - int TokenIndex = 0; - byte[] BinToken = System.Text.ASCIIEncoding.ASCII.GetBytes(Token); + case TCountry.NONE: + case TCountry.Undefined: + return false; + default: + return true; + } + } + protected virtual bool SetHigherBaud() + { + return false; + } - foreach (var Part in File.Values) - { - foreach (byte b in Part) - { - if (SearchTokenUpdate(BinToken, ref TokenIndex, b)) - { - return true; - } - } + protected virtual void ReturnToNormalBaud() + { + + } + + bool DoProgramming(string FilePath, Action Progress) + { + _Session.Port.Write("\r"); + Thread.Sleep(100); + _Session.Port.DiscardInBuffer(); + _Session.Port.Write("UPLOAD\r"); + if (_Session.WaitForToken("Ready\r\n", 5000) && _Session.WaitForToken("C", 5000)) + { + try + { + MissionPlanner.Radio.XModem.ProgressEvent += (d) => Progress(null, d); + bool Result = MissionPlanner.Radio.XModem.Upload(FilePath, _Session.Port); + _Session.AssumeMode(TSession.TMode.INIT); + return Result; + } + catch + { + return false; } } - return false; + else + { + return false; + } } - protected abstract string[] GetFirmwareSearchTokens(); + bool TryFirmwareProgrammingOnce(string FilePath, Action Progress) + { + bool Result; + bool HigherBaud; + + HigherBaud = SetHigherBaud(); + + Result = DoProgramming(FilePath, Progress); + + if (HigherBaud) + { + ReturnToNormalBaud(); + } + + return Result; + } - protected void ShowWrongFirmwareMessageBox() + /// + /// Program the given firmware without doing any checks. + /// + /// The path of the firmware file. Must not be null. + /// A function to use to provide real-time feedback about the + /// programming progress. + /// true if successful, false if failed. + protected override bool DoFirmwareProgramming(string FilePath, Action Progress) { - string S = "File doesn't appear to be valid for this radio. Could not find "; - var Tokens = GetFirmwareSearchTokens(); - for (int n = 0; n < Tokens.Length; n++) + while (!TryFirmwareProgrammingOnce(FilePath, Progress)) { - if (n != 0) + switch (System.Windows.Forms.MessageBox.Show("Programming firmware failed. Try again?", "Programming firmware failed. Try again?", System.Windows.Forms.MessageBoxButtons.YesNoCancel)) { - if (n >= (Tokens.Length - 1)) - { - S += " or "; - } - else - { - S += ", "; - } + case System.Windows.Forms.DialogResult.Yes: + break; + case System.Windows.Forms.DialogResult.No: + case System.Windows.Forms.DialogResult.Cancel: + return false; } - S += "\"" + Tokens[n] + "\""; } - - S += " in File."; - - System.Windows.Forms.MessageBox.Show(S); - } - - public abstract Uploader.Board Board { get; } - } - - public abstract class RFD900APU : RFD900 - { - public RFD900APU(TSession Session) - : base(Session) - { - + return true; } - public override bool ProgramFirmware(string FilePath, Action Progress) + /// + /// Check that the firmware is the right type for this modem. + /// + /// The path to the firmware. Must not be null. + /// true if correct, false if not. + protected override bool CheckFirmwareOK(string FilePath) { - try + if (SearchBinary(FilePath, GetFirmwareSearchTokens())) { - IHex Hex = new IHex(); - Hex.load(FilePath); - - if (SearchHex(Hex, GetFirmwareSearchTokens())) - { - Uploader UL = new Uploader(); - UL.ProgressEvent += (d) => Progress(d); - UL.upload(_Session.Port, Hex); - return true; - } - else - { - ShowWrongFirmwareMessageBox(); - return false; - } + return true; } - catch + else { + ShowWrongFirmwareMessageBox(); return false; } } + public enum TCountry + { + NONE = 0, + AU = 1, + NZ = 2, + US = 3, + EU = 4, + PRC = 5, + Ins = 6, + India = 8, + Undefined = 255, + } + } + + public abstract class RFD900xux : RFD900xuxRevN + { + public RFD900xux(TSession Session) + : base(Session) + { + } + /// - /// Get the correct object for the modem which is in bootloader mode. + /// Returns whether the file of the given path is "certified". i.e. Whether it + /// will return whether it is locked to a country using the ATI command. /// - /// The session. Must not be null. - /// null if could not generate modem object - public static RFD900APU GetObjectForModem(TSession Session) + /// The file path. Must not be null. + /// true if certified, false if not. + bool IsFirmwareCertified(string FilePath) { - Uploader U = new Uploader(); - U.port = Session.Port; - Uploader.Board Board = Uploader.Board.FAILED; - Uploader.Frequency Freq = Uploader.Frequency.FAILED; + return SearchBinary(FilePath, new string[] { "HastaLaVistaBaby" }); + } - U.getDevice(ref Board, ref Freq); - switch (Board) - { - case Uploader.Board.DEVICE_ID_RFD900A: - return new RFD900a(Session); - case Uploader.Board.DEVICE_ID_RFD900P: - return new RFD900p(Session); - case Uploader.Board.DEVICE_ID_RFD900U: - return new RFD900u(Session); - case Uploader.Board.DEVICE_ID_RFD900: - return new RFD900old(Session); - case Uploader.Board.DEVICE_ID_HM_TRP: - return new HM_TRP(Session); - case Uploader.Board.DEVICE_ID_HB1060: - return new HB1060(Session); - default: - return null; - } + protected override int GetCountryCodeRegPosition() + { + return 32; } - } - public class RFD900old : RFD900APU - { - public RFD900old(TSession Session) - : base(Session) + protected abstract string GetRefFirmwareResourcePath(); + + /// + /// Unpack the reference firmware embedded into this exe into a temp file and return + /// the path to that file. + /// + /// The path to the temp file containing the ref file. Never null. + string GetRefFirmwarePath() { + string Temp = System.IO.Path.GetTempFileName(); + var assembly = Assembly.GetExecutingAssembly(); + //var resourceName = "RFD900Tools.Properties.Resources.resources.RFDSiK_V3.00_rfd900x.bin"; + //var resourceName = "RFD900Tools.Resources.RFDSiK V3.00 rfd900x.bin"; + var resourceName = GetRefFirmwareResourcePath(); - } + var Names = assembly.GetManifestResourceNames(); + Console.WriteLine(Names.ToString()); - protected override string[] GetFirmwareSearchTokens() - { - return new string[] { "RFD900" }; - } + using (Stream stream = assembly.GetManifestResourceStream(resourceName)) + using (Stream FileStream = System.IO.File.OpenWrite(Temp)) + using (StreamReader reader = new StreamReader(stream)) + using (StreamWriter writer = new StreamWriter(FileStream)) + { + stream.Seek(0, SeekOrigin.Begin); + stream.CopyTo(FileStream); + } - public override Uploader.Board Board + return Temp; + } + + public override string[] FirmwareFileNameExtensions + { + get + { + return new string[] { "bin" }; + } + } + + public override bool WriteCounty(TCountry C) + { + return _Session.ATCClient.DoCommand("AT+C" + GetCountryCodeRegPosition().ToString() + "=" + ((int)C).ToString()); + } + + /// + /// Program the given firmware. Do necesary checks first. + /// + /// The path to the firmware file. Must not be null. + /// The function to call back to provide progress updates. + /// true if successful, false if failed. + public override bool ProgramFirmware(string FilePath, Action Progress) { - get + if (IsFirmwareCertified(FilePath)) { - return Uploader.Board.DEVICE_ID_RFD900; + return base.ProgramFirmware(FilePath, Progress); } - } - } + else + { + Progress("Trying to put into AT command mode.", double.NaN); + if (_Session.PutIntoATCommandMode() != TSession.TMode.AT_COMMAND) + { + Progress("Trying to put into bootloader mode.", double.NaN); + if (_Session.PutIntoBootloaderMode() == TSession.TMode.BOOTLOADER_X) + { + Progress("Programming temporary firmware into modem to check certified.", double.NaN); + string RefFirmwarePath = GetRefFirmwarePath(); + try + { + if (!DoFirmwareProgramming(RefFirmwarePath, Progress)) + { + return false; + } + } + finally + { + try + { + System.IO.File.Delete(RefFirmwarePath); + } + catch + { + + } + } + } + else + { + return false; + } + } - public class RFD900a : RFD900APU + //Can it go into AT command mode? + Progress("Trying to put into AT command mode.", double.NaN); + if (_Session.PutIntoATCommandMode() == TSession.TMode.AT_COMMAND) + { + Progress("Checking if modem certified.", double.NaN); + if (!GetIsThisLockedToCountry()) + { + //They can program whatever they want into it. + return base.ProgramFirmware(FilePath, Progress); + } + else + { + //They can only program certified firmware into it. + if (IsFirmwareCertified(FilePath)) + { + return base.ProgramFirmware(FilePath, Progress); + } + else + { + System.Windows.Forms.MessageBox.Show("The selected firmware is not certified to run on this modem. Aborting."); + return false; + } + } + } + else + { + return false; + } + } + } + } + + public class RFD900x : RFD900xux { - public RFD900a(TSession Session) + public RFD900x(TSession Session) : base(Session) { } + protected override string GetRefFirmwareResourcePath() + { + return "RFD900Tools.Resources.RFDSiK V3.01 rfd900x.bin"; + } + protected override string[] GetFirmwareSearchTokens() { - return new string[] { "RFD900A" }; + return new string[] { "RFD900x", "RFD900X" }; } public override Uploader.Board Board { get { - return Uploader.Board.DEVICE_ID_RFD900A; + return Uploader.Board.DEVICE_ID_RFD900X; } } } @@ -1044,157 +2571,205 @@ public override Uploader.Board Board } } - - public class RFD900p : RFD900APU + public class RFD900ux : RFD900xux { - public RFD900p(TSession Session) + public RFD900ux(TSession Session) : base(Session) { } - protected override string[] GetFirmwareSearchTokens() - { - return new string[] { "RFD900P" }; + protected override string GetRefFirmwareResourcePath() + { + return "RFD900Tools.Resources.RFDSiK V3.08 rfd900ux.bin"; } public override Uploader.Board Board { get { - return Uploader.Board.DEVICE_ID_RFD900P; + return Uploader.Board.DEVICE_ID_RFD900UX; } } + + protected override string[] GetFirmwareSearchTokens() + { + return new string[] { "RFD900ux", "RFD900UX" }; + } } - public class RFD900u : RFD900APU - { - public RFD900u(TSession Session) + /*public class RFD900sx : RFD900xux + { + public RFD900sx(TSession Session) : base(Session) { + } + + protected override string[] GetFirmwareSearchTokens() + { + return new string[] { "RFD900sx", "RFD900SX" }; + } + }*/ + public abstract class RFD900xuxRev2 : RFD900xuxRevN + { + public RFD900xuxRev2(TSession Session) + : base(Session) + { } - protected override string[] GetFirmwareSearchTokens() - { - return new string[] { "RFD900U" }; + protected override int GetCountryCodeRegPosition() + { + return 51; } - public override Uploader.Board Board - { - get - { - return Uploader.Board.DEVICE_ID_RFD900U; - } + protected override bool CheckFirmwareOK(string FilePath) + { + return true; + } + + protected override string[] GetFirmwareSearchTokens() + { + return new string[0]; + } + + protected override bool SetHigherBaud() + { + _Session.WriteToPort("BAUDHI\r\n"); + + bool Result = _Session.WaitForToken("OK", 500); + + if (Result) + { + _Session.Port.BaudRate = 1200000; + } + + return Result; + } + + protected override void ReturnToNormalBaud() + { + _Session.WriteToPort("BAUDLO\r\n"); + _Session.WaitForToken("OK", 500); + _Session.Port.BaudRate = 57600; + } + + public override bool WriteCounty(TCountry C) + { + return base.WriteCounty(C) && + _Session.ATCClient.DoCommand("AT+LC"); + } + + public override string[] FirmwareFileNameExtensions + { + get + { + return new string[] { "gbl" }; + } } } - public abstract class RFD900xux : RFD900 + public class RFD900X2 : RFD900xuxRev2 { - public RFD900xux(TSession Session) + public RFD900X2(TSession Session) : base(Session) { - } - /// - /// Get the correct object for the modem which is in bootloader mode. - /// - /// The session. Must not be null. - /// null if could not generate modem object - public static RFD900xux GetObjectForModem(TSession Session) - { - Session.Port.Write("\r\n"); - Thread.Sleep(200); - Session.Port.DiscardInBuffer(); - Session.Port.Write("CHIPID\r\n"); - int TokenIndex = Session.WaitForAnyOfTheseTokens(new string[] { "RFD900x", "RFD900ux" }, 200); - switch (TokenIndex) + public override Uploader.Board Board + { + get { - case 0: - return new RFD900x(Session); - case 1: - return new RFD900ux(Session); - default: - return null; - } + return Uploader.Board.DEVICE_ID_RFD900X2; + } } - - public override bool ProgramFirmware(string FilePath, Action Progress) + } + + public class RFD900UX2 : RFD900xuxRev2 + { + public RFD900UX2(TSession Session) + : base(Session) { - if (SearchBinary(FilePath, GetFirmwareSearchTokens())) - { - _Session.Port.Write("\r"); - Thread.Sleep(100); - _Session.Port.DiscardInBuffer(); - _Session.Port.Write("UPLOAD\r"); - if (_Session.WaitForToken("Ready\r\n", 5000) && _Session.WaitForToken("C", 5000)) - { - try - { - MissionPlanner.Radio.XModem.ProgressEvent += (d) => Progress(d); - MissionPlanner.Radio.XModem.Upload(FilePath, _Session.Port); - return true; - } - catch - { - return false; - } - } - else - { - return false; - } - } - else - { - ShowWrongFirmwareMessageBox(); - return false; - } + } + + public override Uploader.Board Board + { + get + { + return Uploader.Board.DEVICE_ID_RFD900UX2; + } } } - public class RFD900x : RFD900xux + /// + /// A RFDLib.IO.TSerialPort wrapper for TMissionPlannerSerialPort + /// + public class TMissionPlannerSerialPort : RFDLib.IO.TSerialPort { - public RFD900x(TSession Session) - : base(Session) + MissionPlanner.Comms.ICommsSerial _Port; + + public TMissionPlannerSerialPort(MissionPlanner.Comms.ICommsSerial Port) + { + _Port = Port; + } + + public override void Write(string Text) { + _Port.Write(Text); + } + public override void DiscardInBuffer() + { + _Port.DiscardInBuffer(); } - protected override string[] GetFirmwareSearchTokens() + public override int ReadChar() { - return new string[] { "RFD900x", "RFD900X" }; + return _Port.ReadChar(); } - public override Uploader.Board Board + public override string ReadExisting() + { + return _Port.ReadExisting(); + } + + public override string ReadLine() + { + return _Port.ReadLine(); + } + + public override int ReadTimeout { get { - return Uploader.Board.DEVICE_ID_RFD900X; + return _Port.ReadTimeout; + } + set + { + _Port.ReadTimeout = value; } } } - public class RFD900ux : RFD900xux + public class TATCClient : RFDLib.IO.ATCommand.TClient { - public RFD900ux(TSession Session) - : base(Session) - { - + public TATCClient(RFDLib.IO.TSerialPort Port) + : base(Port) + { } - public override Uploader.Board Board + public override string DoQuery(string Command, bool WaitForTerminator) { - get + string Raw = base.DoQuery(Command, WaitForTerminator); + + if (Raw.StartsWith("[") && Raw.Contains("]") && ((Raw.IndexOf(']') + 1) < Raw.Length)) { - return Uploader.Board.DEVICE_ID_RFD900UX; + return Raw.Substring(Raw.IndexOf(']') + 1); + } + else + { + return Raw; } - } - - protected override string[] GetFirmwareSearchTokens() - { - return new string[] { "RFD900ux", "RFD900UX" }; } } } \ No newline at end of file diff --git a/SikRadio/RFDLib/Array.cs b/SikRadio/RFDLib/Array.cs index 213f1163cf..7f4da5be74 100644 --- a/SikRadio/RFDLib/Array.cs +++ b/SikRadio/RFDLib/Array.cs @@ -13,6 +13,30 @@ public static T[] CherryPickArray(U[] x, Func PickFn) Result[n] = PickFn(x[n]); } return Result; + } + + /// + /// Copy the given array, removing elements which meet the given condition. + /// + /// + /// + /// + /// + public static T[] ConditionalRemove(T[] x, Func Condition) + { + T[] Temp = new T[x.Length]; + int Length = 0; + foreach (var a in x) + { + if (!Condition(a)) + { + Temp[Length++] = a; + } + } + + T[] Result = new T[Length]; + System.Array.Copy(Temp, Result, Length); + return Result; } } } diff --git a/SikRadio/RFDLib/Collections.cs b/SikRadio/RFDLib/Collections.cs new file mode 100644 index 0000000000..3db3b7b1a5 --- /dev/null +++ b/SikRadio/RFDLib/Collections.cs @@ -0,0 +1,36 @@ +using System; +using System.Collections.Generic; + +namespace RFDLib +{ + public static class Collections + { + public static Dictionary Translate(Dictionary x, Func TransLateFn) + { + Dictionary Result = new Dictionary(); + + foreach (var kvp in x) + { + Result[kvp.Key] = TransLateFn(kvp.Value); + } + + return Result; + } + + /// + /// Update the given original dictionary with new values from NewValues. + /// + /// + /// + /// + /// + public static void Update(Dictionary Original, Dictionary NewValues) + { + foreach (var kvp in NewValues) + { + Original[kvp.Key] = kvp.Value; + } + } + } + +} \ No newline at end of file diff --git a/SikRadio/RFDLib/GUI/Settings.cs b/SikRadio/RFDLib/GUI/Settings.cs new file mode 100644 index 0000000000..183c0582c7 --- /dev/null +++ b/SikRadio/RFDLib/GUI/Settings.cs @@ -0,0 +1,262 @@ +using System; +using System.Collections.Generic; +using System.Windows.Forms; + +namespace RFDLib.GUI.Settings +{ + public class TLabelEditorPair + { + public readonly Label L; + public readonly Control Editor; + + public TLabelEditorPair(Label L, Control Editor) + { + this.L = L; + this.Editor = Editor; + } + + public virtual string[] SettingNames + { + get + { + return new string[] { Editor.Name }; + } + } + } + + /// + /// A TLabelEditorPair which remembers the original name and label. + /// + public class TOrigLabelEditorPair : TLabelEditorPair + { + public readonly string OriginalLabel; + public readonly string OriginalName; + public readonly bool OrigVisible; + public readonly ToolTip OrigToolTip; + public readonly string OrigToolTipText; + + public TOrigLabelEditorPair(Label L, Control Editor, ToolTip TT) + : base(L, Editor) + { + this.OriginalLabel = L.Text; + this.OriginalName = Editor.Name; + this.OrigVisible = Editor.Visible; + this.OrigToolTip = TT; + this.OrigToolTipText = TT.GetToolTip(Editor); + } + + /// + /// Reset to original values. + /// + public void Reset() + { + L.Text = OriginalLabel; + Editor.Name = OriginalName; + L.Visible = OrigVisible; + Editor.Visible = OrigVisible; + OrigToolTip.SetToolTip(Editor, OrigToolTipText); + } + } + + /// + /// This is for dynamically re-using spare label-editor pairs for which there is no setting in the modem. + /// + public class TLabelEditorPairRegister + { + Dictionary _Pairs = new Dictionary(); + Dictionary _Spare = new Dictionary(); + + /// + /// Add a label-editor pair. + /// + /// + public void Add(TOrigLabelEditorPair Pair) + { + _Pairs[Pair.OriginalName] = Pair; + } + + /// + /// Add a label-editor pair. + /// + /// + /// + public void Add(Label L, Control Editor, ToolTip TT) + { + Add(new TOrigLabelEditorPair(L, Editor, TT)); + } + + /// + /// Reset all label-editor pairs to their original labels and names. + /// + public void Reset() + { + foreach (var P in _Pairs.Values) + { + P.Reset(); + } + + _Spare.Clear(); + } + + /// + /// Call this when the list of setting names has been read from the modem, so the spare + /// label-editor pairs can be put into a separate list. + /// + /// The list of setting names read from the modem. Must not be null. + public void SetUp(List SettingNamesSet) + { + foreach (var kvp in _Pairs) + { + if (!SettingNamesSet.Contains(kvp.Value.Editor.Name)) + { + _Spare[kvp.Key] = kvp.Value; + } + } + } + + /// + /// Get a spare editor control for an unexpected setting read from the modem. Set the editor's label + /// to the setting name, if a spare editor was found. + /// + /// The setting name. Must not be null. + /// The condition the editor control must meet. Must not be null. + /// + Control GetSpare(string SettingName, Func Condition, string Description) + { + TOrigLabelEditorPair Pair = null; + + foreach (var kvp in _Spare) + { + if (Condition(kvp.Value.Editor)) + { + //Assign to a variable and break, instead of processing here, because + //part of the processing is removing it from _Spare, but _Spare is being iterated here. + Pair = kvp.Value; + break; + } + } + + if (Pair == null) + { + return null; + } + else + { + Pair.Editor.Name = SettingName; + Pair.L.Text = Description; + if (Pair.L.Bottom > Pair.Editor.Top) + { + while (Pair.L.Width > (Pair.Editor.Left - Pair.L.Left) && Pair.L.Font.Size > 1) + { + Pair.L.Font = new System.Drawing.Font(Pair.L.Font.FontFamily, Pair.L.Font.Size - 1); + } + } + Pair.L.Visible = true; + Pair.Editor.Visible = true; + Pair.OrigToolTip.SetToolTip(Pair.Editor, Description); + _Spare.Remove(Pair.OriginalName); + return Pair.Editor; + } + } + + /// + /// Return a spare combobox if there is one, otherwise return null. + /// + /// + /// + public ComboBox GetSpareComboBox(string SettingName, string Description) + { + return (ComboBox)GetSpare(SettingName, (C) => C is ComboBox, Description); + } + + /// + /// Return a spare checkbox if there is one, otherwise return null. + /// + /// + /// + public CheckBox GetSpareCheckbox(string SettingName, string Description) + { + return (CheckBox)GetSpare(SettingName, (C) => C is CheckBox, Description); + } + } + + public class TDynamicLabelEditorPair : TLabelEditorPair + { + public readonly TSettingNameLabelTextPair[] AlternateNames; + + public TDynamicLabelEditorPair(Label L, Control Editor, TSettingNameLabelTextPair[] AlternateNames) + : base(L, Editor) + { + this.AlternateNames = AlternateNames; + } + + public override string[] SettingNames + { + get + { + string[] Result = new string[AlternateNames.Length]; + + for (int n = 0; n < AlternateNames.Length; n++) + { + Result[n] = AlternateNames[n].SettingName; + } + + return Result; + } + } + + public bool SetUpForSettingName(string SettingName) + { + foreach (var SNLTP in AlternateNames) + { + if (SNLTP.SettingName == SettingName) + { + L.Text = SNLTP.LabelText; + return true; + } + } + + return false; + } + + public class TSettingNameLabelTextPair + { + public readonly string SettingName; + public readonly string LabelText; + + public TSettingNameLabelTextPair(string SettingName, string LabelText) + { + this.SettingName = SettingName; + this.LabelText = LabelText; + } + } + } + + public class TDynamicLabelEditorPairRegister + { + public readonly TDynamicLabelEditorPair[] Pairs; + + public TDynamicLabelEditorPairRegister(TDynamicLabelEditorPair[] Pairs) + { + this.Pairs = Pairs; + } + + /// + /// Try to find an editor control for the setting of the given name, and if found, set up its label. + /// Returns the editor control if successful, otherwise returns null. + /// + /// The setting name. Must not be null. + /// Returns the editor control if successful, otherwise returns null. + public Control FindAndSetUpEditorWithSettingName(string SettingName) + { + foreach (var Pair in Pairs) + { + if (Pair.SetUpForSettingName(SettingName)) + { + return Pair.Editor; + } + } + return null; + } + } +} \ No newline at end of file diff --git a/SikRadio/RFDLib/IO/ATCommand.cs b/SikRadio/RFDLib/IO/ATCommand.cs new file mode 100644 index 0000000000..5aa01b105d --- /dev/null +++ b/SikRadio/RFDLib/IO/ATCommand.cs @@ -0,0 +1,209 @@ +using System; + +namespace RFDLib.IO.ATCommand +{ + /// + /// An AT-command interface client. + /// + public class TClient + { + public IO.TSerialPort _Port; + /// + /// The line terminator. null if nothing. + /// + public string Terminator = "\r\n"; + /// + /// true if the server echoes commands, and the echoes need to be ignored. + /// + public bool Echoes = true; + /// + /// The maximum time to wait for a response. + /// + public int Timeout = 2000; + + /// + /// Create a new TClient + /// + /// The serial port to use. Must not be null. + public TClient(IO.TSerialPort Port) + { + _Port = Port; + } + + /// + /// Returns the terminator to use. + /// + /// The terminator to use, never null. + string GetTerminator() + { + if (Terminator == null) + { + return ""; + } + else + { + return Terminator; + } + } + + /// + /// Get next char from serial port. Wait up to the read timeout. + /// + /// the char read + /// true if got char before timeout, false if not. + bool GetNextChar(out char x) + { + try + { + x = (char)_Port.ReadChar(); + return true; + } + catch + { + x = '\0'; + return false; + } + } + + /// + /// Eliminate the command echo. + /// + /// The complete command including terminator. Must not be null. + /// true if got echo OK, false if not. + bool EliminateEcho(string CompleteCommand) + { + if (Echoes) + { + _Port.ReadTimeout = Timeout; + int n = 0; + char Temp; + while ((n < CompleteCommand.Length) && GetNextChar(out Temp)) + { + if (CompleteCommand[n] == Temp) + { + n++; + } + else + { + return false; + } + } + } + return true; + } + + /// + /// Do a command and wait for a reply. Returns true if "OK" + /// + /// + /// + public bool DoCommand(string Command) + { + string Result = DoQuery(Command, true); + return Result.Contains("OK"); + } + + /// + /// Returns a received line from the interface. + /// + /// + public string GetLine() + { + return _Port.ReadLine(); + } + + /// + /// Do the given command. If wait for terminator, returns the result minus + /// the terminator. + /// + /// The command. Must not be null. + /// true to wait for terminator. + /// The reply, except for the echo. + public virtual string DoQuery(string Command, bool WaitForTerminator) + { + string CompleteCommand = Command + GetTerminator(); + _Port.DiscardInBuffer(); + _Port.Write(CompleteCommand); + if (EliminateEcho(CompleteCommand)) + { + string Result; + if (WaitForTerminator) + { + if (IO.TSerialPort.WaitForToken(_Port, Terminator, Timeout, out Result)) + { + //Get the terminator out of it. + return Result.Split(new string[] { Terminator }, StringSplitOptions.None)[0]; + } + else + { + return Result; + } + } + else + { + IO.TSerialPort.WaitForToken(_Port, null, Timeout, out Result); + return Result; + } + } + else + { + return ""; + } + } + + public string DoQueryWithMultiLineResponse(string Command) + { + string CompleteCommand = Command + GetTerminator(); + _Port.DiscardInBuffer(); + _Port.Write(CompleteCommand); + + if (EliminateEcho(CompleteCommand)) + { + string Result = ""; + string Temp; + int Timeout = this.Timeout; + + while (IO.TSerialPort.WaitForToken(_Port, Terminator, Timeout, out Temp)) + { + Result += Temp; + Timeout = 500; + } + + return Result; + } + else + { + return ""; + } + } + } + + public class TServer + { + TSerialPort _Port; + public event Action GotCommand; + + public TServer(TSerialPort Port) + { + _Port = Port; + } + + public abstract class TCommand + { + } + + public class TQuery : TCommand + { + public char FirstCharacter; + public string Parameter; + } + + public class TSetValue : TCommand + { + public char FirstCharacter; + public string Parameter; + public string Value; + } + + } +} \ No newline at end of file diff --git a/SikRadio/RFDLib/IO/SerialPort/SerialPort.cs b/SikRadio/RFDLib/IO/SerialPort/SerialPort.cs new file mode 100644 index 0000000000..a2ea7f4c55 --- /dev/null +++ b/SikRadio/RFDLib/IO/SerialPort/SerialPort.cs @@ -0,0 +1,137 @@ +using System; + +namespace RFDLib.IO +{ + public abstract class TSerialPort + { + public abstract void Write(string Text); + public abstract string ReadExisting(); + public abstract int ReadTimeout { get; set; } + public abstract int ReadChar(); + public abstract string ReadLine(); + public abstract void DiscardInBuffer(); + + /// + /// Query a serial port. + /// + /// The port. Must not be null. + /// The query to send, without the terminator. Must not be null. + /// The terminator. Can be null if none. + /// The maximum period to wait in milliseconds. + /// The data returned. Never null. + public static string Query(TSerialPort Port, + string Query, string Terminator, int MaxWait) + { + Port.DiscardInBuffer(); + Query = Query + (Terminator == null ? "" : Terminator); + Port.Write(Query); + string Reply; + WaitForToken(Port, Terminator, MaxWait, out Reply); + return Reply; + } + + /// + /// Wait for the given token or timeout on the given serial port. + /// + /// The port. Must not be null. + /// The token to wait for. Can be null if not waiting for a token. + /// The maximum amount of time to wait for a response, in milliseconds. + /// true if token was received, false if not. + public static bool WaitForToken(TSerialPort Port, + string Token, int MaxWait) + { + string Temp; + return WaitForToken(Port, Token, MaxWait, out Temp); + } + + /// + /// Wait for the given token or timeout on the given serial port + /// + /// The port. Must not be null. + /// The token to wait for. Can be null if not waiting for a token. + /// The maximum amount of time to wait for a response, in milliseconds. + /// The data returned. Never null. + /// true if token was received, false if not. + public static bool WaitForToken(TSerialPort Port, + string Token, int MaxWait, out string Result) + { + System.Diagnostics.Stopwatch SW = new System.Diagnostics.Stopwatch(); + string Temp = ""; + int Timeout = Port.ReadTimeout; + Port.ReadTimeout = MaxWait; + SW.Start(); + + while (SW.ElapsedMilliseconds < MaxWait) + { + //System.Diagnostics.Stopwatch StWa = new System.Diagnostics.Stopwatch(); + //SW.Start(); + string x = Port.ReadExisting(); + //if (StWa.ElapsedMilliseconds > 10) + //{ + // System.Diagnostics.Debug.WriteLine("Read existing slow\n"); + //} + Temp += x; + + if ((Token != null) && Temp.Contains(Token)) + { + Port.ReadTimeout = Timeout; + Result = Temp; + return true; + } + + System.Threading.Thread.Sleep(50); + } + Port.ReadTimeout = Timeout; + Result = Temp; + return false; + } + } + + public class TSystemIOPortsSerialPort : TSerialPort + { + System.IO.Ports.SerialPort _Port; + + public TSystemIOPortsSerialPort(System.IO.Ports.SerialPort Port) + { + _Port = Port; + } + + public override void DiscardInBuffer() + { + _Port.DiscardInBuffer(); + } + + public override int ReadChar() + { + return _Port.ReadChar(); + } + + public override void Write(string Text) + { + _Port.Write(Text); + } + + public override string ReadLine() + { + return _Port.ReadLine(); + } + + public override string ReadExisting() + { + return _Port.ReadExisting(); + } + + public override int ReadTimeout + { + get + { + return _Port.ReadTimeout; + } + set + { + _Port.ReadTimeout = value; + } + } + } + +} \ No newline at end of file diff --git a/SikRadio/RFDLib/RFDLib.cs b/SikRadio/RFDLib/RFDLib.cs new file mode 100644 index 0000000000..565554647e --- /dev/null +++ b/SikRadio/RFDLib/RFDLib.cs @@ -0,0 +1,49 @@ +using System; + + +namespace RFDLib +{ + + public static class Utils + { + + public static bool Retry(Func ToTry, Func PassedCondition, int QTYTries) + { + int TryCount; + + for (TryCount = 0; TryCount < QTYTries; TryCount++) + { + if (PassedCondition(ToTry())) + { + return true; + } + } + + return false; + } + + public static bool Retry(Func PassedCondition, int QTYTries) + { + return Retry(() => (int)1, (x) => PassedCondition(), QTYTries); + } + + public static System.Collections.Generic.KeyValuePair[] EnumToStrings(Type EnumType) + { + var Values = Enum.GetValues(EnumType); + System.Collections.Generic.KeyValuePair[] Result = + new System.Collections.Generic.KeyValuePair[Values.Length]; + + for (int n = 0; n < Values.Length; n++) + { + Result[n] = new System.Collections.Generic.KeyValuePair( + Enum.GetName(EnumType, Values.GetValue(n)), (int)Values.GetValue(n)); + + } + + return Result; + } + + } + + +} \ No newline at end of file diff --git a/SikRadio/RFDLib/Text.cs b/SikRadio/RFDLib/Text.cs index 57fcfb8e72..9cba4abd0d 100644 --- a/SikRadio/RFDLib/Text.cs +++ b/SikRadio/RFDLib/Text.cs @@ -3,7 +3,18 @@ namespace RFDLib { public static class Text - { + { + /// + /// Case-insensitive contains. + /// + /// + /// + /// + public static bool Contains(string Haystack, string Needle) + { + return Haystack.IndexOf(Needle, StringComparison.OrdinalIgnoreCase) >= 0; + } + /// /// Returns whether the given character is an upper or lower case letter of the alphabet. /// @@ -23,5 +34,10 @@ public static bool CheckIsNumeral(char c) { return (c >= '0' && c <= '9'); } + + public static bool CheckIsHexNumeral(char c) + { + return CheckIsNumeral(c) || (c >= 'a' && c <= 'f') || (c >= 'A' && c <= 'F'); + } } } \ No newline at end of file diff --git a/SikRadio/Resources/RFDSiK V3.00 rfd900x.bin b/SikRadio/Resources/RFDSiK V3.00 rfd900x.bin new file mode 100644 index 0000000000000000000000000000000000000000..c360ac31c31062fa9cd46a17d532c29616d9b449 GIT binary patch literal 110288 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≥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

=Sa8HI%z!>3N4}j1Cd#>zX@mmTL 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%0AOS#EyD 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 + { + Session = new RFD.RFD900.TSession(SikRadio.Config.comPort, MainV2.comPort.BaseStream.BaudRate); + return Session.PutIntoATCommandMode() == RFD.RFD900.TSession.TMode.AT_COMMAND; + } + , 3)) { - inter.doCommand(Config.comPort, "AT&T=RSSI"); + if (RFDLib.Utils.Retry(() => Session.ATCClient.DoQuery("AT&T=RSSI", true).Contains("RSSI"), 3)) + { + Session.AssumeMode(RFD.RFD900.TSession.TMode.TRANSPARENT); - _Session.AssumeMode(RFD.RFD900.TSession.TMode.TRANSPARENT); + tickStart = Environment.TickCount; - tickStart = Environment.TickCount; + timer1.Start(); - timer1.Start(); + _Session = Session; + } + else + { + var ATIReply = Session.ATCClient.DoQuery("ATI", true); + if (RFDLib.Text.Contains(ATIReply, "async")) + { + MissionPlanner.MsgBox.CustomMessageBox.Show("Firmware doesn't support RSSI reporting"); + } + else + { + MissionPlanner.MsgBox.CustomMessageBox.Show("Failed to enter RSSI reporting mode."); + } + } + } + else + { + MissionPlanner.MsgBox.CustomMessageBox.Show("Failed to put modem into AT command mode."); } } } @@ -70,62 +94,10 @@ public void Disconnect() _Session.Dispose(); _Session = null; - - BUT_disconnect.Enabled = false; - BUT_connect.Enabled = true; } } } - private void BUT_connect_Click(object sender, EventArgs e) - { - CustomMessageBox.Show("Ensure you disconnect properly, to leave the radio in a good state"); - - try - { - MainV2.comPort.BaseStream.Open(); - - inter.doConnect(MainV2.comPort.BaseStream); - - inter.doCommand(MainV2.comPort.BaseStream, "AT&T=RSSI"); - - inter.doCommand(MainV2.comPort.BaseStream, "ATO"); - - tickStart = Environment.TickCount; - - timer1.Start(); - - BUT_disconnect.Enabled = true; - BUT_connect.Enabled = false; - } - catch - { - CustomMessageBox.Show("Bad Port Setting"); - } - } - - private void BUT_disconnect_Click(object sender, EventArgs e) - { - try - { - timer1.Stop(); - - inter.doConnect(MainV2.comPort.BaseStream); - - inter.doCommand(MainV2.comPort.BaseStream, "AT&T"); - - inter.doCommand(MainV2.comPort.BaseStream, "ATO"); - - MainV2.comPort.BaseStream.Close(); - - BUT_disconnect.Enabled = false; - BUT_connect.Enabled = true; - } - catch - { - } - } - private void timer1_Tick(object sender, EventArgs e) { var comPort = SikRadio.Config.comPort; @@ -137,40 +109,54 @@ private void timer1_Tick(object sender, EventArgs e) if (comPort.BytesToRead < 50) return; - var line = comPort.ReadLine(); + try + { + var line = comPort.ReadLine(); - /* -L/R RSSI: 12/0 L/R noise: 17/0 pkts: 0 txe=0 rxe=0 stx=0 srx=0 ecc=0/0 temp=61 dco=0 -L/R RSSI: 12/0 L/R noise: 16/0 pkts: 0 txe=0 rxe=0 stx=0 srx=0 ecc=0/0 temp=61 dco=0 - */ + /* + L/R RSSI: 12/0 L/R noise: 17/0 pkts: 0 txe=0 rxe=0 stx=0 srx=0 ecc=0/0 temp=61 dco=0 + L/R RSSI: 12/0 L/R noise: 16/0 pkts: 0 txe=0 rxe=0 stx=0 srx=0 ecc=0/0 temp=61 dco=0 + */ - var rssi = new Regex(@"RSSI: ([0-9]+)/([0-9]+)\s+L/R noise: ([0-9]+)/([0-9]+)"); + var rssi = new Regex(@"RSSI: ([0-9]+)/([0-9]+)\s+L/R noise: ([0-9]+)/([0-9]+)"); - var match = rssi.Match(line); + var match = rssi.Match(line); - if (match.Success) - { - var time = (Environment.TickCount - tickStart)/1000.0; + if (match.Success) + { + var time = (Environment.TickCount - tickStart) / 1000.0; - plotdatarssil.Add(time, double.Parse(match.Groups[1].Value)); - plotdatarssir.Add(time, double.Parse(match.Groups[2].Value)); - plotdatanoicel.Add(time, double.Parse(match.Groups[3].Value)); - plotdatanoicer.Add(time, double.Parse(match.Groups[4].Value)); + plotdatarssil.Add(time, double.Parse(match.Groups[1].Value)); + plotdatarssir.Add(time, double.Parse(match.Groups[2].Value)); + plotdatanoicel.Add(time, double.Parse(match.Groups[3].Value)); + plotdatanoicer.Add(time, double.Parse(match.Groups[4].Value)); - // Make sure the Y axis is rescaled to accommodate actual data - zedGraphControl1.AxisChange(); + // Make sure the Y axis is rescaled to accommodate actual data + zedGraphControl1.AxisChange(); - // Force a redraw + // Force a redraw - zedGraphControl1.Invalidate(); + zedGraphControl1.Invalidate(); - if (Terminal.sw != null) - { - Terminal.sw.Write(line); - Terminal.sw.Flush(); + if (Terminal.sw != null) + { + Terminal.sw.Write(line); + Terminal.sw.Flush(); + } } } + catch + { + } + } + } + + public string Header + { + get + { + return "RSSI"; } } } diff --git a/SikRadio/SikRadio.csproj b/SikRadio/SikRadio.csproj index 992a3f2f91..9ecc061046 100644 --- a/SikRadio/SikRadio.csproj +++ b/SikRadio/SikRadio.csproj @@ -118,6 +118,7 @@ Linked\XModem.cs + Form @@ -133,6 +134,11 @@ + + + + + UserControl @@ -228,6 +234,9 @@ Designer + + + diff --git a/SikRadio/Terminal.cs b/SikRadio/Terminal.cs index 4cdac91d33..2fc4128831 100644 --- a/SikRadio/Terminal.cs +++ b/SikRadio/Terminal.cs @@ -22,6 +22,11 @@ public Terminal() { InitializeComponent(); + SetupStreamWriter(); + } + + public static void SetupStreamWriter() + { if (sw == null) sw = new StreamWriter(Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments) + "\\Terminal-" + DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss") + ".txt"); } @@ -79,13 +84,22 @@ public void Connect() { if (!_RunRxThread) { - var Session = new RFD.RFD900.TSession(SikRadio.Config.comPort); - Session.PutIntoATCommandMode(); - Session.Dispose(); - - _RunRxThread = true; - _RxThread = new Thread(RxWorker); - _RxThread.Start(); + if (RFDLib.Utils.Retry(() => + { + var Session = new RFD.RFD900.TSession(SikRadio.Config.comPort, MainV2.comPort.BaseStream.BaudRate); + var Result = Session.PutIntoATCommandMode() == RFD.RFD900.TSession.TMode.AT_COMMAND; + Session.Dispose(); + return Result; + }, 3)) + { + _RunRxThread = true; + _RxThread = new Thread(RxWorker); + _RxThread.Start(); + } + else + { + MissionPlanner.MsgBox.CustomMessageBox.Show("Failed to enter AT command mode."); + } } } @@ -287,5 +301,13 @@ private void TXT_terminal_KeyPress(object sender, KeyPressEventArgs e) cmd.Append(e.KeyChar); } } + + public string Header + { + get + { + return "Terminal"; + } + } } } \ No newline at end of file From dcbb3b27c27bc77e0ec394376c2b1f7d34425e8b Mon Sep 17 00:00:00 2001 From: Tatsuya Yamaguchi Date: Fri, 15 Dec 2023 11:48:00 +0900 Subject: [PATCH 37/44] Joystick: fix expo saving function --- ExtLibs/ArduPilot/Joystick/JoystickBase.cs | 5 +++++ Joystick/JoystickSetup.cs | 7 +++++++ 2 files changed, 12 insertions(+) diff --git a/ExtLibs/ArduPilot/Joystick/JoystickBase.cs b/ExtLibs/ArduPilot/Joystick/JoystickBase.cs index e067a60cca..f9576cc82d 100644 --- a/ExtLibs/ArduPilot/Joystick/JoystickBase.cs +++ b/ExtLibs/ArduPilot/Joystick/JoystickBase.cs @@ -229,6 +229,11 @@ public void setAxis(int channel, joystickaxis axis) JoyChannels[channel].axis = axis; } + public void setExpo(int channel, int expo) + { + JoyChannels[channel].expo = expo; + } + public void setChannel(int channel, joystickaxis axis, bool reverse, int expo) { JoyChannel joy = new JoyChannel(); diff --git a/Joystick/JoystickSetup.cs b/Joystick/JoystickSetup.cs index ad1a4d5576..4baff5bf98 100644 --- a/Joystick/JoystickSetup.cs +++ b/Joystick/JoystickSetup.cs @@ -95,6 +95,13 @@ private void Joystick_Load(object sender, EventArgs e) return (short)MainV2.comPort.MAV.cs.GetType().GetField("rcoverridech" + ax.ChannelNo) .GetValue(MainV2.comPort.MAV.cs); }; + ax.Expo = () => + { + if (int.TryParse(ax.ExpoValue, out int expoValue)) + { + MainV2.joystick?.setExpo(ax.ChannelNo, expoValue); + } + }; Controls.Add(ax); From bd890f41f3995297901f80bc15210800883aea72 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 23 Feb 2024 15:06:41 +1100 Subject: [PATCH 38/44] LogBrowse: add ability to custom y axis scale --- Log/LogBrowse.cs | 41 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/Log/LogBrowse.cs b/Log/LogBrowse.cs index b6f9a2250d..2e073a37cf 100644 --- a/Log/LogBrowse.cs +++ b/Log/LogBrowse.cs @@ -316,9 +316,44 @@ private void LogBrowse_Load(object sender, EventArgs e) ThreadPool.QueueUserWorkItem(o => LoadLog(logfilename)); } + zg1.ContextMenuBuilder += Zg1_ContextMenuBuilder; + log.Info("LogBrowse_Load Done"); } + private void Zg1_ContextMenuBuilder(ZedGraphControl sender, ContextMenuStrip menuStrip, Point mousePt, ZedGraphControl.ContextMenuObjectState objState) + { + menuStrip.Items.Add(new ToolStripMenuItem("Properties MasterPane", null, (c, e) => + { + var propertyGrid1 = new PropertyGrid(); + propertyGrid1.Width = 500; + propertyGrid1.Height = 800; + propertyGrid1.SelectedObject = zg1.MasterPane; + + propertyGrid1.ShowUserControl(); + })); + + menuStrip.Items.Add(new ToolStripMenuItem("Properties YAxis", null, (c, e) => + { + var propertyGrid1 = new PropertyGrid(); + propertyGrid1.Width = 500; + propertyGrid1.Height = 800; + propertyGrid1.SelectedObject = zg1.GraphPane.YAxis.Scale; + + propertyGrid1.ShowUserControl(); + })); + + menuStrip.Items.Add(new ToolStripMenuItem("Properties YAxis2", null, (c, e) => + { + var propertyGrid1 = new PropertyGrid(); + propertyGrid1.Width = 500; + propertyGrid1.Height = 800; + propertyGrid1.SelectedObject = zg1.GraphPane.Y2Axis.Scale; + + propertyGrid1.ShowUserControl(); + })); + } + public void LoadLog(string FileName) { while (!this.IsHandleCreated) @@ -3856,5 +3891,11 @@ private void exportFilesToolStripMenuItem_Click(object sender, EventArgs e) } } } + + private class MetaData + { + public double Min; + public double Max; + } } } \ No newline at end of file From 4b7d64361c78391c5b6582158b56e1ae6569f81c Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 1 Mar 2024 11:21:21 +1100 Subject: [PATCH 39/44] Plugin: fix example load --- Plugins/example18-externalapi.cs | 632 +++++++++++++++---------------- 1 file changed, 316 insertions(+), 316 deletions(-) diff --git a/Plugins/example18-externalapi.cs b/Plugins/example18-externalapi.cs index c9d688efa6..b3d1f2961f 100644 --- a/Plugins/example18-externalapi.cs +++ b/Plugins/example18-externalapi.cs @@ -1,317 +1,317 @@ -using MissionPlanner.Controls; -using MissionPlanner.Utilities; -using Org.BouncyCastle.Tls; -using Org.BouncyCastle.Tls.Crypto.Impl.BC; -using System; -using System.Collections.Generic; -using System.IO; -using System.Net; -using System.Net.Sockets; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using Org.BouncyCastle.Utilities.Encoders; - -//loadassembly: BouncyCastle - -namespace MissionPlanner.plugins -{ - public class example18_externalapi : Plugin.Plugin - { - public override string Name { get; } = "External API"; - - public override string Version { get; } - - public override string Author { get; } - - public override bool Exit() - { - return true; - } - - public string address = Settings.Instance.GetString("ex_api_address", "droneshare.cubepilot.org"); - public int port = Settings.Instance.GetInt32("ex_api_port", 8042); - - public override bool Init() - { - var rootbut = new ToolStripMenuItem("Share to API"); - rootbut.Click += but_Click; - ToolStripItemCollection col = Host.FDMenuMap.Items; - col.Add(rootbut); - - return true; - } - - private void but_Click(object sender2, EventArgs e) - { - if (InputBox.Show("Server", "Server", ref address) != DialogResult.OK) - return; - if (InputBox.Show("Server port", "Server port", ref port) != DialogResult.OK) - return; - - string username = Settings.Instance.GetString("ex_api_username"); - string token = Settings.Instance.GetString("ex_api_psk"); - - if (InputBox.Show("Username", "Username", ref username) != DialogResult.OK) - return; - if (InputBox.Show("Token", "Token", ref token) != DialogResult.OK) - return; - - Settings.Instance["ex_api_address"] = address; - Settings.Instance["ex_api_port"] = port.ToString(); - - Settings.Instance["ex_api_username"] = username; - Settings.Instance["ex_api_psk"] = token; - - var psk = new BasicTlsPskIdentity(username, token.MakeBytes()); - var pskclient = new DTLSPsk(psk); - - Task.Run(() => - { - try - { - - - DtlsClientProtocol client = new DtlsClientProtocol(); - DatagramTransport transport = new UDPTransport(address, port); - var dtlstx = client.Connect(pskclient, transport); - - MainV2.comPort.OnPacketReceived += (sender, message) => - { - try - { - dtlstx.Send(message.buffer, 0, message.buffer.Length); - } - catch (Exception ex) - { - } - }; - - var buf = new byte[dtlstx.GetReceiveLimit()]; - - while (MainV2.comPort.BaseStream.IsOpen) - { - try - { - var read = dtlstx.Receive(buf, 0, buf.Length, 1000); - lock (MainV2.comPort.writelock) - { - if (MainV2.comPort.BaseStream.IsOpen) - MainV2.comPort.BaseStream.Write(buf, 0, read); - } - } - catch (Exception ex) - { - } - } - } - catch (Exception ex) - { - CustomMessageBox.Show(Strings.ERROR, ex.ToString()); - } - }); - } - - public override bool Loaded() - { - return true; - } - } - - internal class DTLSPsk : PskTlsClient - { - public DTLSPsk(TlsPskIdentity pskIdentity) : base(new BcTlsCrypto(new Org.BouncyCastle.Security.SecureRandom()), - pskIdentity) - { - } - - public override int[] GetCipherSuites() - { - return new int[] - { - CipherSuite.TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, - CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, - CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, - CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, - CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, - CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA, - CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256 - }; - } - - public override void NotifyAlertRaised(short alertLevel, short alertDescription, string message, - Exception cause) - { - TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; - output.WriteLine("DTLS client raised alert: " + AlertLevel.GetText(alertLevel) - + ", " + AlertDescription.GetText(alertDescription)); - if (message != null) - { - output.WriteLine("> " + message); - } - - if (cause != null) - { - output.WriteLine(cause); - } - } - - public override void NotifyAlertReceived(short alertLevel, short alertDescription) - { - TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; - output.WriteLine("DTLS client received alert: " + AlertLevel.GetText(alertLevel) - + ", " + AlertDescription.GetText(alertDescription)); - } - - public override void NotifyServerVersion(ProtocolVersion serverVersion) - { - base.NotifyServerVersion(serverVersion); - - Console.WriteLine("DTLS client negotiated " + serverVersion); - } - - public override TlsAuthentication GetAuthentication() - { - return base.GetAuthentication(); - } - - public override void NotifySecureRenegotiation(bool secureRenegotiation) - { - // this is psk, not needed - //base.NotifySecureRenegotiation(secureRenegotiation); - } - - public override void NotifyHandshakeComplete() - { - base.NotifyHandshakeComplete(); - - ProtocolName protocolName = m_context.SecurityParameters.ApplicationProtocol; - if (protocolName != null) - { - Console.WriteLine("Client ALPN: " + protocolName.GetUtf8Decoding()); - } - - TlsSession newSession = m_context.Session; - if (newSession != null) - { - if (newSession.IsResumable) - { - byte[] newSessionID = newSession.SessionID; - string hex = ToHexString(newSessionID); - /* - if (base.m_session != null && Arrays.AreEqual(base.m_session.SessionID, newSessionID)) - { - Console.WriteLine("Client resumed session: " + hex); - } - else - { - Console.WriteLine("Client established session: " + hex); - } - - this.m_session = newSession; - */ - - Console.WriteLine("Client established session: " + hex); - } - - byte[] tlsServerEndPoint = m_context.ExportChannelBinding(ChannelBinding.tls_server_end_point); - if (null != tlsServerEndPoint) - { - Console.WriteLine("Client 'tls-server-end-point': " + ToHexString(tlsServerEndPoint)); - } - - byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique); - Console.WriteLine("Client 'tls-unique': " + ToHexString(tlsUnique)); - } - } - - public override IDictionary GetClientExtensions() - { - if (m_context.SecurityParameters.ClientRandom == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - return base.GetClientExtensions(); - } - - public override void ProcessServerExtensions(IDictionary serverExtensions) - { - if (m_context.SecurityParameters.ServerRandom == null) - throw new TlsFatalAlert(AlertDescription.internal_error); - - base.ProcessServerExtensions(serverExtensions); - } - - protected virtual string ToHexString(byte[] data) - { - return data == null ? "(null)" : Hex.ToHexString(data); - } - - protected override ProtocolVersion[] GetSupportedVersions() - { - return ProtocolVersion.DTLSv12.Only(); - } - } - - public class UDPTransport : DatagramTransport - { - private string address; - private int port; - private UdpClient _udpclient; - - private readonly ByteQueue mRecordQueue = new ByteQueue(); - - public UDPTransport(string address, int port) - { - this.address = address; - this.port = port; - - _udpclient = new UdpClient(address, port); - } - - public void Close() - { - _udpclient.Close(); - } - - public int GetReceiveLimit() - { - return 1 << 14; - } - - public int GetSendLimit() - { - return 1 << 14; - } - - public int Receive(byte[] buf, int off, int len, int waitMillis) - { - var endtime = DateTime.Now.AddMilliseconds(waitMillis); - while (mRecordQueue.Available < len && endtime > DateTime.Now) - { - if (_udpclient.Available > 0) - { - IPEndPoint ep = null; - var data = _udpclient.Receive(ref ep); - - mRecordQueue.AddData(data, 0, data.Length); - - break; - } - - Thread.Yield(); - } - - len = Math.Min(mRecordQueue.Available, len); - mRecordQueue.Read(buf, off, len, 0); - mRecordQueue.RemoveData(len); - return len; - } - - public void Send(byte[] buf, int off, int len) - { - var span = new ReadOnlySpan(buf, off, len); - _udpclient.Send(span.ToArray(), span.Length); - } - } +using MissionPlanner.Controls; +using MissionPlanner.Utilities; +using Org.BouncyCastle.Tls; +using Org.BouncyCastle.Tls.Crypto.Impl.BC; +using System; +using System.Collections.Generic; +using System.IO; +using System.Net; +using System.Net.Sockets; +using System.Threading; +using System.Threading.Tasks; +using System.Windows.Forms; +using Org.BouncyCastle.Utilities.Encoders; + +//loadassembly: BouncyCastle.Cryptography + +namespace MissionPlanner.plugins +{ + public class example18_externalapi : Plugin.Plugin + { + public override string Name { get; } = "External API"; + + public override string Version { get; } + + public override string Author { get; } + + public override bool Exit() + { + return true; + } + + public string address = Settings.Instance.GetString("ex_api_address", "droneshare.cubepilot.org"); + public int port = Settings.Instance.GetInt32("ex_api_port", 8042); + + public override bool Init() + { + var rootbut = new ToolStripMenuItem("Share to API"); + rootbut.Click += but_Click; + ToolStripItemCollection col = Host.FDMenuMap.Items; + col.Add(rootbut); + + return true; + } + + private void but_Click(object sender2, EventArgs e) + { + if (InputBox.Show("Server", "Server", ref address) != DialogResult.OK) + return; + if (InputBox.Show("Server port", "Server port", ref port) != DialogResult.OK) + return; + + string username = Settings.Instance.GetString("ex_api_username"); + string token = Settings.Instance.GetString("ex_api_psk"); + + if (InputBox.Show("Username", "Username", ref username) != DialogResult.OK) + return; + if (InputBox.Show("Token", "Token", ref token) != DialogResult.OK) + return; + + Settings.Instance["ex_api_address"] = address; + Settings.Instance["ex_api_port"] = port.ToString(); + + Settings.Instance["ex_api_username"] = username; + Settings.Instance["ex_api_psk"] = token; + + var psk = new BasicTlsPskIdentity(username, token.MakeBytes()); + var pskclient = new DTLSPsk(psk); + + Task.Run(() => + { + try + { + + + DtlsClientProtocol client = new DtlsClientProtocol(); + DatagramTransport transport = new UDPTransport(address, port); + var dtlstx = client.Connect(pskclient, transport); + + MainV2.comPort.OnPacketReceived += (sender, message) => + { + try + { + dtlstx.Send(message.buffer, 0, message.buffer.Length); + } + catch (Exception ex) + { + } + }; + + var buf = new byte[dtlstx.GetReceiveLimit()]; + + while (MainV2.comPort.BaseStream.IsOpen) + { + try + { + var read = dtlstx.Receive(buf, 0, buf.Length, 1000); + lock (MainV2.comPort.writelock) + { + if (MainV2.comPort.BaseStream.IsOpen) + MainV2.comPort.BaseStream.Write(buf, 0, read); + } + } + catch (Exception ex) + { + } + } + } + catch (Exception ex) + { + CustomMessageBox.Show(Strings.ERROR, ex.ToString()); + } + }); + } + + public override bool Loaded() + { + return true; + } + } + + internal class DTLSPsk : PskTlsClient + { + public DTLSPsk(TlsPskIdentity pskIdentity) : base(new BcTlsCrypto(new Org.BouncyCastle.Security.SecureRandom()), + pskIdentity) + { + } + + public override int[] GetCipherSuites() + { + return new int[] + { + CipherSuite.TLS_ECDHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_DHE_PSK_WITH_CHACHA20_POLY1305_SHA256, + CipherSuite.TLS_DHE_PSK_WITH_AES_128_GCM_SHA256, + CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA256, + CipherSuite.TLS_DHE_PSK_WITH_AES_128_CBC_SHA, + CipherSuite.TLS_PSK_WITH_AES_128_GCM_SHA256 + }; + } + + public override void NotifyAlertRaised(short alertLevel, short alertDescription, string message, + Exception cause) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS client raised alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + if (message != null) + { + output.WriteLine("> " + message); + } + + if (cause != null) + { + output.WriteLine(cause); + } + } + + public override void NotifyAlertReceived(short alertLevel, short alertDescription) + { + TextWriter output = (alertLevel == AlertLevel.fatal) ? Console.Error : Console.Out; + output.WriteLine("DTLS client received alert: " + AlertLevel.GetText(alertLevel) + + ", " + AlertDescription.GetText(alertDescription)); + } + + public override void NotifyServerVersion(ProtocolVersion serverVersion) + { + base.NotifyServerVersion(serverVersion); + + Console.WriteLine("DTLS client negotiated " + serverVersion); + } + + public override TlsAuthentication GetAuthentication() + { + return base.GetAuthentication(); + } + + public override void NotifySecureRenegotiation(bool secureRenegotiation) + { + // this is psk, not needed + //base.NotifySecureRenegotiation(secureRenegotiation); + } + + public override void NotifyHandshakeComplete() + { + base.NotifyHandshakeComplete(); + + ProtocolName protocolName = m_context.SecurityParameters.ApplicationProtocol; + if (protocolName != null) + { + Console.WriteLine("Client ALPN: " + protocolName.GetUtf8Decoding()); + } + + TlsSession newSession = m_context.Session; + if (newSession != null) + { + if (newSession.IsResumable) + { + byte[] newSessionID = newSession.SessionID; + string hex = ToHexString(newSessionID); + /* + if (base.m_session != null && Arrays.AreEqual(base.m_session.SessionID, newSessionID)) + { + Console.WriteLine("Client resumed session: " + hex); + } + else + { + Console.WriteLine("Client established session: " + hex); + } + + this.m_session = newSession; + */ + + Console.WriteLine("Client established session: " + hex); + } + + byte[] tlsServerEndPoint = m_context.ExportChannelBinding(ChannelBinding.tls_server_end_point); + if (null != tlsServerEndPoint) + { + Console.WriteLine("Client 'tls-server-end-point': " + ToHexString(tlsServerEndPoint)); + } + + byte[] tlsUnique = m_context.ExportChannelBinding(ChannelBinding.tls_unique); + Console.WriteLine("Client 'tls-unique': " + ToHexString(tlsUnique)); + } + } + + public override IDictionary GetClientExtensions() + { + if (m_context.SecurityParameters.ClientRandom == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + + return base.GetClientExtensions(); + } + + public override void ProcessServerExtensions(IDictionary serverExtensions) + { + if (m_context.SecurityParameters.ServerRandom == null) + throw new TlsFatalAlert(AlertDescription.internal_error); + + base.ProcessServerExtensions(serverExtensions); + } + + protected virtual string ToHexString(byte[] data) + { + return data == null ? "(null)" : Hex.ToHexString(data); + } + + protected override ProtocolVersion[] GetSupportedVersions() + { + return ProtocolVersion.DTLSv12.Only(); + } + } + + public class UDPTransport : DatagramTransport + { + private string address; + private int port; + private UdpClient _udpclient; + + private readonly ByteQueue mRecordQueue = new ByteQueue(); + + public UDPTransport(string address, int port) + { + this.address = address; + this.port = port; + + _udpclient = new UdpClient(address, port); + } + + public void Close() + { + _udpclient.Close(); + } + + public int GetReceiveLimit() + { + return 1 << 14; + } + + public int GetSendLimit() + { + return 1 << 14; + } + + public int Receive(byte[] buf, int off, int len, int waitMillis) + { + var endtime = DateTime.Now.AddMilliseconds(waitMillis); + while (mRecordQueue.Available < len && endtime > DateTime.Now) + { + if (_udpclient.Available > 0) + { + IPEndPoint ep = null; + var data = _udpclient.Receive(ref ep); + + mRecordQueue.AddData(data, 0, data.Length); + + break; + } + + Thread.Yield(); + } + + len = Math.Min(mRecordQueue.Available, len); + mRecordQueue.Read(buf, off, len, 0); + mRecordQueue.RemoveData(len); + return len; + } + + public void Send(byte[] buf, int off, int len) + { + var span = new ReadOnlySpan(buf, off, len); + _udpclient.Send(span.ToArray(), span.Length); + } + } } \ No newline at end of file From f216661d2d4180c1dcecf46285e35559c5f57991 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 1 Mar 2024 11:21:49 +1100 Subject: [PATCH 40/44] workflow: dont cache dll's android --- .github/workflows/android.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index 4e31cdbad9..dd3a16751e 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -27,6 +27,7 @@ jobs: !**.apk !**.so !**.aab + !**.dll key: ${{ runner.os }}-buildAAB - name: Build @@ -102,6 +103,7 @@ jobs: !**.apk !**.so !**.aab + !**.dll key: ${{ runner.os }}-buildAPK - name: Build shell: pwsh From 017a7204b1899360ef41ee4f16d1028bf77dd70d Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 1 Mar 2024 11:23:14 +1100 Subject: [PATCH 41/44] APFirmware: add external manifest support - loaded at same time as main manifest --- ExtLibs/ArduPilot/APFirmware.cs | 608 +++++++++++++++++--------------- 1 file changed, 327 insertions(+), 281 deletions(-) diff --git a/ExtLibs/ArduPilot/APFirmware.cs b/ExtLibs/ArduPilot/APFirmware.cs index 54f132f5da..9cec657c34 100644 --- a/ExtLibs/ArduPilot/APFirmware.cs +++ b/ExtLibs/ArduPilot/APFirmware.cs @@ -1,281 +1,327 @@ -using Newtonsoft.Json; -using System; -using System.Collections.Generic; -using System.IO; -using System.IO.Compression; -using System.Linq; -using System.Net; -using System.Net.Http; -using System.Text.RegularExpressions; -using System.Threading.Tasks; -using log4net; -using MissionPlanner.Utilities; - -namespace MissionPlanner.ArduPilot -{ - public class APFirmware - { - private static readonly ILog log = - LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - - - static APFirmware() - { - // bg get list - Task.Run(() => GetList()); - } - public class FirmwareInfo - { - [JsonProperty("board_id", NullValueHandling = NullValueHandling.Ignore)] - public long BoardId { get; set; } - - [JsonProperty("mav-type")] public string MavType { get; set; } - - [JsonProperty("mav-firmware-version-minor", NullValueHandling = NullValueHandling.Ignore)] - public long MavFirmwareVersionMinor { get; set; } - - [JsonProperty("format")] public string Format { get; set; } - - [JsonProperty("url")] public Uri Url { get; set; } - - [JsonProperty("mav-firmware-version-type")] - public string MavFirmwareVersionType { get; set; } - - [JsonProperty("mav-firmware-version-patch", NullValueHandling = NullValueHandling.Ignore)] - public long MavFirmwareVersionPatch { get; set; } - - [JsonProperty("mav-autopilot")] public string MavAutopilot { get; set; } - - [JsonProperty("vehicletype")] public string VehicleType { get; set; } - - [JsonProperty("USBID", NullValueHandling = NullValueHandling.Ignore)] - public string[] Usbid { get; set; } = new string[0]; - - [JsonProperty("platform")] public string Platform { get; set; } - - [JsonProperty("mav-firmware-version", NullValueHandling = NullValueHandling.Ignore)] - public Version MavFirmwareVersion { get; set; } - - [JsonProperty("bootloader_str", NullValueHandling = NullValueHandling.Ignore)] - public string[] BootloaderStr { get; set; } = new string[0]; - - [JsonProperty("git-sha")] public string GitSha { get; set; } - - [JsonProperty("mav-firmware-version-major", NullValueHandling = NullValueHandling.Ignore)] - public long MavFirmwareVersionMajor { get; set; } - - [JsonProperty("mav-firmware-version-str", NullValueHandling = NullValueHandling.Ignore)] - public string MavFirmwareVersionStr { get; set; } - - [JsonProperty("latest")] public long Latest { get; set; } - } - - public class ManifestRoot - { - [JsonProperty("firmware")] public FirmwareInfo[] Firmware { get; set; } - - [JsonProperty("format-version")] public Version FormatVersion { get; set; } - } - - // from generate_manifest.py - with map - public enum RELEASE_TYPES - { - BETA, // beta - DEV, // latest - OFFICIAL // stable - } - - public enum MAV_TYPE - { - ANTENNA_TRACKER, - Copter, - HELICOPTER, - FIXED_WING, - GROUND_ROVER, - SUBMARINE - } - - private static readonly object getListlock = new object(); - - public static void GetList(string url = "https://firmware.ardupilot.org/manifest.json.gz", bool force = false) - { - lock (getListlock) - { - if (force == false && Manifest != null) - return; - - try - { - log.Info(url); - - var client = new HttpClient(); - - if (!String.IsNullOrEmpty(Settings.Instance.UserAgent)) - client.DefaultRequestHeaders.Add("User-Agent", Settings.Instance.UserAgent); - - var manifestgz = client.GetByteArrayAsync(url).GetAwaiter().GetResult(); - var mssrc = new MemoryStream(manifestgz); - var msdest = new MemoryStream(); - GZipStream gz = new GZipStream(mssrc, CompressionMode.Decompress); - gz.CopyTo(msdest); - msdest.Position = 0; - var manifest = new StreamReader(msdest).ReadToEnd(); - - Manifest = JsonConvert.DeserializeObject(manifest); - - log.Info(Manifest.Firmware?.Length); - } - catch (Exception ex) - { - log.Error(ex); - } - } - } - - public static ManifestRoot Manifest { get; set; } - - public static long[] GetBoardID(DeviceInfo device, bool boardidcheck = true) - { - GetList(); - - log.Info("device: "+device.ToJSON()); - - // match the board description - var ans = Manifest.Firmware.Where(a => ( - a.Platform?.ToLower() == device.board?.ToLower() || - a.BootloaderStr.Any(b => b?.ToLower() == device.board?.ToLower()))); - - if (boardidcheck) - ans = ans.Where(a => a.BoardId != 0); - - if (ans.Any()) - { - return ans.Select(a => a.BoardId).Distinct().ToArray(); - } - - if (device.hardwareid == null) - return null; - - // match the vid/pid - Regex vidpid = new Regex("VID_([0-9a-f]+)&PID_([0-9a-f]+)&", RegexOptions.IgnoreCase); - - if (vidpid.IsMatch(device.hardwareid)) - { - var match = vidpid.Match(device.hardwareid); - var lookfor = String.Format("0x{0}/0x{1}", match.Groups[1].Value, match.Groups[2].Value); - - var vidandusbdesc = Manifest.Firmware.Where(a => a.Usbid.Any(b => b.ToLower().Contains(lookfor.ToLower())) && a.BoardId != 0); - - if (vidandusbdesc.Any()) - { - return vidandusbdesc.Select(a => a.BoardId).Distinct().ToArray(); - } - } - - return null; - } - - public static List GetOptions(DeviceInfo device, RELEASE_TYPES? reltype = null, MAV_TYPE? mav_type = null) - { - GetList(); - - log.Info("device: "+device.ToJSON()); - - // match the board description - var ans = Manifest.Firmware.Where(a => ( - a.Platform?.ToLower() == device.board?.ToLower() || - a.BootloaderStr.Any(b => b?.ToLower() == device.board?.ToLower())) && a.BoardId != 0); - - // ignore platform - ans = Manifest.Firmware; - - if (reltype.HasValue) - ans = ans.Where(a => a.MavFirmwareVersionType == reltype.Value.ToString()); - - if (mav_type.HasValue) - ans = ans.Where(a => a.MavType == mav_type.Value.ToString()); - - // "0x26AC/0x0011" - //USB\VID_2DAE&PID_1011&REV_0200 - - // match the vid/pid - Regex vidpid = new Regex("VID_([0-9a-f]+)&PID_([0-9a-f]+)&", RegexOptions.IgnoreCase); - - if (vidpid.IsMatch(device.hardwareid)) - { - var match = vidpid.Match(device.hardwareid); - var lookfor = String.Format("0x{0}/0x{1}", match.Groups[1].Value, match.Groups[2].Value); - - var vidandusbdesc = ans.Where(a => a.Usbid.Any(b => b.ToLower().Contains(lookfor.ToLower()))); - - if (vidandusbdesc.Count() == 0) - return ans.ToList(); - - return vidandusbdesc.ToList(); - } - - return ans.ToList(); - } - - public static List GetRelease(RELEASE_TYPES reltype) - { - GetList(); - - var ans = Manifest.Firmware.Where(a => a.MavFirmwareVersionType == reltype.ToString()); - - ans = ans.GroupBy(b => b.MavType) - .SelectMany(a => - a.Where(b => a.Key == b.MavType && b.MavFirmwareVersion == a.Max(c => c.MavFirmwareVersion)).OrderBy(b=>b.Format)); - /* - ans = ans.GroupBy(b => b.MavType).Select(a => - a.Where(b => a.Key == b.MavType && b.MavFirmwareVersion == a.Max(c => c.MavFirmwareVersion)) - .FirstOrDefault()); - */ - - return ans.ToList(); - } - - public static List GetReleaseNewest(RELEASE_TYPES reltype) - { - // get max version for each mavtype - return GetRelease(reltype).GroupBy(b => b.MavType).Select(a => - a.Where(b => a.Key == b.MavType && b.MavFirmwareVersion == a.Max(c => c.MavFirmwareVersion)) - .FirstOrDefault()).ToList(); - } - - - public static void Test() - { - GetList(); - - var cb = Manifest.Firmware.Where(a => a.Platform == "CubeBlack") - .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); - - var vid = Manifest.Firmware.Where(a => a.Usbid.Any(b => b.ToLower().Contains("ac"))) - .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); - - var bl = Manifest.Firmware.Where(a => a.BootloaderStr.Any(b => b.ToLower().Contains("cubeblack"))) - .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); - - var bid = Manifest.Firmware.Where(a => a.BoardId == 9) - .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); - - - var vidandusbdesc = Manifest.Firmware - .Where(a => a.Usbid.Any(b => b.ToLower().Contains("26ac"))) - .Where(a => a.BootloaderStr.Any(c => c.ToLower().Contains("fmuv3") || c.ToLower().Contains("fmuv3-bl"))) - .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); - - var vidandusbdesc1 = Manifest.Firmware - .Where(a => a.Usbid.Any(b => b.ToLower().Contains("26ac"))) - .Where(a => a.BootloaderStr.Any(c => c.ToLower().Contains("fmuv3") || c.ToLower().Contains("fmuv3-bl"))) - .Where(a => a.MavFirmwareVersionType == "DEV"); - - var vidandusbdesc2 = Manifest.Firmware - .Where(a => a.Usbid.Any(b => b.ToLower().Contains("26ac"))) - .Where(a => a.BootloaderStr.Any(c => c.ToLower().Contains("fmuv3") || c.ToLower().Contains("fmuv3-bl"))) - .Where(a => a.MavFirmwareVersionType == "BETA"); - } - - } -} +using Newtonsoft.Json; +using System; +using System.Collections.Generic; +using System.IO; +using System.IO.Compression; +using System.Linq; +using System.Net; +using System.Net.Http; +using System.Text.RegularExpressions; +using System.Threading.Tasks; +using log4net; +using MissionPlanner.Utilities; + +namespace MissionPlanner.ArduPilot +{ + public class APFirmware + { + private static readonly ILog log = + LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + + static APFirmware() + { + // bg get list + Task.Run(() => GetList()); + } + public class FirmwareInfo + { + [JsonProperty("board_id", NullValueHandling = NullValueHandling.Ignore)] + public long BoardId { get; set; } + + [JsonProperty("mav-type")] public string MavType { get; set; } + + [JsonProperty("mav-firmware-version-minor", NullValueHandling = NullValueHandling.Ignore)] + public long MavFirmwareVersionMinor { get; set; } + + [JsonProperty("format")] public string Format { get; set; } + + [JsonProperty("url")] public Uri Url { get; set; } + + [JsonProperty("mav-firmware-version-type")] + public string MavFirmwareVersionType { get; set; } + + [JsonProperty("mav-firmware-version-patch", NullValueHandling = NullValueHandling.Ignore)] + public long MavFirmwareVersionPatch { get; set; } + + [JsonProperty("mav-autopilot")] public string MavAutopilot { get; set; } + + [JsonProperty("vehicletype")] public string VehicleType { get; set; } + + [JsonProperty("USBID", NullValueHandling = NullValueHandling.Ignore)] + public string[] Usbid { get; set; } = new string[0]; + + [JsonProperty("platform")] public string Platform { get; set; } + + [JsonProperty("mav-firmware-version", NullValueHandling = NullValueHandling.Ignore)] + public Version MavFirmwareVersion { get; set; } + + [JsonProperty("bootloader_str", NullValueHandling = NullValueHandling.Ignore)] + public string[] BootloaderStr { get; set; } = new string[0]; + + [JsonProperty("git-sha")] public string GitSha { get; set; } + + [JsonProperty("mav-firmware-version-major", NullValueHandling = NullValueHandling.Ignore)] + public long MavFirmwareVersionMajor { get; set; } + + [JsonProperty("mav-firmware-version-str", NullValueHandling = NullValueHandling.Ignore)] + public string MavFirmwareVersionStr { get; set; } + + [JsonProperty("latest")] public long Latest { get; set; } + } + + public class ManifestRoot + { + [JsonProperty("firmware")] public FirmwareInfo[] Firmware { get; set; } + + [JsonProperty("format-version")] public Version FormatVersion { get; set; } + } + + // from generate_manifest.py - with map + public enum RELEASE_TYPES + { + BETA, // beta + DEV, // latest + OFFICIAL // stable + } + + public enum MAV_TYPE + { + ANTENNA_TRACKER, + Copter, + HELICOPTER, + FIXED_WING, + GROUND_ROVER, + SUBMARINE + } + + private static readonly object getListlock = new object(); + + public static void GetList(string url = "https://firmware.ardupilot.org/manifest.json.gz", bool force = false) + { + lock (getListlock) + { + if (force == false && Manifest != null) + return; + + try + { + log.Info(url); + + var client = new HttpClient(); + + if (!String.IsNullOrEmpty(Settings.Instance.UserAgent)) + client.DefaultRequestHeaders.Add("User-Agent", Settings.Instance.UserAgent); + + var manifestgz = client.GetByteArrayAsync(url).GetAwaiter().GetResult(); + var mssrc = new MemoryStream(manifestgz); + var msdest = new MemoryStream(); + GZipStream gz = new GZipStream(mssrc, CompressionMode.Decompress); + gz.CopyTo(msdest); + msdest.Position = 0; + var manifest = new StreamReader(msdest).ReadToEnd(); + + Manifest = JsonConvert.DeserializeObject(manifest); + + log.Info(Manifest.Firmware?.Length); + + APFirmware.GetListAppend("https://raw.githubusercontent.com/CubePilot/periph-manifest/main/manifest.json"); + } + catch (Exception ex) + { + log.Error(ex); + } + } + } + + public static void GetListAppend(string url, bool force = false) + { + lock (getListlock) + { + try + { + log.Info(url); + + var client = new HttpClient(); + + if (!String.IsNullOrEmpty(Settings.Instance.UserAgent)) + client.DefaultRequestHeaders.Add("User-Agent", Settings.Instance.UserAgent); + + var manifestgz = client.GetByteArrayAsync(url).GetAwaiter().GetResult(); + var mssrc = new MemoryStream(manifestgz); + var msdest = new MemoryStream(); + if (url.EndsWith(".gz")) + { + GZipStream gz = new GZipStream(mssrc, CompressionMode.Decompress); + gz.CopyTo(msdest); + msdest.Position = 0; + } + else + { + mssrc.CopyTo(msdest); + msdest.Position = 0; + } + var manifest = new StreamReader(msdest).ReadToEnd(); + + var Manifest2 = JsonConvert.DeserializeObject(manifest); + + var list = Manifest.Firmware.ToList(); + list.AddRange(Manifest2.Firmware); + Manifest.Firmware = list.ToArray(); + + log.Info(Manifest.Firmware?.Length); + } + catch (Exception ex) + { + log.Error(ex); + } + } + } + + public static ManifestRoot Manifest { get; set; } + + public static long[] GetBoardID(DeviceInfo device, bool boardidcheck = true) + { + GetList(); + + log.Info("device: "+device.ToJSON()); + + // match the board description + var ans = Manifest.Firmware.Where(a => ( + a.Platform?.ToLower() == device.board?.ToLower() || + a.BootloaderStr.Any(b => b?.ToLower() == device.board?.ToLower()))); + + if (boardidcheck) + ans = ans.Where(a => a.BoardId != 0); + + if (ans.Any()) + { + return ans.Select(a => a.BoardId).Distinct().ToArray(); + } + + if (device.hardwareid == null) + return null; + + // match the vid/pid + Regex vidpid = new Regex("VID_([0-9a-f]+)&PID_([0-9a-f]+)&", RegexOptions.IgnoreCase); + + if (vidpid.IsMatch(device.hardwareid)) + { + var match = vidpid.Match(device.hardwareid); + var lookfor = String.Format("0x{0}/0x{1}", match.Groups[1].Value, match.Groups[2].Value); + + var vidandusbdesc = Manifest.Firmware.Where(a => a.Usbid.Any(b => b.ToLower().Contains(lookfor.ToLower())) && a.BoardId != 0); + + if (vidandusbdesc.Any()) + { + return vidandusbdesc.Select(a => a.BoardId).Distinct().ToArray(); + } + } + + return null; + } + + public static List GetOptions(DeviceInfo device, RELEASE_TYPES? reltype = null, MAV_TYPE? mav_type = null) + { + GetList(); + + log.Info("device: "+device.ToJSON()); + + // match the board description + var ans = Manifest.Firmware.Where(a => ( + a.Platform?.ToLower() == device.board?.ToLower() || + a.BootloaderStr.Any(b => b?.ToLower() == device.board?.ToLower())) && a.BoardId != 0); + + // ignore platform + ans = Manifest.Firmware; + + if (reltype.HasValue) + ans = ans.Where(a => a.MavFirmwareVersionType == reltype.Value.ToString()); + + if (mav_type.HasValue) + ans = ans.Where(a => a.MavType == mav_type.Value.ToString()); + + // "0x26AC/0x0011" + //USB\VID_2DAE&PID_1011&REV_0200 + + // match the vid/pid + Regex vidpid = new Regex("VID_([0-9a-f]+)&PID_([0-9a-f]+)&", RegexOptions.IgnoreCase); + + if (vidpid.IsMatch(device.hardwareid)) + { + var match = vidpid.Match(device.hardwareid); + var lookfor = String.Format("0x{0}/0x{1}", match.Groups[1].Value, match.Groups[2].Value); + + var vidandusbdesc = ans.Where(a => a.Usbid.Any(b => b.ToLower().Contains(lookfor.ToLower()))); + + if (vidandusbdesc.Count() == 0) + return ans.ToList(); + + return vidandusbdesc.ToList(); + } + + return ans.ToList(); + } + + public static List GetRelease(RELEASE_TYPES reltype) + { + GetList(); + + var ans = Manifest.Firmware.Where(a => a.MavFirmwareVersionType == reltype.ToString()); + + ans = ans.GroupBy(b => b.MavType) + .SelectMany(a => + a.Where(b => a.Key == b.MavType && b.MavFirmwareVersion == a.Max(c => c.MavFirmwareVersion)).OrderBy(b=>b.Format)); + /* + ans = ans.GroupBy(b => b.MavType).Select(a => + a.Where(b => a.Key == b.MavType && b.MavFirmwareVersion == a.Max(c => c.MavFirmwareVersion)) + .FirstOrDefault()); + */ + + return ans.ToList(); + } + + public static List GetReleaseNewest(RELEASE_TYPES reltype) + { + // get max version for each mavtype + return GetRelease(reltype).GroupBy(b => b.MavType).Select(a => + a.Where(b => a.Key == b.MavType && b.MavFirmwareVersion == a.Max(c => c.MavFirmwareVersion)) + .FirstOrDefault()).ToList(); + } + + + public static void Test() + { + GetList(); + + var cb = Manifest.Firmware.Where(a => a.Platform == "CubeBlack") + .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); + + var vid = Manifest.Firmware.Where(a => a.Usbid.Any(b => b.ToLower().Contains("ac"))) + .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); + + var bl = Manifest.Firmware.Where(a => a.BootloaderStr.Any(b => b.ToLower().Contains("cubeblack"))) + .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); + + var bid = Manifest.Firmware.Where(a => a.BoardId == 9) + .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); + + + var vidandusbdesc = Manifest.Firmware + .Where(a => a.Usbid.Any(b => b.ToLower().Contains("26ac"))) + .Where(a => a.BootloaderStr.Any(c => c.ToLower().Contains("fmuv3") || c.ToLower().Contains("fmuv3-bl"))) + .Where(a => a.MavFirmwareVersionType == "OFFICIAL"); + + var vidandusbdesc1 = Manifest.Firmware + .Where(a => a.Usbid.Any(b => b.ToLower().Contains("26ac"))) + .Where(a => a.BootloaderStr.Any(c => c.ToLower().Contains("fmuv3") || c.ToLower().Contains("fmuv3-bl"))) + .Where(a => a.MavFirmwareVersionType == "DEV"); + + var vidandusbdesc2 = Manifest.Firmware + .Where(a => a.Usbid.Any(b => b.ToLower().Contains("26ac"))) + .Where(a => a.BootloaderStr.Any(c => c.ToLower().Contains("fmuv3") || c.ToLower().Contains("fmuv3-bl"))) + .Where(a => a.MavFirmwareVersionType == "BETA"); + } + + } +} From 3db687543fdaecd6c62a02f86d7685a982c0f6fe Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 1 Mar 2024 11:25:29 +1100 Subject: [PATCH 42/44] MainV2: add periph version checking at connect. --- MainV2.cs | 124 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 124 insertions(+) diff --git a/MainV2.cs b/MainV2.cs index 1d9175092a..ce875effe8 100644 --- a/MainV2.cs +++ b/MainV2.cs @@ -38,6 +38,8 @@ using MissionPlanner.Joystick; using System.Net; using Newtonsoft.Json; +using DroneCAN; +using Accord.Math; namespace MissionPlanner { @@ -1767,6 +1769,128 @@ public void doConnect(MAVLinkInterface comPort, string portname, string baud, bo } }); + // check for newer firmware - can peripheral + if (showui) + Task.Run(() => + { + try + { + List buses = new List { 1, 2 }; + foreach (var bus in buses) + { + using (var port = new CommsInjection()) + { + var can = new DroneCAN.DroneCAN(); + can.SourceNode = 127; + + port.ReadBufferUpdate += (o, i) => { }; + port.WriteCallback += (o, bytes) => + { + var lines = ASCIIEncoding.ASCII.GetString(bytes.ToArray()) + .Split(new[] { '\r' }, StringSplitOptions.RemoveEmptyEntries); + + foreach (var line in lines) + { + can.ReadMessageSLCAN(line); + + } + + }; + + // mavlink to slcan + var canref = MainV2.comPort.SubscribeToPacketType(MAVLink.MAVLINK_MSG_ID.CAN_FRAME, (m) => + { + if (m.msgid == (uint)MAVLink.MAVLINK_MSG_ID.CAN_FRAME) + { + var canfd = false; + var pkt = (MAVLink.mavlink_can_frame_t)m.data; + var cf = new CANFrame(BitConverter.GetBytes(pkt.id)); + var length = pkt.len; + var payload = new CANPayload(pkt.data); + + var ans2 = String.Format("{0}{1}{2}{3}\r", canfd ? 'B' : 'T', cf.ToHex(), length.ToString("X") + , payload.ToHex(DroneCAN.DroneCAN.dlcToDataLength(length))); + + port.AppendBuffer(ASCIIEncoding.ASCII.GetBytes(ans2)); + } + else if (m.msgid == (uint)MAVLink.MAVLINK_MSG_ID.CANFD_FRAME) + { + var canfd = true; + var pkt = (MAVLink.mavlink_canfd_frame_t)m.data; + var cf = new CANFrame(BitConverter.GetBytes(pkt.id)); + var length = pkt.len; + var payload = new CANPayload(pkt.data); + + var ans2 = String.Format("{0}{1}{2}{3}\r", canfd ? 'B' : 'T', cf.ToHex(), length.ToString("X") + , payload.ToHex(DroneCAN.DroneCAN.dlcToDataLength(length))); + + port.AppendBuffer(ASCIIEncoding.ASCII.GetBytes(ans2)); + } + + return true; + }, (byte)MainV2.comPort.sysidcurrent, (byte)MainV2.comPort.compidcurrent, true); + + can.NodeAdded += (id, status) => + { + Console.WriteLine(id + " Node status seen"); + // get node info + DroneCAN.DroneCAN.uavcan_protocol_GetNodeInfo_req gnireq = new DroneCAN.DroneCAN.uavcan_protocol_GetNodeInfo_req() { }; + + var slcan = can.PackageMessageSLCAN((byte)id, 30, 0, gnireq); + + can.WriteToStreamSLCAN(slcan); + }; + + // be invisible + can.NodeStatus = false; + can.StartSLCAN(port.BaseStream); + + //start on bus + var ans = MainV2.comPort.doCommand((byte)MainV2.comPort.sysidcurrent, + (byte)MainV2.comPort.compidcurrent, MAVLink.MAV_CMD.CAN_FORWARD, bus, 0, 0, 0, 0, 0, 0, + false); + + Thread.Sleep(5000); + + // stop + MainV2.comPort.doCommand((byte)MainV2.comPort.sysidcurrent, + (byte)MainV2.comPort.compidcurrent, MAVLink.MAV_CMD.CAN_FORWARD, 0, 0, 0, 0, 0, 0, 0, + false); + + foreach (var node in can.NodeInfo) + { + var devicename = can.GetNodeName((byte)node.Key); + var githash = can.NodeInfo[node.Key].software_version.vcs_commit.ToString("X"); + //Version and githash + + var option = APFirmware.Manifest.Firmware.Where(a => + a.MavFirmwareVersionType == APFirmware.RELEASE_TYPES.OFFICIAL.ToString() && + a.VehicleType == "AP_Periph" && + a.Format == "bin" && + a.MavType == "CAN_PERIPHERAL" && + a.MavFirmwareVersionMajor >= node.Value.software_version.major && + a.MavFirmwareVersionMinor >= node.Value.software_version.minor && + node.Value.software_version.major != 0 && + node.Value.software_version.minor != 0 && + devicename.EndsWith(a.Platform) && + !a.GitSha.StartsWith(githash, StringComparison.InvariantCultureIgnoreCase) + ).FirstOrDefault(); + if (option != default(APFirmware.FirmwareInfo)) + { + Common.MessageShowAgain("New firmware", "New firmware for " + devicename + " " + option.MavFirmwareVersion + " " + option.GitSha + "\nUpdate via the dronecan screen"); + } + } + + MainV2.comPort.UnSubscribeToPacketType(canref); + } + } + } + catch (Exception ex) + { + log.Error(ex); + } + }); + this.BeginInvokeIfRequired(() => { _connectionControl.UpdateSysIDS(); From 89a12c3d3b19e00cf9ac56bad19c28547908cead Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 1 Mar 2024 11:38:56 +1100 Subject: [PATCH 43/44] MissionPlannerLib: fix missing files --- MainV2.cs | 1 - MissionPlannerLib.csproj | 6 +++++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/MainV2.cs b/MainV2.cs index ce875effe8..aa0fc37f82 100644 --- a/MainV2.cs +++ b/MainV2.cs @@ -39,7 +39,6 @@ using System.Net; using Newtonsoft.Json; using DroneCAN; -using Accord.Math; namespace MissionPlanner { diff --git a/MissionPlannerLib.csproj b/MissionPlannerLib.csproj index d03f4109fc..6eac41a5d0 100644 --- a/MissionPlannerLib.csproj +++ b/MissionPlannerLib.csproj @@ -471,6 +471,11 @@ + + + + + @@ -545,7 +550,6 @@ - From 7fc177c07eeb9aad0a11e2bd1bead6ce60dd3322 Mon Sep 17 00:00:00 2001 From: Michael Oborne Date: Fri, 1 Mar 2024 13:36:43 +1100 Subject: [PATCH 44/44] Update android.yml --- .github/workflows/android.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/android.yml b/.github/workflows/android.yml index dd3a16751e..dfc543c730 100644 --- a/.github/workflows/android.yml +++ b/.github/workflows/android.yml @@ -47,7 +47,7 @@ jobs: $manifest.Save($current.Path + "\ExtLibs\Xamarin\Xamarin.Android\Properties\AndroidManifest.xml") - choco install microsoft-openjdk + choco install microsoft-openjdk --version=11.0.11.9 msbuild -v:m -restore -t:SignAndroidPackage -p:Configuration=Release "ExtLibs\Xamarin\Xamarin.Android\Xamarin.Android.csproj" @@ -126,7 +126,7 @@ jobs: Set-Content -Path ExtLibs\Xamarin\Xamarin.Android\Xamarin.Android.csproj -Value (Get-Content -Path ExtLibs\Xamarin\Xamarin.Android\Xamarin.Android.csproj -Raw).Replace("true","false") - choco install microsoft-openjdk + choco install microsoft-openjdk --version=11.0.11.9 msbuild -v:m -restore -t:SignAndroidPackage -p:Configuration=Release "ExtLibs\Xamarin\Xamarin.Android\Xamarin.Android.csproj"