Включите AMP с CEC из полученных пакетов TCP
Во-первых, у меня есть рабочее решение, но оно подвержено сбоям.
Я хотел бы включить свой усилитель из Logitech Squeeze Center.
- Сервер работает на 192.168.0.30
- Игрок в столовой работает на 192.168.0.31
- Плеер подключен через HDMI к усилителю
Мне удалось отправить команды CEC от плеера на усилитель, чтобы включить его.
Я далее разработал (с помощью фрагментов кода из Интернета) решение, чтобы интерфейс в SqueezeCenter при нажатии кнопки питания отправлял TCP-пакет игроку, в котором проигрыватель запускает сценарий bash, и, в свою очередь, отправляет Команда CEC для AMP - включение.
Плагин 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
Очень сложная настройка, но это то, с чем я должен работать в плане плагинов Perl для Squeezebox.
Я хотел бы знать, есть ли более стабильный способ сделать это и что бы это было - могу ли я настроить текущую настройку, чтобы сделать ее более стабильной - могу ли я изменить скрипт Perl, чтобы записать файл на проигрыватель вместо отправки пакет и использование netcat (это швы, чтобы быть местом, где он ломается)
Я не знаю Perl, но довольно разбираюсь в Linux и bash-скриптах
ОБНОВЛЕНИЕ 29/08/2014: на тему отправки по IP-адресу проигрывателя похоже, что он создает экземпляр $ client и у него есть метод имени - интересно, что там еще есть - человек, я бы хотел знать Perl,
1 ответ
Я решил изменить свой подход, чтобы сервер передавал SSH в проигрыватель и запускал соответствующий скрипт.
Начальные тесты показывают, что это намного надежнее, чем netcat. Я не смог заставить работать ключ auth, поэтому пришлось ввести пароль в скрипт.
Perl Script:
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
Я не буду отмечать как правильный, но в случае, если у кого-то есть лучшие решения или подсказки.