From dd3575174b51bf7920bb9af4791ca8f0b294c2e0 Mon Sep 17 00:00:00 2001 From: Oleg Kalachev Date: Thu, 22 Jan 2026 22:58:43 +0300 Subject: [PATCH] Add wifi configuration using parameters and cli Add console commands to setup wifi. Add a parameter for choosing between STA and AP mode. Add parameters for udp ports. Remove WIFI_ENABLED macro. --- .github/workflows/build.yml | 2 -- .markdownlint.json | 1 + docs/usage.md | 36 +++++++++++++++++++- flix/cli.ino | 12 +++---- flix/flix.ino | 5 --- flix/mavlink.ino | 4 --- flix/parameters.ino | 5 +++ flix/wifi.ino | 67 ++++++++++++++++++++++++++----------- gazebo/flix.h | 3 +- 9 files changed, 95 insertions(+), 40 deletions(-) diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index f4ef650..3bb9234 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -25,8 +25,6 @@ jobs: path: flix/build - name: Build firmware for ESP32-S3 run: make BOARD=esp32:esp32:esp32s3 - - name: Build firmware with WiFi disabled - run: sed -i 's/^#define WIFI_ENABLED 1$/#define WIFI_ENABLED 0/' flix/flix.ino && make - name: Check c_cpp_properties.json run: tools/check_c_cpp_properties.py diff --git a/.markdownlint.json b/.markdownlint.json index f98602c..ae571f8 100644 --- a/.markdownlint.json +++ b/.markdownlint.json @@ -7,6 +7,7 @@ "MD024": false, "MD033": false, "MD034": false, + "MD040": false, "MD059": false, "MD044": { "html_elements": false, diff --git a/docs/usage.md b/docs/usage.md index db3c8fa..8011866 100644 --- a/docs/usage.md +++ b/docs/usage.md @@ -243,9 +243,43 @@ In this mode, the pilot inputs are ignored (except the mode switch, if configure If the pilot moves the control sticks, the drone will switch back to *STAB* mode. +## Wi-Fi configuration + +You can configure the Wi-Fi using parameters and console commands. + +The Wi-Fi mode is chosen using `WIFI_MODE` parameter in QGroundControl or in the console: + +* `0` — Wi-Fi is disabled. +* `1` — Access Point mode (*AP*) — the drone creates a Wi-Fi network. +* `2` — Client mode (*STA*) — the drone connects to an existing Wi-Fi network. +* `3` — *ESP-NOW (not implemented yet)*. + +> [!WARNING] +> Tests showed that Client mode may cause **additional delays** in remote control (due to retranslations), so it's generally not recommended. + +The SSID and password are configured using the `ap` and `sta` console commands: + +``` +ap +sta +``` + +Example of configuring the Access Point mode: + +``` +ap my-flix-ssid mypassword123 +p WIFI_MODE 1 +``` + +Disabling Wi-Fi: + +``` +p WIFI_MODE 0 +``` + ## Flight log -After the flight, you can download the flight log for analysis wirelessly. Use the following for that: +After the flight, you can download the flight log for analysis wirelessly. Use the following command on your computer for that: ```bash make log diff --git a/flix/cli.ino b/flix/cli.ino index 145b80e..2e4f9f8 100644 --- a/flix/cli.ino +++ b/flix/cli.ino @@ -38,6 +38,8 @@ const char* motd = "raw/stab/acro/auto - set mode\n" "rc - show RC data\n" "wifi - show Wi-Fi info\n" +"ap - setup Wi-Fi access point\n" +"sta - setup Wi-Fi client mode\n" "mot - show motor output\n" "log [dump] - print log header [and data]\n" "cr - calibrate RC\n" @@ -54,9 +56,7 @@ void print(const char* format, ...) { vsnprintf(buf, sizeof(buf), format, args); va_end(args); Serial.print(buf); -#if WIFI_ENABLED mavlinkPrint(buf); -#endif } void pause(float duration) { @@ -64,9 +64,7 @@ void pause(float duration) { while (t - start < duration) { step(); handleInput(); -#if WIFI_ENABLED processMavlink(); -#endif delay(50); } } @@ -136,9 +134,11 @@ void doCommand(String str, bool echo = false) { print("mode: %s\n", getModeName()); print("armed: %d\n", armed); } else if (command == "wifi") { -#if WIFI_ENABLED printWiFiInfo(); -#endif + } else if (command == "ap") { + configWiFi(true, arg0.c_str(), arg1.c_str()); + } else if (command == "sta") { + configWiFi(false, arg0.c_str(), arg1.c_str()); } else if (command == "mot") { print("front-right %g front-left %g rear-right %g rear-left %g\n", motors[MOTOR_FRONT_RIGHT], motors[MOTOR_FRONT_LEFT], motors[MOTOR_REAR_RIGHT], motors[MOTOR_REAR_LEFT]); diff --git a/flix/flix.ino b/flix/flix.ino index 8036b60..370d66a 100644 --- a/flix/flix.ino +++ b/flix/flix.ino @@ -7,7 +7,6 @@ #include "quaternion.h" #include "util.h" -#define WIFI_ENABLED 1 extern float t, dt; extern float controlRoll, controlPitch, controlYaw, controlThrottle, controlMode; @@ -25,9 +24,7 @@ void setup() { setupLED(); setupMotors(); setLED(true); -#if WIFI_ENABLED setupWiFi(); -#endif setupIMU(); setupRC(); setLED(false); @@ -42,9 +39,7 @@ void loop() { control(); sendMotors(); handleInput(); -#if WIFI_ENABLED processMavlink(); -#endif logData(); syncParameters(); } diff --git a/flix/mavlink.ino b/flix/mavlink.ino index 0366ca4..f894497 100644 --- a/flix/mavlink.ino +++ b/flix/mavlink.ino @@ -3,8 +3,6 @@ // MAVLink communication -#if WIFI_ENABLED - #include #include "util.h" @@ -275,5 +273,3 @@ void sendMavlinkPrint() { } mavlinkPrintBuffer.clear(); } - -#endif diff --git a/flix/parameters.ino b/flix/parameters.ino index a6e7115..ae5e868 100644 --- a/flix/parameters.ino +++ b/flix/parameters.ino @@ -9,6 +9,7 @@ extern float channelZero[16]; extern float channelMax[16]; extern float rollChannel, pitchChannel, throttleChannel, yawChannel, armedChannel, modeChannel; +extern int wifiMode, udpLocalPort, udpRemotePort; Preferences storage; @@ -82,6 +83,10 @@ Parameter parameters[] = { {"RC_THROTTLE", &throttleChannel}, {"RC_YAW", &yawChannel}, {"RC_MODE", &modeChannel}, + // wifi + {"WIFI_MODE", &wifiMode}, + {"WIFI_LOC_PORT", &udpLocalPort}, + {"WIFI_REM_PORT", &udpRemotePort}, }; void setupParameters() { diff --git a/flix/wifi.ino b/flix/wifi.ino index 30f6d4a..6814dbe 100644 --- a/flix/wifi.ino +++ b/flix/wifi.ino @@ -1,49 +1,76 @@ // Copyright (c) 2023 Oleg Kalachev // Repository: https://github.com/okalachev/flix -// Wi-Fi support - -#if WIFI_ENABLED +// Wi-Fi communication #include #include #include +#include "Preferences.h" -#define WIFI_SSID "flix" -#define WIFI_PASSWORD "flixwifi" -#define WIFI_UDP_PORT 14550 -#define WIFI_UDP_REMOTE_PORT 14550 -#define WIFI_UDP_REMOTE_ADDR "255.255.255.255" +extern Preferences storage; // use the main preferences storage + +const int W_DISABLED = 0, W_AP = 1, W_STA = 2; +int wifiMode = W_AP; +int udpLocalPort = 14550; +int udpRemotePort = 14550; +IPAddress udpRemoteIP = "255.255.255.255"; WiFiUDP udp; void setupWiFi() { print("Setup Wi-Fi\n"); - WiFi.softAP(WIFI_SSID, WIFI_PASSWORD); - udp.begin(WIFI_UDP_PORT); + if (wifiMode == W_AP) { + WiFi.softAP(storage.getString("WIFI_AP_SSID", "flix").c_str(), storage.getString("WIFI_AP_PASS", "flixwifi").c_str()); + } else if (wifiMode == W_STA) { + WiFi.begin(storage.getString("WIFI_STA_SSID", "").c_str(), storage.getString("WIFI_STA_PASS", "").c_str()); + } + udp.begin(udpLocalPort); } void sendWiFi(const uint8_t *buf, int len) { - if (WiFi.softAPIP() == IPAddress(0, 0, 0, 0) && WiFi.status() != WL_CONNECTED) return; - udp.beginPacket(udp.remoteIP() ? udp.remoteIP() : WIFI_UDP_REMOTE_ADDR, WIFI_UDP_REMOTE_PORT); + if (WiFi.softAPgetStationNum() == 0 && !WiFi.isConnected()) return; + udp.beginPacket(udpRemoteIP, udpRemotePort); udp.write(buf, len); udp.endPacket(); } int receiveWiFi(uint8_t *buf, int len) { udp.parsePacket(); + if (udp.remoteIP()) udpRemoteIP = udp.remoteIP(); return udp.read(buf, len); } void printWiFiInfo() { - print("MAC: %s\n", WiFi.softAPmacAddress().c_str()); - print("SSID: %s\n", WiFi.softAPSSID().c_str()); - print("Password: %s\n", WIFI_PASSWORD); - print("Clients: %d\n", WiFi.softAPgetStationNum()); - print("Status: %d\n", WiFi.status()); - print("IP: %s\n", WiFi.softAPIP().toString().c_str()); - print("Remote IP: %s\n", udp.remoteIP().toString().c_str()); + if (WiFi.getMode() == WIFI_MODE_AP) { + print("Mode: Access Point (AP)\n"); + print("MAC: %s\n", WiFi.softAPmacAddress().c_str()); + print("SSID: %s\n", WiFi.softAPSSID().c_str()); + print("Password: ***\n"); + print("Clients: %d\n", WiFi.softAPgetStationNum()); + print("IP: %s\n", WiFi.softAPIP().toString().c_str()); + } else if (WiFi.getMode() == WIFI_MODE_STA) { + print("Mode: Client (STA)\n"); + print("Connected: %d\n", WiFi.isConnected()); + print("MAC: %s\n", WiFi.macAddress().c_str()); + print("SSID: %s\n", WiFi.SSID().c_str()); + print("Password: ***\n"); + print("IP: %s\n", WiFi.localIP().toString().c_str()); + } else { + print("Mode: Disabled\n"); + return; + } + print("Remote IP: %s\n", udpRemoteIP.toString().c_str()); print("MAVLink connected: %d\n", mavlinkConnected); } -#endif +void configWiFi(bool ap, const char *ssid, const char *password) { + if (ap) { + storage.putString("WIFI_AP_SSID", ssid); + storage.putString("WIFI_AP_PASS", password); + } else { + storage.putString("WIFI_STA_SSID", ssid); + storage.putString("WIFI_STA_PASS", password); + } + print("✓ Reboot to apply new settings\n"); +} diff --git a/gazebo/flix.h b/gazebo/flix.h index 91d72c4..8d13f5e 100644 --- a/gazebo/flix.h +++ b/gazebo/flix.h @@ -10,8 +10,6 @@ #include "Arduino.h" #include "wifi.h" -#define WIFI_ENABLED 1 - extern float t, dt; extern float controlRoll, controlPitch, controlYaw, controlThrottle, controlMode; extern Vector rates; @@ -73,3 +71,4 @@ void calibrateAccel() { print("Skip accel calibrating\n"); }; void printIMUCalibration() { print("cal: N/A\n"); }; void printIMUInfo() {}; void printWiFiInfo() {}; +void configWiFi(bool, const char*, const char*) { print("Skip WiFi config\n"); };