Android端末から電源を切れるようにする

前回beaglebone black上にbotic_demoのkernel再々構築を行い、mpdクライアントから楽曲の再生を行う用意をした。
自分にとり優先順位の高いWiFi経由での接続も行え、NASサーバー上の楽曲ファイルをMPDroidを用いてAndroid端末から再生することもできるようになった。
時々無音期間が発生したり勝手にリブートしてしまうので安定性という意味ではまだまだである。
しかし、音飛びや再生停止はTorneでドラマを見ていても発生するので、我が家のWiFi事情でしかたがないことと原因も調べず諦めている。
自分にとって仕事後、深夜に帰宅しクールダウンする時間が必要なのであるが、BBBのbotic_demoを立ち上げ音楽を聴けるようになったのは大きい。
そのうちBBBごと適当な箱に入れてしまおうと考えている。

今回は箱入れのための課題の一つであるBBBのリモートからの電源オフの方法を考える。
ただ、結論から言うと目的は達せられたもののGUI的には非常に不細工である。
Android端末で見栄えの良いWEBデザインは、それはそれで一つの技術課題であり勉強が必要であるようだ。

リモートでBBBの電源を切るために、BBBにlighttdをインストールし、perlによるCGIでshutdownを実行することとする。
ついでに、CGIでPCM5122のvolumeをコントロールするインターフェースを実装する。

BBBでのperlの場所を確認。

debian@bbb:~$ which perl
/usr/bin/perl

次にlighttpdをインストールするが、botic_demoの環境では以下のまじないを行わないと、apt-getが動作しない。

debian@bbb:~$ sudo nano /etc/apt/apt.conf
debian@bbb:~$ cat /etc/apt/apt.conf
Acquire::Check-Valid-Until "0";

debian@bbb:~$ 

apt-get updateを行う。

debian@bbb:~$ sudo apt-get update
Get:1 http://ftp.us.debian.org wheezy Release.gpg [1,655 B]
Get:2 http://ftp.us.debian.org wheezy-updates Release.gpg [836 B]
Get:3 http://ftp.us.debian.org wheezy Release [168 kB]
Get:4 http://ftp.us.debian.org wheezy-updates Release [124 kB]
Get:5 http://ftp.us.debian.org wheezy/main Sources [7,496 kB]
Get:6 http://security.debian.org wheezy/updates Release.gpg [836 B]
Hit http://security.debian.org wheezy/updates Release
Get:7 http://security.debian.org wheezy/updates/main Sources [225 kB]
Get:8 http://security.debian.org wheezy/updates/contrib Sources [20 B]
Get:9 http://security.debian.org wheezy/updates/non-free Sources [20 B]
Get:10 http://security.debian.org wheezy/updates/main armhf Packages [356 kB]
Get:11 http://security.debian.org wheezy/updates/contrib armhf Packages [20 B]
Get:12 http://security.debian.org wheezy/updates/non-free armhf Packages [20 B]
Get:13 http://security.debian.org wheezy/updates/contrib Translation-en [14 B]
Get:14 http://security.debian.org wheezy/updates/main Translation-en [165 kB]
Get:15 http://security.debian.org wheezy/updates/non-free Translation-en [14 B]
Get:16 http://ftp.us.debian.org wheezy/contrib Sources [55.8 kB]
Get:17 http://ftp.us.debian.org wheezy/non-free Sources [112 kB]
Get:18 http://ftp.us.debian.org wheezy/main armhf Packages [7,432 kB]
Get:19 http://ftp.us.debian.org wheezy/contrib armhf Packages [39.3 kB]
Get:20 http://ftp.us.debian.org wheezy/non-free armhf Packages [67.7 kB]
Get:21 http://ftp.us.debian.org wheezy/contrib Translation-en [34.8 kB]
Get:22 http://ftp.us.debian.org wheezy/main Translation-en [3,848 kB]
Get:23 http://ftp.us.debian.org wheezy/non-free Translation-en [66.1 kB]
Get:24 http://ftp.us.debian.org wheezy-updates/main Sources [3,198 B]
Get:25 http://ftp.us.debian.org wheezy-updates/contrib Sources [20 B]
Get:26 http://ftp.us.debian.org wheezy-updates/non-free Sources [20 B]
Get:27 http://ftp.us.debian.org wheezy-updates/main armhf Packages [4,384 B]
Get:28 http://ftp.us.debian.org wheezy-updates/contrib armhf Packages [20 B]
Get:29 http://ftp.us.debian.org wheezy-updates/non-free armhf Packages [20 B]
Get:30 http://ftp.us.debian.org wheezy-updates/contrib Translation-en [14 B]
Get:31 http://ftp.us.debian.org wheezy-updates/non-free Translation-en [14 B]
Get:32 http://ftp.us.debian.org wheezy-updates/main Translation-en [3,198 B]
Fetched 20.2 MB in 27s (724 kB/s)
Reading package lists... Done
debian@bbb:~$ 

