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!

  • 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"? – jose can u c May 10 '18 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 '18 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 '18 at 13:01
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.

  • Wow! Thanks for the fast answer. Alright, I guess I have to settle for non-binary then.. Thanks! – user125756 May 10 '18 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. – jose can u c May 10 '18 at 13:03
  • I would've upvoted your answer if I could :) (low rep blocks that at the moment) – user125756 May 10 '18 at 13:14

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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