2
0
mirror of https://github.com/fhem/fhem-mirror.git synced 2025-03-13 11:16:36 +00:00

improved on/off detection added playlists added sync --This line, and

those below, will be ignored--

M 97_SB_SERVER.pm


git-svn-id: https://svn.fhem.de/fhem/trunk@6212 2b470e98-0d58-463d-a4d8-8e2adae1ed80
This commit is contained in:
fhemrocks 2014-07-06 22:13:50 +00:00
parent 9e17d08593
commit a1e2a2ee2a

View File

@ -10,7 +10,7 @@
# #
# This is absolutley open source. Please feel free to use just as you # This is absolutley open source. Please feel free to use just as you
# like. Please note, that no warranty is given and no liability # like. Please note, that no warranty is given and no liability
# granted. # granted
# #
# ############################################################################ # ############################################################################
# #
@ -149,6 +149,12 @@ sub SB_SERVER_Define( $$ ) {
$hash->{LASTANSWER} = "none"; $hash->{LASTANSWER} = "none";
# used for alive checking of the CLI interface
$hash->{ALIVECHECK} = "?";
# the status of the CLI connection (on / off)
$hash->{CLICONNECTION} = "?";
# preset our attributes # preset our attributes
if( !defined( $attr{$name}{alivetimer} ) ) { if( !defined( $attr{$name}{alivetimer} ) ) {
$attr{$name}{alivetimer} = 120; $attr{$name}{alivetimer} = 120;
@ -187,12 +193,6 @@ sub SB_SERVER_Define( $$ ) {
$hash->{READINGS}{serversecure}{TIME} = $tn; $hash->{READINGS}{serversecure}{TIME} = $tn;
} }
# the status of our server alive check mechanism
if( !defined( $hash->{READINGS}{alivecheck}{VAL} ) ) {
$hash->{READINGS}{alivecheck}{VAL} = "?";
$hash->{READINGS}{alivecheck}{TIME} = $tn;
}
# the maximum number of favorites on the server # the maximum number of favorites on the server
if( !defined( $hash->{READINGS}{favoritestotal}{VAL} ) ) { if( !defined( $hash->{READINGS}{favoritestotal}{VAL} ) ) {
@ -371,12 +371,13 @@ sub SB_SERVER_Ready( $ ) {
SB_SERVER_Broadcast( $hash, "SERVER", "OFF" ); SB_SERVER_Broadcast( $hash, "SERVER", "OFF" );
} }
if( $hash->{TCPDev} ) { return( DevIo_OpenDev( $hash, 1, "SB_SERVER_DoInit") );
SB_SERVER_DoInit( $hash );
}
} }
return( DevIo_OpenDev( $hash, 1, "SB_SERVER_DoInit" ) ); #if( $hash->{TCPDev} ) {
#SB_SERVER_DoInit( $hash );
#}
} }
@ -405,7 +406,7 @@ sub SB_SERVER_Attr( @ ) {
my $name = shift( @_ ); my $name = shift( @_ );
my @args = @_; my @args = @_;
Log( 1, "SB_SERVER_Attr: called with @args" ); Log( 4, "SB_SERVER_Attr: called with @args" );
if( $cmd eq "set" ) { if( $cmd eq "set" ) {
if( $args[ 0 ] eq "alivetimer" ) { if( $args[ 0 ] eq "alivetimer" ) {
@ -461,7 +462,12 @@ sub SB_SERVER_Set( $@ ) {
DevIo_SimpleWrite( $hash, "listen 0\n", 0 ); DevIo_SimpleWrite( $hash, "listen 0\n", 0 );
} elsif( $cmd eq "statusRequest" ) { } elsif( $cmd eq "statusRequest" ) {
Log3( $hash, 5, "SB_SERVER_Set: statusRequest" );
DevIo_SimpleWrite( $hash, "serverstatus 0 200\n", 0 ); DevIo_SimpleWrite( $hash, "serverstatus 0 200\n", 0 );
DevIo_SimpleWrite( $hash, "favorites items 0 " .
AttrVal( $name, "maxfavorites", 100 ) . "\n",
0 );
DevIo_SimpleWrite( $hash, "playlists 0 200\n", 0 );
} elsif( $cmd eq "cliraw" ) { } elsif( $cmd eq "cliraw" ) {
# write raw messages to the CLI interface per player # write raw messages to the CLI interface per player
@ -610,11 +616,19 @@ sub SB_SERVER_DoInit( $ ) {
if( !$hash->{TCPDev} ) { if( !$hash->{TCPDev} ) {
Log3( $hash, 5, "SB_SERVER_DoInit: no TCPDev available?" ); Log3( $hash, 5, "SB_SERVER_DoInit: no TCPDev available?" );
DevIo_CloseDev( $hash );
} }
if( $hash->{STATE} eq "disconnected" ) { if( $hash->{STATE} eq "disconnected" ) {
# server is off after FHEM start, broadcast to clients # server is off after FHEM start, broadcast to clients
if( ( ReadingsVal( $name, "power", "on" ) eq "on" ) ||
( ReadingsVal( $name, "power", "on" ) eq "?" ) ) {
# obviously the first we realize the Server is off
readingsSingleUpdate( $hash, "power", "off", 1 );
# and signal to our clients
SB_SERVER_Broadcast( $hash, "SERVER", "OFF" ); SB_SERVER_Broadcast( $hash, "SERVER", "OFF" );
}
return( "" ); return( "" );
} }
@ -627,9 +641,10 @@ sub SB_SERVER_DoInit( $ ) {
DevIo_SimpleWrite( $hash, "serverstatus 0 200\n", 0 ); DevIo_SimpleWrite( $hash, "serverstatus 0 200\n", 0 );
DevIo_SimpleWrite( $hash, "favorites items 0 " . DevIo_SimpleWrite( $hash, "favorites items 0 " .
AttrVal( $name, "maxfavorites", 100 ) . "\n", 0 ); AttrVal( $name, "maxfavorites", 100 ) . "\n", 0 );
DevIo_SimpleWrite( $hash, "playlists 0 200\n", 0 );
# start the alive checking mechanism # start the alive checking mechanism
readingsSingleUpdate( $hash, "alivecheck", "?", 0 ); $hash->{ALIVECHECK} = "?";
InternalTimer( gettimeofday() + AttrVal( $name, "alivetimer", 120 ), InternalTimer( gettimeofday() + AttrVal( $name, "alivetimer", 120 ),
"SB_SERVER_Alive", "SB_SERVER_Alive",
$hash, $hash,
@ -707,7 +722,7 @@ sub SB_SERVER_ParseCmds( $$ ) {
} }
} elsif( $cmd eq "fhemalivecheck" ) { } elsif( $cmd eq "fhemalivecheck" ) {
readingsSingleUpdate( $hash, "alivecheck", "received", 0 ); $hash->{ALIVECHECK} = "received";
Log3( $hash, 4, "SB_SERVER_ParseCmds($name): alivecheck received" ); Log3( $hash, 4, "SB_SERVER_ParseCmds($name): alivecheck received" );
} elsif( $cmd eq "favorites" ) { } elsif( $cmd eq "favorites" ) {
@ -728,6 +743,10 @@ sub SB_SERVER_ParseCmds( $$ ) {
Log3( $hash, 4, "SB_SERVER_ParseCmds($name): server status" ); Log3( $hash, 4, "SB_SERVER_ParseCmds($name): server status" );
SB_SERVER_ParseServerStatus( $hash, \@args ); SB_SERVER_ParseServerStatus( $hash, \@args );
} elsif( $cmd eq "playlists" ) {
Log3( $hash, 4, "SB_SERVER_ParseCmds($name): playlists" );
SB_SERVER_ParseServerPlaylists( $hash, \@args );
} else { } else {
# unkown # unkown
} }
@ -741,6 +760,10 @@ sub SB_SERVER_Alive( $ ) {
my ($hash) = @_; my ($hash) = @_;
my $name = $hash->{NAME}; my $name = $hash->{NAME};
my $rccstatus = "on";
my $pingstatus = "on";
my $nexttime = gettimeofday() + AttrVal( $name, "alivetimer", 120 );
Log3( $hash, 4, "SB_SERVER_Alive($name): called" ); Log3( $hash, 4, "SB_SERVER_Alive($name): called" );
if( AttrVal( $name, "doalivecheck", "false" ) eq "false" ) { if( AttrVal( $name, "doalivecheck", "false" ) eq "false" ) {
@ -748,29 +771,48 @@ sub SB_SERVER_Alive( $ ) {
return; return;
} }
# let's ping the server to figure out if he is reachable # check via the RCC element
# needed for servers that go in hibernate mode if( $hash->{RCCNAME} ne "none" ) {
# an RCC element has been given as argument
$rccstatus = ReadingsVal( $hash->{RCCNAME}, "state", "off" );
}
# check via ping
my $p = Net::Ping->new( 'tcp' ); my $p = Net::Ping->new( 'tcp' );
if( $p->ping( $hash->{IP}, 2 ) ) { if( $p->ping( $hash->{IP}, 2 ) ) {
# host is reachable so go on normally $pingstatus = "on";
} else {
$pingstatus = "off";
}
# close our ping mechanism again
$p->close( );
# set the status of the server accordingly
if( ( $rccstatus eq "on" ) || ( $pingstatus eq "on" ) ) {
# the server is reachable
if( ReadingsVal( $name, "power", "on" ) eq "off" ) { if( ReadingsVal( $name, "power", "on" ) eq "off" ) {
Log3( $hash, 5, "SB_SERVER_Alive($name): ping succesful. " . # the first time we see the server being on
Log3( $hash, 5, "SB_SERVER_Alive($name): " .
"SB-Server is back again." ); "SB-Server is back again." );
# first time we realized server is away # first time we realized server is away
DevIo_OpenDev( $hash, 1, "SB_SERVER_DoInit" ); DevIo_OpenDev( $hash, 1, "SB_SERVER_DoInit" );
readingsSingleUpdate( $hash, "power", "on", 1 ); readingsSingleUpdate( $hash, "power", "on", 1 );
readingsSingleUpdate( $hash, "alivecheck", "?", 0 ); $hash->{ALIVECHECK} = "?";
# signal that to our clients $hash->{CLICONNECTION} = "off";
SB_SERVER_Broadcast( $hash, "SERVER", "ON" );
# quicker update to capture CLI connection faster
$nexttime = gettimeofday() + 10;
} }
if( ReadingsVal( $name, "alivecheck", "received" ) eq "waiting" ) { # check the CLI connection (sub-state)
if( $hash->{ALIVECHECK} eq "waiting" ) {
# ups, we did not receive any answer in the last minutes # ups, we did not receive any answer in the last minutes
# SB Server potentially dead or shut-down # SB Server potentially dead or shut-down
Log3( $hash, 5, "SB_SERVER_Alive($name): overrun SB-Server dead." ); Log3( $hash, 5, "SB_SERVER_Alive($name): overrun SB-Server dead." );
readingsSingleUpdate( $hash, "power", "off", 1 ); $hash->{CLICONNECTION} = "off";
readingsSingleUpdate( $hash, "alivecheck", "?", 0 );
# signal that to our clients # signal that to our clients
SB_SERVER_Broadcast( $hash, "SERVER", "OFF" ); SB_SERVER_Broadcast( $hash, "SERVER", "OFF" );
@ -781,22 +823,32 @@ sub SB_SERVER_Alive( $ ) {
# remove all timers we created # remove all timers we created
RemoveInternalTimer( $hash ); RemoveInternalTimer( $hash );
} else { } else {
if( $hash->{CLICONNECTION} eq "off" ) {
# signal that to our clients
# to be revisited, should only be sent after CLI established
SB_SERVER_Broadcast( $hash, "SERVER", "ON" );
}
$hash->{CLICONNECTION} = "on";
# just send something to the SB-Server. It will echo it # just send something to the SB-Server. It will echo it
# if we receive the echo, the server is still alive # if we receive the echo, the server is still alive
DevIo_SimpleWrite( $hash, "fhemalivecheck\n", 0 ); DevIo_SimpleWrite( $hash, "fhemalivecheck\n", 0 );
readingsSingleUpdate( $hash, "alivecheck", "waiting", 0 ); $hash->{ALIVECHECK} = "waiting";
} }
} else {
# the server is away and therefore presumably in hibernate / suspend } elsif( ( $rccstatus eq "off" ) && ( $pingstatus eq "off" ) ) {
Log3( $hash, 5, "SB_SERVER_Alive($name): ping timeout. " . if( ReadingsVal( $name, "power", "on" ) eq "on" ) {
# the first time we realize the server is off
Log3( $hash, 5, "SB_SERVER_Alive($name): " .
"SB-Server in hibernate / suspend?." ); "SB-Server in hibernate / suspend?." );
if( ReadingsVal( $name, "power", "off" ) eq "on" ) {
# first time we realized server is away # first time we realized server is away
$hash->{CLICONNECTION} = "off";
readingsSingleUpdate( $hash, "power", "off", 1 ); readingsSingleUpdate( $hash, "power", "off", 1 );
readingsSingleUpdate( $hash, "alivecheck", "?", 0 ); $hash->{ALIVECHECK} = "?";
# signal that to our clients # signal that to our clients
SB_SERVER_Broadcast( $hash, "SERVER", "OFF" ); SB_SERVER_Broadcast( $hash, "SERVER", "OFF" );
@ -806,14 +858,14 @@ sub SB_SERVER_Alive( $ ) {
# remove all timers we created # remove all timers we created
RemoveInternalTimer( $hash ); RemoveInternalTimer( $hash );
} }
} else {
# we shouldn't end up here
Log3( $hash, 5, "SB_SERVER_Alive($name): funny server status " .
"received. Ping=" . $pingstatus . " RCC=" . $rccstatus );
} }
# close our ping mechanism again
$p->close( );
# do an update of the status # do an update of the status
InternalTimer( gettimeofday() + AttrVal( $name, "alivetimer", 120 ), InternalTimer( $nexttime,
"SB_SERVER_Alive", "SB_SERVER_Alive",
$hash, $hash,
0 ); 0 );
@ -937,6 +989,13 @@ sub SB_SERVER_ParseServerStatus( $$ ) {
} elsif( $_ =~ /^(scanning:)([0-9]*)/ ) { } elsif( $_ =~ /^(scanning:)([0-9]*)/ ) {
readingsBulkUpdate( $hash, "scanning", $2 ); readingsBulkUpdate( $hash, "scanning", $2 );
next; next;
} elsif( $_ =~ /^(rescan:)([0-9]*)/ ) {
if( $2 eq "1" ) {
readingsBulkUpdate( $hash, "scanning", "yes" );
} else {
readingsBulkUpdate( $hash, "scanning", "no" );
}
next;
} elsif( $_ =~ /^(version:)([0-9\.]*)/ ) { } elsif( $_ =~ /^(version:)([0-9\.]*)/ ) {
readingsBulkUpdate( $hash, "serverversion", $2 ); readingsBulkUpdate( $hash, "serverversion", $2 );
next; next;
@ -1080,6 +1139,20 @@ sub SB_SERVER_ParseServerStatus( $$ ) {
} }
} }
# the list for the sync masters
# make all client create e new sync master list
SB_SERVER_Broadcast( $hash, "SYNCMASTER",
"FLUSH dont care", undef );
# now send the list for the sync masters
foreach my $player ( keys %players ) {
my $uniqueid = join( "", split( ":", $players{$player}{MAC} ) );
SB_SERVER_Broadcast( $hash, "SYNCMASTER",
"ADD $players{$player}{name} " .
"$players{$player}{MAC} $uniqueid", undef );
}
return; return;
} }
@ -1345,6 +1418,83 @@ sub SB_SERVER_CMDStackPop( $ ) {
} }
# ----------------------------------------------------------------------------
# parse the list of known Playlists
# ----------------------------------------------------------------------------
sub SB_SERVER_ParseServerPlaylists( $$ ) {
my( $hash, $dataptr ) = @_;
my $name = $hash->{NAME};
my $namebuf = "";
my $uniquename = "";
my $idbuf = -1;
# typically the start index being a number
if( $dataptr->[ 0 ] =~ /^([0-9])*/ ) {
shift( @{$dataptr} );
} else {
Log3( $hash, 5, "SB_SERVER_ParseServerPlaylists($name): entry is " .
"not the start number" );
return;
}
# typically the max index being a number
if( $dataptr->[ 0 ] =~ /^([0-9])*/ ) {
shift( @{$dataptr} );
} else {
Log3( $hash, 5, "SB_SERVER_ParseServerPlaylists($name): entry is " .
"not the end number" );
return;
}
my $datastr = join( " ", @{$dataptr} );
Log3( $hash, 5, "SB_SERVER_ParseServerPlaylists($name): data to parse: " .
$datastr );
# make all client create e new favorites list
SB_SERVER_Broadcast( $hash, "PLAYLISTS",
"FLUSH dont care", undef );
my @data1 = split( " ", $datastr );
foreach( @data1 ) {
if( $_ =~ /^(id:)(.*)/ ) {
Log3( $hash, 5, "SB_SERVER_ParseServerPlaylists($name): " .
"id:$idbuf name:$namebuf " );
if( $idbuf != -1 ) {
$uniquename = SB_SERVER_FavoritesName2UID( $namebuf );
SB_SERVER_Broadcast( $hash, "PLAYLISTS",
"ADD $namebuf $idbuf $uniquename", undef );
}
$idbuf = $2;
$namebuf = "";
$uniquename = "";
next;
} elsif( $_ =~ /^(playlist:)(.*)/ ) {
$namebuf = $2;
next;
} elsif( $_ =~ /^(count:)([0-9]*)/ ) {
# the last entry of the return
Log3( $hash, 5, "SB_SERVER_ParseServerPlaylists($name): " .
"id:$idbuf name:$namebuf " );
if( $idbuf != -1 ) {
$uniquename = SB_SERVER_FavoritesName2UID( $namebuf );
SB_SERVER_Broadcast( $hash, "PLAYLISTS",
"ADD $namebuf $idbuf $uniquename", undef );
}
} else {
$namebuf .= "_" . $_;
next;
}
}
return;
}
1; 1;
=pod =pod