Presence Funktion für Mikrotik/RouterOS (SNMP) und TP-Link Geräte (WEB)

Begonnen von pipp37, 01 September 2016, 00:52:58

Vorheriges Thema - Nächstes Thema

schka17

Zitat von: borsti67 am 16 September 2017, 12:47:31
Hallo,

kann es sein, dass der TP-LINK-Code nur auf bestimmten Geräten oder älteren Firmwares läuft? Ich habe einen TL-WA850RE, aber der scheint diese RPM-Seiten nicht zu kennen, denn egal welches ergoogelte Ziel ich mittels curl/wget ziehen möchte, der liefert nur "Server Error 501: not implemented"... :(
Klar, sogar sehr wahrscheinlich solange nicht die SNMP MIB-2 verwendet wird. Probier einfach mal mir ein einem Mib browser zu schauen welche OID's unterstützt werden


Sent from my iPad using Tapatalk
M: Thinclient x64 Debian | CUL FS20, HMS100WD, HMS100TF, HMS100T, HMS100CO, S300, S555TH | OWServer DS1420, DS18B20, DS2408 | RFXCOM UVN128, THWR800, THGR228N,RTGR328, PCR800 |Jeelink PCA301 EC3000|CUNO+IR|HMLAN|HMUSB|CUL433 Somfy|mySensors|espEasy
S1:Raspberry mit BPM810, Jeelink EC3000

borsti67

Danke schka17,
der antwortet offenbar gar nicht auf SNMP. :( Sehr schade.
cu/2
Borsti
---
FHEM 5.8 auf Synology DS211j (bis 11/17) | FHEM 6.0 auf Raspi Zero W (bis 11/20) | FHEM 6.2 als VM in Synology DS1815+ (ab 11/20)

Patrick131184

#17
Hallo zusammen,
es scheint das der hier gezeigte Code für die TP-Link Router nicht mehr funktioniert.
Anscheinend klappt der Login nicht richtig.

Ich hab mal ein bisschen gegoogelt und folgenden Blog gefunden:

https://www.xeve.de/wp/2015/02/automatically-reboot-tp-link-router-wdr4300-n750-with-bash-script/

Den Code ein bisschen auf unsere Zwecke abgeändert und siehe da, es klappt nun auch wieder mit der Presence Erkennung bei meinem TP-Link WR841N v10.

#!/bin/bash

#
# Check Mobile Phone Status TP-Link Router and send state to FHEM
##############
# Modified Version of https://www.xeve.de/wp/2015/02/automatically-reboot-tp-link-router-wdr4300-n750-with-bash-script/
# Reboot TP Link router on modern firmware (tested only on WDR4300/N750)
# Author: Nicolai Spohrer <nicolai@xeve.de>
##############
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.



if [ "$#" -ne 3 ]; then
    echo "Illegal number of parameters";
    echo "Usage: $0 ROUTER_IP USERNAME PASSWORD";
    exit;
fi

IP=$1;
USERNAME=$2;
PASSWORD=$3;


MAX_TRIES=6; # maximum number of attempts
SYSLOG_TAG="Check_MAC_TP-Link.sh"

# From https://stackoverflow.com/questions/296536/urlencode-from-a-bash-script/10660730#10660730
rawurlencode() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo "${encoded}"    # You can either set a return variable (FASTER)
  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}

PASSWORD_MD5=`echo -n $PASSWORD | md5sum | cut -d " " -f 1`;
COOKIE_B64_PART=`echo -n $USERNAME":"$(echo -n $PASSWORD_MD5)|base64`;
COOKIEVAL_UNENCODED=`echo -n "Basic $COOKIE_B64_PART"`;
COOKIEVAL=`rawurlencode "$COOKIEVAL_UNENCODED"`

GET_KEY_URL=`echo "http://$IP/userRpm/LoginRpm.htm?Save=Save"`


# If the reboot sequence fails, try again $MAX_TRIES times
for i in $(seq 1 $MAX_TRIES)
do

  RESPONSE=`curl -s --cookie "Authorization=$COOKIEVAL" $GET_KEY_URL`;
  KEY=`echo $RESPONSE |  head -n 1 | cut -d '/' -f 4` # extract key from post-login-page

  sleep 1;

  REBOOT_URL="http://"$IP"/"$KEY"/userRpm/WlanStationRpm.htm";
  REBOOT_REFERER_URL="http://"$IP"/"$KEY"/userRpm/WlanStationRpm.htm";

  FINAL_RESPONSE=`curl -s --cookie "Authorization=$COOKIEVAL" --referer $REBOOT_REFERER_URL $REBOOT_URL`;
   
  #to show received response uncomment next line
  #echo $FINAL_RESPONSE
  MATCH_PAT=`echo $FINAL_RESPONSE | grep -c "F0-FA-BC-13-1B-41"`
  MATCH_ALI=`echo $FINAL_RESPONSE | grep -c "F0-FA-BC-13-1B-42"`
  if [ $MATCH_PAT -gt 0 ]; then
    # Success!
    break
  else
    echo "Failed on try $i..."
    sleep 1;
  fi
done

if [ $MATCH_PAT -gt 0 ]; then
  SUCCESS_TEXT="sending present from Patrick to FHEM...";
  curl -s http://localhost:8083/fhem?cmd=set%20Patrick%20home
  echo $SUCCESS_TEXT;
  logger -t $SYSLOG_TAG $SUCCESS_TEXT;
else
  FAILURE_TEXT="sending absent from Patrick to FHEM...";
  curl -s http://localhost:8083/fhem?cmd=set%20Patrick%20absent
  echo $FAILURE_TEXT;
  logger -t $SYSLOG_TAG $FAILURE_TEXT;

  # Log failure details
  MYRAND=$RANDOM;
  MYFILES="/tmp/failure-$MYRAND";
  echo $RESPONSE > "$MYFILES-response1"
  echo $FINAL_RESPONSE > "$MYFILES-finalresponse"

 
fi

if [ $MATCH_ALI -gt 0 ]; then
  SUCCESS_TEXT="sending present from Alina to FHEM...";
  curl -s http://localhost:8083/fhem?cmd=set%20Alina%20home
  echo $SUCCESS_TEXT;
  logger -t $SYSLOG_TAG $SUCCESS_TEXT;
else
  FAILURE_TEXT="sending absent from Alina to FHEM...";
  curl -s http://localhost:8083/fhem?cmd=set%20Alina%20absent
  echo $FAILURE_TEXT;
  logger -t $SYSLOG_TAG $FAILURE_TEXT;


  # Log failure details
  MYRAND=$RANDOM;
  MYFILES="/tmp/failure-$MYRAND";
  echo $RESPONSE > "$MYFILES-response1"
  echo $FINAL_RESPONSE > "$MYFILES-finalresponse"

fi




Geschaltet wird die Anwesenheitserkennung über RESIDENT Devices per Webaufruf.

Ich bin kein Bash-Experte. Falls hier noch was korriegiert werden muss könnt Ihr gerne den Code modifizieren.

Eventuell hilft das ja dem einen oder anderen weiter.
Lasst mich wissen wenn es euch weitergeholfen hat :)


