# $Id$ ############################################################################## # # 70_HYDRAWISE.pm # An FHEM Perl module for controlling a Hunter Hydrawise irigation controller. # # 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 . # ############################################################################## package main; use 5.012; use strict; use warnings; use Time::HiRes qw(gettimeofday); use JSON qw(decode_json encode_json); use Encode qw(encode_utf8 decode_utf8); use Time::Piece; use Time::Local; # use Data::Dumper; use HttpUtils; my %sets = ( stop => "", stopall => "noArg", run => "", runall => "", suspend => "", suspendall => "", renewContext => "noArg", renewRelays => "noArg", ); my %gets = ( "help" => "noArg", ); ################################### sub HYDRAWISE_Initialize { my $hash = shift; Log3 $hash, 5, 'HYDRAWISE_Initialize: Entering'; %{$hash} = ( GetFn => 'HYDRAWISE_Get', SetFn => 'HYDRAWISE_Set', DefFn => 'HYDRAWISE_Define', UndefFn => 'HYDRAWISE_Undefine', AttrList => "disable:0,1 $readingFnAttributes", ); return; } ################################### sub HYDRAWISE_Define { my ( $hash, $def ) = @_; my @a = split( "[ \t][ \t]*", $def ); my $name = $hash->{NAME}; Log3 $name, 5, "HYDRAWISE $name: called function HYDRAWISE_Define()"; if ( @a < 3 ) { my $msg = "Wrong syntax: define HYDRAWISE []"; Log3 $name, 4, $msg; return $msg; } $hash->{TYPE} = "HYDRAWISE"; my $api_key = $a[2]; $hash->{helper}{APIKEY} = $api_key; # use interval of 300 sec if not defined my $interval = $a[3] || 300; $hash->{INTERVAL} = $interval; unless ( defined( AttrVal( $name, "webCmd", undef ) ) ) { $attr{$name}{webCmd} = 'stopall renewContext renewRelays'; } # start the status update timer RemoveInternalTimer($hash); InternalTimer( gettimeofday() + 2, "HYDRAWISE_GetStatus", $hash, 1 ); return; } ################################### sub HYDRAWISE_Undefine { my ( $hash, $arg ) = @_; my $name = $hash->{NAME}; Log3 $name, 5, "HYDRAWISE $name: called function HYDRAWISE_Undefine()"; # De-Authenticate HYDRAWISE_SendCommand( $hash, "deauthenticate" ); # Stop the internal GetStatus-Loop and exit RemoveInternalTimer($hash); return; } ##################################### sub HYDRAWISE_GetStatus { my ( $hash, $update ) = @_; my $name = $hash->{NAME}; my $interval = $hash->{INTERVAL}; Log3 $name, 5, "HYDRAWISE $name: called function HYDRAWISE_GetStatus()"; RemoveInternalTimer($hash); InternalTimer( gettimeofday() + $interval, "HYDRAWISE_GetStatus", $hash, 0 ); return if ( AttrVal( $name, "disable", 0 ) == 1 ); # check device availability if ( !$update ) { HYDRAWISE_SendCommand( $hash, "state" ); } return; } ################################### sub HYDRAWISE_Get { my ( $hash, @a ) = @_; my $name = $hash->{NAME}; my $what; Log3 $name, 5, "HYDRAWISE $name: called function HYDRAWISE_Get()"; return "argument is missing" if ( @a < 2 ); $what = $a[1]; return _HYDRAWISE_help() if ( $what =~ /^(help)$/ ); return "Unknown argument $what, choose one of help:noArg"; } sub _HYDRAWISE_help { return << 'EOT'; ----------------------------------------------------------------------------------------------------- |renewcontext | Refresh readings customerdetail | ----------------------------------------------------------------------------------------------------- |renewRelays | Refresh readings statusdetails | ----------------------------------------------------------------------------------------------------- |run | Run zone for a period of time. 2 Parameters: "relay_id" "time_in_seconds" | ----------------------------------------------------------------------------------------------------- |runall | Run all zones for a period of time. 1 Parameter: "time_in_seconds" | ----------------------------------------------------------------------------------------------------- |stop | Stop zone. 1 Parameter: "relay_id" | ----------------------------------------------------------------------------------------------------- |stopall | Stop all currently running zones. | ----------------------------------------------------------------------------------------------------- |suspend | Suspend zone for a period of time. 3 Parameters: "relay_id" "DD.MM.YYYY" "HH24:MI" | ----------------------------------------------------------------------------------------------------- |suspendall | Suspend all zones for a period of time. 2 Parameters: "DD.MM.YYYY" "HH24:MI" | ----------------------------------------------------------------------------------------------------- EOT } ################################### sub HYDRAWISE_Set { my ( $hash, $name, $cmd, @a ) = @_; Log3 $name, 5, "HYDRAWISE $name: called function HYDRAWISE_Set()"; return "\"sets\" needs at least one parameter" if ( !$cmd ); # stopall () if ( $cmd eq "stopall" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd . $a[0]; HYDRAWISE_SendCommand( $hash, "stopall" ); readingsSingleUpdate( $hash, "state", "Set_stopall", 1 ); } # stop (relay_id) elsif ( $cmd eq "stop" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd . " " . $a[0]; return "Expected: \"\"" if ( !defined( $a[0] ) ); HYDRAWISE_SendCommand( $hash, "stop", $a[0] ); readingsSingleUpdate( $hash, "state", "Set_stop", 1 ); } # runall (custom) elsif ( $cmd eq "runall" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd . " " . $a[0]; return "Expected: \"\"" if ( !defined( $a[0] ) ); HYDRAWISE_SendCommand( $hash, "runall", "$a[0]" ); readingsSingleUpdate( $hash, "state", "Set_runall", 1 ); } # run (relay_id, custom) elsif ( $cmd eq "run" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd . " " . $a[0] . " " . $a[1]; return "Expected: \" \"" if ( !defined( $a[0] ) || !defined( $a[1] ) ); HYDRAWISE_SendCommand( $hash, "run", "$a[0] $a[1]" ); readingsSingleUpdate( $hash, "state", "Set_run", 1 ); } # suspendall (date time) elsif ( $cmd eq "suspendall" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd . " " . $a[0] . " " . $a[1]; return "Expected: \" \"" if ( !defined( $a[0] ) || !defined( $a[1] ) ); my ( $day, $month, $year ) = split /\./, $a[0]; my ( $hour, $min ) = split /\:/, $a[1]; my $time = timelocal( 00, $min, $hour, $day, $month - 1, $year - 1900 ); HYDRAWISE_SendCommand( $hash, "suspendall", $time ); readingsSingleUpdate( $hash, "state", "Set_suspendall", 1 ); } # suspend (relay_id, date, time) elsif ( $cmd eq "suspend" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd . $a[0] . " " . $a[1] . " " . $a[2]; return "Expected: \" \"" if ( !defined( $a[0] ) || !defined( $a[1] ) || !defined( $a[2] ) ); my ( $day, $month, $year ) = split /\./, $a[1]; my ( $hour, $min ) = split /\:/, $a[2]; my $time = timelocal( 00, $min, $hour, $day, $month - 1, $year - 1900 ); HYDRAWISE_SendCommand( $hash, "suspend", "$a[0] $time" ); readingsSingleUpdate( $hash, "state", "Set_suspend", 1 ); } # renewContext elsif ( $cmd eq "renewContext" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd; HYDRAWISE_SendCommand( $hash, "authenticate" ); } # relays elsif ( $cmd eq "renewRelays" ) { Log3 $name, 2, "HYDRAWISE set $name " . $cmd; HYDRAWISE_SendCommand( $hash, "relays" ); } # return usage hint else { return "Unknown argument $cmd, choose one of " . join( " ", map { "$_" . ( $sets{$_} ? ":$sets{$_}" : "" ) } keys %sets ); } return; } ############################################################################################################ # # Begin of helper functions # ############################################################################################################ ################################### sub HYDRAWISE_SendCommand { my ( $hash, $service, $type ) = @_; my $name = $hash->{NAME}; my $api_key = $hash->{helper}{APIKEY}; my $timestamp = gettimeofday(); my $timeout = 30; my $data; my $method = "GET"; Log3 $name, 5, "HYDRAWISE $name: called function HYDRAWISE_SendCommand()"; my $URL_STATUSSCHEDULE = "https://api.hydrawise.com/api/v1/statusschedule.php?api_key=" . $api_key; my $URL_CUSTOMERDETAILS = "https://api.hydrawise.com/api/v1/customerdetails.php?api_key=" . $api_key; my $URL_SETZONE = "https://api.hydrawise.com/api/v1/setzone.php?api_key=$api_key"; my $URL = ""; my $ACTION = ""; Log3 $name, 4, "HYDRAWISE $name: REQ $service"; if ( $service eq "authenticate" ) { $ACTION = 1; $URL = $URL_CUSTOMERDETAILS; } elsif ( $service eq "relays" ) { $ACTION = 1; $URL = $URL_STATUSSCHEDULE; } elsif ( $service eq "stopall" ) { $ACTION = 2; $URL = $URL_SETZONE . "&action=stopall"; } elsif ( $service eq "stop" ) { $ACTION = 2; $URL = $URL_SETZONE . "&action=stop&relay_id=$type"; } elsif ( $service eq "runall" ) { $ACTION = 2; $URL = $URL_SETZONE . "&action=runall&period_id=999&custom=$type"; } elsif ( $service eq "run" ) { $ACTION = 2; my @a = split( "[ \t][ \t]*", $type ); $URL = $URL_SETZONE . "&action=run&period_id=999&relay_id=$a[0]&custom=$a[1]"; } elsif ( $service eq "suspendall" ) { $ACTION = 2; $URL = $URL_SETZONE . "&action=suspendall&period_id=999&custom=$type"; } elsif ( $service eq "suspend" ) { $ACTION = 2; my @a = split( "[ \t][ \t]*", $type ); $URL = $URL_SETZONE . "&action=suspend&period_id=999&relay_id=$a[0]&custom=$a[1]"; } elsif ( $service eq "state" ) { $ACTION = 3; } else { # $URL .= $api_key; } # send request via HTTP-GET method Log3 $name, 5, "HYDRAWISE $name: $method $URL (" . urlDecode($data) . ")" if ( defined($data) ); Log3 $name, 5, "HYDRAWISE $name: $method $URL" if ( !defined($data) ); if ( defined($type) && $type eq "blocking" ) { my ( $err, $data ) = HttpUtils_BlockingGet( { url => $URL, timeout => 15, noshutdown => 1, data => $data, method => $method, hash => $hash, service => $service, timestamp => $timestamp, } ); return $data; } else { if ( $ACTION eq "3" ) { HttpUtils_NonblockingGet( { url => $URL_STATUSSCHEDULE, timeout => $timeout, noshutdown => 1, data => $data, method => $method, hash => $hash, service => $service, timestamp => $timestamp, callback => \&HYDRAWISE_ReceiveCommand, } ); HttpUtils_NonblockingGet( { url => $URL_CUSTOMERDETAILS, timeout => $timeout, noshutdown => 1, data => $data, method => $method, hash => $hash, service => $service, timestamp => $timestamp, callback => \&HYDRAWISE_ReceiveCommand, } ); } elsif ( $ACTION eq "2" ) { HttpUtils_NonblockingGet( { url => $URL, timeout => $timeout, noshutdown => 1, data => $data, method => $method, hash => $hash, service => $service, timestamp => $timestamp, } ); } elsif ( $ACTION eq "1" ) { HttpUtils_NonblockingGet( { url => $URL, timeout => $timeout, noshutdown => 1, data => $data, method => $method, hash => $hash, service => $service, timestamp => $timestamp, callback => \&HYDRAWISE_ReceiveCommand, } ); } } return; } ################################### sub HYDRAWISE_ReceiveCommand { my ( $param, $err, $data, $do_trigger ) = @_; my $hash = $param->{hash}; my $name = $hash->{NAME}; my $service = $param->{service}; my $cmd = $param->{cmd}; my $state = ReadingsVal( $name, "state", "off" ); my $presence = ReadingsVal( $name, "presence", "absent" ); my $rc = ( $param->{buf} ) ? $param->{buf} : $param; my $return; Log3 $name, 5, "HYDRAWISE $name: called function HYDRAWISE_ReceiveCommand() rc: $rc err: $err data: $data "; readingsBeginUpdate($hash); # device not reachable if ($err) { $presence = "absent"; $state = "off"; if ( !defined($cmd) || $cmd eq "" ) { Log3 $name, 4, "HYDRAWISE $name:$service RCV $err"; } else { Log3 $name, 4, "HYDRAWISE $name:$service/$cmd RCV $err"; } readingsBulkUpdateIfChanged( $hash, "presence", $presence ); readingsBulkUpdateIfChanged( $hash, "state", $state ); # keep last state #HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "state", "Error" ); } # data received elsif ($data) { $presence = "present"; $state = "on"; # Set reading for presence # readingsSingleUpdate( $hash, "presence", $presence, 1 ); #HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "presence", "$presence" ); # Set reading for state # readingsSingleUpdate( $hash, "state", $state, 1 ); #HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "state", "$state" ); if ( !defined($cmd) ) { Log3 $name, 4, "HYDRAWISE $name: RCV $service"; } else { Log3 $name, 4, "HYDRAWISE $name: RCV $service/$cmd"; } if ( $data ne "" ) { if ( $data =~ /^{/ || $data =~ /^\[/ ) { if ( !defined($cmd) || $cmd eq "" ) { Log3 $name, 4, "HYDRAWISE $name: RES $service - DATA: $data"; } else { Log3 $name, 4, "HYDRAWISE $name: RES $service/$cmd - $data"; } $return = decode_json( encode_utf8($data) ); #print "Decoded return: ".Dumper($return); #Debug $return; } else { Log3 $name, 4, "HYDRAWISE $name: RES ERROR $service\n" . $data; if ( !defined($cmd) || $cmd eq "" ) { Log3 $name, 5, "HYDRAWISE $name: RES ERROR $service\n$data"; } else { Log3 $name, 5, "HYDRAWISE $name: RES ERROR $service/$cmd\n$data"; } return; } } ####################### # process return data # # state if ( $service eq "state" or $service eq "longpollState" ) { if ( ref($return) eq "HASH" && !defined($cmd) ) { # controllers if ($return->{customer_id}){ HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "customer_id", $return->{customer_id} ); } if ($return->{controller_id}){ HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "cur_controller_id", $return->{controller_id} ); } if ($return->{current_controller}){ HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "cur_controller_name", $return->{current_controller} ); } if ( ref( $return->{controllers} ) eq "ARRAY" && scalar( @{ $return->{controllers} } ) > 0 ) { my $lnnumer = 1; my $last_contact; HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "controller_counts", scalar( @{ $return->{controllers} } ) ); for my $controllers ( @{ $return->{controllers} } ) { HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "ct" . $lnnumer . "_controller_id", $controllers->{controller_id} ); $last_contact = localtime( $controllers->{last_contact} ) ->strftime('%F %T'); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "ct" . $lnnumer . "_last_contact", $last_contact ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "ct" . $lnnumer . "_controller_name", $controllers->{name} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "ct" . $lnnumer . "_controller_message", $controllers->{status} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "ct" . $lnnumer . "_serial_number", $controllers->{serial_number} ); $lnnumer++; } } # relays if ( ref( $return->{relays} ) eq "ARRAY" and scalar( @{ $return->{relays} } ) > 0 ) { HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "relay_counts", scalar( @{ $return->{relays} } ) ); for my $relays ( @{ $return->{relays} } ) { Log3 $name, 5,"HYDRAWISE $name: $relays->{relay} $relays->{relay_id}"; #readingsSingleUpdate( $hash, "rl" . $relays->{relay} . "_relay", $relays->{relay}, $do_trigger ); #readingsSingleUpdate( $hash, "rl" . $relays->{relay} . "_relay_id", $relays->{relay_id}, $do_trigger ); #readingsSingleUpdate( $hash, "rl" . $relays->{relay} . "_name", $relays->{name}, $do_trigger ); #readingsSingleUpdate( $hash, "rl" . $relays->{relay} . "_next", $relays->{timestr}, $do_trigger ); #readingsSingleUpdate( $hash, "rl" . $relays->{relay} . "_run_minutes", $relays->{run}, $do_trigger ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_relay", $relays->{relay} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_relay_id", $relays->{relay_id} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_name", $relays->{name} ); #HYDRAWISE_ReadingsBulkUpdateIfChanged($hash, "rl".$relays->{relay}."_time", $relays->{time}); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_next", HYDRAWISE_GetDay( $hash, $relays->{timestr} ) ); #HYDRAWISE_ReadingsBulkUpdateIfChanged($hash, "rl".$relays->{relay}."_period", HYDRAWISE_GetDuration($hash,$relays->{period})); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_run_minutes", $relays->{run} / 60 ); #HYDRAWISE_ReadingsBulkUpdateIfChanged($hash, "rl".$relays->{relay}."_nicetime", $relays->{nicetime}); } } } readingsEndUpdate( $hash, 1 ); HYDRAWISE_CheckLongpoll($hash) if ( $service eq "state" ); HYDRAWISE_SendCommand( $hash, "longpollState" ) if ( $service eq "longpollState" ); } # relays elsif ( $service eq "relays" ) { if ( ref( $return->{relays} ) eq "ARRAY" and scalar( @{ $return->{relays} } ) > 0 ) { readingsBeginUpdate ($hash); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "relay_counts", scalar( @{ $return->{relays} } ) ); for my $relays ( @{ $return->{relays} } ) { Log3 $name, 5, "HYDRAWISE $name: $relays->{relay} $relays->{relay_id}"; HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_relay", $relays->{relay} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_relay_id", $relays->{relay_id} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_name", $relays->{name} ); #HYDRAWISE_ReadingsBulkUpdateIfChanged($hash, "rl".$relays->{relay}."_time", $relays->{time}); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_next", HYDRAWISE_GetDay( $hash, $relays->{timestr} ) ); #HYDRAWISE_ReadingsBulkUpdateIfChanged($hash, "rl".$relays->{relay}."_period", HYDRAWISE_GetDuration($hash,$relays->{period})); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "rl" . $relays->{relay} . "_run_minutes", $relays->{run} / 60 ); #HYDRAWISE_ReadingsBulkUpdateIfChanged($hash, "rl".$relays->{relay}."_nicetime", $relays->{nicetime}); } } readingsEndUpdate( $hash, 1 ); } # authenticate elsif ( $service eq "authenticate" ) { if ( ref($return) eq "HASH" ) { HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "controller_id", $return->{controller_id} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "customer_id", $return->{customer_id} ); HYDRAWISE_ReadingsBulkUpdateIfChanged( $hash, "user_id", $return->{user_id} ); readingsEndUpdate( $hash, 1 ); # new context received - reload state HYDRAWISE_SendCommand( $hash, "state" ); HYDRAWISE_TriggerFullDataUpdate($hash); # re-execute previous command if ( defined($cmd) ) { if ( $cmd =~ /(\w+)\/(\w+)/ ) { HYDRAWISE_SendCommand( $hash, $1, $2 ); } else { HYDRAWISE_SendCommand( $hash, $cmd ); } } } } # all other command results else { Log3 $name, 2, "HYDRAWISE $name: ERROR: method to handle response of $service not implemented"; } } else { if ( $rc =~ /401/ ) { Log3 $name, 4, "HYDRAWISE $name: authentication context invalidated"; if ( $service =~ /deleteAlert|setCalendar/ ) { HYDRAWISE_SendCommand( $hash, "authenticate", "$service" ); } elsif ( $service eq "state" and defined($cmd) ) { HYDRAWISE_SendCommand( $hash, "authenticate", "$service/$cmd" ); } else { readingsSingleUpdate( $hash, "contextId", "", 1 ); } $hash->{LONGPOLL} = 0 if ( $service eq "longpollState" ); } } return; } sub HYDRAWISE_CheckLongpoll { my $hash = shift; my $name = $hash->{NAME}; return if ( AttrVal( $name, "disable", 0 ) == 1 ); if ( !defined( $hash->{LONGPOLL} ) || time() - $hash->{LONGPOLL} > 3600 ) { Log3 $name, 4, "HYDRAWISE $name: Request GET state (longPoll)"; HYDRAWISE_SendCommand( $hash, "longpollState" ); } return; } sub HYDRAWISE_TriggerFullDataUpdate { my $hash = shift; # HYDRAWISE_SendCommand($hash, "firmware"); # HYDRAWISE_SendCommand($hash, "automaticUpdate"); # HYDRAWISE_SendCommand($hash, "calendar"); # HYDRAWISE_SendCommand($hash, "updates"); # HYDRAWISE_SendCommand($hash, "security"); # HYDRAWISE_SendCommand($hash, "predictive/location"); # HYDRAWISE_SendCommand($hash, "predictive/weather"); return; } sub HYDRAWISE_ReadingsBulkUpdateIfChanged { my ( $hash, $reading, $value, $do_trigger) = @_; my $name = $hash->{NAME}; # print "hydrawise READING: $reading -> $value \n"; if($value){ readingsBeginUpdate ($hash); readingsBulkUpdate( $hash, $reading, $value); readingsEndUpdate($hash, 1); }else{ # Value not set # print "hydrawise READING: $reading -> value not set \n"; if ($reading =~ m/_next$/) { readingsBeginUpdate ($hash); readingsBulkUpdate( $hash, $reading, "idle"); readingsEndUpdate($hash, 1); } elsif ($reading =~ m/_run_minutes$/) { readingsBeginUpdate ($hash); readingsBulkUpdate( $hash, $reading, "none"); readingsEndUpdate($hash, 1); } else { readingsBeginUpdate ($hash); readingsDelete( $hash, $reading ); readingsEndUpdate($hash, 1); } } return; } sub HYDRAWISE_GetDuration { my ( $hash, $duration ) = @_; return sprintf( "%d:%02d", int( $duration / 60 ), $duration - int( $duration / 60 ) * 60 ); } sub HYDRAWISE_GetDay { my ( $hash, $day ) = @_; my $days = { 'Mon' => "Montag", 'Tue' => "Dienstag", 'Wed' => "Mittwoch", 'Thu' => "Donnerstag", 'Fri' => "Freitag", 'Sat' => "Samstag", 'Sun' => "Sonntag", 'Now' => "Running", }; if ( defined( $days->{$day} ) ) { return $days->{$day}; # Wochentag } return $day; # Uhrzeit bei heutigem Tag } 1; =pod =item device =item summary controlling Hydrawise irrigation =item summary_DE Steuerung der Hydrawise-Bewässerung =begin html

