#include "utils.h" bool greenButton() { return digitalRead(GREEN_BUTTON_PIN) == BUTTON_CLOSED; } bool redButton() { return digitalRead(RED_BUTTON_PIN) == BUTTON_CLOSED; } void relayOn() { digitalWrite(RELAY_PIN, RELAY_CLOSED); } void relayOff() { digitalWrite(RELAY_PIN, RELAY_OPEN); } void greenLEDOn() { digitalWrite(GREEN_LED_PIN, LED_PIN_ON); } void greenLEDOff() { digitalWrite(GREEN_LED_PIN, LED_PIN_OFF); } void redLEDOn() { digitalWrite(RED_LED_PIN, LED_PIN_ON); } void redLEDOff() { digitalWrite(RED_LED_PIN, LED_PIN_OFF); } int8_t charToNum(char input) { return String("0123456789ABCDEF").indexOf(input); } bool checksum(struct cardData *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 (int8_t 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() { struct cardData *cardData = (struct cardData *) cardBuffer; if (cardData->head == CARD_HEAD_BYTE && cardData->tail == CARD_TAIL_BYTE && checksum(cardData)) { String cardStr = String(); String authorizedCards = String(); for (uint8_t i = 0; i < CARD_DATA_LENGTH; i++) { cardStr += cardData->data[i]; } for (uint16_t i = 0; i < EEPROM_SIZE; i++) { char tmp = EEPROM.read(i); authorizedCards += tmp; if (tmp == EEPROM_END_MARKER) break; } if (SERIAL_LOGGING) Serial.println("[INFO] Good scan from card: " + cardStr); logEvent(LOG_CARD_GOOD_READ, cardStr.c_str(), cardStr.length()); if (authorizedCards.indexOf(cardStr) >= 0) { if (SERIAL_LOGGING) Serial.println("[INFO] Card is authorized on machine."); if (lockState == LOCK_OFF) { lockState = LOCK_PREARM; } logEvent(LOG_CARD_ACCEPTED, cardStr.c_str(), cardStr.length()); } else { if (SERIAL_LOGGING) Serial.println("[INFO] Card not authorized on machine."); LEDState = LED_ERROR; logEvent(LOG_CARD_DENIED, cardStr.c_str(), cardStr.length()); } } } // JSON functions to prevent memory leaking see: // https://arduinojson.org/v5/faq/i-found-a-memory-leak-in-the-library/ String serializeLockJson(uint8_t lockState) { // Generated with: https://arduinojson.org/assistant/ const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50; StaticJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.createObject(); root["lockState"] = (uint8_t) lockState; String postData = String(); root.printTo(postData); return postData; } String deserializeLockJson(String input) { // Generated with: https://arduinojson.org/assistant/ const size_t bufferSize = JSON_OBJECT_SIZE(1) + 50; StaticJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.parseObject(input); String action = root["action"]; return action; } String serializeLog() { size_t logLengthBytes = logPosition * sizeof(struct logData); return "{\"log\": \"" + base64::encode((uint8_t *) eventLog, logLengthBytes, false) + "\"}"; } void deserializeInfoJson(String input, uint8_t *processed, uint32_t *unixTime, String *version) { // Generated with: https://arduinojson.org/assistant/ const size_t bufferSize = JSON_OBJECT_SIZE(3) + 70; StaticJsonBuffer jsonBuffer; JsonObject& root = jsonBuffer.parseObject(input); *processed = root["processed"]; *unixTime = root["unixTime"]; *version = root["version"].as(); }