root / plugins / amr / amr.pl @ 2ecac880
Historique | Voir | Annoter | Télécharger (5,4 ko)
| 1 | 9860b097 | Antoine Beaupré | #! /usr/bin/perl |
|---|---|---|---|
| 2 | |||
| 3 | # Copyright (C) 2014 Antoine Beaupré <anarcat@anarc.at> |
||
| 4 | # Copyright (C) 2008 Joey Schulze <joey@infodrom.org> |
||
| 5 | # |
||
| 6 | # This program is free software; you can redistribute it and/or modify |
||
| 7 | # it under the terms of the GNU General Public License as published by |
||
| 8 | # the Free Software Foundation; version 2 dated June, 1991. |
||
| 9 | # |
||
| 10 | # This program is distributed in the hope that it will be useful, |
||
| 11 | # but WITHOUT ANY WARRANTY; without even the implied warranty of |
||
| 12 | # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
||
| 13 | # GNU General Public License for more details. |
||
| 14 | # |
||
| 15 | # You should have received a copy of the GNU General Public License |
||
| 16 | # along with this program; if not, write to the Free Software |
||
| 17 | # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA. |
||
| 18 | |||
| 19 | # Munin plugin to monitor power usage in smart meters in the 900MHz ISM band |
||
| 20 | |||
| 21 | # Inspired by the postfix_mailstats plugin from munin-contrib |
||
| 22 | |||
| 23 | # Supported configuration: |
||
| 24 | # |
||
| 25 | # [amr] |
||
| 26 | # user root |
||
| 27 | # group adm |
||
| 28 | # env.logdir /var/log |
||
| 29 | # env.logfile rtlamr.log |
||
| 30 | |||
| 31 | use strict; |
||
| 32 | use warnings; |
||
| 33 | |||
| 34 | use Munin::Plugin; |
||
| 35 | |||
| 36 | my $LOGDIR = $ENV{'logdir'} || '/var/log';
|
||
| 37 | my $LOGFILE = $ENV{'logfile'} || 'rtlamr.log';
|
||
| 38 | my $unit = $ENV{'unit'} || 'J';
|
||
| 39 | if ($unit ne 'J' and $unit ne 'Wh') |
||
| 40 | {
|
||
| 41 | print "invalid unit, reverting to Joule"; |
||
| 42 | $unit = 'J'; |
||
| 43 | } |
||
| 44 | my $logfile = $LOGDIR .'/'. $LOGFILE; |
||
| 45 | |||
| 46 | # station id => power consumption (in kWh) |
||
| 47 | my %stations; |
||
| 48 | # number of signals sent per station |
||
| 49 | my %signals; |
||
| 50 | 2ecac880 | Antoine Beaupré | my $count; |
| 51 | 9860b097 | Antoine Beaupré | |
| 52 | sub autoconf |
||
| 53 | {
|
||
| 54 | if (-d $LOGDIR) {
|
||
| 55 | if (-f $logfile) {
|
||
| 56 | print "yes\n"; |
||
| 57 | exit 0; |
||
| 58 | } else {
|
||
| 59 | print "no (logfile not found)\n"; |
||
| 60 | } |
||
| 61 | } else {
|
||
| 62 | print "no (could not find logdir)\n"; |
||
| 63 | } |
||
| 64 | exit 1; |
||
| 65 | } |
||
| 66 | |||
| 67 | sub config |
||
| 68 | {
|
||
| 69 | print "multigraph amr_power\n"; |
||
| 70 | print "graph_title Power consumption\n"; |
||
| 71 | print "graph_args --base 1000 -l 0\n"; |
||
| 72 | print "graph_vlabel Watt\n"; |
||
| 73 | print "graph_total Total\n"; |
||
| 74 | print "graph_category AMR\n"; |
||
| 75 | |||
| 76 | 2ecac880 | Antoine Beaupré | $count = 0; |
| 77 | 9860b097 | Antoine Beaupré | foreach my $station (sort keys %stations) {
|
| 78 | my $name = clean_fieldname('station power ' . $station);
|
||
| 79 | 2ecac880 | Antoine Beaupré | printf "%s.label station %d\n", $name, $count; |
| 80 | 9860b097 | Antoine Beaupré | printf "%s.type COUNTER\n", $name; |
| 81 | 2ecac880 | Antoine Beaupré | if ($count++) {
|
| 82 | printf "%s.draw STACK\n", $name; |
||
| 83 | 9860b097 | Antoine Beaupré | } |
| 84 | else {
|
||
| 85 | 2ecac880 | Antoine Beaupré | printf "%s.draw AREA\n", $name; |
| 86 | 9860b097 | Antoine Beaupré | } |
| 87 | printf "%s.min 0\n", $name; |
||
| 88 | } |
||
| 89 | |||
| 90 | print "multigraph amr_meter\n"; |
||
| 91 | print "graph_title Meter reading\n"; |
||
| 92 | print "graph_args --base 1000 -l 0\n"; |
||
| 93 | print "graph_vlabel kWh\n"; |
||
| 94 | print "graph_scale no\n"; |
||
| 95 | print "graph_category AMR\n"; |
||
| 96 | |||
| 97 | 2ecac880 | Antoine Beaupré | $count = 0; |
| 98 | 9860b097 | Antoine Beaupré | foreach my $station (sort keys %stations) {
|
| 99 | my $name = clean_fieldname('station meter ' . $station);
|
||
| 100 | 2ecac880 | Antoine Beaupré | printf "%s.label station %d\n", $name, $count++; |
| 101 | 9860b097 | Antoine Beaupré | printf "%s.type GAUGE\n", $name; |
| 102 | printf "%s.min 0\n", $name; |
||
| 103 | } |
||
| 104 | |||
| 105 | print "multigraph amr_stations\n"; |
||
| 106 | print "graph_title Known AMR stations\n"; |
||
| 107 | print "graph_args --base 1000 -l 0\n"; |
||
| 108 | print "graph_vlabel stations\n"; |
||
| 109 | print "graph_category AMR\n"; |
||
| 110 | print "stations.label number of stations\n"; |
||
| 111 | |||
| 112 | print "multigraph amr_signals\n"; |
||
| 113 | print "graph_title Number of signals received\n"; |
||
| 114 | print "graph_args --base 1000 -l 0\n"; |
||
| 115 | print "graph_vlabel signals / \${graph_period}\n";
|
||
| 116 | print "graph_period minute\n"; |
||
| 117 | print "graph_category AMR\n"; |
||
| 118 | 2ecac880 | Antoine Beaupré | $count = 0; |
| 119 | 9860b097 | Antoine Beaupré | foreach my $station (sort keys %stations) {
|
| 120 | my $name = clean_fieldname('station signals ' . $station);
|
||
| 121 | 2ecac880 | Antoine Beaupré | printf "%s.label station %d\n", $name, $count++; |
| 122 | 9860b097 | Antoine Beaupré | printf "%s.type ABSOLUTE\n", $name; |
| 123 | } |
||
| 124 | |||
| 125 | exit 0; |
||
| 126 | } |
||
| 127 | |||
| 128 | sub parse |
||
| 129 | {
|
||
| 130 | my $logfile = shift; |
||
| 131 | my $pos = shift; |
||
| 132 | |||
| 133 | my ($log,$rotated) = tail_open $logfile, $pos; |
||
| 134 | |||
| 135 | while (<$log>) {
|
||
| 136 | # \d protects us against HTML injection here, be careful when changing |
||
| 137 | if (m,SCM:{ID:(\d+) +.* +Consumption: +(\d+) +,) {
|
||
| 138 | $stations{$1} = $2;
|
||
| 139 | $signals{$1}++;
|
||
| 140 | } |
||
| 141 | } |
||
| 142 | return tail_close $log; |
||
| 143 | } |
||
| 144 | |||
| 145 | need_multigraph(); |
||
| 146 | autoconf if $#ARGV > -1 && $ARGV[0] eq "autoconf"; |
||
| 147 | |||
| 148 | my @state_vector = restore_state; |
||
| 149 | my $pos = shift @state_vector || 0; |
||
| 150 | %stations = @state_vector; |
||
| 151 | |||
| 152 | $pos = parse $logfile, $pos; |
||
| 153 | if ($#ARGV > -1 && $ARGV[0] eq "config") {
|
||
| 154 | config; |
||
| 155 | # don't save position on config so next run will reparse it |
||
| 156 | } |
||
| 157 | else {
|
||
| 158 | # this may not scale so well with large graphs, and is useful only |
||
| 159 | # for debugging, when you want to run this repeatedly without |
||
| 160 | # loosing data |
||
| 161 | # this will also mean that stations that disappear will remain forever |
||
| 162 | save_state $pos, %stations; |
||
| 163 | } |
||
| 164 | |||
| 165 | print "multigraph amr_power\n"; |
||
| 166 | foreach my $station (sort keys %stations) {
|
||
| 167 | # the number from the counter is "Wh over 5 minutes", we want to |
||
| 168 | # give munin joules so he can generate watts by dividing by the period |
||
| 169 | # 1 Wh = W * 3600 s |
||
| 170 | # = 3600 s * J / s |
||
| 171 | # = 3.6 kJ |
||
| 172 | my $power = $stations{$station} * 3600;
|
||
| 173 | if ($unit eq 'Wh') {
|
||
| 174 | # since we want absolute, we'll multiply our result by 300, the assumed time period |
||
| 175 | $power = $stations{$station} * 300;
|
||
| 176 | } |
||
| 177 | printf "%s.value %d\n", clean_fieldname('station power ' . $station), $power;
|
||
| 178 | } |
||
| 179 | |||
| 180 | print "multigraph amr_meter\n"; |
||
| 181 | foreach my $station (sort keys %stations) {
|
||
| 182 | printf "%s.value %d\n", clean_fieldname('station meter ' . $station), $stations{$station};
|
||
| 183 | } |
||
| 184 | |||
| 185 | print "multigraph amr_stations\n"; |
||
| 186 | printf "stations.value %d\n", scalar keys %stations; |
||
| 187 | |||
| 188 | print "multigraph amr_signals\n"; |
||
| 189 | foreach my $station (sort keys %signals) {
|
||
| 190 | printf "%s.value %d\n", clean_fieldname('station signals ' . $station), $signals{$station};
|
||
| 191 | } |
