Commit 0064bb76 authored by Gus Grubba's avatar Gus Grubba

Merge pull request #2733 from dogmaphobic/wifibridgeStatus

Adding (optional) link status data to the WiFi Bridge panel.
parents 7c360bc9 0af5efd4
...@@ -24,6 +24,7 @@ ...@@ -24,6 +24,7 @@
import QtQuick 2.5 import QtQuick 2.5
import QtQuick.Controls 1.2 import QtQuick.Controls 1.2
import QtQuick.Dialogs 1.2 import QtQuick.Dialogs 1.2
import QtQuick.Layouts 1.2
import QGroundControl 1.0 import QGroundControl 1.0
import QGroundControl.FactSystem 1.0 import QGroundControl.FactSystem 1.0
...@@ -42,12 +43,70 @@ QGCView { ...@@ -42,12 +43,70 @@ QGCView {
property int _firstColumn: ScreenTools.defaultFontPixelWidth * 20 property int _firstColumn: ScreenTools.defaultFontPixelWidth * 20
property int _secondColumn: ScreenTools.defaultFontPixelWidth * 12 property int _secondColumn: ScreenTools.defaultFontPixelWidth * 12
readonly property string dialogTitle: "controller WiFi Bridge" readonly property string dialogTitle: "controller WiFi Bridge"
property int stStatus: XMLHttpRequest.UNSENT
property int stErrorCount: 0
property bool stEnabled: false
property bool stResetCounters: false
ESP8266ComponentController { ESP8266ComponentController {
id: controller id: controller
factPanel: panel factPanel: panel
} }
Timer {
id: timer
}
function thisThingHasNoNumberLocaleSupport(n) {
return n.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",").replace(",,", ",")
}
function updateStatus() {
timer.stop()
var req = new XMLHttpRequest;
var url = "http://192.168.4.1/status.json"
if(stResetCounters) {
url = url + "?r=1"
stResetCounters = false
}
req.open("GET", url);
req.onreadystatechange = function() {
stStatus = req.readyState;
if (stStatus === XMLHttpRequest.DONE) {
var objectArray = JSON.parse(req.responseText);
if (objectArray.errors !== undefined) {
console.log("Error fetching WiFi Bridge Status: " + objectArray.errors[0].message)
stErrorCount = stErrorCount + 1
if(stErrorCount < 2 && stEnabled)
timer.start()
} else {
if(stEnabled) {
//-- This should work but it doesn't
// var n = 34523453.345
// n.toLocaleString()
// "34,523,453.345"
vpackets.text = thisThingHasNoNumberLocaleSupport(objectArray["vpackets"])
vsent.text = thisThingHasNoNumberLocaleSupport(objectArray["vsent"])
vlost.text = thisThingHasNoNumberLocaleSupport(objectArray["vlost"])
gpackets.text = thisThingHasNoNumberLocaleSupport(objectArray["gpackets"])
gsent.text = thisThingHasNoNumberLocaleSupport(objectArray["gsent"])
glost.text = thisThingHasNoNumberLocaleSupport(objectArray["glost"])
stErrorCount = 0
wifiStatus.visible = true
timer.start()
}
}
}
}
req.send()
}
Component.onCompleted: {
timer.interval = 1000
timer.repeat = true
timer.triggered.connect(updateStatus)
}
property Fact wifiChannel: controller.getParameterFact(controller.componentID, "WIFI_CHANNEL") property Fact wifiChannel: controller.getParameterFact(controller.componentID, "WIFI_CHANNEL")
property Fact hostPort: controller.getParameterFact(controller.componentID, "WIFI_UDP_HPORT") property Fact hostPort: controller.getParameterFact(controller.componentID, "WIFI_UDP_HPORT")
property Fact clientPort: controller.getParameterFact(controller.componentID, "WIFI_UDP_CPORT") property Fact clientPort: controller.getParameterFact(controller.componentID, "WIFI_UDP_CPORT")
...@@ -76,13 +135,19 @@ QGCView { ...@@ -76,13 +135,19 @@ QGCView {
Rectangle { Rectangle {
width: parent.width width: parent.width
height: wifiCol.height + (ScreenTools.defaultFontPixelHeight * 2) height: wifiStatus.visible ? Math.max(wifiCol.height, wifiStatus.height) + (ScreenTools.defaultFontPixelHeight * 2) : wifiCol.height + (ScreenTools.defaultFontPixelHeight * 2)
color: palette.windowShade color: palette.windowShade
Row {
anchors.verticalCenter: parent.verticalCenter
spacing: ScreenTools.defaultFontPixelWidth
Rectangle {
height: parent.height
width: 1
color: palette.window
}
Column { Column {
id: wifiCol id: wifiCol
anchors.margins: ScreenTools.defaultFontPixelHeight / 2
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter
anchors.left: parent.left
spacing: ScreenTools.defaultFontPixelHeight / 2 spacing: ScreenTools.defaultFontPixelHeight / 2
Row { Row {
spacing: ScreenTools.defaultFontPixelWidth spacing: ScreenTools.defaultFontPixelWidth
...@@ -171,6 +236,131 @@ QGCView { ...@@ -171,6 +236,131 @@ QGCView {
} }
} }
} }
Rectangle {
height: parent.height
width: 1
color: palette.text
visible: wifiStatus.visible
}
Column {
id: wifiStatus
anchors.margins: ScreenTools.defaultFontPixelHeight / 2
spacing: ScreenTools.defaultFontPixelHeight / 2
visible: false
QGCLabel {
text: "Bridge/Vehicle Link"
font.weight: Font.DemiBold
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Received"
width: _firstColumn
}
QGCLabel {
id: vpackets
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Lost"
width: _firstColumn
}
QGCLabel {
id: vlost
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Sent"
width: _firstColumn
}
QGCLabel {
id: vsent
}
}
Rectangle {
height: 1
width: parent.width
color: palette.text
}
QGCLabel {
text: "Bridge/QGC Link"
font.weight: Font.DemiBold
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Received"
width: _firstColumn
}
QGCLabel {
id: gpackets
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Lost"
width: _firstColumn
}
QGCLabel {
id: glost
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Sent"
width: _firstColumn
}
QGCLabel {
id: gsent
}
}
Rectangle {
height: 1
width: parent.width
color: palette.text
}
QGCLabel {
text: "QGC/Bridge Link"
font.weight: Font.DemiBold
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Received"
width: _firstColumn
}
QGCLabel {
text: controller.vehicle ? thisThingHasNoNumberLocaleSupport(controller.vehicle.messagesReceived) : 0
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Lost"
width: _firstColumn
}
QGCLabel {
text: controller.vehicle ? thisThingHasNoNumberLocaleSupport(controller.vehicle.messagesLost) : 0
}
}
Row {
spacing: ScreenTools.defaultFontPixelWidth
QGCLabel {
text: "Messages Sent"
width: _firstColumn
}
QGCLabel {
text: controller.vehicle ? thisThingHasNoNumberLocaleSupport(controller.vehicle.messagesSent) : 0
}
}
}
}
} }
Row { Row {
spacing: ScreenTools.defaultFontPixelWidth * 1.5 spacing: ScreenTools.defaultFontPixelWidth * 1.5
...@@ -204,6 +394,31 @@ QGCView { ...@@ -204,6 +394,31 @@ QGCView {
} }
} }
} }
QGCButton {
text: stEnabled ? "Hide Status" : "Show Status"
width: ScreenTools.defaultFontPixelWidth * 16
onClicked: {
stEnabled = !stEnabled
if(stEnabled)
updateStatus()
else {
wifiStatus.visible = false
timer.stop()
}
}
}
QGCButton {
text: "Reset Counters"
visible: stEnabled
enabled: stEnabled
width: ScreenTools.defaultFontPixelWidth * 16
onClicked: {
stResetCounters = true;
updateStatus()
if(controller.vehicle)
controller.vehicle.resetCounters()
}
}
} }
} }
} }
......
...@@ -58,9 +58,10 @@ public: ...@@ -58,9 +58,10 @@ public:
Q_PROPERTY(QStringList baudRates READ baudRates CONSTANT) Q_PROPERTY(QStringList baudRates READ baudRates CONSTANT)
Q_PROPERTY(int baudIndex READ baudIndex WRITE setBaudIndex NOTIFY baudIndexChanged) Q_PROPERTY(int baudIndex READ baudIndex WRITE setBaudIndex NOTIFY baudIndexChanged)
Q_PROPERTY(bool busy READ busy NOTIFY busyChanged) Q_PROPERTY(bool busy READ busy NOTIFY busyChanged)
Q_PROPERTY(Vehicle* vehicle READ vehicle CONSTANT)
Q_INVOKABLE void restoreDefaults(); Q_INVOKABLE void restoreDefaults();
Q_INVOKABLE void reboot(); Q_INVOKABLE void reboot ();
int componentID () { return MAV_COMP_ID_UDP_BRIDGE; } int componentID () { return MAV_COMP_ID_UDP_BRIDGE; }
QString version (); QString version ();
...@@ -70,6 +71,7 @@ public: ...@@ -70,6 +71,7 @@ public:
QStringList baudRates () { return _baudRates; } QStringList baudRates () { return _baudRates; }
int baudIndex (); int baudIndex ();
bool busy () { return _waitType != WAIT_FOR_NOTHING; } bool busy () { return _waitType != WAIT_FOR_NOTHING; }
Vehicle* vehicle () { return _vehicle; }
void setWifiSSID (QString id); void setWifiSSID (QString id);
void setWifiPassword (QString pwd); void setWifiPassword (QString pwd);
......
...@@ -111,6 +111,12 @@ Vehicle::Vehicle(LinkInterface* link, ...@@ -111,6 +111,12 @@ Vehicle::Vehicle(LinkInterface* link,
, _joystickManager(joystickManager) , _joystickManager(joystickManager)
, _flowImageIndex(0) , _flowImageIndex(0)
, _allLinksInactiveSent(false) , _allLinksInactiveSent(false)
, _messagesReceived(0)
, _messagesSent(0)
, _messagesLost(0)
, _messageSeq(0)
, _compID(0)
, _heardFrom(false)
{ {
_addLink(link); _addLink(link);
...@@ -215,6 +221,16 @@ Vehicle::~Vehicle() ...@@ -215,6 +221,16 @@ Vehicle::~Vehicle()
} }
void
Vehicle::resetCounters()
{
_messagesReceived = 0;
_messagesSent = 0;
_messagesLost = 0;
_messageSeq = 0;
_heardFrom = false;
}
void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message) void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t message)
{ {
if (message.sysid != _id && message.sysid != 0) { if (message.sysid != _id && message.sysid != 0) {
...@@ -225,6 +241,32 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes ...@@ -225,6 +241,32 @@ void Vehicle::_mavlinkMessageReceived(LinkInterface* link, mavlink_message_t mes
_addLink(link); _addLink(link);
} }
//-- Check link status
_messagesReceived++;
emit messagesReceivedChanged();
if(!_heardFrom) {
if(message.msgid == MAVLINK_MSG_ID_HEARTBEAT) {
_heardFrom = true;
_compID = message.compid;
_messageSeq = message.seq + 1;
}
} else {
if(_compID == message.compid) {
uint16_t seq_received = (uint16_t)message.seq;
uint16_t packet_lost_count = 0;
//-- Account for overflow during packet loss
if(seq_received < _messageSeq) {
packet_lost_count = (seq_received + 255) - _messageSeq;
} else {
packet_lost_count = seq_received - _messageSeq;
}
_messageSeq = message.seq + 1;
_messagesLost += packet_lost_count;
if(packet_lost_count)
emit messagesLostChanged();
}
}
// Give the plugin a change to adjust the message contents // Give the plugin a change to adjust the message contents
_firmwarePlugin->adjustMavlinkMessage(this, &message); _firmwarePlugin->adjustMavlinkMessage(this, &message);
...@@ -471,6 +513,8 @@ void Vehicle::_sendMessageOnLink(LinkInterface* link, mavlink_message_t message) ...@@ -471,6 +513,8 @@ void Vehicle::_sendMessageOnLink(LinkInterface* link, mavlink_message_t message)
int len = mavlink_msg_to_send_buffer(buffer, &message); int len = mavlink_msg_to_send_buffer(buffer, &message);
link->writeBytes((const char*)buffer, len); link->writeBytes((const char*)buffer, len);
_messagesSent++;
emit messagesSentChanged();
} }
void Vehicle::_sendMessage(mavlink_message_t message) void Vehicle::_sendMessage(mavlink_message_t message)
...@@ -1269,8 +1313,8 @@ void Vehicle::_connectionLostTimeout(void) ...@@ -1269,8 +1313,8 @@ void Vehicle::_connectionLostTimeout(void)
{ {
if (_connectionLostEnabled && !_connectionLost) { if (_connectionLostEnabled && !_connectionLost) {
_connectionLost = true; _connectionLost = true;
_heardFrom = false;
emit connectionLostChanged(true); emit connectionLostChanged(true);
_say(QString("connection lost to vehicle %1").arg(id()), GAudioOutput::AUDIO_SEVERITY_NOTICE); _say(QString("connection lost to vehicle %1").arg(id()), GAudioOutput::AUDIO_SEVERITY_NOTICE);
} }
} }
...@@ -1278,11 +1322,9 @@ void Vehicle::_connectionLostTimeout(void) ...@@ -1278,11 +1322,9 @@ void Vehicle::_connectionLostTimeout(void)
void Vehicle::_connectionActive(void) void Vehicle::_connectionActive(void)
{ {
_connectionLostTimer.start(); _connectionLostTimer.start();
if (_connectionLost) { if (_connectionLost) {
_connectionLost = false; _connectionLost = false;
emit connectionLostChanged(false); emit connectionLostChanged(false);
_say(QString("connection regained to vehicle %1").arg(id()), GAudioOutput::AUDIO_SEVERITY_NOTICE); _say(QString("connection regained to vehicle %1").arg(id()), GAudioOutput::AUDIO_SEVERITY_NOTICE);
} }
} }
......
...@@ -119,6 +119,12 @@ public: ...@@ -119,6 +119,12 @@ public:
Q_PROPERTY(bool genericFirmware READ genericFirmware CONSTANT) Q_PROPERTY(bool genericFirmware READ genericFirmware CONSTANT)
Q_PROPERTY(bool connectionLost READ connectionLost NOTIFY connectionLostChanged) Q_PROPERTY(bool connectionLost READ connectionLost NOTIFY connectionLostChanged)
Q_PROPERTY(bool connectionLostEnabled READ connectionLostEnabled WRITE setConnectionLostEnabled NOTIFY connectionLostEnabledChanged) Q_PROPERTY(bool connectionLostEnabled READ connectionLostEnabled WRITE setConnectionLostEnabled NOTIFY connectionLostEnabledChanged)
Q_PROPERTY(uint messagesReceived READ messagesReceived NOTIFY messagesReceivedChanged)
Q_PROPERTY(uint messagesSent READ messagesSent NOTIFY messagesSentChanged)
Q_PROPERTY(uint messagesLost READ messagesLost NOTIFY messagesLostChanged)
/// Resets link status counters
Q_INVOKABLE void resetCounters ();
/// Returns the number of buttons which are reserved for firmware use in the MANUAL_CONTROL mavlink /// Returns the number of buttons which are reserved for firmware use in the MANUAL_CONTROL mavlink
/// message. For example PX4 Flight Stack reserves the first 8 buttons to simulate rc switches. /// message. For example PX4 Flight Stack reserves the first 8 buttons to simulate rc switches.
...@@ -275,6 +281,9 @@ public: ...@@ -275,6 +281,9 @@ public:
bool genericFirmware () { return !px4Firmware() && !apmFirmware(); } bool genericFirmware () { return !px4Firmware() && !apmFirmware(); }
bool connectionLost () const { return _connectionLost; } bool connectionLost () const { return _connectionLost; }
bool connectionLostEnabled() const { return _connectionLostEnabled; } bool connectionLostEnabled() const { return _connectionLostEnabled; }
uint messagesReceived () { return _messagesReceived; }
uint messagesSent () { return _messagesSent; }
uint messagesLost () { return _messagesLost; }
void setConnectionLostEnabled(bool connectionLostEnabled); void setConnectionLostEnabled(bool connectionLostEnabled);
...@@ -305,6 +314,10 @@ signals: ...@@ -305,6 +314,10 @@ signals:
void connectionLostChanged(bool connectionLost); void connectionLostChanged(bool connectionLost);
void connectionLostEnabledChanged(bool connectionLostEnabled); void connectionLostEnabledChanged(bool connectionLostEnabled);
void messagesReceivedChanged ();
void messagesSentChanged ();
void messagesLostChanged ();
/// Used internally to move sendMessage call to main thread /// Used internally to move sendMessage call to main thread
void _sendMessageOnThread(mavlink_message_t message); void _sendMessageOnThread(mavlink_message_t message);
void _sendMessageOnLinkOnThread(LinkInterface* link, mavlink_message_t message); void _sendMessageOnLinkOnThread(LinkInterface* link, mavlink_message_t message);
...@@ -506,6 +519,13 @@ private: ...@@ -506,6 +519,13 @@ private:
bool _allLinksInactiveSent; ///< true: allLinkInactive signal already sent one time bool _allLinksInactiveSent; ///< true: allLinkInactive signal already sent one time
uint _messagesReceived;
uint _messagesSent;
uint _messagesLost;
uint8_t _messageSeq;
uint8_t _compID;
bool _heardFrom;
// Settings keys // Settings keys
static const char* _settingsGroup; static const char* _settingsGroup;
static const char* _joystickModeSettingsKey; static const char* _joystickModeSettingsKey;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment