This is an old revision of the document!


DIY Access Control
and Burglar alarm
founder: crowdsourcing
depends on:
interested: harvie
software license:
hardware license:

For hackerspace more secure and without the annoyance of physical keys. DIY digital lock control, open/closed space status monitor and burglar alarm.

System architecture: Raspberry Pi + Adafruit PN532 shield. Supports ISO14443 cards (Mifare Classic, Desfire, Yubikey, you could even use Visa/Mastercard NFC payment cards; Android NFC Host Card Emulation could be used as well with some changes). Authentication: via UID, challenge-response with Yubikey Neo, signed public-key cryptography (Ed25519) messages with Desfire cards.

Unlocking the Door

Executive summary, how to get in without a key - arrange registering your RFID card (ISO-14443A, e.g. Mifare Classic, Mifare DESFire) with council at the meetup (or over mail rada _at_ brmlab.cz). After adding your card to brmdoor DB, you will be able to unlock the door by placing the card next to the reader.

BrmDoor Hardware

  • MCU/controller: Raspberry PI (all versions supported - 1, 2, 3)
  • OS: Raspbian or Ubuntu (other may work as well if you can get required packages to build and install)
  • Lock device - BERA-E electromagnetic lock:
    • From inside, it is possible to open the door anytime by just pushing the handle.
    • From outside, it is possible to open the door by turning the lock by the key, OR by pushing the handle if the voltage is applied.
    • Lock specs say 12-24V should be used, but from experience 12 V is not enough. Use 24 V.

Communication is over SPI: both SEL0 and SEL1 are shorted which turns communication to be over SPI.

Documentation of Adafruit PN532 shield (our revision is 1.2):

BrmDoor Firmware

List of authorized cards

Card list is on brmlab VPS (vps.brmlab.cz) are exported from JendaSAP, on /root/sap/cards.txt.

Adding a new card to JendaSAP and import to brmdoor

Put the card next to the reader, then look into a log (on brmdoor raspi in /root/brmdoor_libnfc/brmdoor.log) for Unknown UID line.

Login to vps.brmlab.cz. In /root/sap/members, find member's file and add line with the card UID (4, 7 or 10 byte UID), e.g.

card 0102ab89

On vps.brmlab.cz in /root/sap directory, run parse.py script:

cd /root/sap

This will create cards.txt. Copy the cards.txt to brmdoor and run on brmdoor raspi:

cd brmdoor_libnfc/; ./import_jendasap_cards.py /path/to/cards.txt brmdoor.sqlite''

No need to restart brmdoor daemon. Note that the import can take even a minute since the brmdoor Raspberry 1 is fucking slow.

Commit the changes to members directory on vps.brmlab.cz.

In the members directory, commit the changed card with

git commit -m "Added card for member Ctulhu" 1234_member_uid_file

OPEN/CLOSED switch with update of topic on IRC

In brmdoor_nfc.config, look at the section [open_switch]. IRC must be enabled in [irc] section for status update to work.

The first part of the topic until | character will be replaced by OPEN/CLOSED (if there is no pipe character, OPEN/CLOSED will be prepended).

Configuration needs setting a file that is read once per second, open_value determines which value means “open”. Thus you can use any daemon/cron script/whatever that just writes a predetermined value to file which will be read by brmdoor daemon.

For a simple switch (that just closes/opens the electrical connection) connected to GPIO PINs, you need to configure a PIN in input mode and turn on internal pullup on the input PIN. An example of this is in the brmdoor_start.sh script below. Connect one cable of the switch to an input PIN and the other to the ground.

export PIN=22
if [ '!' -d /sys/class/gpio/gpio$PIN ]; then
    echo $PIN > /sys/class/gpio/export
    echo in > /sys/class/gpio/gpio$PIN/direction
python -c "import wiringpi; wiringpi.wiringPiSetupGpio(); wiringpi.pinMode($PIN, wiringpi.INPUT); wiringpi.pullUpDnControl($PIN, wiringpi.PUD_UP)"

If the switch is in open position (connected to ground), the “open” value will be 0, the close value will be 1 (effect of the internal pull-up).

