1

まず、機能するソリューションがありますが、失敗する傾向があります。

Logicool Squeeze Center からアンプの電源を入れたいです。

  • サーバーは 192.168.0.30 で実行されています
  • プレイヤーは 192.168.0.31 で実行されているダイニング ルームにいます
  • プレーヤーはHDMI経由でアンプに接続されています

プレーヤーからアンプに CEC コマンドを送信して電源を入れることができました。

私はさらに (Web 上のコード スニペットの助けを借りて) ソリューションを開発し、電源ボタンが押されたときに SqueezeCenter のインターフェイスが TCP パケットをプレーヤーに送信し、そこでプレーヤーが bash スクリプトを実行してから、 AMP への CEC コマンド - 電源を入れます。

プレーヤーの電源ボタン

関連するプレーヤーの電源ボタンが押されたときにパケットを送信する 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 スクリプトにはかなり精通しています。

UPDATE 29/08/2014: プレイヤーの IP に送信するというトピックでは、$client をインスタンス化し、名前のメソッドがあるように見えます - 他に何が利用できるのだろうか - Perl を知っていたらよかったのに.

4

1 に答える 1

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

誰かがより良い解決策やヒントを持っている場合に備えて、まだ正しいとマークしません。

于 2014-09-01T08:05:38.183 に答える