Trouble handling subscribe data

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 
      }
    }
}
1 Like