Comunicaciones descentralizadas (preparación para el fin del mundo)

Me gusta llevar tranquilidad a la gente, para eso, es importante escuchar a Bea Busaniche en Gelatina que nos da una explicación sobre algunas declaraciones apocalípticas que están circulando en relación a la inteligencia artificial.

Más allá de esa tecnología, tenemos otros problemas que pueden dejarnos de un día para el otro sin comunicación: inundaciones, terremotos, cortes de luz generalizados (como el que ocurrió en Buenos Aires el 20/9/2026 [600000 hogares sin luz], en toda la Argentina el 16/6/2019 [apagón histórico en Argentina] o en España el 28/4/2025 [apagón masivo en España y Portugal]), o simplemente la necesidad de comunicarnos en una multitud (con saturación de la red móvil) o en un lugar con poca señal, paseando o haciendo trekking.

Meshtastic

Hace unas semanas mi hermana me envió un video de Instagram que hablaba de un aparatito maravilloso, y luego de escucharlo e investigar un poco más, mi entusiasmo fue cada vez mayor.

Se trata de una red inalámbrica descentralizada formada por nodos que se comunican a través de radio de largo alcance (LoRa, Long Range).

“Están diseñadas para intercambiar mensajes de texto, ubicación y datos sin necesidad de Internet, red eléctrica ni telefonía móvil.

Los dispositivos pueden ser de fabricación casera o comercial, son completamente libres, con firmware libre y gratuito y no requieren licencias para operar.” (Meshtastic Argentina)

Debido a que no utilizan internet, la comunicación se realiza a través de un protocolo de radio (LoRa), pero los dispositivos más económicos no tienen teclado ni pantalla, o tienen una pantalla diminuta, con lo cual los mensajes se envían y reciben a través de una aplicación en el celular. La comunicación entre el celular y el dispositivo se realiza vía Bluetooth.

Cada nodo tiene un alcance limitado: dependiendo de los obstáculos (montañas, edificios, interferencias) puede ir desde 0,5 km a 40 km (más información sobre el alcance).

Sin embargo, gracias a que entre todos los nodos conforman una mesh, una persona puede comunicarse con otra que esté a mayor distancia ya que los mensajes van saltando entre uno y otro nodo. En Buenos Aires nos sugieren una configuración que permita dar hasta 7 saltos, pero si hay muchos nodos se sugiere que sean menos, para no saturar la red.

Esquema de comunicación por saltos: celular-nodo, nodo, nodo, nodo, nodo-celular

Si el tema te entusiasma y tenés ganas de comprarte un aparatito, te cuento que no son caros (por supuesto, esto es relativo a la economía de cada persona). Los más económicos son en este momento los Heltec V3, pero hay que tener muchísimo cuidado (no seas como yo) y ver que uno compra el que abarca la frecuencia de 915 mhz, en el caso de Buenos Aires (en otros lugares o para otros fines se utilizan otras frecuencias).

Cajitas de mis dispositivos Heltec V3 y WiFi LoRa 32 V4

Por otra parte, hay dispositivos con y sin pantalla, con y sin GPS, y algunos con teclado o pantalla touch. En este tema suele ocurrir que es mejor que el dispositivo tenga la menor cantidad de chiches que pueden dejarte sin batería, y por lo tanto, sin comunicación en un corte de luz. Y aún no llegué a eso, pero entiendo que un complemento indispensable sería una batería que se cargue con energía solar.

Bitchat

Si no tenés dinero para comprar ningún dispositivo pero te interesa mantenerte en comunicación sin internet, sin datos o en una situación de saturación de antenas (una marcha, una multitud festejando haber salido campeones, etc.) con tu mismo celular con bluetooth podés comunicarte con otras personas a través de Bitchat, que es una aplicación para chatear sin usar datos de celular, sólo usando Bluetooth.

Sin números de teléfono, sin datos, sin internet. Comunicación par a par.

