Hi, is it possible to round data in PVM code?
I tried something like this but it doesn't compile:
round(.battery.level) ==> #battery.level
Hi, is it possible to round data in PVM code?
I tried something like this but it doesn't compile:
round(.battery.level) ==> #battery.level
TomD please use that code:
.battery.level ==> math.round ==> #battery.level
And here is a full list of math functions added:
math.round, math.floor, math.ceil, math.abs, math.acos, math.asin, math.atan, math.cos, math.exp, math.log, math.log2, math.log10, math.sin, math.sqrt, math.tan, math.trunc
All of them should be used in the same way as in the example above.
Awesome, it works. Thank you!
Follow up question. Is there a simpler way of rounding to 2 decimal places? I'm using this:
$x * 100 ==> math.round ==> this / 100 ==> $x
I tried asking the PVM generator which suggests:
$x ==> math.round[2] ==> $x
or
$x ==> format["%.2f", $x] ==> $x
However, neither work. I get a validation error when trying to save the code.
TomD
There is no dedicated function for that. You can use one of the following approaches:
optional .sensor.temperature ==> this * 100 ==> math.round ==> this / 100.0 ==> #sensor.temperature.round1
optional .sensor.temperature[number] ==> format["%.2f"] ==> %double ==> #sensor.temperature.round2
Thanks, not sure why the PVM generator suggested the 2 options that don't work?
Also, I assume the reason why you divide by 100.0 (instead of 100) is to ensure it doesn't do integer division when the numerator rounds to an integer? I tested and it seemed like as long as temperature is float,, math.round will produce a float, even if rounded to integer. If temperature is integer, the multiplication and integer division will still produce the correct result. But maybe you want to ensure the result is stored as float?
TomD Thanks, not sure why the PVM generator suggested the 2 options that don't work?
It's based on LLM, and unfortunately it just hallucinated info about argument availability for math.round
.
TomD Also, I assume the reason why you divide by 100.0 (instead of 100) is to ensure it doesn't do integer division when the numerator rounds to an integer?
Exactly. PVM internally stores and manages numeric values as int64_t
, uint64_t
or double
type (to work effectively with binary data). And division operator (/
) performs integer division if both of its operands are int64_t
or uint64_t
. That's why it's a good practice to explicitly specify zero fractional part in division expression.
And math.round
for integer values leaves value unchanged (nothing to round), which may lead to unexpected integer division.
But in most cases we speaking about PVM plugin code, which usually do something with message parameters. Message is a JSON object itself, and number
-type values in it stored as double
, thus you rarely face integer division at all.