raspberrypiでデジタルサイネージを作る！

展示会などでモニターに映像を流しておきたいですが、高価なスマホを繋ぎっぱなしにできないため、raspberrypiならちょうどよさそうということでやってみました。

【概要】
動画や静止画を流す。
ダイソーの３００円シャッターで画像を切り替える。

【苦労したところ】
動画を繰り返し出力すると動画が乱れたことへの対処
静止画を出力する方法を見つけるのに時間がかかった
動画、静止画のプレイヤーを終了させる方法を見つけること

【まだ未解決のところ】
プレイヤーを終了した時にraspiのデスクトップ画面や終了ログを表示してしまうこと

【詳細】
１．動画自動再生
raspi標準の動画プレイヤー、omxplayerを使用します。

自動実行の方法は何種類かありますが、今回は
/home/pi/.config/lxsession/LXDE-pi/autostart に以下を追加することにより自動再生にします。
omxplayer --no-osd --refresh --loop --blank -o both /home/pi/demo.mp4

参考にした記事：
映像展示の再生デバイスとしてRaspberry Piを使うと最高
http://nomolk.hatenablog.com/entry/2016/10/25/223000

２．静止画再生
静止画は高速に動作するfbiを使います。
sudo fbi -T 1 -d /dev/fb0 -noverbose /home/pi/demo.mpg

参考にした記事：
ラズパイカメラを使って連続撮影＆fbiコマンドでCUI画面のフレームバッファに直接表示する方法。SSH経由でもOK！
https://iot-plus.net/make/raspi/raspistill-continuous-shooting-displays-on-cui-using-frame-buffer-with-ssh-connection/

３．ファイル一覧取得
raspi内の動画、静止画ファイル一覧を取得

files = os.listdir(path)
files_file = [f for f in files if os.path.isfile(os.path.join(path, f))]

参考にした記事：
Pythonでファイル名・ディレクトリ名の一覧をリストで取得
https://note.nkmk.me/python-listdir-isfile-isdir/

４．プレイヤーの停止方法
omxplayerは'q'を送信
fbiはプロセスをkill（sudo pkill　fbi）
→qを送れば停止するらしいのだが上手くいかず。

参考にした記事：
OmxplayerをPythonコードから停止させる
https://qiita.com/goowaSystemTeam/items/95525dae25dee270087b

５．最新のraspbianではautostartファイルがない
結論としては、今までと同様の/home/pi/.config/lxsession/LXDE-pi/autostartファイルを作ればOK。

参考にした記事：
newest Raspbian Stretch LXDE not installed - how ot autostart now?
https://www.raspberrypi.org/forums/viewtopic.php?t=228199

６．ダイソーの３００円シャッターボタンを認識させる
bluebuttonをインストールしてconfigファイルのlongdownイベント時にos.system("sudo shutdown -h now")を実行すればよい。

参考にした記事：
ABshutter3
Bluetoothシャットダウンボタンを作る #300円でIoTボタン
https://qiita.com/nori-dev-akg/items/96584d9591d329f9dcb2

７．シャッターボタンが押されたときに次の映像ファイルを再生する
bluebuttonはイベントを起こすだけであり、現在の表示ファイルの番号はわからない。
そこで、シャッターボタンが押されたときに値をインクリメントしてpikleで保存している。
映像再生側で保存した値を読み込んで次の映像を表示する。

ここでpikleのモードを読み込みrb、書き込みwbとしたところ、数回に１回pikle型で読めなかったエラーが発生。ボタン押下での読み書きと映像再生側の読みの２つの処理が同時に走っており、ボタン押下のwbで一度pikleが初期化されたタイミングで映像再生側で読んだためのエラーの模様。
rb+として書き込むことで（初期化がなくなり）エラーが発生しなくなった。

8.omxplayerの連続再生に対応する
連続再生させると画像が乱れるので以下を/boot/config.txtに追加
gpu_mem=128

参考記事：
RPi3 OmxPlayer / VLC Player 連続再生2回目から映像が乱れる問題 
http://studio-geek.com/archives/1094

```shell:/home/pi/.config/lxsession/LXDE-pi/autostart
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash
@point-rpi
@/home/pi/start.sh
```
```shell:/home/pi/start.sh
sudo bluebutton -d="Shutter3" -c ~/.config/bluebutton &
sudo python /home/pi/demo.py
```

```shell:/home/pi/.config/bluebutton
keyup=echo UP
keydown=sudo python /home/pi/nextimage.py
longup=echo LONG UP
longdown=sudo python /home/pi/shutdown.py
```

```python:/home/pi/nextimage.py
#!/usr/bin/python
# coding:utf-8

import pickle
import os

path = '/home/pi/demo/'

files = os.listdir(path)
files_file = [f for f in files if os.path.isfile(os.path.join(path, f))]
file_num = len(files_file)

print(file_num)
print(files_file)

isCreated = os.path.exists('/home/pi/num.dat')
if (isCreated):
	f = open('num.dat','rb')
	num = pickle.load(f)
	f.close
else:
	num = 0

num = num +1
if (num >= file_num):
	num = 0
	print('roll over!!')

f = open('num.dat','rb+')
pickle.dump(num,f)
f.close
```
```python:/home/pi/shutdown.py
#!/usr/bin/python
# coding:utf-8
import os

os.system("sudo shutdown -h now")
```
```python:/home/pi/demo.py
# -*- coding: utf-8 -*-
#!/usr/bin/python

# import module
from time import sleep  # time module
import subprocess
from subprocess import call
import time
import pickle
import os

status = 1
num = 0

f = open('num.dat','wb')
pickle.dump(num,f)
f.close

path = '/home/pi/demo/'

files = os.listdir(path)
files_file = [f for f in files if os.path.isfile(os.path.join(path, f))]
file_num = len(files_file)

print(file_num)
print(files_file)

sleep(10)

last_num = num

while True:
    sleep(1)

    f = open('num.dat','rb')
    num = pickle.load(f)
    f.close

    if (last_num != num ):
        root, ext = os.path.splitext(files_file[last_num])
        if ( ext == '.mp4' ):
            proc.stdin.write("q")
        else:
            call (["sudo pkill fbi"], shell=True)
        status = 1
        last_num = num

    if ( status == 0 ):
        pass

    elif( status == 1 ):
        root, ext = os.path.splitext(files_file[num])
        if ( ext == '.mp4' ):
            command = 'omxplayer --no-osd --refresh --loop --blank -o both /home/pi/demo/'+files_file[num]
        else:
            command = 'sudo fbi -T 1 -d /dev/fb0 -noverbose demo/'+files_file[num]
        proc = subprocess.Popen(command,shell=True,stdin=subprocess.PIPE)
        status = 0

    else:
        pass
```
また、shファイルに実行権を与えておきましょう。

```shell
$ chmod +x start.sh
```

変更履歴：
２０１９.３.２３　新規作成
２０１９.３.２５　バグ修正（home.py）
 再生最初のファイルがmp4でない場合に対応した（１回目のomxplayer固定をやめた）
　num.datがないときに新規作成するよう対応（rb＋をwbに戻した）
　また、start.shの実行権付与を追加
２０１９.３.３１　バグ修正（home.py）
　不足していたfrom subprocess import callを追加