Share the Companion terminal with the WiFi console

This commit is contained in:
mikecarper committed 2026-09-08 19:48:15 -07:00
1 parent cb79dcd4e3
commit d178cf1474
20 files changed
+3047 -2062

No files matched your search

+7 -7
View File
@@ -3370,9 +3370,9 @@ void MyMesh::onConfigBatchEnd() {
}
void MyMesh::execAdminCommand(char* cmd, char* reply) {
// WebConfig runs this bounded dispatcher on the mesh loop. It must not
// enter the stateful USB/TCP terminal, select a recipient, or capture that
// terminal's stream. Use remote-call semantics for board-specific commands.
// The settings-batch API runs independently from the interactive terminal.
// The browser CLI uses runStreamTerminal() for the shared USB/TCP session;
// a settings batch must not capture or reset that session's stream.
reply[0] = 0;
if (!cmd || (strlen(cmd) > 2 && cmd[2] == '|')) {
strcpy(reply, "Error: enter a plain CLI command");
@@ -6810,7 +6810,7 @@ void MyMesh::printTerminalBanner(bool show_binary_stop) {
if (show_binary_stop) {
output.print(" (+++MESHCORE-TERM-STOP returns to Binary mode)\r\n");
} else {
output.print(" (disconnect to close this TCP terminal)\r\n");
output.print(" (disconnect to close this network terminal)\r\n");
}
output.print("\r\n> ");
}
@@ -6828,9 +6828,9 @@ void MyMesh::exitTerminalMode() {
if (_terminal_output == &mesh::usbTerminalPort()) _terminal_output = NULL;
}
#if COMPANION_FEATURE_NETWORK_TERMINAL
#if COMPANION_FEATURE_NETWORK_TERMINAL || defined(WITH_WEBCONFIG)
bool MyMesh::enterNetworkTerminalMode(Stream& output) {
if (_terminal_mode) return false;
if (_terminal_mode || (_terminal_output != NULL && _terminal_output != &output)) return false;
_terminal_output = &output;
resetTerminalSession();
printTerminalBanner(false);
@@ -7983,7 +7983,7 @@ void MyMesh::handleTerminalCommand(char* command) {
if (_terminal_mode) {
terminalOutput().print(" +++MESHCORE-TERM-STOP\r\n");
} else {
terminalOutput().print(" disconnect (closes the TCP terminal)\r\n");
terminalOutput().print(" disconnect (closes the network terminal)\r\n");
}
} else if (handleCommand(command, 0, local_reply)) {
// Fill the same safe shared-command surface for getters (`get name`,
+13 -1
View File
@@ -187,6 +187,15 @@ public:
void execCommand(char* cmd, char* reply) override;
bool supportsCliTerminal() const override { return true; }
void execAdminCommand(char* cmd, char* reply) override;
#ifdef ENABLE_USB_INTERFACE
bool supportsStreamTerminal() const override { return true; }
bool beginStreamTerminal(Stream& output) override;
bool ownsStreamTerminal(const Stream& output) const override {
return isNetworkTerminalMode(output);
}
void runStreamTerminal(char* command) override { handleTerminalCommand(command); }
void endStreamTerminal(Stream& output) override;
#endif
void rebootNow() override;
void onConfigBatchStart() override;
void onConfigBatchEnd() override;
@@ -206,10 +215,13 @@ public:
void resetTerminalSession();
bool isTerminalMode() const { return _terminal_mode; }
void handleTerminalCommand(char* command);
#if COMPANION_FEATURE_NETWORK_TERMINAL
#if COMPANION_FEATURE_NETWORK_TERMINAL || defined(WITH_WEBCONFIG)
bool enterNetworkTerminalMode(Stream& output);
void exitNetworkTerminalMode(Stream& output);
bool isNetworkTerminalMode(const Stream& output) const;
bool isAnyNetworkTerminalMode() const {
return !_terminal_mode && _terminal_output != NULL;
}
#endif
#endif
+43 -8
View File
@@ -137,7 +137,7 @@ MultiSerialInterface interface_manager;
#endif
#endif
#if COMPANION_FEATURE_NETWORK_TERMINAL
#if defined(ENABLE_USB_INTERFACE) && (COMPANION_FEATURE_NETWORK_TERMINAL || defined(WITH_WEBCONFIG))
static bool isNetworkTerminalActive();
#endif
@@ -867,7 +867,7 @@ static void serviceUsbTerminal() {
#else
false,
#endif
#if COMPANION_FEATURE_NETWORK_TERMINAL
#if COMPANION_FEATURE_NETWORK_TERMINAL || defined(WITH_WEBCONFIG)
isNetworkTerminalActive()
#else
false
@@ -1047,6 +1047,47 @@ static void expireUsbBinaryStartupProbeBeforeDispatch() {
#endif
#endif
#if defined(ENABLE_USB_INTERFACE) && (COMPANION_FEATURE_NETWORK_TERMINAL || defined(WITH_WEBCONFIG))
static bool isNetworkTerminalActive() {
return the_mesh.isAnyNetworkTerminalMode();
}
#endif
#if defined(WITH_WEBCONFIG) && defined(ENABLE_USB_INTERFACE)
static mesh::UsbTcpTerminalHandoff browser_usb_handoff;
bool MyMesh::beginStreamTerminal(Stream& output) {
static_assert(mesh::kTerminalCommandCapacity == MAX_TRANS_UNIT * 2 + 32,
"Browser and USB/TCP command capacities must match");
if (isAnyNetworkTerminalMode()) return false;
const bool ascii_selected = isTerminalMode();
const bool input_idle = usb_terminal_line_len == 0 && !usb_terminal_discard_line
#if defined(COMPANION_RADIO_FULL)
&& !usb_binary_startup_probe.isActive()
#endif
;
if (!browser_usb_handoff.begin(ascii_selected,
hasObservableActiveUsbTerminalClient(), input_idle,
usb_serial_interface.getCompletedFrameCount())) return false;
if (ascii_selected) leaveUsbTerminalMode(false);
if (enterNetworkTerminalMode(output)) return true;
if (browser_usb_handoff.shouldRestoreAscii(
usb_serial_interface.getCompletedFrameCount())) enterUsbTerminalMode();
return false;
}
void MyMesh::endStreamTerminal(Stream& output) {
const bool owned = isNetworkTerminalMode(output);
exitNetworkTerminalMode(output);
if (!owned) {
browser_usb_handoff.cancel();
} else if (browser_usb_handoff.shouldRestoreAscii(
usb_serial_interface.getCompletedFrameCount())) {
enterUsbTerminalMode();
}
}
#endif
void halt() {
while (1) ;
}
@@ -1641,12 +1682,6 @@ void halt() {
static mesh::UsbTcpTerminalHandoff ota_console_usb_handoff;
#endif
#if COMPANION_FEATURE_NETWORK_TERMINAL
static bool isNetworkTerminalActive() {
return the_mesh.isNetworkTerminalMode(ota_console_client);
}
#endif
static void ota_console_clear_line() {
memset(ota_console_line, 0, sizeof(ota_console_line));
ota_console_len = 0;