Al igual que en el caso anterior, el bluetooth tiene un alcance muy limitado (unos 10 metros). Sin embargo, mientras más personas con la aplicación existan en un área, más posibilidad de comunicarte vas a tener, porque los mensajes también dan saltos entre los distintos dispositivos.

Pantalla minimalista de Bitchat, sólo texto, no contiene imágenes

Mapeando la cultura libre / software libre

El movimiento de la cultura libre y la difusión del modelo del software libre, cuyas raíces se remontan a los años 1960, fueron creciendo y tomando fuerza a partir de los 80.

Hoy estamos en un momento muy particular a raíz de la popularización de la Inteligencia Artificial Generativa. Un momento de aprendizaje fuerte, de replanteos acerca de la información abierta, los derechos de autor, el entrenamiento de las IA utilizando el trabajo del voluntariado de sitios como Wikipedia.

Sin embargo, estamos. Y estamos en muchos lugares del mundo, seguimos organizando eventos como el Flisol (Festival Latinoamericano de Instalación de Software Libre) y conversando en grupos y comunidades acerca de la realidad que nos toca vivir (invito a participar de nuestro grupo Clementina, para docentes con interés en software libre, hardware libre y cultura libre). Y es muy importante que nos conozcamos y se nos conozca.

Es por ello que propuse armar este mapa colaborativo, con el objetivo de visibilizar la presencia de eventos, organizaciones y personas que defienden la cultura libre, el software libre, y temas vinculados (como el cooperativismo). El mapa va creciendo poco a poco, y espero que esto continúe:

Ver en pantalla completa

Inteligencia Artificial y Educación

Comparto el artículo que escribí para la revista TI: Futuros Comunes, la publicación de las Tecnicaturas Informacionales de la Universidad Nacional de José C Paz (UNPAZ).

Gracias a Horacio Bilbao por la invitación y la gestión, y a Laura Zabala por la corrección.

Inteligencia artificial en educación: la urgencia de replantearnos todo [enlace]

Enlace al artículo

Vibe Coding para crear Recursos Educativos Reutilizables

Hace un tiempo que venimos experimentando con la programación a través de herramientas de Inteligencia Artificial, creando sitios con ChatGPT, creando gráficos tipo SVG a través del código, y luego mini aplicaciones interactivas. También creamos cartelitos para un aula virtual pidiendo el código html.

Este último tiempo me enteré del concepto de VibeCoding, creado en febrero de 2025, poniéndole nombre a esto que ya veníamos experimentando, que hace referencia a una forma de programar utilizando lenguaje natural.

Algo muy novedoso es la capacidad de las distintas herramientas para crear ese código a partir de nuestro pedido en lenguaje natural, mostrarnos el resultado, y permitirnos compartir el enlace para que otras personas puedan utilizar la aplicación.

En Claude, cada creación interactiva se denomina artefacto, y es posible remixar un artefacto que alguien comparte, para crear uno similar.

En Gemini, la opción de ver y utilizar el código generado se llama canvas.

En DeepSeek, es posible generar código y previsualizarlo pero por el momento no hay opción de compartir el enlace para que otras personas lo vean (hay que descargar el código y subirlo a un servidor o enviar el archivo)

¿Cómo reutilizar una de estas producciones?

En Claude, al visualizar un interactivo, por ejemplo este sobre teóricos de la educación, se hace clic en la opción “Remixar artefacto” o “Customize artifact”, y se le pide a través del prompt que cree un interactivo similar, modificando el contenido.


Más ejemplos, y esto es sólo el comienzo

Aquí dejo dos videos sobre cómo crear aplicaciones, pero esto recién empieza.

Crear recuadro en HTML y CSS para Moodle, usando ChatGPT o DeepSeek

Mucha gente crea banners o botones utilizando un graficador, y luego inserta la imagen en el Moodle, lo cual no es una buena práctica.

¿Por qué es mejor crear banners y botones utilizando HTML y CSS? Porque se puede seleccionar el texto, copiar y pegar, agrandar y achicar, e incluso desactivar los estilos si uno no llega a ver bien por tener problemas con el contraste, por ejemplo. Poner los títulos como imágenes es similar a enviar una foto del CBU cuando quieren hacerte una transferencia…