oetti77

Auch wenn der Thread schon etwas älter ist - danke Pipp37 für die Codeschnipsel.
Läuft einwandfrei mit Mikrotik  :)

Gruß
Chris
FHEM 5.8 (CentOS 7 auf ESXi 6.5), HM-CC-RT-DN, HM-Sec-Sc, HM-WDS40-TO, HM-LC-SW1-FM, HM-LC-Bl1PBU-FM, Sonos, Alexa, Nest Protect 2, Tradfri

Module: HUE, Lightify, ECOTOUCH, TelegramBot, Sonos, Alexa, Pushover, Enigma2

mumpitzstuff

Das Skript für TP-Link habe ich mal ein wenig erweitert, allerdings erst mal die Aktionen entfernt, da ich bisher nur die reine Erkennung ausprobieren wollte. Hinzugekommen ist der Support für Pages (die Geräte können auf mehreren Html Seiten verteilt sein) und ein Logout am Ende des Skriptes. Wenn das Logout fehlt, dann kann ich mich 2min lang selbst nicht mehr am Router anmelden, was irgendwie nicht so toll ist.

Die Anzahl der Versuche muss mind. auf 2 stehen, sonst klappt es nicht, wenn die Abfragen zu schnell hintereinander kommen.

Das Skript funktioniert auf einem Archer C7 (AC1750).

#!/bin/bash

