Zwei Jahre ist es nun her, dass die Raspberry Pi Stechuhr in unserem Dresdner Büro im täglichen Einsatz ist. Im Laufe der Zeit hat sich, danke an Robert für das Feedback, etwas im Setup-Prozess geändert. Das nehmen wir zum Anlass, um unsere Raspberry Pi Stechuhr auf den Stand der Technik in 2020 zu heben.
Zur Erinnerung - die ersten beiden Teile findet ihr hier:
Was hat sich verändert?
Nun, im Grundaufbau der NFC Raspberry Pi Stechuhr hat sich eine kleine, dafür umso mehr entscheidende Stelle geändert. Wir nutzten ein Firefox Add-On, um selbigen per Telnet fernzusteuern. Das war von Anfang an ein Workaround - funktionierte aber tadellos. Bis folgendes passierte:
Ende Januar 2020 entfernte Mozilla alle Firefox-Extensions die Remote-Code ausführten.
Dieser Schritt, aus sicherheitstechnischen Gründen vollkommen nachvollziehbar, führte zwangsläufig zur Löschung des in unserem Setup genutzten Remote-Control Add-Ons. Also hieß es eine stabilere Lösung finden :)
Installation des Raspberry Pi
An der Hardware hat sich für uns seit dem letzten Artikel nichts verändert. Dagegen ändert sich Im Bereich Software sehr viel in zwei Jahren.
Als OS nutzen wir nun Raspbian Buster with Desktop. Dies lässt sich einfach mit dem Apple Pi Backer oder einem anderen Programm dafür auf eine SD-Karte spielen. Die SD-Karte einfach in den Pi einstecken und los geht's.
Zur Konfiguration wird im Terminal folgender Befehl ausgeführt:
sudo raspi-config
Anschließend kann im Tool das SPI (unter Interfacing Options => SPI) und SSH (optional) eingeschaltet werden.
Für die Ausführung des neuen Skripts müssen folgende Befehle zur Installation von Chromium, den Treibern zum Steuern von Chromium und die Steuer-API installiert werden.
sudo apt-get update && sudo apt-get install
sudo apt-get install chromium-browser chromium-chromedriver
pip3 install -U selenium
Zur Verwendung von SPI in Python muss noch die Extension für Python installiert werden. Da dies nicht ohne Weiteres möglich ist, erfolgt die Installation händisch wie folgt:
cd ~
git clone https://github.com/lthiery/SPI-Py.git
cd SPI-Py
sudo python3 setup.py build && sudo python3 setup.py install
Die Skripte
Aus Kompatibilitätsgründen musste mit dem Wechsel auf Python3 auch das Skript zur Kommunikation mit dem NFC Reader ausgetauscht werden. Hier ist der Link zum neuen Skript. Dabei handelt es sich um einen Fork des alten Skriptes mit kleineren Anpassungen, um es mit Python3 kompatibel zu machen.
Statt wie bisher den Browser per Telnet fernzusteuern, nutzen wir nun eine API um den Browser direkt zu steuern. Dies hat den Vorteil dass es deutlich sicherer ist und (hoffentlich) länger unterstützt wird.
#!/usr/bin/env python
# -*- coding: utf8 -*-
import RPi.GPIO as GPIO
import MFRC522
import signal
import datetime
import platform
import sys
import time
import threading
from selenium import webdriver
def main():
# start browser, might take a while
browser = initBrowser()
continue_reading = True
last_uid = [0, 0, 0, 0, 0]
time_to_delete = 0
# Capture SIGINT for cleanup when the script is aborted
def end_read(signal, frame):
global continue_reading
continue_reading = False
GPIO.cleanup()
if browser is not None:
browser.quit()
sys.exit(0)
# Hook the SIGINT and SIGTERM
signal.signal(signal.SIGINT, end_read)
signal.signal(signal.SIGTERM, end_read)
# Create an objecet of the class MFRC522
MIFAREReader = MFRC522.MFRC522()
# This loop keeps checking for chips. If one is near it will get the UID and authenticate
while continue_reading:
(status, TagType) = MIFAREReader.MFRC522_Request(MIFAREReader.PICC_REQIDL)
# If a card is found
if time_to_delete != 0 and time_to_delete < datetime.datetime.now():
time_to_delete = 0
last_uid = [0, 0, 0, 0, 0]
navigate(browser, 'https://sandstorm.de')
# Get the UID of the card
(status, uid) = MIFAREReader.MFRC522_Anticoll()
# If we have the UID, continue
if status == MIFAREReader.MI_OK:
if last_uid != uid:
uid_strings = []
for part in uid:
uid_strings.append(str(hex(part)).replace('0x', ''))
# we only use the first 4 entries
uid_strings.pop(4)
uid_string = '-'.join(uid_strings)
last_uid = uid
time_to_delete = datetime.datetime.now() + datetime.timedelta(0, 5)
url = "https://www.your-url.de/workingtime/dongle/toggle.html?rfidToken=" + uid_string
navigate(browser, url)
# start the browser in fullscreen and open the default page
def initBrowser():
options = webdriver.ChromeOptions()
options.add_argument('--kiosk')
browser = webdriver.Chrome(options=options)
global_browser = browser
browser.get('https://sandstorm.rocks/')
return browser
# small funktion to change current page in browser
def navigate(browser, url):
if browser is None:
print('navigation not available')
else:
browser.get(url)
if __name__ == '__main__':
main()
Die beiden Skripte befinden sich bei uns im Ordner `/utl` und lassen sich nach Anpassung des folgenden Services bei Bedarf ohne Probleme auch in einem anderen Ordner ablegen.
Achtung: der ausführende Nutzer muss die notwendigen Rechte haben, um die Skripte ausführen zu dürfen.
cd /utl
chmod +x timeClock.py
chmod +x MFRC522.py
Autostart
Wie bisher, überlassen wir das automatische Starten des Skripts dem systemd von Rasbpian. Eine Änderung ist allerdings, dass dies nun pro Nutzer und nicht mehr systemweit konfiguriert wird. Die Konfiguration des Dienstes sieht wie folgt aus:
[Unit]
Description=Python Sandstorm time clock
After=network.target
PartOf=graphical-session.target
[Service]
Type=simple
ExecStart=python3 /utl/timeClock.py
Restart=on-failure
RestartSec=10
KillMode=process
[Install]
WantedBy=default.target
Diese Datei heißt bei uns `frankWalter.service` und befindet sich im Ordner `~/.config/systemd/user`
Um das Ganze nun zu starten, muss nur der Service gestartet werden:
systemctl --user enable frankWalter.service
Geschafft!
Wir hoffen sehr, dass euch das Update gefällt! Für weitere Fragen stehen wir euch gern zur Verfügung!