LoginSignup
4
5

More than 3 years have passed since last update.

Raspberry PIでデジタルサイネージ

Posted at

Raspberry PIでデジタルサイネージを作ろう。

image.png

縦看板にするためのHDMI出力設定

/boot/config.txt に設定を追加

/boot/config.txt
display_rotate=1 #追加することにより縦方向表示になる。

プログラムからChromeを起動制御するためには、Selenium Chrome webdriverが必要です。

$ mkdir chrome
$ cd chrome
# sudo pip install selenium
# wget http://launchpadlibrarian.net/361669488/chromium-chromedriver_65.0.3325.181-0ubuntu0.14.04.1_armhf.deb
# sudo dpkg -i chromium-chromedriver_65.0.3325.181-0ubuntu0.14.04.1_armhf.deb

visual studio 2017を使ってcoding 参照

テンプレートを使ってさくっと出来上がり

static/contには、表示するコンテント

.
├── DigitalSignage.pyproj
├── app.py
├── comm.py
├── routes.py
├── static
│   ├── cont
│   │   ├── Raspberries.jpg
│   │   ├── Raspberries1.jpg
│   │   ├── Raspberries2.jpg
│   │   ├── Raspberries3.jpg
│   │   └── Raspberries4.jpg
│   ├── content
│   │   ├── bootstrap.css
│   │   ├── bootstrap.min.css
│   │   └── site.css
│   ├── favicon.ico
│   ├── fonts
│   │   ├── glyphicons-halflings-regular.eot
│   │   ├── glyphicons-halflings-regular.svg
│   │   ├── glyphicons-halflings-regular.ttf
│   │   └── glyphicons-halflings-regular.woff
│   └── scripts
│       ├── _references.js
│       ├── bootstrap.js
│       ├── bootstrap.min.js
│       ├── jquery-1.10.2.intellisense.js
│       ├── jquery-1.10.2.js
│       ├── jquery-1.10.2.min.js
│       ├── jquery-1.10.2.min.map
│       ├── jquery.validate-vsdoc.js
│       ├── jquery.validate.js
│       ├── jquery.validate.min.js
│       ├── jquery.validate.unobtrusive.js
│       ├── jquery.validate.unobtrusive.min.js
│       ├── modernizr-2.6.2.js
│       ├── respond.js
│       └── respond.min.js
└── views
    ├── index.tpl
    └── layout.tpl

6 directories, 35 files

ソースの中身は、github

app.py
"""
This script runs the application using a development server.
"""

import bottle,sys,os,time,threading
from selenium import webdriver
os.environ['DISPLAY']=':0'          #HDMI出力設定
os.environ['SERVER_HOST']='0.0.0.0' #webserver 設定
os.environ['SERVER_PORT']='8890'  #webserver port設定
# chrome 自動起動設定
import comm
comm.options = webdriver.ChromeOptions()
comm.options.add_argument("--kiosk")
comm.options.add_argument("--disable-infobars") 
comm.browser = webdriver.Chrome(chrome_options=comm.options,executable_path="/usr/bin/chromedriver")

# routes contains the HTTP handlers for our server and must be imported.
import routes

if '--debug' in sys.argv[1:] or 'SERVER_DEBUG' in os.environ:
    # Debug mode will enable more verbose output in the console window.
    # It must be set at the beginning of the script.
    bottle.debug(True)

def wsgi_app():
    """Returns the application to make available through wfastcgi. This is used
    when the site is published to Microsoft Azure."""
    return bottle.default_app()

if __name__ == '__main__':
    PROJECT_ROOT = os.path.abspath(os.path.dirname(__file__))
    STATIC_ROOT = os.path.join(PROJECT_ROOT, 'static').replace('\\', '/')
    HOST = os.environ.get('SERVER_HOST', 'localhost')
    try:
        PORT = int(os.environ.get('SERVER_PORT', '5555'))
    except ValueError:
        PORT = 5555

    @bottle.route('/static/<filepath:path>')
    def server_static(filepath):
        """Handler for static files, used with the development server.
        When running under a production server such as IIS or Apache,
        the server should be configured to serve the static files."""
        return bottle.static_file(filepath, root=STATIC_ROOT)
    def geturl():
        time.sleep(1)
        comm.browser.get('http://%s:%s/'%(HOST,PORT))
        time.sleep(1)
        comm.browser.execute_script("document.body.style.zoom = '75%'")
    th = threading.Thread(target=geturl)
    th.start()
    # Starts a local test server.
    bottle.run(server='wsgiref', host=HOST, port=PORT)

