La primer opción fue escanear el tráfico directamente de la red e ir contando el tamaño de los datos transmitidos. Sin embargo, esta solución no funciono, ya que al estar conectados al ruteador, sólo recibimos paquetes que están destinados al Raspeberry o paquetes broadcast.
La segunda opción fue conectarse directamente al ruteador y extraer la información del tráfico del día. Para ello, primero nos conectamos manualmente al ruteador y monitoreamos el tráfico usando Wireshark, esto nos permitió aprender que el ruteador usa autenticación básica y que la página que contiene la información del tráfico se llama traffic.htm. Esto también nos ayudo a inspeccionar el contenido de traffic.htm y observar que una variable de javascript contiene la información que necesitamos.
Con toda esta información, la lógica del programa es muy sencilla.
- Inicializar IO y prender todos los LEDs durante 3 segundos para diagnosticar LEDs en mal estado.
- Ciclo infinito:
- Obtener traffic.htm del ruteador
- Extraer tráfico del día
- Desplegar en formato binario usando los LEDs el tráfico del día en cientos de MB
El código en python es el siguiente:
import urllib2 import re import base64 import time import RPi.GPIO as GPIO def get_router_page(): theurl = 'http://192.168.1.1/traffic.htm' username = 'admin' password = 'your_password' req = urllib2.Request(theurl) # First try without username/password try: handle = urllib2.urlopen(req) except IOError, e: pass else: return handle.read() # Now try with authentication base64string = base64.encodestring( '%s:%s' % (username, password))[:-1] authheader = "Basic %s" % base64string req.add_header("Authorization", authheader) try: handle = urllib2.urlopen(req) except IOError, e: print e return None return handle.read() def get_traffic_in_MB(page): for line in page.split('\n'): match = re.search( r'\s*var\s*traffic_today_total\s*=\s*"(.*)"\s*;\s*', line) if match: return match.group(1).replace(',','') return None def is_bit_set(value, bit): mask = 1 << bit return (value & mask) def display_traffic(traffic_MB): traffic_in_100_MB = int(float(traffic_MB) / 100) if traffic_in_100_MB > 31: traffic_in_100_MB = 31 print traffic_in_100_MB GPIO.output(LED_0_PIN,is_bit_set(traffic_in_100_MB,0)) GPIO.output(LED_1_PIN,is_bit_set(traffic_in_100_MB,1)) GPIO.output(LED_2_PIN,is_bit_set(traffic_in_100_MB,2)) GPIO.output(LED_3_PIN,is_bit_set(traffic_in_100_MB,3)) GPIO.output(LED_4_PIN,is_bit_set(traffic_in_100_MB,4)) def init_IO(): # Init outputs GPIO.setmode(GPIO.BCM) GPIO.setup(LED_0_PIN,GPIO.OUT) GPIO.setup(LED_1_PIN,GPIO.OUT) GPIO.setup(LED_2_PIN,GPIO.OUT) GPIO.setup(LED_3_PIN,GPIO.OUT) GPIO.setup(LED_4_PIN,GPIO.OUT) # Test all leds GPIO.output(LED_0_PIN,True) GPIO.output(LED_1_PIN,True) GPIO.output(LED_2_PIN,True) GPIO.output(LED_3_PIN,True) GPIO.output(LED_4_PIN,True) time.sleep(3) GPIO.output(LED_0_PIN,False) GPIO.output(LED_1_PIN,False) GPIO.output(LED_2_PIN,False) GPIO.output(LED_3_PIN,False) GPIO.output(LED_4_PIN,False) LED_0_PIN = 23 LED_1_PIN = 24 LED_2_PIN = 25 LED_3_PIN = 8 LED_4_PIN = 7 init_IO() while True: page = get_router_page() if page is not None: traffic = get_traffic_in_MB(page) if traffic is not None: display_traffic(traffic) time.sleep(60) GPIO.cleanup()
Saludos.