First, yes, readButtons returns the current state of all buttons. It simply reads the current state of the MCP23017 and pulls out the button bits. This is typical behavior for this sort of thing. Usually, you would maintain a local copy of the last state read, and perform an exclusive-or with the value returned by readButtons to determine which buttons, if any, changed state. Then you'd react to the new state of the changed buttons.
For toggles, you can simply read the state of your output pin. If it reads as HIGH, then your relay is enabled, and you can turn it off. And vice-versa.
- Code: Select all | TOGGLE FULL SIZE
if (digitalRead(buttonPin) == HIGH) // button is pressed
digitalWrite(ledPin, !digitalRead(ledPin)); // toggle current output state - if HIGH, write LOW. if LOW, write HIGH
Put a delay(250); at the bottom of the loop so you don't cycle through too quickly