En Moodle, como en varias plataformas, podemos agregar contenido en formato HTML y CSS. Estos dos códigos se utilizan para el contenido (HTML) y para el estilo (CSS).

Sin embargo, estos códigos son complejos para aprenderlos rápidamente, por lo cual muestro acá una forma de crear estos códigos utilizando Inteligencia Artificial.

Para continuar aprovechando la inteligencia artificial para crear el diseño de mi aula virtual, le pedí que me brinde el código html y css para crear una cuadrícula con videos de Youtube. Me sorprendió muchísimo ver que como ejemplo puso un video que circula por toda la web… justamente, por eso lo habrá elegido.

Este es el prompt: “Crea el código HTML y CSS para hacer una cuadrícula utilizando DIV. Dentro de cada cuadrícula vamos a incrustar un video de Youtube. La cuadrícula debe ser accesible y adaptarse al tamaño de la ventana. El CSS tiene que estar incrustado en el HTML.”

El resultado:

Código de la cuadrícula de videos:

<body>
    <div class="grid-container" style=" display: grid;
    grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
    gap: 16px;     padding: 16px;
    box-sizing: border-box;">
        <div class="grid-item" style="position: relative;
    width: 100%;
    padding-top: 5%; /* Relación de aspecto 16:9 para los videos */
    overflow: hidden;">
            <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
        </div>
        <div class="grid-item" style="position: relative;
    width: 100%;
    padding-top: 5%; /* Relación de aspecto 16:9 para los videos */
    overflow: hidden;">
            <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
        </div>
        <div class="grid-item" style="position: relative;
    width: 100%;
    padding-top: 5%; /* Relación de aspecto 16:9 para los videos */
    overflow: hidden;">
            <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
        </div>
        <div class="grid-item" style="position: relative;
    width: 100%;
    padding-top: 5%; /* Relación de aspecto 16:9 para los videos */
    overflow: hidden;">
            <iframe src="https://www.youtube.com/embed/dQw4w9WgXcQ" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>
        </div>
    </div>
</body>
</html>

Un cuarto de siglo

Pasaron 25 años ya de aquel año que nos iba a encontrar “unidos o dominados”.

Quienes nos dedicamos a la tecnología educativa hemos perdido varias batallas últimamente.

Una de las batallas perdidas que más me duele y me cuesta comprender es la del sistema operativo Huayra. Hermoso, eficiente, adaptado a las necesidades educativas y localizado (es decir, vuelto local, argentinizado). Creo que la causa principal de este bajo nivel de adopción fue el doble booteo con el que venían las netbooks del plan Conectar Igualdad, que trajo como consecuencia el nulo uso de Huayra por parte de los equipos docentes.

Otra batalla perdida, también dolorosa y difícil de entender es el desinterés por la accesibilidad. Crear contenidos accesibles significa -por poner un ejemplo- cuidar el contraste de colores para que todas las personas puedan ver (¿es mayor el costo de un color que el otro en una pantalla? ¿o simplemente quienes diseñan contenido son insensibles o les falta capacitación?). Cumplir los estándares, nada más, nada menos. Se mejoraría la vida de todas las personas, todas, porque quienes no tenemos hoy una discapacidad, si tenemos suerte vamos a envejecer, y allí los dolores de mano, los problemas de vista, las dificultades para encontrar algo en una pantalla poco usable, van a hacernos sufrir los sitios mal diseñados.

Y la tercera es nueva, tan nueva que todavía no la entiendo. La batalla por los derechos de autor de aquellas cosas que subimos a la web, como este texto, con licencias libres, que hoy son usadas como alimento de la inteligencia artificial. En esta sí que nos mataron. Al final, nuestro sueño de una Internet libre, abierta, alimentada por cultura libre, está siendo pisoteado por empresas gigantes, por nubelistas dueños de los nuevos feudos informacionales, que se alimentan de nuestras producciones para recrear textos, imágenes, videos, ¡código!.

