1 puntos por GN⁺ 2024-10-05 | 1 comentarios | Compartir por WhatsApp
  • Para reducir el hábito de pasar sin parar entre noticias y redes sociales en el celular cada mañana, imprime todos los días una portada personalizada en papel con una impresora matricial
  • La configuración es simple: una Star NP-10, una Raspberry Pi Zero W, un adaptador de puerto paralelo a USB y una fuente de poder; en la Pi, la impresora se maneja como el dispositivo /dev/usb/lp0
  • La impresora antigua no acepta Unicode normal, sino un conjunto de caracteres limitado más cercano a Code Page 437, así que desde PHP envía valores hexadecimales directamente para imprimir líneas, cajas y el símbolo de temperatura
  • Los datos se obtienen de Open-Meteo, twelvedata, NYTimes y Reddit JSON, y se formatean el clima, acciones, titulares y publicaciones de Reddit para que quepan en el ancho del papel
  • Se ejecuta automáticamente con cron alrededor de las 8 a. m. cada día, y una hoja con noticias finitas reemplaza el desplazamiento infinito de sitios web y apps

Crear una portada en papel en vez de una pantalla

  • Quería reducir el hábito de abrir el celular por la mañana y quedarme desplazándome por varios sitios de noticias y redes sociales, sin dejar de enterarme de lo más reciente
  • Lo resolvió aprovechando una impresora matricial comprada en eBay para imprimir cada día una portada personalizada ya preparada
  • Todo el código fuente está publicado en el repositorio de GitHub

Elección y conexión del hardware

  • Los componentes necesarios son bastante simples
  • La impresora usada es una Star NP-10 que parece ser de mediados de los años 80
    • Es probable que cualquier impresora matricial con puerto paralelo pueda funcionar
    • El precio normal rondaba los 80 a 120 dólares, pero la compró por aproximadamente la mitad porque estaba marcada como “funcionamiento incierto”
  • Después de una limpieza ligera y de ajustar el cartucho de cinta, logró imprimir una página de prueba
  • La Raspberry Pi se conecta por WiFi y se enlaza con el puerto paralelo de la impresora mediante el adaptador USB
    • Tras conectarse a la Pi por ssh, confirmó que la impresora aparecía en /dev/usb/lp0

Enviar datos directamente a la impresora

  • Al principio comprobó si imprimía enviando texto sin procesar directamente desde la shell
echo "Hello, world!" > /dev/usb/lp0
  • Como apareció un error de acceso al archivo, sorteó el problema de permisos con chmod
sudo chmod 666 /dev/usb/lp0
  • Después de eso, el texto enviado a /dev/usb/lp0 salió impreso
  • En PHP, lo amplió abriendo el archivo de la impresora con fopen() y escribiendo texto allí
  • Al probar con oraciones normales, espacios y arte Unicode, confirmó que el rango de caracteres compatible de la impresora era limitado

El conjunto de caracteres de la Star NP-10

  • Encontró el manual de usuario escaneado de la Star NP-10 para entender cómo funcionaba la impresora
  • Esta impresora solo acepta un conjunto de caracteres muy específico
    • Basado de forma flexible en Code Page 437 de IBM PC
    • Incluye caracteres alfanuméricos estándar y algunos símbolos especiales, líneas y caracteres de caja
  • En PHP se pueden construir cadenas con valores hexadecimales y enviarlas directamente a la impresora
$horizontalDouble = "\xCD";
$deg = "\xF8";

echo str_repeat($horizontalDouble, 24);
echo '78' . $deg . 'F' . PHP_EOL;
  • Con este método puede imprimir no solo texto normal, sino también caracteres decorativos como líneas, cajas y símbolos de temperatura

Datos obtenidos y APIs

  • En su portada personal incluyó cuatro secciones
    • Clima
    • Acciones
    • Titulares principales
    • Publicaciones destacadas de Reddit
  • Como era un proyecto experimental, quiso mantener bajo el costo de los datos y usar APIs gratuitas siempre que fuera posible; encontró las APIs necesarias en el repositorio public-apis, que recopila APIs públicas gratuitas
  • Las fuentes de datos usadas fueron las siguientes
    • Open-Meteo: datos del clima, sin necesidad de API key
    • twelvedata: datos bursátiles, con un nivel gratuito generoso
    • NYTimes: titulares de noticias, con un nivel gratuito suficiente para el proyecto
    • Reddit JSON: publicaciones de Reddit, gratis pero requiere suplantar el User-Agent
  • El script en PHP obtiene la carga útil de cada endpoint y combina solo los datos necesarios en un gran arreglo
    • Usa solo ciertas acciones, ciertos tipos de noticias y publicaciones de subreddits específicos
    • Si alguna de las secciones no tiene datos para mostrar, el script termina antes y vuelve a intentarlo más tarde

Cómo filtra los datos de noticias

  • Los datos de NYTimes se consideran fallidos si la respuesta de la API no tiene results
  • Solo reúne para imprimir los artículos que cumplen estas condiciones
    • type es Article
    • section es U.S., World, Weather o Arts
    • Solo se agregan mientras no se supere la cantidad máxima MAXNEWS
  • NEWS, NEWSKEY y MAXNEWS están definidos como constantes al inicio del script para que sea fácil modificarlos

Formato de salida adaptado al papel

  • En vez de imprimir solo los títulos de las secciones, crea una caja con borde en la parte superior con la fecha actual, el día de la semana y el nombre de la portada
  • Calcula el diseño tomando como base que el ancho de página de la impresora es de 80 caracteres
    • Caracteres hexadecimales
    • str_repeat
    • Un valor fijo para el ancho de página
  • Los títulos de sección se imprimen combinando caracteres de línea con texto
str_repeat($horizontalSingle, 3) . " WEATHER " . str_repeat($horizontalSingle, (PAGEWIDTH - 9)) . "\n";
  • El clima y las acciones se imprimen en una sola línea porque son lo bastante cortos como para no llegar al borde del papel
  • Los titulares y las publicaciones de Reddit suelen ser más largos, así que requieren una lógica de salto de línea aparte

Manejo del salto de línea en textos largos

  • La impresora puede continuar automáticamente una línea larga en la siguiente
  • Pero para evitar que las palabras se corten a la mitad al pasar de línea, implementó una función que divide la cadena según una longitud máxima por línea
  • La función splitString() separa las palabras por espacios y devuelve un arreglo procurando que cada línea no supere PAGEWIDTH
    • Si una sola palabra es más larga que la longitud máxima, esa palabra se corta
  • En el caso de las publicaciones de Reddit, recorre el arreglo de líneas resultante y las escribe en la impresora
foreach (splitString($redditPost) as $line) {
    fwrite($printer, $line) . "\n";
}

Ejecución automática y experiencia de uso

  • La ejecución manual se puede hacer con php print.php
  • En el uso real, lo automatizó con una tarea de cron
    • Cada día, alrededor de las 8 a. m., se imprime una portada personalizada
    • Arranca la hoja impresa y la revisa mientras toma café
  • Le parece mejor una noticia finita contenida en una sola hoja que la costumbre de desplazarse sin fin por sitios web y apps sociales
  • El proceso mismo de conectar hardware físico antiguo con tecnología nueva también fue una parte importante de la diversión del proyecto

1 comentarios

 
GN⁺ 2024-10-05
Opiniones de Hacker News
  • Probé hacer algo parecido con una impresora de recibos, y una impresora térmica USB de recibos cuesta unos 75 dólares y también es fácil de controlar con Python.
    Imprimir imágenes y códigos QR es sencillo, y la función de corte automático ayuda a separar los mensajes.
    También se puede hacer sonar la campana interna para usarla como una notificación adicional, y tiene una salida para controlar la caja registradora, así que estoy pensando en conectarla para controlar algo como luces.
    La configuré para el correo electrónico e hice que imprima mi agenda todas las mañanas.
    Si se usa junto con controles físicos como botones o un lector NFC, la interfaz encaja bastante bien. Por ejemplo, una tarjeta NFC para imprimir la agenda, otra para imprimir correos no leídos: uno da una “orden” y recibe una impresión.
    Es una forma divertida de reducir el tiempo frente a la pantalla, aunque irónicamente creo que pasé más tiempo mirando la pantalla programando y configurando esto que el tiempo que me ahorré.

    • Las impresoras de recibos son divertidas, pero hay que tener cuidado de no comprar papel térmico nocivo.
      https://www.consumerreports.org/cro/news/2014/03/the-health-...
    • Mi impresora térmica también imprime el clima todas las mañanas, y saca una notificación si algún dispositivo importante se desconecta de la red.
    • Las impresoras de recibos son realmente divertidas. Hace unos años hice un proyecto para imprimir tickets de GitHub con una configuración parecida, muy similar a la que ahora uso con una impresora de matriz de puntos.
    • Me da curiosidad qué impresora usas. Estoy pensando en comprar una, y no sabía de la función de notificación ni de las funciones de control externo que mencionas.
  • Hoy de pronto me entró la curiosidad.
    Una de las cosas que hace esta persona es simplemente hacer echo a /dev/lp0, y antes así era como se hacía. Metías texto por la interfaz y la impresora lo imprimía.
    Las impresoras de hoy son mucho más sofisticadas, pero siguen siendo impresoras con un largo legado. Las primeras impresoras láser de HP también imprimían en Courier 10, 66 líneas por página, si enviabas datos por el cable. Supongo que la Apple LaserWriter no funcionaba así porque era una impresora PostScript dedicada; en su lugar, le metías PostScript.
    A medida que las impresoras evolucionaron, el lenguaje que se les enviaba se volvió más complejo, pero aun así mantuvieron una larga compatibilidad hacia atrás.
    Entonces, si conecto una impresora USB a una computadora y hago ls > /dev/usbXXX, ¿se imprimirá incluso hoy? ¿Todavía funcionará así sin más?
    Si le envío códigos de escape EPSON MX-80 a una EPSON, ¿todavía funcionará? Ninguna de las dos respuestas me sorprendería, pero las impresoras modernas son una caja negra para mí, así que me pregunto si alguien lo sabe.
    Seguro que también hay gente que recuerda el placer de pelearse para que un reporte saliera bien alineado en formularios NCR multicopia preimpresos.

    • Acabo de probarlo en OS X, y parece que no expone la impresora bajo /dev/ de la forma descrita. En cambio, OS X también tiene lp, así que se puede usar algo como echo "Hello printer" | lp -d, y el nombre se puede encontrar con lpstat -p.
      Lo probé con una impresora nueva y efectivamente funciona.
    • En mi entorno funcionaron las dos opciones de abajo:
      printf 'hello\f' > /dev/usb/lp0
      printf 'hello\f' | nc -N $printer_ip 9100
      Es con una impresora láser Brother, y junto al manual en línea hay un enlace a la guía de programación. El lenguaje es PCL, pero para una impresión simple no hace falta saber mucho.
      Las dos opciones anteriores no usan CUPS. Como dicen en otros comentarios, si quieres usar los ejecutables lp/lpr, primero la impresora tiene que estar registrada en CUPS.
      En el caso de ls >, la impresora espera saltos de línea de DOS. \n solo avanza a la línea siguiente y no hace “retorno de carro”, así que hay que pasarlo por sed 's/$/\r/' o usar nc -C.
      Con conexión USB se puede imprimir varias veces para formar una página, y el papel no sale hasta que se envía un avance de formulario. Con conexión TCP, la página se imprime cuando se cierra la conexión.
    • Tengo una Epson LX-350 que compré nueva hace unos años; se conecta por USB y también tiene puertos serial/paralelo. Al conectarla por USB aparecía como algo parecido a /dev/usblp0, y funcionaba incluso enviándole datos con cat.
      Los clientes que compran nuevos estos productos seguramente quieren que sean compatibles con los procesos que han usado durante los últimos 30 a 50 años, así que, como era de esperarse, soporta ESC/P 2 y también códigos de escape de IBM. Me sorprendió, porque creo que las viejas impresoras matriciales que usábamos en los 90 no soportaban los códigos de IBM.
      Lo más sorprendente fue que la MacBook tenía un controlador integrado para impresoras Epson genéricas, y funcionó. La calidad no era buena y lo imprimía como gráficos, pero al menos existía.
      No sé bien cómo será con las impresoras de inyección de tinta y láser más recientes. Una Epson de inyección de tinta que usaba hace unos 20 años soportaba códigos ESC/P sin procesar.
    • También se puede hacer con una impresora de red. Si envías un PDF con netcat a un puerto abierto, se imprime.
      https://retrohacker.substack.com/p/bye-cups-printing-with-ne...
    • En el laboratorio de computación de la escuela en los años 90 todavía había una impresora de matriz de puntos, y estaba configurada como impresora predeterminada en todas las computadoras de la red.
      Un error común de los usuarios era que, cuando alguien intentaba imprimir un documento de Word, se enviaba PostScript a la impresora de matriz de puntos, y la impresora imprimía fielmente el código fuente PostScript tal cual, desperdiciando papel y cinta hasta que alguien la detenía.
  • Las impresoras matriciales también pueden hacer bastantes cosas, según el modelo. Cambiar tipografías, negrita, subrayado, a veces cursiva, caracteres de doble ancho/alto e incluso gráficos. Aunque los gráficos suelen tener una resolución relativamente baja, como 90 o 180 DPI.
    Hace tiempo armé una caja con solo un conector de impresora paralelo para algo parecido a un juego de escape room. Al conectarla a la impresora, tomaba alimentación parásita de una de las líneas de control del puerto paralelo, y un microcontrolador PIC muy pequeño, usando apenas unos cientos de µA, enviaba pistas a la impresora.

    • Hace tiempo, entre los primeros programas de autoedición, existía uno de SoftCraft llamado Fancy Font. Era un programa para CP/M y luego para DOS, así que no era una herramienta WYSIWYG de maquetación como PageMaker; usaba documentos de texto formateados con un lenguaje de marcado simple.
      Al principio aprovechaba el modo gráfico de alta resolución de las impresoras matriciales Epson. Estas impresoras podían hacer microajustes de la platina tan pequeños como 1/3 de la separación entre los pines del cabezal, lo que permitía obtener el triple de resolución vertical de la que el cabezal podía dar por sí solo.
      Fancy Font renderizaba el texto en la computadora y luego lo enviaba como gráficos en ese modo especial de alta resolución, logrando con equipos domésticos de principios de los 80 un resultado lo más cercano posible a la composición tipográfica.
      Las versiones posteriores también incluían drivers para impresoras láser tempranas como la HP LaserJet original, pero con la llegada de la Mac, el futuro de esos sistemas quedó bastante claro.
    • Mi padre tenía una impresora matricial de 4 colores en los 90. Imprimir la cabeza del faraón de Deluxe Paint II tardaba una eternidad, pero en realidad se veía bastante linda.
      Eso sí, después de imprimir el papel quedaba muy ondulado. Todavía tengo la impresora, pero no sé dónde podría conseguir una cinta de 4 colores.
    • Recuerdo imprimir banners enormes en modo horizontal sobre rollos interminables de papel. Era algo parecido al arte ASCII que hoy generan comandos como figlet en la terminal. Quizá todavía soporte salida a impresora.
    • Desde el punto de vista del diseño, quería explorar más esto. El manual tiene literalmente decenas de páginas sobre tamaños de letra, énfasis, cursiva, subíndices y superíndices, y cosas así.
      Tal vez lo pruebe en la versión 2.0.
    • Sería divertido tener una terminal que entienda ESC/P y soporte varias tipografías y cosas como CPI.
  • Tuve esta máquina conectada a feeds de noticias durante varios años.[1] Es el mecanismo de una impresora de cinta Model 14 Teletype, todavía está en mi sala y la cinta cae en una canasta de alambre.
    La manejo con un programa en Python desde una vieja subnotebook EeePC.
    [1] https://aetherltd.com/refurbishing14.html

    • Qué genial. Siempre quise conseguir una de estas para imitar una cinta ticker que imprimiera precios de acciones/cripto actualizados constantemente.
      También hacía muchísimo que no escuchaba el nombre EeePC; me trajo recuerdos.
  • Parece una idea de producto realmente excelente. Me encanta la idea de recibir cada mañana un feed de noticias personalizado, y no de un lugar como MSN, sino un feed de noticias offline elegido de verdad por mí.
    Y si además pudiera reemplazar el despertador con una impresora matricial, sería todavía mejor.
    Podría adaptar fácilmente el PHP a mis fuentes de noticias, pero no sé cómo empezar por mi cuenta con la parte de hardware. Imagino que hay bastante gente en esa situación.
    Si saliera al mercado, creo que lo compraría incluso si costara mucho más que una impresora vieja.

    • Como alguien que hizo algo parecido antes, en realidad es bastante fácil. Conectas la impresora y escribes en la salida de dev. Suponiendo que corre en Linux, esa salida es simplemente un archivo.
      La parte más difícil es conectar la impresora; quizá necesites un cable adaptador.
  • Muy limpio. Me recuerda a cuando trabajé un tiempo en una estación de radio. Casi no recuerdo los detalles, pero creo que marcaba automáticamente a algún número de Associated Press, traía los titulares más recientes y luego los mandaba a una impresora matricial.
    Era a fines de los 90 y corría en MS-DOS.
    En esa época la mayoría de las impresoras permitían configurar la tipografía con códigos de control, y muchas tenían también tipografías de ancho variable.

  • Me gusta. Últimamente estoy pensando en suscribirme a un periódico impreso de fin de semana como FT Weekend, porque leo noticias en el teléfono con demasiada frecuencia.
    Las noticias muchas veces no son muy útiles y solo generan emociones negativas. Creo que leerlas en papel, y solo una vez por semana, sería más relajante.
    Este enfoque de imprimir noticias en papel todos los días parece un buen punto intermedio.
    De paso, me encantan las impresoras matriciales. ¿Habrá alguna impresora open source buena para hackear de esta manera?

    • Me cuesta recomendar FT.
      Intenté suscribirme al periódico impreso, pero nunca recibí nada; solo después de unas 3 llamadas y unos 10 correos, cuando pedí cancelar la suscripción y que me reembolsaran, dijeron que iban a escalar el ticket. Para entonces ya habían pasado 3 semanas y yo había gastado bastante tiempo.
      Por eso también me interesa mucho imprimir noticias de internet yo mismo para no seguir mirando pantallas.
  • Durante un tiempo estuve imprimiendo “tarjetas de tres lados”. Un lado tiene una imagen y el otro un código QR que lleva a un documento.
    https://mastodon.social/@UP8/111013706271196029
    El “tercer” lado es el sitio web al que lleva el código QR.
    Me aburrí de la fotografía, así que inventé un personaje que lleva un lente barato, siempre cierra el diafragma a f/18 o más, aplica mucho posprocesado y corrección de color, y usa una relación de aspecto estándar pero que se siente no estándar. La idea es que parezca que usa una cámara rara de una línea temporal alternativa.
    Al empezar a imprimir esta serie, llegué a la conclusión de que si recortas un 4x6 puedes hacer fácilmente un 4x5, pero en vez de recortar, podía dejar un espacio de 1 pulgada para poner en el frente el código QR y el documento. Del mismo modo, si recortas un 5x7 a un cuadrado de 5x5, queda espacio para el documento.
    Tengo varias cajas de papel brillante en el que no se puede imprimir por el reverso, así que pienso usarlo así. Después también descubrí que Instagram tiene un estándar 4x5, y que las fotos deportivas tomadas con buenos lentes se ven realmente bien en ese formato.
    Pero me cuesta decidir qué forma debería tener el documento: cambiar lo mínimo posible de la composición actual, usar un efecto falso de impresora matricial que parezca una impresora vieja que podría venir integrada en esa cámara fantástica, o aprovechar al máximo las ventajas de una impresora de inyección de tinta.

    • Quiero entenderlo, pero siento que el texto en sí, o yo, nos perdimos mucho contexto. Casi todos los párrafos parecen completamente desconectados del anterior.
  • Si “como es un proyecto experimental, quería mantener muy bajo el costo de estos datos, idealmente gratis”, también está NewsCatcher. Es gratis para proyectos paralelos open source
    https://docs.google.com/forms/d/e/1FAIpQLSejrsj4a1ZQkIasiKCt...

  • Algo relacionado: uso un pequeño script en mi MacBook que abre la portada de NYTimes cada mañana
    d=$(date +%d)
    m=$(date +%m)
    y=$(date +%Y)
    wget -q [https://static01.nyt.com/images/$y/$m/$d/nytfrontpage/scan.p...](<https://static01.nyt.com/images/$y/$m/$d/nytfrontpage/scan.pdf>;) && open ./scan.pdf