fhem-mirror/FHEM/70_HYDRAWISE.pm
2020-09-24 07:15:41 +00:00

1057 lines
37 KiB
Perl
Executable File
Raw Blame History

# $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 <http://www.gnu.org/licenses/>.
#
##############################################################################
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 <name> HYDRAWISE <api_key> [<poll-interval>]";
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: \"<relay_id>\"" 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: \"<time_in_seconds>\"" 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: \"<relay_id> <time_in_seconds>\""
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: \"<DD.MM.YYYY> <HH24:MI>\""
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: \"<relay_id> <DD.MM.YYYY> <HH24:MI>\""
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<65>sserung
=begin html
<a name="HYDRAWISE"></a>
<h3>Hunter Hydrawise</h3>
<ul>
The module receives data and sends commands via the Hunter Hydrawise API.<br>
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.
<br>
<br>
<b>Prerequisits</b>
<ul>
<br/>
API keys can be obtained from your Hydrawise account under My Account -> Generate API Key.
This has the format XXXX-XXXX-XXXX-XXXX.
<br>
</ul>
<br/>
<a name="Hydrawisedefine"></a>
<b>Definition and usage</b>
<ul>
<br>
The module is defined using the API key and the refresh interval!
</ul>
<br>
<ul>
<b> Definition of the module </b>
<br>
<ul>
<br>
<code>define &lt;name&gt; HYDRAWISE &lt;API-KEY&gt; &lt;Interval&gt;</code><br>
<br>
</ul>
</ul>
<br>
<b>Example of a definition: </b><br>
<ul>
<br>
<code>define myHydrawise HYDRAWISE 1234-5678-90AB-CDEF 60</code><br>
<br>
</ul>
<a name="HydrawiseSet"></a>
<b>Set</b>
<br>
<ul>
<table>
<colgroup> <col width=20%> <col width=80%> </colgroup>
<tr><td><b>renewcontext</b> </td><td> Returns details of all controllers associated with the customer account. </td></tr>
<tr><td><b>renewRelays</b> </td><td> Return of irrigation plans for control units </td></tr>
<tr><td><b>run</b> </td><td> Execute a zone for a certain period of time. 2 Parameters: "relay_id" "time_in_seconds</td></tr>
<tr><td><b>runall</b> </td><td> Execute all zones for a certain period of time. 1 Parameter: "time_in_seconds" </td></tr>
<tr><td><b>stop</b> </td><td> Stops a zone. 1 Parameter: "relay_id"</td></tr>
<tr><td><b>stopall</b> </td><td> Stops all running zones.</td></tr>
<tr><td><b>suspend</b> </td><td> Suspends a zone for a certain time. 3 Parameters: "relay_id" "DD.MM.YYYY" "HH24:MI". </td></tr>
<tr><td><b>suspendall</b> </td><td> Suspends all zones for a certain time. 2 Parameters: "DD.MM.YYYY" "HH24:MI" </td></tr>
</table>
</ul>
<br>
<b>Get</b>
<br>
<ul>
<table>
<colgroup> <col width=20%> <col width=80%> </colgroup>
<tr><td><b>help</b> </td><td> Displays help for the SET commands </td></tr>
</table>
</ul>
<br>
<a name="Hydrawisereadings"></a>
<b>Readings</b>
<ul>
<br>
<table>
<colgroup> <col width=35%> <col width=65%> </colgroup>
<tr><td><b>controller_counts</b> </td><td> Number of available controllers</td></tr>
<tr><td><b>controller_id</b> </td><td> Controller ID </td></tr>
<tr><td><b>ct1_controller_id</b> </td><td> Controler 1: ID</td></tr>
<tr><td><b>ct1_controller_message</b> </td><td> Controler 1: Status message from Hydrawise</td></tr>
<tr><td><b>ct1_controller_name</b> </td><td> Controler 1: Defined name in Hydrawise</td></tr>
<tr><td><b>ct1_last_contact</b> </td><td> Controler 1: Last contact from Hydrawise to the controller</td></tr>
<tr><td><b>ct1_serial_number</b> </td><td> Controler 1: Serial number of the controller</td></tr>
<tr><td><b>cur_controller_id</b> </td><td> Current Controller (ID)</td></tr>
<tr><td><b>cur_controller_name</b> </td><td> Current Controller name</td></tr>
<tr><td><b>customer_id</b> </td><td> Customer ID of Hydrawise</td></tr>
<tr><td><b>presence</b> </td><td> Status of the module: presence or absent</td></tr>
<tr><td><b>relay_counts</b> </td><td> Number of relays</td></tr>
<tr><td><b>rl1_name</b> </td><td> Relay 1: Name </td></tr>
<tr><td><b>rl1_next</b> </td><td> Relay 1: Next time this zone will water</td></tr>
<tr><td><b>rl1_relay</b> </td><td> Relay 1: Physical zone number</td></tr>
<tr><td><b>rl1_relay_id</b> </td><td> Relay 1: Unique ID for this zone</td></tr>
<tr><td><b>rl1_run_minutes</b> </td><td> Relay 1: Length of next run time. If a run is in progress value will indicate number of seconds remaining.</td></tr>
</table>
<br>
</ul>
</ul>
=end html
=begin html_DE
<a name="HYDRAWISE"></a>
<h3>Hunter Hydrawise</h3>
<ul>
Das Modul empf&auml;ngt Daten und sendet Befehle &uuml;ber die Hunter Hydrawise API.<br>
Alle Zonen werden durch eine eindeutige ID identifiziert - diese ID wird verwendet, um die Bew&auml;sserungspl&auml;ne der Zonen zu modifizieren,
einschlie&szlig;lich des Betreibens einer Zone, des Anhaltens einer Zone und des Aussetzens einer Zone f&uuml;r eine bestimmte Zeit.
Statusinformationen zu allen Zonen, die mit einem Konto verbunden sind, k&ouml;nnen ebenfalls abgefragt werden.
<br>
<br>
<b>Voraussetzungen</b>
<ul>
<br/>
Einen API-Schl&uuml;ssel k&ouml;nnen Sie von Ihrem Hydrawise-Konto unter Mein Konto generieren lassen.
Dieser hat das Format XXXX-XXXX-XXXX-XXXX.
<br>
</ul>
<br/>
<a name="Hydrawisedefine"></a>
<b>Definition und Verwendung</b>
<ul>
<br>
Das Modul wird mithilfe des API-Keys und des Refreshintervals definiert!
</ul>
<br>
<ul>
<b> Definition des Moduls </b>
<br>
<ul>
<br>
<code>define &lt;name&gt; HYDRAWISE &lt;API-KEY&gt; &lt;Intervall&gt;</code><br>
<br>
</ul>
</ul>
<br>
<b>Beispiel f&uuml;r eine Moduldefinition: </b><br>
<ul>
<br>
<code>define myHydrawise HYDRAWISE 1234-5678-90AB-CDEF 60</code><br>
<br>
</ul>
<a name="HydrawiseSet"></a>
<b>Set</b>
<br>
<ul>
<table>
<colgroup> <col width=20%> <col width=80%> </colgroup>
<tr><td><b>renewcontext</b> </td><td> Gibt Details zu allen Controllern zur&uuml;ck, die mit dem Kundenkonto verbunden sind. </td></tr>
<tr><td><b>renewRelays</b> </td><td> R&uuml;ckgabe von Bew&auml;sserungspl&auml;nen f&uuml;r Steuerger&auml;te </td></tr>
<tr><td><b>run</b> </td><td> Eine Zone f&uuml;r eine bestimmte Zeitspanne ausf&uuml;hren. 2 Parameter: "relay_id" "zeit_in_sekunden"</td></tr>
<tr><td><b>runall</b> </td><td> Alle Zonen f&uuml;r eine bestimmte Zeitspanne ausf&uuml;hren. 1 Parameter: "zeit_in_sekunden" </td></tr>
<tr><td><b>stop</b> </td><td> Stoppt eine Zone. 1 Parameter: "relay_id"</td></tr>
<tr><td><b>stopall</b> </td><td> Stoppt alle laufenden Zonen.</td></tr>
<tr><td><b>suspend</b> </td><td> Setzt eine Zone f&uuml;r eine bestimmte Zeit aus. 3 Parameter: "relay_id" "DD.MM.YYYY" "HH24:MI" </td></tr>
<tr><td><b>suspendall</b> </td><td> Setzt alle Zonen f&uuml;r eine bestimmte Zeit aus. 2 Parameter: "DD.MM.YYYY" "HH24:MI" </td></tr>
</table>
</ul>
<br>
<b>Get</b>
<br>
<ul>
<table>
<colgroup> <col width=20%> <col width=80%> </colgroup>
<tr><td><b>help</b> </td><td> Zeigt die Hilfe f&uuml;r die SET Befehle an </td></tr>
</table>
</ul>
<br>
<a name="Hydrawisereadings"></a>
<b>Readings</b>
<ul>
<br>
<table>
<colgroup> <col width=35%> <col width=65%> </colgroup>
<tr><td><b>controller_counts</b> </td><td> Anzahl der vorhandenen Controller</td></tr>
<tr><td><b>controller_id</b> </td><td> Controller ID </td></tr>
<tr><td><b>ct1_controller_id</b> </td><td> Controler 1: ID</td></tr>
<tr><td><b>ct1_controller_message</b> </td><td> Controler 1: Statusnachricht von Hydrawise</td></tr>
<tr><td><b>ct1_controller_name</b> </td><td> Controler 1: Definierter Name in Hydrawise</td></tr>
<tr><td><b>ct1_last_contact</b> </td><td> Controler 1: Letzter Kontakt von Hydrawise zum Controller</td></tr>
<tr><td><b>ct1_serial_number</b> </td><td> Controler 1: Seriennummer des Controllers</td></tr>
<tr><td><b>cur_controller_id</b> </td><td> Aktiver Controller (ID)</td></tr>
<tr><td><b>cur_controller_name</b> </td><td> Aktiver Controllername</td></tr>
<tr><td><b>customer_id</b> </td><td> KundenID von Hydrawise</td></tr>
<tr><td><b>presence</b> </td><td> Status des Moduls: presence oder absent</td></tr>
<tr><td><b>relay_counts</b> </td><td> Anzahl der Relays</td></tr>
<tr><td><b>rl1_name</b> </td><td> Relay 1: Name </td></tr>
<tr><td><b>rl1_next</b> </td><td> Relay 1: N&auml;chste Ausf&uuml;hrung der Zone</td></tr>
<tr><td><b>rl1_relay</b> </td><td> Relay 1: Physikalische Zonennummer</td></tr>
<tr><td><b>rl1_relay_id</b> </td><td> Relay 1: Eindeutige ID f&uuml;r diese Zone</td></tr>
<tr><td><b>rl1_run_minutes</b> </td><td> Relay 1: L&auml;nge der n&auml;chsten Laufzeit. Wenn ein Lauf im Gange ist, gibt der Wert die Anzahl der verbleibenden Sekunden an.</td></tr>
</table>
<br>
</ul>
</ul>
=end html_DE
=cut