Así que en este cuarto de siglo de tantas batallas perdidas, también en lo político y cultural en mi país, Argentina, sólo queda el refugio de las redes humanas que fuimos construyendo. Nuestra salvación, creo yo, está en las personas con las que compartimos cada viaje: compañeros/as de estudio, de trabajo, la familia, las amistades. Y como los árboles en otoño, dejar que se caigan esas hojas para crear nuevas cuando llegue el momento.

Mis deseos para el próximo año: no seguir perdiendo batallas, profundizar amistades y redes presenciales, estudiar, aprender, compartir.

Licencias abiertas: una introducción a los derechos de autor en educación

Comparto la presentación de la charla sobre derechos de autor en educación brindada para las Jornadas de Acceso Abierto organizadas por el CRAI de la Universidad del Chubut. ¡Gracias por la invitación!

Accesibilidad web: para todas las personas, para tu propio futuro

Me invitaron a participar de las Jornadas Regionales de Software Libre que se realizaron este año en Santa Fe. Lamento no haber podido viajar pero sí pude enviar una participación a través de un video. Gracias al equipo organizador por la invitación.

Programando jueguitos con ChatGPT

Continuando con mis experimentos anteriores, estuve chateando hasta lograr programar un juego completo.

Este es el chat en el que le fui pidiendo a la herramienta que me generase un código, dándole poco a poco más detalles de cómo quería que funcione: Enlace al chat. (al final me quedé sin créditos para ChatGPT 4o y por eso no puedo seguir ahora)

En este enlace se puede probar el juego: Hacé grande a tu país

Y el código resultante después de todo el chat es el siguiente:

<!DOCTYPE html>
<html lang="es">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Juego del Auto</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            flex-direction: column;
            align-items: center;
            font-family: Arial, sans-serif;
        }
        #title {
            font-size: 36px;
            margin: 20px;
            color: #007BFF; /* Azul */
        }
        #gameContainer {
            position: relative;
            width: 90%;
            height: 80vh;
            background-color: lightblue;
            overflow: hidden;
            border: 2px solid black;
        }
        #score {
            font-size: 24px;
            margin: 10px;
        }
        #car {
            position: absolute;
            bottom: 10px;
            width: 100px;
            height: 50px;
            display: flex;
            flex-direction: column;
        }
        #car div {
            height: 33.33%;
        }
        #car .top, #car .bottom {
            background-color: #75AADB; /* Celeste */
        }
        #car .middle {
            background-color: white;
        }
        .word {
            position: absolute;
            font-size: 18px;
            color: black;
        }
        #message {
            font-size: 36px;
            color: #8A2BE2; /* Violeta azulado */
            margin: 20px;
            text-align: center;
        }
        #restartButton {
            display: none;
            padding: 10px 20px;
            font-size: 18px;
            cursor: pointer;
            background-color: #007BFF;
            color: white;
            border: none;
            border-radius: 5px;
            margin-top: 20px;
        }
        .centered {
            position: absolute;
            top: 50%;
            left: 50%;
            transform: translate(-50%, -50%);
            display: flex;
            flex-direction: column;
            align-items: center;
        }
    </style>