#
# Check Mobile Phone Status TP-Link Router and send state to FHEM
##############
# Modified Version of https://www.xeve.de/wp/2015/02/automatically-reboot-tp-link-router-wdr4300-n750-with-bash-script/
# Reboot TP Link router on modern firmware (tested only on WDR4300/N750)
# Author: Nicolai Spohrer <nicolai@xeve.de>
##############
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 3 of the License, or
# (at your option) any later version.



if [ "$#" -ne 3 ]; then
    echo "Illegal number of parameters";
    echo "Usage: $0 ROUTER_IP USERNAME PASSWORD";
    exit;
fi

IP=$1
USERNAME=$2
PASSWORD=$3


MAX_TRIES=2 # maximum number of attempts
MAX_PAGES=2 # maximum pages to search for clients

# From https://stackoverflow.com/questions/296536/urlencode-from-a-bash-script/10660730#10660730
rawurlencode() {
  local string="${1}"
  local strlen=${#string}
  local encoded=""

  for (( pos=0 ; pos<strlen ; pos++ )); do
     c=${string:$pos:1}
     case "$c" in
        [-_.~a-zA-Z0-9] ) o="${c}" ;;
        * )               printf -v o '%%%02x' "'$c"
     esac
     encoded+="${o}"
  done
  echo "${encoded}"    # You can either set a return variable (FASTER)
  REPLY="${encoded}"   #+or echo the result (EASIER)... or both... :p
}

PASSWORD_MD5=`echo -n $PASSWORD | md5sum | cut -d " " -f 1`;
COOKIE_B64_PART=`echo -n $USERNAME":"$(echo -n $PASSWORD_MD5)|base64`;
COOKIEVAL_UNENCODED=`echo -n "Basic $COOKIE_B64_PART"`;
COOKIEVAL=`rawurlencode "$COOKIEVAL_UNENCODED"`;

GET_KEY_URL=`echo "http://$IP/userRpm/LoginRpm.htm?Save=Save"`;


# If the reboot sequence fails, try again $MAX_TRIES times
for i in $(seq 1 $MAX_TRIES)
do
  REPEAT=1
  RESPONSE=`curl -s --cookie "Authorization=$COOKIEVAL" $GET_KEY_URL`
  #echo -e $RESPONSE "\n\n"
  KEY=`echo $RESPONSE |  head -n 1 | cut -d '/' -f 4` # extract key from post-login-page
  #echo -e $KEY "\n\n"

  sleep 1

  for n in `seq 1 $MAX_PAGES`;
  do
    WLAN_URL="http://"$IP"/"$KEY"/userRpm/WlanStationRpm.htm?Page=$n"

    FINAL_RESPONSE=`curl -s --cookie "Authorization=$COOKIEVAL" --referer $WLAN_URL $WLAN_URL`

    #echo -e $FINAL_RESPONSE "\n\n"
    MATCH_CLIENT1=`echo $FINAL_RESPONSE | grep -c "AA-AA-AA-AA-AA-AA"`
    MATCH_CLIENT2=`echo $FINAL_RESPONSE | grep -c "BB-BB-BB-BB-BB-BB"`

    if [ $MATCH_CLIENT1 -gt 0 ]; then
      echo "Success on try $i for page $n (CLIENT 1)!"

      let REPEAT=0
    fi

    if [ $MATCH_CLIENT2 -gt 0 ]; then
      echo "Success on try $i for page $n (CLIENT 2)!"

      let REPEAT=0
    fi

    if [ $MATCH_CLIENT1 = 0 ] && [ $MATCH_CLIENT2 = 0 ]; then
      echo "Failed on try $i for page $n..."
    fi
  done

  if [ $REPEAT = 0 ]; then
    break
  fi

  sleep 1
done

LOGOUT_URL="http://"$IP"/"$KEY"/userRpm/LogoutRpm.htm"

FINAL_RESPONSE=`curl -s --cookie "Authorization=$COOKIEVAL" --referer $LOGOUT_URL $LOGOUT_URL`

pd33

Zitat von: gramels am 10 April 2017, 23:33:42
Hallo,

blöde Frage, braucht es bei diesem script den obige snmp Abfrage überhaupt?
Ich versuche es gerade stand alone, und bekomme es nicht zum laufen..

Grüsse
gramels

Hallo gramels,

