Hi
Maybe this has been answered several times, but I haven't been able to find an answer that helps me. I'm not very code skilled, more of a DIY enthusiast with good patience. My apologies if double posting or using the wrong forum section.
I have an MCP23017 expansion board hooked up and use MQTT to send commands turning on/off the relays connected to the MCP.
Everything is working fine - I can receive MQTT commands and turn the relays on/off and publish back a state when successful. A topic I use in my callback may look like this
Controller/MCP23017P0/command
Where the "0" between "P" and "/command" is identifying the MCP pin to get the status change and the integer I want to get my hands on.
My issue is that I would like to have a more elegant code and avoid duplicating it. Sure, I could write 16 if statements using strcmp() and have the exact same code within each section. But, that will take up a lot of space and be cumbersome to maintain when doing changes.
So, I'm thinking that extracting the int "0" (in the example above) could allow me to skip the if section and work with the extracted int and concatenating when needed.
There are 16 pins on the MCP expander, so the int I need to extract can be 0-15. Any help would be appreciated, thanks.
void setup()
{
Serial.begin(115200);
while (!Serial);
Serial.println(extract("Controller/MCP23017P0/command"));
Serial.println(extract("Controller/MCP23017P15/command"));
}
void loop()
{
}
int extract(char * data)
{
char * ptr = strtok(data, "P"); //skip to first P
ptr = strtok(NULL, "P"); //skip to second P
ptr = strtok(NULL, "/"); //get the data between P and /
return atoi(ptr);
}
int parsePin(char* cmd) {
Serial.print("cmd:"); Serial.println(cmd);
cSFP(sfCmd, cmd); // warps cmd in a SafeString
cSF(token, 20);
sfCmd.firstToken(token, '/');
sfCmd.nextToken(token, '/');
int idx = token.lastIndexOf('P'); // token should now have M....P..
token.removeBefore(idx + 1); // removes P as well
// should have pin number left
int pinNo = -1;
if (!token.toInt(pinNo)) {
Serial.print(F(" ")); Serial.print(token); Serial.println(F(" is not a number"));
return -1;
} // else
sfCmd.nextToken(token, '/'); // make sure this is a command
if (token != "command") {
Serial.print(F(" Not a command :")); Serial.println(token);
return -1;
}
return pinNo;
}
which gives
cmd:Controller/MCP23017P0/command
Parsed pinNo:0
cmd:Controller/MCQ23017P15/command
Parsed pinNo:15
cmd:Controller/MCP23017Q15/command
23017Q15 is not a number
Invalid pinNo
cmd:Controller/MCP23017P15/data
Not a command :data
Invalid pinNo
Thank you for the quick replies. This has made me go mad - such a seemingly easy task has been really difficult. The parsing code suggested is very daunting for an amateur like me. I've been looking at atoi before, but never got it to work. But, after reviewing your example it ended up working perfectly by just adding one simple line of code..
int pinVal = atoi(topic + strlen("Controller/MCP23017P"));
Again, thank you for the very good and helpful replies!