Author Topic: Trick Your Bridge and Gather The Data  (Read 1565 times)

0 Members and 1 Guest are viewing this topic.

Offline thefuzz4

  • Member
  • *
  • Posts: 4
Trick Your Bridge and Gather The Data
« on: February 18, 2016, 01:30:29 AM »
Ok so after several phone calls back and forth with Acurite the final solution for me was to plug my bridge directly into my cable modem in order for my bridge to be happy.  However I was not happy with this and thus began my quest to hack the crap out of this thing using George's technique coupled along with some other stuff.

So this was my issue.  I work in IT so naturally I have quite the robust network here at my house.  I am using the Sophos UTM for a firewall here at home.  I told the firewall to assign a specific IP to the bridge so I always know what its IP is.  The bridge wasn't happy so I then told the FW to now allow all outbound traffic from the bridge to wherever it wants to go.  This worked great for about 3 weeks then all of sudden the bridge stopped reporting and went into an endless reboot cycle.  So I thought I had a dead bridge.  After talking with support I decided against everything IT holy to plug the damn thing in, in front of my FW and viola it started to work grrrrr

Then I found this http://moderntoil.com/?p=794
That got me to thinking along with George's technique of forwarding the data

So this is what I did.  I told my firewall hey for www.acu-link.com give it an internal IP instead of letting it call the mother ship.

Then I tried to use George's code and while it did its thing by capturing the packets just fine on my CentOS box I had issues with getting weewx to work right with it.

So then I found this site

http://homeautomaton.blogspot.com/

And bingo now we were getting somewhere using that and weewx 2.7 can't use the latest and greatest weewx since there needs to be some code changes and well I'm no developer so I'm not exactly sure what the changes are needed in order to make this work.

