//////////////////////////////////////////////////////////////////////////////////////////////////
rule “Energy consumption calculation”
//////////////////////////////////////////////////////////////////////////////////////////////////
when
Item Node_garage1 received update
then
var long currentTime = now.millis
if (LastUpdate != 0) {
var long timeElapsed = currentTime - LastUpdate
if (timeElapsed > 0) {
var Number power = Node_garage1.state as DecimalType
var Number energyConsumption = (power * timeElapsed) / 3600000 / 1000 // kWh
postUpdate(CumulativeEnergyConsumption, CumulativeEnergyConsumption.state as DecimalType + energyConsumption) //increment
}
}
LastUpdate = currentTime
end
and the values i’m getting are resulting in some long values… for example when i send a tweet with my current energy value at the end of a day, i get something like this…
I understand that i can limit the value in sitemaps, but how can i limit the value to 2 decimal places in the calculations? i would like to limit it as early on as possible to keep things simple, even if it reduces accuracy.
In general you typically don’t round the values until you display it or in this case send it to Twitter. So you will want to round it before sending it off but not during the calculations.
But since you didn’t provide that code where you do that I’ll provide the code for the function you did post. Floating point math accuracy is pretty horrible on computers beyond a certain point (maybe two decimal places) and premature rounding can cause an even faster accumulation of errors. Depending on how often this calculation is done you could be off by several digits.
One way to round is to use the DecimalFormat utility:
val java.text.DecimalFormat df = new java.text.DecimalFormat("#.##")
val Number roundedEnergyConsumption = Double.valueOf(dt.format(CumulativeEnergyConsumption.state as DecimalType + energyConsumption.doubleValue))
postUpdate(CumuativeEnergyConsumption, roundedEnergyConsumption)
Another is to use Math.round, though that is not always guaranteed to work given how computers actually calculate and store floating point numbers. Basically, the divide by 100 at the end may end up reintroducing more than two decimal places again.
val double rounded = java.lang.Math.round(100 * (CumulativeEnergyConsumption.state as DecimalType + energyConsumption))/100.0