Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Submit feedback
Contribute to GitLab
Sign in
Toggle navigation
Q
qgroundcontrol
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Valentin Platzgummer
qgroundcontrol
Commits
6b6361ef
Commit
6b6361ef
authored
Aug 08, 2017
by
Don Gagne
Committed by
GitHub
Aug 08, 2017
Browse files
Options
Browse Files
Download
Plain Diff
Merge pull request #5533 from NaterGator/consoleperf
Switch over to model based storage for the mavlink console
parents
ab0e284f
f7aac909
Changes
3
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
141 additions
and
79 deletions
+141
-79
MavlinkConsoleController.cc
src/AnalyzeView/MavlinkConsoleController.cc
+65
-44
MavlinkConsoleController.h
src/AnalyzeView/MavlinkConsoleController.h
+4
-16
MavlinkConsolePage.qml
src/AnalyzeView/MavlinkConsolePage.qml
+72
-19
No files found.
src/AnalyzeView/MavlinkConsoleController.cc
View file @
6b6361ef
...
@@ -12,7 +12,8 @@
...
@@ -12,7 +12,8 @@
#include "UAS.h"
#include "UAS.h"
MavlinkConsoleController
::
MavlinkConsoleController
()
MavlinkConsoleController
::
MavlinkConsoleController
()
:
_cursor_home_pos
{
-
1
},
:
QStringListModel
(),
_cursor_home_pos
{
-
1
},
_cursor
{
0
},
_cursor
{
0
},
_vehicle
{
nullptr
}
_vehicle
{
nullptr
}
{
{
...
@@ -35,7 +36,7 @@ MavlinkConsoleController::sendCommand(QString command)
...
@@ -35,7 +36,7 @@ MavlinkConsoleController::sendCommand(QString command)
command
.
append
(
"
\n
"
);
command
.
append
(
"
\n
"
);
_sendSerialData
(
qPrintable
(
command
));
_sendSerialData
(
qPrintable
(
command
));
_cursor_home_pos
=
-
1
;
_cursor_home_pos
=
-
1
;
_cursor
=
_console_text
.
length
();
_cursor
=
rowCount
();
}
}
void
void
...
@@ -49,9 +50,10 @@ MavlinkConsoleController::_setActiveVehicle(Vehicle* vehicle)
...
@@ -49,9 +50,10 @@ MavlinkConsoleController::_setActiveVehicle(Vehicle* vehicle)
if
(
_vehicle
)
{
if
(
_vehicle
)
{
_incoming_buffer
.
clear
();
_incoming_buffer
.
clear
();
_console_text
.
clear
();
// Reset the model
emit
cursorChanged
(
0
);
setStringList
(
QStringList
());
emit
textChanged
(
_console_text
);
_cursor
=
0
;
_cursor_home_pos
=
-
1
;
_uas_connections
<<
connect
(
_vehicle
,
&
Vehicle
::
mavlinkSerialControl
,
this
,
&
MavlinkConsoleController
::
_receiveData
);
_uas_connections
<<
connect
(
_vehicle
,
&
Vehicle
::
mavlinkSerialControl
,
this
,
&
MavlinkConsoleController
::
_receiveData
);
}
}
}
}
...
@@ -64,17 +66,27 @@ MavlinkConsoleController::_receiveData(uint8_t device, uint8_t, uint16_t, uint32
...
@@ -64,17 +66,27 @@ MavlinkConsoleController::_receiveData(uint8_t device, uint8_t, uint16_t, uint32
// Append incoming data and parse for ANSI codes
// Append incoming data and parse for ANSI codes
_incoming_buffer
.
append
(
data
);
_incoming_buffer
.
append
(
data
);
auto
old_size
=
_console_text
.
size
();
while
(
!
_incoming_buffer
.
isEmpty
())
{
_processANSItext
();
bool
newline
=
false
;
auto
new_size
=
_console_text
.
size
();
int
idx
=
_incoming_buffer
.
indexOf
(
'\n'
);
if
(
idx
==
-
1
)
{
// Read the whole incoming buffer
idx
=
_incoming_buffer
.
size
();
}
else
{
newline
=
true
;
}
// Update QML and cursor
QByteArray
fragment
=
_incoming_buffer
.
mid
(
0
,
idx
);
if
(
old_size
>
new_size
)
{
if
(
_processANSItext
(
fragment
))
{
// Rewind back so we don't get a warning to stderr
writeLine
(
_cursor
,
fragment
);
emit
cursorChanged
(
new_size
);
if
(
newline
)
_cursor
++
;
_incoming_buffer
.
remove
(
0
,
idx
+
(
newline
?
1
:
0
));
}
else
{
// ANSI processing failed, need more data
return
;
}
}
}
emit
textChanged
(
_console_text
);
emit
cursorChanged
(
new_size
);
}
}
void
void
...
@@ -109,18 +121,16 @@ MavlinkConsoleController::_sendSerialData(QByteArray data, bool close)
...
@@ -109,18 +121,16 @@ MavlinkConsoleController::_sendSerialData(QByteArray data, bool close)
}
}
}
}
void
bool
MavlinkConsoleController
::
_processANSItext
()
MavlinkConsoleController
::
_processANSItext
(
QByteArray
&
line
)
{
{
int
i
;
// Position into the parsed buffer
// Iterate over the incoming buffer to parse off known ANSI control codes
// Iterate over the incoming buffer to parse off known ANSI control codes
for
(
i
=
0
;
i
<
_incoming_buffer
.
size
();
i
++
)
{
for
(
i
nt
i
=
0
;
i
<
line
.
size
();
i
++
)
{
if
(
_incoming_buffer
.
at
(
i
)
==
'\x1B'
)
{
if
(
line
.
at
(
i
)
==
'\x1B'
)
{
// For ANSI codes we expect at
most 4
incoming chars
// For ANSI codes we expect at
least 3
incoming chars
if
(
i
<
_incoming_buffer
.
size
()
-
3
&&
_incoming_buffer
.
at
(
i
+
1
)
==
'['
)
{
if
(
i
<
line
.
size
()
-
2
&&
line
.
at
(
i
+
1
)
==
'['
)
{
// Parse ANSI code
// Parse ANSI code
switch
(
_incoming_buffer
.
at
(
i
+
2
))
{
switch
(
line
.
at
(
i
+
2
))
{
default:
default:
continue
;
continue
;
case
'H'
:
case
'H'
:
...
@@ -134,40 +144,51 @@ MavlinkConsoleController::_processANSItext()
...
@@ -134,40 +144,51 @@ MavlinkConsoleController::_processANSItext()
break
;
break
;
case
'K'
:
case
'K'
:
// Erase the current line to the end
// Erase the current line to the end
{
if
(
_cursor
<
rowCount
())
{
auto
next_lf
=
_console_text
.
indexOf
(
'\n'
,
_cursor
);
setData
(
index
(
_cursor
),
""
);
if
(
next_lf
>
0
)
}
_console_text
.
remove
(
_cursor
,
next_lf
+
1
-
_cursor
);
}
break
;
break
;
case
'2'
:
case
'2'
:
// Erase everything and rewind to home
// Check for sufficient buffer size
if
(
_incoming_buffer
.
at
(
i
+
3
)
==
'J'
&&
_cursor_home_pos
!=
-
1
)
{
if
(
i
>=
line
.
size
()
-
3
)
// Keep newlines so textedit doesn't scroll annoyingly
return
false
;
int
newlines
=
_console_text
.
mid
(
_cursor_home_pos
).
count
(
'\n'
);
_console_text
.
remove
(
_cursor_home_pos
,
_console_text
.
size
());
if
(
line
.
at
(
i
+
3
)
==
'J'
&&
_cursor_home_pos
!=
-
1
)
{
_console_text
.
append
(
QByteArray
(
newlines
,
'\n'
));
// Erase everything and rewind to home
_cursor
=
_cursor_home_pos
;
bool
blocked
=
blockSignals
(
true
);
for
(
int
j
=
_cursor_home_pos
;
j
<
rowCount
();
j
++
)
setData
(
index
(
j
),
""
);
blockSignals
(
blocked
);
QVector
<
int
>
roles
;
roles
.
reserve
(
2
);
roles
.
append
(
Qt
::
DisplayRole
);
roles
.
append
(
Qt
::
EditRole
);
emit
dataChanged
(
index
(
_cursor
),
index
(
rowCount
()),
roles
);
}
}
// Even if we didn't understand this ANSI code, remove the 4th char
// Even if we didn't understand this ANSI code, remove the 4th char
_incoming_buffer
.
remove
(
i
+
3
,
1
);
line
.
remove
(
i
+
3
,
1
);
break
;
break
;
}
}
// Remove the parsed ANSI code and decrement the bufferpos
// Remove the parsed ANSI code and decrement the bufferpos
_incoming_buffer
.
remove
(
i
,
3
);
line
.
remove
(
i
,
3
);
i
--
;
i
--
;
}
else
{
}
else
{
// We can reasonably expect a control code was fragemented
// We can reasonably expect a control code was fragemented
// Stop parsing here and wait for it to come in
// Stop parsing here and wait for it to come in
break
;
return
false
;
}
}
}
}
}
}
return
true
;
}
// Insert the new data and increment the write cursor
void
_console_text
.
insert
(
_cursor
,
_incoming_buffer
.
left
(
i
));
MavlinkConsoleController
::
writeLine
(
int
line
,
const
QByteArray
&
text
)
_cursor
+=
i
;
{
auto
rc
=
rowCount
();
// Remove written data from the incoming buffer
if
(
line
>=
rc
)
{
_incoming_buffer
.
remove
(
0
,
i
);
insertRows
(
rc
,
1
+
line
-
rc
);
}
auto
idx
=
index
(
line
);
setData
(
idx
,
data
(
idx
,
Qt
::
DisplayRole
).
toString
()
+
text
);
}
}
src/AnalyzeView/MavlinkConsoleController.h
View file @
6b6361ef
...
@@ -14,51 +14,39 @@
...
@@ -14,51 +14,39 @@
#include "FactMetaData.h"
#include "FactMetaData.h"
#include <QObject>
#include <QObject>
#include <QString>
#include <QString>
#include <QThread>
#include <QFileInfoList>
#include <QElapsedTimer>
#include <QDebug>
#include <QGeoCoordinate>
#include <QMetaObject>
#include <QMetaObject>
#include <QStringListModel>
// Fordward decls
// Fordward decls
class
Vehicle
;
class
Vehicle
;
/// Controller for MavlinkConsole.qml.
/// Controller for MavlinkConsole.qml.
class
MavlinkConsoleController
:
public
Q
Object
class
MavlinkConsoleController
:
public
Q
StringListModel
{
{
Q_OBJECT
Q_OBJECT
Q_PROPERTY
(
int
cursor
READ
cursor
NOTIFY
cursorChanged
)
Q_PROPERTY
(
QString
text
READ
text
NOTIFY
textChanged
)
public:
public:
MavlinkConsoleController
();
MavlinkConsoleController
();
~
MavlinkConsoleController
();
~
MavlinkConsoleController
();
int
cursor
()
const
{
return
_console_text
.
size
();
}
QString
text
()
const
{
return
_console_text
;
}
public
slots
:
public
slots
:
void
sendCommand
(
QString
command
);
void
sendCommand
(
QString
command
);
signals:
signals:
void
cursorChanged
(
int
);
void
cursorChanged
(
int
);
void
textChanged
(
QString
text
);
private
slots
:
private
slots
:
void
_setActiveVehicle
(
Vehicle
*
vehicle
);
void
_setActiveVehicle
(
Vehicle
*
vehicle
);
void
_receiveData
(
uint8_t
device
,
uint8_t
flags
,
uint16_t
timeout
,
uint32_t
baudrate
,
QByteArray
data
);
void
_receiveData
(
uint8_t
device
,
uint8_t
flags
,
uint16_t
timeout
,
uint32_t
baudrate
,
QByteArray
data
);
private:
private:
void
_processANSItext
(
);
bool
_processANSItext
(
QByteArray
&
line
);
void
_sendSerialData
(
QByteArray
,
bool
close
=
false
);
void
_sendSerialData
(
QByteArray
,
bool
close
=
false
);
void
writeLine
(
int
line
,
const
QByteArray
&
text
);
int
_cursor_home_pos
;
int
_cursor_home_pos
;
int
_cursor
;
int
_cursor
;
QByteArray
_incoming_buffer
;
QByteArray
_incoming_buffer
;
QString
_console_text
;
Vehicle
*
_vehicle
;
Vehicle
*
_vehicle
;
QList
<
QMetaObject
::
Connection
>
_uas_connections
;
QList
<
QMetaObject
::
Connection
>
_uas_connections
;
...
...
src/AnalyzeView/MavlinkConsolePage.qml
View file @
6b6361ef
...
@@ -21,10 +21,12 @@ import QGroundControl.ScreenTools 1.0
...
@@ -21,10 +21,12 @@ import QGroundControl.ScreenTools 1.0
import
QGroundControl
.
Controllers
1.0
import
QGroundControl
.
Controllers
1.0
AnalyzePage
{
AnalyzePage
{
id
:
mavlinkConsolePage
id
:
mavlinkConsolePage
pageComponent
:
pageComponent
pageComponent
:
pageComponent
pageName
:
qsTr
(
"
Mavlink Console
"
)
pageName
:
qsTr
(
"
Mavlink Console
"
)
pageDescription
:
qsTr
(
"
Mavlink Console provides a connection to the vehicle's system shell.
"
)
pageDescription
:
qsTr
(
"
Mavlink Console provides a connection to the vehicle's system shell.
"
)
property
bool
loaded
:
false
Component
{
Component
{
id
:
pageComponent
id
:
pageComponent
...
@@ -34,28 +36,79 @@ AnalyzePage {
...
@@ -34,28 +36,79 @@ AnalyzePage {
height
:
availableHeight
height
:
availableHeight
width
:
availableWidth
width
:
availableWidth
TextArea
{
Connections
{
id
:
consoleEditor
target
:
conController
onDataChanged
:
{
// Keep the view in sync if the button is checked
if
(
loaded
)
{
if
(
followTail
.
checked
)
{
listview
.
positionViewAtEnd
();
}
}
}
}
Component
{
id
:
delegateItem
Rectangle
{
color
:
qgcPal
.
windowShade
height
:
Math
.
round
(
ScreenTools
.
defaultFontPixelHeight
*
0.5
+
field
.
height
)
width
:
listview
.
width
QGCLabel
{
id
:
field
text
:
display
width
:
parent
.
width
wrapMode
:
Text
.
NoWrap
font.family
:
ScreenTools
.
fixedFontFamily
anchors.verticalCenter
:
parent
.
verticalCenter
}
}
}
QGCListView
{
Component.onCompleted
:
{
loaded
=
true
}
Layout.fillHeight
:
true
Layout.fillHeight
:
true
anchors.left
:
parent
.
left
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
anchors.right
:
parent
.
right
font.family
:
ScreenTools
.
fixedFontFamily
clip
:
true
font.pointSize
:
ScreenTools
.
defaultFontPointSize
id
:
listview
readOnly
:
true
model
:
conController
delegate
:
delegateItem
cursorPosition
:
conController
.
cursor
// Unsync the view if the user interacts
text
:
conController
.
text
onMovementStarted
:
{
followTail
.
checked
=
false
}
}
}
QGCTextField
{
RowLayout
{
id
:
command
anchors.left
:
parent
.
left
anchors.left
:
parent
.
left
anchors.right
:
parent
.
right
anchors.right
:
parent
.
right
QGCTextField
{
placeholderText
:
"
Enter Commands here...
"
id
:
command
Layout.fillWidth
:
true
placeholderText
:
"
Enter Commands here...
"
onAccepted
:
{
conController
.
sendCommand
(
text
)
text
=
""
}
}
QGCButton
{
id
:
followTail
text
:
qsTr
(
"
Show Latest
"
)
checkable
:
true
checked
:
true
onAccepted
:
{
onCheckedChanged
:
{
conController
.
sendCommand
(
text
)
if
(
checked
&&
loaded
)
{
text
=
""
listview
.
positionViewAtEnd
();
}
}
}
}
}
}
}
}
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment