1 pontos por GN⁺ 2024-10-05 | 1 comentários | Compartilhar no WhatsApp
  • Para reduzir o hábito de passar infinitamente por notícias e redes sociais no celular todas as manhãs, imprime diariamente uma primeira página personalizada em papel usando uma impressora matricial
  • A configuração é simples, com uma Star NP-10, Raspberry Pi Zero W, adaptador de porta paralela para USB e fonte de alimentação; no Pi, a impressora é tratada como o dispositivo /dev/usb/lp0
  • A impressora antiga aceita um conjunto limitado de caracteres mais próximo de Code Page 437 do que de Unicode comum, então ele envia valores hexadecimais diretamente em PHP para imprimir linhas, caixas e símbolos de temperatura
  • Os dados vêm de Open-Meteo, twelvedata, NYTimes e Reddit JSON, e clima, ações, manchetes e posts do Reddit são formatados para caber na largura do papel
  • A execução é automatizada por cron por volta das 8h da manhã todos os dias, e uma página única com notícias finitas substitui o scroll infinito de sites e apps

Criando uma primeira página em papel em vez de uma tela

  • Queria reduzir o hábito de abrir o celular de manhã e ficar rolando vários sites de notícias e redes sociais, sem deixar de acompanhar as informações mais recentes
  • Implementou isso usando uma impressora matricial comprada no eBay para imprimir diariamente uma primeira página personalizada
  • Todo o código-fonte está disponível no repositório no GitHub

Escolha e conexão do hardware

  • Os componentes necessários são relativamente simples
  • A impressora usada é uma Star NP-10, aparentemente de meados dos anos 1980
    • Qualquer impressora matricial com porta paralela provavelmente pode funcionar
    • A faixa de preço comum era de cerca de US$ 80 a US$ 120, mas ele conseguiu comprar por quase metade disso por estar marcada como “funcionamento incerto”
  • Depois de uma limpeza básica e de ajustar o cartucho da fita de tinta, conseguiu imprimir uma página de teste
  • O Raspberry Pi é conectado ao Wi-Fi e ligado à porta paralela da impressora via adaptador USB
    • Após acessar o Pi por ssh, confirmou que a impressora aparecia em /dev/usb/lp0

Enviando dados diretamente para a impressora

  • No início, testou a impressão enviando texto bruto diretamente pelo shell
echo "Hello, world!" > /dev/usb/lp0
  • Surgiu um erro de acesso ao arquivo, então ele contornou o problema de permissão com chmod
sudo chmod 666 /dev/usb/lp0
  • Depois disso, o texto enviado para /dev/usb/lp0 passou a ser impresso
  • Em PHP, expandiu a abordagem abrindo o arquivo da impressora com fopen() e escrevendo o texto nele
  • Ao testar frases comuns, espaços e arte em Unicode, percebeu que a faixa de caracteres suportados pela impressora era limitada

O conjunto de caracteres da Star NP-10

  • Encontrou o manual do usuário escaneado da Star NP-10 para entender como a impressora funcionava
  • Essa impressora aceita apenas um conjunto de caracteres muito específico
    • Baseado de forma aproximada na Code Page 437 do IBM PC
    • Inclui caracteres alfanuméricos padrão e alguns símbolos especiais, linhas e caracteres de caixa
  • Em PHP, é possível montar strings com valores hexadecimais e enviá-las diretamente para a impressora
$horizontalDouble = "\xCD";
$deg = "\xF8";

echo str_repeat($horizontalDouble, 24);
echo '78' . $deg . 'F' . PHP_EOL;
  • Com isso, é possível imprimir não só texto comum, mas também caracteres decorativos como linhas, caixas e símbolos de temperatura

Dados coletados e APIs

  • A primeira página pessoal inclui quatro seções
    • Clima
    • Ações
    • Principais manchetes
    • Posts mais populares do Reddit
  • Como era um projeto experimental, ele quis manter o custo dos dados baixo e usar APIs gratuitas sempre que possível, encontrando as APIs necessárias no repositório public-apis, que reúne APIs públicas gratuitas
  • As fontes de dados usadas foram as seguintes
    • Open-Meteo: dados de clima, sem necessidade de chave de API
    • twelvedata: dados de ações, com um plano gratuito generoso
    • NYTimes: manchetes de notícias, com plano gratuito suficiente para o projeto
    • Reddit JSON: posts do Reddit, gratuito, mas exigindo spoofing do User-Agent
  • O script em PHP busca os payloads em cada endpoint de API e junta apenas os dados necessários em um grande array
    • Usa apenas ações específicas, certos tipos de notícia e posts de subreddits específicos
    • Se qualquer uma das seções não tiver dados para exibir, o script encerra mais cedo e tenta novamente depois