nein, braucht man nicht. Ich habe mittlerweile alle meine "presence"-Abfragen aus FHEM verbannt, da diese doch sehr dazu beigetragen haben, dass mein FHEM immer langsamer wurde. Alle Ping und WLAN-Abfragen habe ich auf RouterOS Scripte bzw. Netwatch umgestellt und bin damit sehr zufrieden.

Wenn noch Bedarf besteht, teile ich die Infos dazu gern hier.


Viele Grüße
Christian

psycho160

Hammer @Pipp37. Danke für die Funktionen

Habe jetzt auch auf Capsman und SNMP umgestellt.

Hat jemand schon versucht anhand der Registration Table eine Anwesenheitserkennung auf Raumebene zu realisieren?

Mit ist schon klar das diese Variante nicht extra genau ist, aber ich weiß ca. bei welchem AP sich der Client in der Nähe befindet.
- 2013@FHEM - 2020 Setup: Pi 4 4GB Systeme: Shelly, Tasmota, Zigbee und mittlerweile nur noch wenig Homematic. Entwicker von: tado-FHEM Modul (perlcritic 3 ^^)(https://git.wolfmajer.at/Public/FHEM-Tado)

JoeALLb

Ich bin von SNMP auf Syslog umgestiegen.
Es gibt ein FHEM Syslogmodul, das als Server agiert und ausgesuchte Mikrotik Liga mitlesen kann. Darunter eben auch dchp leases... Funktioniert genial und ich nutze es auch zur Raumzuordnung.


SG Joe
FHEM-Server auf IntelAtom+Debian (8.1 Watt), KNX,
RasPi-2 Sonos-FHEM per FHEM2FHEM,RasPi-3 Versuchs-RasPi für WLAN-Tests
Gateways: DuoFern Stick, CUL866 PCA301, CUL HM, HMLan, JeeLink, LaCrosse,VCO2
Synology. Ardurino UNO für 1-Wire Tests, FB7270

psycho160

Zitat von: JoeALLb am 14 September 2018, 17:48:09
Ich bin von SNMP auf Syslog umgestiegen.
Es gibt ein FHEM Syslogmodul, das als Server agiert und ausgesuchte Mikrotik Liga mitlesen kann. Darunter eben auch dchp leases... Funktioniert genial und ich nutze es auch zur Raumzuordnung.


SG Joe

Hört sich nicht schlecht an. Hast du hier nähere Infos? Wie machst du das mit der Raumzuordnung?
- 2013@FHEM - 2020 Setup: Pi 4 4GB Systeme: Shelly, Tasmota, Zigbee und mittlerweile nur noch wenig Homematic. Entwicker von: tado-FHEM Modul (perlcritic 3 ^^)(https://git.wolfmajer.at/Public/FHEM-Tado)

JoeALLb

Siehe:
https://fhem.de/commandref_DE.html#Log2Syslog

Raumzuordnung: nun, ich habe ein sehr funkdichtes Haus, das hei0ßt ich habe in fast jedem Raum einen accesspoint.
von daher ist die zuordnung relativ einfach...

FHEM-Server auf IntelAtom+Debian (8.1 Watt), KNX,
RasPi-2 Sonos-FHEM per FHEM2FHEM,RasPi-3 Versuchs-RasPi für WLAN-Tests
Gateways: DuoFern Stick, CUL866 PCA301, CUL HM, HMLan, JeeLink, LaCrosse,VCO2
Synology. Ardurino UNO für 1-Wire Tests, FB7270

psycho160

Hallo,

der Code von Threadersteller @Pipp37 hat jetzt Jahrelang bei mir einwandfrei funktioniert. Anscheinend gab es bei Mikrotik RouterOS > 7.11 irgendeine Änderung, bei der meine SNMP Anfragen nach einiger Zeit nichts mehr zurück lieferten.

Fehler verursachte fogende Codezeile im Original:

if ( !defined($response = $session->get_request( @snmpoids ) ) ) {Macht auch keinen Sinn alle Oid´s nochmal an den Router zu senden, wenn ich in der vorherigen Schleife schon alle Oid:MAC´s habe. Habe mittlerweile +50 Geräte im WLAN registriert und das jedesmal doppelt abfragen hat den Router anscheinend überfordert.


Ich habe jetzt die SNMP Abrage in der 99_myUtils.pm mal ausgemistet und um einigen Overhead reduziert. Jetzt läuft meine Anwesenheitserkennung (mittels Mikrotik CapsMan) wieder stabil.

Hier der angepasste Code:


#########################################################################################################################
# hex mac address (AA:BB:CC:DD:EE:FF) to hex value (0x...)
#macht aus input: 14:5F:94:DD:BE:AC -> ein Array elements: 14 5F 94 DD BE AC -> return 0x145f94ddbeac
sub HexMacToHex($)
    {
    my ($in) = @_;
    my @elements=split(/:/,$in);
    my $element;
    my $rethex="0x";

    for  $element  (@elements)
        {
        $rethex .= lc($element);
        }
    return $rethex;
    }

#########################################################################################################################
# Function for checking mac addresses with snmp
# Use with presence modul
# (c) armin@pipp.at  8/2016
# refactored by Philipp Wo (wolfmajer.at) 12/2023
#
# Syntax: snmpCheck2 <NAME> <HOST> <OID-Index> <COMMUNITY> <AA:BB:CC:DD:EE:FF>  [LOGLEVEL]
# Returns 1 if found
#   <NAME>             Human readable Name only for logs
#   <HOST>             SNMP Host
#   <OID-Index>         0-2
#                  $oidindex
#                  0 = Mikrotik wireless mac table:    .1.3.6.1.4.1.14988.1.1.1.2.1.1
#                  1 = Mikrotik capsman mac table:     .1.3.6.1.4.1.14988.1.1.1.5.1.1
#                  2 = Apple Airport DHCP table:       .1.3.6.1.2.1.3.1.1.2
#   <COMMUNITY>       SNMP read community string (standard=public)
#   <AA:BB:CC:DD:EE:FF> Client MAC Address for the search
#   [LOGLEVEL]         optional / Loglevel (standard=4)
#
# Fhem PRESENCE: define PR_iPhoneSNMP PRESENCE function { snmpCheck2("iPhone-Armin", "192.168.27.254", 1, "public", "3C:07:71:B3:B6:71" ) } 30 120
#

sub snmpCheck2($$$$$;$){
   use Net::SNMP;
   my ($NAME,$host,$oidindex,$community,$clientMac,$loglevel)=@_;
   my $log=4;
   if (defined($loglevel))   {$log=$loglevel};
   
    my @oidarray = (".1.3.6.1.4.1.14988.1.1.1.2.1.1", ".1.3.6.1.4.1.14988.1.1.1.5.1.1", ".1.3.6.1.2.1.3.1.1.2");
   
    my $client = HexMacToHex($clientMac);
    my $oid = $oidarray[$oidindex];

   #Log3 $name, 5, "snmpCheck2a ($name)"
    Log $log, ("snmpCheck2: $NAME: Parameter=@_");
    Log $log, ("snmpCheck2: $NAME: Vars: OID-Index=$oidindex / OID=$oid / CheckMacHex=$client");

    my ( $session, $error ) = Net::SNMP->session(
        -hostname => $host,
        -community => $community,
        -port => 161,
        -version => 1
        );

    # Error-Handling
unless ($session) {
    Log3 $NAME, 3,"SNMP-Check: Can't connect to host $host";
        return 0;
}

# Key Value Paar mit Oid und MAC - hier landen alle responses
my %oidAndMac = ();
        my $response = $session->get_next_request($oid);
        my @nextid = keys %$response;

    while ( @nextid && $nextid[0] && $nextid[0] =~ m/^$oid/ ) { 
        #print ("$nextid[0]\n");
        $response = $session->get_next_request( $nextid[0] );
my @values = values %$response;
$oidAndMac{$nextid[0]} = $values[0];
        @nextid = keys %$response;
        }
$session->close();

foreach my $oid (keys %oidAndMac)
{
  my $value = $oidAndMac{$oid};
  #print (" $value:$client\n");
  if( $value eq $client ){
#print "Oid $oid has MAC $value\n";
Log3 $NAME, $log,"SNMP-Check: $NAME: Mac $clientMac FOUND in $host" if( $value eq $client );
return 1;
  }
}

Log3 $NAME, $log,"SNMP-Check: $NAME: Mac $clientMac NOT found in $host";
return 0;

}
- 2013@FHEM - 2020 Setup: Pi 4 4GB Systeme: Shelly, Tasmota, Zigbee und mittlerweile nur noch wenig Homematic. Entwicker von: tado-FHEM Modul (perlcritic 3 ^^)(https://git.wolfmajer.at/Public/FHEM-Tado)