Improve wifi handling

This commit is contained in:
Thomas Farstrike
2025-11-24 18:52:49 +01:00
parent 61379985e9
commit f4bd4d0a2b
3 changed files with 79 additions and 19 deletions
@@ -87,16 +87,11 @@ def read_raw_adc(force_refresh=False):
except ImportError:
pass
# Check if WiFi operations are in progress
if WifiService and WifiService.wifi_busy:
raise RuntimeError("Cannot read battery voltage: WifiService is busy")
# Disable WiFi for ADC2 reading
wifi_was_connected = False
# Temporarily disable WiFi for ADC2 reading
was_connected = False
if needs_wifi_disable and WifiService:
wifi_was_connected = WifiService.is_connected()
WifiService.wifi_busy = True
WifiService.disconnect()
# This will raise RuntimeError if WiFi is already busy
was_connected = WifiService.temporarily_disable()
time.sleep(0.05) # Brief delay for WiFi to fully disable
try:
@@ -113,14 +108,7 @@ def read_raw_adc(force_refresh=False):
finally:
# Re-enable WiFi (only if we disabled it)
if needs_wifi_disable and WifiService:
WifiService.wifi_busy = False
if wifi_was_connected:
# Trigger reconnection in background thread
try:
import _thread
_thread.start_new_thread(WifiService.auto_connect, ())
except Exception as e:
print(f"battery_voltage: Failed to start reconnect thread: {e}")
WifiService.temporarily_enable(was_connected)
def read_battery_voltage(force_refresh=False):
@@ -260,9 +260,24 @@ indev.enable(True) # NOQA
# Battery voltage ADC measuring
# NOTE: GPIO13 is on ADC2, which requires WiFi to be disabled during reading on ESP32-S3.
# battery_voltage.py handles this automatically: disables WiFi, reads ADC, reconnects WiFi.
# Readings are cached for 30 seconds to minimize WiFi interruptions.
import mpos.battery_voltage
mpos.battery_voltage.init_adc(13, 3.3 * 2 / 4095)
"""
best fit on battery power:
2482 is 4.180
2470 is 4.170
2457 is 4.147
2433 is 4.109
2429 is 4.102
2393 is 4.044
2369 is 4.000
2343 is 3.957
2319 is 3.916
2269 is 3.831
"""
def adc_to_voltage(adc_value):
return (-0.0016237 * adc_value + 8.2035)
#mpos.battery_voltage.init_adc(13, adc_to_voltage)
mpos.battery_voltage.init_adc(13, 1/616) # simple scaling has an error of ~0.01V vs the adc_to_voltage() method
import mpos.sdcard
mpos.sdcard.init(spi_bus, cs_pin=14)
@@ -197,6 +197,63 @@ class WifiService:
WifiService.wifi_busy = False
print("WifiService: Auto-connect thread finished")
@staticmethod
def temporarily_disable(network_module=None):
"""
Temporarily disable WiFi for operations that require it (e.g., ESP32-S3 ADC2).
This method sets wifi_busy flag and disconnects WiFi if connected.
Caller must call temporarily_enable() in a finally block.
Args:
network_module: Network module for dependency injection (testing)
Returns:
bool: True if WiFi was connected before disabling, False otherwise
Raises:
RuntimeError: If WiFi operations are already in progress
"""
if WifiService.wifi_busy:
raise RuntimeError("Cannot disable WiFi: WifiService is already busy")
# Check actual connection status BEFORE setting wifi_busy
was_connected = False
if HAS_NETWORK_MODULE or network_module:
try:
net = network_module if network_module else network
wlan = net.WLAN(net.STA_IF)
was_connected = wlan.isconnected()
except Exception as e:
print(f"WifiService: Error checking connection: {e}")
# Now set busy flag and disconnect
WifiService.wifi_busy = True
WifiService.disconnect(network_module=network_module)
return was_connected
@staticmethod
def temporarily_enable(was_connected, network_module=None):
"""
Re-enable WiFi after temporary disable operation.
Must be called in a finally block after temporarily_disable().
Args:
was_connected: Return value from temporarily_disable()
network_module: Network module for dependency injection (testing)
"""
WifiService.wifi_busy = False
# Only reconnect if WiFi was connected before we disabled it
if was_connected:
try:
import _thread
_thread.start_new_thread(WifiService.auto_connect, ())
except Exception as e:
print(f"WifiService: Failed to start reconnect thread: {e}")
@staticmethod
def is_connected(network_module=None):
"""