first run
authorRuss Handorf <rhandorf@handorf.org>
Fri, 20 Apr 2018 21:14:51 +0000 (17:14 -0400)
committerRuss Handorf <rhandorf@handorf.org>
Fri, 20 Apr 2018 21:14:51 +0000 (17:14 -0400)
README.md [new file with mode: 0644]
server.py [new file with mode: 0644]
sniffer.pl [new file with mode: 0755]

diff --git a/README.md b/README.md
new file mode 100644 (file)
index 0000000..a313ae7
--- /dev/null
+++ b/README.md
@@ -0,0 +1,26 @@
+LED Wall Bits n Bobs
+
+There is a client/server relationship between the two scripts. I have a box monitoring all my network traffic at 10Gbps. The Perl sniffer script listens on this host and that interface (sniffer.pl) and sends UDP packets to the the RaspberryPi that has a Python script listening on a UDP port and switches on/off the pixels.
+
+Bill of Materials:
+1. Four LED Grids - https://www.amazon.com/gp/product/B01DC0IOCK/
+2. One Power Supply - https://www.amazon.com/gp/product/B01B1QKLNW
+3. One RaspberryPi 3 and relavent bits to make it work
+4. Some wire and mediocre soldering skills
+
+Install Instructions:
+1. Connect/Solder up the panel's INPUTS/OUTPUTs, and extend the voltage injection. It's pretty darn simple.
+2. Install Raspbian 
+3. Install rpi_ws281x on the RaspberryPi : https://github.com/jgarff/rpi_ws281x
+4. Install any missing Python libs via pip
+5. On the sniffer box, use CPAN to install all the required libs
+6. Change the hostnames/IP, subnet filter range, and ethernet interface to sniff from
+
+Start the scripts:
+
+sudo python server.py
+./sniffer.pl
+
+
+*Potenial bugs*
+1. I'm not entirely convinced the timeout to clear a pixel is making its way over. Might have to make a double check in the Python as well
diff --git a/server.py b/server.py
new file mode 100644 (file)
index 0000000..3f9bc55
--- /dev/null
+++ b/server.py
@@ -0,0 +1,53 @@
+import socket
+import threading
+import time
+from neopixel import *
+
+LED_COUNT      = 1024      # Number of LED pixels.
+LED_PIN        = 18      # GPIO pin connected to the pixels (18 uses PWM!).
+#LED_PIN        = 10      # GPIO pin connected to the pixels (10 uses SPI /dev/spidev0.0).
+LED_FREQ_HZ    = 800000  # LED signal frequency in hertz (usually 800khz)
+LED_DMA        = 10      # DMA channel to use for generating signal (try 10)
+LED_BRIGHTNESS = 128     # Set to 0 for darkest and 255 for brightest
+LED_INVERT     = False   # True to invert the signal (when using NPN transistor level shift)
+LED_CHANNEL    = 0       # set to '1' for GPIOs 13, 19, 41, 45 or 53
+
+bind_ip = '0.0.0.0'
+bind_port = 10000
+strip = Adafruit_NeoPixel(LED_COUNT, LED_PIN, LED_FREQ_HZ, LED_DMA, LED_INVERT, LED_BRIGHTNESS, LED_CHANNEL)
+strip.begin()
+
+server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
+server.bind((bind_ip, bind_port))
+
+print 'Listening on {}:{}'.format(bind_ip, bind_port)
+
+pixels = []
+for i in range(1024):
+  pixels.append(tuple((0,0,0)))
+
+strip.show()
+
+print "Starting Server"
+while True:
+  data, addr = server.recvfrom(1024)
+  if data:
+    #print 'Received {}'.format(data)
+    elements=format(data).split(",")
+    color=elements[0].split(":")
+    pixel_color=pixels[int(color[1])]
+    red=pixel_color[0]
+    green=pixel_color[1]
+    blue=pixel_color[2]
+    if (int(elements[1])==0):
+      strip.setPixelColor(int(color[1]), Color(0,0,0))
+    if color[0]=="R":
+      strip.setPixelColor(int(color[1]), Color(green, int(elements[1]), blue))
+      pixels[int(color[1])] =(int(elements[1]),green,blue)
+    if color[0]=="G":
+      strip.setPixelColor(int(color[1]), Color(int(elements[1]), red, blue))
+      pixels[int(color[1])] =(red,int(elements[1]),blue)
+    if color[0]=="B":
+      strip.setPixelColor(int(color[1]), Color(green, red, int(elements[1])))
+      pixels[int(color[1])] =(red,green,int(elements[1]))
+    strip.show()
diff --git a/sniffer.pl b/sniffer.pl
new file mode 100755 (executable)
index 0000000..1401de2
--- /dev/null
@@ -0,0 +1,104 @@
+#!/usr/bin/perl
+
+use strict;
+use POSIX;
+use Net::Pcap;
+use NetPacket::Ethernet;
+use NetPacket::IP;
+use NetPacket::TCP;
+use NetPacket::UDP;
+use Socket;
+use IO::Socket;
+
+my $server = IO::Socket::INET->new(
+  Proto     => 'udp',
+  PeerPort => 10000,
+  PeerAddr    => 'led-wall' )
+or die "can't setup server";
+
+my @led_timer;
+
+my $err;
+
+my $dev = "eth1";
+unless (defined $dev) {
+    $dev = Net::Pcap::lookupdev(\$err);
+    if (defined $err) {
+        die 'Unable to determine network device for monitoring - ', $err;
+    }
+}
+
+my ($address, $netmask);
+my $object = Net::Pcap::open_live($dev, 1500, 0, 0, \$err);
+
+my $filter;
+Net::Pcap::compile(
+    $object, 
+    \$filter,
+    #make your private network range in the filter below
+    '(not src net 192.168.0.0/16)',
+    0, 
+    $netmask
+) && die 'Unable to compile packet capture filter';
+
+Net::Pcap::setfilter($object, $filter) &&
+  die 'Unable to set packet capture filter';
+
+unless (defined $object) {
+  die 'Unable to create packet capture on device ', $dev, ' - ', $err;
+}
+
+#print $server "ticklex";
+
+Net::Pcap::loop($object, -1, \&packets, $server) ||
+  die 'Unable to perform packet capture';
+
+sub led_timeout {
+  my ($user_data, $pixel) = @_;
+  $led_timer[$pixel] = time() + 15;
+
+  for (my $i=0; $i<1024; $i++) {
+    if (($led_timer[$i] < time()) && ($led_timer[$i]>0)) {
+      print $user_data "R:$i,0";
+      print $user_data "G:$i,0";
+      print $user_data "B:$i,0";
+      $led_timer[$i] = 0;
+    }
+  }
+}
+
+sub ip2dec ($) {
+    unpack N => pack CCCC => split /\./ => shift;
+}
+
+sub packets {
+  my ($user_data, $header, $packet) = @_;
+  my $ether_data = NetPacket::Ethernet::strip($packet);
+  my $ip = NetPacket::IP->decode($ether_data);
+  my $num;
+  my $pixel;
+  my $intensity;
+  if($ip->{proto} == 6) {
+    my $tcp = NetPacket::TCP->decode($ip->{'data'});
+    if ($tcp) {
+      $num = $tcp->{'src_port'} / 64;
+      $pixel = floor($num);
+      $intensity = floor((((sprintf("%.2f",($num-$pixel))*100)) * 256) / 100);
+      print $user_data "R:$pixel,$intensity";
+    }
+  } elsif ($ip->{proto} == 17) {
+    my $udp = NetPacket::UDP->decode($ip->{'data'});
+    if ($udp) {
+      $num = $udp->{'src_port'} / 64;
+      $pixel = floor($num);
+      $intensity = floor((((sprintf("%.2f",($num-$pixel))*100)) * 256) / 100);
+      print $user_data "G:$pixel,$intensity";
+    }
+  } else {
+    $num = ip2dec($ip->{'src_ip'}) / 4194304;
+    $pixel = floor($num);
+    $intensity = floor((((sprintf("%.2f",($num-$pixel))*100)) * 256) / 100);
+    print $user_data "B:$pixel,$intensity";
+  }
+  led_timeout($user_data, $pixel);
+}