I'm working with an arduino UNO. I would like to be able to send it set and get commands over serial and have it update class data class members accordingly by key value pair. I spoke to users in the cpp room, and they suggested I try using map to map every key to value.
command structure
command:key:value
ex. set:key1:20
ex. get:key2
I created a class called Uno, assigned all my keys to private data members, and defined set and get functions. However, I am experiencing unintended behavior.
Unintended behavior
The set function ends up setting key1 and key2 to the same value, and the get function returns a random integer value that wasn't assigned.
#include <ArduinoSTL.h>
#include <string.h>
#include <map>
class Uno{
//private
int key1;
int key2;
std::map<String, int Uno::*> keys;
public:
//Constructor
Uno(){
key1 = 0;
key2 = 0;
keys["key1"] = &Uno::key1;
keys["key2"] = &Uno::key2;
}
bool setKey(String key, int value){
if (keys.count(key)) {
this->*keys[key] = value;
return true;
}
return false;
}
int getKey(String key){
if (keys.count(key)) {
return this->*keys[key];
}
}
};
String inputString = ""; // a String to hold incoming data
bool stringComplete = false; // whether the string is complete
bool scan = false; // whether a scan is in progress
Uno myMS; // global declaration of Mass Spec Class
void setup() {
// initialize serial:
Serial.begin(9600);
// reserve 250 bytes for the inputString:
inputString.reserve(250);
}
void loop() {
if (stringComplete) {
t(inputString); // tokenize and process string
//RESET STRING
inputString = "";
stringComplete = false;
}
}
void serialEvent() {
while (Serial.available()) {
// get the new byte:
char inChar = (char)Serial.read();
// add it to the inputString:
inputString += inChar;
// if the incoming character is a newline, set a flag so the main loop can
// do something about it:
if (inChar == '\n') {
stringComplete = true;
}
}
}
void t(String inputString) {
//get command
String command = getValue(inputString, ':', 0);
if(command == "set"){
// get key, get value
String key = getValue(inputString, ':', 1);
int value = (getValue(inputString, ':', 2)).toInt();
Serial.println(myMS.setKey(key,value));
}
else if(command == "get"){
String key = getValue(inputString, ':', 1);
int value = myMS.getKey(key);
Serial.println(value);
}
else if(command == "stop"){
scan = false;
}
else if(command == "scan"){
scan = true;
while(scan){
// Serial.println(myMS.scan());
}
}
else{
Serial.println("not recognized");
}
}
String getValue(String data, char separator, int index)
{
int found = 0;
int strIndex[] = {0, -1};
int maxIndex = data.length()-1;
for(int i=0; i<=maxIndex && found<=index; i++){
if(data.charAt(i)==separator || i==maxIndex){
found++;
strIndex[0] = strIndex[1]+1;
strIndex[1] = (i == maxIndex) ? i+1 : i;
}
}
return found>index ? data.substring(strIndex[0], strIndex[1]) : "";
}
EDIT: Here is a REPL IT working demo of concept provided by nwp. https://repl.it/repls/AntiqueProductiveMineral
Sample output
set:key1:10 ===> 1 (GOOD)
get:key1 ===> 32512