summaryrefslogtreecommitdiffstats
path: root/munin/boiler
diff options
context:
space:
mode:
Diffstat (limited to 'munin/boiler')
-rwxr-xr-xmunin/boiler552
1 files changed, 0 insertions, 552 deletions
diff --git a/munin/boiler b/munin/boiler
deleted file mode 100755
index 199893c..0000000
--- a/munin/boiler
+++ /dev/null
@@ -1,552 +0,0 @@
-#!/usr/bin/env perl
-
-use Net::Telnet;
-use Data::Dumper;
-
-#0 Status => 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-#17 Relative modulation level => 0
-#18 CH water pressure => 1.14453125
-#25 Boiler water temperature => 53
-#26 DHW temperature => 49
-#28 Return water temperature => 48.375
-#57 Max CH water setpoint => 80
-#80 Supply inlet temperature => 21.25
-#256 Status => 0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0
-#257 Control setpoint => 7
-#270 Maximum relative modulation level => 100
-#272 Room setpoint => 18
-#280 Room temperature => 26.7265625
-#312 DHW setpoint => 60
-
-my $ot_registers = {
- 0 => {
- format => ["flag16"],
- name => "Status",
- names => [
- '', '',
- '', '',
- '', '',
- 'DHW enabled', 'CH enabled',
- '', 'diagnostic indication',
- '', '',
- 'Flame', 'DHW active',
- 'CH active', 'fault'
- ],
- warnings => [
- undef, undef, undef, undef, undef, undef, undef, undef,
- undef, undef, undef, undef, undef, undef, undef, '1'
- ]
- },
- 1 => { format => ["f8.8"], name => "Control setpoint", units => 'C' },
- 2 => { format => [ "flag8", "u8" ], name => "Master configuration" },
- 3 => { format => [ "flag8", "u8" ], name => "Slave configuration" },
- 4 => { format => [ "u8", "u8" ], name => "Remote command" },
- 5 => { format => [ "flag8", "u8" ], name => "Application-specific flags" },
- 6 => { format => [ "flag8", "flag8" ], name => "Remote parameter flags" },
- 7 => { format => ["f8.8"], name => "Cooling control signal" },
- 8 => { format => ["f8.8"], name => "Control setpoint 2" },
- 9 => { format => ["f8.8"], name => "Remote override room setpoint" },
- 10 => { format => [ "u8", "nu" ], name => "Number of TSPs" },
- 11 => { format => [ "u8", "u8" ], name => "TSP setting" },
- 12 => { format => [ "u8", "nu" ], name => "Size of fault buffer" },
- 13 => { format => [ "u8", "u8" ], name => "Fault buffer entry" },
- 14 => {
- format => ["f8.8"],
- name => "Maximum relative modulation level",
- units => '%'
- },
- 15 => {
- format => [ "u8", "u8" ],
- name => "Boiler capacity and modulation limits"
- },
- 16 => { format => ["f8.8"], name => "Room setpoint", units => 'C' },
- 17 =>
- { format => ["f8.8"], name => "Relative modulation level", units => '%' },
- 18 => {
- format => ["f8.8"],
- name => "CH water pressure",
- units => 'bar',
- warning => '0.9:2.6',
- critical => '0.8:2.8'
- },
- 19 => { format => ["f8.8"], name => "DHW flow rate" },
- 20 => { format => ["time"], name => "Day of week and time of day" },
- 21 => { format => ["date"], name => "Date" },
- 22 => { format => ["u16"], name => "Year" },
- 23 => { format => ["f8.8"], name => "Room Setpoint CH2" },
- 24 => { format => ["f8.8"], name => "Room temperature", units => 'C' },
- 25 =>
- { format => ["f8.8"], name => "Boiler water temperature", units => 'C' },
- 26 => { format => ["f8.8"], name => "DHW temperature", units => 'C' },
- 27 => { format => ["f8.8"], name => "Outside temperature" },
- 28 =>
- { format => ["f8.8"], name => "Return water temperature", units => 'C' },
- 29 => { format => ["f8.8"], name => "Solar storage temperature" },
- 30 => { format => ["f8.8"], name => "Solar collector temperature" },
- 31 => { format => ["f8.8"], name => "Flow temperature CH2" },
- 32 => { format => ["f8.8"], name => "DHW2 temperature" },
- 33 => { format => ["s16"], name => "Exhaust temperature" },
- 34 => { format => ["f8.8"], name => "Boiler heat exchanger temperature" },
- 35 => { format => [ "u8", "u8" ], name => "Boiler fan speed and setpoint" },
- 48 => { format => [ "s8", "s8" ], name => "DHW setpoint boundaries" },
- 49 => { format => [ "s8", "s8" ], name => "Max CH setpoint boundaries" },
- 50 =>
- { format => [ "s8", "s8" ], name => "OTC heat curve ratio boundaries" },
- 51 => { format => [ "s8", "s8" ], name => "Remote parameter 4 boundaries" },
- 52 => { format => [ "s8", "s8" ], name => "Remote parameter 5 boundaries" },
- 53 => { format => [ "s8", "s8" ], name => "Remote parameter 6 boundaries" },
- 54 => { format => [ "s8", "s8" ], name => "Remote parameter 7 boundaries" },
- 55 => { format => [ "s8", "s8" ], name => "Remote parameter 8 boundaries" },
- 56 => { format => ["f8.8"], name => "DHW setpoint", units => 'C' },
- 57 => { format => ["f8.8"], name => "Max CH water setpoint", units => 'C' },
- 58 => { format => ["f8.8"], name => "OTC heat curve ratio" },
- 59 => { format => ["f8.8"], name => "Remote parameter 4" },
- 60 => { format => ["f8.8"], name => "Remote parameter 5" },
- 61 => { format => ["f8.8"], name => "Remote parameter 6" },
- 62 => { format => ["f8.8"], name => "Remote parameter 7" },
- 63 => { format => ["f8.8"], name => "Remote parameter 8" },
- 70 => { format => [ "flag8", "flag8" ], name => "Status V/H" },
- 71 => { format => [ "nu", "u8" ], name => "Control setpoint V/H" },
- 72 => { format => [ "flag8", "u8" ], name => "Fault flags/code V/H" },
- 73 => { format => ["u16"], name => "OEM diagnostic code V/H" },
- 74 => { format => [ "flag8", "u8" ], name => "Configuration/memberid V/H" },
- 75 => { format => ["f8.8"], name => "OpenTherm version V/H" },
- 76 => { format => [ "u8", "u8" ], name => "Product version V/H" },
- 77 => { format => [ "nu", "u8" ], name => "Relative ventilation" },
- 78 => { format => [ "u8", "u8" ], name => "Relative humidity exhaust air" },
- 79 => { format => ["u16"], name => "CO2 level exhaust air" },
- 80 =>
- { format => ["f8.8"], name => "Supply inlet temperature", units => 'C' },
- 81 => { format => ["f8.8"], name => "Supply outlet temperature" },
- 82 => { format => ["f8.8"], name => "Exhaust inlet temperature" },
- 83 => { format => ["f8.8"], name => "Exhaust outlet temperature" },
- 84 => { format => ["u16"], name => "Exhaust fan speed" },
- 85 => { format => ["u16"], name => "Inlet fan speed" },
- 86 => {
- format => [ "flag8", "flag8" ],
- name => "Remote parameter settings V/H"
- },
- 87 => { format => [ "u8", "nu" ], name => "Nominal ventilation value" },
- 88 => { format => [ "u8", "nu" ], name => "Number of TSPs V/H" },
- 89 => { format => [ "u8", "u8" ], name => "TSP setting V/H" },
- 90 => { format => [ "u8", "nu" ], name => "Size of fault buffer V/H" },
- 91 => { format => [ "u8", "u8" ], name => "Fault buffer entry V/H" },
- 100 => { format => [ "nu", "flag8" ], name => "Remote override function" },
- 101 => {
- format => [ "flag8", "flag8" ],
- name => "Solar storage mode and status"
- },
- 102 => { format => [ "flag8", "u8" ], name => "Solar storage fault flags" },
- 103 =>
- { format => [ "flag8", "u8" ], name => "Solar storage config/memberid" },
- 104 =>
- { format => [ "u8", "u8" ], name => "Solar storage product version" },
- 105 => { format => [ "u8", "nu" ], name => "Number of TSPs solar storage" },
- 106 => { format => [ "u8", "u8" ], name => "TSP setting solar storage" },
- 107 => {
- format => [ "u8", "u8" ],
- name => "Size of fault buffer solar storage"
- },
- 108 =>
- { format => [ "u8", "u8" ], name => "Fault buffer entry solar storage" },
- 113 => { format => ["u16"], name => "Unsuccessful burner starts" },
- 114 => { format => ["u16"], name => "Flame signal too low count" },
- 115 => { format => ["u16"], name => "OEM diagnostic code" },
- 116 => { format => ["u16"], name => "Burner starts" },
- 117 => { format => ["u16"], name => "CH pump starts" },
- 118 => { format => ["u16"], name => "DHW pump/valve starts" },
- 119 => { format => ["u16"], name => "DHW burner starts" },
- 120 => { format => ["u16"], name => "Burner operation hours" },
- 121 => { format => ["u16"], name => "CH pump operation hours" },
- 122 => { format => ["u16"], name => "DHW pump/valve operation hours" },
- 123 => { format => ["u16"], name => "DHW burner operation hours" },
- 124 => { format => ["f8.8"], name => "OpenTherm version Master" },
- 125 => { format => ["f8.8"], name => "OpenTherm version Slave" },
- 126 => { format => [ "u8", "u8" ], name => "Master product version" },
- 127 => { format => [ "u8", "u8" ], name => "Slave product version" },
-};
-
-my $ot_types = {
- 0 => "read data",
- 1 => "write data",
- 2 => "invalidate data",
- 3 => "unknown 0x3",
- 4 => "read ack",
- 5 => "write ack",
- 6 => "data invalid",
- 7 => "unknown 0x7"
-};
-
-sub decode($$$) {
- my ( $dataref, $string, $offset ) = @_;
- my $b0 = hex( substr( $string, 0, 2 ) );
-
- my $type = ( $b0 >> 4 ) & 7;
- my $id = hex( substr( $string, 2, 2 ) );
-
- my $data = pack( 'H4', substr( $string, 4, 4 ) );
- my $format = ["u16"];
-
- my $ret = {
- id => $id,
- fake_id => $id + $offset,
- type => $type,
- type_str => $ot_types->{$type},
- };
-
- my $bits = undef;
-
- if ( exists $ot_registers->{$id} ) {
- $ret->{id_str} = $ot_registers->{$id}->{name};
- $ret->{units} = $ot_registers->{$id}->{units};
- $format = $ot_registers->{$id}->{format};
- $bits = $ot_registers->{$id}->{names};
- }
-
- $ret->{format} = join( ',', @$format );
- $ret->{raw_hex} = substr( $string, 4, 4 );
- $ret->{raw} = $data;
-
- $ret->{values} = [];
- for my $f (@$format) {
-
- if ( $f eq "u16" ) {
- push @{ $ret->{values} }, unpack( 'S>', $data );
- $data = substr( $data, 2 );
- }
- elsif ( $f eq 's16' ) {
- push @{ $ret->{values} }, unpack( 's>', $data );
- $data = substr( $data, 2 );
- }
- elsif ( $f eq 'u8' ) {
- push @{ $ret->{values} }, unpack( 'C', $data );
- $data = substr( $data, 1 );
- }
- elsif ( $f eq 's8' ) {
- push @{ $ret->{values} }, unpack( 'c', $data );
- $data = substr( $data, 1 );
- }
- elsif ( $f eq 'nu' ) {
- $data = substr( $data, 1 );
- }
- elsif ( $f eq 'flag16' ) {
- push @{ $ret->{values} },
- ( unpack( "(A)*", unpack( "B16", $data ) ) );
- $data = substr( $data, 2 );
- }
- elsif ( $f eq 'flag8' ) {
- push @{ $ret->{values} },
- ( unpack( "(A)*", unpack( "B8", $data ) ) );
- $data = substr( $data, 1 );
- }
- elsif ( $f eq 'f8.8' ) {
- push @{ $ret->{values} }, unpack( 's>', $data ) / 256.0;
- }
-
- }
-
- $dataref->{ $id + $offset } = $ret;
-
- if ( defined $bits ) {
- my @vs = ( @{ $ret->{values} } );
- my $bit = scalar( @{ $ret->{values} } );
-
- for my $label (@$bits) {
- $bit--;
- my $v = shift(@vs);
- next unless length($label) > 0;
- my $key = sprintf( "%d.%d", $id + $offset, $bit );
- $ret = {};
-
- $ret->{id} = sprintf( "%d.%d", $id, $bit );
- $ret->{fake_id} = $key;
- $ret->{type} = $type;
- $ret->{type_str} = $ot_types->{$type};
- $ret->{id_str} = $label;
- $ret->{values} = [$v];
-
- $dataref->{$key} = $ret;
- }
- }
-
- return $ret;
-}
-
-sub thermostat($$) {
- my ( $string, $data ) = @_;
-
- return decode( $data, $string, 0x100 );
-
-}
-
-sub boiler($$) {
- my ( $string, $data ) = @_;
-
- return decode( $data, $string, 0x0 );
-
-}
-
-sub get_units($) {
- my $id = shift;
-
- if ( $id =~ /^\d+$/ ) {
- return '' unless exists $ot_registers->{$id};
- return '' unless exists $ot_registers->{$id}->{units};
- return $ot_registers->{$id}->{units};
- }
- elsif ( $id =~ /^(\d+)\.(\d+)$/ ) {
- my $base_id = $1;
- my $bit = $2;
-
- return '' unless exists $ot_registers->{$base_id};
- return '' unless exists $ot_registers->{$base_id}->{unitss};
-
- $bit =
- ( scalar( @{ $ot_registers->{$base_id}->{unitss} } ) - 1 ) - $bit;
- return $ot_registers->{$base_id}->{unitss}->[$bit];
- }
- else {
- return '';
- }
-}
-
-sub get_name($) {
- my $id = shift;
-
- if ( $id =~ /^\d+$/ ) {
- return "Unknown $id" unless exists $ot_registers->{$id};
- return $ot_registers->{$id}->{name};
- }
- elsif ( $id =~ /^(\d+)\.(\d+)$/ ) {
- my $base_id = $1;
- my $bit = $2;
-
- return "Unknown $id" unless exists $ot_registers->{$base_id};
- return "Unknown $id" unless exists $ot_registers->{$base_id}->{names};
-
- $bit = ( scalar( @{ $ot_registers->{$base_id}->{names} } ) - 1 ) - $bit;
- return $ot_registers->{$base_id}->{names}->[$bit];
- }
- else {
- return undef;
- }
-}
-
-sub get_warning($) {
- my $id = shift;
-
- if ( $id =~ /^\d+$/ ) {
- return "Unknown $id" unless exists $ot_registers->{$id};
- return $ot_registers->{$id}->{warning};
- }
- elsif ( $id =~ /^(\d+)\.(\d+)$/ ) {
- my $base_id = $1;
- my $bit = $2;
-
- return "Unknown $id" unless exists $ot_registers->{$base_id};
- return "Unknown $id" unless exists $ot_registers->{$base_id}->{names};
-
- $bit =
- ( scalar( @{ $ot_registers->{$base_id}->{warnings} } ) - 1 ) - $bit;
- return $ot_registers->{$base_id}->{warnings}->[$bit];
- }
- else {
- return undef;
- }
-}
-
-sub get_critical($) {
- my $id = shift;
-
- if ( $id =~ /^\d+$/ ) {
- return "Unknown $id" unless exists $ot_registers->{$id};
- return $ot_registers->{$id}->{crtitical};
- }
- elsif ( $id =~ /^(\d+)\.(\d+)$/ ) {
- my $base_id = $1;
- my $bit = $2;
-
- return "Unknown $id" unless exists $ot_registers->{$base_id};
- return "Unknown $id" unless exists $ot_registers->{$base_id}->{names};
-
- $bit =
- ( scalar( @{ $ot_registers->{$base_id}->{crtiticals} } ) - 1 ) - $bit;
- return $ot_registers->{$base_id}->{crtiticals}->[$bit];
- }
- else {
- return undef;
- }
-}
-
-sub maul($) {
- my $n = shift;
-
- $n =~ s/\s/_/g;
- return "boiler_" . lc($n);
-}
-
-my $report = [
- '0.0', '0.1', '0.2', '0.3', '0.6', '0.8', '0.9', '17', '18', '25',
- '26', '28', '57', '80', '257', '270', '272', '280', '312'
-];
-
-sub do_thing($) {
- my $t = shift;
-
- my $name = get_name($t);
- my $maul = maul($name);
- my $warning = get_warning($t);
- my $critical = get_critical($t);
-
- print "$maul.draw LINE2\n";
- print "$maul.type GAUGE\n";
- print "$maul.label $name\n";
-
- print "$maul.warning ", $warning, "\n" if $warning;
- print "$maul.critical ", $critical, "\n" if $critical;
-}
-
-sub do_units($) {
- my $want_unit = shift;
-
- for my $t (@$report) {
- my $unit = get_units($t);
-
- next unless $want_unit eq $unit;
- do_thing($t);
- }
-}
-
-sub do_values_units($$) {
- my ( $data, $wanted_units ) = @_;
-
- for my $t (@$report) {
- next unless exists $data->{$t};
-
- my $units = get_units($t);
- next unless $units eq $wanted_units;
-
- my $name = get_name($t);
- my $maul = maul($name);
-
- print $maul, ".value ", $data->{$t}->{values}->[0], "\n";
- }
-}
-
-my $wanted = { map { my $q = $_; $q =~ s/\..*$//; $q => 1 } @$report };
-my $n_wanted = scalar( keys %$wanted );
-
-for my $t ( keys %$ot_registers ) {
- $ot_registers->{ $t + 0x100 } = $ot_registers->{$t};
-}
-
-my @bits = split( /_+/, $0 );
-
-exit 0 unless scalar(@bits) > 1;
-
-my $host = $bits[1];
-
-$host =~ s/-//g;
-
-my $short_host = $host;
-
-$short_host =~ s/\..*$//;
-
-if ( $ARGV[0] eq 'config' ) {
-
- print "host_name ", $host, "\n";
-
- print "multigraph temperatures_${short_host}\n";
- print "graph_title Temperatures\n";
- print "graph_category boiler\n";
- print "graph_vlabel centigrade\n";
-
- do_units('C');
-
- print "multigraph pressures_${short_host}\n";
- print "graph_title Pressures\n";
- print "graph_category boiler\n";
- print "graph_vlabel bar\n";
-
- do_units('bar');
-
- print "multigraph modulation_${short_host}\n";
- print "graph_title Modulation\n";
- print "graph_category boiler\n";
- print "graph_vlabel bar\n";
-
- do_units('%');
-
- for my $t (@$report) {
- next if length( get_units($t) ) > 0;
-
- my $name = get_name($t);
- my $maul = maul($name);
-
- print "multigraph ${maul}_${short_host}\n";
- print "graph_title $name\n";
- print "graph_category boiler\n";
-
- do_thing($t);
-
- }
-
- exit(0);
-}
-
-my $telnet = new Net::Telnet(
- Timeout => 10,
- Telnetmode => 0,
- Binmode => 1,
- Host => $bits[1],
- Port => 2001
-);
-
-#$telnet->open($bits[1]);
-
-my $data = {};
-my $then = time;
-my $timeout = 60;
-
-while ( ($n_wanted) and ( ( time - $then ) < $timeout ) ) {
- my $line = $telnet->getline( Timeout => 1, Errmode => 'return' );
- my $id = -1;
-
- chomp $line;
- chomp $line;
-
- if ( $line =~ /^T/ ) {
- $id = thermostat( substr( $line, 1, 8 ), $data );
- }
- elsif ( $line =~ /^B/ ) {
- $id = boiler( substr( $line, 1, 8 ), $data );
- }
-
- if ( exists $wanted->{$id} ) {
- $n_wanted--;
- delete $wanted->{$id};
- }
-
-}
-
-print "multigraph temperatures_${short_host}\n";
-do_values_units( $data, 'C' );
-print "multigraph pressures_${short_host}\n";
-do_values_units( $data, 'bar' );
-print "multigraph modulation_${short_host}\n";
-do_values_units( $data, '%' );
-
-for my $t (@$report) {
- next unless exists $data->{$t};
-
- my $units = get_units($t);
- next unless $units eq '';
-
- my $name = get_name($t);
- my $maul = maul($name);
-
- print "multigraph ${maul}_${short_host}\n";
- print $maul, ".value ", $data->{$t}->{values}->[0], "\n";
-}
-
-exit(0);