Como os dados de notícias são filtrados

  • Os dados do NYTimes são tratados como falha se a resposta da API não tiver results
  • Entre os artigos, ele reúne para impressão apenas os itens que atendem às condições a seguir
    • type igual a Article
    • section em U.S., World, Weather ou Arts
    • Só adiciona enquanto o total estiver abaixo de MAXNEWS
  • NEWS, NEWSKEY e MAXNEWS são definidos como constantes no topo do script para facilitar ajustes

Formatação de impressão adaptada ao papel

  • Em vez de imprimir apenas os títulos das seções, ele cria uma caixa com borda no topo contendo a data atual, o dia da semana e o nome da primeira página
  • O layout é calculado com base na largura de 80 caracteres da página da impressora
    • Caracteres hexadecimais
    • str_repeat
    • Valor fixo da largura da página
  • Os títulos das seções são impressos combinando caracteres de linha com texto
str_repeat($horizontalSingle, 3) . " WEATHER " . str_repeat($horizontalSingle, (PAGEWIDTH - 9)) . "\n";
  • Clima e ações são curtos o suficiente para serem impressos em uma única linha sem encostar nas bordas do papel
  • Manchetes e posts do Reddit costumam ser longos, então exigem quebra de linha separada

Quebra de linha para textos longos

  • A impressora consegue continuar automaticamente uma linha longa na linha seguinte
  • Mas, para evitar que palavras fossem cortadas no meio ao passar para a linha seguinte, ele implementou uma função que divide strings com base em um comprimento máximo de linha
  • A função splitString() separa palavras com base em espaços e retorna um array garantindo que cada linha não ultrapasse PAGEWIDTH
    • Se uma única palavra for maior que o comprimento máximo, ela é cortada e tratada separadamente
  • Para os posts do Reddit, ele percorre o array de linhas retornado e escreve cada uma na impressora
foreach (splitString($redditPost) as $line) {
    fwrite($printer, $line) . "\n";
}

Execução automática e experiência de uso

  • A execução manual pode ser feita com php print.php
  • No uso real, ele automatizou tudo com uma tarefa no cron
    • Todos os dias, por volta das 8h da manhã, a primeira página personalizada é impressa
    • Ele destaca a folha impressa e a lê enquanto toma café
  • As notícias finitas em uma única folha pareceram melhores do que a experiência de rolagem infinita em sites e apps sociais
  • O próprio processo de conectar hardware físico antigo com tecnologia nova também foi uma parte importante da diversão do projeto

