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
8a021e74
Commit
8a021e74
authored
Jun 26, 2014
by
Lorenz Meier
Browse files
Options
Browse Files
Download
Plain Diff
Merged mavlink-ftp
parents
95862015
4b861414
Changes
14
Hide whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
843 additions
and
123 deletions
+843
-123
qgroundcontrol.pro
qgroundcontrol.pro
+7
-2
MockMavlinkFileServer.cc
src/qgcunittest/MockMavlinkFileServer.cc
+148
-0
MockMavlinkFileServer.h
src/qgcunittest/MockMavlinkFileServer.h
+52
-0
MockMavlinkInterface.cc
src/qgcunittest/MockMavlinkInterface.cc
+9
-0
MockMavlinkInterface.h
src/qgcunittest/MockMavlinkInterface.h
+44
-0
MockUAS.cc
src/qgcunittest/MockUAS.cc
+13
-1
MockUAS.h
src/qgcunittest/MockUAS.h
+11
-4
QGCUASFileManagerTest.cc
src/qgcunittest/QGCUASFileManagerTest.cc
+156
-0
QGCUASFileManagerTest.h
src/qgcunittest/QGCUASFileManagerTest.h
+92
-0
QGCUASFileManager.cc
src/uas/QGCUASFileManager.cc
+222
-89
QGCUASFileManager.h
src/uas/QGCUASFileManager.h
+79
-27
UAS.cc
src/uas/UAS.cc
+5
-0
MainWindow.cc
src/ui/MainWindow.cc
+4
-0
QGCUASFileView.cc
src/ui/QGCUASFileView.cc
+1
-0
No files found.
qgroundcontrol.pro
View file @
8a021e74
...
@@ -186,22 +186,27 @@ DebugBuild {
...
@@ -186,22 +186,27 @@ DebugBuild {
src
/
qgcunittest
/
MockUASManager
.
h
\
src
/
qgcunittest
/
MockUASManager
.
h
\
src
/
qgcunittest
/
MockUAS
.
h
\
src
/
qgcunittest
/
MockUAS
.
h
\
src
/
qgcunittest
/
MockQGCUASParamManager
.
h
\
src
/
qgcunittest
/
MockQGCUASParamManager
.
h
\
src
/
qgcunittest
/
MockMavlinkInterface
.
h
\
src
/
qgcunittest
/
MockMavlinkFileServer
.
h
\
src
/
qgcunittest
/
MultiSignalSpy
.
h
\
src
/
qgcunittest
/
MultiSignalSpy
.
h
\
src
/
qgcunittest
/
FlightModeConfigTest
.
h
\
src
/
qgcunittest
/
FlightModeConfigTest
.
h
\
src
/
qgcunittest
/
FlightGearTest
.
h
\
src
/
qgcunittest
/
FlightGearTest
.
h
\
src
/
qgcunittest
/
TCPLinkTest
.
h
\
src
/
qgcunittest
/
TCPLinkTest
.
h
\
src
/
qgcunittest
/
TCPLoopBackServer
.
h
src
/
qgcunittest
/
TCPLoopBackServer
.
h
\
src
/
qgcunittest
/
QGCUASFileManagerTest
.
h
SOURCES
+=
\
SOURCES
+=
\
src
/
qgcunittest
/
UASUnitTest
.
cc
\
src
/
qgcunittest
/
UASUnitTest
.
cc
\
src
/
qgcunittest
/
MockUASManager
.
cc
\
src
/
qgcunittest
/
MockUASManager
.
cc
\
src
/
qgcunittest
/
MockUAS
.
cc
\
src
/
qgcunittest
/
MockUAS
.
cc
\
src
/
qgcunittest
/
MockQGCUASParamManager
.
cc
\
src
/
qgcunittest
/
MockQGCUASParamManager
.
cc
\
src
/
qgcunittest
/
MockMavlinkFileServer
.
cc
\
src
/
qgcunittest
/
MultiSignalSpy
.
cc
\
src
/
qgcunittest
/
MultiSignalSpy
.
cc
\
src
/
qgcunittest
/
FlightModeConfigTest
.
cc
\
src
/
qgcunittest
/
FlightModeConfigTest
.
cc
\
src
/
qgcunittest
/
FlightGearTest
.
cc
\
src
/
qgcunittest
/
FlightGearTest
.
cc
\
src
/
qgcunittest
/
TCPLinkTest
.
cc
\
src
/
qgcunittest
/
TCPLinkTest
.
cc
\
src
/
qgcunittest
/
TCPLoopBackServer
.
cc
src
/
qgcunittest
/
TCPLoopBackServer
.
cc
\
src
/
qgcunittest
/
QGCUASFileManagerTest
.
cc
}
}
#
#
...
...
src/qgcunittest/MockMavlinkFileServer.cc
0 → 100644
View file @
8a021e74
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "MockMavlinkFileServer.h"
void
MockMavlinkFileServer
::
sendMessage
(
mavlink_message_t
message
)
{
QGCUASFileManager
::
Request
ackResponse
;
QString
path
;
Q_ASSERT
(
message
.
msgid
==
MAVLINK_MSG_ID_ENCAPSULATED_DATA
);
mavlink_encapsulated_data_t
requestEncapsulatedData
;
mavlink_msg_encapsulated_data_decode
(
&
message
,
&
requestEncapsulatedData
);
QGCUASFileManager
::
Request
*
request
=
(
QGCUASFileManager
::
Request
*
)
&
requestEncapsulatedData
.
data
[
0
];
// Validate CRC
if
(
request
->
hdr
.
crc32
!=
QGCUASFileManager
::
crc32
(
request
))
{
_sendNak
(
QGCUASFileManager
::
kErrCrc
);
}
switch
(
request
->
hdr
.
opcode
)
{
case
QGCUASFileManager
:
:
kCmdTestNoAck
:
// ignored, ack not sent back, for testing only
break
;
case
QGCUASFileManager
:
:
kCmdReset
:
// terminates all sessions
// Fall through to send back Ack
case
QGCUASFileManager
:
:
kCmdNone
:
// ignored, always acked
ackResponse
.
hdr
.
magic
=
'f'
;
ackResponse
.
hdr
.
opcode
=
QGCUASFileManager
::
kRspAck
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
crc32
=
0
;
ackResponse
.
hdr
.
size
=
0
;
_emitResponse
(
&
ackResponse
);
break
;
case
QGCUASFileManager
:
:
kCmdList
:
// We only support root path
path
=
(
char
*
)
&
request
->
data
[
0
];
if
(
!
path
.
isEmpty
()
&&
path
!=
"/"
)
{
_sendNak
(
QGCUASFileManager
::
kErrNotDir
);
break
;
}
if
(
request
->
hdr
.
offset
>
(
uint32_t
)
_fileList
.
size
())
{
_sendNak
(
QGCUASFileManager
::
kErrEOF
);
break
;
}
ackResponse
.
hdr
.
magic
=
'f'
;
ackResponse
.
hdr
.
opcode
=
QGCUASFileManager
::
kRspAck
;
ackResponse
.
hdr
.
session
=
0
;
ackResponse
.
hdr
.
size
=
0
;
if
(
request
->
hdr
.
offset
==
0
)
{
// Requesting first batch of file names
Q_ASSERT
(
_fileList
.
size
());
char
*
bufPtr
=
(
char
*
)
&
ackResponse
.
data
[
0
];
for
(
int
i
=
0
;
i
<
_fileList
.
size
();
i
++
)
{
const
char
*
filename
=
_fileList
[
i
].
toStdString
().
c_str
();
size_t
cchFilename
=
strlen
(
filename
);
strcpy
(
bufPtr
,
filename
);
ackResponse
.
hdr
.
size
+=
cchFilename
+
1
;
bufPtr
+=
cchFilename
+
1
;
}
// Final double termination
*
bufPtr
=
0
;
ackResponse
.
hdr
.
size
++
;
}
else
{
// All filenames fit in first ack, send final null terminated ack
ackResponse
.
data
[
0
]
=
0
;
ackResponse
.
hdr
.
size
=
1
;
}
_emitResponse
(
&
ackResponse
);
break
;
// Remainder of commands are NYI
case
QGCUASFileManager
:
:
kCmdTerminate
:
// releases sessionID, closes file
case
QGCUASFileManager
:
:
kCmdOpen
:
// opens <path> for reading, returns <session>
case
QGCUASFileManager
:
:
kCmdRead
:
// reads <size> bytes from <offset> in <session>
case
QGCUASFileManager
:
:
kCmdCreate
:
// creates <path> for writing, returns <session>
case
QGCUASFileManager
:
:
kCmdWrite
:
// appends <size> bytes at <offset> in <session>
case
QGCUASFileManager
:
:
kCmdRemove
:
// remove file (only if created by server?)
default:
// nack for all NYI opcodes
_sendNak
(
QGCUASFileManager
::
kErrUnknownCommand
);
break
;
}
}
void
MockMavlinkFileServer
::
_sendNak
(
QGCUASFileManager
::
ErrorCode
error
)
{
QGCUASFileManager
::
Request
nakResponse
;
nakResponse
.
hdr
.
magic
=
'f'
;
nakResponse
.
hdr
.
opcode
=
QGCUASFileManager
::
kRspNak
;
nakResponse
.
hdr
.
session
=
0
;
nakResponse
.
hdr
.
size
=
sizeof
(
nakResponse
.
data
[
0
]);
nakResponse
.
data
[
0
]
=
error
;
_emitResponse
(
&
nakResponse
);
}
void
MockMavlinkFileServer
::
_emitResponse
(
QGCUASFileManager
::
Request
*
request
)
{
mavlink_message_t
mavlinkMessage
;
request
->
hdr
.
crc32
=
QGCUASFileManager
::
crc32
(
request
);
mavlink_msg_encapsulated_data_pack
(
250
,
0
,
&
mavlinkMessage
,
0
/*_encdata_seq*/
,
(
uint8_t
*
)
request
);
emit
messageReceived
(
NULL
,
mavlinkMessage
);
}
\ No newline at end of file
src/qgcunittest/MockMavlinkFileServer.h
0 → 100644
View file @
8a021e74
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef MOCKMAVLINKFILESERVER_H
#define MOCKMAVLINKFILESERVER_H
#include "MockMavlinkInterface.h"
#include "QGCUASFileManager.h"
#include <QStringList>
class
MockMavlinkFileServer
:
public
MockMavlinkInterface
{
Q_OBJECT
public:
MockMavlinkFileServer
(
void
)
{
};
void
setFileList
(
QStringList
&
fileList
)
{
_fileList
=
fileList
;
}
// From MockMavlinkInterface
virtual
void
sendMessage
(
mavlink_message_t
message
);
private:
void
_sendNak
(
QGCUASFileManager
::
ErrorCode
error
);
void
_emitResponse
(
QGCUASFileManager
::
Request
*
request
);
QStringList
_fileList
;
};
#endif
src/qgcunittest/MockMavlinkInterface.cc
0 → 100644
View file @
8a021e74
//
// MockMavlinkInterface.cc
// QGroundControl
//
// Created by Donald Gagne on 6/19/14.
// Copyright (c) 2014 Donald Gagne. All rights reserved.
//
#include "MockMavlinkInterface.h"
src/qgcunittest/MockMavlinkInterface.h
0 → 100644
View file @
8a021e74
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include <QObject>
#include "QGCMAVLink.h"
#include "LinkInterface.h"
#ifndef MOCKMAVLINKINTERFACE_H
#define MOCKMAVLINKINTERFACE_H
class
MockMavlinkInterface
:
public
QObject
{
Q_OBJECT
public:
virtual
void
sendMessage
(
mavlink_message_t
message
)
=
0
;
signals:
// link argument will always be NULL
void
messageReceived
(
LinkInterface
*
link
,
mavlink_message_t
message
);
};
#endif
src/qgcunittest/MockUAS.cc
View file @
8a021e74
...
@@ -27,7 +27,8 @@ QString MockUAS::_bogusStaticString;
...
@@ -27,7 +27,8 @@ QString MockUAS::_bogusStaticString;
MockUAS
::
MockUAS
(
void
)
:
MockUAS
::
MockUAS
(
void
)
:
_systemType
(
MAV_TYPE_QUADROTOR
),
_systemType
(
MAV_TYPE_QUADROTOR
),
_systemId
(
1
)
_systemId
(
1
),
_mavlinkPlugin
(
NULL
)
{
{
}
}
...
@@ -41,4 +42,15 @@ void MockUAS::setMockParametersAndSignal(MockQGCUASParamManager::ParamMap_t& map
...
@@ -41,4 +42,15 @@ void MockUAS::setMockParametersAndSignal(MockQGCUASParamManager::ParamMap_t& map
i
.
next
();
i
.
next
();
emit
parameterChanged
(
_systemId
,
0
,
i
.
key
(),
i
.
value
());
emit
parameterChanged
(
_systemId
,
0
,
i
.
key
(),
i
.
value
());
}
}
}
void
MockUAS
::
sendMessage
(
mavlink_message_t
message
)
{
Q_UNUSED
(
link
);
if
(
!
_mavlinkPlugin
)
{
Q_ASSERT
(
false
);
}
_mavlinkPlugin
->
sendMessage
(
message
);
}
}
\ No newline at end of file
src/qgcunittest/MockUAS.h
View file @
8a021e74
...
@@ -26,6 +26,7 @@
...
@@ -26,6 +26,7 @@
#include "UASInterface.h"
#include "UASInterface.h"
#include "MockQGCUASParamManager.h"
#include "MockQGCUASParamManager.h"
#include "MockMavlinkInterface.h"
#include <limits>
#include <limits>
...
@@ -50,6 +51,9 @@ public:
...
@@ -50,6 +51,9 @@ public:
virtual
int
getUASID
(
void
)
const
{
return
_systemId
;
}
virtual
int
getUASID
(
void
)
const
{
return
_systemId
;
}
virtual
QGCUASParamManagerInterface
*
getParamManager
()
{
return
&
_paramManager
;
};
virtual
QGCUASParamManagerInterface
*
getParamManager
()
{
return
&
_paramManager
;
};
// sendMessage is only supported if a mavlink plugin is installed.
virtual
void
sendMessage
(
mavlink_message_t
message
);
public:
public:
// MockUAS methods
// MockUAS methods
MockUAS
(
void
);
MockUAS
(
void
);
...
@@ -63,12 +67,15 @@ public:
...
@@ -63,12 +67,15 @@ public:
/// allows you to simulate parameter input and validate parameter setting
/// allows you to simulate parameter input and validate parameter setting
MockQGCUASParamManager
*
getMockQGCUASParamManager
(
void
)
{
return
&
_paramManager
;
}
MockQGCUASParamManager
*
getMockQGCUASParamManager
(
void
)
{
return
&
_paramManager
;
}
/// Sets the parameter map into the mock QGCUASParamManager and signals parameterChanged for
///
@brief
Sets the parameter map into the mock QGCUASParamManager and signals parameterChanged for
/// each param
/// each param
void
setMockParametersAndSignal
(
MockQGCUASParamManager
::
ParamMap_t
&
map
);
void
setMockParametersAndSignal
(
MockQGCUASParamManager
::
ParamMap_t
&
map
);
void
emitRemoteControlChannelRawChanged
(
int
channel
,
float
raw
)
{
emit
remoteControlChannelRawChanged
(
channel
,
raw
);
}
void
emitRemoteControlChannelRawChanged
(
int
channel
,
float
raw
)
{
emit
remoteControlChannelRawChanged
(
channel
,
raw
);
}
/// @brief Installs a mavlink plugin. Only a single mavlink plugin is supported at a time.
void
setMockMavlinkPlugin
(
MockMavlinkInterface
*
mavlinkPlugin
)
{
_mavlinkPlugin
=
mavlinkPlugin
;
};
public:
public:
// Unimplemented UASInterface overrides
// Unimplemented UASInterface overrides
virtual
QString
getUASName
()
const
{
Q_ASSERT
(
false
);
return
_bogusString
;
};
virtual
QString
getUASName
()
const
{
Q_ASSERT
(
false
);
return
_bogusString
;
};
...
@@ -112,9 +119,7 @@ public:
...
@@ -112,9 +119,7 @@ public:
virtual
QGCUASFileManager
*
getFileManager
()
{
Q_ASSERT
(
false
);
return
NULL
;
}
virtual
QGCUASFileManager
*
getFileManager
()
{
Q_ASSERT
(
false
);
return
NULL
;
}
/** @brief Send a message over this link (to this or to all UAS on this link) */
/** @brief Send a message over this link (to this or to all UAS on this link) */
virtual
void
sendMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
){
Q_ASSERT
(
false
);}
virtual
void
sendMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
){
Q_UNUSED
(
link
);
Q_UNUSED
(
message
);
Q_ASSERT
(
false
);
}
/** @brief Send a message over all links this UAS can be reached with (!= all links) */
virtual
void
sendMessage
(
mavlink_message_t
message
)
{
Q_ASSERT
(
false
);}
virtual
QString
getAutopilotTypeName
()
{
Q_ASSERT
(
false
);
return
_bogusString
;
};
virtual
QString
getAutopilotTypeName
()
{
Q_ASSERT
(
false
);
return
_bogusString
;
};
virtual
void
setAutopilotType
(
int
apType
)
{
Q_UNUSED
(
apType
);
Q_ASSERT
(
false
);
};
virtual
void
setAutopilotType
(
int
apType
)
{
Q_UNUSED
(
apType
);
Q_ASSERT
(
false
);
};
virtual
QMap
<
int
,
QString
>
getComponents
()
{
Q_ASSERT
(
false
);
return
_bogusMapIntQString
;
};
virtual
QMap
<
int
,
QString
>
getComponents
()
{
Q_ASSERT
(
false
);
return
_bogusMapIntQString
;
};
...
@@ -182,6 +187,8 @@ private:
...
@@ -182,6 +187,8 @@ private:
int
_systemId
;
int
_systemId
;
MockQGCUASParamManager
_paramManager
;
MockQGCUASParamManager
_paramManager
;
MockMavlinkInterface
*
_mavlinkPlugin
;
///< Mock Mavlink plugin, NULL for none
// Bogus variables used for return types of NYI methods
// Bogus variables used for return types of NYI methods
QString
_bogusString
;
QString
_bogusString
;
...
...
src/qgcunittest/QGCUASFileManagerTest.cc
0 → 100644
View file @
8a021e74
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "QGCUASFileManagerTest.h"
/// @file
/// @brief QGCUASFileManager unit test
///
/// @author Don Gagne <don@thegagnes.com>
QGCUASFileManagerUnitTest
::
QGCUASFileManagerUnitTest
(
void
)
:
_fileManager
(
NULL
),
_multiSpy
(
NULL
)
{
}
// Called once before all test cases are run
void
QGCUASFileManagerUnitTest
::
initTestCase
(
void
)
{
_mockUAS
.
setMockMavlinkPlugin
(
&
_mockFileServer
);
}
// Called before every test case
void
QGCUASFileManagerUnitTest
::
init
(
void
)
{
Q_ASSERT
(
_multiSpy
==
NULL
);
_fileManager
=
new
QGCUASFileManager
(
NULL
,
&
_mockUAS
);
Q_CHECK_PTR
(
_fileManager
);
bool
connected
=
connect
(
&
_mockFileServer
,
SIGNAL
(
messageReceived
(
LinkInterface
*
,
mavlink_message_t
)),
_fileManager
,
SLOT
(
receiveMessage
(
LinkInterface
*
,
mavlink_message_t
)));
Q_ASSERT
(
connected
);
connected
=
connect
(
_fileManager
,
SIGNAL
(
statusMessage
(
const
QString
&
)),
this
,
SLOT
(
statusMessage
(
const
QString
&
)));
Q_ASSERT
(
connected
);
_rgSignals
[
statusMessageSignalIndex
]
=
SIGNAL
(
statusMessage
(
const
QString
&
));
_rgSignals
[
errorMessageSignalIndex
]
=
SIGNAL
(
errorMessage
(
const
QString
&
));
_rgSignals
[
resetStatusMessagesSignalIndex
]
=
SIGNAL
(
resetStatusMessages
(
void
));
_multiSpy
=
new
MultiSignalSpy
();
Q_CHECK_PTR
(
_multiSpy
);
QCOMPARE
(
_multiSpy
->
init
(
_fileManager
,
_rgSignals
,
_cSignals
),
true
);
}
// Called after every test case
void
QGCUASFileManagerUnitTest
::
cleanup
(
void
)
{
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_fileManager
);
delete
_fileManager
;
delete
_multiSpy
;
_fileManager
=
NULL
;
_multiSpy
=
NULL
;
}
/// @brief Connected to QGCUASFileManager statusMessage signal in order to catch list command output
void
QGCUASFileManagerUnitTest
::
statusMessage
(
const
QString
&
msg
)
{
// Keep a list of all names received so we can test it for correctness
_fileListReceived
+=
msg
;
}
void
QGCUASFileManagerUnitTest
::
_ackTest
(
void
)
{
Q_ASSERT
(
_fileManager
);
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_multiSpy
->
checkNoSignals
()
==
true
);
// If the file manager doesn't receive an ack it will timeout and emit an error. So make sure
// we don't get any error signals.
QVERIFY
(
_fileManager
->
_sendCmdTestAck
());
QVERIFY
(
_multiSpy
->
checkNoSignals
());
}
void
QGCUASFileManagerUnitTest
::
_noAckTest
(
void
)
{
Q_ASSERT
(
_fileManager
);
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_multiSpy
->
checkNoSignals
()
==
true
);
// This should not get the ack back and timeout.
QVERIFY
(
_fileManager
->
_sendCmdTestNoAck
());
QTest
::
qWait
(
2000
);
// Let the file manager timeout, magic number 2 secs must be larger than file manager ack timeout
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
errorMessageSignalMask
),
true
);
}
void
QGCUASFileManagerUnitTest
::
_resetTest
(
void
)
{
Q_ASSERT
(
_fileManager
);
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_multiSpy
->
checkNoSignals
()
==
true
);
// Send a reset command
// We should not get any signals back from this
QVERIFY
(
_fileManager
->
_sendCmdReset
());
QVERIFY
(
_multiSpy
->
checkNoSignals
());
}
void
QGCUASFileManagerUnitTest
::
_listTest
(
void
)
{
Q_ASSERT
(
_fileManager
);
Q_ASSERT
(
_multiSpy
);
Q_ASSERT
(
_multiSpy
->
checkNoSignals
()
==
true
);
// Send a bogus path
// We should get a single resetStatusMessages signal
// We should get a single errorMessage signal
_fileManager
->
listRecursively
(
"/bogus"
);
QCOMPARE
(
_multiSpy
->
checkOnlySignalByMask
(
errorMessageSignalMask
|
resetStatusMessagesSignalMask
),
true
);
_multiSpy
->
clearAllSignals
();
// Send a list command at the root of the directory tree
// We should get back a single resetStatusMessages signal
// We should not get back an errorMessage signal
// We should get back one or more statusMessage signals
// The returned list should match out inputs
QStringList
fileList
;
fileList
<<
"Ddir"
<<
"Ffoo"
<<
"Fbar"
;
_mockFileServer
.
setFileList
(
fileList
);
QStringList
fileListExpected
;
fileListExpected
<<
"dir/"
<<
"foo"
<<
"bar"
;
_fileListReceived
.
clear
();
_fileManager
->
listRecursively
(
"/"
);
QCOMPARE
(
_multiSpy
->
checkSignalByMask
(
resetStatusMessagesSignalMask
),
true
);
// We should be told to reset status messages
QCOMPARE
(
_multiSpy
->
checkNoSignalByMask
(
errorMessageSignalMask
),
true
);
// We should not get an error signals
QVERIFY
(
_fileListReceived
==
fileListExpected
);
}
src/qgcunittest/QGCUASFileManagerTest.h
0 → 100644
View file @
8a021e74
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef QGCUASFILEMANAGERTEST_H
#define QGCUASFILEMANAGERTEST_H
#include <QObject>
#include <QtTest/QtTest>
#include "AutoTest.h"
#include "MockUAS.h"
#include "MockMavlinkFileServer.h"
#include "QGCUASFileManager.h"
#include "MultiSignalSpy.h"
/// @file
/// @brief QGCUASFileManager unit test
///
/// @author Don Gagne <don@thegagnes.com>
class
QGCUASFileManagerUnitTest
:
public
QObject
{
Q_OBJECT
public:
QGCUASFileManagerUnitTest
(
void
);
private
slots
:
// Test case initialization
void
initTestCase
(
void
);
void
init
(
void
);
void
cleanup
(
void
);
// Test cases
void
_ackTest
(
void
);
void
_noAckTest
(
void
);
void
_resetTest
(
void
);
void
_listTest
(
void
);
// Connected to QGCUASFileManager statusMessage signal
void
statusMessage
(
const
QString
&
);
private:
enum
{
statusMessageSignalIndex
=
0
,
errorMessageSignalIndex
,
resetStatusMessagesSignalIndex
,
maxSignalIndex
};
enum
{
statusMessageSignalMask
=
1
<<
statusMessageSignalIndex
,
errorMessageSignalMask
=
1
<<
errorMessageSignalIndex
,
resetStatusMessagesSignalMask
=
1
<<
resetStatusMessagesSignalIndex
,
};
MockUAS
_mockUAS
;
MockMavlinkFileServer
_mockFileServer
;
QGCUASFileManager
*
_fileManager
;
MultiSignalSpy
*
_multiSpy
;
static
const
size_t
_cSignals
=
maxSignalIndex
;
const
char
*
_rgSignals
[
_cSignals
];
QStringList
_fileListReceived
;
};
DECLARE_TEST
(
QGCUASFileManagerUnitTest
)
#endif
src/uas/QGCUASFileManager.cc
View file @
8a021e74
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#include "QGCUASFileManager.h"
#include "QGCUASFileManager.h"
#include "QGC.h"
#include "QGC.h"
#include "MAVLinkProtocol.h"
#include "MAVLinkProtocol.h"
...
@@ -44,86 +67,106 @@ static const quint32 crctab[] =
...
@@ -44,86 +67,106 @@ static const quint32 crctab[] =
QGCUASFileManager
::
QGCUASFileManager
(
QObject
*
parent
,
UASInterface
*
uas
)
:
QGCUASFileManager
::
QGCUASFileManager
(
QObject
*
parent
,
UASInterface
*
uas
)
:
QObject
(
parent
),
QObject
(
parent
),
_currentOperation
(
kCOIdle
),
_mav
(
uas
),
_mav
(
uas
),
_encdata_seq
(
0
)
_encdata_seq
(
0
)
{
{
bool
connected
=
connect
(
&
_ackTimer
,
SIGNAL
(
timeout
()),
this
,
SLOT
(
_ackTimeout
()));
Q_ASSERT
(
connected
);
}
}
quint32
/// @brief Calculates a 32 bit CRC for the specified request.
QGCUASFileManager
::
crc32
(
const
uint8_t
*
src
,
unsigned
len
,
unsigned
state
)
/// @param request Request to calculate CRC for. request->size must be set correctly.
/// @param state previous crc state
/// @return Calculated CRC
quint32
QGCUASFileManager
::
crc32
(
Request
*
request
,
unsigned
state
)
{
{
for
(
unsigned
i
=
0
;
i
<
len
;
i
++
)
uint8_t
*
data
=
(
uint8_t
*
)
request
;
state
=
crctab
[(
state
^
src
[
i
])
&
0xff
]
^
(
state
>>
8
);
size_t
cbData
=
sizeof
(
RequestHeader
)
+
request
->
hdr
.
size
;
// Always calculate CRC with 0 initial CRC value
quint32
crcSave
=
request
->
hdr
.
crc32
;
request
->
hdr
.
crc32
=
0
;
for
(
size_t
i
=
0
;
i
<
cbData
;
i
++
)
state
=
crctab
[(
state
^
data
[
i
])
&
0xff
]
^
(
state
>>
8
);
request
->
hdr
.
crc32
=
crcSave
;
return
state
;
return
state
;
}
}
void
QGCUASFileManager
::
nothingMessage
()
void
QGCUASFileManager
::
nothingMessage
()
{
{
mavlink_message_t
message
;
// FIXME: Connect ui correctly
RequestHeader
hdr
;
hdr
.
magic
=
'f'
;
hdr
.
session
=
0
;
hdr
.
crc32
=
0
;
hdr
.
size
=
0
;
hdr
.
crc32
=
crc32
((
uint8_t
*
)
&
hdr
,
sizeof
(
hdr
)
+
hdr
.
size
,
0
);
mavlink_msg_encapsulated_data_pack
(
250
,
0
,
&
message
,
_encdata_seq
,
(
uint8_t
*
)
&
hdr
);
_mav
->
sendMessage
(
message
);
qDebug
()
<<
"Sent message!"
;
}
}
void
QGCUASFileManager
::
receiveMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
)
void
QGCUASFileManager
::
receiveMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
)
{
{
Q_UNUSED
(
link
);
Q_UNUSED
(
link
);
if
(
message
.
msgid
!=
MAVLINK_MSG_ID_ENCAPSULATED_DATA
)
{
if
(
message
.
msgid
!=
MAVLINK_MSG_ID_ENCAPSULATED_DATA
)
{
// wtf, not for us
// wtf, not for us
return
;
return
;
}
}
emit
statusMessage
(
"msg"
);
qDebug
()
<<
"FTP GOT MESSAGE"
;
mavlink_encapsulated_data_t
data
;
mavlink_encapsulated_data_t
data
;
mavlink_msg_encapsulated_data_decode
(
&
message
,
&
data
);
mavlink_msg_encapsulated_data_decode
(
&
message
,
&
data
);
const
RequestHeader
*
hdr
=
(
const
RequestHeader
*
)
&
data
.
data
[
0
];
Request
*
request
=
(
Request
*
)
&
data
.
data
[
0
];
unsigned
seqnr
=
data
.
seqnr
;
qDebug
()
<<
"FTP: opcode:"
<<
request
->
hdr
.
opcode
;
switch
(
_current_operation
)
{
case
kCOIdle
:
// FIXME: Check CRC
// we should not be seeing anything here.. shut the other guy up
emit
statusMessage
(
"resetting file transfer session"
);
if
(
request
->
hdr
.
opcode
==
kRspAck
)
{
sendReset
();
_clearAckTimeout
();
break
;
switch
(
_currentOperation
)
{
case
kCOList
:
case
kCOIdle
:
if
(
hdr
->
opcode
==
kRspAck
)
{
// we should not be seeing anything here.. shut the other guy up
listDecode
(
&
hdr
->
data
[
0
],
hdr
->
size
);
qDebug
()
<<
"FTP resetting file transfer session"
;
}
else
{
_sendCmdReset
();
emit
statusMessage
(
"unexpected opcode in List mode"
);
break
;
case
kCOAck
:
// We are expecting an ack back
_clearAckTimeout
();
_currentOperation
=
kCOIdle
;
break
;
case
kCOList
:
listDecode
(
&
request
->
data
[
0
],
request
->
hdr
.
size
);
break
;
default:
_emitErrorMessage
(
"Ack received in unexpected state"
);
break
;
}
}
break
;
}
else
if
(
request
->
hdr
.
opcode
==
kRspNak
)
{
_clearAckTimeout
();
default:
_emitErrorMessage
(
QString
(
"Nak received, error: "
).
append
(
errorString
(
request
->
data
[
0
])));
emit
statusMessage
(
"message in unexpected state"
);
_currentOperation
=
kCOIdle
;
}
else
{
// Note that we don't change our operation state. If something goes wrong beyond this, the operation
// will time out.
_emitErrorMessage
(
tr
(
"Unknown opcode returned server: %1"
).
arg
(
request
->
hdr
.
opcode
));
}
}
}
}
void
QGCUASFileManager
::
listRecursively
(
const
QString
&
from
)
void
QGCUASFileManager
::
listRecursively
(
const
QString
&
from
)
{
{
if
(
_current_operation
!=
kCOIdle
)
{
if
(
_currentOperation
!=
kCOIdle
)
{
// XXX beep and don't do anything
_emitErrorMessage
(
tr
(
"Command not sent. Waiting for previous command to complete."
));
return
;
}
}
// clear the text widget
// clear the text widget
emit
resetStatusMessages
();
emit
resetStatusMessages
();
// initialise the lister
// initialise the lister
_list
_p
ath
=
from
;
_list
P
ath
=
from
;
_list
_o
ffset
=
0
;
_list
O
ffset
=
0
;
_current
_o
peration
=
kCOList
;
_current
O
peration
=
kCOList
;
// and send the initial request
// and send the initial request
sendList
();
sendList
();
...
@@ -136,15 +179,22 @@ void QGCUASFileManager::listDecode(const uint8_t *data, unsigned len)
...
@@ -136,15 +179,22 @@ void QGCUASFileManager::listDecode(const uint8_t *data, unsigned len)
// parse filenames out of the buffer
// parse filenames out of the buffer
while
(
offset
<
len
)
{
while
(
offset
<
len
)
{
const
char
*
ptr
=
(
const
char
*
)
data
+
offset
;
// get the length of the name
// get the length of the name
unsigned
nlen
=
strnlen
(
(
const
char
*
)
data
+
offset
,
len
-
offset
);
unsigned
nlen
=
strnlen
(
ptr
,
len
-
offset
);
if
(
nlen
==
0
)
{
if
(
nlen
<
2
)
{
break
;
break
;
}
}
// Returned names are prepended with D for directory or F for file
QString
s
(
ptr
+
1
);
if
(
*
ptr
==
'D'
)
{
s
.
append
(
'/'
);
}
// put it in the view
// put it in the view
emit
statusMessage
(
QString
((
const
char
*
)
data
+
offset
)
);
emit
statusMessage
(
s
);
// account for the name + NUL
// account for the name + NUL
offset
+=
nlen
+
1
;
offset
+=
nlen
+
1
;
...
@@ -155,59 +205,35 @@ void QGCUASFileManager::listDecode(const uint8_t *data, unsigned len)
...
@@ -155,59 +205,35 @@ void QGCUASFileManager::listDecode(const uint8_t *data, unsigned len)
// we have run out of files to list
// we have run out of files to list
if
(
files
==
0
)
{
if
(
files
==
0
)
{
_current
_o
peration
=
kCOIdle
;
_current
O
peration
=
kCOIdle
;
}
else
{
}
else
{
// update our state
// update our state
_list
_o
ffset
+=
files
;
_list
O
ffset
+=
files
;
// and send another request
// and send another request
sendList
();
sendList
();
}
}
}
}
void
QGCUASFileManager
::
sendReset
()
{
mavlink_message_t
message
;
RequestHeader
hdr
;
hdr
.
magic
=
'f'
;
hdr
.
session
=
0
;
hdr
.
opcode
=
kCmdReset
;
hdr
.
crc32
=
0
;
hdr
.
offset
=
0
;
hdr
.
size
=
0
;
hdr
.
crc32
=
crc32
((
uint8_t
*
)
&
hdr
,
sizeof
(
hdr
)
+
hdr
.
size
,
0
);
mavlink_msg_encapsulated_data_pack
(
250
,
0
,
&
message
,
_encdata_seq
,
(
uint8_t
*
)
&
hdr
);
// XXX 250 is a magic length
_mav
->
sendMessage
(
message
);
}
void
QGCUASFileManager
::
sendList
()
void
QGCUASFileManager
::
sendList
()
{
{
mavlink_message_t
message
;
Request
request
;
RequestHeader
hdr
;
request
.
hdr
.
magic
=
'f'
;
hdr
.
magic
=
'f'
;
request
.
hdr
.
session
=
0
;
hdr
.
session
=
0
;
request
.
hdr
.
opcode
=
kCmdList
;
hdr
.
opcode
=
kCmdList
;
request
.
hdr
.
offset
=
_listOffset
;
hdr
.
crc32
=
0
;
hdr
.
offset
=
_list_offset
;
strncpy
((
char
*
)
&
request
.
data
[
0
],
_listPath
.
toStdString
().
c_str
(),
sizeof
(
request
.
data
));
strncpy
((
char
*
)
&
hdr
.
data
[
0
],
_list_path
.
toStdString
().
c_str
(),
200
);
// XXX should have a real limit here
request
.
hdr
.
size
=
strnlen
((
const
char
*
)
&
request
.
data
[
0
],
sizeof
(
request
.
data
));
hdr
.
size
=
strlen
((
const
char
*
)
&
hdr
.
data
[
0
]);
_sendRequest
(
&
request
);
hdr
.
crc32
=
crc32
((
uint8_t
*
)
&
hdr
,
sizeof
(
hdr
)
+
hdr
.
size
,
0
);
mavlink_msg_encapsulated_data_pack
(
250
,
0
,
&
message
,
_encdata_seq
,
(
uint8_t
*
)
&
hdr
);
// XXX 250 is a magic length
emit
statusMessage
(
"sending List request..."
);
_mav
->
sendMessage
(
message
);
}
}
void
QGCUASFileManager
::
downloadPath
(
const
QString
&
from
,
const
QString
&
to
)
void
QGCUASFileManager
::
downloadPath
(
const
QString
&
from
,
const
QString
&
to
)
{
{
Q_UNUSED
(
from
);
// Send path, e.g. /fs/microsd and download content
// Send path, e.g. /fs/microsd and download content
// recursively into a local directory
// recursively into a local directory
...
@@ -225,3 +251,110 @@ void QGCUASFileManager::downloadPath(const QString &from, const QString &to)
...
@@ -225,3 +251,110 @@ void QGCUASFileManager::downloadPath(const QString &from, const QString &to)
emit
statusMessage
(
QString
(
"Downloaded: %1 to directory %2"
).
arg
(
filename
).
arg
(
to
));
emit
statusMessage
(
QString
(
"Downloaded: %1 to directory %2"
).
arg
(
filename
).
arg
(
to
));
}
}
QString
QGCUASFileManager
::
errorString
(
uint8_t
errorCode
)
{
switch
(
errorCode
)
{
case
kErrNone
:
return
QString
(
"no error"
);
case
kErrNoRequest
:
return
QString
(
"bad request"
);
case
kErrNoSession
:
return
QString
(
"bad session"
);
case
kErrSequence
:
return
QString
(
"bad sequence number"
);
case
kErrNotDir
:
return
QString
(
"not a directory"
);
case
kErrNotFile
:
return
QString
(
"not a file"
);
case
kErrEOF
:
return
QString
(
"read beyond end of file"
);
case
kErrNotAppend
:
return
QString
(
"write not at end of file"
);
case
kErrTooBig
:
return
QString
(
"file too big"
);
case
kErrIO
:
return
QString
(
"device I/O error"
);
case
kErrPerm
:
return
QString
(
"permission denied"
);
case
kErrUnknownCommand
:
return
QString
(
"unknown command"
);
case
kErrCrc
:
return
QString
(
"bad crc"
);
default:
return
QString
(
"unknown error code"
);
}
}
/// @brief Sends a command which only requires an opcode and no additional data
/// @param opcode Opcode to send
/// @param newOpState State to put state machine into
/// @return TRUE: command sent, FALSE: command not sent, waiting for previous command to finish
bool
QGCUASFileManager
::
_sendOpcodeOnlyCmd
(
uint8_t
opcode
,
OperationState
newOpState
)
{
if
(
_currentOperation
!=
kCOIdle
)
{
// Can't have multiple commands in play at the same time
return
false
;
}
Request
request
;
request
.
hdr
.
magic
=
'f'
;
request
.
hdr
.
session
=
0
;
request
.
hdr
.
opcode
=
opcode
;
request
.
hdr
.
offset
=
0
;
request
.
hdr
.
size
=
0
;
_currentOperation
=
newOpState
;
_setupAckTimeout
();
_sendRequest
(
&
request
);
return
TRUE
;
}
/// @brief Starts the ack timeout timer
void
QGCUASFileManager
::
_setupAckTimeout
(
void
)
{
qDebug
()
<<
"Setting Ack"
;
Q_ASSERT
(
!
_ackTimer
.
isActive
());
_ackTimer
.
setSingleShot
(
true
);
_ackTimer
.
start
(
_ackTimerTimeoutMsecs
);
}
/// @brief Clears the ack timeout timer
void
QGCUASFileManager
::
_clearAckTimeout
(
void
)
{
qDebug
()
<<
"Clearing Ack"
;
Q_ASSERT
(
_ackTimer
.
isActive
());
_ackTimer
.
stop
();
}
/// @brief Called when ack timeout timer fires
void
QGCUASFileManager
::
_ackTimeout
(
void
)
{
_currentOperation
=
kCOIdle
;
_emitErrorMessage
(
tr
(
"Timeout waiting for ack"
));
}
void
QGCUASFileManager
::
_emitErrorMessage
(
const
QString
&
msg
)
{
qDebug
()
<<
"QGCUASFileManager:"
<<
msg
;
emit
errorMessage
(
msg
);
}
/// @brief Sends the specified Request out to the UAS.
void
QGCUASFileManager
::
_sendRequest
(
Request
*
request
)
{
mavlink_message_t
message
;
_setupAckTimeout
();
request
->
hdr
.
crc32
=
crc32
(
request
);
// FIXME: Send correct system id instead of harcoded 250
mavlink_msg_encapsulated_data_pack
(
250
,
0
,
&
message
,
_encdata_seq
,
(
uint8_t
*
)
request
);
_mav
->
sendMessage
(
message
);
}
\ No newline at end of file
src/uas/QGCUASFileManager.h
View file @
8a021e74
/*=====================================================================
QGroundControl Open Source Ground Control Station
(c) 2009 - 2014 QGROUNDCONTROL PROJECT <http://www.qgroundcontrol.org>
This file is part of the QGROUNDCONTROL project
QGROUNDCONTROL is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
QGROUNDCONTROL is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with QGROUNDCONTROL. If not, see <http://www.gnu.org/licenses/>.
======================================================================*/
#ifndef QGCUASFILEMANAGER_H
#ifndef QGCUASFILEMANAGER_H
#define QGCUASFILEMANAGER_H
#define QGCUASFILEMANAGER_H
#include <QObject>
#include <QObject>
#include "UASInterface.h"
#include "UASInterface.h"
class
QGCUASFileManager
:
public
QObject
class
QGCUASFileManager
:
public
QObject
...
@@ -9,17 +33,22 @@ class QGCUASFileManager : public QObject
...
@@ -9,17 +33,22 @@ class QGCUASFileManager : public QObject
Q_OBJECT
Q_OBJECT
public:
public:
QGCUASFileManager
(
QObject
*
parent
,
UASInterface
*
uas
);
QGCUASFileManager
(
QObject
*
parent
,
UASInterface
*
uas
);
/// These methods are only used for testing purposes.
bool
_sendCmdTestAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdNone
,
kCOAck
);
};
bool
_sendCmdTestNoAck
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdTestNoAck
,
kCOAck
);
};
bool
_sendCmdReset
(
void
)
{
return
_sendOpcodeOnlyCmd
(
kCmdReset
,
kCOAck
);
};
signals:
signals:
void
statusMessage
(
const
QString
&
msg
);
void
statusMessage
(
const
QString
&
msg
);
void
resetStatusMessages
();
void
resetStatusMessages
();
void
errorMessage
(
const
QString
&
ms
);
public
slots
:
public
slots
:
void
receiveMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
);
void
receiveMessage
(
LinkInterface
*
link
,
mavlink_message_t
message
);
void
nothingMessage
();
void
nothingMessage
();
void
listRecursively
(
const
QString
&
from
);
void
listRecursively
(
const
QString
&
from
);
void
downloadPath
(
const
QString
&
from
,
const
QString
&
to
);
void
downloadPath
(
const
QString
&
from
,
const
QString
&
to
);
// void timedOut();
protected:
protected:
struct
RequestHeader
struct
RequestHeader
...
@@ -30,23 +59,32 @@ protected:
...
@@ -30,23 +59,32 @@ protected:
uint8_t
size
;
uint8_t
size
;
uint32_t
crc32
;
uint32_t
crc32
;
uint32_t
offset
;
uint32_t
offset
;
uint8_t
data
[];
};
};
struct
Request
{
struct
RequestHeader
hdr
;
// The entire Request must fit into the data member of the mavlink_encapsulated_data_t structure. We use as many leftover bytes
// after we use up space for the RequestHeader for the data portion of the Request.
uint8_t
data
[
sizeof
(((
mavlink_encapsulated_data_t
*
)
0
)
->
data
)
-
sizeof
(
RequestHeader
)];
};
enum
Opcode
enum
Opcode
{
{
kCmdNone
,
// ignored, always acked
kCmdNone
,
// ignored, always acked
kCmdTerminate
,
// releases sessionID, closes file
kCmdTerminate
,
// releases sessionID, closes file
kCmdReset
,
// terminates all sessions
kCmdReset
,
// terminates all sessions
kCmdList
,
// list files in <path> from <offset>
kCmdList
,
// list files in <path> from <offset>
kCmdOpen
,
// opens <path> for reading, returns <session>
kCmdOpen
,
// opens <path> for reading, returns <session>
kCmdRead
,
// reads <size> bytes from <offset> in <session>
kCmdRead
,
// reads <size> bytes from <offset> in <session>
kCmdCreate
,
// creates <path> for writing, returns <session>
kCmdCreate
,
// creates <path> for writing, returns <session>
kCmdWrite
,
// appends <size> bytes at <offset> in <session>
kCmdWrite
,
// appends <size> bytes at <offset> in <session>
kCmdRemove
,
// remove file (only if created by server?)
kCmdRemove
,
// remove file (only if created by server?)
kRspAck
,
kRspAck
,
kRspNak
kRspNak
,
kCmdTestNoAck
,
// ignored, ack not sent back, for testing only, should timeout waiting for ack
};
};
enum
ErrorCode
enum
ErrorCode
...
@@ -61,35 +99,49 @@ protected:
...
@@ -61,35 +99,49 @@ protected:
kErrNotAppend
,
kErrNotAppend
,
kErrTooBig
,
kErrTooBig
,
kErrIO
,
kErrIO
,
kErrPerm
kErrPerm
,
kErrUnknownCommand
,
kErrCrc
};
};
enum
OperationState
enum
OperationState
{
{
kCOIdle
,
// not doing anything
kCOIdle
,
// not doing anything
kCOAck
,
// waiting for an Ack
kCOList
,
// waiting for a List response
kCOList
,
// waiting for a List response
};
};
OperationState
_current_operation
;
unsigned
_retry_counter
;
protected
slots
:
void
_ackTimeout
(
void
);
UASInterface
*
_mav
;
quint16
_encdata_seq
;
protected:
bool
_sendOpcodeOnlyCmd
(
uint8_t
opcode
,
OperationState
newOpState
);
unsigned
_session_id
;
// session ID for current session
void
_setupAckTimeout
(
void
);
unsigned
_list_offset
;
// offset for the current List operation
void
_clearAckTimeout
(
void
);
QString
_list_path
;
// path for the current List operation
void
_emitErrorMessage
(
const
QString
&
msg
);
void
_sendRequest
(
Request
*
request
);
void
sendTerminate
();
void
sendReset
();
void
sendList
();
void
sendList
();
void
listDecode
(
const
uint8_t
*
data
,
unsigned
len
);
void
listDecode
(
const
uint8_t
*
data
,
unsigned
len
);
static
quint32
crc32
(
const
uint8_t
*
src
,
unsigned
len
,
unsigned
state
);
static
quint32
crc32
(
Request
*
request
,
unsigned
state
=
0
);
static
QString
errorString
(
uint8_t
errorCode
);
OperationState
_currentOperation
;
///> Current operation of state machine
QTimer
_ackTimer
;
///> Used to signal a timeout waiting for an ack
static
const
int
_ackTimerTimeoutMsecs
=
1000
;
///> Timeout in msecs for ack timer
UASInterface
*
_mav
;
quint16
_encdata_seq
;
unsigned
_listOffset
;
// offset for the current List operation
QString
_listPath
;
// path for the current List operation
// We give MockMavlinkFileServer friend access so that it can use the data structures and opcodes
// to build a mock mavlink file server for testing.
friend
class
MockMavlinkFileServer
;
};
};
#endif // QGCUASFILEMANAGER_H
#endif // QGCUASFILEMANAGER_H
src/uas/UAS.cc
View file @
8a021e74
...
@@ -149,6 +149,8 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(),
...
@@ -149,6 +149,8 @@ UAS::UAS(MAVLinkProtocol* protocol, QThread* thread, int id) : UASInterface(),
pitch
(
0.0
),
pitch
(
0.0
),
yaw
(
0.0
),
yaw
(
0.0
),
imagePackets
(
0
),
// We must initialize to 0, otherwise extended data packets maybe incorrectly thought to be images
blockHomePositionChanges
(
false
),
blockHomePositionChanges
(
false
),
receivedMode
(
false
),
receivedMode
(
false
),
...
@@ -1371,6 +1373,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
...
@@ -1371,6 +1373,7 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
// NO VALID TRANSACTION - ABORT
// NO VALID TRANSACTION - ABORT
// Restart statemachine
// Restart statemachine
imagePacketsArrived
=
0
;
imagePacketsArrived
=
0
;
break
;
}
}
for
(
int
i
=
0
;
i
<
imagePayload
;
++
i
)
for
(
int
i
=
0
;
i
<
imagePayload
;
++
i
)
...
@@ -1387,6 +1390,8 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
...
@@ -1387,6 +1390,8 @@ void UAS::receiveMessage(LinkInterface* link, mavlink_message_t message)
if
((
imagePacketsArrived
>=
imagePackets
))
if
((
imagePacketsArrived
>=
imagePackets
))
{
{
// Restart statemachine
// Restart statemachine
imagePackets
=
0
;
imagePacketsArrived
=
0
;
emit
imageReady
(
this
);
emit
imageReady
(
this
);
//qDebug() << "imageReady emitted. all packets arrived";
//qDebug() << "imageReady emitted. all packets arrived";
}
}
...
...
src/ui/MainWindow.cc
View file @
8a021e74
...
@@ -820,6 +820,10 @@ void MainWindow::loadDockWidget(const QString& name)
...
@@ -820,6 +820,10 @@ void MainWindow::loadDockWidget(const QString& name)
{
{
createDockWidget
(
centerStack
->
currentWidget
(),
new
ParameterInterface
(
this
),
tr
(
"Onboard Parameters"
),
"PARAMETER_INTERFACE_DOCKWIDGET"
,
currentView
,
Qt
::
RightDockWidgetArea
);
createDockWidget
(
centerStack
->
currentWidget
(),
new
ParameterInterface
(
this
),
tr
(
"Onboard Parameters"
),
"PARAMETER_INTERFACE_DOCKWIDGET"
,
currentView
,
Qt
::
RightDockWidgetArea
);
}
}
else
if
(
name
==
"FILE_VIEW_DOCKWIDGET"
)
{
createDockWidget
(
centerStack
->
currentWidget
(),
new
QGCUASFileViewMulti
(
this
),
tr
(
"Onboard Files"
),
"FILE_VIEW_DOCKWIDGET"
,
VIEW_ENGINEER
,
Qt
::
RightDockWidgetArea
);
}
else
if
(
name
==
"UAS_STATUS_DETAILS_DOCKWIDGET"
)
else
if
(
name
==
"UAS_STATUS_DETAILS_DOCKWIDGET"
)
{
{
createDockWidget
(
centerStack
->
currentWidget
(),
new
UASInfoWidget
(
this
),
tr
(
"Status Details"
),
"UAS_STATUS_DETAILS_DOCKWIDGET"
,
currentView
,
Qt
::
RightDockWidgetArea
);
createDockWidget
(
centerStack
->
currentWidget
(),
new
UASInfoWidget
(
this
),
tr
(
"Status Details"
),
"UAS_STATUS_DETAILS_DOCKWIDGET"
,
currentView
,
Qt
::
RightDockWidgetArea
);
...
...
src/ui/QGCUASFileView.cc
View file @
8a021e74
...
@@ -17,6 +17,7 @@ QGCUASFileView::QGCUASFileView(QWidget *parent, QGCUASFileManager *manager) :
...
@@ -17,6 +17,7 @@ QGCUASFileView::QGCUASFileView(QWidget *parent, QGCUASFileManager *manager) :
connect
(
ui
->
downloadButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
downloadFiles
()));
connect
(
ui
->
downloadButton
,
SIGNAL
(
clicked
()),
this
,
SLOT
(
downloadFiles
()));
connect
(
_manager
,
SIGNAL
(
statusMessage
(
QString
)),
ui
->
messageArea
,
SLOT
(
appendPlainText
(
QString
)));
connect
(
_manager
,
SIGNAL
(
statusMessage
(
QString
)),
ui
->
messageArea
,
SLOT
(
appendPlainText
(
QString
)));
connect
(
_manager
,
SIGNAL
(
errorMessage
(
QString
)),
ui
->
messageArea
,
SLOT
(
appendPlainText
(
QString
)));
connect
(
_manager
,
SIGNAL
(
resetStatusMessages
()),
ui
->
messageArea
,
SLOT
(
clear
()));
connect
(
_manager
,
SIGNAL
(
resetStatusMessages
()),
ui
->
messageArea
,
SLOT
(
clear
()));
}
}
...
...
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