lighttpdをインストールする。

debian@bbb:~$  sudo apt-get install -y lighttpd
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  libfam0 libterm-readkey-perl libterm-readline-perl-perl spawn-fcgi
Suggested packages:
  fam rrdtool apache2-utils
The following NEW packages will be installed:
  libfam0 libterm-readkey-perl libterm-readline-perl-perl lighttpd spawn-fcgi
0 upgraded, 5 newly installed, 0 to remove and 67 not upgraded.
Need to get 394 kB of archives.
After this operation, 1,128 kB of additional disk space will be used.
Get:1 http://ftp.us.debian.org/debian/ wheezy/main libfam0 armhf 2.7.0-17 [26.9 kB]
Get:2 http://ftp.us.debian.org/debian/ wheezy/main libterm-readkey-perl armhf 2.30-4 [29.7 kB]
Get:3 http://ftp.us.debian.org/debian/ wheezy/main libterm-readline-perl-perl all 1.0303-1 [51.9 kB]
Get:4 http://ftp.us.debian.org/debian/ wheezy/main lighttpd armhf 1.4.31-4+deb7u3 [272 kB]
Get:5 http://ftp.us.debian.org/debian/ wheezy/main spawn-fcgi armhf 1.6.3-1 [13.4 kB]
Fetched 394 kB in 3s (120 kB/s)
Selecting previously unselected package libfam0.
(Reading database ... 33193 files and directories currently installed.)
Unpacking libfam0 (from .../libfam0_2.7.0-17_armhf.deb) ...
Selecting previously unselected package libterm-readkey-perl.
Unpacking libterm-readkey-perl (from .../libterm-readkey-perl_2.30-4_armhf.deb) ...
Selecting previously unselected package libterm-readline-perl-perl.
Unpacking libterm-readline-perl-perl (from .../libterm-readline-perl-perl_1.0303-1_all.deb) ...
Selecting previously unselected package lighttpd.
Unpacking lighttpd (from .../lighttpd_1.4.31-4+deb7u3_armhf.deb) ...
Selecting previously unselected package spawn-fcgi.
Unpacking spawn-fcgi (from .../spawn-fcgi_1.6.3-1_armhf.deb) ...
Processing triggers for man-db ...
Processing triggers for systemd ...
systemctl: enabling lighttpd.service
Setting up libfam0 (2.7.0-17) ...
Setting up libterm-readkey-perl (2.30-4) ...
Setting up libterm-readline-perl-perl (1.0303-1) ...
Setting up lighttpd (1.4.31-4+deb7u3) ...
[ ok ] Starting lighttpd (via systemctl): lighttpd.service.
Setting up spawn-fcgi (1.6.3-1) ...
update-alternatives: using /usr/bin/spawn-fcgi.standalone to provide /usr/bin/spawn-fcgi (spawn-fcgi) in auto mode
update-alternatives: warning: not replacing /usr/share/man/man1/spawn-fcgi.1.gz with a link
localepurge: Disk space freed in /usr/share/locale: 0 KiB
localepurge: Disk space freed in /usr/share/man: 0 KiB

Total disk space freed by localepurge: 0 KiB

debian@bbb:~$ 

インストール後にLAN上のPCからBBBのIPアドレスにアクセスするとWelcome Pageを表示することができる。

CGIを有効にする。

debian@bbb:~$ sudo lighty-enable-mod cgi
debian@bbb:~$

CGIの設定ファイルを編集。

debian@bbb:~$ nano /etc/lighttpd/conf-enabled/10-cgi.conf
debian@bbb:~$ cat /etc/lighttpd/conf-enabled/10-cgi.conf
# /usr/share/doc/lighttpd/cgi.txt

server.modules += ( "mod_cgi" )

$HTTP["url"] =~ "^/cgi-bin/" {
        cgi.assign = (
                ".pl"  => "/usr/bin/perl",
                ".cgi" => "/usr/bin/perl"
         )
}

## Warning this represents a security risk, as it allow to execute any file
## with a .pl/.py even outside of /usr/lib/cgi-bin.
#
#cgi.assign      = (
#       ".pl"  => "/usr/bin/perl",
#       ".py"  => "/usr/bin/python",
#)
debian@bbb:~$

lighttpdの再起動。

debian@bbb:~$ sudo /etc/init.d/lighttpd restart
[ ok ] Restarting lighttpd (via systemctl): lighttpd.service.
debian@bbb:~$

