Atypical Particle.subcribe Handling On 1.5.4-rc.1 for Device Name Functionality

Hello,

I’m trying to track down a menacing bug in my code when trying to call a Particle.subscribe() handler. I want to send my device name in a JSON payload to parse with a firebase DB. In order to do that I’m using the code provided in the reference files of the particle website. Here is the referenced stock code:
image

I now am going to paste the code I have on my device, I have it split up because its referenced in different areas of the code so I’m snipping here for clarity:
Here is the setup of the subscribe command and the publish command at the beginning of my code

void setup() {
    Particle.subscribe("particle/device/name", deviceNameHandler, MY_DEVICES);
    Particle.publish("admin","particle/device/name", MY_DEVICES);

Here is another part of my code where I issue the publish command to call the handler to check if the name has changed (it only does this once)

if (deviceNameFlag == false ) {
            Particle.publish("admin","particle/device/name", MY_DEVICES);
            deviceNameFlag = true;    

Here is the handler function I have outside of the loop():

void deviceNameHandler(const char *topic, const char *data) {
	deviceName = data;
    Particle.publish("debug2", "device Handler Called");
}

The weird part is that I got it working last night but now its not working at all. I double-checked everything and its the same as it was last night.
This is what I’m seeing In my Event Viewer:

Could you share the code that formats the Report_Payload event. Also, how do you define deviceName? If deviceName is a String you can’t just use equal operator to copy it from a const char* type.

1 Like

Sure: this is the payload function, I’m using a JsonParserGeneratorRK to parse the information for me in the first part and I’m also sending it outside as part of me debugging. I was also having this problem without the JsonParserGeneratorRK being used so I don’t think its related to the library:

This will not trigger the Particle.subscribe("particle/device/name", ...) handler.
You need to publish like this

Particle.publish("particle/device/name", PRIVATE);

(for particle/... events the scope is irrelevant but in general you need to publish as PRIVATE when subscribing for MY_DEVICES and PUBLIC when subscribing for All_DEVICES)

You subscribe to the event name (first parameter) not to the payload (second string parameter).

1 Like

How are you defining deviceName?

I see at least two possible bugs here.

First, you are publishing to the "admin" topic, with "particle/device/name" as the data. In the docs it says to publish to the "particle/device/name" topic with no data. Are you sure this was working last night?

Particle.publish("admin","particle/device/name", MY_DEVICES);

@ScruffR beat me to it on this one.

Second, in deviceNameHandler the following line may have unexpected results:

deviceName = data;

Since data is a pointer to a char array, when you set deviceName to the same pointer, the data at that address likely changes before you dereference deviceName later in your application.

As @armor asked, how have you defined deviceName in your code? In order for your code to work as expected, it should be a char array. (If it was a String object the compiler likely gave you a warning.)

For example:

char deviceName[25]; // 24 chars + null terminator

In order to copy the contents of data into deviceName you need to use a function like strncpy.

strncpy(deviceName, data, sizeof(deviceName);

If deviceName and data are of different lengths you will need to set the null terminator manually in deviceName.

For example:

deviceName[24] = '\0';

Unfortunately even after changing the Particle.subscribe() to this in my code:

Particle.publish("particle/device/name", PRIVATE);

image

I still am not seeing it in Events:

Have you addressed the issue with deviceName that @armor and I mentioned?

I think you may be onto something here, but I haven’t got it to work yet. I will keep you all informed on my progress.

1 Like

So I’m still getting null value. Here is how I declare deviceName:
image

and here is how the handler is coded:
image

Still nothing in console:

It’s almost as if the handler isn’t getting called from the Particle.subscribe command because if it was I would see this debug Particle.publish(“device handler called” in console:

Do you have physical access to the device? Printing debug messages over serial is much preferable over publishing events because events can get throttled and publishes and subscriptions use the same buffer.

A quick Serial print in deviceNameHandler could tell you a lot:

// At the beginning of the function
Serial.println(data);

// At the end of the function
Serial.println(deviceName);

Also, on line 1029, that publish might not be getting through because you didn’t specify PRIVATE.

Also, you defined the length of deviceName to 24, but you set the null terminator on index 24, which is out of range. You should set it on index 23, which is the last index. That yellow squiggle might be a warning about this. You could also define the length as 25. Also, since data is likely less than 24 characters, you could remove that line setting the null terminator altogether.

I will try but I currently don’t have access.

Try specifying PRIVATE in the publish on line 1029, and comment out line 1028, where you set the null terminator out of bounds.

Okay so I got it working but I don’t know how. I put the

Particle.publish("particle/device/name", PRIVATE);

inside the loop() function instead of in the void do_report() and it started working.


Why? I don’t know…

Okay, so I finally figure out what was causing the fault condition, but I dont know why… Maybe someone else can shed some light.

In order for Particle.subscribe() to call the handler function

Particle.subscribe("particle/device/name", deviceNameHandler, MY_DEVICES);

Particle.publish(function below) has to be called at least twice:

Particle.publish("particle/device/name", PRIVATE);

My code was set up in a way that the Particle.publish() command was only sent once, so the handler was not called.

I don’t know if that’s a bug or something specific to my code but that’s what seems to have fixed it.

Here’s some proof: Look at my Event viewer, the first time my do_report was called the deviceName was not updated, but the second time the Particle.publish command was called it did work.

If anyone has experienced similar behavior please let me know.

Sweet!!

image

1 Like

I don’t think so - I’d rather think it’s some race condition where your first publish just happens too early.

1 Like