Add RFID card scanning off a list of card numbers
This commit is contained in:
parent
506f286990
commit
a8331ab798
|
@ -6,7 +6,22 @@
|
||||||
const char* WIFI_SSID = "Protospace";
|
const char* WIFI_SSID = "Protospace";
|
||||||
const char* WIFI_PASS = "yycmakers";
|
const char* WIFI_PASS = "yycmakers";
|
||||||
char wifiMACAddr[18];
|
char wifiMACAddr[18];
|
||||||
const String API_ROUTE = String("http://tools-socket.protospace.ca/api/lockout/");
|
const String SOCKET_URL = String("http://tools-socket.protospace.ca/api/lockout/");
|
||||||
|
const String CARD_URL = String("http://tools-auth.protospace.ca/cards/");
|
||||||
|
|
||||||
|
#define CARD_BUFFER_LENGTH 14
|
||||||
|
char cardBuffer[CARD_BUFFER_LENGTH];
|
||||||
|
|
||||||
|
#define CARD_DATA_LENGTH 10
|
||||||
|
#define CARD_CHECK_LENGTH 2
|
||||||
|
typedef struct __attribute__((packed)) cardData {
|
||||||
|
char head;
|
||||||
|
char data[CARD_DATA_LENGTH];
|
||||||
|
char checksum[CARD_CHECK_LENGTH];
|
||||||
|
char tail;
|
||||||
|
} cardData_t;
|
||||||
|
|
||||||
|
String authorizedCards = String("00000C5123,00000D1234,00000C5999,00000C5998,00000C5666");
|
||||||
|
|
||||||
#define RELAY_PIN D1
|
#define RELAY_PIN D1
|
||||||
#define GREEN_BUTTON_PIN D3
|
#define GREEN_BUTTON_PIN D3
|
||||||
|
@ -23,8 +38,10 @@ const String API_ROUTE = String("http://tools-socket.protospace.ca/api/lockout/"
|
||||||
|
|
||||||
#define LOGGING true
|
#define LOGGING true
|
||||||
|
|
||||||
#define DELAY_TIME 10
|
#define ONE_SECOND 1000
|
||||||
#define COMM_IDLE_TIME 500 / DELAY_TIME
|
#define DELAY_TIME ONE_SECOND / 100
|
||||||
|
#define COMM_LOCK_IDLE_TIME ONE_SECOND / 2
|
||||||
|
#define COMM_CARD_IDLE_TIME ONE_SECOND * 60 * 5
|
||||||
|
|
||||||
enum wifiStates
|
enum wifiStates
|
||||||
{
|
{
|
||||||
|
@ -38,7 +55,7 @@ enum lockStates
|
||||||
LOCK_OFF,
|
LOCK_OFF,
|
||||||
LOCK_PREARM,
|
LOCK_PREARM,
|
||||||
LOCK_ARMED,
|
LOCK_ARMED,
|
||||||
LOCK_ON_PRESSED,
|
LOCK_ON_PRESSED, // to wait until button is released
|
||||||
LOCK_ON,
|
LOCK_ON,
|
||||||
} lockState = LOCK_OFF;
|
} lockState = LOCK_OFF;
|
||||||
|
|
||||||
|
@ -46,12 +63,13 @@ enum commStates
|
||||||
{
|
{
|
||||||
COMM_INIT,
|
COMM_INIT,
|
||||||
COMM_IDLE,
|
COMM_IDLE,
|
||||||
COMM_SEND,
|
COMM_GET_LOCK,
|
||||||
|
COMM_GET_CARD,
|
||||||
} commState = COMM_INIT;
|
} commState = COMM_INIT;
|
||||||
|
|
||||||
void setup()
|
void setup()
|
||||||
{
|
{
|
||||||
if (LOGGING) Serial.begin(115200);
|
Serial.begin(9600);
|
||||||
if (LOGGING) Serial.println("[INFO] Serial started.");
|
if (LOGGING) Serial.println("[INFO] Serial started.");
|
||||||
|
|
||||||
pinMode(RELAY_PIN, OUTPUT);
|
pinMode(RELAY_PIN, OUTPUT);
|
||||||
|
@ -67,14 +85,88 @@ void loop()
|
||||||
processLockState();
|
processLockState();
|
||||||
processCommState();
|
processCommState();
|
||||||
|
|
||||||
|
if (Serial.available() >= CARD_BUFFER_LENGTH) {
|
||||||
|
uint8_t bufPos = 0;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
char readChar = Serial.read();
|
||||||
|
|
||||||
|
if (readChar == -1) {
|
||||||
|
break;
|
||||||
|
} else if (readChar == 0x2) {
|
||||||
|
bufPos = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bufPos >= CARD_BUFFER_LENGTH) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
cardBuffer[bufPos++] = readChar;
|
||||||
|
|
||||||
|
if (readChar == 0x3 && bufPos == CARD_BUFFER_LENGTH) {
|
||||||
|
checkCard();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
delay(DELAY_TIME);
|
delay(DELAY_TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int8_t charToNum(char input) {
|
||||||
|
return String("0123456789ABCDEF").indexOf(input);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool checksum(cardData_t *cardData) {
|
||||||
|
// checksum is each hex data byte xord'd together.
|
||||||
|
// each char is a hex nibble, so we have to work in pairs.
|
||||||
|
|
||||||
|
int8_t even = 0, odd = 0;
|
||||||
|
|
||||||
|
for (int i = 0; i < CARD_DATA_LENGTH; i++) {
|
||||||
|
int8_t num = charToNum(cardData->data[i]);
|
||||||
|
|
||||||
|
if (num == -1) return false;
|
||||||
|
if (i % 2 == 0) even ^= num;
|
||||||
|
if (i % 2 == 1) odd ^= num;
|
||||||
|
}
|
||||||
|
|
||||||
|
int8_t checksum_even = charToNum(cardData->checksum[0]);
|
||||||
|
int8_t checksum_odd = charToNum(cardData->checksum[1]);
|
||||||
|
|
||||||
|
if (even == checksum_even && odd == checksum_odd) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkCard() {
|
||||||
|
cardData_t *cardData = (cardData_t *) cardBuffer;
|
||||||
|
|
||||||
|
if (cardData->head == 0x2 && cardData->tail == 0x3 && checksum(cardData)) {
|
||||||
|
String cardStr = String();
|
||||||
|
|
||||||
|
for (int i = 0; i < CARD_DATA_LENGTH; i++)
|
||||||
|
cardStr += cardData->data[i];
|
||||||
|
|
||||||
|
if (LOGGING) Serial.println("[INFO] Good scan from card: " + cardStr);
|
||||||
|
|
||||||
|
if (authorizedCards.indexOf(cardStr) >= 0) {
|
||||||
|
if (LOGGING) Serial.println("[INFO] Card is authorized on machine.");
|
||||||
|
if (lockState == LOCK_OFF) {
|
||||||
|
lockState = LOCK_PREARM;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (LOGGING) Serial.println("[INFO] Card not authorized or machine.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void processWifiState()
|
void processWifiState()
|
||||||
{
|
{
|
||||||
switch(wifiState) {
|
switch(wifiState) {
|
||||||
case WIFI_DISCONNECTED:
|
case WIFI_DISCONNECTED:
|
||||||
lockState = LOCK_OFF;
|
|
||||||
commState = COMM_INIT;
|
commState = COMM_INIT;
|
||||||
|
|
||||||
if (LOGGING) Serial.println("[INFO] Wifi is disconnected. Attempting to connect...");
|
if (LOGGING) Serial.println("[INFO] Wifi is disconnected. Attempting to connect...");
|
||||||
|
@ -83,7 +175,6 @@ void processWifiState()
|
||||||
wifiState = WIFI_CONNECTING;
|
wifiState = WIFI_CONNECTING;
|
||||||
break;
|
break;
|
||||||
case WIFI_CONNECTING:
|
case WIFI_CONNECTING:
|
||||||
lockState = LOCK_OFF;
|
|
||||||
commState = COMM_INIT;
|
commState = COMM_INIT;
|
||||||
|
|
||||||
if (WiFi.status() == WL_CONNECTED) {
|
if (WiFi.status() == WL_CONNECTED) {
|
||||||
|
@ -148,7 +239,7 @@ void processLockState()
|
||||||
|
|
||||||
if (redButton()) {
|
if (redButton()) {
|
||||||
if (LOGGING) Serial.println("[INFO] Unarming interlock.");
|
if (LOGGING) Serial.println("[INFO] Unarming interlock.");
|
||||||
lockState = LOCK_OFF_PRESSED;
|
lockState = LOCK_OFF;
|
||||||
} else if (greenButton()) {
|
} else if (greenButton()) {
|
||||||
if (LOGGING) Serial.println("[INFO] On button pressed.");
|
if (LOGGING) Serial.println("[INFO] On button pressed.");
|
||||||
lockState = LOCK_ON_PRESSED;
|
lockState = LOCK_ON_PRESSED;
|
||||||
|
@ -157,7 +248,7 @@ void processLockState()
|
||||||
case LOCK_ON_PRESSED:
|
case LOCK_ON_PRESSED:
|
||||||
if (redButton()) {
|
if (redButton()) {
|
||||||
if (LOGGING) Serial.println("[ERROR] Off button pressed, aborting.");
|
if (LOGGING) Serial.println("[ERROR] Off button pressed, aborting.");
|
||||||
lockState = LOCK_OFF_PRESSED;
|
lockState = LOCK_OFF;
|
||||||
} else if (!greenButton()) {
|
} else if (!greenButton()) {
|
||||||
if (LOGGING) Serial.println("[INFO] Turning machine on.");
|
if (LOGGING) Serial.println("[INFO] Turning machine on.");
|
||||||
lockState = LOCK_ON;
|
lockState = LOCK_ON;
|
||||||
|
@ -182,20 +273,20 @@ void processLockState()
|
||||||
}
|
}
|
||||||
|
|
||||||
// JSON functions to prevent memory leaking
|
// JSON functions to prevent memory leaking
|
||||||
String serializeJson(int lockState) {
|
String serializeLockJson(uint8_t lockState) {
|
||||||
// Generated with: https://arduinojson.org/assistant/
|
// Generated with: https://arduinojson.org/assistant/
|
||||||
const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50;
|
const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50;
|
||||||
DynamicJsonBuffer jsonBuffer(bufferSize);
|
DynamicJsonBuffer jsonBuffer(bufferSize);
|
||||||
|
|
||||||
JsonObject& root = jsonBuffer.createObject();
|
JsonObject& root = jsonBuffer.createObject();
|
||||||
root["lockState"] = (int) lockState;
|
root["lockState"] = (uint8_t) lockState;
|
||||||
String postData = String();
|
String postData = String();
|
||||||
root.printTo(postData);
|
root.printTo(postData);
|
||||||
|
|
||||||
return postData;
|
return postData;
|
||||||
}
|
}
|
||||||
|
|
||||||
String deserializeJson(String input) {
|
String deserializeLockJson(String input) {
|
||||||
// Generated with: https://arduinojson.org/assistant/
|
// Generated with: https://arduinojson.org/assistant/
|
||||||
const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50;
|
const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50;
|
||||||
DynamicJsonBuffer jsonBuffer(bufferSize);
|
DynamicJsonBuffer jsonBuffer(bufferSize);
|
||||||
|
@ -208,30 +299,37 @@ String deserializeJson(String input) {
|
||||||
|
|
||||||
void processCommState()
|
void processCommState()
|
||||||
{
|
{
|
||||||
static int commIdleCount = 0;
|
static uint16_t commLockIdleCount = 0;
|
||||||
|
static uint16_t commCardIdleCount = 0;
|
||||||
|
|
||||||
switch (commState) {
|
switch (commState) {
|
||||||
case COMM_INIT:
|
case COMM_INIT:
|
||||||
commIdleCount = 0;
|
commLockIdleCount = 0;
|
||||||
|
commCardIdleCount = 0;
|
||||||
|
|
||||||
commState = COMM_IDLE;
|
commState = COMM_IDLE;
|
||||||
break;
|
break;
|
||||||
case COMM_IDLE:
|
case COMM_IDLE:
|
||||||
commIdleCount++;
|
commLockIdleCount++;
|
||||||
if (commIdleCount >= COMM_IDLE_TIME) {
|
commCardIdleCount++;
|
||||||
commState = COMM_SEND;
|
|
||||||
|
if (commLockIdleCount >= COMM_LOCK_IDLE_TIME / DELAY_TIME) {
|
||||||
|
commState = COMM_GET_LOCK;
|
||||||
|
} else if (commCardIdleCount >= COMM_CARD_IDLE_TIME / DELAY_TIME) {
|
||||||
|
commState = COMM_GET_CARD;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case COMM_SEND:
|
case COMM_GET_LOCK:
|
||||||
if (LOGGING) Serial.println("[INFO] HTTP begin.");
|
if (LOGGING) Serial.println("[INFO] Lock state HTTP begin.");
|
||||||
HTTPClient http;
|
HTTPClient http;
|
||||||
//http.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS
|
//http.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS
|
||||||
http.begin(API_ROUTE + wifiMACAddr);
|
http.begin(SOCKET_URL + wifiMACAddr);
|
||||||
http.addHeader("Content-Type", "application/json");
|
http.addHeader("Content-Type", "application/json");
|
||||||
|
|
||||||
if (LOGGING) Serial.print("[INFO] HTTP POST: ");
|
if (LOGGING) Serial.print("[INFO] HTTP POST: ");
|
||||||
String postData = serializeJson(lockState);
|
String postData = serializeLockJson(lockState);
|
||||||
if (LOGGING) Serial.println(postData);
|
if (LOGGING) Serial.println(postData);
|
||||||
int httpCode = http.POST(postData);
|
uint16_t httpCode = http.POST(postData);
|
||||||
|
|
||||||
if (httpCode > 0) {
|
if (httpCode > 0) {
|
||||||
if (LOGGING) Serial.printf("[INFO] POST success, code: %d\n", httpCode);
|
if (LOGGING) Serial.printf("[INFO] POST success, code: %d\n", httpCode);
|
||||||
|
@ -240,10 +338,10 @@ void processCommState()
|
||||||
if (LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
|
if (LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
|
||||||
String payload = http.getString();
|
String payload = http.getString();
|
||||||
if (LOGGING) Serial.println(payload);
|
if (LOGGING) Serial.println(payload);
|
||||||
String action = deserializeJson(payload);
|
String action = deserializeLockJson(payload);
|
||||||
|
|
||||||
if (action == "arm" && lockState == LOCK_OFF) {
|
if (action == "arm" && lockState == LOCK_OFF) {
|
||||||
lockState = LOCK_PREARMED;
|
lockState = LOCK_PREARM;
|
||||||
} else if (action == "disarm") {
|
} else if (action == "disarm") {
|
||||||
lockState = LOCK_OFF;
|
lockState = LOCK_OFF;
|
||||||
}
|
}
|
||||||
|
@ -256,7 +354,9 @@ void processCommState()
|
||||||
if (LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", http.errorToString(httpCode).c_str());
|
if (LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", http.errorToString(httpCode).c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
commState = COMM_INIT;
|
commLockIdleCount = 0;
|
||||||
|
|
||||||
|
commState = COMM_IDLE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user