Here is a little project I have been working on for the past few months. This project is essentially a Wiegand code generator and a range extender over IP. I gave it the nickname WEX (Wiegand EXtender). While eventually it could become a real commercial or open source product, right now it is mainly a tool I couldn’t do without.
Few month ago, while I was working on a .net C# web service application, I realize that I had no real way of testing this new application. My application was creating a bridge between the Kantech Hattrix access control system and a customer HR system. Of course I could swipe a card in front a access control reader a couple of time to get some access granted and simulate how my software would behave (and I did of course), but since the customer was a large company with more than 1000 swipes per hour, I knew I had to come up with something better to emulate this scenario.
My initial goal was to create a tool that could attached itself to the card reader port of an access controller (in this case a Kantech KT-300) and generate at regular intervals, a card swipe (wiegand data pulses). The solution had to be controlled remotely over the network (I’m lazy, I did not want to walk to the generator each time I wanted to start a test). Finally, it had to be cheap.
Everybody loves PI:
Since I’ve been playing for a couple of month with the Raspberry PI, I decided this project would be a perfect candidate for this small and cheap single board computer.
The PI has GPIOs pins, runs Linux (Raspbian, a Raspberry PI Linux flavour) and is amazingly user friendly. Like many other people I bought a Raspberry PI out of curiosity, without any real intendend purpose. I got one now.
My first step was to get a wiegand interface on the PI. As Wikipedia is rightfully putting it:
The Wiegand interface uses three wires, one of which is a common ground and two of which are data transmission wires usually called DATA0 and DATA1, alternately labeled “D0” and “D1” or “Data Low” and “Data High”. When no data is being sent, both DATA0 and DATA1 are pulled up to the “high” voltage level — usually +5 VDC. When a 0 is sent the DATA0 wire is pulled to a low voltage while the DATA1 wire stays at a high voltage. When a 1 is sent the DATA1 wire is pulled to a low voltage while DATA0 stays at a high voltage
This translate to the following graphic in the logic analyser when you present a card in front of the HID card reader.
The screen is split in half where the upper part is DATA0 (the green wire) and the bottom part is DATA1 (the white wire). The vertical line are drop in voltage for about 40 μs (microseconds). The firmware will need to detect this voltage dropped and transcode this information in binary format.
The simple circuit:
The following very simple circuit was only created to protect the 3.3v Raspberry PI GPIO pins from the 5v output of the Wiegand reader. In order to achieve this I picked up the Bi-Directionnal Logic Level Converter from Sparkfun. But the 4-channel Bi-directional Logic Level Converter board from Adafruit would have done the trick too. I added a couple of leds just to get a status update of the different operations.
In this setup, the wiegand card reader (connected to pin 17 and 18) is taking its power from the 5v output of the PI.
Here is a diagram of the connections. The LEDs are simply used for status updates (card generation, card read, TCP/IP connection status, …).
The firmware development:
Many developers out there had a hard time to get the PI to read Wiegand data .The main cause of their failure was most likely the fact they tried to use an interpreted language (such as Python) to read the wiegand pulses, microseconds apart. This kind of language was not really intended for this type of job.
This is why I decided to use a development language such as C/C++ and a compiled binary. I used a cross compiler on Linux Ubuntu with the Eclipse IDE. The program is compiles using the arm-bcm2708 GCC cross compiler tool-chain (a good guide for this is found here). While I could accessed directly the GPIOs, I still decided to use the WiringPi library. Gordon (the creator of the lib) did a great job at simplifying the process and use a syntax similar to Arduino.
The WEX operations:
The operation of the program is separated in 3 modes:
- Wiegand signal read from the GPIOs
- Wiegand signal write to the GPIOs
- Wiegand code generator
Here is a screenshot of the program command line (connected by ssh to the PI):
Wiegand signal read mode:
The read mode is very useful to read the identity of a card, log transactions to a file or to send Wiegand signal over the network. Here is a few examples:
./wpp -r -o myLog.csv
The previous command will start wex in read mode and display on screen every wiegand read it gets (typically coming from a wiegand reader attached to the raspberry PI). The transactions are also logged to a comma delimited file under the name of myLog.csv. Please note this command need to be preceed by “sudo” to grant supervisory rights since we are accessing the GPIOs.
You will notice that on each read sequence, the Wex software count the number of bits received, display the raw representation in binary, display the interpretation (site:ID) and confirm the validity of the checksum.
The following is similar to the previous command, but this time we are sending the Wiegand signal we read from the GPIOs to a remote network IP address.
./wpp -r -n 192.168.1.67:6777 -o myLog.csv
The data is sent through an encrypted TCP/IP connection. At this time, the communication is unidirectional. It is only from the reader to the remote writer.
As you might guess the remote recipient will be a WEX software in the wiegand signal write mode (see next section).
Wiegand signal write mode:
The wiegand signal write mode is useful to relay the wiegand data from a remote reader over the network (running wex in a Raspberry PI, connected to a card reader). The wex in write mode would typically be attached to a access controller. Here is an example
./wpp -w -n 6777 -o myServerLog.csv
In this mode the wex program will act as a server and receive wiegand data from any wex reader by listening to the network port 6777. So with two networked Raspberry PI, one attached to the card reader and one attached to an access controller we just created a wiegand range extender. In effect, the card reader could be in Montreal and the access controller in Taiwan. The distance does not really matter. Alternatively, you could also connect the Raspberry Pi over the network with Wifi dongles and you got yourself a wifi reader.
Wiegand signal generator mode:
While the previous description of wiegand data transmission over the network is an interesting concept, it is actually a side effect of the main purpose why I developed the code in the first place. That is, to generate wiegand data.
In this mode, the Wex program generate at fix interval a wiegand data pulse. Here is an example:
./wpp -w -g AA:10000-AA:10006 -p 2 -0 outputtestlog.txt
The previous command will output 7 wiegand data pulse through GPIO 17 and 18 with a pause of 2 seconds between each transmission. It will then terminate by itself. If you attached the PI to an access controller for example, it would simulate someone swapping 7 different cards.
Since I like to generate lots of traffic, I usually specify larger range like (AA:00001- AA:65535). This will keep the access control equipment busy for a while.
Of course, this is a modest little software that I find useful in my specific development context. It shows however some of the great potential of this little 35$ micro-controller.
Here is some of the features I am currently working on:
- Real-time watchdog
- Network encryption
- Led and buzzer feedback (card reader feedback)
- Remote relay operations (remote door unlock)