diff --git a/fhem/CHANGED b/fhem/CHANGED
index bf0a5a7a1..591dc4d70 100644
--- a/fhem/CHANGED
+++ b/fhem/CHANGED
@@ -1,5 +1,8 @@
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
# Do not insert empty lines here, update check depends on it.
+ - new: 98_Nmap: introducing new module to perform a network scan with
+ Nmap and display information about the available network
+ devices
- update: 98_DOIFtools: better shortcut positioning
- feature: 70_Pushover: new command 'msgCancel' to prematurely cancel
confirmation requests for priority 2 messages
diff --git a/fhem/FHEM/74_Nmap.pm b/fhem/FHEM/74_Nmap.pm
new file mode 100644
index 000000000..0b095d1c7
--- /dev/null
+++ b/fhem/FHEM/74_Nmap.pm
@@ -0,0 +1,1053 @@
+# Id ##########################################################################
+# $Id$
+
+# copyright ###################################################################
+#
+# 74_Nmap.pm
+#
+# Copyright by igami
+#
+# This file is part of FHEM.
+#
+# FHEM 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 2 of the License, or
+# (at your option) any later version.
+#
+# FHEM is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with FHEM. If not, see .
+
+# packages ####################################################################
+package main;
+ use strict;
+ use warnings;
+
+ use Blocking;
+
+ use Nmap::Parser;
+
+# forward declarations ########################################################
+sub Nmap_Initialize($);
+
+sub Nmap_Define($$);
+sub Nmap_Undefine($$);
+sub Nmap_Set($@);
+sub Nmap_Attr(@);
+
+sub Nmap_statusRequest($);
+sub Nmap_blocking_statusRequest($);
+sub Nmap_done($);
+sub Nmap_aborted($);
+
+sub Nmap_deleteOldReadings($$);
+sub Nmap_updateUptime($$;$);
+
+# initialize ##################################################################
+sub Nmap_Initialize($) {
+ my ($hash) = @_;
+ my $TYPE = "Nmap";
+
+ $hash->{DefFn} = $TYPE."_Define";
+ $hash->{UndefFn} = $TYPE."_Undefine";
+ $hash->{SetFn} = $TYPE."_Set";
+ $hash->{AttrFn} = $TYPE."_Attr";
+
+ $hash->{AttrList} =
+ "absenceThreshold "
+ . "args "
+ . "deleteOldReadings "
+ . "devAlias:textField-long "
+ . "disable:1,0 "
+ . "excludeHosts "
+ . "interval "
+ . "keepReadings:1,0 "
+ . "leadingZeros:1,0 "
+ . "metaReading:alias,hostname,ip,macAddress "
+ . "path "
+ . "sudo:1,0 "
+ . $readingFnAttributes
+ ;
+}
+
+# regular Fn ##################################################################
+sub Nmap_Define($$) {
+ my ($hash, $def) = @_;
+ my ($SELF, $TYPE, $targets) = split(/[\s]+/, $def, 3);
+
+ return "Usage: define $TYPE " if(!$targets);
+
+ my $interval = AttrVal($SELF, "interval", 900);
+ $interval = 900 if(!looks_like_number($interval));
+ $interval = 30 if($interval < 30);
+
+ $hash->{ARGS} = AttrVal($SELF, "args", "-sn");
+ $hash->{INTERVAL} = $interval;
+ $hash->{PATH} = AttrVal($SELF, "path", "/usr/bin/nmap");
+
+ readingsSingleUpdate($hash, "state", "Initialized", 1);
+
+ RemoveInternalTimer($hash);
+ InternalTimer(
+ gettimeofday() + $hash->{INTERVAL}, "Nmap_statusRequest", $hash
+ );
+
+ return;
+}
+
+sub Nmap_Undefine($$) {
+ my ($hash, $arg) = @_;
+
+ RemoveInternalTimer($hash);
+ BlockingKill($hash->{helper}{RUNNING_PID})
+ if(defined($hash->{helper}{RUNNING_PID}));
+
+ return;
+}
+
+sub Nmap_Set($@) {
+ my ($hash, @a) = @_;
+ my $TYPE = $hash->{TYPE};
+
+ return "\"set $TYPE\" needs at least one argument" if(@a < 2);
+
+ my $SELF = shift @a;
+ my $argument = shift @a;
+ my $value = join(" ", @a) if (@a);
+ my %Nmap_sets = (
+ "clear" => "clear:readings",
+ "deleteOldReadings" => "deleteOldReadings",
+ "interrupt" => "interrupt:noArg",
+ "statusRequest" => "statusRequest:noArg"
+ );
+
+ return(
+ "Unknown argument $argument, choose one of "
+ . join(" ", values %Nmap_sets)
+ ) if(!exists($Nmap_sets{$argument}));
+
+ if($argument eq "clear" && $value eq "readings"){
+ foreach (keys %{$hash->{READINGS}}) {
+ delete $hash->{READINGS}->{$_} if($_ ne "state");
+ }
+ }
+ elsif($argument eq "deleteOldReadings" && $value){
+ my $ret = Nmap_deleteOldReadings($hash, $value);
+
+ return($ret) if($ret);
+
+ readingsSingleUpdate($hash, "state", "deleteOldReadings $value", 1);
+ }
+ elsif(!IsDisabled($SELF)){
+ if($argument eq "interrupt"){
+ BlockingKill($hash->{helper}{RUNNING_PID})
+ if(defined($hash->{helper}{RUNNING_PID}));
+ RemoveInternalTimer($hash);
+ InternalTimer(
+ gettimeofday() + $hash->{INTERVAL}, "Nmap_statusRequest", $hash
+ );
+ }
+ elsif($argument eq "statusRequest"){
+ Nmap_statusRequest($hash);
+ }
+ }
+
+ return;
+}
+
+sub Nmap_Attr(@) {
+ my ($cmd, $SELF, $attribute, $value) = @_;
+ my $hash = $defs{$SELF};
+
+ if($attribute eq "args"){
+ $hash->{ARGS} = $cmd eq "set" ? $value : "-sn";
+ }
+ elsif(
+ $attribute eq "devAlias"
+ && $cmd eq "set"
+ ){
+ return(
+ "$SELF: Value \"$value\" is not allowed for devAlias!\n"
+ . "Must be \"<ID>: <ID2>: ...\", "
+ . "e.g. 123abc:MyAndroid\n"
+ . "Only these characters are allowed: [alphanumeric - _ .]"
+ )if($value !~ /^([\w\.\-]+:[\w\.\-]+\s*)+$/s);
+ }
+ elsif($attribute eq "disable"){
+ if($value && $value == 1){
+ BlockingKill($hash->{helper}{RUNNING_PID})
+ if(defined($hash->{helper}{RUNNING_PID}));
+ RemoveInternalTimer($hash);
+ readingsSingleUpdate($hash, "state", "disabled", 1);
+ }
+ elsif($cmd eq "del" || !$value){
+ InternalTimer(
+ gettimeofday() + $hash->{INTERVAL}, "Nmap_statusRequest", $hash
+ );
+ readingsSingleUpdate($hash, "state", "Initialized", 1);
+ }
+ }
+ elsif($attribute eq "leadingZeros"){
+ foreach (keys %{$hash->{READINGS}}){
+ my $newkey = $_;
+ $newkey =~
+ s/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/sprintf('%03d',$1).".".sprintf('%03d',$2).".".sprintf('%03d',$3).".".sprintf('%03d',$4)/e
+ if($value and $value == 1);
+ $newkey =~
+ s/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/sprintf('%00d',$1).".".sprintf('%00d',$2).".".sprintf('%00d',$3).".".sprintf('%00d',$4)/e
+ if($cmd eq "del" or !$value);
+ $hash->{READINGS}{$newkey} = delete $hash->{READINGS}{$_};
+ }
+
+ my $knownHosts = ReadingsVal($SELF, ".knownHosts", "");
+ $knownHosts =~
+ s/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/sprintf('%03d',$1).".".sprintf('%03d',$2).".".sprintf('%03d',$3).".".sprintf('%03d',$4)/ge
+ if($value and $value == 1);
+ $knownHosts =~
+ s/([0-9]+)\.([0-9]+)\.([0-9]+)\.([0-9]+)/sprintf('%00d',$1).".".sprintf('%00d',$2).".".sprintf('%00d',$3).".".sprintf('%00d',$4)/ge
+ if($cmd eq "del" or !$value);
+
+ readingsSingleUpdate($hash, ".knownHosts", $knownHosts, 0);
+ }
+
+ return if(IsDisabled($SELF));
+
+ if($attribute eq "interval"){
+ my $interval = $cmd eq "set" ? $value : 900;
+ $interval = 900 if(!looks_like_number($interval));
+ $interval = 30 if($interval < 30);
+
+ $hash->{INTERVAL} = $interval;
+
+ RemoveInternalTimer($hash);
+ InternalTimer(
+ gettimeofday() + $hash->{INTERVAL}, "Nmap_statusRequest", $hash
+ );
+ }
+
+ return;
+}
+
+# blocking Fn #################################################################
+sub Nmap_statusRequest($) {
+ my ($hash) = @_;
+ my $SELF = $hash->{NAME};
+ my $TYPE = $hash->{TYPE};
+
+ BlockingKill($hash->{helper}{RUNNING_PID})
+ if(defined($hash->{helper}{RUNNING_PID}));
+ RemoveInternalTimer($hash);
+
+ return if(IsDisabled($SELF));
+
+ InternalTimer(
+ gettimeofday() + $hash->{INTERVAL}, "Nmap_statusRequest", $hash
+ );
+
+ if(
+ AttrVal($SELF, "sudo", 0) == 1
+ && qx(sudo -n $hash->{PATH} -V 2>&1 > /dev/null)
+ ){
+ readingsSingleUpdate($hash, "state", "aborted", 1);
+ Log3($SELF, 1, "$TYPE ($SELF) - sudo password required");
+
+ return;
+ }
+
+ readingsSingleUpdate($hash, "state", "running", 1);
+ Log3($SELF, 3, "$TYPE ($SELF) - starting network scan");
+
+ $hash->{helper}{RUNNING_PID} = BlockingCall(
+ "Nmap_blocking_statusRequest", $SELF
+ , "Nmap_done", $hash->{INTERVAL}-1
+ , "Nmap_aborted", $hash
+ ) unless(exists($hash->{helper}{RUNNING_PID}));
+
+ return;
+}
+
+sub Nmap_blocking_statusRequest($) {
+ my ($SELF) = @_;
+ my ($hash) = $defs{$SELF};
+ my @ret = $SELF;
+ my $NP = new Nmap::Parser;
+ my $path =
+ (AttrVal($SELF, "sudo", 0) == 1 ? "sudo " : "")
+ . $hash->{PATH}
+ ;
+ my $excludeHosts = AttrVal($SELF, "excludeHosts", undef);
+ my $args = $hash->{ARGS};
+ $args .= " --exclude $excludeHosts" if($excludeHosts);
+
+ open(STDERR, ">", "/dev/null");
+
+ $NP->parsescan($path, $args, $hash->{DEF});
+ my $NPS = $NP->get_session();
+
+ push(@ret, $NPS->nmap_version());
+ push(@ret, int($NP->all_hosts()));
+ push(@ret, $NPS->finish_time() - $NPS->start_time());
+
+ my @hostsUp = $NP->all_hosts("up");
+
+ foreach (@hostsUp){
+ my $hostname = $_->hostname() ? $_->hostname() : $_->ipv4_addr();
+ my $macAddress = $_->mac_addr() ? $_->mac_addr() : "Unknown";
+ my $macVendor = $_->mac_vendor() ? $_->mac_vendor() : "Unknown";
+
+ push(@ret, $_->ipv4_addr()."|$hostname|$macAddress|$macVendor");
+ }
+
+ return (join("||", @ret));
+}
+
+sub Nmap_done($) {
+ my ($string) = @_;
+
+ return unless(defined($string));
+
+ my ($SELF, $NmapVersion, $hostsScanned, $scanDuration, @hostsUp) =
+ split("\\|\\|", $string);
+ my ($hash) = $defs{$SELF};
+ my $TYPE = $hash->{TYPE};
+ my $devAliases = AttrVal($SELF, "devAlias", undef);
+ my %knownHosts = map{$_, 0} split(",", ReadingsVal($SELF, ".knownHosts", ""));
+ my $metaReadingAttrVal = AttrVal($SELF, "metaReading", "ip");
+
+ delete($hash->{helper}{RUNNING_PID});
+
+ readingsBeginUpdate($hash);
+ readingsBulkUpdate($hash, "NmapVersion", $NmapVersion);
+ readingsBulkUpdate($hash, "hostsScanned", $hostsScanned);
+ readingsBulkUpdate($hash, "hostsUp", int(@hostsUp));
+ readingsBulkUpdate($hash, "scanDuration", $scanDuration);
+
+ foreach (@hostsUp){
+ my ($ip, $hostname, $macAddress, $macVendor) = split("\\|", $_);
+ my ($oldMetaReading, $metaReading);
+ my $alias = $hostname;
+
+ if(
+ $devAliases && $devAliases =~ /$macAddress:(.+?)(\s|$)/
+ || $devAliases && $devAliases =~ /$hostname:(.+?)(\s|$)/
+ || $devAliases && $devAliases =~ /$ip:(.+?)(\s|$)/
+ ){
+ $alias = $1;
+ }
+
+ if($metaReadingAttrVal eq "ip"){
+ $metaReading = $ip;
+ }
+ elsif($metaReadingAttrVal eq "macAddress"){
+ $metaReading = $macAddress ne "Unknown" ? $macAddress : $ip;
+ }
+ elsif($metaReadingAttrVal eq "alias"){
+ $metaReading = $alias;
+ }
+ elsif($metaReadingAttrVal eq "hostname"){
+ $metaReading = $hostname;
+ }
+
+ $metaReading =~ s/([0-9]+)/sprintf('%03d',$1)/ge
+ if(AttrVal($SELF, "leadingZeros", 0) == 1 && $metaReading eq $ip);
+ $metaReading =~ s/:/-/g;
+ $knownHosts{$metaReading} = 1;
+
+ if($macAddress ne "Unknown"){
+ foreach (keys %knownHosts){
+ $oldMetaReading = $_
+ if(ReadingsVal($SELF, $_."_macAddress", "") eq $macAddress);
+
+ next unless($oldMetaReading);
+
+ last;
+ }
+ if(
+ $oldMetaReading
+ && ReadingsVal($SELF, $oldMetaReading."_ip", "") ne $ip
+ ){
+ Log3($SELF, 4, "$TYPE ($SELF) - new IP: $hostname ($ip)");
+
+ DoTrigger($SELF, "new IP: $hostname ($ip)");
+ }
+ }
+
+ unless($hash->{READINGS}{$metaReading."_hostname"} || $oldMetaReading){
+ Log3($SELF, 4, "$TYPE ($SELF) - new host: $hostname ($ip)");
+
+ DoTrigger($SELF, "new host: $hostname ($ip)");
+ }
+
+ if(
+ $oldMetaReading && $oldMetaReading ne $metaReading
+ && AttrVal($SELF, "keepReadings", 0) == 0
+ ){
+ delete $knownHosts{$oldMetaReading};
+ delete $hash->{READINGS}{$oldMetaReading."_alias"};
+ delete $hash->{READINGS}{$oldMetaReading."_hostname"};
+ delete $hash->{READINGS}{$oldMetaReading."_ip"};
+ delete $hash->{READINGS}{$oldMetaReading."_lastSeen"};
+ delete $hash->{READINGS}{$oldMetaReading."_macAddress"};
+ delete $hash->{READINGS}{$oldMetaReading."_macVendor"};
+ delete $hash->{READINGS}{$oldMetaReading."_state"};
+ delete $hash->{READINGS}{$oldMetaReading."_uptime"};
+
+ Log3($SELF, 4, "$TYPE ($SELF) - delete old host: $oldMetaReading");
+ }
+
+ readingsBulkUpdate($hash, $metaReading."_alias", $alias);
+ readingsBulkUpdate($hash, $metaReading."_hostname", $hostname);
+ readingsBulkUpdate($hash, $metaReading."_ip", $ip);
+ readingsBulkUpdate($hash, $metaReading."_lastSeen", TimeNow());
+ readingsBulkUpdate($hash, $metaReading."_macAddress", $macAddress)
+ if($macAddress ne "Unknown");
+ readingsBulkUpdate($hash, $metaReading."_macVendor", $macVendor)
+ if($macVendor ne "Unknown");
+ readingsBulkUpdate($hash, $metaReading."_state", "present");
+
+ Nmap_updateUptime($hash, $metaReading);
+ }
+
+ foreach (keys %knownHosts){
+ next if(
+ $knownHosts{$_} == 1
+ || ReadingsVal($SELF, $_."_state", "present") eq "absent"
+ );
+
+ my $absenceThreshold = ReadingsVal($SELF, ".".$_."_absenceThreshold", 1);
+
+ if($absenceThreshold >= AttrVal($SELF, "absenceThreshold", 1)){
+ delete $hash->{READINGS}{".".$_."_absenceThreshold"};
+
+ readingsBulkUpdate($hash, $_."_state", "absent");
+
+ Nmap_updateUptime($hash, $_, 0);
+ }
+ else{
+ $absenceThreshold ++;
+
+ readingsBulkUpdate($hash, ".".$_."_absenceThreshold", $absenceThreshold);
+ readingsBulkUpdate($hash, $_."_state", "present");
+
+ Nmap_updateUptime($hash, $_);
+ }
+ }
+
+ readingsBulkUpdate($hash, ".knownHosts", join(",", sort(keys %knownHosts)));
+ readingsBulkUpdate($hash, "knownHosts", int(keys %knownHosts));
+ readingsBulkUpdate($hash, "state", "done");
+ readingsEndUpdate($hash, 1);
+
+ my $deleteOldReadings = AttrVal($SELF, "deleteOldReadings", 0);
+ Nmap_deleteOldReadings($hash, $deleteOldReadings) if($deleteOldReadings != 0);
+
+ Log3($SELF, 3, "$TYPE ($SELF) - network scan done");
+
+ return;
+}
+
+sub Nmap_aborted($) {
+ my ($hash) = @_;
+ my $SELF = $hash->{NAME};
+ my $TYPE = $hash->{TYPE};
+
+ delete($hash->{helper}{RUNNING_PID});
+
+ Log3($SELF, 2, "$TYPE ($SELF) - network scan aborted");
+ readingsSingleUpdate($hash, "state", "aborted", 1);
+
+ return;
+}
+
+# module Fn ###################################################################
+sub Nmap_deleteOldReadings($$) {
+ my ($hash, $value) = @_;
+ my $SELF = $hash->{NAME};
+ my $TYPE = $hash->{TYPE};
+ $value = eval($value);
+
+ unless(looks_like_number($value)){
+ my $ret = "no numeric value given for deleteOldReadings";
+
+ Log3($SELF, 2, "$TYPE ($SELF) - $ret");
+
+ return($ret);
+ }
+
+ my %knownHosts =
+ map{$_, 0} split(",", ReadingsVal($SELF, ".knownHosts", ""));
+
+ foreach (keys %knownHosts) {
+ if(ReadingsAge($SELF, $_."_lastSeen", 0) >= $value){
+ CommandDeleteReading(undef, "$SELF $_.*");
+ delete $knownHosts{$_};
+ }
+ }
+
+ readingsBeginUpdate($hash);
+ readingsBulkUpdate($hash, ".knownHosts", join(",", sort(keys %knownHosts)));
+ readingsBulkUpdate($hash, "knownHosts", int(keys %knownHosts));
+ readingsEndUpdate($hash, 1);
+
+ Log3($SELF, 4, "$TYPE ($SELF) - delete Readings older than $value seconds");
+
+ return;
+}
+
+sub Nmap_updateUptime($$;$) {
+ my ($hash, $metaReading, $uptime) = @_;
+ my $SELF = $hash->{NAME};
+
+ my $uptime =(
+ ReadingsVal($SELF, $metaReading."_uptime", 0)
+ + ReadingsAge($SELF, $metaReading."_uptime", 0)
+ ) unless($uptime);
+
+ my $s = $uptime;
+ my $d = int($s / 86400);
+ $s -= $d * 86400;
+ my $h = int($s / 3600);
+ $s -= $h * 3600;
+ my $m = int($s / 60);
+ $s -= $m * 60;
+
+ my $uptimeText = sprintf(
+ "%d days, %02d hours, %02d minutes, %02d seconds"
+ , $d, $h, $m, $s
+ );
+
+ readingsBulkUpdate($hash, $metaReading."_uptime", $uptime);
+ readingsBulkUpdate($hash, $metaReading."_uptimeText", $uptimeText);
+
+ return;
+}
+
+1;
+
+# commandref ##################################################################
+=pod
+=item helper
+=item summary Interpret of an Nmap network scans
+=item summary_DE Auswertung eines Nmap Netzwerkscans
+
+=begin html
+
+
+Nmap
+( en | de )
+
+
+ Nmap is the FHEM module to perform a network scan with Nmap and to display information about the available network devices.
+ If a new device is detected, an event
+ "<name> new host: <hostname> (<IPv4>)"
+ is generated.
+ If a device with a known MAC address has been given a new IP, an event
+ "<name> new IP: <hostname> (<IPv4>)"
+ is generated.
+
+ Prerequisites:
+
+ The "Nmap" program and the Perl module "Nmap::Parser" are required.
+ Under Debian (based) system, these can be installed using "apt-get
+ install nmap libnmap-parser-perl".
+
+
+
+ Define
+
+ define <name> Nmap <target specification>
+ In the <target specification> are all target hosts, which are to be
+ scanned.
+ The simplest case is the description of an IP destination address or a
+ target host name for scanning.
+ To scan an entire network of neighboring hosts, Nmap supports CIDR-style
+ addresses. Numbits can be appended to an IPv4 address or hostname, and
+ Nmap will scan all IP addresses where the first numbits match those of
+ the given IP or host name. For example, 192.168.10.0/24 would scan the
+ 256 hosts between 192.168.10.0 and 192.168.10.255. 192.168.10.40/24 would
+ scan exactly the same targets.
+ See
+
+ Nmap Manpage (Specifying Destinations)
+ .
+
+
+ Set
+
+ -
+
clear readings
+ Deletes all readings except "state".
+
+ -
+
deleteOldReadings <s>
+ Deletes all readings older than <s> seconds.
+
+ -
+
interrupt
+ Cancels a running scan.
+
+ -
+
statusRequest
+ Starts a network scan.
+
+
+
+ Readings
+
+ General Readings:
+
+ -
+
NmapVersion
+ The version number of the installed Nmap program.
+
+ -
+
hostsScanned
+ The number of scanned addresses.
+
+ -
+
hostsUp
+ The number of available network devices.
+
+ -
+
knownHosts
+ The number of known network devices.
+
+ -
+
scanDuration
+ The scan time in seconds.
+
+ -
+
state
+
+ -
+
Initialized
+ Nmap has been defined or enabled.
+
+ -
+
running
+ A network scan is running.
+
+ -
+
done
+ Network scan completed successfully.
+
+ -
+
aborted
+ The network scan was aborted due to a timeout or by the user.
+
+ -
+
disabled
+ Nmap has been disabled.
+
+
+
+
+ Host-specific readings:
+
+ -
+
<metaReading>_alias
+ Alias which is specified under the attribute "devAlias" for the
+ network device. If no alias is specified, the hostname is displayed.
+
+ -
+
<metaReading>_hostname
+ Hostname of the network device. If this can not be determined, the IPv4
+ address is displayed.
+
+ -
+
<metaReading>_ip
+ IPv4 address of the network device.
+
+ -
+
<metaReading>_lastSeen
+ The time at which the network device was last seen as.
+
+ -
+
<metaReading>_macAddress
+ MAC address of the network device. This can only be determined if the
+ scan is executed with root privileges.
+
+ -
+
<metaReading>_macVendor
+ Probable manufacturer of the network device. This can only be
+ determined if the scan is executed with root privileges.
+
+ -
+
<metaReading>_state
+ State of the network device. Can be either "absent" or "present".
+
+ -
+
<metaReading>_uptime
+ Time in seconds since the network device is reachable.
+
+ -
+
<metaReading>_uptimeText
+ Time in "d days, hh hours, mm minutes, ss seconds" since the network
+ device is reachable.
+
+
+
+ Attribute
+
+ -
+
absenceThreshold <n>
+ The number of network cans that must result in "absent" before the
+ state of a network device changes to "absent". With this function you
+ can verify the absence of a device before the status is changed to
+ "absent". If this attribute is set to a value >1, the reading
+ "<metaReading>_state" remains on "present" until the final status
+ changes to "absent".
+
+ -
+
args <args>
+ Arguments for the Nmap scan.
+ The default is "-sn".
+
+ -
+
deleteOldReadings <s>
+ After a network scan, all host-specific readings older than <s>
+ seconds are deleted
+
+ -
+
+ devAlias <ID>:<ALIAS> <ID2>:<ALIAS2> ...
+
+ A whitespace separated list of <ID>:<ALIAS> pairs that can be used to give an alias to network devices.
+ The ID can be MAC address, hostname or IPv4 address.
+ Examples:
+
+ MAC address:
+
+ attr <name> devAlias 5C:51:88:A5:94:1F:Michaels_Handy_byMAC
+
+ Hostname:
+
+ attr <name> devAlias
+ android-87c7a6221093d830:Michaels_Handy_byHOST
+
+ IPv4 address:
+
+ attr <name> devAlias 192.168.1.130:Michaels_Handy_byIP
+
+
+
+ -
+
disable 1
+ A running scan is canceled and no new scans are started.
+
+ -
+
excludeHosts <target specification>
+ All target hosts in the <target specification> are skipped during the scan.
+
+ -
+
interval <seconds>
+ Interval in seconds in which the scan is performed.
+ The default value is 900 seconds and the minimum value is 30 seconds.
+
+ -
+
keepReadings 1
+ If a new IP address is recognized for a device with a known MAC
+ address, the invalid readings are deleted unless this attribute is set.
+
+ -
+
leadingZeros 1
+ For the readings, the IPv4 addresses are displayed with leading zeros.
+
+ -
+
metaReading <metaReading>
+ You can specify "alias", "hostname", "ip" or "macAddress" as
+ <metaReading> and is the identifier for the readings.
+ The default is "ip".
+
+ -
+
path
+ Path under which the Nmap program is to be reached.
+ The default is "/urs/bin/nmap".
+
+ -
+
sudo 1
+ The scan runs with root privileges.
+ The prerequisite is that the user has these rights under the FHEM. For
+ the user "fhem", on a Debian (based) system, they can be set in the
+ "/etc/sudoers" file. For this, the line "fhem ALL=(ALL) NOPASSWD:
+ /usr/bin/nmap" must be inserted in the section "#User privilege
+ specification".
+
+
+
+
+
+=end html
+
+=begin html_DE
+
+
+Nmap
+( en | de )
+
+
+ Nmap ist das FHEM Modul um einen Netzwerkscan mit Nmap durchzuführen
+ und Informationen über die erreichbaren Netzwerkgeräte
+ darzustellen.
+ Wird ein neues Gerät erkannt wird ein Event
+ "<name> new host: <hostname> (<IPv4>)"
+ erzeugt.
+ Wird erkannt, dass ein Gerät mit bekannter MAC-Adresse eine neue IP
+ erhalten hat wird ein Event
+ "<name> new IP: <hostname> (<IPv4>)"
+ erzeugt.
+
+ Vorraussetzungen:
+
+ Das Programm "Nmap" sowie das Perl-Modul "Nmap::Parser" werden
+ benötigt.
+ Unter Debian (basierten) System, können diese mittels
+ "apt-get install nmap libnmap-parser-perl"
+ installiert werden.
+
+
+
+ Define
+
+ define <name> Nmap <target specification>
+ In der <target specification> stehen alle Zielhosts, die gescannet
+ werden sollen.
+ Der einfachste Fall ist die Beschreibung einer IP-Zieladresse oder eines
+ Zielhostnamens zum Scannen.
+ Um ein ganzes Netzwerk benachbarter Hosts zu scannen unterstützt
+ Nmap Adressen im CIDR-Stil. Es können /numbits an eine IPv4-Adresse
+ oder an einen Hostnamen angefügt werden, und Nmap wird alle
+ IP-Adressen scannen, bei denen die ersten numbits mit denen der gegebenen
+ IP oder des gegebenen Hostnamens übereinstimmen. Zum Beispiel
+ würde 192.168.10.0/24 die 256 Hosts zwischen 192.168.10.0 und
+ 192.168.10.255 scannen. 192.168.10.40/24 würde genau dieselben Ziele
+ scannen.
+ Siehe
+
+ Nmap Man Page (Angabe von Zielen)
+ .
+
+
+ Set
+
+ -
+
clear readings
+ Löscht alle Readings außer "state".
+
+ -
+
deleteOldReadings <s>
+ Löscht alle Readings die älter sind als <s> Sekunden.
+
+ -
+
interrupt
+ Bricht einen laufenden Scan ab.
+
+ -
+
statusRequest
+ Startet einen Netzwerkscan.
+
+
+
+ Readings
+
+ Allgemeine Readings:
+
+ -
+
NmapVersion
+ Die Versionsnummer des installierten Nmap Programms.
+
+ -
+
hostsScanned
+ Die Anzahl der gescannten Adressen.
+
+ -
+
hostsUp
+ Die Anzahl der erreichbaren Netzwerkgeräte.
+
+ -
+
knownHosts
+ Die Anzahl der bekannten Netzwerkgeräte.
+
+ -
+
scanDuration
+ Die Scan-Dauer in Sekunden.
+
+ -
+
state
+
+ -
+
Initialized
+ Nmap wurde definiert oder enabled.
+
+ -
+
running
+ Ein Netzwerkscan wird ausgeführt.
+
+ -
+
done
+ Der Netzwerkscan wurde erfolgreich abgeschlossen.
+
+ -
+
aborted
+ Der Netzwerkscan wurde aufgrund einer Zeitüberschreitung oder
+ durch den Benutzer abgebrochen.
+
+ -
+
disabled
+ Nmap wurde deaktiviert.
+
+
+
+
+ Hostspezifische Readings:
+
+ -
+
<metaReading>_alias
+ Alias welcher unter dem Attribut "devAlias" für das Netzwerkgerät
+ angegeben ist. Ist kein Alias angegeben wird der Hostname angezeigt.
+
+ -
+
<metaReading>_hostname
+ Hostname des Netzwerkgeräts. Kann dieser nicht ermittel werden
+ wird die IPv4-Adresse angezeigt.
+
+ -
+
<metaReading>_ip
+ IPv4-Adresse des Netzwerkgeräts.
+
+ -
+
<metaReading>_lastSeen
+ Der Zeitpunkt zu dem das Netzwerkgerät das letzte mal als gesehen
+ wurde.
+
+ -
+
<metaReading>_macAddress
+ MAC-Adresse des Netzwerkgeräts. Diese kann nur ermittelt werden,
+ wenn der Scan mit Root-Rechten ausgeführt wird.
+
+ -
+
<metaReading>_macVendor
+ Vermutlicher Hersteller des Netzwerkgeräts. Dieser kann nur
+ ermittelt werden, wenn der Scan mit Root-Rechten ausgeführt wird.
+
+ -
+
<metaReading>_state
+ Status des Netzwerkgeräts. Kann entweder "absent" oder "present"
+ sein.
+
+ -
+
<metaReading>_uptime
+ Zeit in Sekunden seit der das Netzwerkgerät erreichbar ist.
+
+ -
+
<metaReading>_uptimeText
+ Zeit in "d days, hh hours, mm minutes, ss seconds" seit der das
+ Netzwerkgerät erreichbar ist.
+
+
+
+ Attribute
+
+ -
+
absenceThreshold <n>
+ Die Anzahl an Netzwerkscans, welche in "absent" resultieren
+ müssen, bevor der Status eines Netzwerkgeräts auf "absent"
+ wechselt. Mit dieser Funktion kann man die Abwesenheit eines
+ Gerätes verifizieren bevor der Status final auf "absent"
+ geändert wird. Wenn dieses Attribut auf einen Wert >1 gesetzt
+ ist, verbleibt das Reading "<metaReading>_state" auf "present",
+ bis der Status final auf "absent" wechselt.
+
+ -
+
args <args>
+ Argumente für den Nmap-Scan.
+ Die Vorgabe ist "-sn".
+
+ -
+
deleteOldReadings <s>
+ Nach einem Netzwerkscan werden alle hostspezifischen Readings, die
+ älter sind als <s> Sekunden, gelöscht
+
+ -
+
+ devAlias <ID>:<ALIAS> <ID2>:<ALIAS2> ...
+
+ Eine Leerzeichen-getrennte getrennte Liste von <ID>:<ALIAS>
+ Paaren, die dazu genutzt werden kann um Netzwerkgeräten einen
+ Alias zu geben.
+ Die ID kann dabei MAC-Adresse, hostname oder IPv4-Adresse sein.
+ Beispiele:
+
+ MAC-Adresse:
+
+ attr <name> devAlias 5C:51:88:A5:94:1F:Michaels_Handy_byMAC
+
+ hostname:
+
+ attr <name> devAlias
+ android-87c7a6221093d830:Michaels_Handy_byHOST
+
+ IPv4-Adresse:
+
+ attr <name> devAlias 192.168.1.130:Michaels_Handy_byIP
+
+
+
+ -
+
disable 1
+ Ein laufender Scan wird abgebrochen und es werden keine neuen Scans
+ gestartet.
+
+ -
+
excludeHosts <target specification>
+ In der <target specification> stehen alle Zielhosts, die beim
+ Scan übersprungen werden sollen.
+
+ -
+
interval <seconds>
+ Intervall in Sekunden in dem der Scan durchgeführt wird.
+ Der Vorgabewert ist 900 Sekunden und der Mindestwert 30 Sekunden.
+
+ -
+
keepReadings 1
+ Wird für ein Gertät mit bekannter MAC-Adresse eine neue IP-Adresse
+ erkannt, werden die ungültig gewordenen Readings gelöscht es sei denn
+ dieses Attribut ist gesetzt.
+
+ -
+
leadingZeros 1
+ Bei den Readings-Namen werden die IPv4-Adressen mit führenden
+ Nullen dargestellt.
+
+ -
+
metaReading <metaReading>
+ Als <metaReading> kann "alias", "hostname", "ip" oder
+ "macAddress" angegeben werden und ist der Bezeichner für die
+ Readings.
+ Die Vorgabe is "ip".
+
+ -
+
path
+ Pfad unter dem das Nmap Programm zu erreichen ist.
+ Die Vorgabe ist "/urs/bin/nmap".
+
+ -
+
sudo 1
+ Der Scan wird mit Root-Rechten ausgeführt.
+ Voraussetzung ist, dass der Benutzer unter dem FHEM ausgeführt
+ diese Rechte besitzt. Für den Benutzer "fhem", auf einem Debian
+ (basierten) System, lassen sich diese in der Datei "/etc/sudoers"
+ festlegen. Dafür muss im Abschnitt "# User privilege
+ specification" die Zeile "fhem ALL=(ALL) NOPASSWD: /usr/bin/nmap"
+ eingefügt werden.
+
+
+
+
+
+=end html_DE
+=cut
diff --git a/fhem/MAINTAINER.txt b/fhem/MAINTAINER.txt
index 3a70646ed..653b73078 100644
--- a/fhem/MAINTAINER.txt
+++ b/fhem/MAINTAINER.txt
@@ -300,6 +300,7 @@ FHEM/74_NUKIBridge.pm CoolTux http://forum.fhem.de Sonstige
FHEM/74_AMAD.pm CoolTux http://forum.fhem.de Unterstuetzende Dienste
FHEM/74_HOMBOT.pm CoolTux http://forum.fhem.de Unterstuetzende Dienste
FHEM/74_NUKIDevice.pm CoolTux http://forum.fhem.de Sonstige Systeme
+FHEM/74_Nmap.pm igami http://forum.fhem.de Unterstuetzende Dienste
FHEM/74_XiaomiFlowerSens CoolTux http://forum.fhem.de Sonstige Systeme
FHEM/74_THINKINGCLEANER.pm loredo http://forum.fhem.de Unterstuetzende Dienste
FHEM/74_Unifi.pm rapster http://forum.fhem.de Automatisierung