RRDtool

104 views
Skip to first unread message

bart groot

unread,
Aug 21, 2016, 3:49:34 AM8/21/16
to OpenRemote
Ive been busy migrating from 2.1 to 2.6 
I decided to start from scratch, a lot of work but i am getting there!
I also made some nice graphs. One of them displays the power usage in my house.
But now i not only want to see this in a graph but i also want to display the last value from this graph in a sensor.
I guess this can be done with a fetch command but i don't have any idea how and where to do this.
Can anyone gets me started on this? below is the print from my rrd4j-config.xml. I would like to get the last value from the datasource wattage and display this in a sensor.

<?xml version="1.0" encoding="UTF-8"?>



  <rrdDB fileName="Stroom.rrd" step="300">
  <datasource name="Pulsen" type="DERIVE" heartbeat="600" />
<archive function="AVERAGE" xff="0.9" steps="1" rows="54400" />
  </rrdDB> 

 
  <rrd_graph_def name="Energie">
     <options>
         <vertical_label>WATT</vertical_label>
         <title>Stroomverbruik</title>
     </options>
     <datasources>
         <def>
             <name>Pulsen</name>
             <rrd>Stroom.rrd</rrd>
             <source>Pulsen</source>
             <cf>AVERAGE</cf>
         </def>
         <cdef>
             <name>wattage</name>
             <rpn>Pulsen,9600,*</rpn>
         </cdef>
     </datasources>
     <graph>
          <line>
             <datasource>wattage</datasource>
             <color>#9999FF</color>
             <legend>stroomverbruik</legend>
             <width>2</width>
         </line>
         <comment>kWh meter</comment>
     </graph>
 </rrd_graph_def>
 
</rrd4j>

Stuart Hanlon

unread,
Aug 21, 2016, 2:31:07 PM8/21/16
to OpenRemote
Hi Bart,

I'm not too familiar with how the RRD engine works, but surely the last value it has is the one it got from the OpenRemote Sensor?


So have you tried displaying that sensor?


