Skip to content

Commit 5ca54e2

Browse files
authored
add mavlink port set config options for tx backpack (#167)
adds ability to set mavlink send and listen ports via webui
1 parent cfeb404 commit 5ca54e2

File tree

6 files changed

+201
-15
lines changed

6 files changed

+201
-15
lines changed

html/scan.js

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ function _(el) {
66

77
function init() {
88
initAat();
9+
initMavLink();
910

1011
// sends XMLHttpRequest, so do it last
1112
initOptions();
@@ -25,6 +26,27 @@ function initAat() {
2526
);
2627
}
2728

29+
function initMavLink() {
30+
// Fetch initial MavLink configuration
31+
const xmlhttp = new XMLHttpRequest();
32+
xmlhttp.onreadystatechange = function() {
33+
if (this.readyState == 4 && this.status == 200) {
34+
const data = JSON.parse(this.responseText);
35+
updateMavLinkConfig(data);
36+
37+
// Start periodic updates of MavLink stats
38+
updateMavLinkStats();
39+
setInterval(updateMavLinkStats, 1000);
40+
41+
const resetButton = _('mavlink_reset_defaults');
42+
if (resetButton) {
43+
resetButton.addEventListener('click', resetMavLinkDefaults);
44+
}
45+
}
46+
};
47+
xmlhttp.open('GET', '/mavlink', true);
48+
xmlhttp.send();
49+
}
2850
function initOptions() {
2951
const xmlhttp = new XMLHttpRequest();
3052
xmlhttp.onreadystatechange = function() {
@@ -38,6 +60,63 @@ function initOptions() {
3860
xmlhttp.send();
3961
}
4062

63+
function updateMavLinkConfig(data) {
64+
_('mavlink_listen_port').value = data.ports.listen;
65+
_('mavlink_send_port').value = data.ports.send;
66+
}
67+
68+
function updateMavLinkStats() {
69+
const xmlhttp = new XMLHttpRequest();
70+
xmlhttp.onreadystatechange = function() {
71+
if (this.readyState == 4 && this.status == 200) {
72+
const data = JSON.parse(this.responseText);
73+
74+
// Update Stats
75+
_('mavlink_gcs_ip').textContent = data.ip.gcs;
76+
_('mavlink_packets_down').textContent = data.counters.packets_down;
77+
_('mavlink_packets_up').textContent = data.counters.packets_up;
78+
_('mavlink_drops_down').textContent = data.counters.drops_down;
79+
_('mavlink_overflows_down').textContent = data.counters.overflows_down;
80+
}
81+
};
82+
xmlhttp.open('GET', '/mavlink', true);
83+
xmlhttp.send();
84+
}
85+
86+
function resetMavLinkDefaults() {
87+
const defaultSendPort = 14550;
88+
const defaultListenPort = 14555;
89+
90+
// Update the input fields
91+
_('mavlink_listen_port').value = defaultListenPort;
92+
_('mavlink_send_port').value = defaultSendPort;
93+
94+
// Send the new values to the server
95+
const xmlhttp = new XMLHttpRequest();
96+
xmlhttp.onreadystatechange = function() {
97+
if (this.readyState == 4) {
98+
if (this.status == 200) {
99+
cuteAlert({
100+
type: "success",
101+
title: "Default Settings Applied",
102+
message: "MavLink ports have been reset to default values."
103+
});
104+
// Refresh the MavLink stats to reflect the changes
105+
updateMavLinkStats();
106+
} else {
107+
cuteAlert({
108+
type: "error",
109+
title: "Error",
110+
message: "Failed to apply default settings. Please try again."
111+
});
112+
}
113+
}
114+
};
115+
xmlhttp.open('POST', '/setmavlink', true);
116+
xmlhttp.setRequestHeader('Content-type', 'application/x-www-form-urlencoded');
117+
xmlhttp.send(`listen=${defaultListenPort}&send=${defaultSendPort}`);
118+
}
119+
41120
function updateConfig(data) {
42121
let config = data.config;
43122
if (config.mode==="STA") {

html/txbp_index.html

Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ <h1><b>ExpressLRS</b></h1>
2525
<li id="tx_tab" class="mui--is-active"><a data-mui-toggle="tab" data-mui-controls="pane-justified-1">TX</a></li>
2626
<li><a data-mui-toggle="tab" data-mui-controls="pane-justified-2">Backpack</a></li>
2727
<li><a data-mui-toggle="tab" data-mui-controls="pane-justified-3">Network</a></li>
28+
<li><a data-mui-toggle="tab" data-mui-controls="pane-justified-4">MavLink</a></li>
2829
</ul>
2930

3031
<div class="mui-tabs__pane mui--is-active" id="pane-justified-1">
@@ -97,6 +98,54 @@ <h2>Home Network: <span id="ssid"></span></h2>
9798
<a id="access" href="#" class="mui-btn mui-btn--primary">Disconnect</a>
9899
</div>
99100
</div>
101+
102+
<div class="mui-tabs__pane" id="pane-justified-4">
103+
<h2>MavLink Configuration</h2>
104+
<form action="/setmavlink" id="mavlink_form" method="POST" autocomplete="off" class="mui-form">
105+
<div class="mui-textfield">
106+
Send Port
107+
<input type="number" id="mavlink_send_port" name="send" placeholder="Send Port">
108+
</div>
109+
<div class="mui-textfield">
110+
Listen Port
111+
<input type="number" id="mavlink_listen_port" name="listen" placeholder="Listen Port">
112+
</div>
113+
<!-- I wanted to avoid adding css -->
114+
<table>
115+
<tr>
116+
<td>
117+
<input type="submit" value="Save Configuration" class="mui-btn mui-btn--primary">
118+
</td>
119+
<td>
120+
<button id="mavlink_reset_defaults" class="mui-btn mui-btn--primary">Reset Defaults</button>
121+
</td>
122+
</tr>
123+
</table>
124+
</form>
125+
<h3>MavLink Statistics</h3>
126+
<table class="mui-table">
127+
<tr>
128+
<td>Packets Downlink:</td>
129+
<td id="mavlink_packets_down"></td>
130+
</tr>
131+
<tr>
132+
<td>Packets Uplink:</td>
133+
<td id="mavlink_packets_up"></td>
134+
</tr>
135+
<tr>
136+
<td>Drops Downlink:</td>
137+
<td id="mavlink_drops_down"></td>
138+
</tr>
139+
<tr>
140+
<td>Overflows Downlink:</td>
141+
<td id="mavlink_overflows_down"></td>
142+
</tr>
143+
<tr>
144+
<td>GCS IP Adresses</Address>:</td>
145+
<td id="mavlink_gcs_ip"></td>
146+
</tr>
147+
</table>
148+
</div>
100149
</div>
101150
</div>
102151
<footer>

lib/MAVLink/MAVLink.h

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,6 @@
11
#if defined(MAVLINK_ENABLED)
22
#include "common/mavlink.h"
33

4-
// This is the port that we will listen for mavlink packets on
5-
constexpr uint16_t MAVLINK_PORT_LISTEN = 14555;
6-
// This is the port that we will send mavlink packets to
7-
constexpr uint16_t MAVLINK_PORT_SEND = 14550;
84
// Size of the buffer that we will use to store mavlink packets in units of mavlink_message_t
95
constexpr size_t MAVLINK_BUF_SIZE = 16;
106
// Threshold at which we will flush the buffer

lib/WIFI/devWIFI.cpp

Lines changed: 50 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -228,28 +228,33 @@ static void WebUpdateSendNetworks(AsyncWebServerRequest *request)
228228
}
229229
}
230230

231-
static void sendResponse(AsyncWebServerRequest *request, const String &msg, WiFiMode_t mode) {
232-
AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", msg);
231+
static void sendResponse(AsyncWebServerRequest *request, const String &msg, const String &type = "text/plain") {
232+
AsyncWebServerResponse *response = request->beginResponse(200, type, msg);
233233
response->addHeader("Connection", "close");
234234
request->send(response);
235235
request->client()->close();
236236
changeTime = millis();
237+
}
238+
239+
static void changeWifiMode(WiFiMode_t mode){
237240
changeMode = mode;
238241
}
239242

240243
static void WebUpdateAccessPoint(AsyncWebServerRequest *request)
241244
{
242245
DBGLN("Starting Access Point");
243246
String msg = String("Access Point starting, please connect to access point '") + wifi_ap_ssid + "' with password '" + wifi_ap_password + "'";
244-
sendResponse(request, msg, WIFI_AP);
247+
sendResponse(request, msg);
248+
changeWifiMode(WIFI_AP);
245249
}
246250

247251
static void WebUpdateConnect(AsyncWebServerRequest *request)
248252
{
249253
DBGLN("Connecting to home network");
250254
String msg = String("Connecting to network '") + station_ssid + "', connect to http://" +
251255
myHostname + ".local from a browser on that network";
252-
sendResponse(request, msg, WIFI_STA);
256+
sendResponse(request, msg);
257+
changeWifiMode(WIFI_STA);
253258
}
254259

255260
static void WebUpdateSetHome(AsyncWebServerRequest *request)
@@ -280,13 +285,16 @@ static void WebUpdateForget(AsyncWebServerRequest *request)
280285
strcpy(station_ssid, firmwareOptions.home_wifi_ssid);
281286
strcpy(station_password, firmwareOptions.home_wifi_password);
282287
String msg = String("Temporary network forgotten, attempting to connect to network '") + station_ssid + "'";
283-
sendResponse(request, msg, WIFI_STA);
288+
sendResponse(request, msg);
289+
changeWifiMode(WIFI_STA);
290+
284291
}
285292
else {
286293
station_ssid[0] = 0;
287294
station_password[0] = 0;
288295
String msg = String("Home network forgotten, please connect to access point '") + wifi_ap_ssid + "' with password '" + wifi_ap_password + "'";
289-
sendResponse(request, msg, WIFI_AP);
296+
sendResponse(request, msg);
297+
changeWifiMode(WIFI_AP);
290298
}
291299
}
292300

@@ -465,8 +473,8 @@ static void WebMAVLinkHandler(AsyncWebServerRequest *request)
465473
json["counters"]["packets_up"] = stats->packets_uplink;
466474
json["counters"]["drops_down"] = stats->drops_downlink;
467475
json["counters"]["overflows_down"] = stats->overflows_downlink;
468-
json["ports"]["listen"] = MAVLINK_PORT_LISTEN;
469-
json["ports"]["send"] = MAVLINK_PORT_SEND;
476+
json["ports"]["listen"] = config.GetMavlinkListenPort();
477+
json["ports"]["send"] = config.GetMavlinkSendPort();
470478
if (gcsIPSet) {
471479
json["ip"]["gcs"] = gcsIP.toString();
472480
} else {
@@ -478,6 +486,35 @@ static void WebMAVLinkHandler(AsyncWebServerRequest *request)
478486
serializeJson(json, *response);
479487
request->send(response);
480488
}
489+
490+
static void WebUpdateSetMavLink(AsyncWebServerRequest *request)
491+
{
492+
uint16_t listen_port = request->arg("listen").toInt();
493+
uint16_t send_port = request->arg("send").toInt();
494+
495+
DBGLN("Setting MavLink configuration: listen=%d, send=%d", listen_port, send_port);
496+
497+
config.SetMavlinkListenPort(listen_port);
498+
config.SetMavlinkSendPort(send_port);
499+
config.SetWiFiService(WIFI_SERVICE_MAVLINK_TX);
500+
config.Commit();
501+
502+
// Restart MavLink UDP service
503+
mavlinkUDP.stop();
504+
mavlinkUDP.begin(config.GetMavlinkListenPort());
505+
506+
String response = F(
507+
"<html><head>"
508+
"<meta http-equiv='refresh' content='2;url=/'>"
509+
"<title>MavLink Settings Updated</title>"
510+
"</head><body>"
511+
"<h1>MavLink Settings Updated Successfully</h1>"
512+
"<p>Redirecting back to the main page in 2 seconds...</p>"
513+
"</body></html>"
514+
);
515+
516+
sendResponse(request, response, "text/html");
517+
}
481518
#endif
482519

483520
static void wifiOff()
@@ -600,6 +637,9 @@ static void startServices()
600637
server.on("/config", HTTP_GET, GetConfiguration);
601638
server.on("/networks.json", WebUpdateSendNetworks);
602639
server.on("/sethome", WebUpdateSetHome);
640+
#if defined(MAVLINK_ENABLED)
641+
server.on("/setmavlink", WebUpdateSetMavLink);
642+
#endif
603643
server.on("/forget", WebUpdateForget);
604644
server.on("/connect", WebUpdateConnect);
605645
server.on("/access", WebUpdateAccessPoint);
@@ -632,7 +672,7 @@ static void startServices()
632672

633673
startMDNS();
634674
#if defined(MAVLINK_ENABLED)
635-
mavlinkUDP.begin(MAVLINK_PORT_LISTEN);
675+
mavlinkUDP.begin(config.GetMavlinkListenPort());
636676
#endif
637677

638678
servicesStarted = true;
@@ -748,7 +788,7 @@ static void HandleWebUpdate()
748788
remote = WiFi.broadcastIP();
749789
}
750790

751-
mavlinkUDP.beginPacket(remote, MAVLINK_PORT_SEND);
791+
mavlinkUDP.beginPacket(remote, config.GetMavlinkSendPort());
752792
mavlink_message_t* msgQueue = mavlink.GetQueuedMsgs();
753793
for (uint8_t i = 0; i < mavlink.GetQueuedMsgCount(); i++)
754794
{

lib/config/config.cpp

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,8 @@ TxBackpackConfig::SetDefaults()
5252
m_config.password[0] = 0;
5353
memset(m_config.address, 0, 6);
5454
m_config.wifiService = WIFI_SERVICE_UPDATE;
55+
m_config.mavlinkListenPort = 14555; // Default MavLink listen port
56+
m_config.mavlinkSendPort = 14550; // Default MavLink send port
5557
m_modified = true;
5658
Commit();
5759
}
@@ -97,6 +99,19 @@ TxBackpackConfig::SetTelemMode(telem_mode_t mode)
9799
m_config.telemMode = mode;
98100
m_modified = true;
99101
}
102+
void
103+
TxBackpackConfig::SetMavlinkListenPort(uint16_t port)
104+
{
105+
m_config.mavlinkListenPort = port;
106+
m_modified = true;
107+
}
108+
109+
void
110+
TxBackpackConfig::SetMavlinkSendPort(uint16_t port)
111+
{
112+
m_config.mavlinkSendPort = port;
113+
m_modified = true;
114+
}
100115
#endif
101116

102117
/////////////////////////////////////////////////////
@@ -310,6 +325,7 @@ TimerBackpackConfig::Commit()
310325
if (!m_modified)
311326
{
312327
// No changes
328+
DBGLN("No Config Changes Detected")
313329
return;
314330
}
315331
// Write the struct to eeprom

lib/config/config.h

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@
77
#define VRX_BACKPACK_CONFIG_MAGIC (0b10 << 30)
88
#define TIMER_BACKPACK_CONFIG_MAGIC (0b11 << 30)
99

10-
#define TX_BACKPACK_CONFIG_VERSION 3
10+
#define TX_BACKPACK_CONFIG_VERSION 4
1111
#define VRX_BACKPACK_CONFIG_VERSION 3
1212
#define TIMER_BACKPACK_CONFIG_VERSION 3
1313

@@ -34,6 +34,8 @@ typedef struct {
3434
uint8_t address[6];
3535
wifi_service_t wifiService;
3636
telem_mode_t telemMode;
37+
uint16_t mavlinkListenPort;
38+
uint16_t mavlinkSendPort;
3739
} tx_backpack_config_t;
3840

3941
class TxBackpackConfig
@@ -50,6 +52,8 @@ class TxBackpackConfig
5052
uint8_t *GetGroupAddress() { return m_config.address; }
5153
wifi_service_t GetWiFiService() { return m_config.wifiService; }
5254
telem_mode_t GetTelemMode() { return m_config.telemMode; }
55+
uint16_t GetMavlinkListenPort() const { return m_config.mavlinkListenPort; }
56+
uint16_t GetMavlinkSendPort() const { return m_config.mavlinkSendPort; }
5357

5458
// Setters
5559
void SetStorageProvider(ELRS_EEPROM *eeprom);
@@ -60,6 +64,8 @@ class TxBackpackConfig
6064
void SetGroupAddress(const uint8_t address[6]);
6165
void SetWiFiService(wifi_service_t service);
6266
void SetTelemMode(telem_mode_t mode);
67+
void SetMavlinkListenPort(uint16_t port);
68+
void SetMavlinkSendPort(uint16_t port);
6369

6470
private:
6571
tx_backpack_config_t m_config;

0 commit comments

Comments
 (0)