javaraspberry-pi3android-thingswiegand

Wiegand 26 protocol on Android Things


I'm using Android things with a VSIONIS keypad in reader mode, which outputs on D0 and D1 pins in Wiegand 26 format. I found a few libraries on how to do this on Arduino and have ported over the code, but cannot seem to make it work on Android Things. I'm using a Raspberry Pi 3. Does anyone have any knowledge on how to make this work?

Here's the Arduino library.

Here's the ported over code:

/**
 * @author bilal
 */
public class Wiegand {
    public static final String TAG = "thing:Wiegand";

    long cardTempHigh = 0;
    long cardTemp = 0;
    long lastWiegand = 0;
    long sysTick = 0;
    long code = 0;
    int bitCount = 0;
    int wiegandType = 0;

    ///
    long codehigh, codelow;

    private static final String GPIO_PIN_D0_Name = "BCM4";
    private static final String GPIO_PIN_D1_Name = "BCM5";

    private Gpio mWiegand34GpioD0;
    private Gpio mWiegand34GpioD1;

    public void begin() {

        System.out.println("wiegand begin");
        lastWiegand = 0;
        cardTempHigh = 0;
        cardTemp = 0;
        code = 0;
        wiegandType = 0;
        bitCount = 0;
        sysTick = System.currentTimeMillis();

//        final GpioPinDigitalInput D0Pin = gpio.provisionDigitalInputPin(RaspiPin.GPIO_00, PinPullResistance.PULL_UP);
//        final GpioPinDigitalInput D1Pin = gpio.provisionDigitalInputPin(RaspiPin.GPIO_07, PinPullResistance.PULL_UP);

        PeripheralManagerService service = new PeripheralManagerService();
        Log.d("thing:Wiegand (begin)", "Available GPIO: " + service.getGpioList());

        try {
            // Step 1. Create GPIO connection.
            mWiegand34GpioD0 = service.openGpio(GPIO_PIN_D0_Name);
            mWiegand34GpioD1 = service.openGpio(GPIO_PIN_D1_Name);
            // Step 2. Configure as an input.
            mWiegand34GpioD0.setDirection(Gpio.DIRECTION_IN);
            mWiegand34GpioD1.setDirection(Gpio.DIRECTION_IN);
            // Step 3. Enable edge trigger events.
            mWiegand34GpioD0.setEdgeTriggerType(Gpio.EDGE_FALLING);
            mWiegand34GpioD1.setEdgeTriggerType(Gpio.EDGE_FALLING);

            //Testing what this do
            //mWiegand34GpioD0.setActiveType(Gpio.ACTIVE_HIGH);

            // Step 4. Register an event callback.
            mWiegand34GpioD0.registerGpioCallback(data_pulse0);
            mWiegand34GpioD1.registerGpioCallback(data_pulse1);
        } catch (IOException e) {
            Log.e(TAG, "Error on PeripheralIO API", e);
        }


        //attachInterrupt(0, ReadD0, FALLING); // Hardware interrupt - high to low pulse
        //attachInterrupt(1, ReadD1, FALLING); // Hardware interrupt - high to low pulse
    }

    private GpioCallback data_pulse0 = new GpioCallback() {
        @Override
        public boolean onGpioEdge(Gpio gpio) {
            bitCount++; // Increment bit count for Interrupt connected to D0
            if (bitCount > 31) { // If bit count more than 31, process high bits
                cardTempHigh |= ((0x80000000 & cardTemp) >> 31); // shift value to high bits
                cardTempHigh = 1;
                cardTemp = 1;
            } else {
                cardTemp = 1; // D0 represent binary 0, so just left shift card data
            }

            lastWiegand = sysTick; // Keep track of last wiegand bit received
            Log.d(TAG + "data_pulse0)", cardTemp + "");
            return true;
        }
    };

    private GpioCallback data_pulse1 = new GpioCallback() {
        @Override
        public boolean onGpioEdge(Gpio gpio) {
            bitCount++; // Increment bit count for Interrupt connected to D1

            if (bitCount > 31) { // If bit count more than 31, process high bits

                cardTempHigh |= ((0x80000000 & cardTemp) >> 31); // shift value to high bits
                cardTempHigh = 1;
                cardTemp |= 1;
                cardTemp = 1;
            } else {
                cardTemp |= 1; // D1 represent binary 1, so OR card data with 1 then
                cardTemp = 1; // left shift card data
            }

            lastWiegand = sysTick; // Keep track of last wiegand bit received
            Log.d(TAG + "data_pulse1)", cardTemp + "");
            return true;
        }
    };

    boolean available() {
        return DoWiegandConversion();
    }

    public long getCode() {
        return code;
    }


    long GetCardId(char bitlength) {

        long cardID = 0;

        if (bitlength == 26) // EM tag
            cardID = (codelow & 0x1FFFFFE) >> 1;

        if (bitlength == 34) { // Mifare
            codehigh = codehigh & 0x03; // only need the 2 LSB of the codehigh
            codehigh = 30; // shift 2 LSB to MSB
            codelow = 1;
            cardID = codehigh | codelow;
        }
        Log.d(TAG + "(GetCardId)", cardID + "");
        System.out.println("cardID:" + cardID);
        return cardID;
    }

    public boolean DoWiegandConversion() {
        long cardID;
        sysTick = System.currentTimeMillis();

        if ((sysTick - lastWiegand) > 25) { // if no more signal coming through after 25ms
            if ((bitCount == 26) || (bitCount == 34) || (bitCount == 8)) { // bitCount for keypress=8, Wiegand 26=26, Wiegand 34=34
                cardTemp >>= 1; // shift right 1 bit to get back the real value - interrupt done 1 left shift in advance
                if (bitCount > 32) // bit count more than 32 bits, shift high bits right to make adjustment
                    cardTempHigh >>= 1;
                if ((bitCount == 26) || (bitCount == 34)) { // wiegand 26 or wiegand 34

                    cardID = GetCardId((char) bitCount);
                    wiegandType = bitCount;
                    bitCount = 0;
                    cardTemp = 0;
                    cardTempHigh = 0;
                    code = cardID;

                    return true;
                } else if (bitCount == 8) { // keypress wiegand
                    // 8-bit Wiegand keyboard data, high nibble is the "NOT" of low nibble
                    // eg if key 1 pressed, data=E1 in binary 11100001 , high nibble=1110 , low nibble = 0001
                    char highNibble = (char) ((cardTemp & 0xf0) >> 4);
                    char lowNibble = (char) (cardTemp & 0x0f);
                    wiegandType = bitCount;
                    bitCount = 0;
                    cardTemp = 0;
                    cardTempHigh = 0;

                    if (lowNibble == (~highNibble & 0x0f)) { // check if low nibble matches the "NOT" of high nibble.
                        if (lowNibble == 0x0b) { // ENT pressed
                            code = 0x0d;
                        } else if (lowNibble == 0x0a) { // ESC pressed
                            code = 0x1b;
                        } else {
                            code = (int) lowNibble; // 0 - 9 keys
                        }

                        return true;
                    }
                }
            } else {
                // well time over 25 ms and bitCount !=8 , !=26, !=34 , must be noise or nothing then.
                lastWiegand = sysTick;
                bitCount = 0;
                cardTemp = 0;
                cardTempHigh = 0;
                return false;
            }
        }

        return false;
    }
}

And called from my Activity here:

Wiegand wiegand = new Wiegand();
wiegand.begin();
Log.d(TAG, wiegand.getCode() + "");

Solution

  • It's a work in progress but it is working: https://gist.github.com/austinn/e9b6daa322e928c8cf3e06b06cdfb3c5