bblanchon / ArduinoJson

📟 JSON library for Arduino and embedded C++. Simple and efficient.
https://arduinojson.org
MIT License
6.72k stars 1.12k forks source link

Converting a JSON array of hex values to uint8_t #1815

Closed proffalken closed 2 years ago

proffalken commented 2 years ago

Describe the issue

I have an API that returns data in the following format:

{
  "dev_eui": [
    "0xcc",
    "0x53",
    "0xee",
    "0x8f",
    "0xad",
    "0xc4",
    "0x89",
    "0x13"
  ],
  "app_key": [
    "0xef",
    "0xe0",
    "0x7f",
    "0x2b",
    "0x33",
    "0x8d",
    "0xc5",
    "0x5d",
    "0x60",
    "0xcb",
    "0x9a",
    "0x4e",
    "0x4f",
    "0x81",
    "0xe4",
    "0xc3"
  ],
  "app_eui": [
    "0xcc",
    "0x59",
    "0xe3",
    "0x84",
    "0xac",
    "0xc6",
    "0x12",
    "0x55"
  ]
}

I want to turn this into three uint8_t variables stored as byte arrays using the Preferences functionality on an ESP32 device so I can automatically programme devices for LoRaWAN Networks.

The lorawan example code shows defining these values as follows:

/* OTAA para*/
uint8_t DevEui[] = { 0x22, 0x32, 0x33, 0x00, 0x00, 0x88, 0x88, 0x02 };
uint8_t AppEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t AppKey[] = { 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x88, 0x66, 0x01 };

My code defines them as follows:

// AppEUI (sometimes called JoinEUI)
uint8_t *appEui;
// DevEUI
uint8_t *devEui;
// AppKey
uint8_t *appKey;

.........
htreg.begin("http://my.provisioning.service/");

// Use HTTP 1.x because we want to stream the data
htreg.useHTTP10(true);

............

DynamicJsonDocument config_response(768);
DeserializationError error = deserializeJson(config_response, htreg.getStream());
if (error) {
    Serial.print("TTN Response: ");
    Serial.println(htreg.getString());
    Serial.print("deserializeJson() failed: ");    
    Serial.println(error.c_str());
    Serial.println(ESP.getFreeHeap());
    return;
}

devEui = config_response["dev_eui"];
appKey = config_response["app_key"];
appEui = config_response["app_eui"];

So far, I have tried:

devEui = (uint8_t) config_response["dev_eui"];
devEui = config_response["dev_eui"].as<unsigned char>();
devEui = (uint8_t) config_response["dev_eui"].as<unsigned char>();
devEui = config_response["dev_eui"].as<char*>();

but each time I get something along the lines of

error: invalid conversion from 'uint8_t' {aka 'unsigned char'} to 'uint8_t*' {aka 'unsigned char*'} [-fpermissive]
devEui = (uint8_t) config_response["dev_eui"].as<unsigned char>();

Searching around suggests that I should be using copyArray, but I'm using a JSON dict, so I'm struggling to work out the syntax!

Troubleshooter report
Here is the report generated by the ArduinoJson Troubleshooter:

  1. The issue happens at compile time
  2. The error is not in the list

Environment
Here is the environment that I'm using':

Reproduction
See code above.

bblanchon commented 2 years ago

Hi @proffalken,

JSON doesn't support hexadecimal values, so ArduinoJson provides no facility to read them. I plan on adding support for JSON5 someday, but I can't give you any time estimate.

If you want to keep your current format, you need to loop through each array and call strtol(). Something like this (not tested):

for (const char* hexValue : doc["dev_eui"].as<JsonArray>()) {
   long value = strtol(hexValue, NULL, 16);
   // store value somewhere...
}

Best regards, Benoit

proffalken commented 2 years ago

Fantastic, thanks @bblanchon!