Closed kregiel closed 3 years ago
Hi @kregiel,
The MqttClient :: MessageData :: topicName
uses the Paho MQTTString
type.
The MQTTString
usualy contains c-string
(with string termination character at the end) or char-array
+ char-array-length
.
Unfortunately, this is how the MQTTString
object is used by the Paho library.
You need to handle two possible variants.
What exactly are you trying to do with the topic?
Please take a look on int MQTTPacket_equals(MQTTString* a, char* bptr)
function from MQTTPacket/MQTTPacket.h
as example, it compares an MQTTString
to a c-string
.
I have one message callback for all subscribtions e.g te'mperture/room1' and 'temperature/room2' and I need to know where this temperature is coming from in order to take the right action.
Of course, I can change the naming of topics or/and feed data to include an ID as well, but before reorganizing everything, I'd like to try to handle it as I have it configured now ;)
MQTTPacket_equals (...) is also based on lenstring.data and lenstring.len, so unfortunately, since md.topicName.cstring is empty (maybe could you check if cstring variable is really filled for topicName and how to get it? now I've try to get it like 'md.topicName.cstring') then my way is ok to get topic name?
char topicName[md.topicName.lenstring.len + 1];
memcpy(topicName, md.topicName.lenstring.data, md.topicName.lenstring.len);
topicName[md.topicName.lenstring.len] = '\0';
But in my opinion cstring should be always filled when you create MQTTString or at least to have function to get it on the fly...
Sorry if I missed something, I believe the MQTTPacket_equals
does exactly what you need.
It allows you to compare an MQTTString
with a c-string
.
In your single/global message callback, you can use it to test the topic like MQTTPacket_equals(md.topicName, "temperature/room2")
and as a nice bonus it gracefully handles the dual internal representation of the MQTTString
object, see:
int MQTTPacket_equals(MQTTString* a, char* bptr)
{
int alen = 0,
blen = 0;
char *aptr;
if (a->cstring)
{
aptr = a->cstring;
alen = strlen(a->cstring);
}
else
{
aptr = a->lenstring.data;
alen = a->lenstring.len;
}
blen = strlen(bptr);
return (alen == blen) && (strncmp(aptr, bptr, alen) == 0);
}
You can do exactly as you proposed initially, in case you need to analyze a piece of the topic string, using lenstring
only but in this case, you blindly ignore the possibility of the c-string internal representation.
My suggestion is to use the existing int MQTTstrlen(MQTTString mqttstring)
and int MQTTPacket_equals(MQTTString* a, char* bptr)
or build your own methods that properly tests all fields including cstring
and lenstring
.
I am using the Paho library as the base (everything under the MQTTPacket
directory), this is how Paho returns the topic using MQTTString
type, probably this is because of the memory optimization to avoid unnecessary allocations and coping, I know this is inconvenient but important for microcontrollers.
What kind of helper method would you like to have, It looks like the already existing MQTTPacket_equals
and MQTTstrlen
should cover most of cases.
ok Oleg, thanks for the clarification. In fact, the function MQTTPacket_equals()
is enough for comparing, but not for getting topic name itself e.g. to display to Serial port or for other string/char operations... am I right or I've missed somethig? so maybe I will write something suitable only for my project ;)
I think we can close the issue...
@kregiel, you right, you need another function for printing or manipulations with the topic name.
The MQTTPacket_equals
is a good example of MQTTString
type usage.
Please let me know if I can help more. Good luck with your project!
Hello, I can't get the topic name in useful format (e.g string) from "MqttClient :: MessageData & md" object in message callback. I tried to do this via md.topicName.cstring but it's empty? The variable md.topicName.lenstring.data does contain the topic name but with the payload appended without any separator... Finally, I did it through the so-called "substring" using md.topicName.lenstring.data and md.topicName.lenstring.len, but could this be done easier? Is there any function or variable with plain topic name in message callback function?