Difference between current and last incrementing pulse count values reported by sensor

I have a LoRa water meter pulse count sensor that sends it’s ever incrementing value in the uplink payload which is decoded (E.g… "data.decoded.pulse_count’) and inserted into a data table and displayed on a dashboard, and each payload also has the current Unix epoch time value assigned as well during the decode, but I also want to calculate the difference between the latest pulse count value received, and the last pulse count value received, and the time in seconds between each value update. I am struggling to work out the best way to do this relatively simple task in Losant, which would take seconds in code normally. Any ideas would be of great help thanks!

1 Like

First, it sounds like you may be storing device telemetry data in a data table, something we strongly recommend against as data tables lack the performance, aggregation methods, and scalability of our native time series database.

Now for your question, you have a couple options here …

First, you said it’s a “LoRa water meter”, which leads me to believe that the data is coming into Losant via a webhook or experience endpoint - and thus you are using a workflow to record the device state. So one thing you could do in your workflow is …

  1. Fetch the device you are recording state for using the Device: Get Node, also retrieving the composite state values for your pulse count and Unix timestamp (though you could also just use the time that the pulse count was received).
  2. Calculate the difference between the value that just came from the LoRa sensor and the value that was last recorded to the device. You could do this easily using a Math Node.
  3. In addition to recording the new pulse count and timestamp in your Device: State Node, also now record the calculated differences as separate attributes on the device (i.e. “pulsesSinceLastReport” and “timeSinceLastReport”).
  4. Now, in a dashboard, you can display those calculated differences several different ways, such as using a Gauge Block.

Alternatively, you mentioned that what you are trying to do “would take seconds in code normally”, and you’re right. Luckily there’s a block for that - the Custom HTML Block or, if you’re familiar with Vega, the Custom Chart.

In either case, you could set up two time series queries in the block: one for the pulse count and one for the timestamp. Each would use the “Last” aggregation method and would use a duration and resolution appropriate for how frequently your device reports data; I would aim for the lowest possible values that would ensure you always receive at least two data points that would reflect the most recent and the second-most recent state reports.

With that data in hand, you can calculate the difference between the last pulse count and the one before it, and same for the timestamps. And then you can visualize those two values however you see fit.

Hi Dylan,
ok,I’m curious about what you propose using the ‘Math’ workflow node. But yes, the LoRaWAN (Actility) NS https POST’s to a Losant webhook, which runs a decode workflow, which consistes of a decode ‘function’ node, then a ‘Device Get’ based on the DevEUI, then a ‘Device State’ state write node. So I have a payload path continaing all the decoded and unix timestamp values at ‘data.decoded.’. What exactly would the expression be in the Math workflow node that retrieved a prior sample’s values, to perform the difference calc? That’s the part (expression) that I can’t fathom.


Thinking about it a little more, you actually don’t even need the Math Node; you could do the calculation inline in the Device: State Node when you are defining the value to report.

There’s a lot I don’t know about the property names you have in place, so let’s assume the following for this explanation …

  • The device from the Device: Get Node is at working.device.
    • And the device has attributes named pulse_count and timestamp, and you would be adding new attributes pulses_since_last_report and seconds_since_last_report.
  • The decoded timestamp from your webhook body is at data.decoded.timestamp (alongside data.decoded.pulse_count).

When you request composite state in the Device: Get Node, those state values are hanging off the device object at the property compositeState, and it takes a shape like the following …

  "pulse_count": {
    "time": (Date object of time value was last reported),
    "value": 42
  "timestamp": {
    "time": (Date object of time value was last reported),
    "value": 1234567890

So, putting that all together, the value you would report for your new pulses_since_last_report value in the Device: State Node would be:

{{subtract data.decoded.pulse_count working.device.compositeState.pulse_count.value}}

And for seconds_since_last_report:

{{subtract data.decoded.timestamp working.device.compositeState.timestamp.value}}

I recommend giving this documentation a read if you are having trouble with building payload paths, writing expressions, and manipulating values with string templates. Note that you can also right-click any property in a workflow debug log message to copy the full path to that property, which you can then paste straight into a node’s configuration.

Hi Dylan,
I’ve built a few apps in Losant before, so am reasonably familiar with most functional parts, but the gaps inbetween doing so are wide. See the attached debug trace and workflow pic’s. But I’ll take a look at implementing what you’ve outlined now.

I’ve exported the current test app here https://storage.googleapis.com/losant-exports/63ceebb322f10d3cdf2e050f/export-63ceebb322f10d3cdf2e050f-1674770646023-milesightPulseCounte.zip?GoogleAccessId=production-data-export%40structure-1104.iam.gserviceaccount.com&Expires=1675375446&Signature=Nd%2Bk24y2x8WkbxD%2FrAr3Ly2svfgS4p5b74HoJ55HDVP9YnY5qNXppvKSYs93rJ3kwBRZzhOgetfrBko5IPLT6zkgx8EdblRaPYLYKX1IumRKKQBOfODLKKFiX4%2Bbwm5TbX47PS28Z53Mi9xg6HvGpLj3FtR2BY1h0MJAWNpnzN5RduTVCjXe145ePjJpEeiRgjlGzdqK9zcbiOS%2FW3tmOy7K0fXAg47tPNmeyd5ibowERR04zxRGnSU2UMx2JBWXniANdrrrWIGSjz7B9qHrGikQkWsADvvAvXugofRaJIuMnQWboucni2L2N4%2BZXSQHlyjzZixZbZDVtYLZzUrFWQ%3D%3D&response-content-disposition=attachment%3B%20filename%3D"export-63ceebb322f10d3cdf2e050f-1674770646023-milesightPulseCounte.zip"