(At least that's how I show current and accumulated Velbus energy data from a VMB7IN)

Cheers,

Stuart

bart groot

unread,
Aug 22, 2016, 8:55:13 AM8/22/16
to OpenRemote

Hi Stuart,

Thank you for youre reply. 
Its not quite that easy. I have the Emninent energy reader. This device only registers the pulses from the kWh meter .
I use the RRD engine to save the counter values but also to substract the previous value from the last value and convert this amount of pulses to total wattage per hour. The "Derive" function takes care of that. Before plotting the graph i also multiply these pulses per secound by 9600 to get the correct wattage.
Long story short the sensor only measures the amount of pulses from the kWh meter. The "wattage"variable is the value i would like to show.

It was the easyest way for me to convert the amount of pulses to current usage. (My electricitymeter gives 375 pulses when 1 kWh is used.) I read out the sensor every two minutes so when the difference between the last and teh previous reading is 375 my current usage is 1000Watts.

Hope this explains what i am trying to do here.

Bart

Stuart Hanlon

unread,
Aug 22, 2016, 11:04:48 PM8/22/16
to OpenRemote
Wow!

That's one complex way if getting a reading.


I really wish I could help you.


A Velbus input module could count the LED pulses and give you the answer, but they really doesn't help you right now.

Good luck,

Stuart

Richard Turner

unread,
Aug 23, 2016, 1:21:38 AM8/23/16
to OpenRemote
Hi Bart,

I'd use rules to achieve this: -

Convert pulses to watts
Push value into in memory (virtual) command
Create sensor to show this in memory command value
Configure RRD4J to log this sensor

Can create instantaneous power and KWh sensors and log both to RRD4J as well as show the values on you panels.

Rich

bart groot

unread,
Aug 23, 2016, 3:41:01 PM8/23/16
to OpenRemote

Hi Richard,

Thats exactly the way i started to do this. But, i can't seem to get this working. Sometimes after reboot it works but most of the time it does nothing, i just can't get it right. It probably has something to do with reading the last and the previous version.

This is the rule i made;


rule "write old value"
 timer (int: 00s 2m)
when
  $evt1: Event (source == "Pulsen")
then
  double newValue = Double.parseDouble($evt1.getValue().toString());
 execute.command("KWh",  String.format("%.0f", newValue));
end

rule  "heartbeat_every_2_minutes" 
  timer (int: 00s 2m)  when eval (true) then
   execute.command ("Pulsen");
end

rule "Totaal Verbruik"
timer (int: 00s 2m)
 when
  $evt: Event (source == "Pulsen") 
  $oldevt: Event (source == "meterstand")
then
  double newValue = Double.parseDouble($evt.getValue().toString());
  double oldValue = Double.parseDouble($oldevt.getValue().toString());
  double realtimeWatts = (newValue - oldValue)*30000/375;
  execute.command("Watt",  String.format("%.0f", realtimeWatts));
end
 

The RDD graph is always spot on and makes the correct calculations


Message has been deleted

Richard Turner

unread,
Aug 25, 2016, 5:35:56 AM8/25/16
to OpenRemote
Hi Bart,

To do this with rules use a custom fact to store the previous pulse value, something like this should work but I've not tested it: -

declare PulseCount
    value : Double
end

Then a rule to fire at startup: -

rule "initialise"
when
   eval(true)
then
    PulseCount counter = new PulseCount();
    counter.setValue(-1);
end

timer (int: 00s 2m)
rule "pulse update"
when
  $evt: Event (source == "Pulsen")
  and $counter:PulseCount()
then
  double newValue = Double.parseDouble($evt.getValue().toString());
  double oldValue = $counter.getValue();
  $counter.setValue(newValue);

  // Check if old value is initialised  
  if (oldValue < 0) {
    return;
  }

  // Do calculation
  double realtimeWatts = (newValue - oldValue)*30000/375;
  execute.command("Watt",  String.format("%.0f", realtimeWatts));
end

bart groot

unread,
Aug 26, 2016, 3:55:44 AM8/26/16
to OpenRemote
Hi Richard,

Thanks a lot for youre help. With my limited knowledge of java /drools i would never get this far. I ve been struggling many hours to get a rule that can do this!
I am going to test this tommorow and see if i can get this working.
 I let you know if i succeeded.

Bart

Michal Rutka

unread,
Aug 26, 2016, 4:08:24 AM8/26/16
to OpenRemote
Just remark about this rules. It will work in this example, however if you want to use the custom fact in other rule, or more precisely trigger other rules by its changes then the rules should be:

declare PulseCount
    value : Double
end

rule "initialise"
when
   eval(true)
then
    PulseCount counter = new PulseCount();
    counter.setValue(-1);
end

rule "pulse update"
no-loop true
timer (int: 00s 2m)
when
  $evt: Event (source == "Pulsen")
  and $counter:PulseCount()
then
  double newValue = Double.parseDouble($evt.getValue().toString());
  double oldValue = $counter.getValue();
  $counter.setValue(newValue);
  update($counter);

  // Check if old value is initialised  
  if (oldValue < 0) {
    return;
  }

  // Do calculation
  double realtimeWatts = (newValue - oldValue)*30000/375;
  execute.command("Watt",  String.format("%.0f", realtimeWatts));
end

// following rule would not be executed by the previous code
rule "second rule"
when
  PulseCount()
then
  // do something
end

bart groot

unread,
Aug 27, 2016, 5:07:08 AM8/27/16
to OpenRemote
Richard , Michal,

I put the new rule in my controller to see if all is working. Unfortunately there is one error in the new part of the rule and i don't now how to fix it.

Heres the part from the bootlog;

ERROR 2016-08-27 10:38:40,592 : Rule definition 'modeler_rules.drl' could not be deployed. See errors below.
ERROR 2016-08-27 10:38:40,593 : Rule Compilation error The method setValue(int) in the type PulseCount is not applicable for the arguments (double)
INFO 2016-08-27 10:38:40,714 : Started event processor : Drools Rule Engine
INFO 2016-08-27 10:38:40,786 : Started event processor : RRD4J Data Logger

i am googling to find some kind of drools for dummies to understand the basics of drools. I havent got a clue what to change now. Does this have something to do with the value from my Zwave counter ("Pulsen"). the counter has a negative value when i display the value in OR. at the the moment its  -1625712

Richard Turner

unread,
Aug 27, 2016, 5:09:26 AM8/27/16
to OpenRemote
Apologies, try: -

rule "initialise"
when
   eval(true)
then
    PulseCount counter = new PulseCount();
    counter.setValue(-1d);
end

bart groot

unread,
Aug 27, 2016, 7:12:25 AM8/27/16
to OpenRemote

Richard,

Thnx, there are no errors in the boot log anymore. But it still is not working. Is it correct that the "heartbeat" rule is there?
rule  "heartbeat_every_2_minutes" 
  timer (int: 00s 2m)  when eval (true) then
   execute.command ("Pulsen");
end

It seems that the rule is not firing, i put in an extra line to display the oldValue and newValue but they stay empty.

timer (int: 00s 2m)
rule "pulse update"
when
  $evt: Event (source == "Pulsen")
  $counter:PulseCount()
then
  double newValue = Double.parseDouble($evt.getValue().toString());
  double oldValue = $counter.getValue();
  $counter.setValue(newValue);
 execute.command("KWh",  String.format("%.0f", newValue));
 execute.command("wattage",  String.format("%.0f", oldValue));

Richard Turner

unread,
Aug 27, 2016, 7:23:55 AM8/27/16
to bart groot, OpenRemote

You shouldn't need the heartbeat rule, you should have a sensor called Pulsen and the sensor/protocol will be responsible for updating the pulse count.


--
You received this message because you are subscribed to the Google Groups "OpenRemote" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openremotecommunity+unsub...@googlegroups.com.
Visit this group at https://groups.google.com/group/openremotecommunity.
To view this discussion on the web visit https://groups.google.com/d/msgid/openremotecommunity/b02b1dec-d31e-49f0-bd6f-17efa801c91c%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

bart groot

unread,
Aug 27, 2016, 8:24:31 AM8/27/16
to OpenRemote, groot...@gmail.com

Ok. i understand. The problem with this eminent zwave energy meter reader is that it is not fully supported. Thats why i got the advice to poll the energy reader every 2 minutes.  I tried leaving the heartbeat out but did not receive any update from the sensor.

Richard Turner

unread,
Aug 27, 2016, 9:50:03 AM8/27/16
to OpenRemote, groot...@gmail.com
I'm not familiar with Z wave but that sounds a little limiting.

So you have a rule that fires off a 'send pulses' command (which according to your heartbeat rule the command is called 'Pulsen' also - ensure this command name is unique) to the z wave module; is there then another command to receive this value and link it to a sensor?

Provided that the sensor named 'Pulsen' has a value and that value changes then there is no reason why the rule would not fire. When you link the sensor to a label on your panel do you see the pulse value and does it change over time (obviously putting your heartbeat rule back in place to get the z wave module to broadcast its' value).

bart groot

unread,
Aug 27, 2016, 10:16:25 AM8/27/16
to OpenRemote
That's correct, the rule triggers a command Pulsen which is linked to a sensor named Pulsen as well. I made a label linked to this sensor so I can monitor if the data changes every two minutes, and it does! I did the same with oldValue en newValue, to monitor if there is any data written to these. But unfortunately they stay empty.
That's why I think the rule is not triggered.

Richard Turner

unread,
Aug 27, 2016, 10:28:20 AM8/27/16
to openremot...@googlegroups.com
I would remove the timer from the 'pulse update' rule then it will fire whenever the sensor value changes (which will only be every two minutes anyway due to your heartbeat rule): -

declare PulseCount
    value : Double
end

Then a rule to fire at startup: -

rule "initialise"
when
   eval(true)
then
    PulseCount counter = new PulseCount();
    counter.setValue(-1);
    insert(counter);
end

rule "pulse update"
when
  $evt: Event (source == "Pulsen")
  and $counter:PulseCount()
then
  double newValue = Double.parseDouble($evt.getValue().toString());
  double oldValue = $counter.getValue();
  $counter.setValue(newValue);

  // Check if old value is initialised  
  if (oldValue < 0) {
    return;
  }

  // Do calculation
  double realtimeWatts = (newValue - oldValue)*30000/375;
  execute.command("Watt",  String.format("%.0f", realtimeWatts));
end


You can always put: -

System.out.println("WRITE SOME TEXT");

In your rule body which will be written to console window if/when it triggers (useful for debugging).

bart groot

unread,
Aug 27, 2016, 2:17:41 PM8/27/16
to OpenRemote

 Hurray, the rule works! Big Thank You for all the tips and tricks and off course a nice working rule!!
I did a step by step debug (thanks for the WRITE SOME TEXT) tip!  Somewhere down the line i missed a line (   insert(counter); was missing). After that the rule finally fired but did not get past the // Check if old value is initialized line. For some reason the output from "Pulsen" is a negative value so oldValue will always stay < 0.  so i changed the initialisation to 0.
This is the working rule;

rule  "heartbeat_every_2_minutes" 
  timer (int: 00s 2m)  when eval (true) then
  execute.command ("Pulsen");
end

declare PulseCount
    value : Double
end

rule "initialise"
when
   eval (true)
then
    PulseCount counter = new PulseCount();
    counter.setValue(0d);
    insert(counter);
end

rule "pulse update"
no-loop true
when
  $evt: Event (source == "Pulsen")
  and $counter:PulseCount()
then
  double newValue = Double.parseDouble($evt.getValue().toString());
  double oldValue = $counter.getValue();
  $counter.setValue(newValue);
  update($counter);
  execute.command("KWh",  String.format("%.0f", newValue));
  execute.command("oldval",  String.format("%.0f", oldValue));
// Check if old value is initialised  
  if (oldValue == 0) { return; }

Richard Turner

unread,
Aug 30, 2016, 3:26:27 AM8/30/16
to OpenRemote

Obvious thing I missed off was to insert the fact after creating it: -

rule "initialise"

when
   eval(true)
then
    PulseCount counter = new PulseCount();
    counter.setValue(-1);
    insert(counter);

end

Rich


--
You received this message because you are subscribed to the Google Groups "OpenRemote" group.
To unsubscribe from this group and stop receiving emails from it, send an email to openremotecommunity+unsubscribe...@googlegroups.com.
Reply all
Reply to author
Forward
0 new messages