Just one note. In order to not violate the rate limit for publishes, you might eiter want to increase your delay()
to 1010
or add some timeout that for one only allows one publish per second and also prevents multiple events firing if you keep the button pressed.
Like this
#include "InternetButton/InternetButton.h"
InternetButton b = InternetButton();
const char evtPrefix[] = "Player_";
const int playerID = 1;
void setup()
{
Particle.variable("PlayerID", playerID);
Particle.subscribe(evtPrefix, overwatchHandler);
b.begin();
}
void loop()
{
static uint32_t ms; // to keep track of last publishing time
static int lastState; // to keep track of the last button state
static bool needPublish; // keep track of pending publish requests
int actState = b.buttonOn(3);
if(actState && actState != lastState)
{ // only if the button is pressed first
needPublish = true; // inidcate a pending publish
}
if (needPublish && millis() - ms > 1010)
{ // if there is a pending publish request and
char evt[32];
ms = millis(); // the last publish is long enough gone
// try to publish
snprintf(evt, sizeof(evt), "%s%d", evtPrefix, playerID);
needPublish = !Particle.publish(evt, "Wanna play?");
// but if it failed keep it pending (needPublish = !success)
}
lastState = actState;
}
void overwatchHandler(const char *event, const char *data)
{
if (!strcmp(data, "Wanna play?")) // string compare if they are the same returns 0, so invert
{
int player = atoi(&event[strlen(evtPrefix)]);
b.ledOn(player, 255, 255, 255);
}
else // here you could parse the responses from the other buttons via data
{
...
}
}
For reference
http://www.cplusplus.com/reference/cstdio/snprintf/
http://www.cplusplus.com/reference/cstring/strcmp/
http://www.cplusplus.com/reference/cstdlib/atoi/
For another member I came up with this piece of code to have several Photons communicate with each ohter with just one code to flash to all of them.
I guess this could be adapted for your use too.
You can use this code on your InternetButtons too, you’d just need to name them as indicated in the code
// name all devices with a common prefix
#define COMMON_DEVICE_NAME_PREFIX "Player_"
/* Types required for RGB-LED control */
struct ARGB_COLOR {
byte B; // blue channel
byte G; // green channel
byte R; // red channel
byte A; // alpha channel to indicate RGB.control true (!= 0) / false (== 0)
};
union COLOR {
unsigned int value;
ARGB_COLOR argb;
};
struct devSetup
{
int pinTrigger;
int pinAction;
COLOR RGB;
char devName[32];
};
devSetup devices[] =
{
{ -1, -1, 0x000000, "" },
{ D4, D1, 0xFF0000, "Player_1"},
{ D5, D2, 0x00FF00, "Player_2"},
{ D6, D3, 0x0000FF, "Player_3"},
{ D7, A1, 0xFFFFFF, "Player_4"}
};
const int devCnt = sizeof(devices) / sizeof(devSetup);
char myName[32];
int myIdx;
void sparkEvents(const char *topic, const char *data)
{
Serial.printlnf("%s: %s", topic, data);
if (strstr(topic, "spark/device/name"))
{
strcpy(myName, data);
Serial.printlnf("myName = %s", myName);
// find my own index in devices list
for (myIdx = 1; myIdx < devCnt && strcmp(myName, devices[myIdx].devName); myIdx++);
myIdx %= devCnt; // if I'm not in there reset to 0
}
}
void devEvents(const char *topic, const char *data)
{
int idx;
int state;
Serial.printlnf("%s received %s: %s", myName, topic, data);
if (strstr(topic, myName))
{
Serial.println("Uhh, That's me!");
if (strstr(data, "=") && strstr(data, ";")) // rudimentary sanity check
{
idx = atoi(data);
if (0 < idx && idx < devCnt)
{
state = atoi(strstr(data, "=") + 1);
if (state < 0) // negative numbers indicates toggle current state
state = !digitalRead(devices[idx].pinAction);
digitalWrite(devices[idx].pinAction, state);
Serial.printlnf("%s told me to %s its action", devices[idx].devName, state ? "START" : "STOP");
if (devices[idx].RGB.value > 0)
RGB.color(devices[idx].RGB.argb.R, devices[idx].RGB.argb.G, devices[idx].RGB.argb.B);
}
else
Serial.println("I shan't talk to strangers!");
}
}
else
Serial.println("Meh, no one loves me!");
}
void setup()
{
Serial.begin(115200);
for (int i=0; i < devCnt; i++) // setup LED pins
{
pinMode(devices[i].pinTrigger, INPUT_PULLUP);
pinMode(devices[i].pinAction, OUTPUT);
if (devices[i].RGB.value > 0)
{
RGB.control(true);
RGB.color(0,0,0);
}
}
Particle.subscribe("spark/", sparkEvents);
Particle.subscribe(COMMON_DEVICE_NAME_PREFIX, devEvents, MY_DEVICES);
Particle.publish("spark/device/name"); // push cloud to send my device name
}
void loop()
{
static uint32_t msLastPublish;
int devNr;
for (int i = 1; i < devCnt; i++)
{
if (!digitalRead(devices[i].pinTrigger))
{
Particle.publish(devices[i].devName, String::format("%d=%d;", myIdx, -1), PRIVATE); // -1 for toggle state (otherwise HIGH/LOW for explicit state)
delay(1010); // currently there is an issue #1023 with the rate limit
}
}
}