The numbering scheme is the same as in the lock configuration (BCM GPIO numbering, https://projects.drogon.net/raspberry-pi/wiringpi/pins/). A copy of the mapping is in gpio_vs_wiringpi_numbering_scheme.png file) in case the webpage goes away.

Changing OPEN/CLOSED status remotely with software

Any IRC user in #brmlab channel can change the topic by using the /topic command. This value will stay until the physical switch changes the value.

PIN assignments

General GPIO PIN assignments are configurable, communication (SPI/I2C) must follow the definition in Raspberry Pi pinouts. Raspi pinouts for all versions: http://pi4j.com/pins/model-3b-rev1.html

Numbering scheme used by brmdoor for lock and open switch (based on BCM GPIO numbering, different from P1 header physical PIN numbers): https://projects.drogon.net/raspberry-pi/wiringpi/pins/

PIN assignemnts (physical PINs on P1 header, with BCM GPIO numbers used in config):

  • 5V power into Raspberry: physical #1
  • Ground from power source to Raspberry: physical #9
  • 5V power out into Adafruit PN532 reader: #4
  • Ground for Adafruit PN352: physical #6
  • BERA-E lock open/close: physical #22, BCM GPIO #25
  • Open/close switch input PIN: physical #15, BCM GPIO #22
  • Ground for open/close switch: physical #25
  • SPI pins for Adafruit PN532 reader - SPI PINs on Raspberry - physical #19, #21, #23, #24

GitHub, last commits

Photos of cable connections of Raspi + PN532 shield (location Ke kaplicce 18)

Brmdoor HOWTO (displayed after you login as root, in /etc/motd)

Current brmdoor directory is `/root/brmdoor_libnfc`
Config is in the file: `/root/brmdoor_libnfc/brmdoor_nfc.config`

Full README is at https://github.com/hiviah/brmdoor_libnfc/blob/master/README.md

A preferred way to add a card is to add it to JendaSAP, then import (see below).

## Import cards.txt from JendaSAP's cards.txt (WARNING: THIS WILL OVERWRITE THE TABLE WITH UIDs)

    cd brmdoor_libnfc/
    ./import_jendasap_cards.py cards.txt brmdoor.sqlite

If `brmdoor.sqlite` does not exist, it will be created. If it exists, the `authorized_uids`
table will be replaced with UIDs/nick pairs from `cards.txt` (other tables are not touched).

## Adding card by UID

Note: this is useful for adding card temporarily since import from JendaSAP will remove it

- find out the UID:
  1. put the card near the reader,
  2. as root, look into the log, currently /root/brmdoor_libnfc/brmdoor.log
- look into the log for the unknown UID, look for `Unknown UID` message
- the following command will add a card as authenticated by UID, for other methods see full README

    cd brmdoor_libnfc/
    ./brmdoor_adduser.py -c brmdoor_nfc.config -a uid 1234ABCD SomeUserName

## List authorized cards UIDs + nicks from DB

    sqlite3 ~/brmdoor_libnfc/brmdoor.sqlite 'select nick, uid_hex from authorized_uids;'

## Start/stop daemon

systemctl start brmdoor.service
systemctl stop brmdoor.service
Systemd unit location: `/etc/systemd/system/brmdoor.service`


Source: brmdoor_libnfc

Requires libnfc, libfreefare and WiringPi2


  • Clean, documented and extensible code
  • Authentication data is stored in SQLite DB - no need to restart daemon to make any change; extensible DB schemas
  • NFC smartcard communication support (ISO 14443-4)
  • Multiple authentication schemes supported
  • Dedicated configuration file and logging facilities

Missing features:

  • No sound produced (can be fixed via WiringPi)
  • Setting topic is not finished (python-irc has fairly bad API to retrieve topic)
Except where otherwise noted, content on this wiki is licensed under the following license: CC Attribution-Noncommercial-Share Alike 4.0 International
Recent changes RSS feed Donate Powered by PHP Valid XHTML 1.0 Valid CSS Driven by DokuWiki