2014-08-28 34 views
1

首先,我有一个工作解决方案,但容易失败。从接收到的TCP数据包中打开带CEC的AMP

我想从Logitech Squeeze Center开启我的功放。

  • 服务器上运行192.168.0.30
  • 玩家是在餐厅192.168.0.31上运行
  • 该播放器通过HDMI连接到功放

我一直能够从播放器发送CEC命令到Amp以打开它。

我进一步开发了(在网络代码片段的帮助下)解决方案,以便SqueezeCenter中的界面在按下电源按钮时向播放器发送TCP数据包,播放器运行bash脚本并然后向AMP发送CEC命令 - 为其供电。

Power button for the player

Perl的插件,将在相关玩家按下电源按钮注意我有它设置为只将数据包发送到特定餐厅的球员包 - 但我想它在未来找到按下了电源按钮的播放器的IP并向其发送数据包。

package Plugins::PowerMonitor::Plugin; 

use strict; 

use IO::Socket; 
use Slim::Utils::Log; 
use Slim::Control::Request; 

my $log = Slim::Utils::Log->addLogCategory(
    { category  => 'plugin.powerMonitor', 
     defaultLevel => 'ERROR', 
     description => getDisplayName(), 
    } 
); 

sub getFunctions { 
    return ''; 
} 

sub getDisplayName { 
    return 'PLUGIN_POWER_MONITOR'; 
} 

sub initPlugin { 
    $log->debug("initPlugin"); 
    # Subscribe to power events 
    Slim::Control::Request::subscribe(\&powerCallback, [ ['power'] ]); 
} 

sub shutdownPlugin { 
    $log->debug("shutdownPlugin"); 
    Slim::Control::Request::unsubscribe(\&powerCallback); 
} 

sub powerCallback { 
    $log->debug("powerCallback"); 

    my $request = shift; 
    my $client = $request->client() || return; 

    my $sock = IO::Socket::INET->new(
     Proto => 'tcp', 
     PeerPort => 6500, 
     PeerAddr => '192.168.0.31', 
    ); 
    if (!$sock) { 
     $log->error("Could not create socket: $!"); 
     return; 
    } 

    my $msg = $client->id() . ':' . $client->name() . ':' . $client->power() . $/; 
    $log->debug($msg); 
    my $rc = $sock->send($msg); 
    if (!$rc) { 
     $log->error("Send error: $!"); 
    } 
} 

播放机上的bash脚本 - 这种坐作为对玩家守护程序监听包在端口6500:

#!/bin/bash 

netcat -lk 6500 | while read line 
do 
    if echo $line | grep -q 'Dining_Room:1' 
    then 
     powerStatus=$(echo "pow 5" | cec-client -s -d 1 |grep "power status" |cut -d ' ' -f 3) 

     if [ "$powerStatus" = "standby" ]; then 
      echo "Powering On Amp....." 
      echo "on 5" | cec-client -s -d 1 
     fi 
    elif echo $line | grep -q 'Dining_Room:0' 
    then 
     powerStatus=$(echo "pow 5" | cec-client -s -d 1 |grep "power status" |cut -d ' ' -f 3) 

     if [ "$powerStatus" = "on" ]; then 
      echo "Powering Off Amp....." 
      echo "standby 5" | cec-client -s -d 1 
     fi 
    fi 
done 

一个非常头发右脑复杂的设置,但是这是我必须使用Squeezebox的Perl插件。

我想知道是否有一个更稳定的方式来做到这一点,这将是什么 - 我可以调整当前的设置,使其更稳定 - 我可以更改Perl脚本以在播放器上编写文件而不是发送一个数据包,并使用netcat的(这接缝是它打破了地方),我不知道的Perl,但我相当的Linux和bash脚本精通

更新29/08/2014: 关于它发送到播放器的IP的话题,它看起来像它实例化一个$ client,并且有一个名称的方法 - 我想知道那里还有什么可用的 - 我希望我认识Perl。

+1

〜300这里关于S.O.为'[bash] netcat'。从我以前阅读的内容来看,我认为你是正确的(同时正确地完成工作)是缺点。祝你好运。 – shellter 2014-08-28 13:31:27

回答

0

我决定改变我的方法,以便服务器将SSH连接到播放器并运行相关的脚本。

初始测试显示这比netcat更可靠。我无法获得密钥身份验证,因此必须在脚本中输入密码。

的Perl脚本:

package Plugins::PowerMonitor::Plugin; 

use strict; 
use warnings; 

use IO::Socket; 

use Slim::Utils::Log; 
use Slim::Control::Request; 

use Net::SSH::Any; 

my $log = Slim::Utils::Log->addLogCategory({ 
     category  => 'plugin.powerMonitor', 
     defaultLevel => 'ERROR', 
     description => getDisplayName(), 
}); 

sub getFunctions { 
     return ''; 
} 

sub getDisplayName { 
     return 'PLUGIN_POWER_MONITOR'; 
} 

sub initPlugin { 
     $log->debug("initPlugin"); 
     # Subscribe to power events 
     Slim::Control::Request::subscribe(
       \&powerCallback, 
       [['power']] 
     ); 
} 

sub shutdownPlugin { 
     $log->debug("shutdownPlugin"); 
     Slim::Control::Request::unsubscribe(\&powerCallback); 
} 

sub powerCallback { 
     $log->debug("powerCallback"); 

     my $request = shift; 
     my $client = $request->client() || return; 

my $host = "192.168.0.31"; 

my $user = "pi"; 
my $pass = "myPassword"; 

my $ssh = Net::SSH::Any->new($host, user => $user, password => $pass); 

if ($ssh->error) { 
$log->error("whee...something wrong here: " . $ssh->error); 
} 
else { 
     my @out = $ssh->capture('nohup /home/pi/ampOn > foo.out 2> foo.err < /dev/null &'); 
$log->debug("@out"); 
} 

} 

改变的bash脚本:

#!/bin/bash 

       if [ ! -f /tmp/ampIsOn ] 
       then 
         powerStatus=$(echo "pow 5" | cec-client -s -d 1 |grep "power status" |cut -d ' ' -f 3) 

         if [ "$powerStatus" = "standby" ]; then 
           echo "Powering On Amp....." 
           echo "on 5" | cec-client -s -d 1 
           touch /tmp/ampIsOn 
         fi 

       else 
         powerStatus=$(echo "pow 5" | cec-client -s -d 1 |grep "power status" |cut -d ' ' -f 3) 

         if [ "$powerStatus" = "on" ]; then 
           echo "Powering Off Amp....." 
           echo "standby 5" | cec-client -s -d 1 
           rm /tmp/ampIsOn 
         fi 
       fi 

我万一有人惯于标记为正确但有一些更好的解决方案或提示。

+0

它仍然是不正确的 - 我认为写文件的方法接缝不起作用。 – Rob 2014-09-03 20:09:10