関数間共有変数(selenium用)

comm.py
def init():
    global browser,options

routes.py
"""
Routes and views for the bottle application.
"""

from bottle import route, view
from datetime import datetime
import os

@route('/')
@route('/home')
@view('index')
def home():
    """Renders the home page."""
    lst=os.listdir("./static/cont") #/staic/cont配下にコンテンツ用画像ファイルがある
    return dict(
        year=datetime.now().year,pict = lst
    )
# テンプレートにある以下のファイルは、削除

上部には、時計と天気をウィジェット表示

時計ウィジェット

天気ウィジェット

index.tpl
% rebase('layout.tpl', title='Home Page', year=year)

<div class="jumbotron">
<div class="row">
<!--時計の表示-->
    <div class="col-md-4">
    <div class="cleanslate w24tz-current-time w24tz-large" style="display: inline-block !important; visibility: hidden !important; min-width:300px !important; min-height:145px !important;"><p><a href="//24timezones.com/ja_time/japan_chiba_clock.php" style="text-decoration: none" class="clock24" id="tz24-1559793488-c213600-eyJob3VydHlwZSI6MTIsInNob3dkYXRlIjoiMSIsInNob3dzZWNvbmRzIjoiMSIsImNvbnRhaW5lcl9pZCI6ImNsb2NrX2Jsb2NrX2NiNWNmODhmNTA3NGNmNSIsInR5cGUiOiJkYiIsImxhbmciOiJqYSJ9" title="千葉 世界時計" target="_blank" rel="nofollow">千葉の現在の時刻</a></p><div id="clock_block_cb5cf88f5074cf5"></div></div>
    <script type="text/javascript" src="//w.24timezones.com/l.js" async></script>
    </div>
