The reader is from Aliexpress (was $US9.20 during 11.11 sale, lets buy more next sale) 17.44C$ |Free shipping PN532 NFC RFID module User Kits for Arduino compatible|modul|module pvmodule gps - AliExpress Is connected via SPI using the ICSP connector.
The motor shield is a copy I made of the Adafruit v2 motor shield Adafruit Motor/Stepper/Servo Shield for Arduino v2 Kit [v2.3] : ID 1438 : $19.95 : Adafruit Industries, Unique & fun DIY electronics and kits uses i2c.
The code is very basic. One we have a card database my goal is to turn the locker into a basic vending machine for smd parts. Iāll add wifi/ethernet somehow to do this.
#include <SPI.h>
#include <Adafruit_PN532.h>
#include <Wire.h>
#include <Adafruit_MotorShield.h>
#include "utility/Adafruit_PWMServoDriver.h"
static const uint8_t tomcard[] = {0x4, 0x2, 0x63, 0xEA, 0x50, 0x49, 0x81};
static const uint8_t limit_pin = 6;
static const uint8_t pn532_ss_pin = 10;
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
Adafruit_StepperMotor *myMotor = AFMS.getStepper(200, 2);
Adafruit_PN532 nfc(pn532_ss_pin);
static bool dooropen = true;
#define DEBUG 0
void lock()
{
if (!dooropen) return;
while (!digitalRead(limit_pin))
{
myMotor->onestep(BACKWARD, DOUBLE);
delay(40);
}
myMotor->step(3, FORWARD, DOUBLE);
myMotor->release();
dooropen = false;
}
void unlock()
{
if (dooropen) return;
myMotor->step(50, FORWARD, DOUBLE);
myMotor->release();
dooropen = true;
}
void setup()
{
#if DEBUG
Serial.begin(9600);
while (!Serial);
Serial.println("setup()");
#endif
pinMode(limit_pin, INPUT);
AFMS.begin(); // create with the default frequency 1.6KHz
myMotor->setSpeed(30); // 30 rpm
nfc.begin();
uint32_t versiondata = nfc.getFirmwareVersion();
if (! versiondata)
{
#if DEBUG
Serial.print("Didn't find PN53x board");
#endif
unlock();
while (1); // halt
}
#if DEBUG
Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX);
Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC);
Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
#endif
// Set the max number of retry attempts to read from a card
// This prevents us from waiting forever for a card, which is
// the default behaviour of the PN532.
nfc.setPassiveActivationRetries(0xFF);
// configure board to read RFID tags
nfc.SAMConfig();
#if DEBUG
Serial.println("Waiting for an ISO14443A card");
#endif
lock();
}
void loop()
{
uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 }; // Buffer to store the returned UID
uint8_t uidLength; // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
bool success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, &uid[0], &uidLength);
if (success)
{
if (uidLength == sizeof(tomcard) && !memcmp(tomcard, uid, sizeof(tomcard)))
{
if (dooropen)
lock();
else
unlock();
}
#if DEBUG
Serial.println("Found a card!");
Serial.print("UID Length: ");
Serial.print(uidLength, DEC);
Serial.println(" bytes");
Serial.print("UID Value: ");
for (uint8_t i=0; i < uidLength; i++)
{
Serial.print(" 0x");Serial.print(uid[i], HEX);
}
Serial.println("");
#endif
// Wait 1 second before continuing
delay(1000);
}
else
{
#if DEBUG
// PN532 probably timed out waiting for a card
Serial.println("Timed out waiting for a card");
#endif
}
}
So very cool! Love to see how people are using these new cards!
When the time is right, all the Nomos services are in place to authenticate member cards and we can easily expand on those to suit project needs!
Is there a demo to look at? I guess itās json? Wondering if thereās something light enough to put into an Arduino? i guess it needs https? Something simple that gives a different http error code for valid, invalid, expired cards perhaps? Ok, Iāll look at the nomos source.
Thereās a little bit of documentation in the API section if you log into
Nomos.
Garth also implemented some stuff on the front doorās github:
https://github.com/vhs/intercom-access
I think a single central reader which pops open the correct locker door based on scanned card would be very cool.
Currently all of the end points are JSON via HTTP. It is not difficult to provide any variety of endpoints over HTTP, restful, simple response codes or formats, etc. If we want to go with any other sort of protocol aside from HTTP that is also possible but HTTP is the preferred protocol with JSON endpoints being the ideal.
Documentation is limited but as Jarrett pointed out, intercom-access shows how the pin auth works. The method is nearly identical for RFID. There is also a tab in Nomos itself that describes the basics about creating an API key and getting started with testing.
If creating an API under your user account, youāll be limited to grant only the permissions you have access to with your account. Some of the Auth methods require an administrative role to add RFID/Authentication permissions to an API key. Iād be more than happy to issue you an API key with the appropriate permissions as necessarily. We are still working on improving the workflow/UI to make this more readily available in a self-service manner.
See Nomos also review that Usage tab, itāll provide a brief run down on how to authenticate requests with API keys and how to get a JSON response that describes all of the services currently available on our system (http://membership.vanhack.ca/services/web/help).
If youāre interested in looking at the code, review the service contracts to see which services we provide nomos/app/contracts at master Ā· vhs/nomos Ā· GitHub
nomos/app/services at master Ā· vhs/nomos Ā· GitHub - these are the service implementations if you need to know how they work.
nomos/app/endpoints/web at master Ā· vhs/nomos Ā· GitHub describes which endpoints are registered. As of right now they are all of type JsonEndpoint
@lathlo, can you give me an example of what Iām permitted to do. I get Access denied for the things Iāve tried. Thanks. I know Iām posting my key here, have killed it.
tkeddie@tkeddie-ubuntuvm:~/tmp$ cat api.py
import json, requests
# /services/web/UserService1.svc/GetUsers
url = "http://membership.vanhack.ca/services/web/MemberCardService1.svc/ValidateGenuineCard?key=0x040263ea504981"
headers = {'X-Api-Key': '7b103e2405c08d93e6cb146ce4d65ca6c8e47a6886df460aa68cd8c10a5a38c7'}
resp = requests.get(url=url, headers=headers)
print(resp.text)
IMembershipCardService.ValidateGenuineCard($key) is a simple service with limited permission requirements (only need to be a valid user) that you can use to validate if an RFID key is a valid and genuine VHS membership card.
http://membership.vanhack.ca/services/web/MembershipCardService.svc/ValidateGenuineCard?key=value
There arenāt many extra services for card services yet that will give you any real details about users or anything other than the auth services. We are kinda looking for feedback from what people want to do and then the services can be added.
If you look at nomos/app/contracts at master Ā· vhs/nomos Ā· GitHub the @permission lines will give you an idea of the requirements for certain service calls.
So interesting services for an individual user might be:
http://membership.vanhack.ca/services/web/UserService1.svc/GetStanding?userid=
This will return true/false depending on your current payment standing.
http://membership.vanhack.ca/services/web/UserService1.svc/GetUser?userid=
This will return a bunch of details about your current user profile data.
Our web UI is a pure javascript client that uses the webservices for all of the data that is displayed, so it serves as a great example of what you can do. If you use Chrome, hit Ctrl+J to open the console, click the network tab - with this open while you login to Nomos and browse around youāll be able to see the service calls it makes and the responses.
To get your user id for the currently logged in user:
http://membership.vanhack.ca/services/web/AuthService1.svc/CurrentUser
This will give you a response like:
{āidā:ā42ā,āpermissionsā:[ādoorā,āvettedā,ādoorā,ālaserā,āadministratorā,āuserā]}
That is your user ID and which permissions you have available.
If you generated an API key, make sure you add permissions to that key before you try to use it.
@TomKeddie looks like I mustāve broke some API key permissions at some pointā¦ you should have an inherit option in that list of permissions for the key that would give the āuserā permission. āuserā is required for many of those servicesā¦ at this stage itās basically only allowed to call services that only require āauthenticatedā which is very few. Iāve at least changed ValidateGenuineCard to only require āauthenticatedā
Thanks, I see the difference, much appreciated. Iāll try to put together an Arduino example so we can start sticking these things everywhereā¦ I think this will work fine with the limited ram.
Here is a working python example.
import json, requests
url = "http://membership.vanhack.ca/services/web/MemberCardService1.svc/ValidateGenuineCard?key=04:02:63:ea:50:49:81"
headers = {'X-Api-Key': 'your key goes here'}
resp = requests.get(url=url, headers=headers)
print(resp.text)
@TomKeddie Iāve fixed the inherit option in the API keys section. That would be the only permission you need to add to get everything in the list plus āuserā. The intention is to have granular permissions for service type categories so there is more control but at this time those donāt yet exist. They are easily added as we sort of discover our needs.
For now, setting the API key to Inherit will give you the important āuserā permission (plus everything in that list) so you can run any service you would otherwise be able to as if you logged in.
Note that this is kinda dangerous because that API key could change passwords, see and change pin access codes, etc so make sure you donāt leak your API keys.
In the future Iāll add more granular permissions so that this isnāt such a big deal. Itās easier from an admin perspective because we designed that sorta first where any VHS type appliance would have a dedicated API key for it.
The idea behind the member created API keys are so that people could distribute apps or whatever and people can put in their own API key without having to worry about entering in their direct credentials. We also have oauth for this for more high level type apps you may use.
All that said, if you find some services you think make sense to have specific privileges defined I will gladly add them.
@TomKeddie I also noticed in one of your above snippets that you provided a rfid key in a hex code format such as 0x 0402ā¦ we are using a specific string format for the member cards such as:
04:02:63:ea:0f:0f:0f
At this time I believe they are also case sensitive and should be lower case for the alphabet characters.
I have logged an issue in github to track this enhancement: Support different formats for RFID member card keys Ā· Issue #157 Ā· vhs/nomos Ā· GitHub
Thanks, lower case is fine with me.
Itās a fine line between privacy and features. Itās almost like we want a register of applications that people can permit some of their data to be exposed to. Iād like to be able to get names and emails from rfid keys but it needs to be opt in somehow.