Hunter Hydrawise

    The module receives data and sends commands via the Hunter Hydrawise API.
    All zones are identified by a unique ID - this ID is used to modify zone watering schedules, including running a zone, stopping a zone and suspending a zone for a period of time. Status information on all zones associated with an account can also be queried.

    Prerequisits

      API keys can be obtained from your Hydrawise account under My Account -> Generate API Key. This has the format XXXX-XXXX-XXXX-XXXX.

    Definition and usage

      The module is defined using the API key and the refresh interval!

      Definition of the module

        define <name> HYDRAWISE <API-KEY> <Interval>


    Example of a definition:

      define myHydrawise HYDRAWISE 1234-5678-90AB-CDEF 60

    Set
      renewcontext Returns details of all controllers associated with the customer account.
      renewRelays Return of irrigation plans for control units
      run Execute a zone for a certain period of time. 2 Parameters: "relay_id" "time_in_seconds
      runall Execute all zones for a certain period of time. 1 Parameter: "time_in_seconds"
      stop Stops a zone. 1 Parameter: "relay_id"
      stopall Stops all running zones.
      suspend Suspends a zone for a certain time. 3 Parameters: "relay_id" "DD.MM.YYYY" "HH24:MI".
      suspendall Suspends all zones for a certain time. 2 Parameters: "DD.MM.YYYY" "HH24:MI"

    Get
      help Displays help for the SET commands

    Readings

      controller_counts Number of available controllers
      controller_id Controller ID
      ct1_controller_id Controler 1: ID
      ct1_controller_message Controler 1: Status message from Hydrawise
      ct1_controller_name Controler 1: Defined name in Hydrawise
      ct1_last_contact Controler 1: Last contact from Hydrawise to the controller
      ct1_serial_number Controler 1: Serial number of the controller
      cur_controller_id Current Controller (ID)
      cur_controller_name Current Controller name
      customer_id Customer ID of Hydrawise
      presence Status of the module: presence or absent
      relay_counts Number of relays
      rl1_name Relay 1: Name
      rl1_next Relay 1: Next time this zone will water
      rl1_relay Relay 1: Physical zone number
      rl1_relay_id Relay 1: Unique ID for this zone
      rl1_run_minutes Relay 1: Length of next run time. If a run is in progress value will indicate number of seconds remaining.

