This is not a one-to-one translation of the code, but should illustrate what I’m after
struct STATES {
const char text[16]; // verbal description of state
const int value; // numeric value for that state
} state[] =
{ { "shut" , 0 }
, { "locked" , 0 }
, { "closed" , 0 }
, { "unlocked", 1 }
, { "open" , 2 }
};
const int numStates = sizeof(state) / sizeof(state[0]);
struct OBJECTS {
const char text[32]; // verbal description of the object
int state; // current state of that object
} object[] =
{ { "Office window" , 0 }
, { "Bathroom window", 0 }
, { "Bathroom door" , 0 }
, { "Sliding door" , 0 }
, { "Stores door" , 0 }
, { "Main door" , 0 }
};
const int numObjects = sizeof(object) / sizeof(object[0]);
void handler(const char* event, const char* data) {
int s, o;
for (int s = 0; s < numStates; s++) // find match between data state description
if (strstr(data, state[s].text)) break; // if found stop search
if (s >= numStates) s = -1; // no valid state found in string
for (int o = 0; o < numObjects; o++) // find match between data and object name
if (strstr(data, object[o].text)) break; // if found stop search
if (o >= numObjects) o = -1; // no valid object found in string
if (o >= 0 && s >= 0)
object[o].state = state[o].value; // set the current state of object accordingly
else
Serial.printlnf("'%s' is errors: %s%s", data, (o < 0) ? "unkonwn Object " : "", (s < 0) ? "unknown State " : "");
}
With that kind of logic, you can add states and objects just to the arrays without ever having to revisit the functional code. You also reduce the risk of copy/paste errors, where you just fail alter that one of all these very similar looking code blocks - and these are hell to find when your code just doesn’t behave as expected, since you read over it time and time again as everything looks just too similar.
With some planing ahead and minimal restructure of your variable set, you can save yourself a lot of hassle typing, debugging and extending your code in future.