Introduccion

En este proyecto realizaremos un manejo de parametros de los rayos y truenos de la página web Blitzortung a traves de un web socket.
Lo primero es acceder a la web, para ver el websocket que utilizaremos. Presionando la tecla abriremos el panel de desarrollador y nos dirigiremos al apartado “Network” “Socket”.

Socket

Desde aquí podremos identificar en la seccion “Name” el websocket que vamos a utilizar.
WEB SOCKET-> “wss://ws1.blitzortung.org/”.
Veremos que esta constantemente recibiendo informacion, sin embargo podremos ver que está cifrada.

Investigando la forma de trabajo del websocket identificaremos el metodo que utiliza para iniciar la conexion. Como requisito necesitará que le pasemos en formato JSON el contenido {“a”:111}.
Una vez se ha realizado comenzará a enviar todos los eventos.
Bien, con un poco de codigo simple relacionado con Web-Sockets seremos capaces de recibir esta informacion. Ahora el problema es que esta obfuscada.
Buscando un poco por internet y analizando el formato podremos descubrir que se trata de obfuscacion LZW.

Procederemos a generar un codigo de python que maneje toda la informacion y sea capaz de deobfuscar los datos que recibimos para su tratamiento.

Utilizaremos las librerias websocket y json.

La funcion de deobfuscamiento será la siguiente:

def decoder(encoded_str):
    e = {}
    d = list(encoded_str)
    c = d[0]
    f = c
    g = [c]
    h = 256
    o = h

    for i in range(1, len(d)):
        a = ord(d[i])
        if a < h:
            a_str = d[i]
        elif a in e:
            a_str = e[a]
        else:
            a_str = f + c

        g.append(a_str)
        c = a_str[0]
        e[o] = f + c
        o += 1
        f = a_str
    return ''.join(g).encode('latin1')

Nuestro codigo ha de tener una funcion para mostrar la información de una manera visible, así comprobaremos que estamos tratando con los datos correctos.
Para ello mostraremos tanto el codigo obfuscado y el deobfuscado.

def on_message(ws, message):
    print("Mensaje recibido (texto):", message[:100], "...")  # Mostrar un resumen

    # Aplicar LZW decoder al mensaje completo (texto plano recibido)
    decoded_bytes = decoder(message)
    try:
        decoded_text = decoded_bytes.decode('utf-8')
    except UnicodeDecodeError:
        decoded_text = decoded_bytes.decode('latin1')

    print("Texto decodificado:", decoded_text[:200], "...")  # Mostrar un resumen

    try:
        data = json.loads(decoded_text)
        print("Datos JSON parseados correctamente:", data)
    except json.JSONDecodeError:
        print("No se pudo parsear JSON después de decodificar")

Una vez seamos capaces de obtener los datos decodificados podremos empezar a trabajar con ellos! Creando dos contenedores de Docker (Mysql y Grafana) le daremos forma y vida a estos datos obtenidos.

MySQL

  • sudo docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=<CONTRASEÑA> –name=mysql mysql

Grafana

  • sudo docker run -d -p 3000:3000 –name=grafana grafana/grafana-enterprise

Partiremos de una instalacion predefinida con usuario admin en MySQL y una configuracion por defecto en Grafana.

Para la configuracion de la base de datos cargaremos este script al contenedor de docker a traves de “Mysql-Client”.

comandos.sql:

DROP DATABASE IF EXISTS thunder;
CREATE DATABASE thunder;
USE thunder;

DROP TABLE IF EXISTS main_data;
CREATE TABLE main_data (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  time BIGINT,
  lat DOUBLE,
  lon DOUBLE,
  alt INT,
  pol INT,
  mds INT,
  mcg INT,
  status INT,
  region INT,
  delay FLOAT,
  lonc INT,
  latc INT
);
DROP TABLE IF EXISTS signals;
CREATE TABLE signals (
  id BIGINT AUTO_INCREMENT PRIMARY KEY,
  main_data_id BIGINT,
  sta INT,
  time BIGINT,
  lat DOUBLE,
  lon DOUBLE,
  alt INT,
  status INT,
  FOREIGN KEY (main_data_id) REFERENCES main_data(id)
);

Lo cargaremos con:

mysql -h <IP> -u root -p -vvv < comandos.sql

Donde sera la direccion IP del contenedor de Docker.

Una vez configurada la base de datos accederemos al panel de Grafana desde Data Sources -> Add New Data Source -> Mysql
Completaremos los campos necesarios con las credenciales indicadas.

Grafana

Nota: En caso de no disponer de un certificado TLS/SSL marcaremos la casilla que deshabilita la conexion segura.

Una vez conectada la base de datos MySql con Grafana procederemos a crear la Dashboard que muestre los datos.

Nos dirigiremos al apartado “Dashboards” y crearemos una nueva desde el boton “New Dashboard” y “Add Visualization”.

Nos solicitará un Data Source e introduciremos el que acabamos de crear con MySql.

Tras desplegarse correctamente deberemos crear una consulta que sea capaz de recoger los datos recibidos y mostrarlos en la grafica.
Ejemplos:

SELECT
  FROM_UNIXTIME(time / 1000000000) AS time, -- si tu tiempo está en nanosegundos, ajusta la conversión
  lat,
  lon,
  alt
FROM main_data
ORDER BY time DESC
LIMIT 1000;
SELECT
  FROM_UNIXTIME(s.time / 1000000000) AS time,
  s.sta,
  s.lat,
  s.lon,
  s.alt,
  s.status
FROM signals s
JOIN main_data m ON s.main_data_id = m.id
ORDER BY s.time DESC
LIMIT 1000;

Lanzando las consultas podremos ver que empiezan a mostrarse los datos en el Panle de Visualización.

Grafica

Enhorabuena!

Hemos conseguido almacenar una gran cantidad de datos y una visualización rápida y efectiva de ellos.
Si eres un apasionado de los Truenos y Rayos es tu momento!

Conclusión

A traves de un websocket podemos recibir muchisima información, con su adecuado manejo seremos capaces de una infinidad de cosas.
Docker nos permite utilizar un entorno super optimizado y orientado a tareas especificas con su sistema de contenedores. Gracias a esto podemos desplegar diferentes entornos sin necesidad de sobrecargar nuestro equipo principal.
Grafana es una herramienta muy potente de visualización de datos que de manera organizada y personalizada nos presentará la informacion que seamos capaces de cargar en todos los entornos de los que dispone.

Hasta la vista Hackers.
Kerneloop.