summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorschneefux <schneefux+commit@schneefux.xyz>2020-01-26 12:02:24 +0100
committerschneefux <schneefux+commit@schneefux.xyz>2020-01-26 15:55:18 +0100
commit8b1a693f9f8492f9a9e49aef6b3a64ace9e50e9d (patch)
tree75e165d64e6758113151d10e871563ae428bc773
downloadmagic-kindle-8b1a693f9f8492f9a9e49aef6b3a64ace9e50e9d.tar.gz
magic-kindle-8b1a693f9f8492f9a9e49aef6b3a64ace9e50e9d.zip
Import into gitHEADmaster
-rw-r--r--README.md33
-rw-r--r--demo.jpgbin0 -> 94737 bytes
-rw-r--r--magiccapture/eink_cmap.gifbin0 -> 377 bytes
-rw-r--r--magiccapture/index.js21
-rw-r--r--magiccapture/package-lock.json317
-rw-r--r--magiccapture/package.json14
-rw-r--r--magiccapture/run.sh4
-rw-r--r--magickindle/bin/start.sh58
-rw-r--r--magickindle/config.xml12
-rw-r--r--magickindle/menu.json9
-rw-r--r--magicmirror/config/config.js73
-rw-r--r--magicmirror/css/custom.css58
-rw-r--r--magicmirror/css/main.css243
13 files changed, 842 insertions, 0 deletions
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..536f2f2
--- /dev/null
+++ b/README.md
@@ -0,0 +1,33 @@
+Magic Kindle
+===
+
+Kindle 4 NT hacked to show the Magic Mirror 2 as screensaver.
+
+<img src="demo.jpg" height="300" />
+
+Server Setup
+---
+
+ * Install MagicMirror on localhost, for example in Docker: https://magicmirror.builders/
+ * Install modules, for example a slideshow: https://github.com/roramirez/MMM-ImagesPhotos
+ * Configure MagicMirror and its modules, for example as in `./magicmirror/config`. Avoid transitions and colors.
+ * Customize the CSS, for example as in `./magicmirror/css`.
+ * Install the dependencies of `./magiccapture` and Chromium.
+ * Make sure that the URL in `./magiccapture/index.js` points to the MagicMirror address.
+ * Set up a cron job to run `./magiccapture/run.sh`.
+ * Use a web server and make `./magiccapture/screenshot/screenshot.png` accessible to the network the Kindle will be connected to.
+ * Start MagicMirror, run the cron job and verify that a black/white PNG is being served.
+
+Kindle Setup
+---
+
+ * Get a Kindle 4. This setup was tested on firmware 4.1.3.
+ * Install the jailbreak and USBNetworking, the screensaver hack is not needed: https://wiki.mobileread.com/wiki/Kindle4NTHacking
+ * Install the MKK and KUAL: https://www.mobileread.com/forums/showthread.php?t=203326
+ * Move `./magickindle/` to the Kindle at `/extensions/`.
+ * Change the URL in `./magickindle/bin/start.sh` so that it points to the web server.
+ * Optionally, customize the `rtcWakeup` time. The length of the interval has a significant impact on how long the battery lasts, as the Kindle only consumes power for the one minute wakeup.
+ * Navigate to the KUAL application on the Kindle and start the Magic Kindle extension.
+ * Press the power button to activate the screensaver which triggers the Magic Kindle script.
+
+Enclose the Kindle in a fitting photo frame. Charge it once a month. If it does not turn on, press the power button for a minute and press it again for 10 seconds to force a reboot.
diff --git a/demo.jpg b/demo.jpg
new file mode 100644
index 0000000..499c8ba
--- /dev/null
+++ b/demo.jpg
Binary files differ
diff --git a/magiccapture/eink_cmap.gif b/magiccapture/eink_cmap.gif
new file mode 100644
index 0000000..4f51ee2
--- /dev/null
+++ b/magiccapture/eink_cmap.gif
Binary files differ
diff --git a/magiccapture/index.js b/magiccapture/index.js
new file mode 100644
index 0000000..0db29a6
--- /dev/null
+++ b/magiccapture/index.js
@@ -0,0 +1,21 @@
+const path = require('path');
+const puppeteer = require('puppeteer-core');
+
+async function main() {
+ const browser = await puppeteer.launch({
+ executablePath: 'google-chrome-stable',
+ args: ['--no-sandbox'],
+ })
+ const page = await browser.newPage();
+ await page.setViewport({
+ width: 600,
+ height: 800
+ });
+ await page.goto(`http://localhost:8080`, { waitUntil: 'networkidle0' });
+ await page.waitFor(2000);
+ await page.screenshot({path: 'screenshot/color.png'});
+
+ await browser.close();
+}
+
+main().then(console.log).catch(console.error)
diff --git a/magiccapture/package-lock.json b/magiccapture/package-lock.json
new file mode 100644
index 0000000..d2aa5e0
--- /dev/null
+++ b/magiccapture/package-lock.json
@@ -0,0 +1,317 @@
+{
+ "name": "screenshot",
+ "version": "1.0.0",
+ "lockfileVersion": 1,
+ "requires": true,
+ "dependencies": {
+ "agent-base": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-4.3.0.tgz",
+ "integrity": "sha512-salcGninV0nPrwpGNn4VTXBb1SOuXQBiqbrNXoeizJsHrsL6ERFM2Ne3JUSBWRE6aeNJI2ROP/WEEIDUiDe3cg==",
+ "requires": {
+ "es6-promisify": "^5.0.0"
+ }
+ },
+ "async-limiter": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
+ "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ=="
+ },
+ "balanced-match": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
+ "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
+ },
+ "brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "requires": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "buffer-from": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.1.tgz",
+ "integrity": "sha512-MQcXEUbCKtEo7bhqEs6560Hyd4XaovZlO/k9V3hjVUF/zwW7KBVdSK4gIt/bzwS9MbR5qob+F5jusZsb0YQK2A=="
+ },
+ "concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
+ },
+ "concat-stream": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-1.6.2.tgz",
+ "integrity": "sha512-27HBghJxjiZtIk3Ycvn/4kbJk/1uZuJFfuPEns6LaEvpvG1f0hTea8lilrouyo9mVc2GWdcEZ8OLoGmSADlrCw==",
+ "requires": {
+ "buffer-from": "^1.0.0",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "core-util-is": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
+ "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac="
+ },
+ "debug": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.1.tgz",
+ "integrity": "sha512-pYAIzeRo8J6KPEaJ0VWOh5Pzkbw/RetuzehGM7QRRX5he4fPHx2rdKMB256ehJCkX+XRQm16eZLqLNS8RSZXZw==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ },
+ "es6-promise": {
+ "version": "4.2.8",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-4.2.8.tgz",
+ "integrity": "sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w=="
+ },
+ "es6-promisify": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/es6-promisify/-/es6-promisify-5.0.0.tgz",
+ "integrity": "sha1-UQnWLz5W6pZ8S2NQWu8IKRyKUgM=",
+ "requires": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "extract-zip": {
+ "version": "1.6.7",
+ "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-1.6.7.tgz",
+ "integrity": "sha1-qEC0uK9kAyZMjbV/Txp0Mz74H+k=",
+ "requires": {
+ "concat-stream": "1.6.2",
+ "debug": "2.6.9",
+ "mkdirp": "0.5.1",
+ "yauzl": "2.4.1"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "requires": {
+ "ms": "2.0.0"
+ }
+ },
+ "ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g="
+ }
+ }
+ },
+ "fd-slicer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.0.1.tgz",
+ "integrity": "sha1-i1vL2ewyfFBBv5qwI/1nUPEXfmU=",
+ "requires": {
+ "pend": "~1.2.0"
+ }
+ },
+ "fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8="
+ },
+ "glob": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz",
+ "integrity": "sha512-LwaxwyZ72Lk7vZINtNNrywX0ZuLyStrdDtabefZKAY5ZGJhVtgdznluResxNmPitE0SAO+O26sWTHeKSI2wMBA==",
+ "requires": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ }
+ },
+ "https-proxy-agent": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-3.0.1.tgz",
+ "integrity": "sha512-+ML2Rbh6DAuee7d07tYGEKOEi2voWPUGan+ExdPbPW6Z3svq+JCqr0v8WmKPOkz1vOVykPCBSuobe7G8GJUtVg==",
+ "requires": {
+ "agent-base": "^4.3.0",
+ "debug": "^3.1.0"
+ },
+ "dependencies": {
+ "debug": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz",
+ "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==",
+ "requires": {
+ "ms": "^2.1.1"
+ }
+ }
+ }
+ },
+ "inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=",
+ "requires": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
+ },
+ "isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE="
+ },
+ "mime": {
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-2.4.4.tgz",
+ "integrity": "sha512-LRxmNwziLPT828z+4YkNzloCFC2YM4wrB99k+AV5ZbEyfGNWfG8SO1FUXLmLDBSo89NrJZ4DIWeLjy1CHGhMGA=="
+ },
+ "minimatch": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
+ "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==",
+ "requires": {
+ "brace-expansion": "^1.1.7"
+ }
+ },
+ "minimist": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz",
+ "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0="
+ },
+ "mkdirp": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz",
+ "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=",
+ "requires": {
+ "minimist": "0.0.8"
+ }
+ },
+ "ms": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
+ "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ },
+ "once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=",
+ "requires": {
+ "wrappy": "1"
+ }
+ },
+ "path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
+ },
+ "pend": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz",
+ "integrity": "sha1-elfrVQpng/kRUzH89GY9XI4AelA="
+ },
+ "process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
+ },
+ "progress": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
+ "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA=="
+ },
+ "proxy-from-env": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz",
+ "integrity": "sha1-M8UDmPcOp+uW0h97gXYwpVeRx+4="
+ },
+ "puppeteer-core": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/puppeteer-core/-/puppeteer-core-2.0.0.tgz",
+ "integrity": "sha512-xgg8hLm7VIiwoYRZtgXNy0gf9IKCA/WyT5Rm5RqkDc7mm4bJMeESmzP+YWyl+X/c1CSOuCy4WWnnC+9T+DKgCQ==",
+ "requires": {
+ "debug": "^4.1.0",
+ "extract-zip": "^1.6.6",
+ "https-proxy-agent": "^3.0.0",
+ "mime": "^2.0.3",
+ "progress": "^2.0.1",
+ "proxy-from-env": "^1.0.0",
+ "rimraf": "^2.6.1",
+ "ws": "^6.1.0"
+ }
+ },
+ "readable-stream": {
+ "version": "2.3.7",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
+ "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "requires": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "rimraf": {
+ "version": "2.7.1",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
+ "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "requires": {
+ "glob": "^7.1.3"
+ }
+ },
+ "safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
+ },
+ "string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "requires": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c="
+ },
+ "util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8="
+ },
+ "wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8="
+ },
+ "ws": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.1.tgz",
+ "integrity": "sha512-GIyAXC2cB7LjvpgMt9EKS2ldqr0MTrORaleiOno6TweZ6r3TKtoFQWay/2PceJ3RuBasOHzXNn5Lrw1X0bEjqA==",
+ "requires": {
+ "async-limiter": "~1.0.0"
+ }
+ },
+ "yauzl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.4.1.tgz",
+ "integrity": "sha1-lSj0QtqxsihOWLQ3m7GU4i4MQAU=",
+ "requires": {
+ "fd-slicer": "~1.0.1"
+ }
+ }
+ }
+}
diff --git a/magiccapture/package.json b/magiccapture/package.json
new file mode 100644
index 0000000..2704ca8
--- /dev/null
+++ b/magiccapture/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "screenshot",
+ "version": "1.0.0",
+ "description": "",
+ "main": "index.js",
+ "scripts": {
+ "start": "node index.js"
+ },
+ "author": "schneefux",
+ "license": "UNLICENSED",
+ "dependencies": {
+ "puppeteer-core": "^2.0.0"
+ }
+}
diff --git a/magiccapture/run.sh b/magiccapture/run.sh
new file mode 100644
index 0000000..354c8b6
--- /dev/null
+++ b/magiccapture/run.sh
@@ -0,0 +1,4 @@
+#!/usr/bin/bash
+
+node index.js
+convert screenshot/color.png -filter LanczosSharp -distort Resize 600x800 -colorspace sRGB -background black -gravity center -extent 600x800! -grayscale Rec709Luminance -colorspace sRGB -dither Riemersma -remap eink_cmap.gif -quality 75 -define png:color-type=0 -define png:bit-depth=8 screenshot/screenshot.png
diff --git a/magickindle/bin/start.sh b/magickindle/bin/start.sh
new file mode 100644
index 0000000..4b260ad
--- /dev/null
+++ b/magickindle/bin/start.sh
@@ -0,0 +1,58 @@
+#!/bin/sh
+# redirect stderr and stdout to file
+exec >> /mnt/us/log 2>&1
+
+# kill other instances of this script
+me=$$
+ps -ef | grep 'start.sh' | awk -v me=$me '$2 != me {print $2}' | xargs kill
+
+echo "$(date) starting"
+
+update_screensaver() {
+ echo "$(date) downloading screensaver"
+
+ #echo "$(date) enabling wifi"
+ #lipc-set-prop com.lab126.cmd wirelessEnable 1
+ for i in 1 2 3 4 5
+ do
+ curl "CHANGETHIS.png" --output /mnt/us/screensaver.png --fail --silent --show-error && break
+ sleep 10
+ done
+ # turning off wireless during ready to suspend causes issues with Kindle Wifi
+ # - the Kindle forgets the gateway, the configuration gets desynced,
+ # leading to the Kindle being connected but having no network
+ #echo "$(date) disabling wifi"
+ #lipc-set-prop com.lab126.cmd wirelessEnable 0
+
+ echo "$(date) updating screen"
+ eips -f -g /mnt/us/screensaver.png
+}
+
+LAST_UPDATE=0
+lipc-wait-event -m com.lab126.powerd goingToScreenSaver,readyToSuspend | while read event
+do
+ echo "$(date) event $event"
+
+ # throttle to 1/minute
+ NOW=$(date +%s)
+ if [ "$(($NOW - $LAST_UPDATE))" -ge 60 ]
+ then
+ # run in background so loop is not blocked
+ update_screensaver &
+ fi
+ LAST_UPDATE=$NOW
+
+ case "$event" in
+ # event looks like "goingToScreenSaver 7" so use a regex
+ readyToSuspend*)
+ echo "$(date) scheduling wakeup"
+ # must be called within 5s after readyToSuspend
+ # 60s until screensaver + 29min sleep
+ lipc-set-prop -i com.lab126.powerd rtcWakeup 1740
+ ;;
+ goingToScreenSaver*)
+ ;;
+ esac
+ echo "$(date) waiting for next event"
+done;
+
diff --git a/magickindle/config.xml b/magickindle/config.xml
new file mode 100644
index 0000000..5f28dd6
--- /dev/null
+++ b/magickindle/config.xml
@@ -0,0 +1,12 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<extension>
+ <information>
+ <name>Magic Kindle</name>
+ <version>0.1</version>
+ <author>schneefux</author>
+ <id>MagicKindle</id>
+ </information>
+ <menus>
+ <menu type="json" dynamic="true">menu.json</menu>
+ </menus>
+</extension>
diff --git a/magickindle/menu.json b/magickindle/menu.json
new file mode 100644
index 0000000..5248ce6
--- /dev/null
+++ b/magickindle/menu.json
@@ -0,0 +1,9 @@
+{
+ "items": [
+ {"name": "Magic Kindle Screensaver",
+ "items" : [
+ {"name": "Start", "priority":0, "action": "bin/start.sh" }
+ ]
+ }
+ ]
+}
diff --git a/magicmirror/config/config.js b/magicmirror/config/config.js
new file mode 100644
index 0000000..3896e1f
--- /dev/null
+++ b/magicmirror/config/config.js
@@ -0,0 +1,73 @@
+var config = {
+ address: "0.0.0.0", // any
+ port: 8080,
+ ipWhitelist: [], // any
+ language: "de",
+ timeFormat: 24,
+ units: "metric",
+ serverOnly: true,
+ modules: [
+ {
+ module: "MMM-Trello",
+ position: "bottom_bar",
+ config: {
+ api_key: "",
+ token: "",
+ list: "",
+ reloadInterval: 1000 * 60 * 60,
+ updateInterval: 1000 * 60 * 5,
+ animationSpeed: 0,
+ showTitle: true,
+ showDescription: true,
+ isCompleted: false,
+ showLineBreaks: true,
+ showDueDate: false,
+ showChecklists: false,
+ showChecklistTitle: false,
+ wholeList: false,
+ },
+ },
+ {
+ module: "MMM-ImagesPhotos",
+ position: "fullscreen_below",
+ config: {
+ opacity: 1.0,
+ animationSpeed: 0,
+ updateInterval: 60000,
+ }
+ },
+ {
+ module: "MMM-DateOnly",
+ position: "top_right",
+ config: {
+ showWeek: false,
+ dateFormat: "dddd, LL",
+ }
+ },
+ {
+ module: "MMM-PublicTransportHafas",
+ position: "top_right",
+ config: {
+ stationID: "",
+ stationName: "",
+ updatesEvery: 60 * 15,
+ direction: "",
+ interval: 1000 * 60 * 15,
+ timeToStation: 0,
+ timeInFuture: 180,
+ showColoredLineSymbols: false,
+ useColorForRealtimeInfo: false,
+ showAbsoluteTime: true,
+ marqueeLongDirections: false,
+ showTableHeaders: false,
+ maxReachableDepartures: 2,
+ maxUnreachableDepartures: 0,
+ fadeReachableDepartures: false,
+ },
+ },
+ ]
+
+};
+
+/*************** DO NOT EDIT THE LINE BELOW ***************/
+if (typeof module !== "undefined") {module.exports = config;}
diff --git a/magicmirror/css/custom.css b/magicmirror/css/custom.css
new file mode 100644
index 0000000..6e940b2
--- /dev/null
+++ b/magicmirror/css/custom.css
@@ -0,0 +1,58 @@
+.normal,
+.dimmed,
+header,
+body {
+ color: #fff;
+ text-shadow: -2px 0 black, 0 2px black, 2px 0 black, 0 -2px black;
+}
+
+body {
+ margin: 40px 30px 40px 30px;
+ position: absolute;
+ height: calc(100% - 80px);
+ width: calc(100% - 60px);
+}
+
+/* images slideshow */
+.fullscreen.below {
+ display: flex;
+ flex-direction: column;
+ justify-content: center;
+}
+
+/* hafas */
+.pthBWLineSign {
+ background-color: initial;
+ font-size: initial;
+ font-weight: initial;
+ color: #fff;
+ margin: 0;
+}
+
+
+.pthWrapper header {
+ display: none;
+}
+
+.pthDirectionCell {
+ min-width: 0;
+ padding: 0;
+}
+
+.pthDelay {
+ display: none;
+}
+
+.pthTable {
+ float: right !important;
+ width: auto !important;
+}
+
+.pthDirectionCell::before {
+ content: "nach ";
+}
+
+/* general */
+.module {
+ margin-bottom: 15px;
+}
diff --git a/magicmirror/css/main.css b/magicmirror/css/main.css
new file mode 100644
index 0000000..84f8c4d
--- /dev/null
+++ b/magicmirror/css/main.css
@@ -0,0 +1,243 @@
+html {
+ cursor: none;
+ overflow: hidden;
+ background: #000;
+}
+
+::-webkit-scrollbar {
+ display: none;
+}
+
+body {
+ margin: 60px;
+ position: absolute;
+ height: calc(100% - 120px);
+ width: calc(100% - 120px);
+ background: #000;
+ color: #aaa;
+ font-family: "Roboto Condensed", sans-serif;
+ font-weight: 400;
+ font-size: 2em;
+ line-height: 1.5em;
+ -webkit-font-smoothing: antialiased;
+}
+
+/**
+ * Default styles.
+ */
+
+.dimmed {
+ color: #666;
+}
+
+.normal {
+ color: #999;
+}
+
+.bright {
+ color: #fff;
+}
+
+.xsmall {
+ font-size: 15px;
+ line-height: 20px;
+}
+
+.small {
+ font-size: 20px;
+ line-height: 25px;
+}
+
+.medium {
+ font-size: 30px;
+ line-height: 35px;
+}
+
+.large {
+ font-size: 65px;
+ line-height: 65px;
+}
+
+.xlarge {
+ font-size: 75px;
+ line-height: 75px;
+ letter-spacing: -3px;
+}
+
+.thin {
+ font-family: Roboto, sans-serif;
+ font-weight: 100;
+}
+
+.light {
+ font-family: "Roboto Condensed", sans-serif;
+ font-weight: 300;
+}
+
+.regular {
+ font-family: "Roboto Condensed", sans-serif;
+ font-weight: 400;
+}
+
+.bold {
+ font-family: "Roboto Condensed", sans-serif;
+ font-weight: 700;
+}
+
+.align-right {
+ text-align: right;
+}
+
+.align-left {
+ text-align: left;
+}
+
+header {
+ text-transform: uppercase;
+ font-size: 15px;
+ font-family: "Roboto Condensed", Arial, Helvetica, sans-serif;
+ font-weight: 400;
+ border-bottom: 1px solid #666;
+ line-height: 15px;
+ padding-bottom: 5px;
+ margin-bottom: 10px;
+ color: #999;
+}
+
+sup {
+ font-size: 50%;
+ line-height: 50%;
+}
+
+/**
+ * Module styles.
+ */
+
+.module {
+ margin-bottom: 30px;
+}
+
+.region.bottom .module {
+ margin-top: 30px;
+ margin-bottom: 0;
+}
+
+.no-wrap {
+ white-space: nowrap;
+ overflow: hidden;
+ text-overflow: ellipsis;
+}
+
+.pre-line {
+ white-space: pre-line;
+}
+
+/**
+ * Region Definitions.
+ */
+
+.region {
+ position: absolute;
+}
+
+.region.fullscreen {
+ position: absolute;
+ top: -60px;
+ left: -60px;
+ right: -60px;
+ bottom: -60px;
+ pointer-events: none;
+}
+
+.region.fullscreen * {
+ pointer-events: auto;
+}
+
+.region.right {
+ right: 0;
+ text-align: right;
+}
+
+.region.top {
+ top: 0;
+}
+
+.region.top .container {
+ margin-bottom: 25px;
+}
+
+.region.bottom .container {
+ margin-top: 25px;
+}
+
+.region.top .container:empty {
+ margin-bottom: 0;
+}
+
+.region.top.center,
+.region.bottom.center {
+ left: 50%;
+ -moz-transform: translateX(-50%);
+ -o-transform: translateX(-50%);
+ -webkit-transform: translateX(-50%);
+ -ms-transform: translateX(-50%);
+ transform: translateX(-50%);
+}
+
+.region.top.right,
+.region.top.left,
+.region.top.center {
+ top: 100%;
+}
+
+.region.bottom {
+ bottom: 0;
+}
+
+.region.bottom .container:empty {
+ margin-top: 0;
+}
+
+.region.bottom.right,
+.region.bottom.center,
+.region.bottom.left {
+ bottom: 100%;
+}
+
+.region.bar {
+ width: 100%;
+ text-align: center;
+}
+
+.region.third,
+.region.middle.center {
+ width: 100%;
+ text-align: center;
+ -moz-transform: translateY(-50%);
+ -o-transform: translateY(-50%);
+ -webkit-transform: translateY(-50%);
+ -ms-transform: translateY(-50%);
+ transform: translateY(-50%);
+}
+
+.region.upper.third {
+ top: 33%;
+}
+
+.region.middle.center {
+ top: 50%;
+}
+
+.region.lower.third {
+ top: 66%;
+}
+
+.region.left {
+ text-align: left;
+}
+
+.region table {
+ width: 100%;
+ border-spacing: 0;
+ border-collapse: separate;
+}