Sending CBOR data to sensor endpoint but don't see it in dashboard

Hi,

I’m calling golioth_stream_set_async in my application to send data encoded in CBOR. The callback returns 0, which I imagine means that the data was successfully received by the server, but I don’t see the data in my dashboard under the LightDB stream tab. Can you provide guidance on what I am doing wrong, or help me troubleshoot further?

Thank you,

Hey @mab

Have you been able to get the Golioth CBOR samples working on your project? Knowing that will help us to suss out whether it is a pipeline based problem or a device side CBOR encoding problem.

Could you show some (non-sensitive) CBOR encoded data here or verify that the CBOR encoding was done correctly? There a range of checkers available online.

Hi @ChrisGammell ,

We were able to get the Golioth sample working against our production dashboard using a Thingy91x. I then picked the relevant functions to include in our custom application. Also, something I forgot to mention, warnings that get displayed as logs on the console, do show up in the dashboard. This leads me to believe that the CBOR encoding may not be correct.

Here is a snippet that demonstrates the CBOR encoding (we are essentially sending up canned data that would ultimately represent scanned cell tower data to Golioth):

static bool get_cell_scan_data(zcbor_state_t *zse)
{
        bool ok;
        ok = zcbor_tstr_put_lit(zse, "lte") && zcbor_map_start_encode(zse, 3);
        if (!ok) {
                printk("%s -- failed on lte\n", __func__);
                return false;
        }

        ok = zcbor_tstr_put_lit(zse, "appId") && zcbor_tstr_put_lit(zse, "GROUND_FIX");
        if (!ok) {
                printk("%s -- failed on appId\n", __func__);
                return false;
        }

        ok = zcbor_tstr_put_lit(zse, "messageType") && zcbor_tstr_put_lit(zse, "DATA");
        if (!ok) {
                printk("%s -- failed on messageType\n", __func__);
                return false;
        }

        for (int i = 0; i < 4; i++) {
                ok = zcbor_tstr_put_lit(zse, "data") && zcbor_map_start_encode(zse, 8);

                if (!ok) {
                        printk("%s -- failed on data\n", __func__);
                        return false;
                }

                ok = zcbor_tstr_put_lit(zse, "eci") && zcbor_int32_put(zse, 24270593) &&
                     zcbor_tstr_put_lit(zse, "mcc") && zcbor_int32_put(zse, 310) &&
                     zcbor_tstr_put_lit(zse, "mnc") && zcbor_int32_put(zse, 260) &&
                     zcbor_tstr_put_lit(zse, "tac") && zcbor_int32_put(zse, 14401) &&
                     zcbor_tstr_put_lit(zse, "earfcn") && zcbor_int32_put(zse, 2300) &&
                     zcbor_tstr_put_lit(zse, "rsrp") && zcbor_int32_put(zse, -84) &&
                     zcbor_tstr_put_lit(zse, "rsrq") && zcbor_float32_put(zse, -5.5) &&
                     zcbor_tstr_put_lit(zse, "adv") && zcbor_int32_put(zse, 16);

                if (!ok) {
                        printk("%s -- failed to encode light data\n", __func__);
                        return false;
                }

                ok = zcbor_map_end_encode(zse, 8);
                if (!ok) {
                        printk("%s -- failed to close lte data\n", __func__);
                        return false;
                }
        }

        ok = zcbor_map_end_encode(zse, 3);
        if (!ok)
        {
                printk("%s failed to close map\n", __func__);
                return false;
        }

        return true;
}

.
.
.
void send_golioth_data(void)
{
    char cbor_buf[1100];
    printk("MAB %s - going to send data to golioth\n", __func__);
    ZCBOR_STATE_E(zse, 2, cbor_buf, sizeof(cbor_buf), 1);

    ok = zcbor_map_start_encode(zse, 2);
    if (!ok) {
        printk("%s -- failed to open map\n", __func__);
        return;
    }

    ok = get_cell_scan_data(zse);
    if (!ok) {
       printk("%s -- failed to encode cell scan data\n", __func__);
       return;
     }

      size_t cbor_size = zse->payload - (const uint8_t *) cbor_buf;
      printk("MAB %s -- cbor_size = %d, payload = %d\n", __func__, cbor_size, zse>payload);

     if (golioth_client_is_connected(client)) {
        err = golioth_stream_set_async(client, "sensor", GOLIOTH_CONTENT_TYPE_CBOR, cbor_buf, cbor_size, async_error_handler, NULL);

        if (err) {
            printk("%s - Failed to send sensor data to Golioth: %d", __func__, err);
        }
    } else {
    printk("MAB %s -- not connected to Golioth, skipping sending data\n", __func__);
}
.
.
.

Hey there, jumping in with guidance from our engineering leadership! It looks like you’ll need to put that whole thing in an enclosing map. So the equivalent JSON would be:

"lte"
{
  "appId" : "GROUND_FIX",
  "messageType" : "DATA",
  "data" : {
    ...,
  }
}

But it needs to be:

{
  "lte" :{
    "appId" : "GROUND_FIX",
    "messageType" : "DATA",
    "data" : {
      ...,
    }
  }
}

Hope that helps!

Hi @brian,

Thanks for the hint. Do you have examples or functions I can use to create the suggested map in CBOR (I’m still trying to wrap my head around what functions to use to appropriately create a corresponding JSON output)?

Thanks

We have some samples in our documentation that may help to point you in the right direction. cbor-to-json | Golioth

I’ll so some more digging and see if I can find some more robust examples to assist.

Hi @brian ,

It looks like I was missing a map_end_encode in send_golioth_data() after calling get_scan_data before sending the data out to Golioth.

If you could point me to a reference on how I can send an array of data to Golioth using CBOR that would be great. For example:

"data": {
    [
        "adv": 16,
        "earfcn": 2300,
         . . . 
     ],
     [
          "adv": 17,
          "earfcn": 2301,
     ]
}

Hey @mab,

You can find an example of data formatting as a serialized CBOR object in the Stream client documentation.

Hope this helps!