Initial commit
This commit is contained in:
commit
af6dcf2629
|
@ -0,0 +1,5 @@
|
||||||
|
*.config
|
||||||
|
*.creator
|
||||||
|
*.creator.*
|
||||||
|
*.files
|
||||||
|
*.includes
|
|
@ -0,0 +1,52 @@
|
||||||
|
#include "ArduinoGpio.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
ArduinoGpio::ArduinoGpio(int pin, bool initialValue, IGpio::Mode initialMode):
|
||||||
|
pin(pin)
|
||||||
|
{
|
||||||
|
/* There is no protection to prevent from creation of multiple instances
|
||||||
|
* of single pin, as Arduino does not support C++ exceptions.
|
||||||
|
* Only one parent object may own instance of a pin.
|
||||||
|
*/
|
||||||
|
write(initialValue);
|
||||||
|
setMode((initialMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoGpio::~ArduinoGpio()
|
||||||
|
{
|
||||||
|
setMode(Mode::Input);
|
||||||
|
write(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool ArduinoGpio::read()
|
||||||
|
{
|
||||||
|
return (digitalRead(pin) != 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoGpio::write(bool newValue)
|
||||||
|
{
|
||||||
|
digitalWrite(pin, newValue ? HIGH : LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
IGpio::Mode ArduinoGpio::getMode()
|
||||||
|
{
|
||||||
|
return mode;
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoGpio::setMode(IGpio::Mode newMode)
|
||||||
|
{
|
||||||
|
mode = newMode;
|
||||||
|
pinMode(pin, toAdruinoMode(newMode));
|
||||||
|
}
|
||||||
|
|
||||||
|
int ArduinoGpio::toAdruinoMode(IGpio::Mode mode)
|
||||||
|
{
|
||||||
|
switch(mode) {
|
||||||
|
case Mode::Input:
|
||||||
|
return INPUT;
|
||||||
|
case Mode::InputPullup:
|
||||||
|
return INPUT_PULLUP;
|
||||||
|
case Mode::Output:
|
||||||
|
return OUTPUT;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,22 @@
|
||||||
|
#ifndef ARDUINOGPIO_H
|
||||||
|
#define ARDUINOGPIO_H
|
||||||
|
|
||||||
|
#include "IGpio.h"
|
||||||
|
|
||||||
|
class ArduinoGpio : public IGpio
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
ArduinoGpio(int pin, bool initialValue, Mode initialMode);
|
||||||
|
virtual ~ArduinoGpio();
|
||||||
|
virtual bool read();
|
||||||
|
virtual void write(bool newValue);
|
||||||
|
virtual Mode getMode();
|
||||||
|
virtual void setMode(Mode newMode);
|
||||||
|
|
||||||
|
private:
|
||||||
|
int pin;
|
||||||
|
Mode mode;
|
||||||
|
int toAdruinoMode(Mode mode);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ARDUINOGPIO_H
|
|
@ -0,0 +1,63 @@
|
||||||
|
#include "ArduinoSerialLogger.h"
|
||||||
|
#include <stdarg.h>
|
||||||
|
|
||||||
|
ArduinoSerialLogger::ArduinoSerialLogger(Serial_ &hardwareSerial):
|
||||||
|
hardwareSerial(hardwareSerial)
|
||||||
|
{
|
||||||
|
hardwareSerial.begin(DEBUG_CONSOLE_BAUD);
|
||||||
|
}
|
||||||
|
|
||||||
|
ArduinoSerialLogger::~ArduinoSerialLogger()
|
||||||
|
{
|
||||||
|
hardwareSerial.end();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoSerialLogger::debug(const char *format, ...) const
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
formatLog("DBG/", format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoSerialLogger::info(const char *format, ...) const
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
formatLog("INF/", format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoSerialLogger::warning(const char *format, ...) const
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
formatLog("WRN/", format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoSerialLogger::error(const char *format, ...) const
|
||||||
|
{
|
||||||
|
va_list args;
|
||||||
|
va_start(args, format);
|
||||||
|
formatLog("ERR/", format, args);
|
||||||
|
va_end(args);
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoSerialLogger::flush() const
|
||||||
|
{
|
||||||
|
hardwareSerial.flush();
|
||||||
|
}
|
||||||
|
|
||||||
|
void ArduinoSerialLogger::formatLog(const char *level, const char *format, va_list args) const
|
||||||
|
{
|
||||||
|
char newFormat[128];
|
||||||
|
/* This is the least crappy solution I came up with at 23:40 after a beer.
|
||||||
|
* sstream is not available on this platform.
|
||||||
|
* CAN YOU SPOT THE BUG? */
|
||||||
|
snprintf(newFormat, sizeof(newFormat), "%s%s\n", level, format);
|
||||||
|
|
||||||
|
char buffer[256];
|
||||||
|
vsnprintf(buffer, sizeof(buffer), newFormat, args);
|
||||||
|
hardwareSerial.print(buffer);
|
||||||
|
}
|
|
@ -0,0 +1,31 @@
|
||||||
|
#ifndef ARDUINOSERIALLOGGER_H
|
||||||
|
#define ARDUINOSERIALLOGGER_H
|
||||||
|
|
||||||
|
#include "ILogger.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
#define Serial_ HardwareSerial
|
||||||
|
class ArduinoSerialLogger : public ILogger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
explicit ArduinoSerialLogger(Serial_& hardwareSerial);
|
||||||
|
virtual ~ArduinoSerialLogger();
|
||||||
|
|
||||||
|
virtual void debug(const char *format, ...) const;
|
||||||
|
virtual void info(const char *format, ...) const;
|
||||||
|
virtual void warning(const char* format, ...) const;
|
||||||
|
virtual void error(const char* format, ...) const;
|
||||||
|
|
||||||
|
virtual void flush() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
DEBUG_CONSOLE_BAUD = 9600
|
||||||
|
};
|
||||||
|
|
||||||
|
void formatLog(const char* level, const char* format, va_list args) const;
|
||||||
|
|
||||||
|
Serial_& hardwareSerial;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ARDUINOSERIALLOGGER_H
|
|
@ -0,0 +1,29 @@
|
||||||
|
#include "DoorLock.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
DoorLock::DoorLock(IGpio &gpio, DoorLock::ActiveState activeState, DoorLock::TMilliseconds openTime):
|
||||||
|
gpio(gpio),
|
||||||
|
activeState(activeState),
|
||||||
|
openTime(openTime)
|
||||||
|
{
|
||||||
|
deactivate();
|
||||||
|
gpio.setMode(IGpio::Mode::Output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoorLock::open()
|
||||||
|
{
|
||||||
|
activate();
|
||||||
|
delay(openTime);
|
||||||
|
deactivate();
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoorLock::activate()
|
||||||
|
{
|
||||||
|
gpio.write(activeState == ActiveState::High);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoorLock::deactivate()
|
||||||
|
{
|
||||||
|
gpio.write(activeState != ActiveState::High);
|
||||||
|
}
|
|
@ -0,0 +1,27 @@
|
||||||
|
#ifndef DOORLOCK_H
|
||||||
|
#define DOORLOCK_H
|
||||||
|
|
||||||
|
#include "IGpio.h"
|
||||||
|
|
||||||
|
class DoorLock
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class ActiveState {
|
||||||
|
Low,
|
||||||
|
High,
|
||||||
|
};
|
||||||
|
typedef int TMilliseconds;
|
||||||
|
|
||||||
|
DoorLock(IGpio& gpio, ActiveState activeState, TMilliseconds openTime);
|
||||||
|
void open();
|
||||||
|
|
||||||
|
private:
|
||||||
|
void activate();
|
||||||
|
void deactivate();
|
||||||
|
|
||||||
|
IGpio& gpio;
|
||||||
|
ActiveState activeState;
|
||||||
|
TMilliseconds openTime;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DOORLOCK_H
|
|
@ -0,0 +1,61 @@
|
||||||
|
#include "DoorLockController.h"
|
||||||
|
|
||||||
|
DoorLockController::DoorLockController() :
|
||||||
|
logger(Serial),
|
||||||
|
greenLedGpio(LED_GREEN_PIN, false, IGpio::Mode::Output),
|
||||||
|
redLedGpio(LED_RED_PIN, false, IGpio::Mode::Output),
|
||||||
|
doorLockGpio(DOOR_PIN, false, IGpio::Mode::Output),
|
||||||
|
statusLed(redLedGpio, greenLedGpio),
|
||||||
|
doorLock(doorLockGpio, DoorLock::ActiveState::Low, DOOR_OPEN_TIME_MS),
|
||||||
|
nfcAuthenticator(NFC_SLAVE_SELECT_PIN, NFC_RESET_PIN, logger),
|
||||||
|
oneWireAuthenticator(ONEWIRE_PIN, logger),
|
||||||
|
authenticators{&nfcAuthenticator, &oneWireAuthenticator},
|
||||||
|
unauthorizedAccess(false),
|
||||||
|
heartbeatCounter(0)
|
||||||
|
{
|
||||||
|
logger.info("Ready. Waiting for keys.");
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoorLockController::heartbeat()
|
||||||
|
{
|
||||||
|
heartbeatCounter = (heartbeatCounter == BLINK_INTERVAL_CYCLES - 1) ? 0 : heartbeatCounter+1;
|
||||||
|
if(heartbeatCounter == 0)
|
||||||
|
statusLed.setState(unauthorizedAccess ? DualColorLed::State::Red : DualColorLed::State::Green);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoorLockController::checkForKeys()
|
||||||
|
{
|
||||||
|
for(IAuthenticator* authenticator : authenticators) {
|
||||||
|
Key key = authenticator->getKey();
|
||||||
|
if(!key.isValid())
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if(keyDatabase.contains(key))
|
||||||
|
{
|
||||||
|
statusLed.setState(DualColorLed::State::Green);
|
||||||
|
logger.info("Access granted.");
|
||||||
|
unauthorizedAccess = false;
|
||||||
|
doorLock.open();
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
statusLed.setState(DualColorLed::State::Red);
|
||||||
|
logger.error("ACCESS DENIED!");
|
||||||
|
unauthorizedAccess = true;
|
||||||
|
delay(DOOR_OPEN_TIME_MS);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoorLockController::run()
|
||||||
|
{
|
||||||
|
for(;;)
|
||||||
|
{
|
||||||
|
heartbeat();
|
||||||
|
checkForKeys();
|
||||||
|
statusLed.setState(DualColorLed::State::Off);
|
||||||
|
delay(POLLING_INTERVAL_MS);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
#ifndef CDOORLOCKCONTROLLER_H
|
||||||
|
#define CDOORLOCKCONTROLLER_H
|
||||||
|
|
||||||
|
#include "ArduinoGpio.h"
|
||||||
|
#include "ArduinoSerialLogger.h"
|
||||||
|
|
||||||
|
#include "DoorLock.h"
|
||||||
|
#include "NfcAuthenticator.h"
|
||||||
|
#include "OneWireAuthenticator.h"
|
||||||
|
#include "HardcodedKeyStorage.h"
|
||||||
|
#include "DualColorLed.h"
|
||||||
|
|
||||||
|
class DoorLockController
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
DoorLockController();
|
||||||
|
void run();
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
NFC_SLAVE_SELECT_PIN = 10,
|
||||||
|
NFC_RESET_PIN = 9,
|
||||||
|
ONEWIRE_PIN = 8,
|
||||||
|
DOOR_PIN = 4,
|
||||||
|
LED_RED_PIN = 3,
|
||||||
|
LED_GREEN_PIN = 2,
|
||||||
|
DOOR_OPEN_TIME_MS = 3000,
|
||||||
|
NUM_AUTHENTICATORS=2,
|
||||||
|
POLLING_INTERVAL_MS = 250,
|
||||||
|
BLINK_INTERVAL_CYCLES = 20
|
||||||
|
};
|
||||||
|
|
||||||
|
void heartbeat();
|
||||||
|
void checkForKeys();
|
||||||
|
|
||||||
|
ArduinoSerialLogger logger;
|
||||||
|
ArduinoGpio greenLedGpio, redLedGpio, doorLockGpio;
|
||||||
|
|
||||||
|
DualColorLed statusLed;
|
||||||
|
DoorLock doorLock;
|
||||||
|
NfcAuthenticator nfcAuthenticator;
|
||||||
|
OneWireAuthenticator oneWireAuthenticator;
|
||||||
|
IAuthenticator* authenticators[NUM_AUTHENTICATORS];
|
||||||
|
HardcodedKeyStorage keyDatabase;
|
||||||
|
|
||||||
|
bool unauthorizedAccess;
|
||||||
|
short heartbeatCounter;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // CDOORLOCKCONTROLLER_H
|
|
@ -0,0 +1,37 @@
|
||||||
|
#include "DualColorLed.h"
|
||||||
|
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
DualColorLed::DualColorLed(IGpio& redGpio, IGpio& greenGpio):
|
||||||
|
redGpio(redGpio),
|
||||||
|
greenGpio(greenGpio),
|
||||||
|
currentState(State::Off)
|
||||||
|
{
|
||||||
|
redGpio.write(false);
|
||||||
|
greenGpio.write(false);
|
||||||
|
redGpio.setMode(IGpio::Mode::Output);
|
||||||
|
greenGpio.setMode(IGpio::Mode::Output);
|
||||||
|
}
|
||||||
|
|
||||||
|
void DualColorLed::setState(DualColorLed::State newState)
|
||||||
|
{
|
||||||
|
if(currentState == newState)
|
||||||
|
return;
|
||||||
|
|
||||||
|
currentState = newState;
|
||||||
|
|
||||||
|
switch(newState) {
|
||||||
|
case State::Off:
|
||||||
|
redGpio.write(false);
|
||||||
|
greenGpio.write(false);
|
||||||
|
return;
|
||||||
|
case State::Red:
|
||||||
|
redGpio.write(true);
|
||||||
|
greenGpio.write(false);
|
||||||
|
return;
|
||||||
|
case State::Green:
|
||||||
|
redGpio.write(false);
|
||||||
|
greenGpio.write(true);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef DUALCOLORLED_H
|
||||||
|
#define DUALCOLORLED_H
|
||||||
|
|
||||||
|
#include "IGpio.h"
|
||||||
|
|
||||||
|
class DualColorLed
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class State {
|
||||||
|
Off,
|
||||||
|
Red,
|
||||||
|
Green
|
||||||
|
};
|
||||||
|
DualColorLed(IGpio& redGpio, IGpio& greenGpio);
|
||||||
|
|
||||||
|
void setState(State newState);
|
||||||
|
|
||||||
|
private:
|
||||||
|
IGpio& redGpio;
|
||||||
|
IGpio& greenGpio;
|
||||||
|
State currentState;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // DUALCOLORLED_H
|
|
@ -0,0 +1,36 @@
|
||||||
|
#include "HardcodedKeyStorage.h"
|
||||||
|
|
||||||
|
HardcodedKeyStorage::HardcodedKeyStorage():
|
||||||
|
keyTable( {
|
||||||
|
MifareClassicKey((const uint8_t[]) { 0x01, 0x02, 0x03, 0x04 }), // SAMPLE. DO NOT USE!
|
||||||
|
})
|
||||||
|
{}
|
||||||
|
|
||||||
|
HardcodedKeyStorage::~HardcodedKeyStorage() {}
|
||||||
|
|
||||||
|
bool HardcodedKeyStorage::contains(const Key& inputKey)
|
||||||
|
{
|
||||||
|
if(!inputKey.isValid())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
for(const Key& keyFromTable: keyTable)
|
||||||
|
{
|
||||||
|
if(inputKey == keyFromTable)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HardcodedKeyStorage::insert(const Key &existingKey, const Key &newKey)
|
||||||
|
{
|
||||||
|
(void) existingKey;
|
||||||
|
(void) newKey;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool HardcodedKeyStorage::remove(const Key &key)
|
||||||
|
{
|
||||||
|
(void) key;
|
||||||
|
return false;
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef HARDCODEDKEYSTORAGE_H
|
||||||
|
#define HARDCODEDKEYSTORAGE_H
|
||||||
|
|
||||||
|
#include "IKeyStorage.h"
|
||||||
|
|
||||||
|
class HardcodedKeyStorage: public IKeyStorage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
HardcodedKeyStorage();
|
||||||
|
|
||||||
|
virtual ~HardcodedKeyStorage();
|
||||||
|
virtual bool contains(const Key &inputKey);
|
||||||
|
virtual bool insert(const Key &existingKey, const Key &newKey);
|
||||||
|
virtual bool remove(const Key &key);
|
||||||
|
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
NUMBER_OF_ENTRIES = 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
Key keyTable[NUMBER_OF_ENTRIES];
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // HARDCODEDKEYSTORAGE_H
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef IAUTHENTICATOR_H
|
||||||
|
#define IAUTHENTICATOR_H
|
||||||
|
|
||||||
|
#include "Key.h"
|
||||||
|
|
||||||
|
class IAuthenticator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IAuthenticator() {};
|
||||||
|
|
||||||
|
virtual Key getKey() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IAUTHENTICATOR_H
|
|
@ -0,0 +1,20 @@
|
||||||
|
#ifndef IGPIO_H
|
||||||
|
#define IGPIO_H
|
||||||
|
|
||||||
|
class IGpio
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
enum class Mode {
|
||||||
|
Input,
|
||||||
|
InputPullup,
|
||||||
|
Output,
|
||||||
|
};
|
||||||
|
|
||||||
|
virtual ~IGpio() {}
|
||||||
|
virtual bool read() = 0;
|
||||||
|
virtual void write(bool value) = 0;
|
||||||
|
virtual Mode getMode() = 0;
|
||||||
|
virtual void setMode(Mode mode) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IGPIO_H
|
|
@ -0,0 +1,16 @@
|
||||||
|
#ifndef IKEYSTORAGE_H
|
||||||
|
#define IKEYSTORAGE_H
|
||||||
|
|
||||||
|
#include "Key.h"
|
||||||
|
|
||||||
|
class IKeyStorage
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~IKeyStorage() {}
|
||||||
|
|
||||||
|
virtual bool contains(const Key& key) = 0;
|
||||||
|
virtual bool insert(const Key& existingKey, const Key& newKey) = 0;
|
||||||
|
virtual bool remove(const Key& key) = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // IKEYSTORAGE_H
|
|
@ -0,0 +1,17 @@
|
||||||
|
#ifndef ILOGGER_H
|
||||||
|
#define ILOGGER_H
|
||||||
|
|
||||||
|
class ILogger
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual ~ILogger() {}
|
||||||
|
|
||||||
|
virtual void debug(const char *format, ...) const = 0;
|
||||||
|
virtual void info(const char *format, ...) const = 0;
|
||||||
|
virtual void warning(const char* format, ...) const = 0;
|
||||||
|
virtual void error(const char* format, ...) const = 0;
|
||||||
|
|
||||||
|
virtual void flush() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ILOGGER_H
|
|
@ -0,0 +1,48 @@
|
||||||
|
#include "Key.h"
|
||||||
|
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
Key::Key() :
|
||||||
|
type(KeyType::Invalid),
|
||||||
|
size(0),
|
||||||
|
value()
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
Key::Key(KeyType type, size_t size, const void *data):
|
||||||
|
type(type),
|
||||||
|
size(size),
|
||||||
|
value()
|
||||||
|
{
|
||||||
|
memcpy(value, data, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Key::isValid() const
|
||||||
|
{
|
||||||
|
return type != KeyType::Invalid;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Key::operator==(const Key &rhs) const
|
||||||
|
{
|
||||||
|
if(type == KeyType::Invalid)
|
||||||
|
return type == rhs.type;
|
||||||
|
|
||||||
|
return type == rhs.type && size == rhs.size && isBufferEqual(value, rhs.value, size);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool Key::isBufferEqual(const unsigned char *lhs, const unsigned char *rhs, size_t size) const
|
||||||
|
{
|
||||||
|
unsigned char maskOfDifferences = 0;
|
||||||
|
|
||||||
|
/** This comparison by design checks whole buffers to harden timing attacks */
|
||||||
|
for(size_t i = 0; i < size; ++i)
|
||||||
|
maskOfDifferences |= lhs[i] ^ rhs[i];
|
||||||
|
|
||||||
|
return (maskOfDifferences == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
DallasIButtonKey::DallasIButtonKey(const uint8_t uid[]):
|
||||||
|
Key(KeyType::iButton, UID_SIZE, uid) {}
|
||||||
|
|
||||||
|
MifareClassicKey::MifareClassicKey(const uint8_t nuid[]):
|
||||||
|
Key(KeyType::MifareClassic, NUID_SIZE, nuid) {}
|
|
@ -0,0 +1,48 @@
|
||||||
|
#ifndef KEY_H
|
||||||
|
#define KEY_H
|
||||||
|
|
||||||
|
#include <stddef.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
class Key {
|
||||||
|
public:
|
||||||
|
enum {
|
||||||
|
MAX_KEY_SIZE = 8
|
||||||
|
};
|
||||||
|
|
||||||
|
enum class KeyType
|
||||||
|
{
|
||||||
|
Invalid = 0,
|
||||||
|
MifareClassic = 1,
|
||||||
|
iButton = 2,
|
||||||
|
};
|
||||||
|
|
||||||
|
Key();
|
||||||
|
|
||||||
|
bool isValid() const;
|
||||||
|
bool operator==(const Key& rhs) const;
|
||||||
|
|
||||||
|
protected:
|
||||||
|
Key(KeyType type, size_t size, const void* data);
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool isBufferEqual(const unsigned char *lhs, const unsigned char* rhs, size_t size) const;
|
||||||
|
|
||||||
|
KeyType type;
|
||||||
|
size_t size;
|
||||||
|
unsigned char value[MAX_KEY_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
class DallasIButtonKey: public Key {
|
||||||
|
public:
|
||||||
|
enum {UID_SIZE = 8};
|
||||||
|
explicit DallasIButtonKey(const uint8_t uid[UID_SIZE]);
|
||||||
|
};
|
||||||
|
|
||||||
|
class MifareClassicKey: public Key {
|
||||||
|
public:
|
||||||
|
enum {NUID_SIZE = 4};
|
||||||
|
explicit MifareClassicKey(const uint8_t nuid[NUID_SIZE]);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // KEY_H
|
|
@ -0,0 +1,54 @@
|
||||||
|
#include "NfcAuthenticator.h"
|
||||||
|
|
||||||
|
#include "ILogger.h"
|
||||||
|
#include <SPI.h>
|
||||||
|
|
||||||
|
NfcAuthenticator::NfcAuthenticator(int nfcSlaveSelectPin, int nfcResetPin, const ILogger &logger):
|
||||||
|
rfid(nfcSlaveSelectPin, nfcResetPin),
|
||||||
|
logger(logger)
|
||||||
|
{
|
||||||
|
SPI.begin();
|
||||||
|
rfid.PCD_Init();
|
||||||
|
}
|
||||||
|
|
||||||
|
NfcAuthenticator::~NfcAuthenticator()
|
||||||
|
{}
|
||||||
|
|
||||||
|
Key NfcAuthenticator::getKey()
|
||||||
|
{
|
||||||
|
if(!initializeCard())
|
||||||
|
return Key();
|
||||||
|
|
||||||
|
uint8_t *nuid = rfid.uid.uidByte;
|
||||||
|
logger.debug("Mifare Classic tag detected, NUID: %02hhX %02hhX %02hhX %02hhX", nuid[0], nuid[1], nuid[2], nuid[3]);
|
||||||
|
|
||||||
|
releaseCard();
|
||||||
|
|
||||||
|
return MifareClassicKey(rfid.uid.uidByte);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool NfcAuthenticator::initializeCard()
|
||||||
|
{
|
||||||
|
if (!rfid.PICC_IsNewCardPresent())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (!rfid.PICC_ReadCardSerial())
|
||||||
|
return false;
|
||||||
|
|
||||||
|
auto piccType = rfid.PICC_GetType(rfid.uid.sak);
|
||||||
|
if (piccType != MFRC522::PICC_TYPE_MIFARE_MINI &&
|
||||||
|
piccType != MFRC522::PICC_TYPE_MIFARE_1K &&
|
||||||
|
piccType != MFRC522::PICC_TYPE_MIFARE_4K)
|
||||||
|
{
|
||||||
|
logger.warning("Invalid Mifare tag type: %s", rfid.PICC_GetTypeName(piccType));
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void NfcAuthenticator::releaseCard()
|
||||||
|
{
|
||||||
|
rfid.PICC_HaltA();
|
||||||
|
rfid.PCD_StopCrypto1();
|
||||||
|
}
|
|
@ -0,0 +1,25 @@
|
||||||
|
#ifndef NFCAUTHENTICATOR_H
|
||||||
|
#define NFCAUTHENTICATOR_H
|
||||||
|
|
||||||
|
#include "IAuthenticator.h"
|
||||||
|
|
||||||
|
#include <MFRC522.h>
|
||||||
|
|
||||||
|
class ILogger;
|
||||||
|
|
||||||
|
class NfcAuthenticator: public IAuthenticator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
NfcAuthenticator(int nfcSlaveSelectPin, int nfcResetPin, const ILogger& logger);
|
||||||
|
virtual ~NfcAuthenticator();
|
||||||
|
virtual Key getKey();
|
||||||
|
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool initializeCard();
|
||||||
|
void releaseCard();
|
||||||
|
MFRC522 rfid;
|
||||||
|
const ILogger& logger;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // NFCAUTHENTICATOR_H
|
|
@ -0,0 +1,27 @@
|
||||||
|
#include "OneWireAuthenticator.h"
|
||||||
|
|
||||||
|
#include "ILogger.h"
|
||||||
|
#include <Arduino.h>
|
||||||
|
|
||||||
|
OneWireAuthenticator::OneWireAuthenticator(int interfacePin, const ILogger& logger):
|
||||||
|
oneWire(interfacePin),
|
||||||
|
logger(logger)
|
||||||
|
{
|
||||||
|
pinMode(interfacePin, INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
Key OneWireAuthenticator::getKey()
|
||||||
|
{
|
||||||
|
uint8_t key[ONEWIRE_KEY_SIZE];
|
||||||
|
|
||||||
|
if (!oneWire.search(key)) {
|
||||||
|
oneWire.reset_search();
|
||||||
|
return Key();
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.debug("1-Wire device detected, S/N: %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX %02hhX",
|
||||||
|
key[0], key[1], key[2], key[3], key[4], key[5], key[6], key[7]);
|
||||||
|
|
||||||
|
oneWire.reset();
|
||||||
|
return DallasIButtonKey(key);
|
||||||
|
}
|
|
@ -0,0 +1,24 @@
|
||||||
|
#ifndef ONEWIREAUTHENTICATOR_H
|
||||||
|
#define ONEWIREAUTHENTICATOR_H
|
||||||
|
|
||||||
|
#include "IAuthenticator.h"
|
||||||
|
|
||||||
|
#include <OneWire.h>
|
||||||
|
|
||||||
|
class ILogger;
|
||||||
|
|
||||||
|
class OneWireAuthenticator: public IAuthenticator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
OneWireAuthenticator(int interfacePin, const ILogger& logger);
|
||||||
|
virtual Key getKey();
|
||||||
|
private:
|
||||||
|
enum {
|
||||||
|
ONEWIRE_KEY_SIZE = 8,
|
||||||
|
};
|
||||||
|
|
||||||
|
OneWire oneWire;
|
||||||
|
const ILogger& logger;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif // ONEWIREAUTHENTICATOR_H
|
|
@ -0,0 +1,8 @@
|
||||||
|
#include "DoorLockController.h"
|
||||||
|
|
||||||
|
void setup() {}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
DoorLockController().run();
|
||||||
|
}
|
Reference in New Issue