Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: graiz/newsprint
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: V0.1
Choose a base ref
...
head repository: graiz/newsprint
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: main
Choose a head ref
  • 16 commits
  • 4 files changed
  • 2 contributors

Commits on Mar 25, 2021

  1. Copy the full SHA
    a34bb8e View commit details
  2. Copy the full SHA
    c840da5 View commit details

Commits on Mar 29, 2021

  1. Added Visionect link

    Added product link.
    graiz authored Mar 29, 2021

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    854ac6b View commit details

Commits on Mar 30, 2021

  1. Code cleanup

    Some older versions of PHP may complain so I used more strict syntax on the date object, PHP tags and I also made it generic to call the convert function without a path.
    
    This should make it more compatible.
    graiz committed Mar 30, 2021
    Copy the full SHA
    6672565 View commit details
  2. Copy the full SHA
    7a2cc9c View commit details

Commits on Apr 1, 2021

  1. Fix start of month URL

    Freedomforum doesn't use leading zeros in the date format of their URL's. This wasn't obvious when testing at the end of the month.
    graiz committed Apr 1, 2021
    Copy the full SHA
    b91d023 View commit details
  2. Copy the full SHA
    5f41344 View commit details
  3. Fix index reset

    Blank index request can cause issues.
    graiz committed Apr 1, 2021
    Copy the full SHA
    06d600d View commit details
  4. Copy the full SHA
    7181f8e View commit details

Commits on Apr 12, 2021

  1. Copy the full SHA
    b20f680 View commit details

Commits on May 7, 2021

  1. Copy the full SHA
    0ccf2b8 View commit details
  2. Copy the full SHA
    0c88813 View commit details

Commits on May 27, 2021

  1. Copy the full SHA
    2596539 View commit details

Commits on Jul 12, 2023

  1. Update README.md

    graiz authored Jul 12, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    6645ddc View commit details
  2. Update README.md

    graiz authored Jul 12, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    1b9c77d View commit details

Commits on Jul 13, 2023

  1. Update README.md

    added link for the visionect server install.
    graiz authored Jul 13, 2023

    Verified

    This commit was created on GitHub.com and signed with GitHub’s verified signature. The key has expired.
    Copy the full SHA
    ae31b4a View commit details
