🚧 SD - Start building out json->pb parser, allow debug passthru for parsing a json string hardcoded
This commit is contained in:
parent
30bab50b8e
commit
6bb1ab2815
4 changed files with 178 additions and 33 deletions
|
|
@ -255,6 +255,9 @@ public:
|
|||
bool got_checkin_response; ///< True if a checkin response was received, False
|
||||
///< otherwise.
|
||||
|
||||
// PoC - offline mode TODO
|
||||
wippersnapper_digitalio_DigitalIOAdd _offline_msg_DigitalIOAdd;
|
||||
|
||||
private:
|
||||
void _initV2();
|
||||
|
||||
|
|
|
|||
38
src/Wippersnapper_demo_wokwi.ino.cpp
Normal file
38
src/Wippersnapper_demo_wokwi.ino.cpp
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
# 1 "/var/folders/ff/dmzflvf52tq9kzvt6g8jglxw0000gn/T/tmpxjfs2kc1"
|
||||
#include <Arduino.h>
|
||||
# 1 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo_wokwi.ino"
|
||||
# 14 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo_wokwi.ino"
|
||||
#define IO_USERNAME "brubell"
|
||||
#define IO_KEY "YOUR_AIO_KEY"
|
||||
|
||||
#define WIFI_SSID "Wokwi-GUEST"
|
||||
#define WIFI_PASS ""
|
||||
|
||||
#define WS_DEBUG
|
||||
|
||||
#define API_PIN 0
|
||||
|
||||
#include "ws_manager.h"
|
||||
|
||||
|
||||
Wippersnapper_Manager manager;
|
||||
Wippersnapper_WiFiV2 wipper(IO_USERNAME, IO_KEY, WIFI_SSID, WIFI_PASS, "io.adafruit.com", 8883);
|
||||
void setup();
|
||||
void loop();
|
||||
#line 31 "/Users/brentrubell/Documents/Arduino/libraries/Adafruit_Wippersnapper_Arduino/src/Wippersnapper_demo_wokwi.ino"
|
||||
void setup() {
|
||||
|
||||
manager.checkAPIVersion(API_PIN);
|
||||
manager.provision();
|
||||
|
||||
Serial.begin(115200);
|
||||
|
||||
Serial.println("Adafruit Wippersnapper API Manager Demo");
|
||||
Serial.print("Running Wippersnapper API Version: ");
|
||||
Serial.println(manager.getAPIVersion());
|
||||
manager.connect();
|
||||
}
|
||||
|
||||
void loop() {
|
||||
manager.run();
|
||||
}
|
||||
|
|
@ -58,13 +58,20 @@ bool ws_sdcard::parseConfigFile() {
|
|||
|
||||
JsonDocument doc;
|
||||
// TODO: Change max input length to fit an expected/max json size
|
||||
int max_input_len = 512;
|
||||
int max_input_len = 1024;
|
||||
|
||||
// Attempt to de-serialize the JSON document
|
||||
DeserializationError error;
|
||||
#ifdef ONLINE_MODE_DEBUG
|
||||
// Read the config file from the serial input buffer
|
||||
error = deserializeJson(doc, _serialInput.c_str(), max_input_len);
|
||||
if (!_use_test_data) {
|
||||
// Read the config file from the serial input buffer
|
||||
WS_DEBUG_PRINTLN("Reading JSON config file...");
|
||||
error = deserializeJson(doc, _serialInput.c_str(), max_input_len);
|
||||
} else {
|
||||
// Read the config file from the test JSON string
|
||||
WS_DEBUG_PRINTLN("Reading test JSON data...");
|
||||
error = deserializeJson(doc, json_test_data, max_input_len);
|
||||
}
|
||||
#else
|
||||
// Read the config file from the SD card
|
||||
WS_DEBUG_PRINTLN("Reading config file...");
|
||||
|
|
@ -76,22 +83,83 @@ bool ws_sdcard::parseConfigFile() {
|
|||
// print the error because it is not possible to continue running in offline
|
||||
// mode without a valid config file
|
||||
if (error) {
|
||||
WS_DEBUG_PRINTLN("deserializeJson() failed: " + String(error.c_str()));
|
||||
// TODO: Maybe this func should contain a bool return type for failure at
|
||||
// this point
|
||||
WS_DEBUG_PRINTLN("deserializeJson() failed, error code: " +
|
||||
String(error.c_str()));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse the "components" array
|
||||
// Parse the "components" array into a JsonObject
|
||||
JsonObject components = doc["components"][0];
|
||||
|
||||
// TODO: This is a list so we'll need to refactor the following to loop thru,
|
||||
// parse and dispatch each component individually
|
||||
|
||||
// Parse the PB API type
|
||||
const char *component_api_type =
|
||||
components["componentAPI"]; // ie: "analogio", "digitalio", etc.
|
||||
|
||||
if (component_api_type == nullptr) {
|
||||
WS_DEBUG_PRINTLN("No component API type found in JSON string!");
|
||||
return false;
|
||||
} else {
|
||||
WS_DEBUG_PRINTLN("Component API type found: " + String(component_api_type));
|
||||
}
|
||||
|
||||
// TODO- maybe a Switch case to handle the different component API types but
|
||||
// for now just a simple if-else is OK
|
||||
if (strcmp(component_api_type, "digitalio") == 0) {
|
||||
// TODO - dispatch to create digitalio component protobuf message
|
||||
// Create a new digitalio add protobuf message
|
||||
WsV2._offline_msg_DigitalIOAdd =
|
||||
wippersnapper_digitalio_DigitalIOAdd_init_default;
|
||||
|
||||
// Parse pinName
|
||||
strcpy(WsV2._offline_msg_DigitalIOAdd.pin_name, components["pinName"]);
|
||||
|
||||
// Parse direction
|
||||
const char *direction = components["direction"];
|
||||
if (strcmp(direction, "INPUT") == 0) {
|
||||
WsV2._offline_msg_DigitalIOAdd.gpio_direction =
|
||||
wippersnapper_digitalio_DigitalIODirection_DIGITAL_IO_DIRECTION_INPUT;
|
||||
} else if (strcmp(direction, "INPUT-PULLUP") == 0) {
|
||||
WsV2._offline_msg_DigitalIOAdd.gpio_direction =
|
||||
wippersnapper_digitalio_DigitalIODirection_DIGITAL_IO_DIRECTION_INPUT_PULL_UP;
|
||||
} else if (strcmp(direction, "OUTPUT") == 0) {
|
||||
WsV2._offline_msg_DigitalIOAdd.gpio_direction =
|
||||
wippersnapper_digitalio_DigitalIODirection_DIGITAL_IO_DIRECTION_OUTPUT;
|
||||
} else { // Unknown direction, bail out
|
||||
WS_DEBUG_PRINTLN("Unknown digital pin direction found: " +
|
||||
String(direction));
|
||||
return false;
|
||||
}
|
||||
|
||||
// Determine the sample mode
|
||||
bool is_timer_sample_mode = false;
|
||||
const char *sample_mode = components["sampleMode"];
|
||||
if (strcmp(sample_mode, "TIMER") == 0)
|
||||
is_timer_sample_mode = true;
|
||||
|
||||
if (is_timer_sample_mode) {
|
||||
// If we're sampling periodically, parse the period
|
||||
WsV2._offline_msg_DigitalIOAdd.period = components["timer"];
|
||||
// and set the sample mode
|
||||
WsV2._offline_msg_DigitalIOAdd.sample_mode =
|
||||
wippersnapper_digitalio_DigitalIOSampleMode_DIGITAL_IO_SAMPLE_MODE_TIMER;
|
||||
} else {
|
||||
// set the sample mode for event
|
||||
WsV2._offline_msg_DigitalIOAdd.sample_mode =
|
||||
wippersnapper_digitalio_DigitalIOSampleMode_DIGITAL_IO_SAMPLE_MODE_EVENT;
|
||||
}
|
||||
|
||||
// Print out the contents of the DigitalIOADD message
|
||||
WS_DEBUG_PRINTLN("DigitalIOAdd message:");
|
||||
WS_DEBUG_PRINTLN("Pin Name: " +
|
||||
String(WsV2._offline_msg_DigitalIOAdd.pin_name));
|
||||
WS_DEBUG_PRINTLN("Direction: " + String(direction));
|
||||
WS_DEBUG_PRINTLN("Sample Mode: " + String(sample_mode));
|
||||
WS_DEBUG_PRINTLN("Period: " +
|
||||
String(WsV2._offline_msg_DigitalIOAdd.period));
|
||||
return true;
|
||||
} else if (strcmp(component_api_type, "analogio") == 0) {
|
||||
// TODO - dispatch to create analogio component protobuf message
|
||||
} else {
|
||||
|
|
@ -107,39 +175,72 @@ bool ws_sdcard::parseConfigFile() {
|
|||
// Returns true if input points to a valid JSON string
|
||||
bool ws_sdcard::validateJson(const char *input) {
|
||||
JsonDocument doc, filter;
|
||||
return deserializeJson(doc, input, DeserializationOption::Filter(filter)) ==
|
||||
DeserializationError::Ok;
|
||||
}
|
||||
|
||||
// Note: using this for VALID json:
|
||||
// {"temperature": 22.5, "humidity": 60}
|
||||
// Note: using this for INVALID json:
|
||||
// {"temperature": 22.5, "humidity": 60,
|
||||
DeserializationError error =
|
||||
deserializeJson(doc, input, DeserializationOption::Filter(filter));
|
||||
WS_DEBUG_PRINTLN("Error: " + String(error.c_str()));
|
||||
return error == DeserializationError::Ok;
|
||||
// return deserializeJson(doc, input, DeserializationOption::Filter(filter))
|
||||
// ==
|
||||
// DeserializationError::Ok;
|
||||
}
|
||||
|
||||
// Waits for incoming config file and parses it
|
||||
// TODO: Split out parsing into parseConfigFile() and just read here
|
||||
bool ws_sdcard::waitForSerialConfig() {
|
||||
_serialInput = ""; // Clear the serial input buffer
|
||||
WS_DEBUG_PRINTLN("Waiting for incoming JSON string...");
|
||||
|
||||
// Wait for incoming serial data
|
||||
while (true) {
|
||||
// Check if there is data available to read
|
||||
if (Serial.available() > 0) {
|
||||
// Read and append to _serialInput
|
||||
char c = Serial.read();
|
||||
_serialInput += c;
|
||||
// Check for EoL or end of JSON string
|
||||
if (c == '\n' || c == '}') {
|
||||
break;
|
||||
// We provide three ways to use this function:
|
||||
// 1. Use a SD card with a JSON config file
|
||||
// 2. Provide a JSON string via the hardware's serial input
|
||||
// 3. Use a test JSON string - for debugging purposes ONLY
|
||||
json_test_data =
|
||||
"{\"components\":[{\"componentAPI\":\"analogio\",\"name\":\"Analog "
|
||||
"Pin\",\"pinName\":\"A18\",\"type\":\"analog_pin\",\"mode\":\"ANALOG\","
|
||||
"\"direction\":\"INPUT\",\"sampleMode\":\"TIMER\",\"analogReadMode\":"
|
||||
"\"PIN_VALUE\",\"period\":30,\"isPin\":true}]}\\n\r\n";
|
||||
_use_test_data = true;
|
||||
|
||||
_serialInput = ""; // Clear the serial input buffer
|
||||
if (!_use_test_data) {
|
||||
WS_DEBUG_PRINTLN("Waiting for incoming JSON string...");
|
||||
while (true) {
|
||||
// Check if there is data available to read
|
||||
if (Serial.available() > 0) {
|
||||
// Read and append to _serialInput
|
||||
char c = Serial.read();
|
||||
_serialInput += c;
|
||||
// Check for EoL or end of JSON string
|
||||
// Read the TODO/Note below!
|
||||
// NOTE: This is checking for a \n delimeter from the serial
|
||||
// and that wont be present in non-serial application
|
||||
// Parse JSON normally if not using serial and inspect this condition!
|
||||
if (c == '\n') {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Print out the received JSON string
|
||||
WS_DEBUG_PRINT("[Debug] JSON string received: ");
|
||||
if (_use_test_data) {
|
||||
WS_DEBUG_PRINTLN("[from json test data]");
|
||||
WS_DEBUG_PRINTLN(json_test_data);
|
||||
} else {
|
||||
WS_DEBUG_PRINTLN(_serialInput);
|
||||
}
|
||||
|
||||
// Attempt to validate the string as JSON
|
||||
if (!validateJson(_serialInput.c_str())) {
|
||||
WS_DEBUG_PRINTLN("Invalid JSON string received!");
|
||||
return false;
|
||||
if (!_use_test_data) {
|
||||
if (!validateJson(_serialInput.c_str())) {
|
||||
WS_DEBUG_PRINTLN("Invalid JSON string received!");
|
||||
return false;
|
||||
}
|
||||
} else {
|
||||
if (!validateJson(json_test_data)) {
|
||||
WS_DEBUG_PRINTLN("Invalid JSON string received!");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
WS_DEBUG_PRINTLN("Valid JSON string received!");
|
||||
|
|
|
|||
|
|
@ -38,10 +38,13 @@ public:
|
|||
bool validateJson(const char *input);
|
||||
|
||||
private:
|
||||
bool _is_sd_card_inserted; ///< True if an SD card is inserted, False
|
||||
///< otherwise.
|
||||
SdFat _sd; ///< SD object from Adafruit SDFat library
|
||||
String _serialInput; ///< Serial input buffer
|
||||
bool _is_sd_card_inserted; ///< True if an SD card is inserted, False
|
||||
///< otherwise.
|
||||
SdFat _sd; ///< SD object from Adafruit SDFat library
|
||||
String _serialInput; ///< Serial input buffer
|
||||
const char *json_test_data; ///< Json test data
|
||||
bool _use_test_data; ///< True if sample data is being used to test, instead
|
||||
///< of serial input, False otherwise.
|
||||
};
|
||||
extern Wippersnapper_V2 WsV2;
|
||||
#endif // WS_SDCARD_H
|
||||
Loading…
Reference in a new issue