pslockout/firmware/comm.cpp

231 lines
7.0 KiB
C++

#include "comm.h"
//TODO: abstract http functions
void postState()
{
// Don't log more than one error at a time
static bool logErrors = true;
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(SOCKET_URL + wifiMACAddr);
lockHTTP.addHeader("Content-Type", "application/json");
if (SERIAL_LOGGING) Serial.println("[INFO] Lock state HTTP begin.");
if (SERIAL_LOGGING) Serial.print("[INFO] HTTP POST: ");
String postData = serializeLockJson(lockState);
if (SERIAL_LOGGING) Serial.println(postData);
int16_t lockHTTPCode = lockHTTP.POST(postData);
String lockHTTPCodeStr = String(lockHTTPCode);
if (lockHTTPCode > 0) {
if (SERIAL_LOGGING) Serial.printf("[INFO] POST success, code: %d\n", lockHTTPCode);
if (lockHTTPCode == HTTP_CODE_OK) {
logErrors = true;
if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
String lockPayload = lockHTTP.getString();
if (SERIAL_LOGGING) Serial.println(lockPayload);
String action = deserializeLockJson(lockPayload);
if (action == "arm" && lockState == LOCK_OFF && LEDState == LED_OFF) {
logEvent(LOG_COMM_LOCK_ARM);
lockState = LOCK_PREARM;
} else if (action == "disarm" && lockState != LOCK_ON) {
logEvent(LOG_COMM_LOCK_DISARM);
if (SERIAL_LOGGING) Serial.println("[INFO] Unarming interlock.");
logEvent(LOG_LOCK_DISARM);
lockState = LOCK_OFF;
}
if (SERIAL_LOGGING) Serial.println("[INFO] action: " + action);
} else {
if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found.");
if (logErrors) logEvent(LOG_COMM_LOCK_FAIL, lockHTTPCodeStr.c_str(), lockHTTPCodeStr.length());
logErrors = false;
}
} else {
if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", lockHTTP.errorToString(lockHTTPCode).c_str());
if (logErrors) logEvent(LOG_COMM_LOCK_FAIL, lockHTTPCodeStr.c_str(), lockHTTPCodeStr.length());
logErrors = false;
}
lockHTTP.end();
}
void getCards()
{
// Don't log more than one error at a time
static bool logErrors = true;
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(CARD_URL + wifiMACAddr + "/");
cardHTTP.addHeader("Content-Type", "application/json");
if (SERIAL_LOGGING) Serial.println("[INFO] Card state HTTP begin.");
if (SERIAL_LOGGING) Serial.println("[INFO] HTTP GET");
int16_t cardHTTPCode = cardHTTP.GET();
String cardHTTPCodeStr = String(cardHTTPCode);
if (cardHTTPCode > 0) {
if (SERIAL_LOGGING) Serial.printf("[INFO] GET success, code: %d\n", cardHTTPCode);
if (cardHTTPCode == HTTP_CODE_OK) {
logErrors = true;
if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
String cardPayload = cardHTTP.getString();
cardPayload += String(EEPROM_END_MARKER);
if (SERIAL_LOGGING) Serial.println(cardPayload);
noInterrupts(); // commit() disables interrupts, but we want an atomic EEPROM buffer write
for (int i = 0; i < cardPayload.length(); i++) {
if (i >= EEPROM_SIZE) break;
EEPROM.write(i, cardPayload.charAt(i));
}
EEPROM.commit();
interrupts();
if (SERIAL_LOGGING) Serial.println("[INFO] Finished getting card data.");
} else {
if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found.");
if (logErrors) logEvent(LOG_COMM_CARD_FAIL, cardHTTPCodeStr.c_str(), cardHTTPCodeStr.length());
logErrors = false;
}
} else {
if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", cardHTTP.errorToString(cardHTTPCode).c_str());
if (logErrors) logEvent(LOG_COMM_CARD_FAIL, cardHTTPCodeStr.c_str(), cardHTTPCodeStr.length());
logErrors = false;
}
cardHTTP.end();
}
void postInfolog()
{
// Don't log more than one error at a time
static bool logErrors = true;
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(INFOLOG_URL + wifiMACAddr + "/");
infoHTTP.addHeader("Content-Type", "application/json");
if (SERIAL_LOGGING) Serial.println("[INFO] Info state HTTP begin.");
if (SERIAL_LOGGING) Serial.println("[INFO] HTTP POST.");
String postData = serializeLog();
int16_t infoHTTPCode = infoHTTP.POST(postData);
String infoHTTPCodeStr = String(infoHTTPCode);
if (infoHTTPCode > 0) {
if (SERIAL_LOGGING) Serial.printf("[INFO] POST success, code: %d\n", infoHTTPCode);
if (infoHTTPCode == HTTP_CODE_OK) {
logErrors = true;
if (SERIAL_LOGGING) Serial.print("[INFO] Resource found, parsing response: ");
String infoPayload = infoHTTP.getString();
if (SERIAL_LOGGING) Serial.println(infoPayload);
uint8_t processed;
uint32_t unixTime;
String version = String();
deserializeInfoJson(infoPayload, &processed, &unixTime, &version);
struct timeval tv = { .tv_sec = unixTime, .tv_usec = 0 };
struct timezone tz = { .tz_minuteswest = 0, .tz_dsttime = 0 };
settimeofday(&tv, &tz);
removeLogRecords(processed);
if (version != LOCKOUT_FIRMWARE_VERSION && lockState == LOCK_OFF) {
noInterrupts();
if (SERIAL_LOGGING) Serial.println("[INFO] Firmware out of date. Updating...");
WiFiClient client;
int16_t update_response = ESPhttpUpdate.update(client, UPDATE_URL + wifiMACAddr + "/");
interrupts();
if (SERIAL_LOGGING) printf("[ERROR] %s\n", ESPhttpUpdate.getLastErrorString().c_str());
String lastErrorNum = String(ESPhttpUpdate.getLastError());
logEvent(LOG_UPDATE_FAILED, lastErrorNum.c_str(), lastErrorNum.length());
}
if (SERIAL_LOGGING) Serial.print("[INFO] Set system time to: ");
if (SERIAL_LOGGING) Serial.println(unixTime);
} else {
if (SERIAL_LOGGING) Serial.println("[ERROR] Resource not found.");
if (logErrors) logEvent(LOG_COMM_INFO_FAIL, infoHTTPCodeStr.c_str(), infoHTTPCodeStr.length());
logErrors = false;
}
} else {
if (SERIAL_LOGGING) Serial.printf("[ERROR] POST failed, error: %s\n", infoHTTP.errorToString(infoHTTPCode).c_str());
if (logErrors) logEvent(LOG_COMM_INFO_FAIL, infoHTTPCodeStr.c_str(), infoHTTPCodeStr.length());
logErrors = false;
}
infoHTTP.end();
}
void processCommState()
{
static uint16_t commLockIdleCount, commCardIdleCount, commInfoIdleCount;
switch (commState) {
case COMM_INIT:
commLockIdleCount = 0;
commCardIdleCount = 0;
commInfoIdleCount = 0;
commState = COMM_IDLE;
break;
case COMM_IDLE:
commLockIdleCount++;
commCardIdleCount++;
commInfoIdleCount++;
if (commLockIdleCount >= COMM_LOCK_IDLE_TIME) {
commState = COMM_LOCK;
} else if (commCardIdleCount >= COMM_CARD_IDLE_TIME) {
commState = COMM_CARD;
} else if (commInfoIdleCount >= COMM_INFO_IDLE_TIME) {
commState = COMM_INFO;
}
break;
case COMM_LOCK:
{
postState();
commLockIdleCount = 0;
commState = COMM_IDLE;
}
break;
case COMM_CARD:
{
getCards();
commCardIdleCount = 0;
commState = COMM_IDLE;
}
break;
case COMM_INFO:
{
postInfolog();
commInfoIdleCount = 0;
commState = COMM_IDLE;
}
break;
}
}