Showing with 60 additions and 43 deletions.
  1. +3 −0 .gitignore
  2. +9 −0 LICENSE
  3. +4 −3 README.md
  4. +44 −40 index.php
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
/archive/*
counter.txt

9 changes: 9 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
The MIT License (MIT)

Copyright © 2021 Gregory Raiz and other contributors

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
# newsprint

![GitHub Logo](https://gregraiz.com/wp-content/uploads/2021/03/concept.png)

[The blog post and video](https://gregraiz.com/posts/i-made-an-eink-newspaper) that accompany this code give a general overview of the project.

Newsprint is a simple web application that will fetch the front page of a newspaper and display it on an eink display. The specific resolutions and sizes have been setup to work with a 32" eInk place & play display from Visionect but can be modified for other screen resolutions.

There are two portions to getting this up and running. The first is the application server that displays the newspaper. This code is setup to be run on a simple and low cost PHP webhost with very few dependancies. Simply copy the PHP files into a directory on your server and you should be good to go. You will need an "archive" folder on the server and the ability to call the command line "convert" utility to resize/convert images. Most hosts should have this installed as it's fairly standard.

The current newspapers that I've setup include the Boston Globe, New York Times, Wall St Journal, LA Times, Toronto Star and SF Chronical. Additional sources are easy to add by looking up the newspaper prefix on freedomforum.org. This is typically two letter State and newspaper abbreviation (NY_NYT or MA_BG). Each newspaper is then adjusted to display as much of the paper as possible. Many newspapers have a boarder or printing margin and I've tried to subtract this out in the samples.

The second portion of the software needed to get this running is the Visionect server. This has to run on the same network as the eInk display. The display itself is not standalone, it's a thin client and requires the Visionect software to act as an HTML rendering engine of sorts. The Visionect server software can be run on any docker server and general installation instructions are on the Visionect site. I was able to get it to run on my Synology server with a slightly modified file. The details of this are in the docker folder of this repo.
The second portion of the software needed to get this running is the Visionect server. Information on the [Visionect docker container and server](https://docs.visionect.com/VisionectSoftwareSuite/Installation.html) are available for install. This has to run on the same network as the eInk display. The display itself is not standalone, it's a thin client and requires the Visionect software to act as an HTML rendering engine of sorts. The Visionect server software can be run on any docker server and general installation instructions are on the Visionect site. I was able to get it to run on my Synology server with a slightly modified file. The details of this are in the docker folder of this repo.

[__Affiliate link to Visionect eInk Display that was used__](https://www.visionect.com/ref/graiz/)
84 changes: 44 additions & 40 deletions index.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
<?php
// Don't cache this page.
// Don't cache this page.
header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0");
header("Cache-Control: post-check=0, pre-check=0", false);
header("Pragma: no-cache");
@@ -10,49 +10,53 @@
// https://cdn.freedomforum.org/dfp/pdf16/MA_BG.pdf

$news = array();
$paper['prefix']="WSJ";$paper['style']="width:98%;margin:-70px 0px 0px -15px";array_push($news,$paper); // Wall St Journal
$paper['prefix']="MA_BG";$paper['style']="width:98%;margin:5px 10px 0px 8px";array_push($news,$paper); // Boston Globe
$paper['prefix']="NY_NYT";$paper['style']="width:99%;margin:-88px 14px 0px 3px";array_push($news,$paper); // New York Times
$paper['prefix']="CA_LAT";$paper['style']="width:94%;margin:-2% 0px 0px 0px";array_push($news,$paper); // L.A. Times
$paper['prefix']="CAN_TS";$paper['style']="width:90%;margin:-70px 0px 0px 0px";array_push($news,$paper); // Toronto Star
$paper['prefix']="CA_SFC";$paper['style']="width:96%;margin:-20px 0px 0px 0px";array_push($news,$paper); // San Fran Chronical

//$paper['prefix']="WSJ";$paper['style']="width:98%;margin:-70px 0px 0px -15px";array_push($news,$paper); // WSJ -broken 2021
$paper['prefix']="DC_WP";$paper['style']="width:108%;margin:-5% -5% 0px -5%";array_push($news,$paper); // Washington Post
$paper['prefix']="MA_BG";$paper['style']="width:98%;margin:5px 10px 0px 8px";array_push($news,$paper); // Boston Globe
$paper['prefix']="NY_NYT";$paper['style']="width:99%;margin:-28px 14px 0px 3px";array_push($news,$paper); // New York Times
$paper['prefix']="CA_LAT";$paper['style']="width:94%;margin:-2% 0px 0px 0px";array_push($news,$paper); // L.A. Times
$paper['prefix']="CAN_TS";$paper['style']="width:90%;margin:-70px 0px 0px 0px";array_push($news,$paper);// Toronto Star
$paper['prefix']="CA_SFC";$paper['style']="width:96%;margin:-20px 0px 0px 0px";array_push($news,$paper); // SF Chronical
$maxPapers = count($news) -1;

// Loop a counter without a DB.
// allows us to get a different newspaper
// each load by asking for the counter
// allows us to get a different newspaper
// each load by asking for the counter
function getCounter() {
global $maxPapers;
$fp = fopen("counter.txt", "r");
$x= intval(fread($fp,1024));
if ($x > $maxPapers) {
if ($fp) {
$x= intval(fread($fp,1024));
fclose($fp);
} else {
$x = 0;
}
if ($x > $maxPapers) {
$x = 0;
}
fclose($fp);
if (strlen($_REQUEST['index'])) { // Override the counter if there
if (!empty($_REQUEST['index'])) { // Override the counter if there
$x = $_REQUEST['index']; // is a URL parameter for index
}
return($x);
}
function incrementCounter(int $counter){
// increment the paper for next time
$counter++;
$fp = fopen("counter.txt", "w");
fwrite($fp, $counter);
fclose($fp);
$fp = fopen("counter.txt", "w");
fwrite($fp, $counter);
fclose($fp);
}

// fetch a paper and cache in as a JPG. Return the path to the JPG if we found it.
// We can pass in an offset in days to get yesterday or two days ago
// fetch a paper and cache in as a JPG. Return the path to the JPG if we found it.
// We can pass in an offset in days to get yesterday or two days ago
function fetchPaper($prefix, $offset=0){
$pathToPdf = "https://cdn.freedomforum.org/dfp/pdf" . date(d,strtotime("-" . $offset . " days")) . "/" . $prefix . ".pdf";
$pdffile = "archive/" . $prefix . "_" . date('Ymd',strtotime("-" . $offset . " days")) . ".pdf";
$jpgfile = "archive/" . $prefix . "_" . date('Ymd',strtotime("-" . $offset . " days")) . ".jpg";
$rootpath = getcwd() . "/";
$pathToPdf = "https://cdn.freedomforum.org/dfp/pdf" . date('j',strtotime("-" . $offset . " days")) . "/" . $prefix . ".pdf";
$pdffile = "archive/" . $prefix . "_" . date('Ymd',strtotime("-" . $offset . " days")) . ".pdf";
$pngfile = "archive/" . $prefix . "_" . date('Ymd',strtotime("-" . $offset . " days")) . ".png";
$rootpath = getcwd() . "/";
// check if a jpg has already been created
// if not we start checking for the PDF and converting
if (!file_exists($jpgfile)){
if (!file_exists($pngfile)){
$file_headers = @get_headers($pathToPdf);
if(!$file_headers || $file_headers[0] == 'HTTP/1.1 404 Not Found') {
$exists = false;
@@ -63,30 +67,31 @@ function fetchPaper($prefix, $offset=0){
$data = curl_exec($ch);
curl_close($ch);
$exists = true;
$result = file_put_contents($pdffile, $data);
$result = file_put_contents($pdffile, $data);
}
if ($exists) { // convert a high-dpi image, force a white background and
// resize to 1600px wide at 95% jpg quality
$command = '/bin/convert -density 300 -background white -alpha remove ' . $rootpath . $pdffile .
' -colorspace RGB -resize 1600 -quality 95 ' . $rootpath . $jpgfile;
exec($command, $output, $response);
if ($exists) {
$command = "convert -density 300 -background white -alpha remove '" . $rootpath . $pdffile .
"' -colorspace Gray -resize 1600 '" . $rootpath . $pngfile . "'";
exec($command, $output, $response);
}
} else {
$exists = true;
}
if ($exists) {
return $jpgfile;
return $pngfile;
} else {
return false;
}
}

$currentIndex = getCounter();

if (isset($_REQUEST['index'])) {
$currentIndex = $_REQUEST['index'];
}


$imageresult = fetchPaper($news[$currentIndex]['prefix'],0); // Fetch today
if (empty($imageresult)) {
$imageresult = fetchPaper($news[$currentIndex]['prefix'],1); // yesterday
$imageresult = fetchPaper($news[$currentIndex]['prefix'],1); // yesterday
}
if (empty($imageresult)) {
$imageresult = fetchPaper($news[$currentIndex]['prefix'],2); // twesterday
@@ -99,21 +104,20 @@ function fetchPaper($prefix, $offset=0){
body { text-align:center; }
.paper {
background-color:white;
<?=$news[$currentIndex]['style']?>
<?php echo $news[$currentIndex]['style'] ?>
}
</style>
</head>
<body>
<?if (strlen($jpgfile)> 0) {
echo "Newspaper File Not Found. " . $imageresult. " Will keep looking. Checking again in another hour.";
<?php if (strlen($imageresult) < 1) {
echo "Newspaper File Not Found. " . $imageresult. " Will keep looking. Checking again in another hour.";
} else {
echo "<img src='" . $imageresult . "' class='paper' >";
}
}
?>
</div>
</body>
</html>
<?
<?php
incrementCounter($currentIndex);
?>