Projet

Général

Profil

Révision a806f7d8

IDa806f7d86d6a4b18022b288c2e3a9dc841b9b914
Parent 51ee702d
Enfant 97a0f791

Ajouté par Paul Saunders il y a presque 14 ans

Add support for CC02 devices

Thanks to David Edmondson <>, currentcost now supports CC02
devices. To make use of this make sure to set env.metertype to "CC02".

Voir les différences:

plugins/other/currentcost
37 37

  
38 38
This configuration section shows the defaults of the plugin:
39 39

  
40
        [currentcost]
41
        env.device		/dev/ttyUSB0
42
        env.baud		2400
43
        env.tick		6
44
        env.currency		£
45
        env.rate1		13.9
46
        env.rate1qty		900
47
        env.rate2		8.2
48
        env.nightrate		0
49
        env.nighthours		23:30-06:30
50
        env.standingcharge	0.0
40
    [currentcost]
41
    env.device          /dev/ttyUSB0
42
    env.baud            2400
43
    env.tick            6
44
    env.currency        £
45
    env.rate1           13.9
46
    nenv.rate1qty       900
47
    env.rate2           8.2
48
    env.nightrate       0
49
    env.nighthours      23:30-06:30
50
    env.standingcharge  0.0
51
    env.metertype       CC128
51 52

  
52 53
The configuration can be broken down into the following subsections:
53 54

  
......
101 102

  
102 103
The standing charge in hundreths of a C<env.currency> per month. If you do not have a standing charge, set this to 0.
103 104

  
105
=item env.metertype
106

  
107
The type of the meter. Currently "CC128" and "CC02" are supported.
108

  
104 109
=back
105 110

  
106 111
=head1 MAGIC MARKERS
107 112

  
108
 #%# family=manual contrib
109
 #%# capabilities=multigraph
113
 #%# family=auto contrib
114
 #%# capabilities=multigraph autoconf
110 115

  
111 116
=head1 AUTHOR
112 117

  
......
118 123
use warnings;
119 124
use utf8;
120 125
use Munin::Plugin;
121
use Data::Dump qw{pp};
122 126

  
123 127
need_multigraph();
124 128

  
125
my $device_node = $ENV{device} || "/dev/ttyUSB0";
126
my $baud_rate   = $ENV{baud}   || "2400";           # or 9600 or 57600
127
my $tick_rate   = $ENV{tick}   || "6";
128

  
129
my $device_node    = $ENV{device}         || "/dev/ttyUSB0";
130
my $baud_rate      = $ENV{baud}           || "2400";    # or 9600 or 57600
131
my $tick_rate      = $ENV{tick}           || "6";
129 132
# Tick_Rate is how long to consider data valid for (in seconds)
130 133

  
131 134
# Costs
132
my $currency  = $ENV{currency}  || "£";       # £ or €
133
my $rate1     = $ENV{rate1}     || "13.9";    # in pence/cents
134
my $rate1qty  = $ENV{rate1qty}  || "900";     # in kWh, 0 to use fixed rate2
135
my $rate2     = $ENV{rate2}     || "8.2";     # in pence/cents
136
my $nightrate = $ENV{nightrate} || "0";       # 0 = disabled
137
my $nighthours = $ENV{nighthours} || "23:30-06:30";
138
my $standingcharge = $ENV{standingcharge} || "0.0";    # pence/cents per month
135
my $currency       = $ENV{currency}       || "£";       # £ or €
136
my $rate1          = $ENV{rate1}          || "13.9";    # in pence/cents
137
my $rate1qty       = $ENV{rate1qty}       || "900";     # in kWh, 0 to use fixed rate2
138
my $rate2          = $ENV{rate2}          || "8.2";     # in pence/cents
139
my $nightrate      = $ENV{nightrate}      || "0";       # 0 = disabled
140
my $nighthours     = $ENV{nighthours}     || "23:30-06:30";
141
my $standingcharge = $ENV{standingcharge} || "0.0";     # pence/cents per month
142
my $metertype      = $ENV{metertype}      || "CC128";   # or "CC02"
143

  
144
my $MUNIN_DEBUG    = $ENV{MUNIN_DEBUG}    || 0;         # Set by munin-run
139 145

  
140 146
my $ret;
141 147
if ( !eval "require XML::Simple;" ) {
......
168 174
    if ( !@lastread
169 175
        or time >= Time::Local::timelocal(@lastread) + ($tick_rate) )
170 176
    {
177
        print "# Saving Data (Data is "
178
          . ( time - Time::Local::timelocal(@lastread) )
179
          . " seconds old)\n"
180
          if $MUNIN_DEBUG;
171 181
        @lastread = localtime(time);
172 182

  
173 183
        my @save_vector;
......
198 208
    {
199 209

  
200 210
        # Data is stale
211
        print "# Data is stale ("
212
          . ( time - Time::Local::timelocal(@lastread) )
213
          . " seconds). Re-reading device\n"
214
          if $MUNIN_DEBUG;
215

  
201 216
        eval {
202 217

  
203 218
            # Fetch the XML
204
            my @temparray = collect_cc128_data( $device_node, $baud_rate );
219
            my @temparray;
220
            if ( $metertype eq "CC128" ) {
221
                @temparray = collect_cc128_data( $device_node, $baud_rate );
222
            }
223
            elsif ( $metertype eq "CC02" ) {
224
                @temparray = collect_cc02_data( $device_node, $baud_rate );
225
            }
226
            else {
227
                die "Unknown meter type $metertype.";
228
            }
205 229

  
206
       # Read the time so we know whether to reset daily/monthly/yearly counters
230
            # Read the time so we know whether to reset
231
            #  daily/monthly/yearly counters
207 232
            my @now = localtime(time);
208 233
            my %is_new;
209 234
            $is_new{daily}   = ( $now[3] != $lastread[3] ) ? 1 : 0;
......
222 247
                            if ( $is_new{$period} ) {
223 248

  
224 249
                                # Start of a new period, reset the counter
250
                                print "# Start of a new $period period." .
251
							          " Resetting counter\n" if $MUNIN_DEBUG;
225 252
                                $temparray[$i]->{data}[$j]->{$period} = 0;
226 253
                            }
227 254
                            else {
......
266 293
    if (   $now_time >= $start_time
267 294
        or $now_time <= $stop_time )
268 295
    {
296
        print "# Night rate is ACTIVE\n" if $MUNIN_DEBUG;
269 297
        return 1;
270 298
    }
271 299
    else {
300
        print "# Night rate is enabled, but NOT active\n" if $MUNIN_DEBUG;
272 301
        return 0;
273 302
    }
274 303
}
......
279 308

  
280 309
=head2 Classic format
281 310

  
282
Note: I can't find an official spec for this format so, for now, this plugin doesn't support it.
311
As per L<http://cumbers.wordpress.com/2008/05/07/breakdown-of-currentcost-xml-output/>:
283 312

  
284 313
 <msg>
285 314
    <date>
286
        <dsb>00014</dsb> 
287
        <hr>14</hr> 
315
        <dsb>00014</dsb>        days since birth
316
        <hr>14</hr>             the time
288 317
        <min>07</min> 
289 318
        <sec>07</sec> 
290 319
    </date>
291 320
    <src>
292
        <name>CC02</name> 
293
        <id>03280</id> 
294
        <type>1</type> 
295
        <sver>0.07</sver> 
321
        <name>CC02</name>       name of this device
322
        <id>03280</id>          communication channel for device
323
        <type>1</type>          hardware version of the device
324
        <sver>0.07</sver>       software version
296 325
    </src>
297 326
    <ch1>
298
        <watts>00080</watts> 
327
        <watts>00080</watts>    value from the first channel clamp
299 328
    </ch1>
300 329
    <ch2>
301
        <watts>00000</watts> 
330
        <watts>00000</watts>    value from the second channel clamp
302 331
    </ch2>
303 332
    <ch3>
304
        <watts>00000</watts> 
333
        <watts>00000</watts>    value from the third channel clamp
305 334
    </ch3>
306
    <tmpr>28.8</tmpr> 
335
    <tmpr>28.8</tmpr>           current temperature (degrees celsius)
307 336
    <hist>
308 337
        <hrs>
309
            <h02>000.0</h02> 
338
            <h02>000.0</h02>    total Kwh used in 2 hour blocks
310 339
            <h04>000.1</h04> 
311 340
            <h06>000.1</h06> 
312 341
            <h08>000.0</h08> 
......
321 350
            <h26>000.0</h26> 
322 351
        </hrs>
323 352
        <days>
324
            <d01>0000</d01> 
353
            <d01>0000</d01>     total Kwh used per day(s)
325 354
            <d02>0000</d02> 
326 355
            <d03>0000</d03> 
327 356
            <d04>0000</d04> 
......
354 383
            <d31>0000</d31> 
355 384
        </days>
356 385
        <mths>
357
            <m01>0000</m01> 
386
            <m01>0000</m01>     total Kwh used per month(s)
358 387
            <m02>0000</m02> 
359 388
            <m03>0000</m03> 
360 389
            <m04>0000</m04> 
......
368 397
            <m12>0000</m12> 
369 398
        </mths>
370 399
        <yrs>
371
            <y1>0000000</y1> 
400
            <y1>0000000</y1>    total Kwh used per year(s)
372 401
            <y2>0000000</y2> 
373 402
            <y3>0000000</y3> 
374 403
            <y4>0000000</y4> 
......
419 448
    my %seen_sensors;
420 449

  
421 450
    while (<$ttydev>) {
451
        print "# Read from device: $_\n" if $MUNIN_DEBUG;
422 452
        if (m{(<msg>.*</msg>)}) {
423 453
            my $xmlref = XML::Simple::XMLin( $1, KeepRoot => 1 );
424 454

  
425 455
            my $sensor = $xmlref->{msg}->{sensor};
456
            print "# Parsing Sensor $sensor\n" if $MUNIN_DEBUG;
426 457
            next unless defined $sensor;
427 458
            if ( defined $seen_sensors{$sensor} ) {
428 459

  
429 460
                # We've seen this sensor before.
430 461
                # Time to stop reading data
462
                print "# Hello again, Sensor $sensor\n" if $MUNIN_DEBUG;
431 463
                last;
432 464
            }
433 465
            $seen_sensors{$sensor} = 1;
......
441 473
                    my $channel = $1;
442 474
                    my $unit = ( keys %{ $xmlref->{msg}->{"ch$channel"} } )[0];
443 475
                    my $val  = $xmlref->{msg}->{"ch$channel"}->{$unit};
476
                    print "# Channel $channel, Unit $unit, Value $val\n"
477
                      if $MUNIN_DEBUG;
478
                    push @temparr,
479
                      {
480
                        "channel" => $channel,
481
                        "unit"    => $unit,
482
                        "value"   => $val
483
                      };
484
                }
485
            }
486
            $temphash->{data} = \@temparr;
487

  
488
            push @cc_data_arr, $temphash;
489
        }
490
    }
491
    close($ttydev);
492

  
493
    return @cc_data_arr;
494
}
495

  
496
sub collect_cc02_data {
497
    # Function supplied by David Edmondson <dme@dme.org>
498

  
499
    # Read data from the serial port
500
    my ( $port, $baud ) = @_;
501

  
502
    my $tty = Device::SerialPort->new($port) || die "Can't open $port: $!";
503
    $tty->baudrate($baud)   || die "Can't set serial baudrate";
504
    $tty->parity("none")    || die "Can't set serial parity";
505
    $tty->databits(8)       || die "Can't set serial databits";
506
    $tty->handshake("none") || die "Can't set serial handshake";
507
    $tty->write_settings    || die "Can't set serial parameters";
508

  
509
    open( my $ttydev, "<", $port ) || die "Can't open $port: $?";
510

  
511
    my @cc_data_arr;
512

  
513
    while (<$ttydev>) {
514
        if (m{(<msg>.*</msg>)}) {
515
            my $xmlref = XML::Simple::XMLin( $1, KeepRoot => 1 );
516

  
517
            my $temphash;
518
            $temphash->{sensor} = 0;    # Only one sensor.
519
            $temphash->{temp}   = $xmlref->{msg}->{tmpr};
520
            my @temparr;
521
            foreach my $key ( keys %{ $xmlref->{msg} } ) {
522
                if ( $key =~ /ch(\d+)/ ) {
523
                    my $channel = $1;
524
                    my $unit = ( keys %{ $xmlref->{msg}->{"ch$channel"} } )[0];
525
                    my $val  = $xmlref->{msg}->{"ch$channel"}->{$unit};
444 526
                    push @temparr,
445 527
                      {
446 528
                        "channel" => $channel,
......
452 534
            $temphash->{data} = \@temparr;
453 535

  
454 536
            push @cc_data_arr, $temphash;
537

  
538
            last;
455 539
        }
456 540
    }
457 541
    close($ttydev);
......
475 559
            }
476 560
            elsif ( $unit != $key->{unit} ) {
477 561
                print STDERR
478
"Conflicting units ($unit and $key->{unit}) on sensor $datum->{sensor}";
562
"# Conflicting units ($unit and $key->{unit}) on sensor $datum->{sensor}";
479 563
            }
480 564
        }
481 565

  
......
512 596
${fieldname}_n.min 0
513 597
${fieldname}_t.cdef ${fieldname}_n,UN,${fieldname},${fieldname},IF,3600,TRENDNAN
514 598
EOF
515
                } else {
516
		    print "${fieldname}_t.cdef ${fieldname},3600,TRENDNAN\n";
517
		}
599
                }
600
                else {
601
                    print "${fieldname}_t.cdef ${fieldname},3600,TRENDNAN\n";
602
                }
518 603
            }
519 604

  
520 605
            # Output the Root cumulative graph
......
542 627
EOF
543 628
            }
544 629
            print "\n$confstr";
545
            print <<EOF; 
630
            print <<EOF;
546 631
fudge.label (fudge)
547 632
fudge.type GAUGE
548 633
fudge.graph yes

Formats disponibles : Unified diff