ePaper (e-ink) Tags mit OpenEPaperLink (OEPL) verwalten

Worum geht’s?

Vor gut zwei Jahren bekam ich mit, dass die ePaper-Displays, de z.B. in Supermärkten die gedruckten Preisschilder zusehends ablösten, in der Hardware-Hacker- und Maker-Community ‘angekommen’ waren. Damals verhalf mir Aaron Christophel (atc1441), dankenswerterweise zu ein paar “SOLUM GR29000 ePaper Price Tags”, die mit ihrer Diagonale von 2,9″ (~7cm) eine vernüftige “Leinwand” für Experimente boten. Inzwischen sind Preisschilder in ebook-Reader Größe, mit über 5 Zoll, z.B. bei Lidl, ein üblicher Anblick.
So begab es sich also zu der Zeit, dass ich an Weihnachten 2022 einen “ZBS Flasher” aufbaute und ein paar Displays mit der alternativen Firmware für das ePaper Server Project bespielte. Das Projekt nutzte einen ESP8266 oder ESP32 mit einem CC2531 Zigbee-Dongle, um die Displays aus direkter Nähe mit statischen Bildern zu versorgen. Die vergangenen 2 Jahre war so ein Display hier als “Gäste-WLAN Zettel” im Einsatz: unsere Besucher konnten davon die Zugangsdaten ablesen, das Handy mit einem QR Code konfigurieren oder (über ein aufgeklebtes RFID-Tag) per NFC konfigurieren. Das Schöne an den ePaper Displays ist, dass sie keinen Strom benötigen, wenn der Inhalt nur angezeigt, aber nicht verändert werden soll. So lag unser Guest WiFi Tag zwei Jahre “funktionsfähig” ohne Batterien neben dem Telefon…

Auftritt OpenEPaperLink

Bereits ein Jahr später, im Januar 2023, startete Jonas Niesner dann das Projekt OpenEPaperLink (“OEPL”), das eine bessere Verwaltung der Tags erlaubt. Kern der Projekts sind zwei ESP32: der erste (ein ESP-S3 mit PSRAM) übernimmt die Darstellung eines Webfrontends zur Verwaltung der Tags und der zweite (ein ESP32-C6 oder -H2), dient zur Kommunikation mit den Tags über das (modifizierte) Zigbee Protokoll. So ist es nun bequem möglich, mehrere Duzend Displays zu verwalten, und ihnen Funktionen wie eine Google Kalenderanzeige, die Anzeige des Wetters oder eben weiterhin statischer Bilder zu geben.

Da ich wieder etwas Zeit an der Hand hatte, lag es nahe, mein ePaper-Server Setup upzugraden.

Das OpenEPaperLink Projekt auf GitHub beschreibt in seinem Wiki recht detailiert ein paar Startpunkte für einen OEPL Server. Ich entschied mich für den sog. “Spaghetti-AP”, bei dem die beiden ESP über Dupont Steckkabel miteinander verbunden werden.

Einkaufsliste AP

Der Spaghetti-Server benötigt:

  • einen ESP32 mit ausreichend PSRAM, wie einen ESP32-S3 N16R8 (z.B. auf AliExpress oder ebay) für ca. 6-10 €
  • einen ESP32 mit Zigbee Protokoll, wie den ESP32-C6 oder -H2 (hier oder dort) für nochmal 6-12 €
  • ein USB-C Kabel, um die Microcontroller zu betanken
  • ein USB-Netzteil, um den AP ggfs. später unabhängig von einem Rechner zu betreiben

Umsetzung

Das OEPL Wiki beschreibt, wie die beiden ESP32 zusammengesteckt werden. Das kann entweder über Dupont-Kabel oder durch verlöten geschehen. Die Steck-Variante ist für den Beginn zu empfehlen, um zu testen, ob der Aufbau funktoniert. Insbesondere falls die gekauften Boards von den Beschriebenen abweichen, kann man so schnell den einen oder anderen Port umstecken!

È pronto… Spaghetti-AP: oben der C6 für die Zigbee Kommunikation und unten der S3 für die WiFi-Kommunikation.

