Add command BSSid[1|2] [0|1|11:22:33:44:55:66] to select fixed WiFi Access Point disabling SetOption56 and SetOption57 (#24394)

This commit is contained in:
Theo Arends
2026-06-21 17:43:52 +02:00
parent a27df15739
commit 5ba66d80c3
7 changed files with 65 additions and 10 deletions
+1
View File
@@ -8,6 +8,7 @@ All notable changes to this project will be documented in this file.
- Serial console support for Backspace when enabling `#define USE_SERIAL_BACKSPACE` (#24830)
- Build copy firmware artifacts with ELF-extracted build timestamp (opt-in) (#24794)
- Enhance Matter plugin functionality for On/Off control and add support for Global Scene Control and related commands (#24854)
- Command `BSSid[1|2] [0|1|11:22:33:44:55:66]` to select fixed WiFi Access Point disabling `SetOption56` and `SetOption57` (#24394)
### Breaking Changed
+1
View File
@@ -117,6 +117,7 @@ The latter links can be used for OTA upgrades too like ``OtaUrl https://ota.tasm
- Build copy firmware artifacts with ELF-extracted build timestamp (opt-in) [#24794](https://github.com/arendst/Tasmota/issues/24794)
- Command `SetOption [0..2]` to display SetOption values
- Command `WcResolution 0..24` increasing camera max resolution from 14 to 24
- Command `BSSid[1|2] [0|1|11:22:33:44:55:66]` to select fixed WiFi Access Point disabling `SetOption56` and `SetOption57` [#24394](https://github.com/arendst/Tasmota/issues/24394)
- Support for hostname generation using single-specifier Format() patterns [#24731](https://github.com/arendst/Tasmota/issues/24731)
- Support for Modbus RX Enable GPIO [#24726](https://github.com/arendst/Tasmota/issues/24726)
- Support for multi-byte chars like emojis (💡) in light device toggle buttons [#24482](https://github.com/arendst/Tasmota/issues/24482)
+1
View File
@@ -346,6 +346,7 @@
#define D_CMND_IPADDRESS "IPAddress"
#define D_CMND_NTPSERVER "NtpServer"
#define D_CMND_AP "Ap"
#define D_CMND_BSSID "BSSId"
#define D_CMND_SSID "SSId"
#define D_CMND_PASSWORD "Password"
#define D_CMND_HOSTNAME "Hostname"
+1
View File
@@ -508,6 +508,7 @@ enum SettingsTextIndex { SET_OTAURL,
SET_INFLUXDB_HOST, SET_INFLUXDB_PORT, SET_INFLUXDB_ORG, SET_INFLUXDB_TOKEN, SET_INFLUXDB_BUCKET, SET_INFLUXDB_RP,
SET_CANVAS,
SET_TELEGRAM_FINGERPRINT,
SET_APBSSID1, SET_APBSSID2, // MAX_SSIDS
SET_MAX, // limit of texts stored in Settings
// Index above are not stored in Settings and should be handled specifically in SettingText()
SET_BUTTON17, SET_BUTTON18, SET_BUTTON19, SET_BUTTON20, SET_BUTTON21, SET_BUTTON22, SET_BUTTON23, SET_BUTTON24,
+6
View File
@@ -78,12 +78,18 @@
#ifndef STA_PASS1
#define STA_PASS1 "" // [Password1] Wi-Fi password
#endif
#ifndef AP_BSSID1
#define AP_BSSID1 "" // [BSsid1] Wi-Fi desired AP BSSID to connect to
#endif
#ifndef STA_SSID2
#define STA_SSID2 "" // [Ssid2] Optional alternate AP Wi-Fi SSID
#endif
#ifndef STA_PASS2
#define STA_PASS2 "" // [Password2] Optional alternate AP Wi-Fi password
#endif
#ifndef AP_BSSID2
#define AP_BSSID2 "" // [BSsid2] Wi-Fi desired AP BSSID to connect to
#endif
#ifndef WIFI_AP_PASSPHRASE
#define WIFI_AP_PASSPHRASE "" // AccessPoint passphrase. For WPA2 min 8 char, for open use "" (max 63 char).
#endif
+18 -2
View File
@@ -30,7 +30,7 @@ const char kTasmotaCommands[] PROGMEM = "|" // No prefix
D_CMND_MODULE "|" D_CMND_MODULES "|" D_CMND_GPIO "|" D_CMND_GPIOREAD "|" D_CMND_GPIOS "|" D_CMND_TEMPLATE "|" D_CMND_PWM "|" D_CMND_PWMFREQUENCY "|" D_CMND_PWMRANGE "|"
D_CMND_BUTTONDEBOUNCE "|" D_CMND_SWITCHDEBOUNCE "|" D_CMND_SYSLOG "|" D_CMND_LOGHOST "|" D_CMND_LOGPORT "|"
D_CMND_SERIALBUFFER "|" D_CMND_SERIALSEND "|" D_CMND_BAUDRATE "|" D_CMND_SERIALCONFIG "|" D_CMND_SERIALDELIMITER "|"
D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_WIFI "|" D_CMND_DNSTIMEOUT "|"
D_CMND_IPADDRESS "|" D_CMND_NTPSERVER "|" D_CMND_AP "|" D_CMND_BSSID "|" D_CMND_SSID "|" D_CMND_PASSWORD "|" D_CMND_HOSTNAME "|" D_CMND_WIFICONFIG "|" D_CMND_WIFI "|" D_CMND_DNSTIMEOUT "|"
D_CMND_DEVICENAME "|" D_CMND_FN "|" D_CMND_FRIENDLYNAME "|" D_CMND_SWITCHMODE "|" D_CMND_INTERLOCK "|" D_CMND_TELEPERIOD "|" D_CMND_RESET "|"
D_CMND_TIME "|" D_CMND_TIMEZONE "|" D_CMND_TIMESTD "|" D_CMND_TIMEDST "|" D_CMND_ALTITUDE "|"
D_CMND_LEDPOWER "|" D_CMND_LEDSTATE "|" D_CMND_LEDMASK "|" D_CMND_LEDPWM_ON "|" D_CMND_LEDPWM_OFF "|" D_CMND_LEDPWM_MODE "|"
@@ -79,7 +79,7 @@ void (* const TasmotaCommand[])(void) PROGMEM = {
&CmndModule, &CmndModules, &CmndGpio, &CmndGpioRead, &CmndGpios, &CmndTemplate, &CmndPwm, &CmndPwmfrequency, &CmndPwmrange,
&CmndButtonDebounce, &CmndSwitchDebounce, &CmndSyslog, &CmndLoghost, &CmndLogport,
&CmndSerialBuffer, &CmndSerialSend, &CmndBaudrate, &CmndSerialConfig, &CmndSerialDelimiter,
&CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndWifi, &CmndDnsTimeout,
&CmndIpAddress, &CmndNtpServer, &CmndAp, &CmndBSsid, &CmndSsid, &CmndPassword, &CmndHostname, &CmndWifiConfig, &CmndWifi, &CmndDnsTimeout,
&CmndDevicename, &CmndFriendlyname, &CmndFriendlyname, &CmndSwitchMode, &CmndInterlock, &CmndTeleperiod, &CmndReset,
&CmndTime, &CmndTimezone, &CmndTimeStd, &CmndTimeDst, &CmndAltitude,
&CmndLedPower, &CmndLedState, &CmndLedMask, &CmndLedPwmOn, &CmndLedPwmOff, &CmndLedPwmMode,
@@ -2475,6 +2475,22 @@ void CmndAp(void)
Response_P(S_JSON_COMMAND_NVALUE_SVALUE, XdrvMailbox.command, Settings->sta_active +1, EscapeJSONString(SettingsText(SET_STASSID1 + Settings->sta_active)).c_str());
}
void CmndBSsid(void) {
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) {
if (!XdrvMailbox.usridx) {
ResponseCmndAll(SET_APBSSID1, MAX_SSIDS);
} else {
if ((Shortcut() < 2) || (17 == XdrvMailbox.data_len)) { // Valid BSSID = 18:E8:29:CA:17:C1
SettingsUpdateText(SET_APBSSID1 + XdrvMailbox.index -1,
(SC_CLEAR == Shortcut()) ? "" : (SC_DEFAULT == Shortcut()) ? (1 == XdrvMailbox.index) ? AP_BSSID1 : AP_BSSID2 : XdrvMailbox.data);
Settings->sta_active = XdrvMailbox.index -1;
TasmotaGlobal.restart_flag = 2;
}
ResponseCmndIdxChar(SettingsText(SET_APBSSID1 + XdrvMailbox.index -1));
}
}
}
void CmndSsid(void)
{
if ((XdrvMailbox.index > 0) && (XdrvMailbox.index <= MAX_SSIDS)) {
+37 -8
View File
@@ -410,22 +410,49 @@ void WifiBegin(uint8_t flag, uint8_t channel) {
}
if (Settings->ipv4_address[0]) {
// AddLog(LOG_LEVEL_INFO, ">>>1: Wifi Config DNS %_I %_I", Settings->ipv4_address[3], Settings->ipv4_address[4]);
WiFi.config(Settings->ipv4_address[0], Settings->ipv4_address[1], Settings->ipv4_address[2], Settings->ipv4_address[3], Settings->ipv4_address[4]); // Set static IP
WiFi.config(Settings->ipv4_address[0],
Settings->ipv4_address[1],
Settings->ipv4_address[2],
Settings->ipv4_address[3],
Settings->ipv4_address[4]); // Set static IP
}
WiFi.hostname(TasmotaGlobal.hostname); // ESP8266 needs this here (after WiFi.mode)
char stemp[40] = { 0 };
char stemp[50] = { 0 };
if (channel) {
WiFiHelper::begin(SettingsText(SET_STASSID1 + Settings->sta_active), SettingsText(SET_STAPWD1 + Settings->sta_active), channel, Wifi.bssid);
char bssid_user[16] = " (LastUsed)";
if (strlen(SettingsText(SET_APBSSID1 + Settings->sta_active))) { // Valid BSSID = 18:E8:29:CA:17:C1
char* mac_part = SettingsText(SET_APBSSID1 + Settings->sta_active);
for (uint32_t i = 0; i < 6; i++) {
Wifi.bssid[i] = strtol(mac_part, &mac_part, 16);
mac_part++; // Skip ":"
}
snprintf_P(bssid_user, sizeof(bssid_user), PSTR(" (User)"));
}
else if (Settings->flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's
snprintf_P(bssid_user, sizeof(bssid_user), PSTR(" (Strongest)"));
}
WiFiHelper::begin(SettingsText(SET_STASSID1 + Settings->sta_active),
SettingsText(SET_STAPWD1 + Settings->sta_active),
channel,
Wifi.bssid);
// Add connected BSSID and channel for multi-AP installations
char hex_char[18];
snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s"), channel, ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':'));
snprintf_P(stemp, sizeof(stemp), PSTR(" Channel %d BSSId %s%s"),
channel,
ToHex_P((unsigned char*)Wifi.bssid, 6, hex_char, sizeof(hex_char), ':'),
bssid_user);
} else {
WiFiHelper::begin(SettingsText(SET_STASSID1 + Settings->sta_active), SettingsText(SET_STAPWD1 + Settings->sta_active));
WiFiHelper::begin(SettingsText(SET_STASSID1 + Settings->sta_active),
SettingsText(SET_STAPWD1 + Settings->sta_active));
}
delay(500);
AddLog(LOG_LEVEL_INFO, PSTR(D_LOG_WIFI D_CONNECTING_TO_AP "%d %s%s " D_IN_MODE " %s " D_AS " %s..."),
Settings->sta_active +1, SettingsText(SET_STASSID1 + Settings->sta_active), stemp, WifiGetPhyMode().c_str(), TasmotaGlobal.hostname);
Settings->sta_active +1,
SettingsText(SET_STASSID1 + Settings->sta_active),
stemp,
WifiGetPhyMode().c_str(),
TasmotaGlobal.hostname);
if (Settings->flag5.wait_for_wifi_result) { // SetOption142 - (Wifi) Wait 1 second for wifi connection solving some FRITZ!Box modem issues (1)
WiFi.waitForConnectResult(1000); // https://github.com/arendst/Tasmota/issues/14985
@@ -1235,7 +1262,8 @@ void WifiCheckIp(void) {
}
}
if (Wifi.retry) {
if (Settings->flag3.use_wifi_scan) { // SetOption56 - Scan wifi network at restart for configured AP's
if ((Settings->flag3.use_wifi_scan) && // SetOption56 - Scan wifi network at restart for configured AP's
(!strlen(SettingsText(SET_APBSSID1 + Settings->sta_active)))) { // No BSSID
if (Wifi.retry_init == Wifi.retry) {
Wifi.scan_state = 1; // Select scanned SSID
}
@@ -1300,7 +1328,8 @@ void WifiCheck(uint8_t param)
}
if ((WL_CONNECTED == WiFi.status()) && WifiHasIP() && !Wifi.config_type) {
WifiSetState(1);
if (Settings->flag3.use_wifi_rescan) { // SetOption57 - Scan wifi network every 44 minutes for configured AP's
if ((Settings->flag3.use_wifi_rescan) && // SetOption57 - Scan wifi network every 44 minutes for configured AP's
(!strlen(SettingsText(SET_APBSSID1 + Settings->sta_active)))) { // No BSSID
if (!(TasmotaGlobal.uptime % (60 * WIFI_RESCAN_MINUTES))) {
if (!Wifi.scan_state) { Wifi.scan_state = 2; } // If wifi scan routine is free, use it. Otherwise, wait for next RESCAN TIME
}