Conversion of Device Id to message buffer for Particle.publish()

I am trying to use Particle.Publish to broadcast a series of records from an instrument - initially using Particle.Publish within the Particle environment but subsequently to Google Cloud PubSub.

Each instrument issues a series of records in seperate Publish events, with each record containing the device name so that records from different instruments can be sorted out at the Subscribe end,

I am having difficulty with decoding of the device name into the message buffer as follows:

String devicename; 

// Get device name
    Particle.subscribe("particle/device/name",devnameHandler);  
    Particle.publish("particle/device/name");

// Publish header record
    ncount=0;
    sprintf(msgBuffer,"%4d,%s,%4d-%02d-%02d,%02d%02d\0",ncount,devicename.c_str(),Time.year(),
Time.month(),Time.day(),Time.hour(),Time.minute());
     Particle.publish(devicename,msgBuffer,PRIVATE);

I have looked at previous queries on the bulletin board and have tried various combinations to no avail.
The record counter and date/time fields are fine but the devicename field either contains a blank, nothing at all, or a question mark.

Advice would be much appreciated (as a Fortran programmer from the 80’s there is much about the C++ language that trips me up from time to time).

Thanks in anticipation

I did not include the handler code in the above code extract

void devnameHandler(const char *topic, const char *data)
{devicename=data;}

As always, I’ll start with advising against the use of String :wink:
Next I’d propose this

char deviceName[32] = "unknownDevice";
...
void devNameHandler(const char *topic, const char *data) {
  memset(deviceName, 0x00, sizeof(deviceName));
  strncpy(deviceName, data, sizeof(deviceName)-1);
}

...
  snprintf(msgBuffer, sizeof(msgBuffer)
          , "%4d,%s,%s"
          , ncount
          , deviceName
          , (const char*)Time.format("%F,%H%M")  // YYYY-MM-DD,hhmm
          );
  Particle.publish(deviceName, msgBuffer, PRIVATE);

To understand the format of Time.format() you can look here
http://www.cplusplus.com/reference/ctime/strftime/

1 Like

Thanks for the quick reply

I replaced the code but it did not work (most likely finger trouble on my part).

The Publish event name lost 1 character (Previously showing as PT-B2 became PT-B) and the deviceName in the message buffer became ‘unknown device’. Date and time fields were correct.

It’s getting late here so I will have a closer look in the morning.

The next trick is to encode 200 3-digit numbers into the subsequent messages - I have seen your comments on previous posts so am hoping it will be a breeze.

Again, thanks for the prompt reply @ScruffR

As this is the initila value I chose for the deviceName variable this indicates that you are accessing that variable before it actually got updated with the correct user name.

I'm also not sure where your difference between the publish event name and the device name would come from. In your initial code you are using the same variable for both.

Can you post your entire code?

Thanks @ScruffR

I have looked at the code this morning and have resolved two issues

(a) The shortened device name PT-B instead of PT-B2 was fixed by removing -1 from strlen-1

(b) There is a race condition causing the first record to show deviceName as unknown but subsequent records to have the correct deviceName. The first record is published immediately after the calls to Subscribe then Publish to get the device name as per Docs guide. Inserting a 3 second delay before the first record Publish results in the correct deviceName being used. It is not clear how to check that the Subscribe - Publish sequence has completed.

Although use of an (arbitrary) delay would normally be an undesirable kludge it is not a problem (or even necessary) in this case. I have to add initialization of a 4DSystems display and a Start button to start data recording so there will naturally be a substantial delay between getting the deviceName and the first Publish event as I develop the code further.

I am able to post the code but will progress to embedding the data in subsequent Publish calls. At this stage I think I have it all covered but I know where to come if I come unstuck :slightly_smiling_face:

As ever, thanks for your willing assistance.

Since this wasn't part of any code I saw I wouldn't have known :wink:
I'm using sizeof() not strlen().

I suspected (since not seeing the code) such a race condition, hence I initialised deviceName to something that clearly shows the fact. Normally I'd initialise the deviceName to a zero-string and then check in code if (strlen(deviceName)) to make sure the string is not empty before doing anything with it :wink:

Since you are dealing with asynchronous actions it's never a good idea to do something immediately after initiating such a task - especially not without checks.

Thanks

It was indeed the ‘size of’ that I removed the -1. My error in reply.

Your other points are understood and appreciated - I was unaware that the Sub/Pub actions were asynchronous.

I see, I had a typo in there. The -1 should have been after parenthesis (corrected above).

This topic was automatically closed 182 days after the last reply. New replies are no longer allowed.