<!--天気予報の表示-->
    <div class="col-md-4">
    <!-- weather widget start --><div id="m-booked-weather-bl250-22795"> <div class="booked-wzs-250-175 weather-customize" style="background-color:#707d8a;width:250px;" id="width1"> <div class="booked-wzs-250-175_in"> <div class="booked-wzs-250-175-data"> <div class="booked-wzs-250-175-left-img wrz-03"> <a target="_blank" href="https://www.booked.net/"> <img src="//s.bookcdn.com/images/letter/logo.gif" alt="booked.net" /> </a> </div> <div class="booked-wzs-250-175-right"> <div class="booked-wzs-day-deck"> <div class="booked-wzs-day-val"> <div class="booked-wzs-day-number"><span class="plus">+</span>19</div> <div class="booked-wzs-day-dergee"> <div class="booked-wzs-day-dergee-val">&deg;</div> <div class="booked-wzs-day-dergee-name">C</div> </div> </div> <div class="booked-wzs-day"> <div class="booked-wzs-day-d">H: <span class="plus">+</span>28&deg;</div> <div class="booked-wzs-day-n">L: <span class="plus">+</span>20&deg;</div> </div> </div> <div class="booked-wzs-250-175-info"> <div class="booked-wzs-250-175-city">千葉市 </div> <div class="booked-wzs-250-175-date">木曜日, 06 6月</div> <div class="booked-wzs-left"> <span class="booked-wzs-bottom-l">週間天気予報を見る</span> </div> </div> </div> </div> <a target="_blank" href="https://booked.jp/weather/chiba-19689"> <table cellpadding="0" cellspacing="0" class="booked-wzs-table-250"> <tr> <td></td> <td></td> <td></td> <td></td> <td></td> <td></td> </tr> <tr> <td class="week-day-ico"><div class="wrz-sml wrzs-01"></div></td> <td class="week-day-ico"><div class="wrz-sml wrzs-18"></div></td> <td class="week-day-ico"><div class="wrz-sml wrzs-18"></div></td> <td class="week-day-ico"><div class="wrz-sml wrzs-18"></div></td> <td class="week-day-ico"><div class="wrz-sml wrzs-03"></div></td> <td class="week-day-ico"><div class="wrz-sml wrzs-18"></div></td> </tr> <tr> <td class="week-day-val"><span class="plus">+</span>19&deg;</td> <td class="week-day-val"><span class="plus">+</span>24&deg;</td> <td class="week-day-val"><span class="plus">+</span>27&deg;</td> <td class="week-day-val"><span class="plus">+</span>22&deg;</td> <td class="week-day-val"><span class="plus">+</span>24&deg;</td> <td class="week-day-val"><span class="plus">+</span>25&deg;</td> </tr> <tr> <td class="week-day-val"><span class="plus">+</span>19&deg;</td> <td class="week-day-val"><span class="plus">+</span>21&deg;</td> <td class="week-day-val"><span class="plus">+</span>21&deg;</td> <td class="week-day-val"><span class="plus">+</span>21&deg;</td> <td class="week-day-val"><span class="plus">+</span>21&deg;</td> <td class="week-day-val"><span class="plus">+</span>21&deg;</td> </tr> </table> </a> </div></div> </div><script type="text/javascript"> var css_file=document.createElement("link"); css_file.setAttribute("rel","stylesheet"); css_file.setAttribute("type","text/css"); css_file.setAttribute("href",'https://s.bookcdn.com/css/w/booked-wzs-widget-275.css?v=0.0.1'); document.getElementsByTagName("head")[0].appendChild(css_file); function setWidgetData(data) { if(typeof(data) != 'undefined' && data.results.length > 0) { for(var i = 0; i < data.results.length; ++i) { var objMainBlock = document.getElementById('m-booked-weather-bl250-22795'); if(objMainBlock !== null) { var copyBlock = document.getElementById('m-bookew-weather-copy-'+data.results[i].widget_type); objMainBlock.innerHTML = data.results[i].html_code; if(copyBlock !== null) objMainBlock.appendChild(copyBlock); } } } else { alert('data=undefined||data.results is empty'); } } </script> <script type="text/javascript" charset="UTF-8" src="https://widgets.booked.net/weather/info?action=get_weather_info&ver=6&cityID=19689&type=3&scode=124&ltid=3458&domid=587&anc_id=64726&cmetric=1&wlangID=16&color=707d8a&wwidth=250&header_color=ffffff&text_color=333333&link_color=08488D&border_form=1&footer_color=ffffff&footer_text_color=333333&transparent=0"></script><!-- weather widget end --></div>
    </div>
    <div class="col-md-4">
    </div>
</div>
<!--サイネージの表示-->
<div class="container">
  <div id="myCarousel" class="carousel slide" data-ride="carousel">
     <ol class="carousel-indicators">
        %for i,x in enumerate(pict):
        %it="class='active'" if i==0 else ""
        <li data-target="#myCarousel" data-slide-to="{{i}} {{it}}"></li>
        %end
     </ol>
    <div class="carousel-inner">
        %for i,x in enumerate(pict):
        %it="active" if i==0 else ""
        <div class="item {{it}}">
            <img src="/static/cont/{{x}}" alt="{{x}}" style="width:100%;">
        </div>
        %end
    </div>

    <!-- Left and right controls -->
    <a class="left carousel-control" href="#myCarousel" data-slide="prev">
      <span class="glyphicon glyphicon-chevron-left"></span>
      <span class="sr-only">Previous</span>
    </a>
    <a class="right carousel-control" href="#myCarousel" data-slide="next">
      <span class="glyphicon glyphicon-chevron-right"></span>
      <span class="sr-only">Next</span>
    </a>
  </div>
</div>

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>{{ title }} - Message Application</title>
    <link rel="stylesheet" type="text/css" href="/static/content/bootstrap.min.css" />
    <link rel="stylesheet" type="text/css" href="/static/content/site.css" />
    <link rel="shortcut icon" type="image/x-icon" href="/static/favicon.ico" />
    <script src="/static/scripts/modernizr-2.6.2.js"></script>
    <script src="/static/scripts/jquery-1.10.2.js"></script>
    <script src="/static/scripts/bootstrap.js"></script>
    <script src="/static/scripts/respond.js"></script>
</head>

<body>
    <div class="container body-content">
        {{!base}}
    </div>
    </body>
</html>

image.png

4
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
5