Daily Min / Max Values

I have a temperature probe feeding my emoncms instance with values.  What I am looking to do is create a display showing

maximum & minimum values.  Which is where I get stuck!  I modified the "average" subroutine in process_model.php to

create two new processes.  But then when I go to the input screen, I don't appear able to use them as it sequentially passes the output of one process to the next.  

So please help!   Any fiendishly simple or dastardly complex ideas are welcome! 

 

M

IanGibbons's picture

Re: Daily Min / Max Values

Hi,

 

I'm afraid I couldn't come up with a fiendishly simple way of doing this, so you'll have to settle for a complex one!

WARNING! This breaks the sequentiality by NOT passing on the previous value!

 

First of all, you'll have to edit the /Models/process_model.php and add some arrays within the get_process_list() function:

  $list[23] = array(
      _("Calculate Daily Min for Feed ID"),
    ProcessArg::VALUE,
    "daily_minimum",
    0,
    DataType::UNDEFINED
  );

  $list[24] = array(
      _("Calculate Daily Max for Feed ID"),
    ProcessArg::VALUE,
    "daily_maximum",
    0,
    DataType::UNDEFINED
  );

  $list[25] = array(
    _("Log to feed daily"),
    ProcessArg::FEEDID,
    "log_to_feed_daily",
    1,
    DataType::REALTIME
  );

 

In my case the highest $list[] number was 22 (I've added other processes) so I added the above starting at 23.

 

Then at the end of the same file add the following functions:

 

    // Get the minimum value for a feed for today
    function daily_minimum($feedid_passed_as_argument, $time_now, $value){
        list($start_time, $end_time) = get_start_and_end_times($time_now, "D");
        return feed_stats_minimum( $feedid_passed_as_argument, $start_time, $end_time );
    }

    // Get the maxiumum value for a feed for today
    function daily_maximum($feedid_passed_as_argument, $time_now, $value){
        list($start_time, $end_time) = get_start_and_end_times($time_now, "D");
        return feed_stats_maximum( $feedid_passed_as_argument, $start_time, $end_time );
    }

    // Log to the specified feed but use the calculated 
    // 'Daily' Time from get_start_and_end_times()
    function log_to_feed_daily($id, $time, $value)
    {
      list($start_time, $end_time) = get_start_and_end_times($time, "D");
      update_feed_data($id, $time, $start_time, $value);
      return $value;
    }

    //--- helper functions


    // Get the minimum value for a feed for a time range
    function feed_stats_minimum( $feedID, $start_time, $end_time ){
        $return = false;

        $sql = "SELECT MIN(`data`) as data_value FROM `feed_$feedID` 
               WHERE `time` >= $start_time AND `time` <= $end_time LIMIT 0,1;";

        $result = db_query($sql);
        while( $row = db_fetch_array($result) ){
            $return = $row['data_value'];
        }
        return $return;
    }

    // Get the maxium value for a feed for a time range
    function feed_stats_maximum( $feedID, $start_time, $end_time ){
        $return = false;

        $sql = "SELECT MAX(`data`) as data_value  FROM `feed_$feedID` 
            WHERE `time` >= $start_time AND `time` <= $end_time LIMIT 0,1;";

        $result = db_query($sql);
        while($row  = db_fetch_array($result) ){
            $return = $row['data_value'];
        }
        return $return;
    }

    // calculate start and end times based on the current time and a duration type
    function get_start_and_end_times($time_now, $duration_type){

        $start_time =0;
        $end_time    =0;

        switch($duration_type){
            case "H":    // hourly
                $start_time = mktime(date("H",$time_now), 0, 0, 
                    date("m",$time_now), date("d",$time_now), date("Y",$time_now));
                $end_time     = $start_time + 3600; //easy additio
                break;
            case "D":    // daily
                $start_time = mktime(0, 0, 0, 
                    date("m",$time_now), date("d",$time_now), date("Y",$time_now));
                $end_time     = $start_time + 86400; //easy addition
                break;
            case "M":    // monthly
                $start_time = mktime(0, 0, 0, date("m",$time_now),1, date("Y",$time_now));
                $end_time     = mktime(0, 0, 0, date("m",$start_time)+1,
                    date("d",$start_time), date("Y",$start_time)); // add 1 month
                $end_time     = mktime(0, 0, 0, date("m",$end_time),
                    date("d",$end_time)-1, date("Y",$end_time)); // take one day
                break;
            case "Y":    // yearly
                $start_time = mktime(0, 0, 0, 1,1, date("Y",$time_now));
                $end_time = mktime(0, 0, 0, date("m",$start_time),
                   date("d",$start_time), date("Y",$start_time)+1); // add 1 year
                $end_time = mktime(0, 0, 0, date("m",$end_time),
                    date("d",$end_time)-1, date("Y",$end_time)); // take one day
                break;
        }

        return Array( $start_time, $end_time );
    }

 

To use this you will need to know the feed id of the feed you want the minimum of.  Once you have this, goto the input process list and add a new entry of 'Calculate Daily Min for Feed ID' then enter the feed id.  Then add an entry with 'Log to feed daily' and create a new feed.

This new feed will have only one entry per day (for midnight) that has the minimum value for that day.

Same process for Maximum.

New functions for Hourly, Monthly and Yearly can be added with a $duration type of H, M or Y.  If you want other ranges, adjust the function get_start_and_end_times().

 

I have used the built in MySQL functions MIN() and MAX() for the calculations, other functions are available: http://dev.mysql.com/doc/refman/5.6/en/group-by-functions.html

 

I hope this all makes sense!

Ian

--

 

Robert Wall's picture

Re: Daily Min / Max Values

I've not tried this, but my thinking is:

If your Nanode base (presumably you have one or an equivalent with some intelligence) gets the internet time from  http://emoncms.org/time/   it knows when a day starts. It sees the temperatures as they go past, so it should be trivial to check for max and min and inject those into the data stream, and reset them at midnight (or whenever takes your fancy!). Your emoncms will see the extreme recorded up until that instant, which is pretty much how any min/max display works.

ukmoose's picture

Re: Daily Min / Max Values

Ian,  Many thanks for your brilliant help on this!  I've installed it and its working.

Robert, thanks for your suggestion too.  I suppose my thoughts were to do any "calculation" in one place so I hadn't thought of doing it on the nanode! 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.