Allow WiFi credentials to be set at runtime

Store ssid/pwd in NodePrefs and set them with 'set wifi.ssid' /
'set wifi.pwd' over USB serial; build-time WIFI_SSID/WIFI_PWD stay as
the fallback. Headless WiFi builds get the config CLI on Serial, which
is otherwise unused there.
This commit is contained in:
Michael Graff
2026-09-05 23:15:13 -05:00
parent 0b2c47a932
commit 739a67c9f1
3 changed files with 71 additions and 3 deletions
+34
View File
@@ -932,6 +932,7 @@ MyMesh::MyMesh(mesh::Radio &radio, mesh::RNG &rng, mesh::RTCClock &rtc, SimpleMe
_serial(NULL), telemetry(MAX_PACKET_PAYLOAD - 4), _store(&store), _ui(ui), _iter(0) {
_iter_started = false;
_cli_rescue = false;
cli_command[0] = 0;
offline_queue_len = 0;
app_target_ver = 0;
clearPendingReqs();
@@ -2156,6 +2157,35 @@ bool MyMesh::handleCommand(const char* command, uint32_t sender_timestamp, char*
return true;
}
#ifdef WIFI_SSID
// local console only: these are credentials, and remote admin has no business with them
if (sender_timestamp == 0) {
if (memcmp(command, "set wifi.ssid ", 14) == 0) {
StrHelper::strncpy(_prefs.wifi_ssid, &command[14], sizeof(_prefs.wifi_ssid));
savePrefs();
sprintf(reply, "> wifi.ssid is now %s (set wifi.pwd too, then reboot)", _prefs.wifi_ssid);
return true;
}
if (memcmp(command, "set wifi.pwd ", 13) == 0) {
StrHelper::strncpy(_prefs.wifi_pwd, &command[13], sizeof(_prefs.wifi_pwd));
savePrefs();
strcpy(reply, "> wifi.pwd updated (reboot to apply)");
return true;
}
if (strcmp(command, "set wifi.clear") == 0) {
_prefs.wifi_ssid[0] = 0;
_prefs.wifi_pwd[0] = 0;
savePrefs();
strcpy(reply, "> wifi config cleared, using build-time credentials (reboot to apply)");
return true;
}
if (strcmp(command, "get wifi.ssid") == 0) { // no 'get wifi.pwd', by design
sprintf(reply, "> %s", _prefs.wifi_ssid[0] ? _prefs.wifi_ssid : "(build-time)");
return true;
}
}
#endif
if (strcmp(command, "board") == 0) {
strcpy(reply, board.getManufacturerName());
return true;
@@ -2386,6 +2416,10 @@ void MyMesh::loop() {
checkCLIRescueCmd();
} else {
checkSerialInterface();
#if defined(WIFI_SSID) && !defined(ENABLE_USB_INTERFACE)
// headless WiFi build: USB serial isn't a companion transport, so use it for config
checkCLIRescueCmd();
#endif
}
// is there are pending dirty contacts write needed?
+26 -1
View File
@@ -44,6 +44,10 @@ public:
char default_scope_name[31];
uint8_t default_scope_key[16];
int8_t tz_offset = 0;
#ifdef WIFI_SSID
char wifi_ssid[33] = {0}; // if empty, the compile-time WIFI_SSID is used
char wifi_pwd[64] = {0};
#endif
private:
class RadioPrefs : public CommonRadioPrefs {
@@ -160,6 +164,20 @@ private:
DynamicConfigSerializer custom;
#ifdef WIFI_SSID
class WiFiPrefs : public ConfigSerializer {
NodePrefs* _parent;
protected:
void structure() override {
def("ssid", _parent->wifi_ssid, sizeof(_parent->wifi_ssid));
def("pwd", _parent->wifi_pwd, sizeof(_parent->wifi_pwd));
}
public:
WiFiPrefs(NodePrefs* parent) : _parent(parent) { }
};
WiFiPrefs wifi;
#endif
protected:
void structure() override {
def("name", node_name, sizeof(node_name));
@@ -172,9 +190,16 @@ protected:
def("repeat", repeat);
def("comp", companion);
def("custom", custom);
#ifdef WIFI_SSID
def("wifi", wifi);
#endif
}
public:
NodePrefs() : radio(this), gps(this), companion(this), custom(&radio) {
NodePrefs() : radio(this), gps(this), companion(this), custom(&radio)
#ifdef WIFI_SSID
, wifi(this)
#endif
{
node_name[0] = 0;
default_scope_name[0] = 0;
memset(default_scope_key, 0, sizeof(default_scope_key));
+11 -2
View File
@@ -110,6 +110,8 @@ void halt() {
#ifdef WIFI_SSID
bool wifi_needs_reconnect = false;
unsigned long last_wifi_reconnect_attempt = 0;
const char* wifi_ssid = WIFI_SSID; // replaced by stored prefs, if set
const char* wifi_pwd = WIFI_PWD;
#endif
void setup() {
@@ -206,7 +208,14 @@ void setup() {
});
#endif
WiFi.begin(WIFI_SSID, WIFI_PWD);
// stored credentials win over the build-time ones ('set wifi.ssid <x>' over USB serial)
if (the_mesh.getNodePrefs()->wifi_ssid[0]) {
wifi_ssid = the_mesh.getNodePrefs()->wifi_ssid;
wifi_pwd = the_mesh.getNodePrefs()->wifi_pwd;
}
WIFI_DEBUG_PRINTLN("connecting to %s", wifi_ssid);
WiFi.begin(wifi_ssid, wifi_pwd);
wifi_interface.begin(TCP_PORT);
interface_manager.addInterface(InterfaceType::WiFi, &wifi_interface);
#endif
@@ -273,7 +282,7 @@ void loop() {
if (wifi_needs_reconnect && (millis() - last_wifi_reconnect_attempt > 10000)) {
WIFI_DEBUG_PRINTLN("Attempting manual WiFi reconnect...");
#if defined(RP2040_PLATFORM)
WiFi.begin(WIFI_SSID, WIFI_PWD); // no reconnect() on this platform
WiFi.begin(wifi_ssid, wifi_pwd); // no reconnect() on this platform
#else
WiFi.disconnect();
WiFi.reconnect();