'Logger settings', 'description' => 'Configure settings for logging metering values.', 'page callback' => 'drupal_get_form', 'page arguments' => array('_logger_admin_settings'), 'access arguments' => array('administer site configuration'), ); $items['logger'] = array( 'title' => 'your dashboard', // isn't printed as title on the page, therefore resort to drupal_set_title (t('your ecological dashboard')) in ecology_dashboard; 'description' => 'Configure settings for logging metering values.', 'page callback' => '_logger_dashboard', //takes the callback from the MENU_DEFAULT_LOCAL_TASK -> lightest level-two menu 'page arguments' => array('electricity', 'main', 'hour'), 'access callback' => TRUE, 'type' => MENU_CALLBACK, ); $items['logger/add'] = array( 'title' => 'add this user to the chart', 'page callback' => '_logger_add', 'access arguments' => array('logger'), 'type' => MENU_CALLBACK, ); $items['logger/remove'] = array( 'title' => 'remove this user from the chart', 'page callback' => '_logger_remove', 'access arguments' => array('logger'), 'type' => MENU_CALLBACK, ); $items['logger/unit'] = array( 'title' => 'change the unit', 'page callback' => '_logger_unit', 'access arguments' => array('logger'), 'type' => MENU_CALLBACK, ); $items['logger/electricity'] = array( 'title' => 'electricity', // 'page callback' => '_logger_dashboard', // 'page arguments' => array('electricity', 'main', 'hour'), 'access callback' => TRUE, 'type' => MENU_DEFAULT_LOCAL_TASK, ); /** $items['logger/water'] = array( 'title' => 'water', 'page callback' => '_logger_dashboard', 'page arguments' => array('water', 'main', 'hour'), 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, ); $items['logger/gas'] = array( 'title' => 'gas', 'page callback' => '_logger_dashboard', 'page arguments' => array('gas', 'main', 'hour'), 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, ); **/ $items['logger/electricity/hour'] = array( 'title' => 'hour', 'page callback' => '_logger_dashboard', 'page arguments' => array('electricity', 'main', 'hour'), 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, 'weight' => 0, ); $items['logger/electricity/day'] = array( 'title' => 'day', 'page callback' => '_logger_dashboard', 'page arguments' => array('electricity', 'main', 'day'), 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, 'weight' => 1, ); $items['logger/electricity/month'] = array( 'title' => 'month', 'page callback' => '_logger_dashboard', 'page arguments' => array('electricity', 'main', 'month'), 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, 'weight' => 2, ); $items['logger/electricity/year'] = array( 'title' => 'year', 'page callback' => '_logger_dashboard', 'page arguments' => array('electricity', 'main', 'year'), 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, 'weight' => 3, ); $items['logger/electricity/night'] = array( 'title' => 'night', 'page callback' => '_logger_dashboard', 'page arguments' => array('electricity', 'main', 'night'), 'access callback' => TRUE, 'type' => MENU_LOCAL_TASK, 'weight' => 4, ); return $items; } /** * Callback functions registered in the logger_menu section */ function _logger_dashboard($type, $function, $interval) { // watchdog('dashboard', 'arguments: %type, %function, %interval', array('%type' => $type, '%function' => $function, '%interval' => $interval), WATCHDOG_DEBUG); if (user_access('logger')) { drupal_set_title(t('your dashboard')); global $user; } else { //show users who don't have 'logger' permissions icrarus'es chart drupal_set_title(t("a Fluksonian's dashboard")); $user = new stdClass(); $user->uid = 1; $user->name = 'icarus75'; $user->timezone = '3600'; } $root_path = drupal_get_path('module', 'logger'); $graph_path = $root_path .'/graphs/'. $interval .'/'; $pngid = md5(uniqid()); //generate random numbers for the png chart so that the browser doesn't use the cached one, use cron to clean up the dir hourly switch ($interval) { case 'hour': $data_path = $root_path .'/data/base/'; $start = 'end-1h'; break; case 'day': $data_path = $root_path .'/data/base/'; $start = 'end-1d'; break; case 'month': $data_path = $root_path .'/data/base/'; $start = 'end-60d'; break; case 'year': $data_path = $root_path .'/data/base/'; $start = 'end-1y'; break; case 'night': $data_path = $root_path .'/data/night/'; $start = 'end-60d'; break; } $meter = db_fetch_object(db_query("SELECT meter, unit FROM {logger_meters} WHERE uid = %d AND type = '%s' AND function = '%s'", $user->uid, $type, $function)); switch ($type) { case 'electricity': switch ($meter->unit) { case 'watt': $meter->factor = 3600; // 1Wh/s = 3600 W break; case 'kwh': $meter->unit = 'kWh/year'; $meter->factor = 31536; break; case 'eur': $meter->unit = 'euro/year'; $meter->factor = 5361.12; break; } } $color = array(RED, BLUE, GREEN, YELLOW, PURPLE); $string->def = ' DEF:data0='. $data_path . $meter->meter .'.rrd:meter:AVERAGE CDEF:meter0=data0,'. $meter->factor .',* VDEF:min0=meter0,MINIMUM VDEF:max0=meter0,MAXIMUM VDEF:avg0=meter0,AVERAGE VDEF:last0=meter0,LAST'; $string->line = ' COMMENT:"\s" LINE1:meter0#'. $color[0] .':'.'"'. substr($user->name.' ', 0, 15) .'"'.' GPRINT:min0:"min\:%5.0lf" GPRINT:max0:"\tmax\:%5.0lf" GPRINT:avg0:"\tavg\:%5.0lf" GPRINT:last0:"\tlast\:%5.0lf\l"'; if (user_access('logger') || user_access('staff')) { //allow Veerle to watch the graphs $result = db_query("SELECT u.name, lm.meter FROM (({users} u INNER JOIN {user_relationships} ur ON u.uid = ur.requestee_id) INNER JOIN {user_relationship_types} urt ON ur.rtid = urt.rtid) INNER JOIN {logger_meters} lm ON u.uid = lm.uid WHERE ur.requester_id = %d AND urt.name = '%s' AND type = '%s' AND function = '%s' ORDER BY ur.rid", $user->uid, 'subscription', $type, $function); $i = 0; while ($subscription = db_fetch_object($result)) { $i += 1; // print_r($subscription); $string->def .= ' DEF:data'. $i .'='. $data_path . $subscription->meter .'.rrd:meter:AVERAGE CDEF:meter'. $i .'=data'. $i .','. $meter->factor .',* VDEF:min'. $i .'=meter'. $i .',MINIMUM VDEF:max'. $i .'=meter'. $i .',MAXIMUM VDEF:avg'. $i .'=meter'. $i .',AVERAGE VDEF:last'. $i .'=meter'. $i .',LAST'; $string->line .= ' LINE1:meter'. $i .'#'. $color[$i] .':'.'"'. substr($subscription->name.' ', 0, 15) .'"'.' GPRINT:min'. $i .':"min\:%5.0lf" GPRINT:max'. $i .':"\tmax\:%5.0lf" GPRINT:avg'. $i .':"\tavg\:%5.0lf" GPRINT:last'. $i .':"\tlast\:%5.0lf\l"'; } } //construct the TZ=GMT-02:00 format from the $user->timezone object updated by the autotimezone module if ($user->timezone >= 0) $TZ = 'TZ="GMT-'; else $TZ = 'TZ="GMT+'; $TZ .= gmdate('h:i', abs($user->timezone)) .'" '; //insert the TZ prior to launching rrdtool to obtain a proper time conversion $command = $TZ . $root_path .'/rrdtool graph '. $graph_path . $pngid .'.png -s '. $start .' --vertical-label '. $meter->unit .' --lower-limit 0 -w 500 -h 350 -E -X 0 --font LEGEND:8:'; $command .= $string->def; $command .= $string->line; exec($command, $output, $return_var); // watchdog('dashboard', 'arguments: %command ++ %output ++ %return_var', array('%command' => $command, '%output' => serialize($output), '%return_var' => $return_var), WATCHDOG_DEBUG); return theme('chart', $graph_path . $pngid .'.png'); } function _logger_add($uid) { global $user; $rtid = db_result(db_query("SELECT rtid FROM {user_relationship_types} WHERE name = '%s'", 'subscription')); $result = db_fetch_array(db_query("SELECT COUNT(rid), MAX(rid) FROM {user_relationships} WHERE requester_id = %d AND rtid = %d GROUP BY rtid", $user->uid, $rtid)); // max subscriptions = 4 if ($result['COUNT(rid)'] < 4) { user_relationships_request_relationship($user->uid, $uid, $rtid, TRUE); } else { //check whether the requested relationship doesn't already exist if (!db_result(db_query("SELECT rid FROM {user_relationships} WHERE requester_id = %d AND requestee_id = %d AND rtid = %d", $user->uid, $uid, $rtid))) { // if not, delete the most recently added relationship and replace it with the newly selected one db_query("DELETE FROM {user_relationships} WHERE rid = %d", $result['MAX(rid)']); user_relationships_request_relationship($user->uid, $uid, $rtid, TRUE); } } _logger_cache_clear('subscriptions'); $destination = drupal_get_destination(); drupal_goto($destination); } function _logger_remove($rid) { global $user; // check whether the to-be-deleted relationship was created by the same user if ($user->uid == db_result(db_query("SELECT requester_id FROM {user_relationships} WHERE rid = %d", $rid))) { db_query("DELETE FROM {user_relationships} WHERE rid = %d", $rid); } else { watchdog('relationships', 'attempt to delete rid %rid by non-authorized user %uid', array('%rid' => $rid, '%uid' => $user->uid), WATCHDOG_ERROR); } _logger_cache_clear('subscriptions'); $destination = drupal_get_destination(); drupal_goto($destination); } function _logger_unit($unit) { // TODO : include security checks global $user; // hardcoded type and function db_query("UPDATE {logger_meters} SET unit = '%s' WHERE uid = %d AND type = '%s' AND function = '%s'", $unit, $user->uid, 'electricity', 'main'); _logger_cache_clear('unit'); $destination = drupal_get_destination(); drupal_goto($destination); } /** * Clear the specific (per user) cache entry in the {cache_block} table */ function _logger_cache_clear($delta) { global $theme; //the theme variable isn't set on these callbacks so force it $theme = 'flukso'; $block = db_fetch_object(db_query("SELECT * FROM {blocks} WHERE module = '%s' AND delta = '%s' AND theme = '%s'", 'logger', $delta, 'flukso')); $cid = _block_get_cache_id($block); // prevent the whole chache_block being cleared when _block_get_cache_id returns an empty string (e.g. uid = 1) if ($cid != '') cache_clear_all($cid, 'cache_block'); //watchdog('block_cache', '%cid | %cache', array('%cid' => $cid, '%cache' => variable_get('block_cache', 100)), WATCHDOG_DEBUG); } /** * Implementation of hook_user() for logger * Flush the fluksonians block entries in the block cache */ function logger_user($op) { switch($op) { // new user is being inserted into the database case 'insert': // flush the fluksonians block entries cache_clear_all('logger:fluksonians', 'cache_block', TRUE); break; } } /** * Implementation of hook_theme() for logger */ function logger_theme() { return array( 'chart' => array( 'arguments' => array('chart' => NULL), ), 'logger_item_list' => array( 'arguments' => array('items' => NULL, 'title' => NULL), ), ); } /** * Theming the chart */ function theme_chart($chart) { $output .= '
'; return $output; } /** * Implementation of hook_block() for logger * Adds two blocks to the logger pages for (de-)selecting users and * another one for selecting the desired unit */ function logger_block($op = 'list', $delta = 0, $edit = array()) { global $user; switch ($op) { case 'list': $blocks['subscriptions']['info'] = t('Subscriptions'); $blocks['subscriptions']['status'] = TRUE; $blocks['subscriptions']['region'] = 'right'; $blocks['subscriptions']['weight'] = 0; $blocks['subscriptions']['pages'] = 'logger