ConnectivityManager
MicroPythonOS provides a connectivity monitoring service called ConnectivityManager that tracks network status and notifies apps when connectivity changes. It's inspired by Android's ConnectivityManager API.
Overview
ConnectivityManager provides:
- Connectivity monitoring - Periodic checks of network status
- Callback notifications - Get notified when connectivity changes
- Singleton pattern - Single instance shared across all apps
- Platform-agnostic - Works on ESP32 and desktop
- Android-like API - Familiar patterns for Android developers
Quick Start
Checking Connectivity
from mpos import ConnectivityManager
# Get the singleton instance
cm = ConnectivityManager.get()
# Check if online (has internet)
if cm.is_online():
print("Connected to internet")
else:
print("No internet connection")
# Check if WiFi is connected (local network)
if cm.is_wifi_connected():
print("WiFi connected")
Registering for Connectivity Changes
from mpos import Activity, ConnectivityManager
class MyActivity(Activity):
def onCreate(self):
self.cm = ConnectivityManager.get()
def onResume(self, screen):
super().onResume(screen)
# Register for connectivity changes
self.cm.register_callback(self.on_connectivity_changed)
# Update UI with current status
self.update_status(self.cm.is_online())
def onPause(self, screen):
super().onPause(screen)
# Unregister when activity is paused
self.cm.unregister_callback(self.on_connectivity_changed)
def on_connectivity_changed(self, is_online):
"""Called when connectivity status changes."""
if is_online:
print("Now online!")
self.fetch_data()
else:
print("Gone offline")
self.show_offline_message()
def update_status(self, is_online):
status = "Online" if is_online else "Offline"
self.status_label.set_text(status)
Waiting for Connectivity
from mpos import ConnectivityManager
def download_with_wait():
cm = ConnectivityManager.get()
# Wait up to 30 seconds for connectivity
if cm.wait_until_online(timeout=30):
print("Connected! Starting download...")
# Proceed with download
else:
print("Timeout waiting for connection")
Common Patterns
Network-Aware App
from mpos import Activity, ConnectivityManager, TaskManager, DownloadManager
import lvgl as lv
class NewsReaderActivity(Activity):
def onCreate(self):
self.screen = lv.obj()
self.cm = ConnectivityManager.get()
# Status indicator
self.status_icon = lv.label(self.screen)
self.status_icon.align(lv.ALIGN.TOP_RIGHT, -10, 10)
# Content area
self.content = lv.label(self.screen)
self.content.set_width(280)
self.content.align(lv.ALIGN.CENTER, 0, 0)
self.setContentView(self.screen)
def onResume(self, screen):
super().onResume(screen)
self.cm.register_callback(self.on_connectivity_changed)
self.update_ui()
def onPause(self, screen):
super().onPause(screen)
self.cm.unregister_callback(self.on_connectivity_changed)
def on_connectivity_changed(self, is_online):
self.update_ui()
if is_online:
TaskManager.create_task(self.fetch_news())
def update_ui(self):
if self.cm.is_online():
self.status_icon.set_text(lv.SYMBOL.WIFI)
else:
self.status_icon.set_text(lv.SYMBOL.WARNING)
self.content.set_text("No internet connection")
async def fetch_news(self):
data = await DownloadManager.download_url(
"https://api.example.com/news"
)
if data:
self.content.set_text(data.decode())
Retry on Reconnect
from mpos import ConnectivityManager, TaskManager, DownloadManager
class SyncManager:
def __init__(self):
self.cm = ConnectivityManager.get()
self.pending_sync = False
self.cm.register_callback(self.on_connectivity_changed)
def sync_data(self):
if self.cm.is_online():
TaskManager.create_task(self._do_sync())
else:
# Mark for retry when online
self.pending_sync = True
print("Offline - sync queued")
def on_connectivity_changed(self, is_online):
if is_online and self.pending_sync:
print("Back online - retrying sync")
self.pending_sync = False
TaskManager.create_task(self._do_sync())
async def _do_sync(self):
success = await DownloadManager.download_url(
"https://api.example.com/sync",
# ... sync data
)
if not success:
self.pending_sync = True
Conditional Feature Loading
from mpos import ConnectivityManager
class AppStoreActivity(Activity):
def onCreate(self):
self.cm = ConnectivityManager.get()
if self.cm.is_online():
# Load full app store with remote data
self.load_remote_apps()
else:
# Show only installed apps
self.load_local_apps()
self.show_offline_banner()
API Reference
Getting the Instance
ConnectivityManager.get()
Get the singleton ConnectivityManager instance.
Returns:
- ConnectivityManager - The singleton instance
Example:
cm = ConnectivityManager.get()
Note: The first call initializes the manager and starts periodic connectivity checks.
Connectivity Status
is_online()
Check if the device has internet connectivity.
Returns:
- bool - True if online, False otherwise
Example:
if cm.is_online():
print("Internet available")
is_wifi_connected()
Check if WiFi is connected (local network).
Returns:
- bool - True if WiFi connected, False otherwise
Note: A device can be WiFi-connected but not online (e.g., no internet on the network).
Example:
if cm.is_wifi_connected():
print("WiFi connected")
wait_until_online(timeout=60)
Block until the device is online or timeout expires.
Parameters:
- timeout (int) - Maximum seconds to wait (default: 60)
Returns:
- bool - True if online, False if timeout expired
Example:
if cm.wait_until_online(timeout=30):
print("Connected!")
else:
print("Timeout - still offline")
Callback Management
register_callback(callback)
Register a callback to be notified of connectivity changes.
Parameters:
- callback (callable) - Function that takes one boolean parameter (is_online)
Example:
def on_change(is_online):
print(f"Connectivity: {'online' if is_online else 'offline'}")
cm.register_callback(on_change)
unregister_callback(callback)
Unregister a previously registered callback.
Parameters:
- callback (callable) - The callback to remove
Example:
cm.unregister_callback(on_change)
Important: Always unregister callbacks when your activity is paused or destroyed to prevent memory leaks and stale references.
Monitoring Behavior
ConnectivityManager uses a periodic timer to check connectivity:
| Setting | Value |
|---|---|
| Check interval | 8 seconds |
| Timer ID | 1 (Timer 0 is used by task_handler) |
| Check method | wlan.isconnected() |
How Connectivity is Determined
- ESP32/Hardware:
- Uses
network.WLAN(network.STA_IF).isconnected() -
Returns
Trueif WiFi is connected to an access point -
Desktop/Linux:
- No network module available
- Always reports as "connected" for testing
Callback Timing
- Callbacks are only called when status changes
- Initial status is checked at startup (no callback)
- Callbacks receive
Truewhen going online,Falsewhen going offline
# Example callback sequence:
# Boot: offline (no callback - initial state)
# WiFi connects: callback(True)
# WiFi disconnects: callback(False)
# WiFi reconnects: callback(True)
Platform Differences
| Platform | Behavior |
|---|---|
| ESP32 | Real WiFi monitoring via network module |
| Desktop | Always reports online (no network module) |
Desktop Testing
On desktop, ConnectivityManager always reports as connected:
cm = ConnectivityManager.get()
print(cm.is_online()) # Always True on desktop
print(cm.is_wifi_connected()) # Always True on desktop
This allows apps to be tested without actual network connectivity.
Troubleshooting
Callbacks Not Being Called
Symptom: Registered callback never fires
Possible causes: 1. Connectivity never changes 2. Callback was unregistered 3. Callback raises exception (silently caught)
Solution:
# Check current status
print(f"Current status: {cm.is_online()}")
# Verify callback is registered
print(f"Callbacks: {len(cm.callbacks)}")
# Ensure callback doesn't raise exceptions
def safe_callback(is_online):
try:
# Your logic here
pass
except Exception as e:
print(f"Callback error: {e}")
cm.register_callback(safe_callback)
Memory Leak from Callbacks
Symptom: Memory usage grows over time
Cause: Callbacks not unregistered when activity destroyed
Solution:
class MyActivity(Activity):
def onResume(self, screen):
super().onResume(screen)
self.cm = ConnectivityManager.get()
self.cm.register_callback(self.on_change)
def onPause(self, screen):
super().onPause(screen)
# Always unregister!
self.cm.unregister_callback(self.on_change)
Status Always Shows Online
Symptom: is_online() returns True even when disconnected
Cause: Running on desktop (no network module)
Solution: This is expected behavior on desktop. Test on real hardware for accurate connectivity status.
Timer Conflict
Symptom: Strange behavior with other timers
Cause: ConnectivityManager uses Timer(1)
Solution: Use different timer IDs in your app:
from machine import Timer
# ConnectivityManager uses Timer(1)
# task_handler uses Timer(0)
# Use Timer(2) or higher for your app
my_timer = Timer(2)
Integration with WifiService
ConnectivityManager works alongside WifiService:
- WifiService - Manages WiFi connections (connect, disconnect, scan)
- ConnectivityManager - Monitors connection status and notifies apps
from mpos import WifiService, ConnectivityManager
# WifiService for connection management
WifiService.attempt_connecting("MyNetwork", "password")
# ConnectivityManager for status monitoring
cm = ConnectivityManager.get()
cm.register_callback(lambda online: print(f"Status: {online}"))
Implementation Details
Location: MicroPythonOS/internal_filesystem/lib/mpos/net/connectivity_manager.py
Pattern: Singleton with periodic timer
Key features:
- _instance - Class-level singleton instance
- callbacks - List of registered callback functions
- _check_timer - Machine Timer for periodic checks
- _is_online - Cached online status
Dependencies:
- network module (MicroPython, optional)
- machine.Timer - Periodic connectivity checks
- requests / usocket - Imported but not currently used for connectivity checks
See Also
- WifiService - WiFi connection management
- DownloadManager - HTTP downloads
- TaskManager - Async task management