better error handling

This commit is contained in:
Marko Oldenburg 2017-03-17 17:52:07 +01:00
parent 19ffb719ca
commit cd719bd2db
3 changed files with 187 additions and 34 deletions

View File

@ -37,7 +37,7 @@ use JSON qw(decode_json);
use Encode qw(encode_utf8); use Encode qw(encode_utf8);
my $version = "0.1.71"; my $version = "0.1.72";
@ -249,36 +249,37 @@ sub HEOSGroup_Set($$@) {
return undef unless ( ReadingsVal($name, "state", "off") eq "on" ); return undef unless ( ReadingsVal($name, "state", "off") eq "on" );
if( $cmd eq 'getGroupInfo' ) { if( $cmd eq 'getGroupInfo' ) {
return "usage: getGroupInfo" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = $cmd; $heosCmd = $cmd;
} elsif( $cmd eq 'mute' ) { } elsif( $cmd eq 'mute' ) {
return "usage: mute on/off" if( @args != 1 ); my $param = "on|off";
return "usage: $cmd $param" if( @args != 1 || ! grep { $_ =~ /$args[0]/ } split(/\|/, $param) );
$heosCmd = 'setGroupMute'; $heosCmd = 'setGroupMute';
$action = "state=$args[0]"; $action = "state=$args[0]";
} elsif( $cmd eq 'volume' ) { } elsif( $cmd eq 'volume' ) {
return "usage: volume 0-100" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 100 || $args[0] < 0 ); return "usage: $cmd 0-100" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 100 || $args[0] < 0 );
$heosCmd = 'setGroupVolume'; $heosCmd = 'setGroupVolume';
$action = "level=$args[0]"; $action = "level=$args[0]";
} elsif( $cmd eq 'volumeUp' ) { } elsif( $cmd eq 'volumeUp' ) {
return "usage: volumeUp 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 0 ); return "usage: $cmd 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 1 );
$heosCmd = 'GroupVolumeUp'; $heosCmd = 'GroupVolumeUp';
$action = "step=$args[0]"; $action = "step=$args[0]";
} elsif( $cmd eq 'volumeDown' ) { } elsif( $cmd eq 'volumeDown' ) {
return "usage: volumeDown 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 0 ); return "usage: $cmd 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 1 );
$heosCmd = 'groupVolumeDown'; $heosCmd = 'groupVolumeDown';
$action = "step=$args[0]"; $action = "step=$args[0]";
} elsif( $cmd eq 'clearGroup' ) { } elsif( $cmd eq 'clearGroup' ) {
return "usage: clearGroup" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'createGroup'; $heosCmd = 'createGroup';
$string = "pid=$gid"; $string = "pid=$gid";

View File

@ -54,7 +54,7 @@ eval "use IO::Socket::Multicast;1" or $missingModulNet .= "IO::Socket::Multicast
my $version = "0.1.71"; my $version = "0.1.72";
my %heosCmds = ( my %heosCmds = (
'enableChangeEvents' => 'system/register_for_change_events?enable=', 'enableChangeEvents' => 'system/register_for_change_events?enable=',
@ -265,6 +265,7 @@ sub HEOSMaster_Get($$@) {
if( $cmd eq 'showAccount' ) { if( $cmd eq 'showAccount' ) {
return "usage: $cmd" if( @args != 0 );
return AttrVal($name,'heosUsername',0) . ":" .HEOSMaster_ReadPassword($hash); return AttrVal($name,'heosUsername',0) . ":" .HEOSMaster_ReadPassword($hash);
} }
@ -282,49 +283,51 @@ sub HEOSMaster_Set($@) {
if($cmd eq 'reopen') { if($cmd eq 'reopen') {
return "usage: reopen" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
HEOSMaster_ReOpen($hash); HEOSMaster_ReOpen($hash);
return undef; return undef;
} elsif($cmd eq 'getPlayers') { } elsif($cmd eq 'getPlayers') {
return "usage: getPlayers" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'getPlayers'; $heosCmd = 'getPlayers';
$action = undef; $action = undef;
} elsif($cmd eq 'getGroups') { } elsif($cmd eq 'getGroups') {
return "usage: getGroups" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'getGroups'; $heosCmd = 'getGroups';
$action = undef; $action = undef;
} elsif($cmd eq 'enableChangeEvents') { } elsif($cmd eq 'enableChangeEvents') {
return "usage: enableChangeEvents" if( @args != 1 ); my $param = "on|off";
return "usage: $cmd $param" if( @args != 1 || ! grep { $_ =~ /$args[0]/ } split(/\|/, $param) );
$heosCmd = $cmd; $heosCmd = $cmd;
$action = $args[0]; $action = $args[0];
} elsif($cmd eq 'checkAccount') { } elsif($cmd eq 'checkAccount') {
return "usage: checkAccount" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = $cmd; $heosCmd = $cmd;
$action = undef; $action = undef;
} elsif($cmd eq 'signAccount') { } elsif($cmd eq 'signAccount') {
return "usage: signAccountIn" if( @args != 1 ); my $param = "In|Out";
return "usage: $cmd $param" if( @args != 1 || ! grep { $_ =~ /$args[0]/ } split(/\|/, $param) );
return "please set account informattion first" if(AttrVal($name,'heosUsername','none') eq 'none'); return "please set account informattion first" if(AttrVal($name,'heosUsername','none') eq 'none');
$heosCmd = $cmd . $args[0]; $heosCmd = $cmd . $args[0];
$action = 'un='. AttrVal($name,'heosUsername','none') . '&pw=' . HEOSMaster_ReadPassword($hash) if($args[0] eq 'In'); $action = 'un='. AttrVal($name,'heosUsername','none') . '&pw=' . HEOSMaster_ReadPassword($hash) if($args[0] eq 'In');
} elsif($cmd eq 'password') { } elsif($cmd eq 'password') {
return "usage: password" if( @args != 1 ); return "usage: $cmd" if( @args != 1 );
return HEOSMaster_StorePassword( $hash, $args[0] ); return HEOSMaster_StorePassword( $hash, $args[0] );
} elsif($cmd eq 'reboot') { } elsif($cmd eq 'reboot') {
return "usage: reboot" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = $cmd; $heosCmd = $cmd;
$action = undef; $action = undef;
@ -1384,3 +1387,149 @@ sub HEOSMaster_MakeImage($$) {
1; 1;
=pod
=item device
=item summary Modul to controls the Denon multiroom soundsystem
=item summary_DE Modul zum steuern des Denon Multiroom-Soundsystem
=begin html
<a name="HEOSMaster"></a>
<h3>HEOSMaster</h3>
<ul>
<u><b>HEOSMaster</b></u>
<br>
In combination with HEOSPlayer and HEOSGroup this FHEM Module controls the Denon multiroom soundsystem using a telnet socket connection and the HEOS Command Line Interface (CLI).
<br><br>
<b>Prerequisite</b>
<ul>
<li>Installation of the following packages: apt-get install libjson-perl libnet-telnet-perl libencode-perl
</li>
</ul>
<br>
<a name="HEOSMasterdefine"></a>
<b>Define</b>
<ul><br>
<code>define &lt;name&gt; HEOSMaster &lt;IP address&gt;</code>
<br><br>
Example:
<ul><br>
<code>define MyMasterBox HEOSMaster 192.168.178.67</code><br>
</ul>
<br>
&ltIP address&gt is the IP address of Your HEOS receiver or HEOS box. The master device is created in the room HEOS, then the players of Your system are automatically recognized and created in FHEM. From now on the players can be controlled and changes in the HEOS app or at the Receiver are synchronized with the state and media readings of the players.
<a name="HEOSMasterreadings"></a>
<br><br>
<b>Readings</b>
<ul>
<li>enableChangeEvents - state of the event reproduction at CLI master (on|off)</li>
<li>heosAccount - signed_out | signed_in as &ltHEOSAccount&gt</li>
<li>lastCommand - last executed command</li>
<li>lastPlayerId - player id of the device, which executed the last command</li>
<li>lastPlayerName - player name of the device, which executed the last command</li>
<li>lastResult - result of the last executed command</li>
<li>state - state of the HEOSMaster</li>
</ul>
<br><br>
<a name="HEOSMasterset"></a>
<b>set</b>
<ul>
<li>checkAccount - checks Your HEOS account</li>
<li>enableChangeEvents - activates the event reproduction at the CLI master</li>
<li>getGroups - get a list of all groups and creates the devices, if not done already</li>
<li>getPlayers - get a list of all players and creates the devices, if not yet existing</li>
<li>password - set the password of Your HEOS account</li>
<li>reboot - reboot of the CLI interface at HEOSMaster</li>
<li>reopen - tries to establish a new socket connection with CLI master</li>
<li>signAccount In|Out - sign in|out Your HEOS account (attr MyMasterBox heosUsername &ltusername&gt)</li>
</ul>
<br><br>
<a name="HEOSMasterget"></a>
<b>get</b>
<ul>
<li>ShowAccount - shows Your HEOS account</li>
</ul>
<br><br>
<a name="HEOSMasterstate"></a>
<b>state</b>
<ul>
<li>connected - the HEOSmaster is connected to the CLI Master</li>
<li>not connected - the HEOSmaster is not connected to the CLI Master</li>
</ul>
=end html
=begin html_DE
<a name="HEOSMaster"></a>
<h3>HEOSMaster</h3>
<ul>
<u><b>HEOSMaster</b></u>
<br>
In Kombination mit HEOSPlayer und HEOSGroup steuert dieses FHEM Modul das Denon Multiroom-Soundsystem mit Hilfe einer telnet Socket-Verbindung und dem HEOS Command Line Interface (CLI).
<br><br>
<b>Voraussetzung</b>
<ul>
<li>Installation der folgenden Pakete: apt-get install libjson-perl libnet-telnet-perl libencode-perl
</li>
</ul>
<br>
<a name="HEOSMasterdefine"></a>
<b>Define</b>
<ul><br>
<code>define &lt;name&gt; HEOSMaster &lt;IP address&gt;</code>
<br><br>
Example:
<ul><br>
<code>define MyMasterBox HEOSMaster 192.168.178.67</code><br>
</ul>
<br>
&ltIP address&GT ist die IP-Adresse des HEOS Receivers oder der HEOS Box. Das Master Device wird im Raum HEOS angelegt und danach erfolgt das Einlesen und automatische Anlegen der Player.
Von nun an k&oumlnnen die Player gesteuert werden. Au&szligerdem wird der Status und die Media Readings der Player entsprechend ge&aumlndert, wenn man in der HEOS-App oder direkt am Receiver etwas &aumlndert.
<a name="HEOSMasterreadings"></a>
<br><br>
<b>Readings</b>
<ul>
<li>enableChangeEvents - Status der Event Wiedergabe auf dem CLI Master</li>
<li>heosAccount - signed_out | signed_in as &ltHEOSAccount&gt</li>
<li>lastCommand - zuletzt ausgef&uumlhrtes Kommando</li>
<li>lastPlayerId - Player-Id des Ger&aumlts, welches das Kommando ausgef&uumlhrt hat</li>
<li>lastPlayerName - Player-Name des Ger&aumlts, welches das Kommando ausgef&uumlhrt hat</li>
<li>lastResult - Ergebnis des zuletzt ausgef&uumlhrten Kommandos</li>
<li>state - Status des HEOSMaster</li>
</ul>
<br><br>
<a name="HEOSMasterset"></a>
<b>set</b>
<ul>
<li>checkAccount - pr&uumlft das HEOS Konto</li>
<li>enableChangeEvents - aktiviert die Event Wiedergabe auf dem CLI Master</li>
<li>getGroups - holt eine Liste aller Gruppen und legt die Devices an, sofern noch nicht geschehen</li>
<li>getPlayers - holt eine Liste aller Player und legt die Devices an, sofern noch nicht vorhanden</li>
<li>password - setzt das Passwort des HEOS Kontos</li>
<li>reboot - rebootet das CLI Interface am Master</li>
<li>reopen - versucht eine neue Socket-Verbindung zum CLI Master aufzubauen</li>
<li>signAccount In|Out - anmelden|abmelden am HEOS Konto (attr MyMasterBox heosUsername &ltusername&gt)</li>
</ul>
<br><br>
<a name="HEOSMasterget"></a>
<b>get</b>
<ul>
<li>ShowAccount - zeigt das HEOS Konto an</li>
</ul>
<br><br>
<a name="HEOSMasterstate"></a>
<b>state</b>
<ul>
<li>connected - der HEOSmaster ist mit dem CLI Master verbunden</li>
<li>not connected - der HEOSmaster ist nicht mit dem CLI Master verbunden</li>
</ul>
=end html_DE
=cut

View File

@ -38,7 +38,7 @@ use Encode qw(encode_utf8);
use URI::Escape; use URI::Escape;
use Data::Dumper; use Data::Dumper;
my $version = "0.1.71"; my $version = "0.1.72";
@ -396,27 +396,28 @@ sub HEOSPlayer_Set($$@) {
return undef unless ( ReadingsVal($name, "state", "off") eq "on" ); return undef unless ( ReadingsVal($name, "state", "off") eq "on" );
if( $cmd eq 'getPlayerInfo' ) { if( $cmd eq 'getPlayerInfo' ) {
return "usage: getPlayerInfo" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = $cmd; $heosCmd = $cmd;
} elsif( $cmd eq 'getPlayState' ) { } elsif( $cmd eq 'getPlayState' ) {
return "usage: getPlayState" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = $cmd; $heosCmd = $cmd;
} elsif( $cmd eq 'getPlayMode' ) { } elsif( $cmd eq 'getPlayMode' ) {
return "usage: getPlayMode" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = $cmd; $heosCmd = $cmd;
} elsif( $cmd eq 'getNowPlayingMedia' ) { } elsif( $cmd eq 'getNowPlayingMedia' ) {
return "usage: getNowPlayingMedia" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = $cmd; $heosCmd = $cmd;
} elsif( $cmd eq 'repeat' ) { } elsif( $cmd eq 'repeat' ) {
return "usage: repeat one,all,off" if( @args != 1 ); my $param = "one|all|off";
return "usage: $cmd $param" if( @args != 1 || ! grep { $_ =~ /$args[0]/ } split(/\|/, $param) );
$heosCmd = 'setPlayMode'; $heosCmd = 'setPlayMode';
$rvalue = 'on_'.$args[0]; $rvalue = 'on_'.$args[0];
@ -424,7 +425,8 @@ sub HEOSPlayer_Set($$@) {
$action = "repeat=$rvalue&shuffle=".ReadingsVal($name,'shuffle','off'); $action = "repeat=$rvalue&shuffle=".ReadingsVal($name,'shuffle','off');
} elsif( $cmd eq 'shuffle' ) { } elsif( $cmd eq 'shuffle' ) {
return "usage: shuffle on,off" if( @args != 1 ); my $param = "on|off";
return "usage: $cmd $param" if( @args != 1 || ! grep { $_ =~ /$args[0]/ } split(/\|/, $param) );
$heosCmd = 'setPlayMode'; $heosCmd = 'setPlayMode';
$rvalue = 'on_'.ReadingsVal($name,'repeat','off'); $rvalue = 'on_'.ReadingsVal($name,'repeat','off');
@ -432,49 +434,50 @@ sub HEOSPlayer_Set($$@) {
$action = "repeat=$rvalue&shuffle=$args[0]"; $action = "repeat=$rvalue&shuffle=$args[0]";
} elsif( $cmd eq 'play' ) { } elsif( $cmd eq 'play' ) {
return "usage: play" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'setPlayState'; $heosCmd = 'setPlayState';
$action = "state=$cmd"; $action = "state=$cmd";
} elsif( $cmd eq 'stop' ) { } elsif( $cmd eq 'stop' ) {
return "usage: stop" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'setPlayState'; $heosCmd = 'setPlayState';
$action = "state=$cmd"; $action = "state=$cmd";
} elsif( $cmd eq 'pause' ) { } elsif( $cmd eq 'pause' ) {
return "usage: pause" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'setPlayState'; $heosCmd = 'setPlayState';
$action = "state=$cmd"; $action = "state=$cmd";
} elsif( $cmd eq 'mute' ) { } elsif( $cmd eq 'mute' ) {
return "usage: mute on/off" if( @args != 1 ); my $param = "on|off";
return "usage: $cmd $param" if( @args != 1 || ! grep { $_ =~ /$args[0]/ } split(/\|/, $param) );
$heosCmd = 'setMute'; $heosCmd = 'setMute';
$action = "state=$args[0]"; $action = "state=$args[0]";
} elsif( $cmd eq 'volume' ) { } elsif( $cmd eq 'volume' ) {
return "usage: volume 0-100" if( @args != 1 ); return "usage: $cmd 0-100" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 100 || $args[0] < 0);
$heosCmd = 'setVolume'; $heosCmd = 'setVolume';
$action = "level=$args[0]"; $action = "level=$args[0]";
} elsif( $cmd eq 'volumeUp' ) { } elsif( $cmd eq 'volumeUp' ) {
return "usage: volumeUp 0-10" if( @args != 1 ); return "usage: $cmd 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 1);
$heosCmd = $cmd; $heosCmd = $cmd;
$action = "step=$args[0]"; $action = "step=$args[0]";
} elsif( $cmd eq 'volumeDown' ) { } elsif( $cmd eq 'volumeDown' ) {
return "usage: volumeDown 0-10" if( @args != 1 ); return "usage: $cmd 0-10" if( @args != 1 || $args[0] !~ /(\d+)/ || $args[0] > 10 || $args[0] < 1);
$heosCmd = $cmd; $heosCmd = $cmd;
$action = "step=$args[0]"; $action = "step=$args[0]";
} elsif( $cmd eq 'groupWithMember' ) { } elsif( $cmd eq 'groupWithMember' ) {
return "usage: groupWithMember" if( @args != 1 ); return "usage: $cmd" if( @args != 1 );
foreach ( split('\,', $args[0]) ) { foreach ( split('\,', $args[0]) ) {
@ -485,17 +488,17 @@ sub HEOSPlayer_Set($$@) {
$heosCmd = 'createGroup'; $heosCmd = 'createGroup';
} elsif( $cmd eq 'groupClear' ) { } elsif( $cmd eq 'groupClear' ) {
return "usage: groupClear" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'createGroup'; $heosCmd = 'createGroup';
} elsif( $cmd eq 'next' ) { } elsif( $cmd eq 'next' ) {
return "usage: next" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'playNext'; $heosCmd = 'playNext';
} elsif( $cmd eq 'prev' ) { } elsif( $cmd eq 'prev' ) {
return "usage: prev" if( @args != 0 ); return "usage: $cmd" if( @args != 0 );
$heosCmd = 'playPrev'; $heosCmd = 'playPrev';