Tabular and historical data – do you have any ideas on how to solve this?
I will explain what I mean using a use-case example – I would like to record the difference between electricity consumption and electricity production over the last 7 days to see if consumption has exceeded production.
My idea is as follows: create 7 (one for each day of the week) sets of 4 items:
a) at 00:01 – energy consumption status
b) at 00:01 – energy production status
c) at 11:59 p.m. - energy consumption status
d) at 11:59 p.m. - energy production status
but it adds up to a total of 28 items + 2 items summary for week summary = total of 30 items(!).
That’s a lot
Do you have any ideas for a different solution? Maybe using persistence would make it possible to implement my idea?
You probably only need one Item for the delta, since its daily value can be calculated once per day and also persisted (at say 23:59) and then the chart would show the time series for that.
You’ll need to supply whether you want a plain number or a quantity, which Item to sum the states for and the start and stop timestamps to sum between.
And then just post the result as an update to the Item you want to store the sum.
The energy meter displays cumulative consumption, so I can’t add up the total because the reading itself is a total. Even if I take a very short time interval—1 minute—it shows absurd values (like a log), and the meter logs consumption approximately every 3 minutes. So, the interval total doesn’t work, and it doesn’t work even over a very short time interval.
Previously I tried to use ‘persisted state’, but there was “String” instead of “Number” and I got error “.toFixed is not a function in” that’s why I published the post with ask to help me.
And now I changed it to the “Number” and it works perfectly!
Once again THANK YOU SO MUCH MY MASTER @rlkoshak of OH!
Recently I also wanted to display some historic data in a table. I wanted to display complete history of my precipitation measurement (monthly values + yearly sum).
Here is how I did it (for those that are interested):
I created a rule (plain javascript) that calculates same set of history data for items tagged with particular tag (#historic-data)
it obtains values back in time until there are no more values, using persistence and persistedState at the end of each month
it then serializes all values into JSON and save it to another item (same item name + “History” suffix)
then created widget that uses the JSON from history item and renders table for all measured values
I used that widget in expanded cell in my overview page. Currently just for Rain and Electricity consumption, but I plan to extend it.
Here is the javascript rule that gathers data into JSON
configuration: {}
triggers:
- id: "2"
label: Every 6 hours 2 minutes before midnight
configuration:
cronExpression: 49 58 23/6 * * ? *
type: timer.GenericCronTrigger
conditions: []
actions:
- inputs: {}
id: "1"
configuration:
type: application/javascript
script: >
/* Example of history data JSON
{
"years": [
2026,
2025,
...
],
"history": [
{
"year": 2026,
"values": {
"1": 297.1,
"2": 147.7,
"3": -1,
...
"12": -1,
"max": 297.0985,
"maxMonth": 1,
"min": 147.6747,
"minMonth": 2,
"sum": 444.8,
"avg": 222.4
}
},
...
]
}
*/
let calcHistoryForYear = (calcYear, calcIt) => {
let res = {
year: calcYear,
values: {}
};
let calcDate = time.toZDT(calcYear+'-01-01');
let sum = 0;
let cnt = 0;
for (let m = 1; m <= 12; m++) {
// folowing doesn't work for my very old historic data, so I used alternative way
//const st = calcIt.persistence.persistedState(calcDate.plusMonths(1).minusSeconds(1));
const st = calcIt.persistence.maximumBetween(calcDate.plusMonths(1).minusMinutes(65), calcDate.plusMonths(1));
const calcMonth = calcDate.monthValue();
let val = 0;
if (st) {
val = st.numericState;
}
if (calcDate.isAfter(time.toZDT())) {
val = -1;
} else {
cnt++;
sum += val;
if (val > res.values['max'] || m == 1) {
res.values['max'] = val;
res.values['maxMonth'] = calcMonth;
}
if (val < res.values['min'] || m == 1) {
res.values['min'] = val;
res.values['minMonth'] = calcMonth;
}
}
res.values[calcMonth] = Number(val.toFixed(1));
calcDate = calcDate.plusMonths(1);
}
res.values['sum'] = Number(sum.toFixed(1));
res.values['avg'] = cnt > 0 ? Number((sum / cnt).toFixed(1)) : 0;
return res;
};
// calculate complete history for one given item
let calcHistoryForItem = (calcItem, histItem) => {
let hist = {
years: [],
history: []
}
var calcYear = time.toZDT().year();
let cnt = 100; // safety counter to avoid infinite loop
while (cnt > 0) {
let result = calcHistoryForYear(calcYear, calcItem);
if (result.values['sum'] == 0) break;
hist.years.push(calcYear);
hist.history.push(result);
calcYear--;
cnt--;
}
console.log("Hisoric data for %s (stored to %s):\n %s", calcItem.name, histItem.name, JSON.stringify(hist));
histItem.postUpdate(JSON.stringify(hist));
}
// find all tagged items and check if history item exists, if yes then
calculate history data
items.getItemsByTag("historic-data").forEach((it)=>{
let histIt = items.getItem(it.name + "History", true);
if (histIt) {
calcHistoryForItem(it, histIt);
}
});
type: script.ScriptAction
I should notice that this rule works for item that contains measured values for one month (so it gets reset to zero at the beginning of each month). If you have item with continuous counter you would have to change the part that gets monthly value.
The approach you’re describing with 28 separate items would technically work, but you’re right, that’s a lot of overhead and maintenance. There’s definitely a cleaner way using persistence.
What you actually want is to capture two specific readings each day: the meter values at midnight and just before midnight. Then you can calculate the daily difference without storing every single day’s readings as separate items.
With persistence set up, you can simply query historic values. For example, you’d have one consumption item and one production item that get updated in real time. Then in your rule or script, you’d ask the persistence service for the state of those items at 00:01 and at 23:59. Subtract one from the other and you’ve got your daily totals.
Persistence is exactly the solution here. No need for dozens of items, just smart queries against your time series data.