=end html =begin html_DE

Hunter Hydrawise

    Das Modul empfängt Daten und sendet Befehle über die Hunter Hydrawise API.
    Alle Zonen werden durch eine eindeutige ID identifiziert - diese ID wird verwendet, um die Bewässerungspläne der Zonen zu modifizieren, einschließlich des Betreibens einer Zone, des Anhaltens einer Zone und des Aussetzens einer Zone für eine bestimmte Zeit. Statusinformationen zu allen Zonen, die mit einem Konto verbunden sind, können ebenfalls abgefragt werden.

    Voraussetzungen

      Einen API-Schlüssel können Sie von Ihrem Hydrawise-Konto unter Mein Konto generieren lassen. Dieser hat das Format XXXX-XXXX-XXXX-XXXX.

    Definition und Verwendung

      Das Modul wird mithilfe des API-Keys und des Refreshintervals definiert!

      Definition des Moduls

        define <name> HYDRAWISE <API-KEY> <Intervall>


    Beispiel für eine Moduldefinition:

      define myHydrawise HYDRAWISE 1234-5678-90AB-CDEF 60

    Set
      renewcontext Gibt Details zu allen Controllern zurück, die mit dem Kundenkonto verbunden sind.
      renewRelays Rückgabe von Bewässerungsplänen für Steuergeräte
      run Eine Zone für eine bestimmte Zeitspanne ausführen. 2 Parameter: "relay_id" "zeit_in_sekunden"
      runall Alle Zonen für eine bestimmte Zeitspanne ausführen. 1 Parameter: "zeit_in_sekunden"
      stop Stoppt eine Zone. 1 Parameter: "relay_id"
      stopall Stoppt alle laufenden Zonen.
      suspend Setzt eine Zone für eine bestimmte Zeit aus. 3 Parameter: "relay_id" "DD.MM.YYYY" "HH24:MI"
      suspendall Setzt alle Zonen für eine bestimmte Zeit aus. 2 Parameter: "DD.MM.YYYY" "HH24:MI"

    Get
      help Zeigt die Hilfe für die SET Befehle an

    Readings

      controller_counts Anzahl der vorhandenen Controller
      controller_id Controller ID
      ct1_controller_id Controler 1: ID
      ct1_controller_message Controler 1: Statusnachricht von Hydrawise
      ct1_controller_name Controler 1: Definierter Name in Hydrawise
      ct1_last_contact Controler 1: Letzter Kontakt von Hydrawise zum Controller
      ct1_serial_number Controler 1: Seriennummer des Controllers
      cur_controller_id Aktiver Controller (ID)
      cur_controller_name Aktiver Controllername
      customer_id KundenID von Hydrawise
      presence Status des Moduls: presence oder absent
      relay_counts Anzahl der Relays
      rl1_name Relay 1: Name
      rl1_next Relay 1: Nächste Ausführung der Zone
      rl1_relay Relay 1: Physikalische Zonennummer
      rl1_relay_id Relay 1: Eindeutige ID für diese Zone
      rl1_run_minutes Relay 1: Länge der nächsten Laufzeit. Wenn ein Lauf im Gange ist, gibt der Wert die Anzahl der verbleibenden Sekunden an.

=end html_DE =cut