CGIからshutdownコマンドおよびi2cset/i2cgetコマンドを実行できるように/etc/sudoersを編集する。
このような編集はセキュリティ的に脆弱なものにするので注意が必要である。
ただ、今回のようにLAN上にある前提の場合、お手軽である。
lighttpdはwww-dataで実行するので、www-dataに全権限を与える。

debian@bbb:~$ sudo visudo
debian@bbb:~$ sudo cat /etc/sudoers
#
# This file MUST be edited with the 'visudo' command as root.
#
# Please consider adding local content in /etc/sudoers.d/ instead of
# directly modifying this file.
#
# See the man page for details on how to write a sudoers file.
#
Defaults        env_reset
Defaults        mail_badpass
Defaults        secure_path="/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"

# Host alias specification

# User alias specification

# Cmnd alias specification

# User privilege specification
root    ALL=(ALL:ALL) ALL
www-data ALL=(ALL) NOPASSWD:ALL

# Allow members of group sudo to execute any command
%sudo   ALL=(ALL:ALL) ALL

# See sudoers(5) for more information on "#include" directives:

#includedir /etc/sudoers.d
%admin  ALL=(ALL) ALL
debian@bbb:~$

そして、今回作成したサンプルスクリプト。

debian@bbb:~$ sudo nano /var/www/cgi-bin/pcm5122ctrl.cgi debian@bbb:~$

pcm5122ctrl.cgiのソースコードは以下。


#! /usr/bin/perl
use CGI;

my $mycgi = new CGI;

&parse_form();
&make_html();
exit;

sub shutdown_now{
    my $retval;

    print $mycgi->header(-charset=>"utf-8");
    print $mycgi->start_html(-title=>"PCM5122 I2C Ctrl", -BGCOLOR=>'#ffffff'),
        $mycgi->center($mycgi->h1('PCM5122 I2C Ctrl')),
        $mycgi->hr;
    print "電源を切ります";
    print $mycgi->br;
    print $mycgi->br;
    print $mycgi->end_html;
    sleep(3);
    $retval = `sudo \/etc\/init\.d\/mpd stop`;
    sleep(3);
    $retval = `sudo shutdown -h now`;
    exit;
}

sub get_i2c{
    my ($i2cbus, $daddress, $page, $address) = @_;
    my $retval;
    #select page
    $retval = `sudo i2cset -y $i2cbus $daddress 0x00 $page b`;
    #get value from target register
    $retval = `sudo i2cget -y $i2cbus $daddress $address c`;
}

sub set_i2c{
    my ($i2cbus, $daddress, $page, $address, $value) = @_;
    my $retval;
    #select page
    $retval = `sudo i2cset -y $i2cbus $daddress 0x00 $page b`;
    #set value in target
    $retval = `sudo i2cset -y $i2cbus $daddress $address $value b`;
}

sub get_current_volume{
    my $currentVol;
    $currentVol = &get_i2c( 1 , 0x4c , 0 , 0x3d );
}

sub change_volume{
    my ($input_volume) = @_;
    $input_volume = (24 - $input_volume) * 2;
    if ($input_volume > 255){$input_volume = 255;}
    if ($input_volume <   0){$input_volume =   0;}
    # set volume. VOLL[7:0]
    &set_i2c(1 , 0x4c , 0 , 0x3d , $input_volume);
}

sub set_volume_mute{
    # PCTL[1:0] 01: Right channel volume follows left channel setting
    &set_i2c(1 , 0x4c , 0 , 0x3c , 0x01);
    # set volume to MUTE. VOLL[7:0] = 0xff
    &set_i2c(1 , 0x4c , 0 , 0x3d , 0xff);
}

sub set_volume_0db{
    # PCTL[1:0] 01: Right channel volume follows left channel setting
    &set_i2c(1 , 0x4c , 0 , 0x3c , 0x01);
    # set volume to MUTE. VOLL[7:0] = 0xff
    &set_i2c(1 , 0x4c , 0 , 0x3d , 0x30);
}

sub set_volume_max{
    # PCTL[1:0] 01: Right channel volume follows left channel setting
    &set_i2c(1 , 0x4c , 0 , 0x3c , 0x01);
    # set volume to MUTE. VOLL[7:0] = 0xff
    &set_i2c(1 , 0x4c , 0 , 0x3d , 0x00);
}

sub volume_down{

    my $volume;

    $volume = &get_current_volume();
    $volume = hex($volume);

    if ($volume != 255){
        ++$volume;
        # set volume to MUTE. VOLL[7:0]
        &set_i2c(1 , 0x4c , 0 , 0x3d , $volume)
    }
}

