(gelöst) DHCP Server auf dem RPI & Presence per SNMP

Begonnen von Dirk070, 24 November 2014, 20:15:03

Vorheriges Thema - Nächstes Thema

Dirk070

#15
Ich habe auf Basis des verlinkten Scripts eine Lösung hinbekommen.
Das Script ist sicher noch nicht optimal. Die manuellen Aufrufe funktionieren, nun folgt der Praxistest.

Wer es probieren möchte, hier meine komplette 99_myUtils.pm:
##############################################
# $Id: 99_Utils.pm 3595 2013-08-05 05:38:48Z tobiasfaust $
package main;
use strict;
use warnings;
use POSIX;
#use Net::SNMP;
use Data::Dumper;

sub
myUtils_Initialize($$)
{
my ($hash) = @_;
}
# start with your own functions below this line

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

# Reads and munges the leases file generated by dhcpd
sub DHCPcheck($) {

my $mac = shift;

###--------------------------OPTIONS--------------------------###

# Change to your dhcp file and dhcpd.conf:
# (Currently set to ISC DHCP defaults)

my $dhcpfile = "/var/lib/dhcp/dhcpd.leases";
my $active = "active";

my $line;
my $key;
my $entries;
my $temp;
my $ip;
my @t;
my @words;
my @ips;

###----------------------End of Options-----------------------###

our %lease;
unless(open (IN, $dhcpfile)) {
                return 0;
                return "Error: unable to open file $dhcpfile";
exit -1;
}
my @leases = <IN>;
my $data = "";
foreach $line (@leases) {
unless ($line =~ m/^#/ || length($line) < 2) { # ignore commented lines and empty ones (only CR)
$data .= $line;
}
}
# Split Leases into Array, cut out first empty entry, because first line starts with Split pattern
my @tmpdata = split (/lease /, $data); #split each lease into an array entry
        my @data = grep{ $_ ne ""; } @tmpdata;
foreach (@data) {                 #create hash of hashes keyed on ip from the array
my @temp = split(/{/, $_);
chop($temp[0]); # 0 is IP
chop($temp[1]); # 1 is the rest...
chop($temp[1]);
$temp[1] =~ tr/\t//d;
@t = split(/;\n/, $temp[1]); #split each lease on newline
my $i=0;
while ($t[$i]) {
my $string = $t[$i];
$string =~ tr/\n//d;
$string =~ s/^\s*//; # remove any leading spaces
@words = split(/\s+/, $string); #hashes keyed on first word

if ($words[0]) {
$key = shift(@words);
$lease{$temp[0]}{$key}="@words";
$lease{$temp[0]}{"hardware"}=~ s/ethernet//;
$lease{$temp[0]}{"binding"}=~ s/state //;
}
$i++;
}
}
my @temp = sort(keys(%lease));
my $prev = ""; # checks for duplicates
@ips=grep($_ ne $prev && (($prev) = $_), @temp);
$entries = @ips;

#Finds entry for a given MAC address (hardware id in leases file)

        foreach $ip (@ips) {
                if ($lease{$ip}{"hardware"} =~ /$mac/) {
                    if ($lease{$ip}{"binding"} =~ /$active/) {
return 1;
} }
}

return 0;
}

1;


Der Aufruf aus der fhem.cfg erfolgt ähnlich wie bei der SMTP-Variante (xx ist die Mac-Adresse):
# Presence per DHCP auf dem RPI
define iPhone PRESENCE function {DHCPcheck("xx:xx:xx:xx:xx:xx")} 15 15
attr iPhone room Presence
attr iPhone event-on-change-reading state


Ergänzung; damit in der Leases (File: /var/lib/dhcp/dhcpd.leases) nur ein Eintrag pro Mac-Adresse erzeugt wird, muss der folgende Parameter (File: /etc/dhcp/dhcpd.conf) gesetzt werden:
one-lease-per-client true;

Schöne Grüße,
Dirk

Dirk070

Ich habe noch eine Benachrichtigung per Push (über Pushover) eingerichtet.

Sub in der 99_myUtils (token und user ersetzen, ist hier gut erklärt http://www.meintechblog.de/2013/11/howto-mit-fhem-push-nachrichten-aufs-iphone-schicken-update/), ein Wiki dazu gibt es auch:
sub Pushover($) {

my $text = shift;

# Pushover iPhone
system ("curl -s -F 'token=axxxxxxxxxxxxxxx' -F 'user=uxxxxxxxxxxxxxx' -F 'message=$text' https://api.pushover.net/1/messages.json")

}


Aufruf dann per Watchdog:
define watchdog_Abwesenheit watchdog iPhone:absent 00:01 iPhone:present { Pushover("Abwesend") } ; setstate watchdog_Abwesenheit defined
attr watchdog_Abwesenheit regexp1WontReactivate 1
define watchdog_Anwesenheit watchdog iPhone:present 00:01 iPhone:absent { Pushover("Anwesend") } ; setstate watchdog_Anwesenheit defined
attr watchdog_Anwesenheit regexp1WontReactivate 1


Viel Spaß.

widdi

Hallo zusammen,
ich freue mich diesen Thread gefunden zu haben. Ich habe meinen DHCP-Server jetzt ganz auf einen OpenWRT-Router verlegt und "snmpd" installiert, da bei den neuen AirPort-Geräten nicht mehr dabei ist.

Die mitgelieferte /etc/snmpd.conf sieht so aus:
agentaddress UDP:161                                                                                                                                                   
sysLocation office                                                                                                                                                     
sysContact bofh@example.com                                                                                                                                             
sysName HeartOfGold                                                                                                                                                     
com2sec ro default public                                                                                                                                               
com2sec rw localhost private                                                                                                                                           
group public v1 ro                                                                                                                                                     
group public v2c ro                                                                                                                                                     
group public usm ro                                                                                                                                                     
group private v1 rw                                                                                                                                                     
group private v2c rw                                                                                                                                                   
group private usm rw                                                                                                                                                   
view all included .1                                                                                                                                                   
access public "" any noauth exact all none none                                                                                                                         
access private "" any noauth exact all all all                                                                                                                         
exec  filedescriptors /bin/cat /proc/sys/fs/file-nr                                                                                                                     


Ist das richtig so?

Das iOS-Gerät bezieht seine IP-Adresse jetzt von dem OpenWRT.
Über snmpwalk -c public -v 1 10.0.0.4 .1.3.6.1.2.1.3.1.1.2 taucht das gerät auch auf:

SNMPv2-SMI::mib-2.3.1.1.2.4.1.10.0.0.8 = Hex-STRING: E5 3A 0A F1 21 8C
Das müsste also so auch stimmen.

Egal wie lange das iOS-Gerät jetzt von dem WLAN getrennt ist, der Eintrag taucht auch nach Stunden noch auf (folglich auch "present" in FHEM).
Hat der SNMPD oder Dnsmasq (DNS- und DHCP-Server von OpenWRT) noch Konfigurationsbedarf?
In FHEM steht das iOS-Gerät dauernd auf "present", nachdem es den DHCP-Lese bekommen hat.
Lohnt es sich DD-WRT zu flashen (wie im Thread schon erwähnt wurde), ist dort alles besser vorkonfiguriert?

Danke für eure Hilfe.

sun

Hallo,

ich verwende das Skript von Dirk auf einem Ubuntu Server unter FHEM. Die Anwesenheitserkennung funktioniert soweit getestet. Was ich aber sehe ist das im Log bei jedem Aufruf zwei Fehler eingetragen werden:
2015.02.13 22:37:46 1: PERL WARNING: Use of uninitialized value in substitution (s///) at ./FHEM/99_myUtils.pm line 263, <IN> line 528.
2015.02.13 22:37:46 1: PERL WARNING: Use of uninitialized value in substitution (s///) at ./FHEM/99_myUtils.pm line 264, <IN> line 528.

die werden ausgelöst von
$lease{$temp[0]}{"hardware"}=~ s/ethernet//;
$lease{$temp[0]}{"binding"}=~ s/state //;

und zwar immer beim verarbeiten der letzten Zeile des Lease files.
Ich habe schon versucht das Problem zu lösen kenne mich aber offensichtlich zu wenig mit Perl aus.
Hat jemand eine Idee ?

Gruß,

sun

sun

Falls noch jemand das Problem mit den Log einträgen hat. Ich habe die beiden Zeilen ersetzt durch:

                                if ($lease{$temp[0]}{"hardware"}) {
                                  $lease{$temp[0]}{"hardware"}=~ s/ethernet//;
                                }
                                if ($lease{$temp[0]}{"binding"}) {
                                  $lease{$temp[0]}{"binding"}=~ s/state //;
                                }


Damit ist das warning bei mir verschwunden und die Funktionalität bleibt bestehen.