But alas since I don't have 2 nic's in my current VM where I'm sending the data to and I well I really don't feel like setting up a new vlan just for the bridge and then bridging two nics together (I know I'm lazy)  so instead I present you with this code

Code: [Select]
#!/usr/bin/perl

# Copyright 2014 by Kris Benson
# Based on ipwx tool from George D. Nincehelser

#########################
# Settings

# at 690m AMSL, it seems that 1195 is about right for correction
# 1195 = 119.5 mbar
$barocorrection = 2310;

$dropfile = "/share/weather/wxdata2";

$verbose = 1;

$macaddr = '24C86E0482B2';
$sensor1 = '02907';     # 5-in-1
$sensor2 = '01174';     # tower
$sensor3 = '01438';     # upstairs

#########################

$temp1          = '9999';
$humid1         = '9999';
$temp2          = '9999';
$humid2         = '9999';
$temp3          = '9999';
$humid3         = '9999';
$windspeed      = '9999';
$winddir        = '9999';
$rainfall       = '9999';
$raintotal      = '9999';
$pressure       = '9999';
$nestinfo       = '9999';
$battery1       = '9999';
$battery2       = '9999';
$battery3       = '9999';
$rssi1          = '9999';
$rssi2          = '9999';
$rssi3          = '9999';

open(TCPDUMP, "-|", "/usr/sbin/tcpdump -A -n -p -i ens32 -s0 -w - tcp dst port 80 2>/dev/null | /usr/bin/stdbuf -oL /usr/bin/strings -n8")
        or die "can't open tcpdump: $!";
#chomp $line;
while ($line = <TCPDUMP>) {
  if($line =~ /id=$macaddr/) {
    if($line =~ /sensor=$sensor1/) {
      my $curl = "curl -d \"$line\" http://acu-link.com/messages/";
      #print $curl;
      `$curl`;
      # 5-in-1
      #
      # id=24C86E014F4C&sensor=01086&mt=5N1x31&windspeed=A001660000&winddir=6&rainfall=A0000000&battery=normal&rssi=2
      # id=24C86E014F4C&sensor=01086&mt=5N1x38&windspeed=A003270000&humidity=A0480&temperature=A024222222&battery=normal&rssi=2
      #
      # two different data lines
      # may have
      # windspeed, winddir, rainfall, battery and rssi
      # or
      # windspeed, humidity, temperature, battery and rssi
      if($line =~ /windspeed=A(\d+)&winddir=([^&]+)&rainfall=A(\d+)&battery=([^&]+)&rssi=(\d{1})/) {
        # wind speed is in 100's of mm/s - convert to m/s
        #$windspeed      =       $1 A/ 1000000;
        $index = index ($line, 'windspeed');
        if ($index != -1)
        {
          $wind_frag = substr $line, $index + 11, 5;
          $windspeed = sprintf ("%.0f", $wind_frag / 44.7);
        }
        # see below for decoding
        $winddir_l      =       $2;

        # rainfall is in thousands of mm
        $rainfall       =       $3 / 1000;
        $battery1       =       $4;
        $rssi1          =       $5;

        # Wind direction is reported as a single hex digit
        # Seems to be using a non-standard Gray Code
        if    ($winddir_l eq '5' ) { $winddir = 0 }
        elsif ($winddir_l eq '7' ) { $winddir = 22.5 }
        elsif ($winddir_l eq '3' ) { $winddir = 45 }
        elsif ($winddir_l eq '1' ) { $winddir = 67.5 }
        elsif ($winddir_l eq '9' ) { $winddir = 90 }
        elsif ($winddir_l eq 'B' ) { $winddir = 112.5 }
        elsif ($winddir_l eq 'F' ) { $winddir = 135 }
        elsif ($winddir_l eq 'D' ) { $winddir = 157.5 }
        elsif ($winddir_l eq 'C' ) { $winddir = 180 }
        elsif ($winddir_l eq 'E' ) { $winddir = 202.5 }
        elsif ($winddir_l eq 'A' ) { $winddir = 225 }
        elsif ($winddir_l eq '8' ) { $winddir = 247.5 }
        elsif ($winddir_l eq '0' ) { $winddir = 270 }
        elsif ($winddir_l eq '2' ) { $winddir = 292.5 }
        elsif ($winddir_l eq '6' ) { $winddir = 315 }
        elsif ($winddir_l eq '4' ) { $winddir = 337.5 }
      } elsif ($line =~ /windspeed=A(\d+)&humidity=A(\d+)&temperature=A(\d+)&battery=([^&]+)&rssi=(\d{1})/) {
        # wind speed is in 100's of mm/s - convert to m/s
        #$windspeed      =       $1 / 1000000;
        $index = index ($line, 'windspeed');
        if ($index != -1)
        {
          $wind_frag = substr $line, $index + 11, 5;
          $windspeed = sprintf ("%.0f", $wind_frag / 44.7);
        }
        $humid1         =       $2 / 10;
        $temp1          =       $3 / 1000000;
        $battery1       =       $4;
        $rssi1          =       $5;
      } else {
        print "51 " . $line;
      }
    } elsif($line =~ /sensor=$sensor2/) {
      my $curl = "curl -d \"$line\" http://acu-link.com/messages/";
      #print $curl;
      `$curl`;
      # front porch
      #
      # id=24C86E014F4C&sensor=11583&mt=tower&humidity=A0440&temperature=A026100000&battery=normal&rssi=2
      #
      # we hope to get temperature, humidity, battery and rssi from this one
      if($line =~ /humidity=A(\d+)&temperature=A(\d+)&battery=([^&]+)&rssi=(\d{1})/) {
        $humid2         =       $1 / 10;
        $temp2          =       $2 / 1000000;
        $battery2       =       $3;
        $rssi2          =       $4;
      } else {
        print "S2 " . $line;
      }
    } elsif($line =~ /sensor=$sensor3/) {
      # upstairs
      #
      # id=24C86E014F4C&sensor=01438&mt=tower&humidity=A0160&temperature=A019800000&battery=normal&rssi=2
      #
      # we hope to get temperature, battery and rssi from this one
      # it gives us a humidity value as well, but it's fixed at 16%
      # (cheaper sensor)
      if($line =~ /humidity=A(\d+)&temperature=A(\d+)&battery=([^&]+)&rssi=(\d{1})/) {
        $humid3         =       $1 / 10;
        $temp3          =       $2 / 1000000;
        $battery3       =       $3;
        $rssi3          =       $4;
      } else {
        print "S3 " . $line;
      }
    } elsif($line =~ /mt=pressure/) {
      # bridge, giving barometric pressure
      #
      # id=24C86E014F4C&mt=pressure&C1=442D&C2=0C77&C3=010E&C4=027D&C5=87E7&C6=178F&C7=09C4&A=07&B=19&C=06&D=09&PR=95EF&TR=8902T
      #
      # print "BR " . $line;
      # this should be able to be accomplished more elegantly with regexp
      # but for now, this works...
      $c1 = hex(substr $line, index ($line, 'C1=') + 3, 4);
      $c2 = hex(substr $line, index ($line, 'C2=') + 3, 4);
      $c3 = hex(substr $line, index ($line, 'C3=') + 3, 4);
      $c4 = hex(substr $line, index ($line, 'C4=') + 3, 4);
      $c5 = hex(substr $line, index ($line, 'C5=') + 3, 4);
      $c6 = hex(substr $line, index ($line, 'C6=') + 3, 4);
      $c7 = hex(substr $line, index ($line, 'C7=') + 3, 4);
      $a  = hex(substr $line, index ($line, 'A=') + 2, 2);
      $b  = hex(substr $line, index ($line, 'B=') + 2, 2);
      $c  = hex(substr $line, index ($line, 'C=') + 2, 2);
      $d  = hex(substr $line, index ($line, 'D=') + 2, 2);
      $pr = hex(substr $line, index ($line, 'PR=') + 3, 4);
      $tr = hex(substr $line, index ($line, 'TR=') + 3, 4);

      if ($tr >= $c5) {
        $dut = $tr - $c5 - (($tr-$c5) / 2**7) * (($tr-$c5) / 2**7)* $a / 2**$c;
      } else {
        $dut = $tr - $c5 - (($tr-$c5) / 2**7) * (($tr-$c5) / 2**7)* $b / 2**$c;
      }

      $off = ($c2 + ($c4 - 1024) * $dut / 2**14) * 4;
      $sens = $c1 + $c3 * $dut / 2**10;
      $x = $sens * ($pr - 7168) / 2**14 - $off;
      $p = $x * 10 / 2**5 + $c7;

      $t = 250 + $dut * $c6 / 2**16 - $dut / 2 ** $d;

      $p = $p + $barocorrection;
      $pressure = $p / 10;
    } else {
      print "?? " . $line;
    }
    # write out the file
    open (NESTFILE, '/tmp/nest_current-metric')
        or die "can't open nestfile: $!";
    open (DROPFILE, ">$dropfile")
        or die "can't open dropfile: $!";
    print DROPFILE "outTemp = $temp1\n"         if ($temp1 != '9999');
    print DROPFILE "outHumidity = $humid1\n"    if ($humid1 != '9999');
    print DROPFILE "barometer = $pressure\n"    if ($pressure != '9999');
    print DROPFILE "windSpeed = $windspeed\n"   if ($windspeed != '9999');
    print DROPFILE "windDir = $winddir\n"       if ($winddir != '9999');
    print DROPFILE "rain = $rainfall\n"         if ($rainfall != '9999');
    print DROPFILE "extraTemp1 = $temp2\n"      if ($temp2 != '9999');
    print DROPFILE "extraHumid1 = $humid2\n"    if ($humid2 != '9999');
    print DROPFILE "extraTemp2 = $temp3\n"      if ($temp3 != '9999');
    print DROPFILE "extraHumid2 = $humid3\n"    if ($humid3 != '9999');
    print DROPFILE "rssi1 = $rssi1\n"           if ($rssi1 != '9999');
    print DROPFILE "rssi2 = $rssi2\n"           if ($rssi2 != '9999');
    print DROPFILE "rssi3 = $rssi3\n"           if ($rssi3 != '9999');
    foreach $nestline (<NESTFILE>) {
      print DROPFILE $nestline;
    }
    close(DROPFILE);
    close(NESTFILE);
  }
}
close(TCPDUMP);


So this is the only thing that you need to run once it has its data it just passes the info off to acu-rite like a good little worker.  Weewx is now also passing its data off to WU just as soon as it gets it.  The bridge is updating every 2 seconds now and its awesome.

Now what else can you do with this?

Well if you use splunk at home.  I told the forwarder on this VM to start monitoring the wxdata file that the acusniff.pl spits out and so now I have a fancy little dashboard setup in splunk that monitors realtime temp, windspeed then I have static data that refreshes every hour for my rain, barometer and I also have record panels on there for high temp last 24 hours/7 days and 30 days and I do the same thing for wind as well. 

Thank you George for doing the leg work with the pi and some day I might go down that road but for now by just redirecting all of my bridge calls in house I'm a happy guy.