Für einen dauerhaften oder regelmäßigen Betrieb empfiehlt sich die verlötete Variante: Bei meinen 2 Tagen “Dauerbetrieb” mit fliegender Verkabelung, schien es als machte die Steckverbindung das eine oder andere Mal Pause, was nach einem beherzten ‘wackel’ mal am Kabel’ und einem Neustart der ESPs “geheilt” wurde.

sobald die ESP verkabelt sind, werden sie mit der nötigen Firmware geladen. Am bequemsten verrichtet man dies direkt im Browser, mit dem Web-Flasher unter install.openEPaperLink.org. Hier ist darauf zu achten, für den Spaghetti-AP den “Yellow AP” auszuwählen. Die Website funktioniert nur unter Chromium-basierten Browsern (Google Chrome oder MS-Edge). Nachdem der ESP mit dem USB-Port des Computers verbunden ist, gilt es den richtigen COM-Port auszuwählen. Dann wird der erste der beiden ESP32 geflashed. Der Flash-Vorgang benötigt etwa eine Minute. Nach einem Reset des ESP wird der Vorgang mit dem “Yellow AP” wiederholt. Dabei “merkt” der Web-Flasher, dass der erste ESP bereits versorgt ist und bespielt dann den zweiten ESP, der später für die Komunikation mit den Displays genutzt ird, mit einer eigenen Firmware.

Nach einem weiteren Reset kann der OEPL Server dann endlich konfiguriert werden. Dazu spannt der ESP ein eigenes Konfigurations-WLAN (SSID: OpenEpaperLink) auf. Am einfachsten betritt man mit dem Smartphone oder dem Computer das WLAN, und konfiguriert (http://192.168.4.1/setup) initial das eigene Heim-WLAN. So ist der OEPL Server später bequem aus dem LAN erreichbar. Eine feste Adresszuweisung und ein “merkbarer” Name, den man in der Fritz!Box für den AP vergibt, erleichtern auch in ein paar Monaten die Verbindung…

Die Displays vorbereiten…

Da ich, wie in der Einleitung beschrieben, vor zwei Jahren bereits ein paar der Displays mit einer alternativen Firmware für den ePaper Server beglückt hatte, hatte ich die Hoffnung, dies nicht nochmals tun zu müssen. Meine Suche führte zu keinem eindeutigen Ergebnis. Zwar beschreibt das OEPL Wiki zwar recht detailliert verschiedene Tags und die nötige Firmware, aber die eigentliche Antwort auf meine konkrete Frage gab erst eine EMail von Aaron Christophel:

… da gehen sie hin, die Hoffnungen auf einen quick-and-dirty Nachmittagshack: mal schnell den AP zusammenstecken und eine Stunde später Erfolg vermelden ;-).
Aber dennoch: Danke, Aaron, für die schnelle Antwort! <3

Einkaufsliste für den Flasher

Um die Tags mit der alternativen Firmware zu betanken, müssen wir nochmals Hand anlegen, da dies nur über die Schnittstelle auf dem Board geht.

Dazu benötigen wir:

  • einen “einfachen” ESP32, wie z.B. den ESP32-S2 mini (Ali, Elektrobucht) für ca. 3 Euro
  • einen Adapter, um die Preisschilder an den Microcontroller anzubinden.

Insbesondere für den Adapter gibt es eine Reihe von Möglichkeiten. Möchte man nur mal 1-2 Displays betanken, kann es ausreichen, die notwendigen 9 Käbelchen direkt auf die Platine des Displays zu löten. spätestens nach dem dritten Display schaut man sich aber nach einer anderen Möglichkeit um. Hier bietet es sich an Federkontaktleisten, sog. “Pogo Pins” zu besorgen, die man z.B. in ein 3D-gedrucktes Element einklebt und mit dem ESP32 verbindet. Damit kann man je nach Modell und Aufwand mehr oder weniger bequem viele Displays in Serie flashen, indem man die Pins auf die Kontakte des Displays drückt:

  • Pogo Pins mit 1mm Durchmesser bei AliExpress oder ebay (ruhig ein paar mehr ordern..)
  • eine Aufnahme für die Pins. Hier gibt es 3D-Druck Modelle für verschiedene Displaytypen: Hier mein Modell für die SOLUM Tags.
  • Die Pins lassen sich m.E. am einfachsten mit Lackdraht verlöten. Etwas Vorsicht ist danach beim Umgang mit dem “Rigg” geboten, damit die Kabel nicht abreissen.

