From: Russ Handorf Date: Fri, 20 Apr 2018 21:14:51 +0000 (-0400) Subject: first run X-Git-Url: http://russells-world.com/code/?p=led-wall.git;a=commitdiff_plain;h=9b212eddb83f9e4734f2dcbca41750fd3edc6b83 first run --- 9b212eddb83f9e4734f2dcbca41750fd3edc6b83 diff --git a/README.md b/README.md new file mode 100644 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 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 index 0000000..1401de2 --- /dev/null +++ b/sniffer.pl @@ -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); +}