Skip to content

Commit 74cebec

Browse files
authored
Merge branch 'master' into head-tracker
2 parents 68161e9 + 5ca54e2 commit 74cebec

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
@@ -294,28 +294,33 @@ static void WebUpdateSendNetworks(AsyncWebServerRequest *request)
294294
}
295295
}
296296

297-
static void sendResponse(AsyncWebServerRequest *request, const String &msg, WiFiMode_t mode) {
298-
AsyncWebServerResponse *response = request->beginResponse(200, "text/plain", msg);
297+
static void sendResponse(AsyncWebServerRequest *request, const String &msg, const String &type = "text/plain") {
298+
AsyncWebServerResponse *response = request->beginResponse(200, type, msg);
299299
response->addHeader("Connection", "close");
300300
request->send(response);
301301
request->client()->close();
302302
changeTime = millis();
303+
}
304+
305+
static void changeWifiMode(WiFiMode_t mode){
303306
changeMode = mode;
304307
}
305308

306309
static void WebUpdateAccessPoint(AsyncWebServerRequest *request)
307310
{
308311
DBGLN("Starting Access Point");
309312
String msg = String("Access Point starting, please connect to access point '") + wifi_ap_ssid + "' with password '" + wifi_ap_password + "'";
310-
sendResponse(request, msg, WIFI_AP);
313+
sendResponse(request, msg);
314+
changeWifiMode(WIFI_AP);
311315
}
312316

313317
static void WebUpdateConnect(AsyncWebServerRequest *request)
314318
{
315319
DBGLN("Connecting to home network");
316320
String msg = String("Connecting to network '") + station_ssid + "', connect to http://" +
317321
myHostname + ".local from a browser on that network";
318-
sendResponse(request, msg, WIFI_STA);
322+
sendResponse(request, msg);
323+
changeWifiMode(WIFI_STA);
319324
}
320325

321326
static void WebUpdateSetHome(AsyncWebServerRequest *request)
@@ -346,13 +351,16 @@ static void WebUpdateForget(AsyncWebServerRequest *request)
346351
strcpy(station_ssid, firmwareOptions.home_wifi_ssid);
347352
strcpy(station_password, firmwareOptions.home_wifi_password);
348353
String msg = String("Temporary network forgotten, attempting to connect to network '") + station_ssid + "'";
349-
sendResponse(request, msg, WIFI_STA);
354+
sendResponse(request, msg);
355+
changeWifiMode(WIFI_STA);
356+
350357
}
351358
else {
352359
station_ssid[0] = 0;
353360
station_password[0] = 0;
354361
String msg = String("Home network forgotten, please connect to access point '") + wifi_ap_ssid + "' with password '" + wifi_ap_password + "'";
355-
sendResponse(request, msg, WIFI_AP);
362+
sendResponse(request, msg);
363+
changeWifiMode(WIFI_AP);
356364
}
357365
}
358366

@@ -531,8 +539,8 @@ static void WebMAVLinkHandler(AsyncWebServerRequest *request)
531539
json["counters"]["packets_up"] = stats->packets_uplink;
532540
json["counters"]["drops_down"] = stats->drops_downlink;
533541
json["counters"]["overflows_down"] = stats->overflows_downlink;
534-
json["ports"]["listen"] = MAVLINK_PORT_LISTEN;
535-
json["ports"]["send"] = MAVLINK_PORT_SEND;
542+
json["ports"]["listen"] = config.GetMavlinkListenPort();
543+
json["ports"]["send"] = config.GetMavlinkSendPort();
536544
if (gcsIPSet) {
537545
json["ip"]["gcs"] = gcsIP.toString();
538546
} else {
@@ -544,6 +552,35 @@ static void WebMAVLinkHandler(AsyncWebServerRequest *request)
544552
serializeJson(json, *response);
545553
request->send(response);
546554
}
555+
556+
static void WebUpdateSetMavLink(AsyncWebServerRequest *request)
557+
{
558+
uint16_t listen_port = request->arg("listen").toInt();
559+
uint16_t send_port = request->arg("send").toInt();
560+
561+
DBGLN("Setting MavLink configuration: listen=%d, send=%d", listen_port, send_port);
562+
563+
config.SetMavlinkListenPort(listen_port);
564+
config.SetMavlinkSendPort(send_port);
565+
config.SetWiFiService(WIFI_SERVICE_MAVLINK_TX);
566+
config.Commit();
567+
568+
// Restart MavLink UDP service
569+
mavlinkUDP.stop();
570+
mavlinkUDP.begin(config.GetMavlinkListenPort());
571+
572+
String response = F(
573+
"<html><head>"
574+
"<meta http-equiv='refresh' content='2;url=/'>"
575+
"<title>MavLink Settings Updated</title>"
576+
"</head><body>"
577+
"<h1>MavLink Settings Updated Successfully</h1>"
578+
"<p>Redirecting back to the main page in 2 seconds...</p>"
579+
"</body></html>"
580+
);
581+
582+
sendResponse(request, response, "text/html");
583+
}
547584
#endif
548585

549586
static void wifiOff()
@@ -666,6 +703,9 @@ static void startServices()
666703
server.on("/config", HTTP_GET, GetConfiguration);
667704
server.on("/networks.json", WebUpdateSendNetworks);
668705
server.on("/sethome", WebUpdateSetHome);
706+
#if defined(MAVLINK_ENABLED)
707+
server.on("/setmavlink", WebUpdateSetMavLink);
708+
#endif
669709
server.on("/forget", WebUpdateForget);
670710
server.on("/connect", WebUpdateConnect);
671711
server.on("/access", WebUpdateAccessPoint);
@@ -708,7 +748,7 @@ static void startServices()
708748

709749
startMDNS();
710750
#if defined(MAVLINK_ENABLED)
711-
mavlinkUDP.begin(MAVLINK_PORT_LISTEN);
751+
mavlinkUDP.begin(config.GetMavlinkListenPort());
712752
#endif
713753

714754
servicesStarted = true;
@@ -824,7 +864,7 @@ static void HandleWebUpdate()
824864
remote = WiFi.broadcastIP();
825865
}
826866

827-
mavlinkUDP.beginPacket(remote, MAVLINK_PORT_SEND);
867+
mavlinkUDP.beginPacket(remote, config.GetMavlinkSendPort());
828868
mavlink_message_t* msgQueue = mavlink.GetQueuedMsgs();
829869
for (uint8_t i = 0; i < mavlink.GetQueuedMsgCount(); i++)
830870
{

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
/////////////////////////////////////////////////////
@@ -333,6 +348,7 @@ TimerBackpackConfig::Commit()
333348
if (!m_modified)
334349
{
335350
// No changes
351+
DBGLN("No Config Changes Detected")
336352
return;
337353
}
338354
// 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 (0b10U << 30)
88
#define TIMER_BACKPACK_CONFIG_MAGIC (0b11U << 30)
99

10-
#define TX_BACKPACK_CONFIG_VERSION 3
10+
#define TX_BACKPACK_CONFIG_VERSION 4
1111
#define VRX_BACKPACK_CONFIG_VERSION 5
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)