2

I'm using a library that takes a String as it's parameter (https://github.com/gmag11/painlessMesh)

I want to pass char arrays that is binary (UTF-8) data that also contains null-bytes (0x00). Right now, the resulting String is cut off at the first null-byte as expected. I know the full length of the char array, is it possible to construct an Arduino String while passing the arbitrary length, so that the full String also contains the null-bytes including the data that follows after, up until the pre-set length?

I had this problem before and then I solved it by converting the UTF-8 data to hex and then add a null-byte. I was hoping there is a more elegant way, since this forces me to double the data-size.

Thanks!

3
  • A "String" can't have null characters inside it, so why do you need to pass in data that is not a "String"? Is it because you need to send a message payload that is not a "String"? May 10, 2018 at 12:54
  • 2
    The only zero byte the UTF-8 encoding produces is the null character. If the zero byte is anywhere but at the end, then it's not UTF-8.
    – gre_gor
    May 10, 2018 at 12:59
  • @josecanuc I don't want to use a String, it's just that the library asks me to pass one.
    – user125756
    May 10, 2018 at 13:01

1 Answer 1

3

Assuming you are talking about the function

bool painlessMesh::sendBroadcast( String &msg, bool includeSelf = false)

Then you'll see that ultimately, the library passes msg into the function buildMeshPackage where it constructs a JSON message (see here)

String ICACHE_FLASH_ATTR painlessMesh::buildMeshPackage(uint32_t destId, uint32_t fromId, meshPackageType type, String &msg) {
    debugMsg(GENERAL, "In buildMeshPackage(): msg=%s\n", msg.c_str());

    DynamicJsonBuffer jsonBuffer;
    JsonObject& root = jsonBuffer.createObject();
    root["dest"] = destId;
    //root["from"] = _nodeId;
    root["from"] = fromId;
    root["type"] = (uint8_t)type;

    switch (type) {
    case NODE_SYNC_REQUEST:
    case NODE_SYNC_REPLY:
    {
        JsonArray& subs = jsonBuffer.parseArray(msg);
        if (!subs.success()) {
            debugMsg(GENERAL, "buildMeshPackage(): subs = jsonBuffer.parseArray( msg ) failed!");
        }
        root["subs"] = subs;
        break;
    }
    case TIME_SYNC:
        root["msg"] = jsonBuffer.parseObject(msg);
        break;
    default:
        root["msg"] = msg;
    }

    String ret;
    root.printTo(ret);
    return ret;
}

Even if you did construct a String with null terminators in it, the moment it gets put into the JSON string it destroys everything. JSON by default doesn't support binary data strings (reference).

So, the library is a problem because it happily passes data as JSON messages, and that's bad if you want binary data transported. You could use Base64 or the more efficient http://base91.sourceforge.net/ encoding though to mitigate this a little bit, or search for a different lib.

3
  • Wow! Thanks for the fast answer. Alright, I guess I have to settle for non-binary then.. Thanks!
    – user125756
    May 10, 2018 at 13:02
  • 1
    The key part of this answer is to encode your "binary" data. This has been done for ages, and email messages still commonly have base64-encoded "text" for binary file attachments. If the framework takes Strings, then you must convert your binary data to something that looks like a string. May 10, 2018 at 13:03
  • I would've upvoted your answer if I could :) (low rep blocks that at the moment)
    – user125756
    May 10, 2018 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.