Vor zwei Jahren hatte ich bereits den ZBS-Flasher gebaut. Weil nun OEPL den alten ePaper Server ablösen sollte, habe ich einfach meinen Pogo Pin Adapter “kannibalisiert” und an den S2 mini gelötet. Die ersten Displays waren dann auch irgendwann mit der OEPL Firmware beschrieben.

Für neue Tags ist es wichtig, dass die MAC-Adresse des Tags in einen separaten Speicherbereich, die Infopage, geschrieben wird. der OEPL Flasher bietet hierfür die Option -info an. Ich habe mir für den Flash-Vorgang ein Skript geschrieben das diesen Vorgang automatisiert. Mehr dazu in einem weiteren Artikel.

Programmieradapter (“Rigg”) mit Pogo-Pins: Nicht hübsch, aber hässlich!

Nach einem Reboot melden sich die Displays dann mit der Firmware Message und, abhängig davon, ob man daran gedacht hat, ihnen die passende MAC-Adresse mitzugeben, warten sie geduldig auf einen Link zum OEPL Access Point (AP).

Sobald der OEPL AP richtig funktioniert, erscheinen die Tags dort im Interface und können testweise beschrieben werden. Sollte man noch kein passend skaliertes Bild zur Verfügung haben, bietet der OEPL AP die Möglichkeit, eine Reie vordefinierter Automationen zu laden, wie z.B.:

  • aktuelles Datum
    • aktuelles Wetter am Standort
    • Wettervorhersage
    • QR-Code

Eigene Inhalte

Das Wiki bietet bereits eine Reihe guter Tipps, wie eigene Bilder am optisch besten auf den Tags erscheinen. Ich plane dazu einen separaten Artikel, in dem ich Beispiele vorstelle, Templates verlinke und einige Schriftarten aufzeige, die für eInk besonders geeignet sind.

Links

Minimalist Credit Card Wallet with an AirTag -> “Air/Wallet”

Today I pimped my simple, minimalist card wallet and added a deconstructed AirTag to one of the holder sides.

Due to the desired form factor, I had to rip the AirTag apart, separate the stacked parts and then reattach the electronics to the battery horizontally. This thing is very much just a dirty (albeit working) hack, the 3D files are still work in progress, but you can already download it on Thingiverse or from the Prusa Printers community.

I will add a proper “making of” later. Hit me by email if you need more info

Judging from on the inner layout of the AirTag, I guess it’s just a matter of time until Apple offers a credit card-sized (but thicker) version of the AirTag that goes into your standard wallet comfortably.

The three Stooges

Edit: I changed the name to “Air/Wallet” (with the ‘/’) after realizing the original name may have been copyrighted… ;-)

Use regular expressions (regex) in LuLu to ‘allow’ IP address subnets

LuLu by Objective-See is a macOS firewall for outbound connections. While the built-in Apple product will protect you from network attacks from the networks around you, LuLu will give the user control over the network connections a running software on the Mac may want to open itself, e.g. to the Internet. LuLu can act as a freeware replacement for the firewall part in LittleSnitch, the other well-known security tool for the Mac. If you want to know more about LuLu, follow the link above.

In the “user-guided” mode LuLu will give the choice to create rules for a specific process with:

  • either a single URL / IP and a sigle port (“Remote Endpoint”)
  • or all URL’s / IP’s and all ports (“Process”)

… with the choice of allowing or blocking traffic

If you are like me, you might want to tweak those rules. And that’s where the “regex” checkbox comes into play. You can use it, for example, to allow access to all the machines in your home network.

However, the LuLu user documentation currently does a bad job to describe the regex syntax that’s expected by LuLu. Is it 192.168.1.* as the asterisk in the “allow all” suggests? There are many variations of regular expressions, so an example would certainly be appreciated.

LuLu’s regex syntax

LuLu uses Objective-C’s NSExpression class. You can find that documentation here. The most important elements for creating LuLu rules are:

ExpressionDescriptionExample
\“escape” special characters like
* ? + [ ( ) { } ^ $ | \ . /
in order to treat them as literals
192\.168\.1\.1
.placeholder for any character – exactly _one_ character!192\.168\.1\....
...\.com
a,b,c,..
A,B,C,..
0,1,2,..
characters, numbers, symbols are treated as themselveshuf\.org
[pattern]match any one character from the pattern[aeiou]
[a-z]
[a-zA-Z]
[0-9]
important regex expressions. See the Apple doc link above for more

In addition to the Expressions above there are modifiers, so you can tell LuLu to expect more than one “any character”. You place the modifier after the expression it applies to:

ModifierDescriptionExample
*Match 0 or more times. Match as many times as possible.
+Match 1 or more times. Match as many times as possible.
?Match 0 or 1 times. Prefers 1 times
*?Match 0 or more times. Match as few times as possible.
+?Match 0 or more times. Match as few times as possible.
{n}?Match exactly n times.
{n,}?Match at least n times, but no more than required for an overall pattern match.
{n,m}?Match between n and m times. Match as few times as possible, but not less than n.
Important regex modifiers. See the Apple doc link above for more

Some regexamples

ExpressionWhat it meansIt Matches…
192\.168\.1\..*any IP address starting with 192.168.1. regardless what’s in the last octet, or whatever comes after the last dot. Note that there is a \. escaping the last dot and then the .* matching vor any amount of any character after that dot. 192.168.1.1
192.168.1.25
192.168.1.200
192\.168\.1\.[0-9]{1,3}?This is the safer version of the one above, as it only matches numbers in the last octet. 192.168.1.1
192.168.1.26
192.168.1.230
192\.168\.123\.[0-9]{1,3}?any IP address starting with 192.168.123. regardless what’s in the last octet.192.168.1.2
192.168.1.69
192.168.1.100
… more to come
some examples

So, if your home network is 192.168.1.0/24 (e.g. using a netmask of 255.255.255.0), the example below will tell LuLu to allow the Brave Browser to access any machine in your home network (on any port):

What’s next?

I plan to amend this blog post in a while: I think LuLu’s documentation is lacking a good explanation of basic regex and I volunteered to create something on the public Lulu Git.

I will add more examples (like URL regex-es) as I go ahead with that docu.

Running Brave Browser Incognito from MacOS CLI

You can start the Brave Browser on a Mac in incognito mode from the CLI (Terminal) using the “open -a” command:

open -a "Brave Browser" -n --args --incognito --new-window https://huf.org

open -a : opens the Application
-n : Open a new instance of the application even if one is already running
--args : the following arguments go to Brave
--incognito : what do you think?
--new-window : don't reuse an already existing browser window

looking at the manual page with “man open” will help you here.

adding static ip and routes to /etc/interface in debian 10 “buster”

“The times they are a-changing” – Bob Dylan

however grave the problems were that dylan addressed in his song and 1963 album, he certainly didn’t envision how linux distributions like debian are a-changing the way in which we have to configure our network settings. if we look at how we define static ip addresses, we can see quite some dylan-esque transitions. and when you need to persistently define static routes, keeping up-to-date can be at least hard.

it’s been hardly nine months since my post about static routes in debian 9 when that method has been marked as “deprecated” and won’t actually work anymore in debian 10 “buster”. So here’s how to do both static ip and static routes in buster:

the good thing is, it’s now all in one file. just edit /etc/network/interfaces. for the not-so daring types, make a backup before the edit:

> sudo cp /etc/network/interfaces /etc/network/interfaces.orig

> sudo vi /etc/network/interfaces

an out-of-the-box install will most certainly have dhcp configured. So for static ip, we comment out (or delete) these lines:

# allow-hotplug ens18
# iface ens18 inet dhcp

ens18 is the interface name in this example. that can be eth0 or en0 or something else in your case.

In order to set the static ipv4 address for the machine, insert this:

# static ip address on interface ens18 (or whatever the name):
address 192.168.1.100
netmask 255.255.255.0
gateway 192.168.1.1
dns-domain fritz.box
dns-nameservers 192.168.1.1 8.8.8.8

…of course you have to adapt the adress scheme to your network setup.

right after this we’ll add the static route which has been moved from the route system command to the more general ip tool:

# for a network route:
up /bin/ip route add 192.168.10.0/24 via 192.168.1.10

# and for a host route:
up /bin/ip route add 192.168.10.10/32 via 192.168.1.10

of course you know that the latter – a host route – is merely a special case of the more general classless routing notation above…

ok, my little furry creatures. till next time in our series “fun with the a-changing linux concept of static routes”.

raspberry pi: make routes persistent with dhcpcd

routing decisions…

so, the other day I needed to add a static route to my raspberry’s route table. the critter is running raspbian 9 (“jessie”). this version of debianesque linux uses dhcpcd for the network configuration.

you can find a whole lot of info on how to configure the box with a static ip address. however, there are few examples for configuring a static routing table entry that will persist after a reboot.

as we all know by now, you can enter a manual route using the command:

# /sbin/route add -net 10.1.2.0/24 gw 10.1.1.100

where 10.1.1.100 is the router on your local network behind which the target network 10.1.2.0 with the netmask 255.255.255.0 (the “/24”) is to be found!

this entry will be lost after a reboot. in order to make it persistent, you have to edit/create a so-called “exit hook”. that’s a file that gets executed by dhcpd at various occasions, e.g. after the network interface has been configured with a valid address.

here’s how to do it:

edit the exit hook file. the command will create it, if it’s not there already:

# sudo vi /etc/dhcpcd.exit-hook

add the routing command, just as you’d type it on the command line (first line is for documentation):

## adding the persistent route from the example above:
/sbin/route add -net 10.1.2.0/24 gw 10.1.1.100

now, in order to activate the hook file, you can try:

# sudo service dhcpcd restart

for a definitive test issue the reboot command.

if something goes wrong, you can debug the dhcpcd hooks by editing the file /lib/dhcpcd/dhcpcd-run-hooks and change the line

: ${syslog_debug:=false}
to
: ${syslog_debug:=true}

you can then “tail /var/syslog” in order to see the debug output.

happy routing!

Chrome on Mac: solving the “this browser is managed by your organization” message.

The other day i had this message in my chrome settings: “your browser is managed by your organization”. well, it was actually in german language, so it’s more like this one:

starting with chrome version 73 this warning comes up if one or more of chromes built-in policies differ from the default settings.

so you google the problem and you may find some solutions … for windows! (gasp) — or you come across the ‘solution’ to simply suppress the message without fixing the real problem…

most of us are not part of a browser-managing organization. therefore it would be nice to see which policy elements are set. you can see them with the browser-internal url:

chrome://policy

this should bring up something like this:

here we go again… wasn’t it months ago when you were fed up with that chrome cloud printing dialog?

you wanted apples’ standard dialog window with chrome! you wanted back control!! you wanted reven… – whatever!

so you updated the policy above (DisablePrintPreview=true) and lived happily ever after since… until now: “your browser is being managed by someone else!” – you want to get rid of that message, for zarquon’s sake!

the thing is, when you set the policy element back to “false”, this still counts as a modified policy.

you can set the propery back with this command in a terminal window and restarting chrome:

defaults write com.google.Chrome DisablePrintPreview -bool false

…and guess what shows:

grrrr..

ok, so setting the property to “false” obviously leads nowhere. the trick is, to delete the property like this:

defaults delete com.google.Chrome DisablePrintPreview

et abracadabra: after a chrome restart your browser belongs to you again. no evil corp controlling whatever sleazy (or not) policies are set.

jokes aside: this method is a good way to see if this policy you deleted is actually the reason for the nefarious message. if the message persists after deleting the policy, there’s still another policy active.