Don't log duplicate COMM errors, remove sent log records

This commit is contained in:
Tanner Collin 2019-01-20 20:04:43 -07:00
parent 9717073507
commit 63adb9b9a3

View File

@ -23,12 +23,12 @@ char cardBuffer[CARD_BUFFER_LENGTH];
#define CARD_CHECK_LENGTH 2 #define CARD_CHECK_LENGTH 2
#define CARD_HEAD_BYTE 0x2 #define CARD_HEAD_BYTE 0x2
#define CARD_TAIL_BYTE 0x3 #define CARD_TAIL_BYTE 0x3
typedef struct __attribute__((packed)) cardData { struct __attribute__((packed)) cardData {
char head; char head;
char data[CARD_DATA_LENGTH]; char data[CARD_DATA_LENGTH];
char checksum[CARD_CHECK_LENGTH]; char checksum[CARD_CHECK_LENGTH];
char tail; char tail;
} cardData_t; };
#define RELAY_PIN D1 #define RELAY_PIN D1
#define GREEN_BUTTON_PIN D3 #define GREEN_BUTTON_PIN D3
@ -90,7 +90,8 @@ enum commStates
#define SERIAL_LOGGING true #define SERIAL_LOGGING true
#define LOG_SIZE 100 #define LOG_SIZE 90 // 100 blew up the stack
#define LOG_DATA_LENGTH CARD_DATA_LENGTH
enum eventCodes enum eventCodes
{ {
@ -98,6 +99,8 @@ enum eventCodes
LOG_INIT_COMPLETE, LOG_INIT_COMPLETE,
LOG_WIFI_CONNECTED, LOG_WIFI_CONNECTED,
LOG_WIFI_DISCONNECTED, LOG_WIFI_DISCONNECTED,
LOG_COMM_LOCK_ARM,
LOG_COMM_LOCK_DISARM,
LOG_COMM_LOCK_FAIL, LOG_COMM_LOCK_FAIL,
LOG_COMM_CARD_FAIL, LOG_COMM_CARD_FAIL,
LOG_COMM_INFO_FAIL, LOG_COMM_INFO_FAIL,
@ -105,31 +108,33 @@ enum eventCodes
LOG_LOCK_ARMED, LOG_LOCK_ARMED,
LOG_LOCK_TIMEOUT, LOG_LOCK_TIMEOUT,
LOG_LOCK_ON, LOG_LOCK_ON,
LOG_LOCK_CANCEL, LOG_LOCK_DISARM,
LOG_LOCK_ERROR, LOG_LOCK_ERROR,
LOG_CARD_GOOD_READ, LOG_CARD_GOOD_READ,
LOG_CARD_ACCEPTED, LOG_CARD_ACCEPTED,
LOG_CARD_DENIED, LOG_CARD_DENIED,
}; };
typedef struct __attribute__((packed)) logData { struct __attribute__((packed)) logData {
uint32_t unixTime; uint32_t unixTime;
uint8_t eventCode; uint8_t eventCode;
char data[CARD_DATA_LENGTH]; char data[LOG_DATA_LENGTH];
} logData_t; };
logData_t eventLog[LOG_SIZE]; struct logData eventLog[LOG_SIZE];
uint16_t logPosition = 0; uint16_t logPosition = 0;
void logEvent(uint8_t eventCode, const char *data = nullptr, size_t num = 0) void logEvent(uint8_t eventCode, const char *data = nullptr, size_t num = 0)
{ {
logData_t event; struct logData event;
noInterrupts(); noInterrupts();
event.unixTime = time(nullptr); event.unixTime = time(nullptr);
event.eventCode = eventCode; event.eventCode = eventCode;
for (uint8_t i = 0; i < CARD_DATA_LENGTH; i++) {
memset(event.data, 0, LOG_DATA_LENGTH);
for (uint8_t i = 0; i < LOG_DATA_LENGTH; i++) {
if (i >= num) break; if (i >= num) break;
event.data[i] = data[i]; event.data[i] = data[i];
} }
@ -141,6 +146,22 @@ void logEvent(uint8_t eventCode, const char *data = nullptr, size_t num = 0)
interrupts(); interrupts();
} }
void removeLogRecords(uint8_t num) {
// shift records down by num because they've been sent
if (num > logPosition) return;
noInterrupts();
for (int i = 0; i < num; i++) {
eventLog[i] = eventLog[i + num];
}
logPosition -= num;
interrupts();
}
void setup() void setup()
{ {
Serial.begin(9600); Serial.begin(9600);
@ -217,7 +238,7 @@ int8_t charToNum(char input)
return String("0123456789ABCDEF").indexOf(input); return String("0123456789ABCDEF").indexOf(input);
} }
bool checksum(cardData_t *cardData) bool checksum(struct cardData *cardData)
{ {
// checksum is each hex data byte xord'd together. // checksum is each hex data byte xord'd together.
// each char is a hex nibble, so we have to work in pairs. // each char is a hex nibble, so we have to work in pairs.
@ -244,7 +265,7 @@ bool checksum(cardData_t *cardData)
void checkCard() void checkCard()
{ {
cardData_t *cardData = (cardData_t *) cardBuffer; struct cardData *cardData = (struct cardData *) cardBuffer;
if (cardData->head == CARD_HEAD_BYTE && if (cardData->head == CARD_HEAD_BYTE &&
cardData->tail == CARD_TAIL_BYTE && cardData->tail == CARD_TAIL_BYTE &&
@ -357,7 +378,7 @@ void processLockState()
if (redButton()) { if (redButton()) {
if (SERIAL_LOGGING) Serial.println("[INFO] Unarming interlock."); if (SERIAL_LOGGING) Serial.println("[INFO] Unarming interlock.");
logEvent(LOG_LOCK_CANCEL); logEvent(LOG_LOCK_DISARM);
lockState = LOCK_OFF; lockState = LOCK_OFF;
} else if (greenButton()) { } else if (greenButton()) {
if (SERIAL_LOGGING) Serial.println("[INFO] On button pressed."); if (SERIAL_LOGGING) Serial.println("[INFO] On button pressed.");
@ -485,24 +506,29 @@ String deserializeLockJson(String input)
} }
String serializeLog() { String serializeLog() {
size_t logLengthBytes = logPosition * sizeof(logData_t); size_t logLengthBytes = logPosition * sizeof(struct logData);
return base64::encode((uint8_t *) eventLog, logLengthBytes, false); return "{\"log\": \"" + base64::encode((uint8_t *) eventLog, logLengthBytes, false) + "\"}";
} }
uint32_t deserializeInfoJson(String input) void deserializeInfoJson(String input, uint8_t *processed, uint32_t *unixTime)
{ {
// 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(2) + 50;
StaticJsonBuffer<bufferSize> jsonBuffer; StaticJsonBuffer<bufferSize> jsonBuffer;
JsonObject& root = jsonBuffer.parseObject(input); JsonObject& root = jsonBuffer.parseObject(input);
uint32_t unixTime = root["unixTime"]; *processed = root["processed"];
*unixTime = root["unixTime"];
return unixTime;
} }
//TODO: abstract http functions
void postState() void postState()
{ {
// Don't log more than one error at a time
static bool logErrors = true;
HTTPClient lockHTTP; HTTPClient lockHTTP;
//lockHTTP.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS //lockHTTP.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS
@ -521,27 +547,33 @@ void postState()
if (SERIAL_LOGGING) Serial.printf("[INFO] POST success, code: %d\n", lockHTTPCode); if (SERIAL_LOGGING) Serial.printf("[INFO] POST success, code: %d\n", lockHTTPCode);
if (lockHTTPCode == HTTP_CODE_OK) { if (lockHTTPCode == HTTP_CODE_OK) {
logErrors = true;
if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: "); if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
String lockPayload = lockHTTP.getString(); String lockPayload = lockHTTP.getString();
if (SERIAL_LOGGING) Serial.println(lockPayload); if (SERIAL_LOGGING) Serial.println(lockPayload);
String action = deserializeLockJson(lockPayload); String action = deserializeLockJson(lockPayload);
if (action == "arm" && lockState == LOCK_OFF && LEDState == LED_OFF) { if (action == "arm" && lockState == LOCK_OFF && LEDState == LED_OFF) {
logEvent(LOG_COMM_LOCK_ARM);
lockState = LOCK_PREARM; lockState = LOCK_PREARM;
} else if (action == "disarm" && lockState != LOCK_ON) { } else if (action == "disarm" && lockState != LOCK_ON) {
logEvent(LOG_COMM_LOCK_DISARM);
if (SERIAL_LOGGING) Serial.println("[INFO] Unarming interlock."); if (SERIAL_LOGGING) Serial.println("[INFO] Unarming interlock.");
logEvent(LOG_LOCK_CANCEL); logEvent(LOG_LOCK_DISARM);
lockState = LOCK_OFF; lockState = LOCK_OFF;
} }
if (SERIAL_LOGGING) Serial.println("[INFO] action: " + action); if (SERIAL_LOGGING) Serial.println("[INFO] action: " + action);
} else { } else {
if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found."); if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found.");
logEvent(LOG_COMM_LOCK_FAIL, lockHTTPCodeStr.c_str(), lockHTTPCodeStr.length()); if (logErrors) logEvent(LOG_COMM_LOCK_FAIL, lockHTTPCodeStr.c_str(), lockHTTPCodeStr.length());
logErrors = false;
} }
} else { } else {
if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", lockHTTP.errorToString(lockHTTPCode).c_str()); if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", lockHTTP.errorToString(lockHTTPCode).c_str());
logEvent(LOG_COMM_LOCK_FAIL, lockHTTPCodeStr.c_str(), lockHTTPCodeStr.length()); if (logErrors) logEvent(LOG_COMM_LOCK_FAIL, lockHTTPCodeStr.c_str(), lockHTTPCodeStr.length());
logErrors = false;
} }
lockHTTP.end(); lockHTTP.end();
@ -549,6 +581,9 @@ void postState()
void getCards() void getCards()
{ {
// Don't log more than one error at a time
static bool logErrors = true;
HTTPClient cardHTTP; HTTPClient cardHTTP;
//cardHTTP.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS //cardHTTP.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS
@ -565,6 +600,8 @@ void getCards()
if (SERIAL_LOGGING) Serial.printf("[INFO] GET success, code: %d\n", cardHTTPCode); if (SERIAL_LOGGING) Serial.printf("[INFO] GET success, code: %d\n", cardHTTPCode);
if (cardHTTPCode == HTTP_CODE_OK) { if (cardHTTPCode == HTTP_CODE_OK) {
logErrors = true;
if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: "); if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
String cardPayload = cardHTTP.getString(); String cardPayload = cardHTTP.getString();
cardPayload += String(EEPROM_END_MARKER); cardPayload += String(EEPROM_END_MARKER);
@ -581,11 +618,13 @@ void getCards()
if (SERIAL_LOGGING) Serial.println("[INFO] Finished getting card data."); if (SERIAL_LOGGING) Serial.println("[INFO] Finished getting card data.");
} else { } else {
if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found."); if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found.");
logEvent(LOG_COMM_CARD_FAIL, cardHTTPCodeStr.c_str(), cardHTTPCodeStr.length()); if (logErrors) logEvent(LOG_COMM_CARD_FAIL, cardHTTPCodeStr.c_str(), cardHTTPCodeStr.length());
logErrors = false;
} }
} else { } else {
if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", cardHTTP.errorToString(cardHTTPCode).c_str()); if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", cardHTTP.errorToString(cardHTTPCode).c_str());
logEvent(LOG_COMM_CARD_FAIL, cardHTTPCodeStr.c_str(), cardHTTPCodeStr.length()); if (logErrors) logEvent(LOG_COMM_CARD_FAIL, cardHTTPCodeStr.c_str(), cardHTTPCodeStr.length());
logErrors = false;
} }
cardHTTP.end(); cardHTTP.end();
@ -593,6 +632,9 @@ void getCards()
void postInfolog() void postInfolog()
{ {
// Don't log more than one error at a time
static bool logErrors = true;
HTTPClient infoHTTP; HTTPClient infoHTTP;
//infoHTTP.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS //infoHTTP.begin("https://url", "7a 9c f4 db 40 d3 62 5a 6e 21 bc 5c cc 66 c8 3e a1 45 59 38"); //HTTPS
@ -611,24 +653,32 @@ void postInfolog()
if (SERIAL_LOGGING) Serial.printf("[INFO] POST success, code: %d\n", infoHTTPCode); if (SERIAL_LOGGING) Serial.printf("[INFO] POST success, code: %d\n", infoHTTPCode);
if (infoHTTPCode == HTTP_CODE_OK) { if (infoHTTPCode == HTTP_CODE_OK) {
logErrors = true;
if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: "); if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
String infoPayload = infoHTTP.getString(); String infoPayload = infoHTTP.getString();
if (SERIAL_LOGGING) Serial.println(infoPayload); if (SERIAL_LOGGING) Serial.println(infoPayload);
uint32_t unixTime = deserializeInfoJson(infoPayload); uint8_t processed;
uint32_t unixTime;
deserializeInfoJson(infoPayload, &processed, &unixTime);
struct timeval tv = { .tv_sec = unixTime, .tv_usec = 0 }; struct timeval tv = { .tv_sec = unixTime, .tv_usec = 0 };
struct timezone tz = { .tz_minuteswest = 0, .tz_dsttime = 0 }; struct timezone tz = { .tz_minuteswest = 0, .tz_dsttime = 0 };
settimeofday(&tv, &tz); settimeofday(&tv, &tz);
removeLogRecords(processed);
if (SERIAL_LOGGING) Serial.print("[INFO] Set system time to: "); if (SERIAL_LOGGING) Serial.print("[INFO] Set system time to: ");
if (SERIAL_LOGGING) Serial.println(unixTime); if (SERIAL_LOGGING) Serial.println(unixTime);
} else { } else {
if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found."); if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found.");
logEvent(LOG_COMM_INFO_FAIL, infoHTTPCodeStr.c_str(), infoHTTPCodeStr.length()); if (logErrors) logEvent(LOG_COMM_INFO_FAIL, infoHTTPCodeStr.c_str(), infoHTTPCodeStr.length());
logErrors = false;
} }
} else { } else {
if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", infoHTTP.errorToString(infoHTTPCode).c_str()); if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", infoHTTP.errorToString(infoHTTPCode).c_str());
logEvent(LOG_COMM_INFO_FAIL, infoHTTPCodeStr.c_str(), infoHTTPCodeStr.length()); if (logErrors) logEvent(LOG_COMM_INFO_FAIL, infoHTTPCodeStr.c_str(), infoHTTPCodeStr.length());
logErrors = false;
} }
infoHTTP.end(); infoHTTP.end();