1 điểm bởi GN⁺ 2024-10-05 | 1 bình luận | Chia sẻ qua WhatsApp
  • Để giảm thói quen mỗi sáng lướt vô tận tin tức trên điện thoại và mạng xã hội, tác giả in mỗi ngày một trang nhất giấy được cá nhân hóa bằng máy in ma trận điểm
  • Cấu hình khá đơn giản gồm Star NP-10, Raspberry Pi Zero W, bộ chuyển đổi cổng song song sang USB và bộ nguồn; trên Pi, máy in được xử lý như thiết bị /dev/usb/lp0
  • Máy in cũ không nhận Unicode thông thường mà nhận một bộ ký tự giới hạn gần với Code Page 437, nên trong PHP tác giả gửi trực tiếp các giá trị hex để in đường kẻ, khung và ký hiệu nhiệt độ
  • Dữ liệu được lấy từ Open-Meteo, twelvedata, NYTimes và Reddit JSON, rồi định dạng thời tiết, chứng khoán, tiêu đề tin tức và bài đăng Reddit cho vừa chiều rộng giấy
  • Chạy tự động bằng cron vào khoảng 8 giờ sáng mỗi ngày; một trang tin tức hữu hạn thay thế cho thao tác cuộn vô tận trên website và ứng dụng

Tạo trang nhất bằng giấy thay vì màn hình

  • Tác giả muốn giảm thói quen mở điện thoại vào buổi sáng và cuộn qua nhiều trang tin tức, mạng xã hội, nhưng vẫn muốn nắm thông tin mới nhất
  • Cách triển khai là tận dụng một máy in ma trận điểm mua trên eBay để in trang nhất tùy chỉnh được chuẩn bị mỗi ngày
  • Toàn bộ mã nguồn được công khai trong GitHub repo

Chọn và kết nối phần cứng

  • Các linh kiện cần thiết tương đối đơn giản
  • Máy in được sử dụng là Star NP-10, có vẻ là sản phẩm từ giữa thập niên 1980
    • Nếu là máy in ma trận điểm có cổng song song thì có khả năng hoạt động
    • Mức giá phổ biến khoảng 80~120 USD, nhưng tác giả mua được với giá khoảng một nửa nhờ ghi chú “không chắc còn hoạt động”
  • Sau khi vệ sinh nhẹ và chỉnh hộp băng mực, tác giả đã in thử trang thành công
  • Raspberry Pi được kết nối WiFi và nối với cổng song song của máy in qua bộ chuyển đổi USB
    • Sau khi truy cập Pi bằng ssh, tác giả xác nhận máy in được nhận ở /dev/usb/lp0

Gửi dữ liệu trực tiếp tới máy in

  • Ban đầu, tác giả kiểm tra khả năng in bằng cách gửi văn bản thô trực tiếp từ shell
echo "Hello, world!" > /dev/usb/lp0
  • Do gặp lỗi truy cập tệp, tác giả обход qua vấn đề quyền bằng chmod
sudo chmod 666 /dev/usb/lp0
  • Sau đó, văn bản gửi tới /dev/usb/lp0 được máy in in ra
  • Trong PHP, cách này được mở rộng bằng việc mở tệp máy in bằng fopen() rồi ghi văn bản vào đó
  • Khi thử các câu thông thường, khoảng trắng và Unicode art, tác giả nhận ra phạm vi hỗ trợ ký tự của máy in khá hạn chế

Bộ ký tự của Star NP-10

  • Tác giả tìm được hướng dẫn sử dụng Star NP-10 đã được quét để hiểu cách máy in hoạt động
  • Máy in này chỉ nhận một bộ ký tự rất cụ thể
    • Dựa lỏng lẻo trên Code Page 437 của IBM PC
    • Bao gồm các ký tự chữ-số chuẩn cùng một số ký hiệu đặc biệt, ký tự đường kẻ và khung
  • Trong PHP, có thể tạo chuỗi từ giá trị hex rồi gửi trực tiếp tới máy in
$horizontalDouble = "\xCD";
$deg = "\xF8";

