Skip to content

Instantly share code, notes, and snippets.

@ozankaraali
Created October 21, 2025 14:12
Show Gist options
  • Select an option

  • Save ozankaraali/6a6d7d082f6d26528e5b6a31d02af890 to your computer and use it in GitHub Desktop.

Select an option

Save ozankaraali/6a6d7d082f6d26528e5b6a31d02af890 to your computer and use it in GitHub Desktop.
#!/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