1 comentários

 
GN⁺ 2024-10-05
Comentários do Hacker News
  • Fiz algo parecido com uma impressora de recibos, e uma impressora térmica USB de recibos custa cerca de US$ 75 e também é fácil de controlar com Python.
    Imprimir imagens e QR codes é simples, e o recurso de corte automático ajuda a separar as mensagens.
    Também dá para tocar a campainha interna e usá-la como uma notificação adicional, e ela tem uma saída para controle de gaveta de dinheiro, então estou pensando em ligá-la para controlar algo como luzes.
    Configurei para e-mails e para imprimir minha agenda todas as manhãs.
    Com controles físicos, como botões ou um leitor NFC, a interface combina muito bem. Por exemplo, você usa um cartão NFC para imprimir a agenda ou um cartão NFC para imprimir e-mails não lidos, como se desse um “comando” e recebesse a saída.
    É uma forma divertida de reduzir o tempo de tela, mas, ironicamente, acho que passei mais tempo olhando para a tela codando e configurando isso do que o tempo que economizei.

    • Impressoras de recibos são divertidas, mas é preciso tomar cuidado para não comprar papel térmico nocivo.
      https://www.consumerreports.org/cro/news/2014/03/the-health-...
    • Minha impressora térmica também imprime a previsão do tempo todas as manhãs e imprime alertas quando dispositivos importantes saem da rede.
    • Impressoras de recibos são realmente divertidas. Alguns anos atrás fiz um projeto parecido para imprimir tickets do GitHub, e a configuração era semelhante à que uso agora com uma impressora matricial.
    • Fiquei curioso para saber qual impressora você usa. Estou pensando em comprar uma, mas não conhecia os recursos de notificação e de controle externo que você mencionou.
  • Hoje me bateu uma curiosidade.
    Uma das coisas que essa pessoa faz é simplesmente dar echo em /dev/lp0, e antigamente era exatamente assim que se fazia. Você empurrava texto pela interface e a impressora imprimia.
    As impressoras de hoje são muito mais sofisticadas, mas continuam sendo impressoras com um longo legado. As primeiras impressoras a laser da HP também imprimiam em Courier 10, 66 linhas por página, se você enviasse dados pelo cabo. A Apple LaserWriter, por ser uma impressora PostScript dedicada, acho que não funcionava desse jeito; em vez disso, você empurrava PostScript para ela.
    Conforme as impressoras evoluíram, a linguagem enviada ficou mais complexa, mas ainda assim elas mantiveram uma longa compatibilidade retroativa.
    Então, se eu conectar uma impressora USB ao computador e fizer ls > /dev/usbXXX, isso ainda imprime hoje em dia? Ainda funciona simplesmente assim?
    Se eu enviar códigos de escape EPSON MX-80 para uma EPSON, isso ainda funciona? Eu não ficaria surpreso com nenhuma das respostas, mas impressoras modernas são meio uma caixa-preta para mim, então fiquei curioso se alguém sabe.
    Talvez também haja quem se lembre da alegria de lutar para fazer relatórios saírem alinhados em formulários NCR multicópia pré-impressos.

    • Acabei de testar no OS X, e ele não parece expor a impressora em /dev/ do jeito descrito. Em vez disso, o OS X também tem lp, então dá para usar algo como echo "Hello printer" | lp -d, e o nome pode ser encontrado com lpstat -p.
      Testei em uma impressora nova e de fato funciona.
    • Os dois comandos abaixo funcionaram no meu ambiente:
      printf 'hello\f' > /dev/usb/lp0
      printf 'hello\f' | nc -N $printer_ip 9100
      Foi com uma impressora laser Brother, e há um guia de programação linkado ao lado do manual online. A linguagem é PCL, mas para impressão simples não é preciso saber muita coisa.
      Os dois exemplos acima não usam CUPS. Como em outro comentário, para usar os executáveis lp/lpr, primeiro a impressora precisa estar registrada no CUPS.
      No caso de ls >, a impressora espera quebras de linha no formato DOS. \n só avança para a próxima linha e não faz “carriage return”, então é preciso passar por sed 's/$/\r/' ou usar nc -C.
      Na conexão USB, você pode imprimir várias vezes para compor uma página, e o papel não sai até enviar um form feed. Na conexão TCP, a página é impressa quando a conexão é fechada.
    • Tenho uma Epson LX-350 que comprei nova há alguns anos; ela se conecta por USB e também tem portas serial/paralela. Ao conectar por USB, aparecia como algo parecido com /dev/usblp0, e funcionava simplesmente enviando com cat.
      Clientes que compram esse tipo de produto novo provavelmente querem compatibilidade com processos usados nos últimos 30 a 50 anos, então, como esperado, ela oferece suporte a ESC/P 2 e também a códigos de escape da IBM. Achei surpreendente, porque acho que as antigas impressoras matriciais que eu usava nos anos 90 não suportavam os códigos da IBM.
      Ainda mais surpreendente foi o MacBook ter um driver embutido para impressoras Epson genéricas, e ele funcionar. A qualidade não era boa e ele imprimia como gráfico, mas de qualquer forma existia.
      Não sei quanto às impressoras jato de tinta e laser mais recentes. Uma jato de tinta Epson que eu usava uns 20 anos atrás aceitava códigos ESC/P brutos.
    • Também é possível com impressoras de rede. Se você enviar um PDF com netcat para uma porta aberta, ele imprime.
      https://retrohacker.substack.com/p/bye-cups-printing-with-ne...
    • Nos laboratórios de informática da escola nos anos 1990 ainda havia impressoras matriciais, e elas estavam configuradas como impressora padrão em todos os computadores da rede.
      Um erro comum de usuário era alguém tentar imprimir um documento do Word, fazendo com que PostScript fosse enviado para a impressora matricial; a impressora então imprimia fielmente o código-fonte PostScript como texto, desperdiçando papel e fita até alguém interromper.
  • Impressoras matriciais também conseguem fazer bastante coisa, dependendo do modelo. Dá para mudar fontes, usar negrito, sublinhado, às vezes itálico, caracteres com largura/altura dupla e até gráficos. Só que os gráficos normalmente têm resolução relativamente baixa, como 90 ou 180 DPI.
    Anos atrás, para algo parecido com um jogo de escape room, fiz uma caixa que tinha apenas um conector de impressora paralela. Quando conectada à impressora, ela recebia alimentação parasita de uma das linhas de controle da porta paralela, e um microcontrolador PIC minúsculo, consumindo só algumas centenas de µA, enviava dicas para a impressora.

    • Antigamente havia um dos primeiros programas de editoração eletrônica chamado Fancy Font, da SoftCraft. Era um programa para CP/M e depois para DOS, então não era uma ferramenta WYSIWYG de layout de página como o PageMaker; ele usava documentos de texto formatados com uma linguagem de marcação simples.
      No começo, ele aproveitava o modo gráfico de alta resolução das impressoras matriciais Epson. Essas impressoras conseguiam fazer microajustes do platen tão pequenos quanto 1/3 do espaçamento entre os pinos da cabeça de impressão, obtendo uma resolução vertical três vezes maior do que a cabeça sozinha permitiria.
      O Fancy Font renderizava o texto no computador e depois o enviava como gráficos nesse modo especial de alta resolução, produzindo, com equipamentos domésticos do início dos anos 1980, algo o mais próximo possível de composição tipográfica.
      Versões posteriores também tinham drivers para impressoras a laser iniciais, como a HP LaserJet original, mas, com a chegada do Mac, o futuro desse tipo de sistema ficou óbvio.
    • Meu pai tinha uma impressora matricial de 4 cores nos anos 90. Imprimir a cabeça do faraó do Deluxe Paint II demorava uma eternidade, mas ficava bem bonito de verdade.
      Só que, depois da impressão, o papel ficava muito ondulado. Ainda tenho a impressora, mas não faço ideia de onde encontrar uma fita de 4 cores.
    • Lembro de imprimir banners enormes em modo paisagem, em rolos intermináveis de papel. Era algo parecido com a arte ASCII que comandos como figlet geram nos terminais hoje. Talvez ele ainda tenha suporte a saída para impressora.
    • Do ponto de vista de design, eu queria explorar isso mais. O manual tem literalmente dezenas de páginas sobre tamanhos de fonte, ênfase, itálico, subscrito/sobrescrito e coisas assim.
      Talvez eu faça isso na versão 2.0.
    • Seria divertido ter um terminal que entendesse ESC/P e desse suporte a várias fontes, CPI e coisas do tipo.
  • Mantive esta máquina conectada a um feed de notícias por alguns anos.[1] É o mecanismo de uma impressora de fita Model 14 Teletype, e ela ainda fica na minha sala; a fita sai para dentro de uma cesta de arame.
    Ela é controlada por um programa em Python rodando em um antigo subnotebook EeePC.
    [1] https://aetherltd.com/refurbishing14.html

    • Muito legal. Sempre quis conseguir um equipamento desses para imitar uma fita ticker imprimindo preços de ações/criptomoedas atualizados continuamente.
      Fazia muito tempo que eu não ouvia o nome EeePC; bateu uma nostalgia.
  • Parece uma ideia de produto realmente excelente. A noção de receber todas as manhãs um feed de notícias personalizado, e ainda por cima um feed de notícias off-screen escolhido de verdade por mim, não algo como MSN, é ótima.
    E seria ainda mais legal se o despertador também pudesse ser substituído por uma impressora matricial.
    Eu conseguiria facilmente adaptar o PHP às minhas fontes de notícias, mas não sei como começaria sozinho pela parte de hardware. Imagino que muita gente esteja na mesma situação.
    Se chegasse ao mercado, acho que eu compraria mesmo que custasse bem mais do que uma impressora antiga.

    • Como alguém que já fez algo parecido, na prática é bem fácil. Você conecta a impressora e apenas escreve na saída do dev. Supondo que esteja rodando no Linux, essa saída é simplesmente um arquivo.
      A parte mais difícil é conectar a impressora; talvez você precise de um cabo adaptador.
  • Bacana. Isso me lembra de quando trabalhei por um curto período em uma estação de rádio. Esqueci quase todos os detalhes, mas acho que ela fazia uma discagem automática para algum número da Associated Press, pegava as manchetes mais recentes e depois as enviava para uma impressora matricial.
    Era no fim dos anos 90 e rodava em MS-DOS.
    Na época, a maioria das impressoras permitia configurar a fonte por códigos de controle, e muitas impressoras também tinham fontes de largura variável.

  • Legal. Ultimamente tenho pensado em assinar um jornal impresso de fim de semana, como o FT Weekend, porque leio notícias no celular com frequência demais.
    Notícias muitas vezes nem são tão úteis e só geram emoções negativas. Acho que ler notícias em papel, e só uma vez por semana, seria mais tranquilo.
    Esse método de imprimir notícias em papel todos os dias parece preencher bem esse meio-termo.
    Além disso, gosto muito de impressoras matriciais. Será que existe alguma impressora open source boa para hackear desse jeito?

    • É difícil recomendar o FT.
      Tentei assinar o jornal impresso, mas nunca recebi uma edição; só depois de umas 3 ligações e cerca de 10 e-mails, quando pedi o cancelamento da assinatura e o reembolso, disseram que escalariam o chamado. A essa altura já tinham se passado 3 semanas e eu também tinha gastado bastante do meu tempo.
      Por isso, também tenho muito interesse em imprimir minhas próprias notícias da internet para evitar ficar olhando para telas o tempo todo.
  • Há algum tempo venho imprimindo “cartões de três lados”. Um lado tem uma imagem, e o outro tem um QR code que leva a um documento.
    https://mastodon.social/@UP8/111013706271196029
    O “terceiro” lado é o site para o qual o QR code aponta.
    Fiquei entediado com fotografia, então criei uma persona que anda com uma lente barata, sempre fecha a abertura para f/18 ou mais, faz pós-processamento e correção de cor pesados e fotografa em uma proporção de tela convencional, mas que parece não convencional. A ideia é fazer parecer que estou usando uma câmera estranha de uma linha do tempo alternativa.
    Quando comecei a imprimir essa série, concluí que dava para obter 4x5 facilmente recortando 4x6, mas, em vez de cortar, percebi que poderia deixar um espaço de 1 polegada para colocar o QR code e o documento na frente. Da mesma forma, ao cortar 5x7 para virar um quadrado 5x5, sobra espaço para inserir o documento.
    Tenho algumas caixas de papel brilhante no qual não dá para imprimir no verso, então pretendo usá-las desse jeito. Mais tarde, descobri que existe um padrão 4x5 no Instagram, e que fotos esportivas feitas com boas lentes ficam realmente ótimas nesse formato.
    Só que ainda estou em dúvida sobre qual deve ser a aparência do documento: mudar o mínimo possível da configuração atual, usar um efeito falso de impressora matricial que pareça uma impressora antiga que poderia estar embutida naquela câmera de fantasia, ou aproveitar ao máximo os pontos fortes de uma impressora jato de tinta.

    • Quero entender, mas sinto que estou perdendo muito contexto, seja no texto em si ou da minha parte. Quase todos os parágrafos parecem completamente desconectados do anterior.
  • Se “por ser um projeto experimental, eu queria manter o custo desses dados bem baixo, de preferência gratuito”, também existe o NewsCatcher. É gratuito para projetos paralelos open source
    https://docs.google.com/forms/d/e/1FAIpQLSejrsj4a1ZQkIasiKCt...

  • Um pouco relacionado: uso um pequeno script que abre a primeira página do NYTimes no MacBook todas as manhãs
    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