echo str_repeat($horizontalDouble, 24);
echo '78' . $deg . 'F' . PHP_EOL;
  • Bằng cách này, có thể in không chỉ văn bản thông thường mà cả ký tự trang trí như đường kẻ, khung và ký hiệu nhiệt độ

Dữ liệu lấy về và API

  • Trang nhất cá nhân gồm bốn mục
    • Thời tiết
    • Chứng khoán
    • Tiêu đề tin tức chính
    • Các bài đăng Reddit hàng đầu
  • Vì đây là dự án thử nghiệm, tác giả muốn giảm chi phí dữ liệu và dùng API miễn phí khi có thể; các API cần thiết được tìm trong kho public-apis, nơi tập hợp các API công khai miễn phí
  • Các nguồn dữ liệu được sử dụng như sau
    • Open-Meteo: dữ liệu thời tiết, không cần API key
    • twelvedata: dữ liệu chứng khoán, cung cấp free tier khá rộng rãi
    • NYTimes: tiêu đề tin tức, cung cấp free tier đủ cho dự án
    • Reddit JSON: bài đăng Reddit, miễn phí nhưng cần giả lập User-Agent
  • Script PHP lấy payload từ từng API endpoint và gộp những dữ liệu cần thiết vào một mảng lớn
    • Chỉ dùng các cổ phiếu cụ thể, loại tin tức cụ thể và bài đăng từ các subreddit cụ thể
    • Nếu một trong các mục không có dữ liệu để hiển thị, script sẽ kết thúc sớm và chạy lại sau

Cách lọc dữ liệu tin tức

  • Dữ liệu NYTimes được xem là lỗi nếu phản hồi API không có results
  • Trong số các bài viết, chỉ những mục thỏa các điều kiện sau mới được gom để in
    • typeArticle
    • section là một trong U.S., World, Weather, Arts
    • Chỉ thêm khi số lượng còn nhỏ hơn giới hạn tối đa MAXNEWS
  • NEWS, NEWSKEY, MAXNEWS được định nghĩa dưới dạng hằng số ở đầu script để dễ chỉnh sửa

Định dạng bản in cho vừa giấy

  • Thay vì chỉ in tiêu đề từng mục, tác giả tạo một hộp có viền ở phần trên, chứa ngày hiện tại, thứ trong tuần và tên trang nhất
  • Layout được tính dựa trên việc chiều rộng trang của máy in là 80 ký tự
    • Ký tự hex
    • str_repeat
    • Giá trị chiều rộng trang cố định
  • Tiêu đề mục được in bằng cách kết hợp ký tự đường kẻ và văn bản
str_repeat($horizontalSingle, 3) . " WEATHER " . str_repeat($horizontalSingle, (PAGEWIDTH - 9)) . "\n";
  • Thời tiết và chứng khoán đủ ngắn để in trên một dòng mà không chạm mép giấy
  • Tiêu đề tin tức và bài đăng Reddit thường dài nên cần xử lý xuống dòng riêng

Xử lý xuống dòng cho văn bản dài

  • Máy in có thể tự động in tiếp các dòng dài xuống dòng kế tiếp
  • Tuy nhiên, để tránh việc từ bị cắt giữa chừng khi chuyển dòng, tác giả triển khai hàm chia chuỗi theo độ dài dòng tối đa
  • Hàm splitString() tách từ theo khoảng trắng và trả về một mảng sao cho mỗi dòng không vượt quá PAGEWIDTH
    • Nếu một từ đơn lẻ dài hơn độ dài tối đa, từ đó sẽ được cắt để xử lý
  • Với bài đăng Reddit, script duyệt qua mảng dòng trả về và ghi vào máy in
foreach (splitString($redditPost) as $line) {
    fwrite($printer, $line) . "\n";
}

Tự động chạy và trải nghiệm sử dụng

  • Có thể chạy thủ công bằng php print.php
  • Khi dùng thực tế, việc này được tự động hóa bằng cron job
    • Trang nhất cá nhân hóa được in mỗi ngày vào khoảng 8 giờ sáng
    • Tác giả xé tờ giấy đã in ra và đọc trong lúc uống cà phê
  • Lượng tin tức hữu hạn trên một tờ giấy mang lại cảm giác tốt hơn so với việc cuộn vô tận trên website và ứng dụng mạng xã hội
  • Quá trình kết nối phần cứng vật lý cũ với công nghệ mới cũng là một phần thú vị quan trọng của dự án

