Created
October 21, 2025 14:12
-
-
Save ozankaraali/6a6d7d082f6d26528e5b6a31d02af890 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env python3 | |
| """ | |
| Enable European cellular bands and scan for networks | |
| Based on Quectel RM502Q-AE capabilities | |
| """ | |
| import serial | |
| import time | |
| from datetime import datetime | |
| PORT = '/dev/ttyUSB2' | |
| BAUDRATE = 115200 | |
| # European band configuration | |
| # LTE: Add bands 3, 7, 20, 28 (common in Europe) to existing 2, 41, 66 | |
| EUROPEAN_LTE_BANDS = "1:2:3:4:5:7:8:12:13:18:19:20:25:26:28:29:30:32:34:38:39:40:41:42:43:46:48:66:71" | |
| # 5G: Keep existing + add common European bands | |
| EUROPEAN_5G_BANDS = "1:2:3:5:7:8:12:20:25:28:38:40:41:48:66:71:77:78:79" | |
| # NSA 5G: Similar to above | |
| EUROPEAN_NSA_BANDS = "1:2:3:5:7:8:12:20:25:28:38:40:41:48:66:71:77:78:79" | |
| def send_at_command(ser, command, timeout=5, description=""): | |
| """Send AT command and return response""" | |
| if description: | |
| print(f"\n[{description}]") | |
| print(f">>> {command}") | |
| ser.reset_input_buffer() | |
| ser.write(f"{command}\r\n".encode()) | |
| time.sleep(0.5) | |
| response = "" | |
| start_time = time.time() | |
| while time.time() - start_time < timeout: | |
| if ser.in_waiting: | |
| chunk = ser.read(ser.in_waiting).decode('utf-8', errors='ignore') | |
| response += chunk | |
| print(chunk, end='', flush=True) | |
| if 'OK' in response or 'ERROR' in response: | |
| break | |
| time.sleep(0.2) | |
| if time.time() - start_time >= timeout: | |
| print(f"\n[TIMEOUT after {timeout}s]") | |
| return response | |
| def main(): | |
| print("="*70) | |
| print("European Band Enabler for Quectel RM502Q-AE") | |
| print(f"Started at: {datetime.now()}") | |
| print("="*70) | |
| try: | |
| ser = serial.Serial(PORT, BAUDRATE, timeout=2) | |
| time.sleep(1) | |
| # Step 1: Show current configuration | |
| print("\n" + "="*70) | |
| print("STEP 1: Current Configuration") | |
| print("="*70) | |
| send_at_command(ser, "AT+QNWPREFCFG=\"lte_band\"", description="Current LTE bands") | |
| send_at_command(ser, "AT+QNWPREFCFG=\"nr5g_band\"", description="Current 5G bands") | |
| send_at_command(ser, "AT+QNWPREFCFG=\"nsa_nr5g_band\"", description="Current NSA 5G bands") | |
| send_at_command(ser, "AT+COPS?", description="Current network") | |
| # Step 2: User confirmation | |
| print("\n" + "="*70) | |
| print("STEP 2: Band Configuration Changes") | |
| print("="*70) | |
| print(f"\nLTE bands will be set to: {EUROPEAN_LTE_BANDS}") | |
| print(f" - Adds European bands: 3, 7, 20, 28") | |
| print(f" - Keeps existing: 2, 41, 66") | |
| print(f"\n5G bands will be set to: {EUROPEAN_5G_BANDS}") | |
| print(f" - Adds European bands: 1, 3, 7, 20, 28") | |
| print(f" - Keeps existing: 41, 77, 78") | |
| response = input("\nProceed with band configuration? (yes/no): ") | |
| if response.lower() != 'yes': | |
| print("Aborted by user") | |
| ser.close() | |
| return | |
| # Step 3: Apply band configuration | |
| print("\n" + "="*70) | |
| print("STEP 3: Applying Band Configuration") | |
| print("="*70) | |
| send_at_command(ser, f"AT+QNWPREFCFG=\"lte_band\",{EUROPEAN_LTE_BANDS}", | |
| timeout=5, description="Setting LTE bands") | |
| send_at_command(ser, f"AT+QNWPREFCFG=\"nr5g_band\",{EUROPEAN_5G_BANDS}", | |
| timeout=5, description="Setting 5G bands") | |
| send_at_command(ser, f"AT+QNWPREFCFG=\"nsa_nr5g_band\",{EUROPEAN_NSA_BANDS}", | |
| timeout=5, description="Setting NSA 5G bands") | |
| # Step 4: Verify new configuration | |
| print("\n" + "="*70) | |
| print("STEP 4: Verifying New Configuration") | |
| print("="*70) | |
| send_at_command(ser, "AT+QNWPREFCFG=\"lte_band\"", description="New LTE bands") | |
| send_at_command(ser, "AT+QNWPREFCFG=\"nr5g_band\"", description="New 5G bands") | |
| send_at_command(ser, "AT+QNWPREFCFG=\"nsa_nr5g_band\"", description="New NSA 5G bands") | |
| # Step 5: Disconnect and scan | |
| print("\n" + "="*70) | |
| print("STEP 5: Network Scan with New Band Configuration") | |
| print("="*70) | |
| response = input("\nProceed with network scan? (This will disconnect temporarily) (yes/no): ") | |
| if response.lower() != 'yes': | |
| print("Scan skipped. Bands are configured but staying on current network.") | |
| ser.close() | |
| return | |
| send_at_command(ser, "AT+COPS=2", timeout=10, description="Disconnect from network") | |
| time.sleep(2) | |
| print("\nScanning for networks (up to 2 minutes)...") | |
| scan_result = send_at_command(ser, "AT+COPS=?", timeout=120, description="Network scan") | |
| # Save scan results | |
| timestamp = datetime.now().strftime('%Y%m%d_%H%M%S') | |
| filename = f"network_scan_european_{timestamp}.txt" | |
| with open(filename, 'w') as f: | |
| f.write(f"Network Scan with European Bands - {datetime.now()}\n") | |
| f.write("="*70 + "\n\n") | |
| f.write(scan_result) | |
| print(f"\nScan results saved to: {filename}") | |
| # Step 6: Reconnect | |
| print("\n" + "="*70) | |
| print("STEP 6: Reconnecting to Network") | |
| print("="*70) | |
| send_at_command(ser, "AT+COPS=0", timeout=30, description="Auto network selection") | |
| time.sleep(5) | |
| for i in range(6): | |
| send_at_command(ser, "AT+COPS?", timeout=5, description=f"Connection status {i+1}/6") | |
| time.sleep(3) | |
| ser.close() | |
| print("\n" + "="*70) | |
| print("Complete!") | |
| print("="*70) | |
| except Exception as e: | |
| print(f"\nERROR: {e}") | |
| import traceback | |
| traceback.print_exc() | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment