Merge branch 'master' of mjesec.ffzg.hr:/git/vaillant-thermostat
[vaillant-thermostat] / serial.pl
1 #!/usr/bin/perl
2 use warnings;
3 use strict;
4 use Device::SerialPort;
5 use Data::Dump qw(dump);
6 use Time::HiRes qw(time);
7 use LWP::UserAgent;
8
9 my $read_len = 255;
10
11 # bottom serial on rpi
12 my $path = shift @ARGV || '/dev/serial/by-path/platform-1c14400.usb-usb-0:1:1.0-port0';
13
14 $|=1;
15
16 my $ua = LWP::UserAgent->new;
17
18 connect_again:
19
20 my $s = new Device::SerialPort( $path ) || die $!;
21 $s->baudrate(2400);
22 $s->databits(8); # 7
23 $s->parity('none');
24 $s->stopbits(1);
25 $s->handshake('none');
26 $s->read_char_time(2);
27 $s->read_const_time(3);
28
29 #$s->write('o');
30
31 my $t = time();
32
33 my $sym;
34
35 sub _mqtt_pub {
36         my ( $t, $m ) = @_;
37         my $cmd = "mosquitto_pub -h rpi2 -t '$t' -m '$m'";
38         #warn "# _mqtt_pub [$t] = [$m]\n";
39         #warn "## $cmd";
40         system $cmd;
41 }
42
43 while (1) {
44         my ($len, $string) = $s->read($read_len);
45         goto connect_again if ! defined $len;
46         my $ts = time();
47
48         if ( $len > 0 ) {
49                 my $hex = unpack('H*',$string);
50                 $hex =~ s/(..)/$1 /g;
51
52                 my $temp = `curl --silent rpi:3000/temp.txt`;
53                 $temp =~ s/\s+/ /gs;
54                 $temp =~ s/^\s+//;
55
56                 #printf "%s %2d  %s\n", time(), $len, $hex;
57                 printf "%8.4f %6.2f %2d  %s | %s\n", $ts, $ts - $t, $len, $hex, $temp;
58                 $t = time();
59
60                 if ( $hex =~ m/^.+aa fc 39 aa (.+)/ ) {
61                         my @l = split(/\s+/,$1);
62                         my @d = (
63                                 hex( $l[0] . $l[1] ),
64                                 hex( $l[3] . $l[4] ),
65                                 hex( $l[6] ),
66                                 hex( $l[12] ),
67                                 hex( $l[14] ), # * 300,
68                                 hex( $l[15] ), # * 400,
69                                 hex( $l[18] ),
70                         );
71
72                         _mqtt_pub "stat/boiler/" . chr(ord('a') + $_) => $d[$_] foreach 0 .. $#d;
73                 }
74
75                 my @v = split(/\s+/, $temp, 4);
76                 my @n = qw( DS18B20/temperature DHT22/temperature DHT22/humidity DHT22/errors );
77                    @n = qw( DS18B20/temperature DHT22/temperature DHT22/humidity DHT22/errors ) if $#v == 1; # no DS18B20
78                 foreach (@v) {
79                         _mqtt_pub "stat/boiler/" . shift(@n) => $_;
80                 }
81
82                 my $t = int( $ts * 1_000_000_000 );
83                 my @a = split(/ /, $hex);
84                 if ( $#a == 66 ) {
85                         my $measurement = "boiler " . join(',',
86                                 "o19=".hex( $a[19] ),
87                                 "o25=".hex( $a[35] . $a[36] ),
88                                 "o30=".hex( $a[38] . $a[39] ),
89                                 "o41=".hex( $a[41] ),
90                                 "o47=".hex( $a[47] ),
91                                 "o49=".hex( $a[49] ),
92                                 "o50=".hex( $a[50] ),
93                                 "o51=".hex( $a[51] ),
94                                 "o53=".hex( $a[53] ),
95                                 "ds18b20_temp=$v[0]", "dht22_temp=$v[1]", "dht22_hum=$v[2]"
96                         );
97                         my $response = $ua->post( "http://10.60.0.92:8086/write?db=rot13", Content => $measurement );
98                         chomp(my $content = $response->content());
99                         if ($response->is_success()) {
100                                 #warn "OK $content\n";
101                         } else {
102                                 warn "ERROR $content\n";
103                                 die $response->status_line;
104                         }
105                 }
106         }
107 }
108
109 $s->close;