From 344d5e36f9fc3c15e243f95048f20d85f98f7fc4 Mon Sep 17 00:00:00 2001 From: rudolfkoenig <> Date: Mon, 6 Feb 2012 16:48:39 +0000 Subject: [PATCH] NetIO230B by Andy git-svn-id: https://svn.fhem.de/fhem/trunk/fhem@1240 2b470e98-0d58-463d-a4d8-8e2adae1ed80 --- CHANGED | 1 + FHEM/24_NetIO230B.pm | 290 +++++++++++++++++++++++++++++++++++++++++++ docs/commandref.html | 98 +++++++++++++++ 3 files changed, 389 insertions(+) create mode 100644 FHEM/24_NetIO230B.pm diff --git a/CHANGED b/CHANGED index f77b2dbe3..3c46bfdef 100644 --- a/CHANGED +++ b/CHANGED @@ -8,6 +8,7 @@ - feature: updatefhem backup is using tar+gzip now - feature: EIB: introduce Get, interpret received values upon defined model (by datapoint types) (Maz) + - feature: NetIO230B module by Andy - 2011-12-31 (5.2) - bugfix: applying smallscreen attributes to firefox/opera diff --git a/FHEM/24_NetIO230B.pm b/FHEM/24_NetIO230B.pm new file mode 100644 index 000000000..536f648e2 --- /dev/null +++ b/FHEM/24_NetIO230B.pm @@ -0,0 +1,290 @@ +################################################################ +# fhem-module for NetIO 230B Power Distribution Unit +# +# http://www.koukaam.se/showproduct.php?article_id=1502 +# +# Usage: +# There are 2 modes: +# +# (1) - define the IP, user and password directly in fhem's fhem.cfg (or UI). +# +# define NetIO1 [ ]; +# e.g. define NetIO1 192.168.178.2 1 admin admin; +# +# if you omit the user credentials, the module will look for a configuration file, +# if no configuration file is found, it tries with 'admin', 'admin' +# +# +# (2) - define your credentials using a config file. +# +# define NetIO1 []; +# define NetIO1 192.168.178.2 1 /var/log/fhem/netio.conf); +# +# if you omit the configuration parameter, the module will look for a configuration +# file at: /var/log/fhem/netio.conf +# +# NetIO230B Configuration file format: +# +# %config= ( +# host => "192.168.xx.xx", +# user => "anyusername_without_spaces", +# password => "anypassword_without_spaces" +# ); +# +################################################################ +# created 2012 by Andy Fuchs +#--------- +# Changes: +#--------- +# 2012-02-03 0.1 initial realease +# + +################################################################ +package main; + +use strict; +use warnings; +use Data::Dumper; +use LWP::UserAgent; +use HTTP::Request; + +use constant PARAM_NAME => 1; +use constant PARAM_HOST => 2; +use constant PARAM_SOCK => 3; +use constant PARAM_USER => 4; +use constant PARAM_PASS => 5; +use constant PARAM_FILE => 4; + +use constant DEBUG => 1; + +sub +NetIO230B_Initialize($) +{ + my ($hash) = @_; + + $hash->{SetFn} = "NetIO230B_Set"; + $hash->{GetFn} = "NetIO230B_Get"; + $hash->{DefFn} = "NetIO230B_Define"; + $hash->{AttrList} = "loglevel:0,1,2,3,4,5,6"; + +} + +################################### +sub +NetIO230B_Set($@) +{ + my ($hash, @a) = @_; + + return "no set value specified" if(int(@a) != 2); + return "Unknown argument $a[1], choose one of on off " if($a[1] eq "?"); + + my $state = $a[1]; #initialize state to the passed parameter + my $result = "command was not executed - $state is not 'on' or 'off'"; + if ($state eq "on" || $state eq "off") + { + $hash->{STATE} = $state; + $state = int($state eq "on"); + #prepare the sockets default parameters; 'u' means: don't touch + my @values=("u","u","u","u"); + my @sockets = @{$hash->{SOCKETS}}; + + foreach (@sockets) { + $values[$_-1] = $state; + $hash->{READINGS}{"socket$_"}{TIME} = TimeNow(); + $hash->{READINGS}{"socket$_"}{VAL} = $state; + } + + $result = NetIO230B_Request($hash, "set", join("",@values)); + } + + Log 3, "NetIO230B set @a => $result"; + + return undef; +} + +################################### +sub +NetIO230B_Get($@) +{ + my ($hash, @a) = @_; + my $result = NetIO230B_Request($hash, "get"); + Log 3, "NetIO230B get @a => $result"; + + return $hash->{STATE}; +} + +################################### +sub +NetIO230B_Request($@) +{ + my ($hash, $cmd, $list) = @_; + my $URL=''; + my $log=''; + + $URL="http://".$hash->{HOST}."/tgi/control.tgi?l=p:". $hash->{USER}.":".$hash->{PASS}."&p="; + if($cmd eq "set") { + $URL .= "$list"; + } else { + $URL .= "l"; + } + + my $agent = LWP::UserAgent->new(env_proxy => 1,keep_alive => 1, timeout => 30); + my $header = HTTP::Request->new(GET => $URL); + my $request = HTTP::Request->new('GET', $URL, $header); + my $response = $agent->request($request); + + $log.= "Can't get $URL -- ".$response->status_line + unless $response->is_success; + + if($log ne "") + { + Log 3, "NetIO230B_Request: ".$log; + return(""); + } + + # read decoded content + my $buffer = $response->decoded_content; + + # strip html tags + $buffer =~ s/<(?:[^>'"]*|(['"]).*?\1)*>//gs; + + # strip leading whitespace + $buffer =~ s/^\s+//; + + #strip trailing whitespace + $buffer =~ s/\s+$//; + + return $buffer if ($cmd eq "set"); + + #+++todo + #555 FORBIDDEN + + #split the result into an array + my @values=split(/ */,$buffer); + + #save the values to the readings hash + my $state = "???"; + my @sockets = @{$hash->{SOCKETS}}; + foreach (@sockets) { + $hash->{READINGS}{"socket$_"}{TIME} = TimeNow(); + $hash->{READINGS}{"socket$_"}{VAL} = $values[$_-1]; + if ($state == "???") { #initialize state + $state = $values[$_-1]; + } else { + $state = "???" if ($values[$_-1] != $state); #if states are mixed show ??? + } + } + + $hash->{STATE} = $state; + + # debug output + #my %k = %{$hash->{READINGS}}; + #foreach my $r (sort keys %k) { + # Log 1, "$r S: $k{$r}{VAL} T: $k{$r}{TIME}"; + #} + + return $buffer; +} + +### _Define routing is called when fhem starts -> 'reloading' of the module does not call the define routine!! +### +sub +NetIO230B_Define($$) +{ + my ($hash, $def) = @_; + my @a = split("[ \t][ \t]*", $def); + my $paramCount = int(@a); + + Log 3, "Wrong syntax: use 'define NetIO230B [ ]' or 'define NetIO230B [ ]'" if(int(@a) < 4); #5 = mit user/pass #4 = mit config + + #provide some default settings + $hash->{CONFIGFILEPATH} = "/var/log/fhem/netio.conf"; #default file path is /var/log/fhem/netio.conf + $hash->{USER} = "admin"; + $hash->{PASS} = "admin"; + @{$hash->{SOCKETS}} = (1,2,3,4); #default to all sockets + + #mandatory parameter: 'HOST' + $hash->{HOST} = $a[PARAM_HOST]; #can be overridden, if using a config file + + #mandatory parameter: 'SOCKET #'; negative numbers are ignored + my $buf = $a[PARAM_SOCK]; + if (($buf =~ m/^\d+$/) && ($buf >=0)) { #make sure input value is a positive number + + if ($buf == 0) #input socket '0' is used as 'all' + { + @{$hash->{SOCKETS}} = (1,2,3,4); #use this number as 'array of socket-numbers' to operate on + + } elsif ($buf <= 4) #input socket is a single number <=4 + { + @{$hash->{SOCKETS}} = ($buf); #use this number as 'array of socket-numbers' to operate on + + } else { + + @{$hash->{SOCKETS}} = split("",$buf); #convert the input values to an array of sockets to operate on + } + } + + #optional parameter: 'CONFIGFILE_NAME_or_PATH' + if ($paramCount == 5) #seems a config file is passed + { + $hash->{CONFIGFILEPATH} = $a[PARAM_FILE] if defined($a[PARAM_FILE]);; + } + + #optional parameters: 'USER and PASS' + if ($paramCount != 6) + { + my %config = NetIO230B_GetConfiguration($hash); + if (%config) { + $hash->{HOST} = $config{host} if (defined($config{host})); + $hash->{USER} = $config{user} if (defined($config{user})); + $hash->{PASS} = $config{password} if (defined($config{password})); + } else { + + Log 3, "NetIO230B: Configuration could not be read. Trying default values...\n"; + } + + } else { + #in any other case + $hash->{USER} = $a[PARAM_USER] if defined($a[PARAM_USER]); + $hash->{PASS} = $a[PARAM_PASS] if defined($a[PARAM_PASS]); + } + + Log 3, "NetIO230B: device opened at host: $hash->{HOST} => @a\n"; + + return undef; +} +########################################## +# +# NetIO230B Configuration-Format: +# +# %config= ( +# host => "192.168.xx.xx", +# user => "anyusername_without_spaces", +# password => "anypassword_without_spaces" +# ); +# +# +########################################## + +### _GetConfiguration reads a plain text file containing arbitrary information +sub +NetIO230B_GetConfiguration($) +{ + my ($hash)= @_; + my $configfilename = $hash->{CONFIGFILEPATH}; + + if(!open(CONFIGFILE, $configfilename)) + { + Log 3, "NetIO230B: Cannot open settings file '$configfilename'."; + return (); + } + my @configfile=; + close(CONFIGFILE); + + my %config; + eval join("", @configfile); + + return %config; +} + +1; diff --git a/docs/commandref.html b/docs/commandref.html index 0a35675f7..72f7db4ff 100644 --- a/docs/commandref.html +++ b/docs/commandref.html @@ -105,6 +105,7 @@ M232   M232Counter   M232Voltage   + NetIO230B   OREGON   OWFS   OWTEMP   @@ -6492,6 +6493,103 @@ Terminating
  • loglevel

  • + + + +

    NetIO230B

    +
      +

      + fhem-module for NetIO 230B Power Distribution Unit    (see: NetIO 230B + (koukaam.se)) +

      + Note: this module needs the HTTP::Request and LWP::UserAgent perl modules. +
      + Please also note: the PDU must use firmware 3.1 or later and set to unencrypted mode. +

      + + Define +
        + +
      • define <name> NetIO230B <ip-address> <socket number + > [<user name> <password>]
      • + +
      • define <name> NetIO230B <ip-address> <socket number + > [<config file path>]
      • + +

        + Defines a switching device, where sockets can be switched +

        +
          +
        • separately (just use 0-4 as socket number)
        • +
        • all together (use 1234 as socket number)
        • +
        • in arbitrary groups (e.g 13 switches socket 1 and 3, 42 + switches socket 2 and 4, etc...), invalid numbers are + ignored
        • +
        +

        + User name and password are optional. When no user name or + password is passed, the module looks for a configfile at + '/var/log/fhem/netio.conf'. If no config file is found, it + uses 'admin/admin' as user/pass, since this is the default + configuration for the device. +

        + Alternatively you can pass a path to a configfile instead of + the user/pass combo. (e.g. /var/tmp/tmp.conf) + Configfile-Format:
        +

          + + %config= (
          +    host => "192.168.61.40",
          +    user => "admin",
          +    password => "admin"
          + );
          +

          (All settings optional) +
        +

        +

        Examples:

        +
          +
        • define Socket3 NetIO230B 192.168.178.10 3
        • +
        • define Socket1_and_4 NetIO230B 192.168.178.10 14
        • +
        • define coffeemaker NetIO230B 192.168.178.10 1 username secretpassword
        • +
        • define coffeemaker_and_light NetIO230B 192.168.178.10 23 /var/log/kitchen.conf
        • +
        +
      +
      + + + Get +
        + get <name> state +

        + returns the state of the socket(s)
        + + Example: +
          + get coffeemaker_and_light   => on or off
          +
        +
        +
      + + + Set +
        + set <name> <value> +

        + where value is one of:
        +
        +		on
        +		off
        +		
        + Examples: +
          + set coffeemaker_and_light on
          +
        +
        +
      +
    + +

    TellStick