</head>
<body>
    <div id="title">Hacé que tu país sea un gran país</div>
    <div id="score">Puntaje: 0</div>
    <div id="gameContainer">
        <div id="car">
            <div class="top"></div>
            <div class="middle"></div>
            <div class="bottom"></div>
        </div>
    </div>
    <div id="message" class="centered"></div>
    <div class="centered">
        <button id="restartButton" onclick="restartGame()">Volver a jugar</button>
    </div>

    <script>
        const gameContainer = document.getElementById('gameContainer');
        const car = document.getElementById('car');
        const scoreDisplay = document.getElementById('score');
        const messageDisplay = document.getElementById('message');
        const restartButton = document.getElementById('restartButton');
        let score = 0;
        let carPosition = gameContainer.offsetWidth / 2 - car.offsetWidth / 2;
        const words = [
            "asfalto", "educación pública", "hospital público", "iluminación de la calle", "semáforos",
            "vacunas obligatorias", "regulación del uso de armas", "control de calidad en la comida",
            "netbooks para estudiantes de escuela pública", "universidades en todo el país", "boleto estudiantil",
            "satélites", "trenes estatales", "apoyo al cine nacional", "becas para deportistas",
            "Centro para deportistas de Alto Rendimiento", "clubes barriales", "orquestas juveniles",
            "Sistema operativo Huayra", "Rutas", "Plazas", "Juegos en las plazas", "créditos para viviendas",
            "pensión para discapacidad", "medicamentos gratis para personas jubiladas", "jubilaciones altas"
        ];
        let gameInterval;
        let carWidth = 100;
        let carHeight = 50;

        car.style.left = carPosition + 'px';
        car.style.width = carWidth + 'px';
        car.style.height = carHeight + 'px';

        document.addEventListener('keydown', (event) => {
            if (event.key === 'ArrowLeft') {
                carPosition = Math.max(0, carPosition - 10);
                car.style.left = carPosition + 'px';
            } else if (event.key === 'ArrowRight') {
                carPosition = Math.min(gameContainer.offsetWidth - car.offsetWidth, carPosition + 10);
                car.style.left = carPosition + 'px';
            }
        });

        function createWord() {
            const word = document.createElement('div');
            word.classList.add('word');
            word.textContent = words[Math.floor(Math.random() * words.length)];
            word.style.left = Math.random() * (gameContainer.offsetWidth - 100) + 'px';
            word.style.top = '0px';
            gameContainer.appendChild(word);

            function fall() {
                const wordTop = parseFloat(word.style.top);
                if (wordTop + word.offsetHeight >= gameContainer.offsetHeight - car.offsetHeight) {
                    const wordLeft = parseFloat(word.style.left);
                    const carLeft = parseFloat(car.style.left);
                    if (wordLeft < carLeft + car.offsetWidth && wordLeft + word.offsetWidth > carLeft) {
                        score++;
                        scoreDisplay.textContent = `Puntaje: ${score}`;
                        gameContainer.removeChild(word);
                        checkGameStatus();
                        adjustCarSize(1.10);
                    } else if (wordTop + word.offsetHeight >= gameContainer.offsetHeight) {
                        score--;
                        scoreDisplay.textContent = `Puntaje: ${score}`;
                        gameContainer.removeChild(word);
                        checkGameStatus();
                        adjustCarSize(0.90);
                    } else {
                        word.style.top = wordTop + 2 + 'px';
                        requestAnimationFrame(fall);
                    }
                } else {
                    word.style.top = wordTop + 2 + 'px';
                    requestAnimationFrame(fall);
                }
            }
            fall();
        }

        function adjustCarSize(factor) {
            carWidth *= factor;
            carHeight *= factor;
            car.style.width = carWidth + 'px';
            car.style.height = carHeight + 'px';
        }

        function checkGameStatus() {
            if (score < 0) {
                endGame('Perdiste');
            } else if (score >= 20) {
                endGame('Ganamos. Hiciste que Argentina sea un país más grande.');
            }
        }

        function endGame(message) {
            clearInterval(gameInterval);
            messageDisplay.textContent = message;
            messageDisplay.style.display = 'block';
            restartButton.style.display = 'block';
        }

        function restartGame() {
            score = 0;
            scoreDisplay.textContent = 'Puntaje: 0';
            messageDisplay.textContent = '';
            messageDisplay.style.display = 'none';
            restartButton.style.display = 'none';
            const wordsOnScreen = document.querySelectorAll('.word');
            wordsOnScreen.forEach(word => gameContainer.removeChild(word));
            carWidth = 100;
            carHeight = 50;
            car.style.width = carWidth + 'px';
            car.style.height = carHeight + 'px';
            gameInterval = setInterval(createWord, 2000);
        }

        gameInterval = setInterval(createWord, 2000);
    </script>
</body>
</html>