1 bình luận

 
GN⁺ 2024-10-05
Các ý kiến trên Hacker News
  • Tôi từng thử làm thứ tương tự bằng máy in hóa đơn; máy in hóa đơn nhiệt USB khoảng 75 đô la và cũng dễ điều khiển bằng Python
    Việc in hình ảnh và mã QR khá đơn giản, còn tính năng tự động cắt giúp phân tách các thông điệp rất tiện
    Cũng có thể dùng chuông bên trong như một kiểu thông báo bổ sung, và có cả ngõ ra để điều khiển ngăn kéo tiền, nên tôi đang nghĩ đến việc nối nó để điều khiển những thứ như đèn
    Tôi đã thiết lập nó cho email và cho in lịch trình mỗi sáng
    Khi dùng cùng các điều khiển vật lý như nút bấm hoặc đầu đọc NFC, giao diện khá hợp. Ví dụ như thẻ NFC để in lịch trình, thẻ NFC để in email chưa đọc, kiểu như ra “lệnh” rồi nhận bản in
    Đây là một cách thú vị để giảm thời gian nhìn màn hình, nhưng trớ trêu là có lẽ tôi đã nhìn màn hình lâu hơn để code và cấu hình nó so với thời gian tiết kiệm được

    • Máy in hóa đơn rất thú vị, nhưng phải cẩn thận để không mua giấy nhiệt độc hại
      https://www.consumerreports.org/cro/news/2014/03/the-health-...
    • Máy in nhiệt của tôi cũng in thời tiết mỗi sáng, và in thông báo nếu một thiết bị quan trọng bị rớt khỏi mạng
    • Máy in hóa đơn thật sự rất vui. Vài năm trước tôi từng làm một dự án in ticket GitHub với cấu hình tương tự, khá giống cấu hình tôi đang dùng cho máy in ma trận điểm hiện nay
    • Tôi tò mò bạn dùng máy in nào. Tôi đang nghĩ đến việc mua một cái, nhưng không biết về tính năng thông báo và khả năng điều khiển bên ngoài mà bạn nói
  • Hôm nay chợt thấy tò mò
    Một trong những việc người này làm chỉ là echo vào /dev/lp0, mà ngày xưa vốn đúng là làm như vậy. Bạn đẩy văn bản vào giao diện là máy in sẽ in ra
    Máy in ngày nay hào nhoáng hơn nhiều, nhưng về cơ bản vẫn là máy in với một di sản rất dài. Ngay cả các máy in laser HP đời đầu, nếu gửi dữ liệu qua dây, cũng sẽ in bằng Courier 10, 66 dòng mỗi trang. Có lẽ chỉ Apple LaserWriter là không theo kiểu đó vì là máy in PostScript chuyên dụng; thay vào đó, bạn đẩy PostScript vào
    Khi máy in phát triển, ngôn ngữ gửi đến chúng trở nên phức tạp hơn, nhưng chúng vẫn duy trì khả năng tương thích ngược rất lâu dài
    Vậy nếu cắm máy in USB vào máy tính rồi chạy ls > /dev/usbXXX thì ngày nay nó có in không? Liệu nó vẫn cứ hoạt động chứ?
    Nếu gửi mã escape EPSON MX-80 tới EPSON thì liệu vẫn chạy không? Dù câu trả lời là bên nào tôi cũng không ngạc nhiên, nhưng máy in ngày nay với tôi khá giống hộp đen, nên tôi tò mò không biết có ai biết không
    Chắc cũng có người còn nhớ niềm vui vật lộn để báo cáo in khớp với các biểu mẫu NCR nhiều liên đã in sẵn

    • Tôi vừa thử trên OS X, có vẻ nó không phơi máy in ra dưới /dev/ theo cách bạn mô tả. Thay vào đó OS X cũng có lp, nên có thể dùng kiểu echo "Hello printer" | lp -d, còn tên thì tìm bằng lpstat -p
      Thử với máy in mới thì đúng là hoạt động
    • Hai cách dưới đây đều chạy được trong môi trường của tôi
      printf 'hello\f' > /dev/usb/lp0
      printf 'hello\f' | nc -N $printer_ip 9100
      Đây là với máy in laser Brother, và bên cạnh tài liệu hướng dẫn trực tuyến có liên kết đến hướng dẫn lập trình. Ngôn ngữ là PCL, nhưng để in đơn giản thì không cần biết nhiều
      Hai cách trên không dùng CUPS. Như bình luận khác nói, nếu muốn dùng các chương trình thực thi lp/lpr thì trước tiên máy in phải được đăng ký trong CUPS
      Với trường hợp ls >, máy in kỳ vọng xuống dòng kiểu DOS. \n chỉ chuyển sang dòng mới mà không “đưa đầu in về đầu dòng”, nên cần pipe qua sed 's/$/\r/' hoặc dùng nc -C
      Với kết nối USB, có thể in nhiều lần để tạo thành một trang, và giấy sẽ không chạy ra cho đến khi gửi form feed. Với kết nối TCP, trang được in khi kết nối đóng
    • Tôi có một chiếc Epson LX-350 mua mới vài năm trước, kết nối qua USB và cũng có cổng serial/parallel. Khi nối USB, nó hiện ra kiểu như /dev/usblp0, và chỉ cần gửi bằng cat cũng chạy
      Khách hàng mua mới những sản phẩm này chắc sẽ muốn chúng tương thích với các quy trình họ đã dùng suốt 30–50 năm qua, nên đúng như dự đoán, nó hỗ trợ ESC/P 2 và cả mã escape của IBM. Tôi thấy bất ngờ vì các máy in ma trận cũ tôi dùng hồi thập niên 90 hình như không hỗ trợ mã IBM
      Điều đáng ngạc nhiên hơn là MacBook có sẵn driver tích hợp cho máy in Epson phổ dụng và nó hoạt động. Chất lượng không tốt lắm và in dưới dạng đồ họa, nhưng dù sao nó vẫn tồn tại
      Tôi không rõ về các máy in phun và laser hiện đại. Máy in phun Epson tôi dùng khoảng 20 năm trước có hỗ trợ mã ESC/P thô
    • Máy in mạng cũng làm được. Gửi PDF bằng netcat vào cổng đang mở là nó in
      https://retrohacker.substack.com/p/bye-cups-printing-with-ne...
    • Phòng máy tính ở trường trong thập niên 1990 vẫn có máy in ma trận điểm, và nó được đặt làm máy in mặc định trên mọi máy tính trong mạng
      Một lỗi người dùng thường gặp là khi ai đó cố in tài liệu Word, PostScript bị gửi tới máy in ma trận điểm, và máy in trung thành in nguyên mã nguồn PostScript đó, lãng phí giấy và ruy-băng cho đến khi có người dừng nó lại
  • Máy in ma trận điểm cũng có thể làm được khá nhiều việc tùy theo mẫu máy: đổi phông chữ, in đậm, gạch chân, đôi khi in nghiêng, ký tự rộng/cao gấp đôi, thậm chí cả đồ họa. Tuy vậy đồ họa thường có độ phân giải tương đối thấp, như 90 hoặc 180 DPI
    Trước đây tôi từng làm một cái hộp chỉ có đầu nối máy in song song cho một thứ giống trò chơi thoát khỏi phòng. Khi nối với máy in, nó lấy nguồn ký sinh từ một đường điều khiển của cổng song song, rồi một vi điều khiển PIC rất nhỏ chỉ dùng vài trăm µA để gửi gợi ý ra máy in

    • Ngày xưa, trong số các chương trình dàn trang desktop đời đầu có một thứ của SoftCraft tên là Fancy Font. Vì là chương trình CP/M và sau này là DOS, nó không phải công cụ dàn trang WYSIWYG như PageMaker, mà dùng tài liệu văn bản được định dạng bằng một ngôn ngữ đánh dấu đơn giản
      Ban đầu nó tận dụng chế độ đồ họa độ phân giải cao của máy in ma trận điểm Epson. Các máy in này có thể tinh chỉnh trục cuốn giấy nhỏ bằng 1/3 khoảng cách giữa các kim của đầu in, nên đạt được độ phân giải dọc gấp 3 lần so với chỉ dùng đầu in
      Fancy Font render văn bản trên máy tính rồi gửi ra dưới dạng đồ họa ở chế độ độ phân giải cao đặc biệt này, tạo ra kết quả gần với chế bản nhất có thể bằng thiết bị gia đình đầu thập niên 1980
      Các phiên bản sau cũng có driver cho các máy in laser đời đầu như HP LaserJet nguyên bản, nhưng khi Mac xuất hiện thì tương lai của những hệ thống như vậy đã quá rõ
    • Bố tôi có một máy in ma trận điểm 4 màu vào thập niên 90. In cái đầu Pharaoh trong Deluxe Paint II mất cực kỳ lâu, nhưng thực sự khá đẹp
      Có điều sau khi in xong giấy bị cong rất nặng. Tôi vẫn còn giữ máy in, nhưng không biết kiếm ruy-băng 4 màu ở đâu
    • Tôi còn nhớ việc in những banner khổng lồ theo chiều ngang trên cuộn giấy vô tận. Nó giống kiểu nghệ thuật ASCII mà các lệnh như figlet tạo ra trong terminal ngày nay. Biết đâu nó vẫn còn hỗ trợ xuất ra máy in
    • Xét từ góc độ thiết kế, tôi từng muốn đào sâu thêm thứ này. Trong sách hướng dẫn thật sự có hàng chục trang nói về cỡ chữ, nhấn mạnh, in nghiêng, chỉ số dưới/trên và những thứ tương tự
      Có lẽ tôi sẽ thử trong phiên bản 2.0
    • Nếu có một terminal hiểu ESC/P và hỗ trợ nhiều phông chữ cùng những thứ như CPI thì sẽ thú vị
  • Tôi đã nối cái máy này với feed tin tức trong vài năm.[1] Đây là cơ cấu của máy in băng Teletype Model 14, vẫn còn ở phòng khách nhà tôi, và băng giấy chảy ra một cái giỏ dây thép
    Nó được điều khiển bằng một chương trình Python trên một chiếc subnotebook EeePC cũ
    [1] https://aetherltd.com/refurbishing14.html

    • Quá ngầu. Tôi vẫn luôn muốn kiếm một thiết bị như vậy để mô phỏng ticker tape in giá cổ phiếu/tiền mã hóa được cập nhật liên tục
      Cái tên EeePC cũng lâu lắm rồi mới nghe lại, gợi nhớ nhiều kỷ niệm
  • Trông đúng là một ý tưởng sản phẩm xuất sắc. Ý tưởng mỗi sáng nhận một feed tin tức được cá nhân hóa, lại còn là feed tin ngoài màn hình thật sự do chính mình chọn chứ không phải kiểu MSN, rất hay
    Nếu thêm nữa có thể thay đồng hồ báo thức bằng máy in ma trận điểm thì càng tuyệt
    Việc sửa PHP cho phù hợp với nguồn tin của tôi thì tôi làm dễ, nhưng không biết phải tự bắt đầu phần phần cứng như thế nào. Chắc có khá nhiều người ở tình cảnh này
    Nếu nó được bán ra thị trường, tôi nghĩ mình sẽ mua dù đắt hơn nhiều so với giá máy in cũ

    • Từ kinh nghiệm từng làm thứ tương tự, thực ra khá dễ. Chỉ cần nối máy in vào rồi ghi ra đầu ra dev. Nếu giả định chạy trên Linux thì đầu ra đó chỉ là một file
      Phần khó nhất là kết nối máy in, vì có thể cần cáp chuyển đổi
  • Gọn gàng thật. Nó làm tôi nhớ hồi từng làm một thời gian ngắn ở đài phát thanh. Tôi gần như quên hết chi tiết, nhưng hình như hệ thống tự động quay số tới một số Associated Press nào đó để lấy các tiêu đề mới nhất rồi gửi sang máy in ma trận điểm
    Đó là cuối thập niên 90 và nó chạy trên MS-DOS
    Thời đó hầu hết máy in có thể đặt phông chữ bằng mã điều khiển, và nhiều máy còn có phông chữ tỷ lệ

  • Hay đấy. Dạo này tôi đang nghĩ đến việc đăng ký một báo giấy cuối tuần như FT Weekend, vì tôi đọc tin tức trên điện thoại quá thường xuyên
    Tin tức thường không hữu ích mấy mà lại chỉ tạo ra cảm xúc tiêu cực. Nếu đọc tin trên giấy, lại chỉ mỗi tuần một lần, có lẽ sẽ dễ chịu hơn
    Cách in tin tức ra giấy hằng ngày này có vẻ là lựa chọn tốt để lấp khoảng giữa
    Nhân tiện, tôi rất thích máy in ma trận điểm. Có máy in mã nguồn mở nào phù hợp để hack kiểu này không?

    • Khó mà khuyên dùng FT
      Tôi từng thử đăng ký báo giấy nhưng không nhận được số nào; phải gọi điện 3 lần và gửi khoảng 10 email, rồi đến khi yêu cầu hủy đăng ký và hoàn tiền họ mới nói sẽ chuyển ticket lên cấp cao hơn. Lúc đó đã là 3 tuần sau và tôi cũng đã tốn rất nhiều thời gian
      Vì vậy tôi cũng rất quan tâm đến việc tự in tin từ Internet để khỏi phải nhìn màn hình liên tục
  • Tôi đã in “thẻ ba mặt” được một thời gian. Một mặt có hình ảnh, mặt kia có mã QR dẫn tới tài liệu
    https://mastodon.social/@UP8/111013706271196029
    “Mặt thứ ba” là trang web mà mã QR trỏ tới
    Tôi chán ảnh chụp nên đã tạo ra một nhân vật luôn mang theo ống kính rẻ tiền, luôn khép khẩu từ f/18 trở lên, hậu kỳ và chỉnh màu rất mạnh, chụp với tỷ lệ khung hình tiêu chuẩn nhưng lại có cảm giác phi tiêu chuẩn. Thiết lập là làm cho nó trông như thể dùng một chiếc máy ảnh kỳ lạ từ một dòng thời gian thay thế
    Khi bắt đầu in loạt này, tôi kết luận rằng cắt ảnh 4x6 thì dễ tạo ra 4x5, nhưng thay vì cắt, có thể chừa lại khoảng 1 inch để đặt mã QR và tài liệu ở mặt trước. Tương tự, nếu cắt 5x7 thành hình vuông 5x5 thì sẽ có chỗ cho tài liệu
    Tôi có vài hộp giấy bóng không thể in mặt sau, nên định dùng theo cách đó. Sau này tôi cũng biết Instagram có chuẩn 4x5, và ảnh thể thao chụp bằng ống kính tốt trông rất đẹp ở định dạng đó
    Có điều tôi đang phân vân tài liệu nên trông như thế nào. Tôi bị giằng giữa cách chỉ thay đổi tối thiểu so với bố cục hiện tại, một hiệu ứng ma trận điểm giả trông như máy in cũ có thể được tích hợp trong chiếc máy ảnh tưởng tượng đó, hoặc một cách tận dụng tối đa thế mạnh của máy in phun

    • Tôi muốn hiểu, nhưng cảm giác là hoặc bài viết này, hoặc tôi, đang thiếu rất nhiều ngữ cảnh. Gần như đoạn nào cũng có vẻ hoàn toàn không liên quan tới đoạn trước đó
  • Nếu “vì đây là dự án thử nghiệm nên muốn giữ chi phí dữ liệu này thật rẻ, nếu được thì miễn phí”, thì cũng có NewsCatcher. Miễn phí cho các side project mã nguồn mở
    https://docs.google.com/forms/d/e/1FAIpQLSejrsj4a1ZQkIasiKCt...

  • Hơi liên quan một chút, tôi đang dùng một script nhỏ để mở trang nhất NYTimes trên MacBook mỗi sáng
    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