From 4a888d23a59a281d36a637197d7c343c26172d93 Mon Sep 17 00:00:00 2001 From: Kyle Isom Date: Sat, 7 Oct 2023 16:25:17 -0700 Subject: [PATCH] Working on command line processing. --- include/Commander.h | 12 +++ include/Config.h | 4 +- include/Mode.h | 11 +++ src/Commander.cc | 179 ++++++++++++++++++++++++++++++++++++++++++++ src/main.cc | 15 +++- 5 files changed, 217 insertions(+), 4 deletions(-) create mode 100644 include/Commander.h create mode 100644 include/Mode.h create mode 100644 src/Commander.cc diff --git a/include/Commander.h b/include/Commander.h new file mode 100644 index 0000000..5f6f078 --- /dev/null +++ b/include/Commander.h @@ -0,0 +1,12 @@ +#ifndef KIMODEM_COMMANDER_H +#define KIMODEM_COMMANDER_H + +#include "Mode.h" + + +#define MAX_COMMAND_LENGTH 80 + + +void CommandMode(); + +#endif \ No newline at end of file diff --git a/include/Config.h b/include/Config.h index ae4b6e9..44d2896 100644 --- a/include/Config.h +++ b/include/Config.h @@ -1,5 +1,5 @@ -#ifndef KIMODEM_PREFS_H -#define KIMODEM_PREFS_H +#ifndef KIMODEM_CONFIG_H +#define KIMODEM_CONFIG_H namespace Config { diff --git a/include/Mode.h b/include/Mode.h new file mode 100644 index 0000000..7f642fa --- /dev/null +++ b/include/Mode.h @@ -0,0 +1,11 @@ +#ifndef KIMODEM_MODE_H +#define KIMODEM_MODE_H + + +static struct Mode { + bool (*Process)(); + bool (*Update)(); +} *currentMode(nullptr); + + +#endif \ No newline at end of file diff --git a/src/Commander.cc b/src/Commander.cc new file mode 100644 index 0000000..2eba6d6 --- /dev/null +++ b/src/Commander.cc @@ -0,0 +1,179 @@ +#include +#include + +#include "Commander.h" +#include "Display.h" +#include "Mode.h" +#include "WiFi.h" + + +void resetATCommand(); + +static const char invalidATCommand[] = "INVALID AT COMMAND"; + + +static struct { + char line[MAX_COMMAND_LENGTH]; + uint8_t index; + uint8_t newLine; +} atCommand; + + +void +resetATCommand() +{ + memset(atCommand.line, 0, MAX_COMMAND_LENGTH); + atCommand.newLine = 0; + atCommand.index = 0; + Serial.print("> "); + Serial.flush(); +} + + +static bool +showConnectionState() +{ + Display::Print("802.11 "); + switch (WiFi.status()) { + case WL_CONNECT_FAILED: + Display::Println("CONN FAIL"); + break; + case WL_CONNECTED: + Display::Println("CONNECTED"); + return true; + case WL_CONNECTION_LOST: + Display::Println("CONN LOST"); + break; + case WL_DISCONNECTED: + Display::Println("DISCON"); + break; + case WL_IDLE_STATUS: + Display::Println("IDLE"); + break; + case WL_NO_SSID_AVAIL: + Display::Println("SSID UNAVAIL"); + break; + case WL_SCAN_COMPLETED: + Display::Println("SCAN COMPLETE"); + break; + default: + Display::Println("UNK STATE"); + } + + return false; +} + +static bool +commanderConnect(const char *line, size_t length) +{ + if (length == 0) { + if (showConnectionState()) { + Display::Print(" SSID: "); + Display::Println(WiFi.SSID().c_str()); + + Display::Print(" IP: "); + Display::Println(WiFi.localIP().toString().c_str()); + + Display::Print(" RSSI: "); + Display::Println(String(WiFi.RSSI()).c_str()); + } + + return true; + } + + return false; +} + + +bool +commanderProcess() +{ + static char line[MAX_COMMAND_LENGTH]; + size_t length; + + // commanderProcess tracks a second copy of a line buffer + // because the question of "when should we reset the AT + // command line buffer?" is pretty difficult to answer without + // overcomplicating the code. So, at the expense of a few + // (or MAX_COMMAND_LINE) bytes, it's easier to keep a static + // buffer that is reset on every call and reset the AT + // command buffer on every call. + length = strnlen(atCommand.line, MAX_COMMAND_LENGTH); + memset(line, 0, MAX_COMMAND_LENGTH); + memcpy(line, atCommand.line, length); + resetATCommand(); + + if (length < 2) { + Serial.println(invalidATCommand); + return false; + } + + if ((line[0] != 'A') && (line[1] != 'T')) { + Serial.println(invalidATCommand); + return false; + } + + switch (line[2]) { + case 'C': + return commanderConnect(line+3, length-3); + default: + Serial.print("UNKNOWN COMMAND "); + Serial.println(line); + return false; + } + + return false; +} + + +static bool +commanderUpdate() +{ + char readByte; + + if (!Serial.available()) { + return false; + } + + readByte = Serial.read(); + if (readByte == '\r') { + if (atCommand.newLine != 0) { + Serial.println(); + Serial.println(invalidATCommand); + resetATCommand(); + return false; + } + atCommand.newLine++; + } + + if (readByte == '\n') { + if (atCommand.newLine != 1) { + Serial.println(); + Serial.println(invalidATCommand); + resetATCommand(); + return false; + } + + return true; + } + + atCommand.line[atCommand.index++] = readByte; + + if (atCommand.index == MAX_COMMAND_LENGTH-1) { + return true; + } + return false; +} + + +struct Mode commander = {commanderProcess, commanderUpdate}; + + +void +CommandMode() +{ + resetATCommand(); + + delete currentMode; + currentMode = new Mode{commanderProcess, commanderUpdate}; +} diff --git a/src/main.cc b/src/main.cc index e5d8f30..5af4839 100644 --- a/src/main.cc +++ b/src/main.cc @@ -2,9 +2,11 @@ #include #include "Arena.h" +#include "Commander.h" #include "Config.h" #include "Dictionary.h" #include "Display.h" +#include "Mode.h" #include "WiFiMgr.h" #include "WiFiMeter.h" #include "homenet.h" @@ -82,10 +84,19 @@ void setup() { } Display::Println("MODEM READY"); + CommandMode(); + + Serial.println((uintptr_t)currentMode, HEX); + Serial.println((uintptr_t)(currentMode->Process), HEX); + Serial.println((uintptr_t)(currentMode->Update), HEX); } + void loop() { - delay(1000); - Meter::Update(); + if (millis() % 1000 == 0) Meter::Update(); + if (currentMode->Update()) { + currentMode->Process(); + } + delay(1); }