Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Sending floating point and integer data through MQTT #336

Open
mitra42 opened this issue Sep 28, 2024 · 6 comments
Open

Sending floating point and integer data through MQTT #336

mitra42 opened this issue Sep 28, 2024 · 6 comments

Comments

@mitra42
Copy link

mitra42 commented Sep 28, 2024

I've got some sensors generating floating point and integer data. I'd like to send this over MQTT, and ideally without converting back and forth to the Ascii.

The docs have bool publish(const char topic[], const String &payload);
bool publish(const char topic[], const char payload[]);

I'm wondering if there is an accepted method of sending numbers (floating or int) over MQTT, and if so what it is.... I've tried searching for the answer in all the usual places, but I'm not finding it.

I also think it would be useful to have this in at least one of the examples.

@ForrestErickson
Copy link

Here is an answer the might work. Use JSON libraries to make a JSON object and then convert to binary to send.

The top answer here looks promissing.
https://stackoverflow.com/questions/23947779/how-to-send-data-as-json-objects-over-to-mqtt-broker

Let us know what does and does not work.

@mitra42
Copy link
Author

mitra42 commented Oct 25, 2024

I ended up converting to a string - yes you can use JSON but its more overhead (code size) on small processors.

@ForrestErickson
Copy link

Regarding, "I ended up converting to a string"
Thanks for letting us know you solution.
Can you post the code that works so that persons who find this question, as I did, will find an answer?

For what it is worth I have no idea how memory safe the JASON solutions might be. I have read that Strings in Arduino are not safe under some programing methods because of limited memory. Problem is more sever on an UNO of course.

@mitra42
Copy link
Author

mitra42 commented Oct 25, 2024

My own code is a lot more complex, because its also dealing with things like queuing messages to avoid calling publish within messageReceived (a warning in the library).

The part you want I think is below. It sends a float by converting to a string. There are probably slightly simpler ways to write messageSend(String &topic, String &payload, bool retain, int qos) if you don't want the queuing.

// If retain is set, then the broker will keep a copy 
// TODO implement qos on broker in this library
// qos: 0 = send at most once; 1 = send at least once; 2 = send exactly once
// These are intentionally required parameters rather than defaulting so the coder thinks about the desired behavior
void messageSendInner(Message *m) {
  #ifdef SYSTEM_WIFI_WANT
    client.publish(*m->topic, *m->message, m->retain, m->qos);
  #endif // SYSTEM_WIFI_WANT
}
void messageSend(String &topic, String &payload, bool retain, int qos) {
  // TODO-21-sema also queue if WiFi is down and qos>0 - not worth doing till xWifi::connect is non-blocking
  Message *m = new Message(topic, payload, retain, qos);
  if (inReceived && qos) {
    queued.push(m);
  } else {
    messageSendInner(m);
  }
  // Whether send to net or queue, send loopback and do the retention stuff. 
  #ifdef SYSTEM_MQTT_LOOPBACK
    // This does a local loopback, if anything is listening for this message it will get it twice - once locally and once via server.
    if (m->retain) {
      retained.retain(m); // Keep a copy of outgoing, so local subscribers will see 
    }
    messageReceived(m);
  #endif // SYSTEM_MQTT_LOOPBACK
}
void messageSend(String &topic, float &value, int width, bool retain, int qos) {
  String *foo = new String(value, width);
  messageSend(topic, *foo, retain, qos);

}
void messageSend(String &topic, int value, bool retain, int qos) {
  String *foo = new String(value);
  messageSend(topic, *foo, retain, qos);
}

The full code is in the FrugalIoT repo; but this handles a lot more complexity that most situations won't need, including using MQTT within a single device to communicate between different code modules.

@ForrestErickson
Copy link

@mitra42
Thanks for the example. I am some times novice and seeing the simple function

void messageSend(String &topic, float &value, int width, bool retain, int qos) {
  String *foo = new String(value, width);
  messageSend(topic, *foo, retain, qos);
}

helps

Just to be clear, since I see no conditional tests, you are sending every time a float and then an int. Am I right?

And thanks again.

@mitra42
Copy link
Author

mitra42 commented Oct 25, 2024

Sorry, no the width variable is misnamed, should be "decimalplaces" so String(1.2345678,3) becomes "1.234"

https://docs.arduino.cc/language-reference/en/variables/data-types/stringObject/

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants