diff --git a/qgcresources.qrc b/qgcresources.qrc index d8aea1c6ebbb2741648f725ec68bd30393c2313f..6565a65981866bb24d46e9586ed50fe56294fd1a 100644 --- a/qgcresources.qrc +++ b/qgcresources.qrc @@ -45,6 +45,7 @@ src/AutoPilotPlugins/Common/Images/YPlus.svg src/ui/toolbar/Images/Yield.svg + src/AutoPilotPlugins/Common/Images/wifi.svg src/QmlControls/arrow-down.png src/VehicleSetup/FirmwareUpgradeIcon.png src/AutoPilotPlugins/PX4/Images/FlightModesComponentIcon.png diff --git a/qgroundcontrol.pro b/qgroundcontrol.pro index e2bb7b14d052f7cc91dc92fddc9094f38736714b..728d8b500aaaa654e60e91d33a59d00ca51d314a 100644 --- a/qgroundcontrol.pro +++ b/qgroundcontrol.pro @@ -572,6 +572,7 @@ HEADERS+= \ src/AutoPilotPlugins/APM/APMSensorsComponentController.h \ src/AutoPilotPlugins/APM/APMTuningComponent.h \ src/AutoPilotPlugins/Common/RadioComponentController.h \ + src/AutoPilotPlugins/Common/ESP8266ComponentController.h \ src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.h \ src/AutoPilotPlugins/PX4/AirframeComponent.h \ src/AutoPilotPlugins/PX4/AirframeComponentAirframes.h \ @@ -583,6 +584,7 @@ HEADERS+= \ src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h \ src/AutoPilotPlugins/PX4/PX4Component.h \ src/AutoPilotPlugins/PX4/PX4RadioComponent.h \ + src/AutoPilotPlugins/PX4/PX4ESP8266Component.h \ src/AutoPilotPlugins/PX4/SafetyComponent.h \ src/AutoPilotPlugins/PX4/SensorsComponent.h \ src/AutoPilotPlugins/PX4/SensorsComponentController.h \ @@ -628,6 +630,7 @@ SOURCES += \ src/AutoPilotPlugins/APM/APMSensorsComponentController.cc \ src/AutoPilotPlugins/APM/APMTuningComponent.cc \ src/AutoPilotPlugins/Common/RadioComponentController.cc \ + src/AutoPilotPlugins/Common/ESP8266ComponentController.cc \ src/AutoPilotPlugins/APM/APMAirframeComponentAirframes.cc \ src/AutoPilotPlugins/Generic/GenericAutoPilotPlugin.cc \ src/AutoPilotPlugins/PX4/AirframeComponent.cc \ @@ -640,6 +643,7 @@ SOURCES += \ src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc \ src/AutoPilotPlugins/PX4/PX4Component.cc \ src/AutoPilotPlugins/PX4/PX4RadioComponent.cc \ + src/AutoPilotPlugins/PX4/PX4ESP8266Component.cc \ src/AutoPilotPlugins/PX4/SafetyComponent.cc \ src/AutoPilotPlugins/PX4/SensorsComponent.cc \ src/AutoPilotPlugins/PX4/SensorsComponentController.cc \ diff --git a/qgroundcontrol.qrc b/qgroundcontrol.qrc index 864404ad0659b2c3b82d22754513352a04e7d859..5e5b9340ec04ec2e8256c427aec7488fc932cf96 100644 --- a/qgroundcontrol.qrc +++ b/qgroundcontrol.qrc @@ -106,6 +106,8 @@ src/QmlControls/ScreenTools.qml src/QmlControls/QmlTest.qml src/AutoPilotPlugins/Common/RadioComponent.qml + src/AutoPilotPlugins/Common/ESP8266Component.qml + src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml src/AutoPilotPlugins/PX4/PX4RadioComponentSummary.qml src/AutoPilotPlugins/PX4/PX4TuningComponentCopter.qml src/AutoPilotPlugins/PX4/PX4TuningComponentPlane.qml diff --git a/src/AutoPilotPlugins/AutoPilotPlugin.cc b/src/AutoPilotPlugins/AutoPilotPlugin.cc index dd92394c3cb0ee9ff59d06d6bec8ef0066120c9a..13c7c5b95bed44c2f62c73b5f8ff947650bbf956 100644 --- a/src/AutoPilotPlugins/AutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/AutoPilotPlugin.cc @@ -105,9 +105,9 @@ void AutoPilotPlugin::resetAllParametersToDefaults(void) _vehicle->sendMessage(msg); } -void AutoPilotPlugin::refreshAllParameters(void) +void AutoPilotPlugin::refreshAllParameters(unsigned char componentID) { - _vehicle->getParameterLoader()->refreshAllParameters(); + _vehicle->getParameterLoader()->refreshAllParameters((uint8_t)componentID); } void AutoPilotPlugin::refreshParameter(int componentId, const QString& name) diff --git a/src/AutoPilotPlugins/AutoPilotPlugin.h b/src/AutoPilotPlugins/AutoPilotPlugin.h index f4d754e15772fc33595df51848ba5ea60a23f048..02f244b163ec23cfd2137c82b8607c81fcfd3b9c 100644 --- a/src/AutoPilotPlugins/AutoPilotPlugin.h +++ b/src/AutoPilotPlugins/AutoPilotPlugin.h @@ -71,7 +71,7 @@ Q_INVOKABLE void resetAllParametersToDefaults(void); /// Re-request the full set of parameters from the autopilot - Q_INVOKABLE void refreshAllParameters(void); + Q_INVOKABLE void refreshAllParameters(unsigned char componentID = MAV_COMP_ID_ALL); /// Request a refresh on the specific parameter Q_INVOKABLE void refreshParameter(int componentId, const QString& name); diff --git a/src/AutoPilotPlugins/Common/ESP8266Component.qml b/src/AutoPilotPlugins/Common/ESP8266Component.qml new file mode 100644 index 0000000000000000000000000000000000000000..93d402ca9baca81436657bd778d3c3f259e4df57 --- /dev/null +++ b/src/AutoPilotPlugins/Common/ESP8266Component.qml @@ -0,0 +1,211 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2015 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +import QtQuick 2.5 +import QtQuick.Controls 1.2 +import QtQuick.Dialogs 1.2 + +import QGroundControl 1.0 +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.ScreenTools 1.0 +import QGroundControl.Controllers 1.0 + +QGCView { + id: qgcView + viewPanel: panel + + QGCPalette { id: palette; colorGroupEnabled: panel.enabled } + + property int _firstColumn: ScreenTools.defaultFontPixelWidth * 20 + property int _secondColumn: ScreenTools.defaultFontPixelWidth * 12 + readonly property string dialogTitle: "controller WiFi Bridge" + + ESP8266ComponentController { + id: controller + factPanel: panel + } + + property Fact wifiChannel: controller.getParameterFact(controller.componentID, "WIFI_CHANNEL") + property Fact hostPort: controller.getParameterFact(controller.componentID, "WIFI_UDP_HPORT") + property Fact clientPort: controller.getParameterFact(controller.componentID, "WIFI_UDP_CPORT") + + QGCViewPanel { + id: panel + anchors.fill: parent + + Flickable { + anchors.fill: parent + clip: true + contentHeight: innerColumn.height + contentWidth: panel.width + boundsBehavior: Flickable.StopAtBounds + flickableDirection: Flickable.VerticalFlick + + Column { + id: innerColumn + width: panel.width + spacing: ScreenTools.defaultFontPixelHeight * 0.5 + + QGCLabel { + text: "WiFi Bridge Settings" + font.weight: Font.DemiBold + } + + Rectangle { + width: parent.width + height: wifiCol.height + (ScreenTools.defaultFontPixelHeight * 2) + color: palette.windowShade + Column { + id: wifiCol + anchors.margins: ScreenTools.defaultFontPixelHeight / 2 + anchors.verticalCenter: parent.verticalCenter + anchors.left: parent.left + spacing: ScreenTools.defaultFontPixelHeight / 2 + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + text: "WiFi Channel" + width: _firstColumn + anchors.baseline: channelField.baseline + } + QGCComboBox { + id: channelField + width: _secondColumn + model: controller.wifiChannels + currentIndex: wifiChannel ? wifiChannel.value - 1 : 0 + onActivated: { + wifiChannel.value = index + 1 + } + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + text: "WiFi SSID" + width: _firstColumn + anchors.baseline: ssidField.baseline + } + QGCTextField { + id: ssidField + width: _secondColumn + text: controller.wifiSSID + maximumLength: 16 + onEditingFinished: { + controller.wifiSSID = text + } + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + text: "WiFi Password" + width: _firstColumn + anchors.baseline: passwordField.baseline + } + QGCTextField { + id: passwordField + width: _secondColumn + text: controller.wifiPassword + maximumLength: 16 + onEditingFinished: { + controller.wifiPassword = text + } + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + text: "UART Baud Rate" + width: _firstColumn + anchors.baseline: baudField.baseline + } + QGCComboBox { + id: baudField + width: _secondColumn + model: controller.baudRates + currentIndex: controller.baudIndex + onActivated: { + controller.baudIndex = index + } + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth + QGCLabel { + text: "QGC UDP Port" + width: _firstColumn + anchors.baseline: qgcportField.baseline + } + QGCTextField { + id: qgcportField + width: _secondColumn + text: hostPort ? hostPort.valueString : "" + validator: IntValidator {bottom: 1024; top: 65535;} + inputMethodHints: Qt.ImhDigitsOnly + onEditingFinished: { + hostPort.value = text + } + } + } + } + } + Row { + spacing: ScreenTools.defaultFontPixelWidth * 1.5 + QGCButton { + text: "Restore Defaults" + width: ScreenTools.defaultFontPixelWidth * 16 + onClicked: { + controller.restoreDefaults() + } + } + QGCButton { + text: "Restart WiFi Bridge" + enabled: !controller.busy + width: ScreenTools.defaultFontPixelWidth * 16 + onClicked: { + rebootDialog.visible = true + } + MessageDialog { + id: rebootDialog + visible: false + icon: StandardIcon.Warning + standardButtons: StandardButton.Yes | StandardButton.No + title: "Reboot WiFi Bridge" + text: "This will restart the WiFi Bridge so the settings you've changed can take effect. Note that you may have to change your computer WiFi settings and QGroundControl link settings to match these changes. Are you sure you want to restart it?" + onYes: { + controller.reboot() + rebootDialog.visible = false + } + onNo: { + rebootDialog.visible = false + } + } + } + } + } + } + } +} diff --git a/src/AutoPilotPlugins/Common/ESP8266ComponentController.cc b/src/AutoPilotPlugins/Common/ESP8266ComponentController.cc new file mode 100644 index 0000000000000000000000000000000000000000..548f9a927f6fdd186d567fdf0256d488bee6023c --- /dev/null +++ b/src/AutoPilotPlugins/Common/ESP8266ComponentController.cc @@ -0,0 +1,318 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009, 2016 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +/// @file +/// @brief ESP8266 WiFi Config Qml Controller +/// @author Gus Grubba + +#include "ESP8266ComponentController.h" +#include "AutoPilotPluginManager.h" +#include "QGCApplication.h" +#include "UAS.h" + +QGC_LOGGING_CATEGORY(ESP8266ComponentControllerLog, "ESP8266ComponentControllerLog") + +#define MAX_RETRIES 5 + +//----------------------------------------------------------------------------- +ESP8266ComponentController::ESP8266ComponentController() + : _waitType(WAIT_FOR_NOTHING) + , _retries(0) +{ + for(int i = 1; i < 12; i++) { + _channels.append(QString::number(i)); + } + _baudRates.append("57600"); + _baudRates.append("115200"); + _baudRates.append("230400"); + _baudRates.append("460800"); + _baudRates.append("921600"); + connect(&_timer, &QTimer::timeout, this, &ESP8266ComponentController::_processTimeout); + UASInterface* uas = dynamic_cast(_vehicle->uas()); + connect(uas, &UASInterface::commandAck, this, &ESP8266ComponentController::_commandAck); + Fact* ssid = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID4"); + connect(ssid, &Fact::valueChanged, this, &ESP8266ComponentController::_ssidChanged); + Fact* paswd = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD4"); + connect(paswd, &Fact::valueChanged, this, &ESP8266ComponentController::_passwordChanged); + Fact* baud = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "UART_BAUDRATE"); + connect(baud, &Fact::valueChanged, this, &ESP8266ComponentController::_baudChanged); +} + +//----------------------------------------------------------------------------- +ESP8266ComponentController::~ESP8266ComponentController() +{ + +} + +//----------------------------------------------------------------------------- +QString +ESP8266ComponentController::wifiSSID() +{ + uint32_t s1 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID1")->rawValue().toUInt(); + uint32_t s2 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID2")->rawValue().toUInt(); + uint32_t s3 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID3")->rawValue().toUInt(); + uint32_t s4 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID4")->rawValue().toUInt(); + char tmp[20]; + memcpy(&tmp[0], &s1, sizeof(uint32_t)); + memcpy(&tmp[4], &s2, sizeof(uint32_t)); + memcpy(&tmp[8], &s3, sizeof(uint32_t)); + memcpy(&tmp[12], &s4, sizeof(uint32_t)); + return QString(tmp); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::setWifiSSID(QString ssid) +{ + char tmp[20]; + memset(tmp, 0, sizeof(tmp)); + std::string sid = ssid.toStdString(); + strncpy(tmp, sid.c_str(), sizeof(tmp)); + Fact* f1 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID1"); + Fact* f2 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID2"); + Fact* f3 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID3"); + Fact* f4 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_SSID4"); + uint32_t u; + memcpy(&u, &tmp[0], sizeof(uint32_t)); + f1->setRawValue(QVariant(u)); + memcpy(&u, &tmp[4], sizeof(uint32_t)); + f2->setRawValue(QVariant(u)); + memcpy(&u, &tmp[8], sizeof(uint32_t)); + f3->setRawValue(QVariant(u)); + memcpy(&u, &tmp[12], sizeof(uint32_t)); + f4->setRawValue(QVariant(u)); +} + +//----------------------------------------------------------------------------- +QString +ESP8266ComponentController::wifiPassword() +{ + uint32_t s1 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD1")->rawValue().toUInt(); + uint32_t s2 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD2")->rawValue().toUInt(); + uint32_t s3 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD3")->rawValue().toUInt(); + uint32_t s4 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD4")->rawValue().toUInt(); + char tmp[20]; + memcpy(&tmp[0], &s1, sizeof(uint32_t)); + memcpy(&tmp[4], &s2, sizeof(uint32_t)); + memcpy(&tmp[8], &s3, sizeof(uint32_t)); + memcpy(&tmp[12], &s4, sizeof(uint32_t)); + return QString(tmp); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::setWifiPassword(QString password) +{ + char tmp[20]; + memset(tmp, 0, sizeof(tmp)); + std::string pwd = password.toStdString(); + strncpy(tmp, pwd.c_str(), sizeof(tmp)); + Fact* f1 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD1"); + Fact* f2 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD2"); + Fact* f3 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD3"); + Fact* f4 = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "WIFI_PASSWORD4"); + uint32_t u; + memcpy(&u, &tmp[0], sizeof(uint32_t)); + f1->setRawValue(QVariant(u)); + memcpy(&u, &tmp[4], sizeof(uint32_t)); + f2->setRawValue(QVariant(u)); + memcpy(&u, &tmp[8], sizeof(uint32_t)); + f3->setRawValue(QVariant(u)); + memcpy(&u, &tmp[12], sizeof(uint32_t)); + f4->setRawValue(QVariant(u)); +} + +//----------------------------------------------------------------------------- +int +ESP8266ComponentController::baudIndex() +{ + int b = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "UART_BAUDRATE")->rawValue().toInt(); + switch (b) { + case 57600: + return 0; + case 115200: + return 1; + case 230400: + return 2; + case 460800: + return 3; + case 921600: + default: + return 4; + } +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::setBaudIndex(int idx) +{ + if(idx >= 0 && idx != baudIndex()) { + int baud = 921600; + switch(idx) { + case 0: + baud = 57600; + break; + case 1: + baud = 115200; + break; + case 2: + baud = 230400; + break; + case 3: + baud = 460800; + break; + default: + baud = 921600; + } + Fact* b = getParameterFact(MAV_COMP_ID_UDP_BRIDGE, "UART_BAUDRATE"); + b->setRawValue(baud); + } +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::reboot() +{ + _waitType = WAIT_FOR_REBOOT; + emit busyChanged(); + _retries = MAX_RETRIES; + _reboot(); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::restoreDefaults() +{ + _waitType = WAIT_FOR_RESTORE; + emit busyChanged(); + _retries = MAX_RETRIES; + _restoreDefaults(); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::_reboot() +{ + mavlink_message_t msg; + mavlink_msg_command_long_pack( + qgcApp()->toolbox()->mavlinkProtocol()->getSystemId(), + qgcApp()->toolbox()->mavlinkProtocol()->getComponentId(), + &msg, + _vehicle->id(), + MAV_COMP_ID_UDP_BRIDGE, + MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN, + 1.0f, // Confirmation + 0.0f, // Param1 + 1.0f, // Param2 + 0.0f,0.0f,0.0f,0.0f,0.0f); + qCDebug(ESP8266ComponentControllerLog) << "_reboot()"; + _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); + _timer.start(1000); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::_restoreDefaults() +{ + mavlink_message_t msg; + mavlink_msg_command_long_pack( + qgcApp()->toolbox()->mavlinkProtocol()->getSystemId(), + qgcApp()->toolbox()->mavlinkProtocol()->getComponentId(), + &msg, + _vehicle->id(), + MAV_COMP_ID_UDP_BRIDGE, + MAV_CMD_PREFLIGHT_STORAGE, + 1.0f, // Confirmation + 2.0f, // Param1 + 0.0f,0.0f,0.0f,0.0f,0.0f,0.0f); + qCDebug(ESP8266ComponentControllerLog) << "_restoreDefaults()"; + _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); + _timer.start(1000); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::_processTimeout() +{ + if(!--_retries) { + qCDebug(ESP8266ComponentControllerLog) << "_processTimeout Giving Up"; + _timer.stop(); + _waitType = WAIT_FOR_NOTHING; + emit busyChanged(); + } else { + switch(_waitType) { + case WAIT_FOR_REBOOT: + qCDebug(ESP8266ComponentControllerLog) << "_processTimeout for Reboot"; + _reboot(); + break; + case WAIT_FOR_RESTORE: + qCDebug(ESP8266ComponentControllerLog) << "_processTimeout for Restore Defaults"; + _restoreDefaults(); + break; + } + } +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::_commandAck(UASInterface*, uint8_t compID, uint16_t command, uint8_t result) +{ + if(compID == MAV_COMP_ID_UDP_BRIDGE) { + if(result != MAV_RESULT_ACCEPTED) { + qWarning() << "ESP8266ComponentController command" << command << "rejected."; + return; + } + if((_waitType == WAIT_FOR_REBOOT && command == MAV_CMD_PREFLIGHT_REBOOT_SHUTDOWN) || + (_waitType == WAIT_FOR_RESTORE && command == MAV_CMD_PREFLIGHT_STORAGE)) + { + _timer.stop(); + _waitType = WAIT_FOR_NOTHING; + emit busyChanged(); + qCDebug(ESP8266ComponentControllerLog) << "_commandAck for" << command; + if(command == MAV_CMD_PREFLIGHT_STORAGE) { + _autopilot->refreshAllParameters(MAV_COMP_ID_UDP_BRIDGE); + } + } + } +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::_ssidChanged(QVariant) +{ + emit wifiSSIDChanged(); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::_passwordChanged(QVariant) +{ + emit wifiPasswordChanged(); +} + +//----------------------------------------------------------------------------- +void +ESP8266ComponentController::_baudChanged(QVariant) +{ + emit baudIndexChanged(); +} diff --git a/src/AutoPilotPlugins/Common/ESP8266ComponentController.h b/src/AutoPilotPlugins/Common/ESP8266ComponentController.h new file mode 100644 index 0000000000000000000000000000000000000000..ab5515c1fe717346fb0ac77206f39e704f11d54f --- /dev/null +++ b/src/AutoPilotPlugins/Common/ESP8266ComponentController.h @@ -0,0 +1,108 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009, 2016 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + + +/// @file +/// @brief ESP8266 WiFi Config Qml Controller +/// @author Gus Grubba + +#ifndef ESP8266ComponentController_H +#define ESP8266ComponentController_H + +#include + +#include "FactPanelController.h" +#include "UASInterface.h" +#include "QGCLoggingCategory.h" +#include "AutoPilotPlugin.h" + +Q_DECLARE_LOGGING_CATEGORY(ESP8266ComponentControllerLog) + +namespace Ui { + class ESP8266ComponentController; +} + +class ESP8266ComponentController : public FactPanelController +{ + Q_OBJECT + +public: + ESP8266ComponentController (); + ~ESP8266ComponentController (); + + Q_PROPERTY(int componentID READ componentID CONSTANT) + Q_PROPERTY(QString wifiSSID READ wifiSSID WRITE setWifiSSID NOTIFY wifiSSIDChanged) + Q_PROPERTY(QString wifiPassword READ wifiPassword WRITE setWifiPassword NOTIFY wifiPasswordChanged) + Q_PROPERTY(QStringList wifiChannels READ wifiChannels CONSTANT) + Q_PROPERTY(QStringList baudRates READ baudRates CONSTANT) + Q_PROPERTY(int baudIndex READ baudIndex WRITE setBaudIndex NOTIFY baudIndexChanged) + Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) + + Q_INVOKABLE void restoreDefaults(); + Q_INVOKABLE void reboot(); + + int componentID () { return MAV_COMP_ID_UDP_BRIDGE; } + QString wifiSSID (); + QString wifiPassword (); + QStringList wifiChannels () { return _channels; } + QStringList baudRates () { return _baudRates; } + int baudIndex (); + bool busy () { return _waitType != WAIT_FOR_NOTHING; } + + void setWifiSSID (QString id); + void setWifiPassword (QString pwd); + void setBaudIndex (int idx); + +signals: + void wifiSSIDChanged (); + void wifiPasswordChanged (); + void baudIndexChanged (); + void busyChanged (); + +private slots: + void _processTimeout (); + void _commandAck (UASInterface* uas, uint8_t compID, uint16_t command, uint8_t result); + void _ssidChanged (QVariant value); + void _passwordChanged (QVariant value); + void _baudChanged (QVariant value); + +private: + void _reboot (); + void _restoreDefaults (); + +private: + QTimer _timer; + QStringList _channels; + QStringList _baudRates; + + enum { + WAIT_FOR_NOTHING, + WAIT_FOR_REBOOT, + WAIT_FOR_RESTORE + }; + + int _waitType; + int _retries; +}; + +#endif // ESP8266ComponentController_H diff --git a/src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml b/src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml new file mode 100644 index 0000000000000000000000000000000000000000..50b3792525d3a853f48613442ed04d5247ce0112 --- /dev/null +++ b/src/AutoPilotPlugins/Common/ESP8266ComponentSummary.qml @@ -0,0 +1,56 @@ +import QtQuick 2.2 +import QtQuick.Controls 1.2 + +import QGroundControl.FactSystem 1.0 +import QGroundControl.FactControls 1.0 +import QGroundControl.Controls 1.0 +import QGroundControl.Palette 1.0 +import QGroundControl.Controllers 1.0 + +FactPanel { + id: panel + anchors.fill: parent + color: qgcPal.windowShadeDark + + QGCPalette { id: qgcPal; colorGroupEnabled: enabled } + FactPanelController { id: controller; factPanel: panel } + + ESP8266ComponentController { + id: esp8266 + } + + property Fact debugEnabled: controller.getParameterFact(esp8266.componentID, "DEBUG_ENABLED") + property Fact wifiChannel: controller.getParameterFact(esp8266.componentID, "WIFI_CHANNEL") + property Fact wifiHostPort: controller.getParameterFact(esp8266.componentID, "WIFI_UDP_HPORT") + property Fact wifiClientPort: controller.getParameterFact(esp8266.componentID, "WIFI_UDP_CPORT") + property Fact uartBaud: controller.getParameterFact(esp8266.componentID, "UART_BAUDRATE") + + Column { + anchors.fill: parent + anchors.margins: 8 + VehicleSummaryRow { + labelText: "WiFi Channel:" + valueText: wifiChannel.valueString + } + VehicleSummaryRow { + labelText: "WiFi SSID:" + valueText: esp8266.wifiSSID + } + VehicleSummaryRow { + labelText: "WiFi Password:" + valueText: esp8266.wifiPassword + } + VehicleSummaryRow { + labelText: "QGC UDP Port:" + valueText: wifiHostPort.valueString + } + VehicleSummaryRow { + labelText: "UAV UDP Port:" + valueText: wifiClientPort.valueString + } + VehicleSummaryRow { + labelText: "UART Baud Rate:" + valueText: uartBaud.valueString + } + } +} diff --git a/src/AutoPilotPlugins/Common/Images/wifi.svg b/src/AutoPilotPlugins/Common/Images/wifi.svg new file mode 100644 index 0000000000000000000000000000000000000000..0ca79f571a3fa3af318aeb73fa5372ff2a42eb0e --- /dev/null +++ b/src/AutoPilotPlugins/Common/Images/wifi.svg @@ -0,0 +1,19 @@ + + + + + + diff --git a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc index 10027db2c85ada20470ea3f2397224af02ac10c7..009155223e9e333441d19b2668904e42943c1584 100644 --- a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc +++ b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.cc @@ -69,6 +69,7 @@ PX4AutoPilotPlugin::PX4AutoPilotPlugin(Vehicle* vehicle, QObject* parent) : AutoPilotPlugin(vehicle, parent), _airframeComponent(NULL), _radioComponent(NULL), + _esp8266Component(NULL), _flightModesComponent(NULL), _sensorsComponent(NULL), _safetyComponent(NULL), @@ -101,7 +102,27 @@ const QVariantList& PX4AutoPilotPlugin::vehicleComponents(void) _radioComponent = new PX4RadioComponent(_vehicle, this); _radioComponent->setupTriggerSignals(); _components.append(QVariant::fromValue((VehicleComponent*)_radioComponent)); - + + //-- Is there an ESP8266 Connected? +#ifdef QT_DEBUG +#ifndef __mobile__ + //-- Unit test barfs if I ask for a parameter that does not exists. The whole poing of the + // test below is to behave differently if ESP8266 is present or not. + if (!qgcApp()->runningUnitTests()) { +#endif +#endif + Fact* espVersion = getFact(FactSystem::ParameterProvider, MAV_COMP_ID_UDP_BRIDGE, "SW_VER"); + if(espVersion && espVersion->componentId() == MAV_COMP_ID_UDP_BRIDGE) { + _esp8266Component = new PX4ESP8266Component(_vehicle, this); + _esp8266Component->setupTriggerSignals(); + _components.append(QVariant::fromValue((VehicleComponent*)_esp8266Component)); + } +#ifdef QT_DEBUG +#ifndef __mobile__ + } +#endif +#endif + _flightModesComponent = new FlightModesComponent(_vehicle, this); _flightModesComponent->setupTriggerSignals(); _components.append(QVariant::fromValue((VehicleComponent*)_flightModesComponent)); diff --git a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h index db0b2d1129e06c989440c740ff1378a229b0ce0c..836c3c1cc998a0bc78eb2e9825cf03bb9794ebf5 100644 --- a/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h +++ b/src/AutoPilotPlugins/PX4/PX4AutoPilotPlugin.h @@ -28,6 +28,7 @@ #include "PX4AirframeLoader.h" #include "AirframeComponent.h" #include "PX4RadioComponent.h" +#include "PX4ESP8266Component.h" #include "FlightModesComponent.h" #include "SensorsComponent.h" #include "SafetyComponent.h" @@ -55,6 +56,7 @@ public: // These methods should only be used by objects within the plugin AirframeComponent* airframeComponent(void) { return _airframeComponent; } PX4RadioComponent* radioComponent(void) { return _radioComponent; } + PX4ESP8266Component* esp8266Component(void) { return _esp8266Component; } FlightModesComponent* flightModesComponent(void) { return _flightModesComponent; } SensorsComponent* sensorsComponent(void) { return _sensorsComponent; } SafetyComponent* safetyComponent(void) { return _safetyComponent; } @@ -70,6 +72,7 @@ private: QVariantList _components; AirframeComponent* _airframeComponent; PX4RadioComponent* _radioComponent; + PX4ESP8266Component* _esp8266Component; FlightModesComponent* _flightModesComponent; SensorsComponent* _sensorsComponent; SafetyComponent* _safetyComponent; diff --git a/src/AutoPilotPlugins/PX4/PX4ESP8266Component.cc b/src/AutoPilotPlugins/PX4/PX4ESP8266Component.cc new file mode 100644 index 0000000000000000000000000000000000000000..39e79b2b8bffb638798786353cda2d8d812682c9 --- /dev/null +++ b/src/AutoPilotPlugins/PX4/PX4ESP8266Component.cc @@ -0,0 +1,77 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2016 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +#include "PX4ESP8266Component.h" +#include "PX4AutoPilotPlugin.h" + +PX4ESP8266Component::PX4ESP8266Component(Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent) + : PX4Component(vehicle, autopilot, parent) + , _name(tr("WiFi Bridge")) +{ + +} + +QString PX4ESP8266Component::name(void) const +{ + return _name; +} + +QString PX4ESP8266Component::description(void) const +{ + return tr("The ESP8266 WiFi Bridge Component is used to setup the WiFi link."); +} + +QString PX4ESP8266Component::iconResource(void) const +{ + return "/qmlimages/wifi.svg"; +} + +bool PX4ESP8266Component::requiresSetup(void) const +{ + return false; +} + +bool PX4ESP8266Component::setupComplete(void) const +{ + return true; +} + +QStringList PX4ESP8266Component::setupCompleteChangedTriggerList(void) const +{ + return QStringList(); +} + +QUrl PX4ESP8266Component::setupSource(void) const +{ + return QUrl::fromUserInput("qrc:/qml/ESP8266Component.qml"); +} + +QUrl PX4ESP8266Component::summaryQmlSource(void) const +{ + return QUrl::fromUserInput("qrc:/qml/ESP8266ComponentSummary.qml"); +} + +QString PX4ESP8266Component::prerequisiteSetup(void) const +{ + return QString(); +} diff --git a/src/AutoPilotPlugins/PX4/PX4ESP8266Component.h b/src/AutoPilotPlugins/PX4/PX4ESP8266Component.h new file mode 100644 index 0000000000000000000000000000000000000000..220b0ab4fc2e832386cf0a2d92942e973c8f080b --- /dev/null +++ b/src/AutoPilotPlugins/PX4/PX4ESP8266Component.h @@ -0,0 +1,53 @@ +/*===================================================================== + + QGroundControl Open Source Ground Control Station + + (c) 2009 - 2016 QGROUNDCONTROL PROJECT + + 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 . + + ======================================================================*/ + +#ifndef PX4ESP8266Component_H +#define PX4ESP8266Component_H + +#include "PX4Component.h" + +class PX4ESP8266Component : public PX4Component +{ + Q_OBJECT +public: + PX4ESP8266Component (Vehicle* vehicle, AutoPilotPlugin* autopilot, QObject* parent = NULL); + + // Virtuals from PX4Component + QStringList setupCompleteChangedTriggerList() const; + + // Virtuals from VehicleComponent + QString name () const; + QString description () const; + QString iconResource () const; + bool requiresSetup () const; + bool setupComplete () const; + QUrl setupSource () const; + QUrl summaryQmlSource () const; + QString prerequisiteSetup () const; + +private: + const QString _name; + QVariantList _summaryItems; +}; + +#endif diff --git a/src/FactSystem/ParameterLoader.cc b/src/FactSystem/ParameterLoader.cc index 4c1885d5d20aced8ca1c29f72ad7173feb376aa8..7d4ea5e43395219bd8e76ee64d4dd01e6b92d2da 100644 --- a/src/FactSystem/ParameterLoader.cc +++ b/src/FactSystem/ParameterLoader.cc @@ -72,7 +72,7 @@ ParameterLoader::ParameterLoader(AutoPilotPlugin* autopilot, Vehicle* vehicle, Q _cacheTimeoutTimer.setSingleShot(true); _cacheTimeoutTimer.setInterval(2500); - connect(&_cacheTimeoutTimer, &QTimer::timeout, this, &ParameterLoader::refreshAllParameters); + connect(&_cacheTimeoutTimer, &QTimer::timeout, this, &ParameterLoader::_timeoutRefreshAll); connect(_vehicle->uas(), &UASInterface::parameterUpdate, this, &ParameterLoader::_parameterUpdate); @@ -301,7 +301,7 @@ void ParameterLoader::_valueUpdated(const QVariant& value) } } -void ParameterLoader::refreshAllParameters(void) +void ParameterLoader::refreshAllParameters(uint8_t componentID) { _dataMutex.lock(); @@ -310,11 +310,13 @@ void ParameterLoader::refreshAllParameters(void) } // Reset index wait lists - foreach (int componentId, _paramCountMap.keys()) { + foreach (int cid, _paramCountMap.keys()) { // Add/Update all indices to the wait list, parameter index is 0-based - for (int waitingIndex=0; waitingIndex<_paramCountMap[componentId]; waitingIndex++) { + if(componentID != MAV_COMP_ID_ALL && componentID != cid) + continue; + for (int waitingIndex = 0; waitingIndex < _paramCountMap[cid]; waitingIndex++) { // This will add a new waiting index if needed and set the retry count for that index to 0 - _waitingReadParamIndexMap[componentId][waitingIndex] = 0; + _waitingReadParamIndexMap[cid][waitingIndex] = 0; } } @@ -324,10 +326,11 @@ void ParameterLoader::refreshAllParameters(void) Q_ASSERT(mavlink); mavlink_message_t msg; - mavlink_msg_param_request_list_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, _vehicle->id(), MAV_COMP_ID_ALL); + mavlink_msg_param_request_list_pack(mavlink->getSystemId(), mavlink->getComponentId(), &msg, _vehicle->id(), componentID); _vehicle->sendMessageOnLink(_vehicle->priorityLink(), msg); - qCDebug(ParameterLoaderLog) << "Request to refresh all parameters"; + QString what = (componentID == MAV_COMP_ID_ALL) ? "MAV_COMP_ID_ALL" : QString::number(componentID); + qCDebug(ParameterLoaderLog) << "Request to refresh all parameters for component ID:" << what; } void ParameterLoader::_determineDefaultComponentId(void) @@ -867,7 +870,7 @@ void ParameterLoader::_checkInitialLoadComplete(void) if (initialLoadFailures) { qgcApp()->showMessage("QGroundControl was unable to retrieve the full set of parameters from the vehicle. " - "This will cause QGroundControl to be unable to display it's full user interface. " + "This will cause QGroundControl to be unable to display its full user interface. " "If you are using modified firmware, you may need to resolve any vehicle startup errors to resolve the issue. " "If you are using standard firmware, you may need to upgrade to a newer version to resolve the issue."); qCWarning(ParameterLoaderLog) << "The following parameter indices could not be loaded after the maximum number of retries: " << indexList; @@ -887,3 +890,9 @@ void ParameterLoader::_initialRequestTimeout(void) refreshAllParameters(); _initialRequestTimeoutTimer.start(); } + +void ParameterLoader::_timeoutRefreshAll() +{ + refreshAllParameters(); +} + diff --git a/src/FactSystem/ParameterLoader.h b/src/FactSystem/ParameterLoader.h index 99c1ad923c30bd65e18399e0fa394dbdddc0fd66..3c135fa4cb6272485c2b256b5be46dfe9405de09 100644 --- a/src/FactSystem/ParameterLoader.h +++ b/src/FactSystem/ParameterLoader.h @@ -57,7 +57,7 @@ public: bool parametersAreReady(void) { return _parametersReady; } /// Re-request the full set of parameters from the autopilot - void refreshAllParameters(void); + void refreshAllParameters(uint8_t componentID = MAV_COMP_ID_ALL); /// Request a refresh on the specific parameter void refreshParameter(int componentId, const QString& name); @@ -107,6 +107,9 @@ protected: void _tryCacheLookup(void); void _initialRequestTimeout(void); +private slots: + void _timeoutRefreshAll(); + private: static QVariant _stringToTypedVariant(const QString& string, FactMetaData::ValueType_t type, bool failOk = false); int _actualComponentId(int componentId); diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index a1b490fdea7f3e7e90ef7433224c63d2c903367d..46ae6bed6289482fc387d6df74456163cd807038 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -68,6 +68,7 @@ #include "APMSensorsComponentController.h" #include "PowerComponentController.h" #include "RadioComponentController.h" +#include "ESP8266ComponentController.h" #include "ScreenToolsController.h" #include "AutoPilotPlugin.h" #include "VehicleComponent.h" @@ -384,6 +385,7 @@ void QGCApplication::_initCommon(void) qmlRegisterType ("QGroundControl.Controllers", 1, 0, "SensorsComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "PowerComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "RadioComponentController"); + qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ESP8266ComponentController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "ScreenToolsController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "MainToolBarController"); qmlRegisterType ("QGroundControl.Controllers", 1, 0, "MissionController"); diff --git a/src/comm/UDPLink.cc b/src/comm/UDPLink.cc index 1bbcc79636d4b5053f2b23d62766f515de1b8909..61bdcb87affddafca5d40685514a34c7f1f18ecd 100644 --- a/src/comm/UDPLink.cc +++ b/src/comm/UDPLink.cc @@ -140,7 +140,7 @@ void UDPLink::run() if(!_running) break; //-- Settle down (it gets here if there is nothing to read or write) - this->msleep(50); + this->msleep(5); } } else { exec(); @@ -242,30 +242,21 @@ void UDPLink::_sendBytes(const char* data, qint64 size) **/ void UDPLink::readBytes() { + QByteArray databuffer; while (_socket->hasPendingDatagrams()) { QByteArray datagram; datagram.resize(_socket->pendingDatagramSize()); - QHostAddress sender; quint16 senderPort; _socket->readDatagram(datagram.data(), datagram.size(), &sender, &senderPort); - - // FIXME TODO Check if this method is better than retrieving the data by individual processes - emit bytesReceived(this, datagram); - + databuffer.append(datagram); + //-- Wait a bit before sending it over + if(databuffer.size() > 10 * 1024) { + emit bytesReceived(this, databuffer); + databuffer.clear(); + } _logInputDataRate(datagram.length(), QDateTime::currentMSecsSinceEpoch()); - -// // Echo data for debugging purposes -// std::cerr << __FILE__ << __LINE__ << "Received datagram:" << std::endl; -// int i; -// for (i=0; isetProxy(QNetworkProxy::NoProxy); _connectState = _socket->bind(host, _config->localPort(), QAbstractSocket::ReuseAddressHint | QUdpSocket::ShareAddress); if (_connectState) { + //-- Make sure we have a large enough IO buffers +#ifdef __mobile + _socket->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, 64 * 1024); + _socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 128 * 1024); +#else + _socket->setSocketOption(QAbstractSocket::SendBufferSizeSocketOption, 256 * 1024); + _socket->setSocketOption(QAbstractSocket::ReceiveBufferSizeSocketOption, 512 * 1024); +#endif _registerZeroconf(_config->localPort(), kZeroconfRegistration); //-- Connect signal if this version of Qt is not broken if(!UDP_BROKEN_SIGNAL) { @@ -451,17 +454,18 @@ void UDPConfiguration::addHost(const QString host) void UDPConfiguration::addHost(const QString& host, int port) { + bool changed = false; QMutexLocker locker(&_confMutex); if(_hosts.contains(host)) { if(_hosts[host] != port) { _hosts[host] = port; + changed = true; } } else { QString ipAdd = get_ip_address(host); if(ipAdd.isEmpty()) { qWarning() << "UDP:" << "Could not resolve host:" << host << "port:" << port; } else { - // In simulation and testing setups the vehicle and the GCS can be // running on the same host. This leads to packets arriving through // the local network or the loopback adapter, which makes it look @@ -470,21 +474,17 @@ void UDPConfiguration::addHost(const QString& host, int port) // // We detect this case and force all traffic to a simulated instance // onto the local loopback interface. - bool not_local = true; - // Run through all IPv4 interfaces and check if their canonical // IP address in string representation matches the source IP address foreach (const QHostAddress &address, QNetworkInterface::allAddresses()) { if (address.protocol() == QAbstractSocket::IPv4Protocol) { - if (ipAdd.endsWith(address.toString())) { // This is a local address of the same host not_local = false; } } } - if (not_local) { // This is a normal remote host, add it using its IPv4 address _hosts[ipAdd] = port; @@ -493,9 +493,12 @@ void UDPConfiguration::addHost(const QString& host, int port) // It is localhost, so talk to it through the IPv4 loopback interface _hosts["127.0.0.1"] = port; } + changed = true; } } - _updateHostList(); + if(changed) { + _updateHostList(); + } } void UDPConfiguration::removeHost(const QString host) diff --git a/src/uas/UAS.cc b/src/uas/UAS.cc index 79f8dd8846acaa47874ac084d8f714131aa27d12..1c3d6eb9927dc872953284e92071463a2e3e6653 100644 --- a/src/uas/UAS.cc +++ b/src/uas/UAS.cc @@ -789,6 +789,7 @@ void UAS::receiveMessage(mavlink_message_t message) { mavlink_command_ack_t ack; mavlink_msg_command_ack_decode(&message, &ack); + emit commandAck(this, message.compid, ack.command, ack.result); switch (ack.result) { case MAV_RESULT_ACCEPTED: diff --git a/src/uas/UASInterface.h b/src/uas/UASInterface.h index d351fd72f79959896a4b0b867ed080d45be5c190..dce3e5b02e2e86db3e1adad0579344068567ad35 100644 --- a/src/uas/UASInterface.h +++ b/src/uas/UASInterface.h @@ -327,6 +327,9 @@ signals: void logEntry (UASInterface* uas, uint32_t time_utc, uint32_t size, uint16_t id, uint16_t num_logs, uint16_t last_log_num); void logData (UASInterface* uas, uint32_t ofs, uint16_t id, uint8_t count, const uint8_t* data); + /** @brief Command Ack */ + void commandAck (UASInterface* uas, uint8_t compID, uint16_t command, uint8_t result); + protected: // TIMEOUT CONSTANTS