Einleitung
Ich habe das ekey Home Fingerscanner-Zutrittssystem im Einsatz.
Nun wollte ich das ganze über die Heimautomatisierung irgendwie auswertbar machen und habe mir den ekey CV LAN zugelegt.
Dieser sendet UDP-Datenpakete an eine zuvor definierte IP-Adresse ("Datensenke" im ekey-Jargon).
Die Herausforderung war nun, eine solche Datensenke zu erstellen.
In meinem Fall ist es ein simples Bash-Script geworden, das auf einem Raspberry Pi per systemd läuft. Es empfängt per socat die Pakete, wertet diese aus und sendet sie anschließend an die API meiner Heimautomatisierung. Das kann natürlich beliebig auf jedes andere System angepasst werden, das per HTML-API o.ä. ansprechbar ist.
Voraussetzungen:
- ekey CV LAN für das ekey-Home-System (für ekey home oder multi muss es der mit der Produktnummer 100 460 sein, der andere funktioniert nur mit ekey net)
- ein paar Linux-Kenntnisse schaden nicht
- ein Debian-System (z.B. Raspberry mit Raspbian)
- socat (
apt install socat
)
Vorarbeiten
Den ekey CV LAN nach Bedienungsanleitung in den ekey BUS und ans Netzwerk bringen.
Dann mit der mitgelieferten Software entsprechend einstellen.
Bestandteile
Das Auswertungsscript
In meinem Fall drückt das Script eine virtuelle Taste meiner Heimautomatisierung, falls der Finger nicht erkannt wurde und löst so ein Klingelsignal aus. Wurde der Finger erkannt, wird nur geloggt.
/usr/local/bin/ekey-converter.sh
#!/bin/bash
# --- ekey data sink ---
# The home protocol can only be used in ekey home systems. Data packets are created
# for each recognized finger and every time a refusal takes place at the finger
# scanner. The data fields within the data packet are ASCII-encoded. This protocol
# has the following structure:
# Base format: x_xxxx_x_xxxxxxxxxxxxxx_x_x
#
# Data field name | Number of digits | Data type | Value range | Meaning
# PACKET TYPE 1 String 1 *User data* packet type
# USER ID 4 String (decimal) 0000-9999 User number (default 0000)
# FINGER ID 1 String (decimal) 0-9 1 = left little finger
# 2 = left ring finger
# 3 = left middle finger
# 4 = left index finger
# 5 = left thumb
# 6 = right thumb
# 7 = right index finger
# 8 = right middle finger
# 9 = right ring finger
# 0 = right little finger
# R = RFID
# - = no finger
# SERIAL NO. FS 14 String xxxxxx xx xx xxxx Digits 1-6 = item number
# Digits 7-10 = week code
# Digits 11-14 = sequential number
# ACTION 1 String 1, 2 1 = Open
# 2 = Refuse unrecognized finger
# 8 = Digital input
# RELAY 1 String 1-4; - 1 = Relay 1
# 2 = Relay 2
# 3 = Relay 3
# 4 = Relay 4
# d = Double relay
# - = no relay
log="/usr/bin/logger -i -p local0.info -t ekey-converter.sh"
log_dbg="/usr/bin/logger -i -p local0.debug -t ekey-converter.sh"
log_err="/usr/bin/logger -i -p local0.warning -t ekey-converter.sh"
#debug=true
$log "Start ekey-converter.sh"
# get data from stdin
read MESSAGE
if [ ! -z "$MESSAGE" ]; then
$log " Message: '$MESSAGE'"
# check if MESSAGE has expected format
if [[ ${MESSAGE} =~ ^._.{4}_._12345678901234_._.$ ]]; then
# split into array
IFS='_' read -a msg <<< "${MESSAGE}"
# arrays for naming etc.
name=('PAKETTYPE' 'USERID' 'FINGERID' 'SERIALNO' 'ACTION' 'RELAIS')
fingerids=('right little finger' 'left little finger' 'left ring finger' 'left middle finger' 'left index finger' 'left thumb' 'right thumb' 'right index finger' 'right middle finger' 'right ring finger')
fingerid=${msg[2]}
# resolve finger id to name
if [ $fingerid == "-" ]; then
fingername="None"
elif [ $fingerid == "R" ]; then
fingername="RFID"
else
fingername=${fingerids[$fingerid]}
fi
action=${msg[4]}
userid=${msg[1]}
# resolve userid to name
if [ $userid == "0001" ]; then
username="User1"
elif [ $userid == "0002" ]; then
username="User2"
# etc...
else
username="Unknown"
fi
# debug output if debug is set
if [ $debug ]; then
for i in {0..5..1}; do
$log_dbg " ${name[i]}: ${msg[i]}"
done
fi
$log " User: $username (ID: $userid), Finger: $fingername (ID: $fingerid), Action: $action (1 = Open, 2 = Refuse unrecognized finger)"
# HomeMatic CCU and device to press
hm_server="192.168.0.15"
hm_channel="Klingeltaster_ekey"
hm_url="http://$hm_server:8181/ccu.exe?do=(dom.GetObject(ID_CHANNELS)).Get('$hm_channel').DPByHssDP('PRESS_SHORT').State(1)"
# check if unrecognized finger
if [ $action == "2" ]; then
$log " Unrecognized finger, running: /usr/bin/curl -s '$hm_url'"
/usr/bin/curl -s '$hm_url'
elif [ $action == "1" ]; then
$log " Finger accepted"
fi
else
$log_err " Message corrupted or incomplete, should be 'x_xxxx_x_12345678901234_x_x'."
fi
else
$log_err " No input given, MESSAGE is empty"
fi
$log "End ekey-converter.sh"
# Done
Der Starter
Das vorhergehende Script wird jedes mal aufgerufen, wenn ein Paket vom CV LAN empfangen wird. Dies stellen wir mit folgendem Script sicher.
/usr/local/bin/ekey-converter-starter.sh
#!/bin/bash
while true
do
/usr/bin/socat -u udp4-recvfrom:56000,keepalive,fork system:'/usr/local/bin/ekey-converter.sh'
done
Der systemd-Eintrag
/etc/systemd/system/ekey-cv.service
[Unit]
Description=Socat with ekey-converter
After=network-online.target
Requires=network-online.target
[Service]
ExecStart='/usr/local/bin/ekey-converter-starter.sh'
RestartSec=5
Restart=always
[Install]
WantedBy=multi-user.target
Dann noch den systemd-Eintrag aktivieren und starten:
systemd enable ekey-cv.service
systemd start ekey-cv.service
Fazit
Man kann natürlich im eigentlichen Script auch alles mögliche andere anhand der empfangenen Pakete starten, der Fantasie sind hier kaum Grenzen gesetzt...