Publish and subscribe with eventName as variable

Hi all,

I have a few situations where there are multiple controllers on a single physical location. One of the controllers has a set of sensors that allows the controller to make a decision (open or close?). The other controllers should react to that and do the operation (open or close).

Settings are stored in the EEPROM of the controller with an object. The object has an item to store if the controller is a master (making decisions) or a slave (actually opening an closing). Another item in the object is the projectName this identifies the controller as part of a set of controllers for a single location.

My idea is to make the masters publish an event with the eventName being the projectName and the data being “open” or “close”.

Here is my test code.

int addr = 1;                       // EEPROM addres
struct MyObject {                   // create object structure
bool status;                           // master = true, slave = false
char project[64];                   // project name
} settings;

String projectName = "projectX";

void setup(){
bool status;
bool action = false;
unsigned long previousMillis;
int interval = 20000;
}

void loop(){
// publish as if controller is a master (this controller is master and slave for testing purposes)
if ((millis() - previousMillis) >= interval){
        // publish event to open or close.
        if (action == false){
            Particle.publish(projectName, "open");
            Serial.println("Master says to open");
            action = !action;
        }
        else if (action == true){
            Particle.publish(projectName, "close");
            Serial.println("Master says to close");
            action = !action;
        }
        previousMillis = millis();
    }
}

class Subscriber {
  public:
   Subscriber() {
      Particle.subscribe(projectName, &Subscriber::handler, this);
    }
    void handler(const char *eventName, const char *data) {
      Serial.println(data);
      if (data == "open"){
          Serial.println("Slave will open");
      }
      else if (data == "close"){
          Serial.println("Slave will close");
      }
      else {
          Serial.println("invalid command");
      }
    }
};

When I use a static projectName like “My_project_name” the program works great.
When I use String projectName = “My_project_name” and use the code above the publish succeeds but in the log I get this:
����������������������������������������
Published by 2e0036000xxxxxxxxxxxxx on 11/21/18 at 9:39:21 am
instead of:
My_project_name
Published by 2e0036000xxxxxxxxxxxxxxxx on 11/21/18 at 9:50:09 am

Am I making an error here or am I abusing the Particle.publish function?

You might be having problems due to the nature of the String class.

String projectName = "projectX";

Have you tried using a char[] or a const char*?

I don’t see how that code can compile.

	String projectName = "projectX";

is declared inside setup(). You need to move it outside setup() so it’s a global variable, not a local variable scoped to setup().

2 Likes

That’s an error I’ve made while making the code simpler. I have it declared outside of the setup.

We’d need to see the exact code you are actually running - not some intermediate/transient version of your debugging attempts.

In above code I fail to see the the instantiation of a Subscriber object and since your constructor does require a successfully instantiated Particle object (to successfully call Particle.subscribe() - which may or may not be available at time of execution) you should rather add a init() method that is executed from setup().

Hi all,

Based on your feedback I’ve been tinkering on with this problem.
Yesterday on Thingscon in Rotterdam the Netherlands I met Niels from reflektor.dk who was here on behalf of Particle and we started chatting about my problem.

The result is that I have succesfully created the code to publish with a variable as the event name. I’d like to share this code with you.

String data = "open";
String projectName = "mainstreet";

void setup() {
}

void loop() {
    bool succes;
    succes = Particle.publish(projectName, data);
    Serial.println(succes);

    delay(5000);
}

This results in:
event: mainstreet
data: {“data”:“open”,“ttl”:60,“published_at”:“2018-12-07T10:11:23.506Z”,“coreid”:“2e0036000347343339373536”}

Which is exactly what I need. Now the fun bit starts. I’ve added a Particle.function to set the project name through a webpage and a variable to check the project name in the console.

void setup() {
    Particle.variable("project", projectName);
    Particle.function("Project_Name", setProjectName);
}

My next step is to add a Particle.subscribe with the projectName variable and have only controllers with the same value for projectName respond.

Hope this use case helps other developers as much as it does for me.

1 Like