sub volume_up{
    my $volume;

    $volume = &get_current_volume();
    $volume = hex($volume);

    if ($volume != 0){
        --$volume;
        # set volume to MUTE. VOLL[7:0]
        &set_i2c(1 , 0x4c , 0 , 0x3d , $volume);
    }
}

sub parse_form{
    my $name;
    my $slider;
    $name = $mycgi->param('TurnOff');
    if ($name eq 'PowerOff'){
        &shutdown_now();
    }

    $name = $mycgi->param('Vol Set');
    if ($name eq 'Vol Set'){
        $slider = $mycgi->param('slider');
        &change_volume($slider);
    }

    $name = $mycgi->param('Mute');
    if ($name eq 'Mute'){
        &set_volume_mute();
    }
    $name = $mycgi->param('Vol+');
    if ($name eq 'Vol+'){
        &volume_up();
    }
    $name = $mycgi->param('Vol-');
    if ($name eq 'Vol-'){
        &volume_down();
    }
    $name = $mycgi->param('0dB ');
    if ($name eq '0dB '){
        &set_volume_0db();
    }
    $name = $mycgi->param('Max ');
    if ($name eq 'Max '){
        &set_volume_max();
    }
}

sub make_html{
    my $volume;
    print $mycgi->header(-charset=>"utf-8");
    print $mycgi->start_html(-title=>"PCM5122 I2C Ctrl", -BGCOLOR=>'#ffffff');
    print $mycgi->hr;
    print $debug;
    print $mycgi->start_form();
    print $mycgi->submit(
        -name=>'TurnOff',
        -value=>'PowerOff',
        -style=>'font-size:80pt');
    print $mycgi->end_form;
    print $mycgi->br;
    print $mycgi->br;

    $volume = &get_current_volume();
    $volume = (48 - hex($volume)) /2;;
    print $mycgi->hr;
    print "Current Volume\:";
    print $mycgi->start_form();
    print $mycgi->textfield(
        -name=>$volume,
        -value=>$volume,
        -size=>'4',
        -style=>'font-size:80pt');
    print $mycgi->end_form;

    print $mycgi->start_form();
    print "<input type=\"range\" name=\"slider\" value=\"$volume\" min=\"-104\" max=\"24\" \/>";
    print $mycgi->br;
    print $mycgi->submit(
        -name=>'Vol Set',
        -value=>'Vol Set',
        -style=>'font-size:80pt');
    print $mycgi->end_form;
    print $mycgi->hr;

    print $mycgi->start_form();
    print $mycgi->submit(
        -name=>'Max ',
        -value=>'Max ',
        -style=>'font-size:80pt');
    print $mycgi->end_form;

    print $mycgi->br;

    print $mycgi->hr;
    print $mycgi->start_form();
    print $mycgi->submit(
        -name=>'Vol+',
        -value=>'Vol+',
        -style=>'font-size:80pt');
    print $mycgi->end_form;

    print $mycgi->start_form();
    print $mycgi->submit(
        -name=>'Vol-',
        -value=>'Vol-',
        -style=>'font-size:80pt');
    print $mycgi->end_form;
    print $mycgi->hr;

    print $mycgi->start_form();
    print $mycgi->submit(
        -name=>'0dB ',
        -value=>'0dB ',
        -style=> 'font-size:80pt');
    print $mycgi->end_form;

    print $mycgi->start_form();
    print $mycgi->submit(
        -name=>'Mute',
        -value=>'Mute',
        -style=>'font-size:80pt');
    print $mycgi->end_form;

    $mycgi->end_html;
}

スクリプトに実行権限を与える。

debian@bbb:~$ sudo chmod 755 /var/www/cgi-bin/pcm5122ctrl.cgi
debian@bbb:~$

cgiの置き場所はWelcome Pageには/usr/lib/cgi-binであるように書かれているが、上記手順では/var/www/cgi-bin/となる。
LAN上のPCから例えばhttp://192.168.1.29/cgi-bin/pcm5122ctrl.cgiにアクセスするとCGIを表示することができる。

このCGIはAndroid端末のChromeでアクセスすることのみ想定している。
PC上のChromeから見ると巨大なボタンが表示される。

テキストボックスを編集してもボリュームは変更にならない。
スライダを変更して”Vol Set”ボタンを押すとボリュームの変更を行うことができるが、スライダが小さくて非常に使い辛い。
残念であるが、永遠にサンプルのままであろう。

こんな稚拙なスクリプトを晒すのもどうかと思うが、何はともあれAndroid端末から電源をオフとすること、ボリュームを変更することはできるようになった。

タイトルとURLをコピーしました