mirror of
https://github.com/fhem/fhem-mirror.git
synced 2025-04-19 06:36:04 +00:00
YAMAHA_AVR: added HTTP request queue, send only one request at the same time.
git-svn-id: https://svn.fhem.de/fhem/trunk@10100 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
parent
858d229210
commit
ad219b3684
@ -1,5 +1,8 @@
|
|||||||
# Add changes at the top of the list. Keep it in ASCII, and 80-char wide.
|
# 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.
|
# Do not insert empty lines here, update check depends on it.
|
||||||
|
- changed: YAMAHA_AVR: added HTTP request queue, send only one request at the
|
||||||
|
same time. This increases command reliability and response behaviour of
|
||||||
|
the AV receiver.
|
||||||
- bugfix: 49_SSCam: avoid problems when running this module on
|
- bugfix: 49_SSCam: avoid problems when running this module on
|
||||||
windows systems
|
windows systems
|
||||||
- feature: 14_CUL_TCM97001: Add redirect for Eurochron to SD_WS07 modul
|
- feature: 14_CUL_TCM97001: Add redirect for Eurochron to SD_WS07 modul
|
||||||
|
@ -60,6 +60,90 @@ YAMAHA_AVR_Initialize($)
|
|||||||
$readingFnAttributes;
|
$readingFnAttributes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#############################
|
||||||
|
sub
|
||||||
|
YAMAHA_AVR_Define($$)
|
||||||
|
{
|
||||||
|
my ($hash, $def) = @_;
|
||||||
|
my @a = split("[ \t][ \t]*", $def);
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
|
||||||
|
if(!@a >= 4)
|
||||||
|
{
|
||||||
|
my $msg = "wrong syntax: define <name> YAMAHA_AVR <ip-or-hostname> [<zone>] [<ON-statusinterval>] [<OFF-statusinterval>] ";
|
||||||
|
Log3 $name, 2, $msg;
|
||||||
|
return $msg;
|
||||||
|
}
|
||||||
|
|
||||||
|
my $address = $a[2];
|
||||||
|
|
||||||
|
$hash->{helper}{ADDRESS} = $address;
|
||||||
|
|
||||||
|
# if a zone was given, use it, otherwise use the mainzone
|
||||||
|
if(defined($a[3]))
|
||||||
|
{
|
||||||
|
$hash->{helper}{SELECTED_ZONE} = $a[3];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$hash->{helper}{SELECTED_ZONE} = "mainzone";
|
||||||
|
}
|
||||||
|
|
||||||
|
# if an update interval was given which is greater than zero, use it.
|
||||||
|
if(defined($a[4]) and $a[4] > 0)
|
||||||
|
{
|
||||||
|
$hash->{helper}{OFF_INTERVAL} = $a[4];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$hash->{helper}{OFF_INTERVAL} = 30;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(defined($a[5]) and $a[5] > 0)
|
||||||
|
{
|
||||||
|
$hash->{helper}{ON_INTERVAL} = $a[5];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$hash->{helper}{ON_INTERVAL} = $hash->{helper}{OFF_INTERVAL};
|
||||||
|
}
|
||||||
|
|
||||||
|
$hash->{helper}{CMD_QUEUE} = ();
|
||||||
|
delete($hash->{helper}{HTTP_CONNECTION}) if(exists($hash->{helper}{HTTP_CONNECTION}));
|
||||||
|
|
||||||
|
# In case of a redefine, check the zone parameter if the specified zone exist, otherwise use the main zone
|
||||||
|
if(defined($hash->{helper}{ZONES}) and length($hash->{helper}{ZONES}) > 0)
|
||||||
|
{
|
||||||
|
if(defined(YAMAHA_AVR_getParamName($hash, lc $hash->{helper}{SELECTED_ZONE}, $hash->{helper}{ZONES})))
|
||||||
|
{
|
||||||
|
$hash->{ACTIVE_ZONE} = lc $hash->{helper}{SELECTED_ZONE};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Log3 $name, 2, "YAMAHA_AVR ($name) - selected zone >>".$hash->{helper}{SELECTED_ZONE}."<< is not available on device ".$hash->{NAME}.". Using Main Zone instead";
|
||||||
|
$hash->{ACTIVE_ZONE} = "mainzone";
|
||||||
|
}
|
||||||
|
YAMAHA_AVR_getInputs($hash);
|
||||||
|
}
|
||||||
|
|
||||||
|
# set the volume-smooth-change attribute only if it is not defined, so no user values will be overwritten
|
||||||
|
#
|
||||||
|
# own attribute values will be overwritten anyway when all attr-commands are executed from fhem.cfg
|
||||||
|
$attr{$name}{"volume-smooth-change"} = "1" unless(exists($attr{$name}{"volume-smooth-change"}));
|
||||||
|
|
||||||
|
unless(exists($hash->{helper}{AVAILABLE}) and ($hash->{helper}{AVAILABLE} == 0))
|
||||||
|
{
|
||||||
|
$hash->{helper}{AVAILABLE} = 1;
|
||||||
|
readingsSingleUpdate($hash, "presence", "present", 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
# start the status update timer
|
||||||
|
$hash->{helper}{DISABLED} = 0 unless(exists($hash->{helper}{DISABLED}));
|
||||||
|
YAMAHA_AVR_ResetTimer($hash,0);
|
||||||
|
|
||||||
|
return undef;
|
||||||
|
}
|
||||||
|
|
||||||
###################################
|
###################################
|
||||||
sub
|
sub
|
||||||
YAMAHA_AVR_GetStatus($;$)
|
YAMAHA_AVR_GetStatus($;$)
|
||||||
@ -770,90 +854,6 @@ YAMAHA_AVR_Set($@)
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#############################
|
|
||||||
sub
|
|
||||||
YAMAHA_AVR_Define($$)
|
|
||||||
{
|
|
||||||
my ($hash, $def) = @_;
|
|
||||||
my @a = split("[ \t][ \t]*", $def);
|
|
||||||
my $name = $hash->{NAME};
|
|
||||||
|
|
||||||
if(!@a >= 4)
|
|
||||||
{
|
|
||||||
my $msg = "wrong syntax: define <name> YAMAHA_AVR <ip-or-hostname> [<zone>] [<ON-statusinterval>] [<OFF-statusinterval>] ";
|
|
||||||
Log3 $name, 2, $msg;
|
|
||||||
return $msg;
|
|
||||||
}
|
|
||||||
|
|
||||||
my $address = $a[2];
|
|
||||||
|
|
||||||
$hash->{helper}{ADDRESS} = $address;
|
|
||||||
|
|
||||||
# if a zone was given, use it, otherwise use the mainzone
|
|
||||||
if(defined($a[3]))
|
|
||||||
{
|
|
||||||
$hash->{helper}{SELECTED_ZONE} = $a[3];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$hash->{helper}{SELECTED_ZONE} = "mainzone";
|
|
||||||
}
|
|
||||||
|
|
||||||
# if an update interval was given which is greater than zero, use it.
|
|
||||||
if(defined($a[4]) and $a[4] > 0)
|
|
||||||
{
|
|
||||||
$hash->{helper}{OFF_INTERVAL} = $a[4];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$hash->{helper}{OFF_INTERVAL} = 30;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(defined($a[5]) and $a[5] > 0)
|
|
||||||
{
|
|
||||||
$hash->{helper}{ON_INTERVAL} = $a[5];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
$hash->{helper}{ON_INTERVAL} = $hash->{helper}{OFF_INTERVAL};
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# In case of a redefine, check the zone parameter if the specified zone exist, otherwise use the main zone
|
|
||||||
if(defined($hash->{helper}{ZONES}) and length($hash->{helper}{ZONES}) > 0)
|
|
||||||
{
|
|
||||||
if(defined(YAMAHA_AVR_getParamName($hash, lc $hash->{helper}{SELECTED_ZONE}, $hash->{helper}{ZONES})))
|
|
||||||
{
|
|
||||||
$hash->{ACTIVE_ZONE} = lc $hash->{helper}{SELECTED_ZONE};
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
Log3 $name, 2, "YAMAHA_AVR ($name) - selected zone >>".$hash->{helper}{SELECTED_ZONE}."<< is not available on device ".$hash->{NAME}.". Using Main Zone instead";
|
|
||||||
$hash->{ACTIVE_ZONE} = "mainzone";
|
|
||||||
}
|
|
||||||
|
|
||||||
YAMAHA_AVR_getInputs($hash);
|
|
||||||
}
|
|
||||||
|
|
||||||
# set the volume-smooth-change attribute only if it is not defined, so no user values will be overwritten
|
|
||||||
#
|
|
||||||
# own attribute values will be overwritten anyway when all attr-commands are executed from fhem.cfg
|
|
||||||
$attr{$name}{"volume-smooth-change"} = "1" unless(exists($attr{$name}{"volume-smooth-change"}));
|
|
||||||
|
|
||||||
unless(exists($hash->{helper}{AVAILABLE}) and ($hash->{helper}{AVAILABLE} == 0))
|
|
||||||
{
|
|
||||||
$hash->{helper}{AVAILABLE} = 1;
|
|
||||||
readingsSingleUpdate($hash, "presence", "present", 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
# start the status update timer
|
|
||||||
$hash->{helper}{DISABLED} = 0 unless(exists($hash->{helper}{DISABLED}));
|
|
||||||
YAMAHA_AVR_ResetTimer($hash,0);
|
|
||||||
|
|
||||||
return undef;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
##########################
|
##########################
|
||||||
sub
|
sub
|
||||||
YAMAHA_AVR_Attr(@)
|
YAMAHA_AVR_Attr(@)
|
||||||
@ -915,52 +915,55 @@ YAMAHA_AVR_SendCommand($@)
|
|||||||
my $address = $hash->{helper}{ADDRESS};
|
my $address = $hash->{helper}{ADDRESS};
|
||||||
my $blocking = 0;
|
my $blocking = 0;
|
||||||
|
|
||||||
if($cmd ne "statusRequest" and $hash->{helper}{AVAILABLE} == 1)
|
|
||||||
{
|
|
||||||
$blocking = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
# In case any URL changes must be made, this part is separated in this function".
|
# In case any URL changes must be made, this part is separated in this function".
|
||||||
|
|
||||||
if($blocking == 1)
|
|
||||||
{
|
|
||||||
Log3 $name, 5, "YAMAHA_AVR ($name) - execute blocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data";
|
|
||||||
my $param = {
|
my $param = {
|
||||||
url => "http://".$address."/YamahaRemoteControl/ctrl",
|
|
||||||
timeout => AttrVal($name, "request-timeout", 4),
|
|
||||||
noshutdown => 1,
|
|
||||||
data => "<?xml version=\"1.0\" encoding=\"utf-8\"?>".$data,
|
data => "<?xml version=\"1.0\" encoding=\"utf-8\"?>".$data,
|
||||||
loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
|
|
||||||
hash => $hash,
|
|
||||||
cmd => $cmd,
|
cmd => $cmd,
|
||||||
arg => $arg,
|
arg => $arg,
|
||||||
can_fail => $can_fail
|
can_fail => $can_fail
|
||||||
};
|
};
|
||||||
|
Log3 $name, 4, "YAMAHA_AVR ($name) - append to queue \"$cmd".(defined($arg) ? " ".$arg : "")."\": $data";
|
||||||
|
push @{$hash->{helper}{CMD_QUEUE}}, $param;
|
||||||
|
|
||||||
my ($err, $data) = HttpUtils_BlockingGet($param);
|
YAMAHA_AVR_HandleCmdQueue($hash);
|
||||||
YAMAHA_AVR_ParseResponse($param, $err, $data);
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
Log3 $name, 5, "YAMAHA_AVR ($name) - execute nonblocking \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\" on $name: $data";
|
|
||||||
|
|
||||||
HttpUtils_NonblockingGet({
|
#############################
|
||||||
|
# starts http requests from cmd queue
|
||||||
|
sub
|
||||||
|
YAMAHA_AVR_HandleCmdQueue($)
|
||||||
|
{
|
||||||
|
my ($hash) = @_;
|
||||||
|
my $name = $hash->{NAME};
|
||||||
|
my $address = $hash->{helper}{ADDRESS};
|
||||||
|
|
||||||
|
if(not($hash->{helper}{RUNNING_REQUEST}) and @{$hash->{helper}{CMD_QUEUE}})
|
||||||
|
{
|
||||||
|
my $params = {
|
||||||
url => "http://".$address."/YamahaRemoteControl/ctrl",
|
url => "http://".$address."/YamahaRemoteControl/ctrl",
|
||||||
timeout => AttrVal($name, "request-timeout", 4),
|
timeout => AttrVal($name, "request-timeout", 4),
|
||||||
noshutdown => 1,
|
noshutdown => 1,
|
||||||
data => "<?xml version=\"1.0\" encoding=\"utf-8\"?>".$data,
|
keepalive => 0,
|
||||||
|
httpversion => "1.1",
|
||||||
loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
|
loglevel => ($hash->{helper}{AVAILABLE} ? undef : 5),
|
||||||
hash => $hash,
|
hash => $hash,
|
||||||
cmd => $cmd,
|
|
||||||
arg => $arg,
|
|
||||||
can_fail => $can_fail,
|
|
||||||
callback => \&YAMAHA_AVR_ParseResponse
|
callback => \&YAMAHA_AVR_ParseResponse
|
||||||
}
|
};
|
||||||
);
|
|
||||||
|
my $request = pop @{$hash->{helper}{CMD_QUEUE}};
|
||||||
|
|
||||||
|
map {$hash->{helper}{HTTP_CONNECTION}{$_} = $params->{$_}} keys %{$params};
|
||||||
|
map {$hash->{helper}{HTTP_CONNECTION}{$_} = $request->{$_}} keys %{$request};
|
||||||
|
|
||||||
|
$hash->{helper}{RUNNING_REQUEST} = 1;
|
||||||
|
Log3 $name, 4, "YAMAHA_AVR ($name) - send command \"$request->{cmd}".(defined($request->{arg}) ? " ".$request->{arg} : "")."\": $request->{data}";
|
||||||
|
HttpUtils_NonblockingGet($hash->{helper}{HTTP_CONNECTION});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
# parses the receiver response
|
# parses the receiver response
|
||||||
sub
|
sub
|
||||||
@ -973,6 +976,10 @@ YAMAHA_AVR_ParseResponse ($$$)
|
|||||||
my $cmd = $param->{cmd};
|
my $cmd = $param->{cmd};
|
||||||
my $arg = $param->{arg};
|
my $arg = $param->{arg};
|
||||||
my $can_fail = $param->{can_fail};
|
my $can_fail = $param->{can_fail};
|
||||||
|
my $zone = YAMAHA_AVR_getParamName($hash, $hash->{ACTIVE_ZONE}, $hash->{helper}{ZONES});
|
||||||
|
|
||||||
|
$hash->{helper}{RUNNING_REQUEST} = 0;
|
||||||
|
delete($hash->{helper}{HTTP_CONNECTION}) unless($param->{keepalive});
|
||||||
|
|
||||||
if(exists($param->{code}))
|
if(exists($param->{code}))
|
||||||
{
|
{
|
||||||
@ -1004,7 +1011,8 @@ YAMAHA_AVR_ParseResponse ($$$)
|
|||||||
|
|
||||||
$hash->{helper}{AVAILABLE} = 0;
|
$hash->{helper}{AVAILABLE} = 0;
|
||||||
}
|
}
|
||||||
elsif($data ne "")
|
|
||||||
|
if($data ne "")
|
||||||
{
|
{
|
||||||
Log3 $name, 5, "YAMAHA_AVR ($name) - got response for \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $data";
|
Log3 $name, 5, "YAMAHA_AVR ($name) - got response for \"$cmd".(defined($arg) ? " ".(split("\\|", $arg))[0] : "")."\": $data";
|
||||||
|
|
||||||
@ -1012,6 +1020,7 @@ YAMAHA_AVR_ParseResponse ($$$)
|
|||||||
{
|
{
|
||||||
Log3 $name, 3, "YAMAHA_AVR ($name) - device $name reappeared";
|
Log3 $name, 3, "YAMAHA_AVR ($name) - device $name reappeared";
|
||||||
readingsSingleUpdate($hash, "presence", "present", 1);
|
readingsSingleUpdate($hash, "presence", "present", 1);
|
||||||
|
YAMAHA_AVR_SendCommand($hash, "<YAMAHA_AV cmd=\"GET\"><$zone><Basic_Status>GetParam</Basic_Status></$zone></YAMAHA_AV>", "statusRequest", "basicStatus");
|
||||||
}
|
}
|
||||||
|
|
||||||
$hash->{helper}{AVAILABLE} = 1;
|
$hash->{helper}{AVAILABLE} = 1;
|
||||||
@ -1387,6 +1396,7 @@ YAMAHA_AVR_ParseResponse ($$$)
|
|||||||
readingsEndUpdate($hash, 1);
|
readingsEndUpdate($hash, 1);
|
||||||
|
|
||||||
YAMAHA_AVR_ResetTimer($hash, 5);
|
YAMAHA_AVR_ResetTimer($hash, 5);
|
||||||
|
YAMAHA_AVR_HandleCmdQueue($hash);
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
@ -1401,6 +1411,7 @@ YAMAHA_AVR_ParseResponse ($$$)
|
|||||||
readingsEndUpdate($hash, 1);
|
readingsEndUpdate($hash, 1);
|
||||||
|
|
||||||
YAMAHA_AVR_ResetTimer($hash, 3);
|
YAMAHA_AVR_ResetTimer($hash, 3);
|
||||||
|
YAMAHA_AVR_HandleCmdQueue($hash);
|
||||||
|
|
||||||
return undef;
|
return undef;
|
||||||
}
|
}
|
||||||
@ -1447,8 +1458,11 @@ YAMAHA_AVR_ParseResponse ($$$)
|
|||||||
|
|
||||||
readingsEndUpdate($hash, 1);
|
readingsEndUpdate($hash, 1);
|
||||||
|
|
||||||
YAMAHA_AVR_ResetTimer($hash, 0) if($cmd ne "statusRequest" and $cmd ne "on");
|
YAMAHA_AVR_GetStatus($hash, 1) if($cmd ne "statusRequest" and $cmd ne "on");
|
||||||
|
YAMAHA_AVR_ResetTimer($hash, 10) if($cmd eq "on");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
YAMAHA_AVR_HandleCmdQueue($hash);
|
||||||
}
|
}
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
@ -1568,6 +1582,8 @@ YAMAHA_AVR_ParseXML($$$)
|
|||||||
Log3 $name, 2, "YAMAHA_AVR ($name) - selected zone >>".$hash->{helper}{SELECTED_ZONE}."<< is not available. Using Main Zone instead";
|
Log3 $name, 2, "YAMAHA_AVR ($name) - selected zone >>".$hash->{helper}{SELECTED_ZONE}."<< is not available. Using Main Zone instead";
|
||||||
$hash->{ACTIVE_ZONE} = "mainzone";
|
$hash->{ACTIVE_ZONE} = "mainzone";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
YAMAHA_AVR_GetStatus($hash, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
|
Loading…
x
Reference in New Issue
Block a user