Iterating and storing multiple data samples from single epoch

Hi, I’m totally new to Losant.

We’re sending 24 data samples of data every 2 mins (1sample/5s) that are base64 encoded along with other measurements that are only sampled every 2min. The JSON object has a single epoch timestamp. Basically, looks this:

{
“epoch”: (timestamp),
“sensorData”: {
“samples”: (base64 encoded string of 24 samples)
},
“otherData”: (data)
}

After decoding the base64 string into 24 integers we know we need to iterate over them and pair them with the appropriate timestamp that’s indexed, in 5s steps, from the epoch in the JSON object.

After ingestion, we have an array of samples (as ints) and their associated timestamps. We’ve tried the Loop node, using the timestamp array as the iterator, and then using a Device:State node inside the loop to store each sample in a device attribute but cannot seem to figure out the proper call to index into the data sample array with the iterator inside the Loop node.

We’re not married to the idea of using the Loop node at all. Looking for suggestions on the best way to attack this problem in Losant so that the 24 samples (1sample/5s) can be graphed on the same timescale as the data that’s measured every 2mins. Happy to write code in Function node to do the job.

Thanks!

Hi @Phillip_Warren, and welcome to the Losant Forums!

If I’m reading this correctly, you are essentially batch-reporting 24 state values for a single device, and you have either a beginning or ending timestamp associated with that batch report, and from that one timestamp you can extrapolate the individual timestamps of each of the 24 state reports. Then, on top of that, you have otherData that is associated with just one of the timestamps.

Assuming I have that correct, I would abandon the Loop Node approach and instead create a batch state report - that is, convert your raw data into an array of the following shape …

[
  {
    "time": (extrapolated timestamp),
    "data": {
      "attributeName": (value),
      "anotherAttributeName": (other value)
    }
  },
  ...
]

A Function Node is probably your best bet to build this array, though it could be done with the other native nodes.

Then, in the Device State Node, use the “Payload Path” option and provide a path to the array you constructed.

Let me know if you have any questions or if any of my assumptions are incorrect, and again, welcome to Losant!

@Dylan_Schuster, thank you very much! Think we’re getting close.

Here’s what we have in the data that we built with a Function node:

{
  “time”: (epoch_start),
  “sample_data”: (value),
  “series_data”: {
    0:{
      “time”:(epoch_start + 5s),
      “attributeName”: (value),
      “anotherAttributeName”: (other value)
    },
    1:{
      “time”:(epoch_start + 10s),
      “attributeName”: (value),
      “anotherAttributeName”: (other value)
    },
    2:{
      “time”:(epoch_start + 15s),
      “attributeName”: (value),
      “anotherAttributeName”: (other value)
    },
    …
    23:{
      “time”:(epoch_start + 120s),
      “attributeName”: (value),
      “anotherAttributeName”: (other value)
    }
}

The sample_data matches to epoch_start and each sample after that occurs 5s*i after epoch_start. We’d like to be able to plot both the sample_data and the series_data on the same graph.

Still not sure how to use the Batch Reporting method. Would we set “State Data Payload Path” to data.series_data and the time “Time Payload Path” to data.time? Is there some logic in that node that would perform the indexing that we would otherwise get from iterating through the array in the loop?

Feels like we’re close but just missing a small piece.

Thanks for your help!

So a few things here …

First, the shape of your end result data is not quite right. A batch state report is an array of state report objects and, if you are including a time property, the attributes must be in a data object. So again, that form would be …

[
  {
    "time": (epoch timestamp),
    "data": {
      "attributeName": (attributeName value),
      "anotherAttributeName": (anotherAttributeName value) 
    }
  }
]

Second, whatever attributes you are reporting must be defined on the device, with data types that match the type of value you are reporting. In my example, those would be “attributeName” and “anotherAttributeName”. You can have as many as 256 attributes per device.


Finally, in regards to your question:

Would we set “State Data Payload Path” to data.series_data and the time “Time Payload Path” to data.time?

This is something we should clear up in our documentation, but if you provide a time property in the value referenced through a payload path (including when that path resolves to an array of batch state reports), we ignore the “Time” setting provided in the node configuration. So you can disregard that.

Got it…worked perfectly. Thank you!