2015年6月21日日曜日

サイネージ端末としてのraspberry pi ( dashing ) 〜サードパーティウィジットの設定〜

前回までで、raspberry piにDashingをインストールし、標準で付いているWidgetを表示するところまで出来ました。

Dashingには、サードパーティによって作られている追加ウィジットがあり、以下のサイトにソースコードが公開されています。
https://github.com/Shopify/dashing/wiki/Additional-Widgets

この中から今回は天気を表示するWeatherと、写真のスライドショーを表示するSlide Showを使ってみます。

■Weather
YahooのWeather APIを使って、指定したロケーションの天気を取得し、表示するウィジットです。スクリプトのコードがgithubに公開されており、基本的には以下のURLに記載されている手順で設定できます。

上のURLに書いてある手順そのままですが、参考までにやったことを書いておきます。

まず依存関係の準備として、~/dashboard/Gemfileファイルに、以下の一行を追加します。

gem 'xml-simple'

そして、$bundle installを実行しておきます。

次に、widgetsフォルダにweatherフォルダを作成し、以下の3つのファイルを配置します。

pi@raspberrypi ~/dashboard/widgets/weather $ ls
weather.coffee  weather.html  weather.scss

次に、jobsフォルダにweather.rbファイルを配置します。
そして、天気を表示させたいロケーションのwoe_idというものを調べます。以下のサイトでOsaka, Japanを検索すると、先頭に15015370と表示されたので、これを使うことにします。

weather.rbファイルを編集し、最初から書かれてあるwoe_idをコメントアウトし、
woe_id = 15015370を追記します。

ついでに、Fahrenheit表示ではなくCelcius表示を指定するために、format = 'c'としておきます。

pi@raspberrypi ~/dashboard_project/jobs $ more weather.rb 
require 'net/http'
require 'xmlsimple'

# Get a WOEID (Where On Earth ID)
# for your location from here:
# http://woeid.rosselliot.co.nz/
#woe_id = 3369
woe_id = 15015370

# Temerature format:
# 'c' for Celcius
# 'f' for Fahrenheit
format = 'c'

以下 略

--
ウィジットの表示の際、バックグラウンドに天気のアイコンを表示するために、Climacons Webfontというものを使っているようです。

以下のサイトからダウンロードし、 .eot, .ttf,  .woff ファイルを~/dashboard/assets/fonts フォルダに配置します。

pi@raspberrypi ~/dashboard_project/assets/fonts $ ls
climacons-webfont.eot   fontawesome-webfont.eot  fontawesome-webfont.woff
climacons-webfont.ttf   fontawesome-webfont.svg
climacons-webfont.woff  fontawesome-webfont.ttf

ここまでやってから、以下のweather.erbファイルを作るとwidgetを表示することができます。

pi@raspberrypi ~/dashboard/dashboards $ more weather.erb 
<% content_for :title do %>My weather dashboard<% end %>
<div class="gridster">
  <ul>
  <li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
      <div data-id="weather" data-view="Weather"></div>
    </li>
  </ul>
</div>


■Slide Show
ローカルにおいてある写真を一定間隔でランダムに表示する、いわゆるスライドショーを実現するウィジットです。以下のURLにコードが公開されていますが、説明のなかのリンクが切れていたりするところがあり、うまく動かすまでに結構時間がかかりました。

ソースを見るとこのスクリプトで実現していることは、主に2つあります。一つ目は、あるフォルダに格納した画像ファイルを、毎日5:00と18:00にチェックし、Widgetに適したサイズにリサイズして、SlideShow用のフォルダにコピーすること。2つ目はSlideShow用のフォルダの中からランダムに画像を選択し、20秒ごとに切り替えてスライドショー表示することです。なお、今回は、一つ目のリサイズする機能は不要だったので、すべてコメントアウトしています。

まず、SlideShowウィジットの設定ファイルとして、assetsフォルダにconfigフォルダを作成し、slide_show_setttings.jsonファイルを配置します。

pi@raspberrypi ~/dashboard_project/assets/config $ more slide_show_settings.json{"SlideShow":{"directory":"/home/pi/dashboard/assets/images/slide_show/S
lideShow","pattern":"**/*.{jpg,JPG,gif,GIF,png,PNG}","maxImageSize":[1920,1080],
"subDirectoryExceptions":["very bad party","personal employee pictures","somethi
ng very private"]}}

この設定ファイルにより、スライドショー用の写真は、
/home/pi/dashboard/assets/images/slide_show/SlideShowフォルダに格納されているjpegファイル、GIFファイル、PNGファイルである
という設定をしています。(もともとはリサイズをかける前の画像ファイルを格納するフォルダの指定だと思います。)

次にスクリプトの作者は、標準ウィジットであるImageウィジットを、少し修正しているようなのですが、そのリンクが切れています。同じ作者の以下のサイトがその切れているリンク先だと推測されますので、ここを参考にImageウィジットを置き換えます。

widgets/imageフォルダにある、image.coffee, image.html, image.scssの3つのファイルを上のURLで公開されている内容に置き換えます。ただし、公開されているソースコードそのままではうまく動かなかったので、htmlファイル等に少し修正を加えています。coffeeスクリプトとか本質的なところは全く理解していないので、修正の仕方は美しくないかもしれません。

pi@raspberrypi ~/dashboard/widgets/image $ more image.coffee
class Dashing.Image extends Dashing.Widget

  ready: ->
    # This is fired when the widget is done being rendered
    @handleSize()

  onData: (data) ->
    # Handle incoming data
    # You can access the html node of this widget with `@node`
    # Example: $(@node).fadeOut().fadeIn() will make the node flash each time data comes in.
    @handleSize()

  handleSize: ->
    if !$(@node).data('width') && !$(@node).data('height') && @get('image_width') && @get('image_height
')
      $(@node).fadeOut()
      img = $(@node).find('img')
      paRatio = img.parent().width() / img.parent().height()
      if @get('image_width') >= @get('image_height')
        ratio = @get('image_width') / @get('image_height')
        img.width(img.parent().width() * ratio/paRatio)
      else
        ratio = @get('image_height') / @get('image_width')
        img.height(img.parent().height() * ratio/paRatio)
      $(@node).fadeIn()
---
pi@raspberrypi ~/dashboard/widgets/image $ more image.html
<img data-bind-src="image | prepend '/assets'" data-bind-width="width" data-bind-height="height"/>
<div data-bind="image"> </>
---
pi@raspberrypi ~/dashboard/widgets/image $ more image.scss
// ----------------------------------------------------------------------------
// Sass declarations
// ----------------------------------------------------------------------------
$background-color:  rgba(255,255,255,0);

// ----------------------------------------------------------------------------
// Widget-image styles
// ----------------------------------------------------------------------------
.widget-image {

  background-color: $background-color;

}
---

後にスライドショーウィジットの動作の根幹であるslide_show.rbファイルをjobsフォルダに配置します。少し長くなりますが、動作したコードをそのまま記載します。途中デバッグ用に挿入したコードもコメントで残っていますし、resize_imagesの関数も結局呼んでないので削除してよいのですが、そのままです。とりあえず、動くようになったということで。

pi@raspberrypi ~/dashboard/jobs $ more slide_show.rb 
require 'net/http'
require 'rmagick'

class SlideShow
  SETTINGS_FILE = "assets/config/slide_show_settings.json"
  CURRENT_DIR = Dir.pwd
  DEBUG = 0

  def debug
    DEBUG
  end

  # function to validate json
  def valid_json? (json)
    JSON.parse(json)
    return true
  rescue JSON::ParserError
    return false
  end

  def get_settings
     str = IO.read(SETTINGS_FILE)
     return [] if not str or str.empty? or not valid_json?(str)
     JSON.parse(str)
  end

  def get_dir_file_list(directory, pattern, exceptionDirs = [])
    Dir[directory+'/'+pattern].delete_if { |x| exceptionDirs.any? { |d| x =~ /#{d}/ } }
  end

  def resize_images(files, widget, directory, maxImageSize)
    return if not files or files.length == 0
    files[0..100].each do |f|
      newFile = f.sub directory, CURRENT_DIR+"/assets/images/slide_show/#{widget}"
      next if File.exists?(newFile)
      FileUtils.mkdir_p File.dirname(newFile)
      img = Magick::Image.read(f).first
      newImg = img.change_geometry(maxImageSize[0].to_s+'x'+maxImageSize[1].to_s) { |cols, rows, i|
        newImg = i.resize(cols, rows)
        newImg.write(newFile)
      }
    end
  end

#  def get_file_list(widget, settings)
#    (get_dir_file_list(CURRENT_DIR+"/assets/images/slide_show/#{widget}", settings['pattern'], setting
s['subDirectoryExceptions']).shuffle)[0..30]
#  end
  
  
  def make_web_friendly(widget, directory, file)
    file.sub directory, "/slide_show/#{widget}"
  end
end

@SS = SlideShow.new()

#SCHEDULER.cron '* 5/18 * * *' do |job|
#  settings = @SS.get_settings
#  settings.each do |widget, project|
#    puts DateTime.now.to_s+" Resizing images for #{widget}, #{project.to_s}"
#    @SS.resize_images(
#      @SS.get_dir_file_list(project['directory'], project['pattern'], project['subDirectoryExceptions'
]).shuffle,
#      widget,
#      project['directory'],
#      project['maxImageSize'])
#  end
#end

@files = nil
SCHEDULER.every '10s', :first_in => 0 do |job|
  settings = @SS.get_settings
  settings.each do |widget, project|

#puts DateTime.now.to_s+" Reading images for #{widget}, #{project.to_s}"
    
  @files = { widget => @SS.get_dir_file_list(project['directory'], project['pattern'], project['subDire
ctoryExceptions']) } if not @files or not @files[widget] or @files[widget].length == 0

#    @files = { widget => @SS.get_file_list(widget, project) } if not @files or not @files[widget] or @
files[widget].length == 0

  file = @files[widget].shuffle!.first

  puts DateTime.now.to_s+" Working with #{widget}, #{project.to_s}, #{file}" if @SS.debug > 0

#  puts "make_web_friendly file = " + @SS.make_web_friendly(widget, Dir.pwd+"/assets/images/slide_show/
#{widget}", @files[widget][rand(@files.length)]) if @SS.debug > 0

    send_event(widget, { 
#     image: "/slide_show/#{widget}/2014-12-23_11-31-40-825x510.jpg"
     image: @SS.make_web_friendly(widget, Dir.pwd+"/assets/images/slide_show/#{widget}", @files[widget]
[rand(@files.length)])
     })
  end
end
---

ここまでやってから、以下のslideshow.erbファイルを作るとwidgetを表示することができ、写真とその画像ファイルのファイルパスがスライドショー表示されます。

pi@raspberrypi ~/dashboard/dashboards $ more slideshow.erb 
<% content_for :title do %>My slide show dashboard<% end %>
<div class="gridster">
  <ul>

<li data-row="1" data-col="1" data-sizex="4" data-sizey="2">
  <div data-id="SlideShow" data-view="Image" data-width="100%"></div>
</li>

  </ul>
</div>

■すべてのウィジットを1080pのディスプレイに表示
最後の仕上げに、これまで作成してきたウィジットをすべて並べて、1080pのディスプレイに表示するための1080p.erbという設定ファイルを作りました。デフォルトで準備されているサンプルファイルであるsampletv.erbを参考にしました。


pi@raspberrypi ~/dashboard/dashboards $ more 1080p.erb 
<script type='text/javascript'>
$(function() {
  Dashing.widget_base_dimensions = [370, 340]
  Dashing.numColumns = 5
});
</script>

<% content_for :title do %>My 1080p dashboard<% end %>
<div class="gridster">
  <ul>

    <li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
      <div data-id="my_clock" data-view="Clock"></div>
      <i class="icon-time icon-background"></i>
    </li>

   <li data-row="1" data-col="2" data-sizex="1" data-sizey="1">
      <div data-id="weather" data-view="Weather"></div>
    </li>

    <li data-row="1" data-col="3" data-sizex="2" data-sizey="1">
      <div data-id="my_event" data-view="Text" data-title="本日のイベント" data-text="今日は18:30から懇親会" data-moreinfo=" "></div>
    </li>

    <li data-row="1" data-col="5" data-sizex="1" data-sizey="1">
      <div data-id="my_number" data-view="Number" data-title="数値実績(前年比)" style="background-color:#96bf48;"></div>
      <i class="icon-heart icon-background"></i>
    </li>

    <li data-row="2" data-col="1" data-sizex="2" data-sizey="1">
      <div data-id="twitter_mentions" data-view="Comments" style="background-color:#ff9618;" data-moreinfo="Tweets by @copywritebot"></div>
      <i class="icon-twitter icon-background"></i>
    </li>

   <li data-row="3" data-col="1" data-sizex="2" data-sizey="1">
      <div data-id="twitter_mentions2" data-view="Comments" style="background-color:#ff9618;" data-moreinfo="Tweets by @kando_lyrics"></div>
      <i class="icon-twitter icon-background"></i>
    </li>

<li data-row="2" data-col="3" data-sizex="3" data-sizey="2">
     <div data-id="SlideShow" data-view="Image" data-width="100%"></div>
   </li>

  </ul>
</div>
---

インストールの際、chromiumのキオスクモードでの立ち上げ用に作ったスクリプトに、今回作成した1080pを設定し、実行するとraspberry piのHDMI出力に接続された地デジテレビにキレイにウィジットが配置されて表示されました。

pi@raspberrypi ~ $ more brstart.sh 
#!/bin/sh
export DISPLAY=:0.0

chromium --kiosk --ignore-certificate-errors --dsiable-sync --disable-restore-se
ssion-state http://localhost:3030/1080p




これで、とりあえずDashing on raspberry piは完成です。

2015年5月23日土曜日

サイネージ端末としてのraspberry pi ( dashing ) 〜標準ウィジットの設定〜

前回まででraspberry piにインストールが完了したDashingに設定を行い、自分のダッシュボード画面を作ります。

まず、最初から準備されているウィジットである、時計、メッセージ(テキスト)、数字、Twitterを表示してみます。

前回のインストール手順では、/home/pi/dashboardをdashingのルートフォルダとしました。このルートフォルダ配下のdashboardsフォルダにある.erbファイルが、ダッシュボードのレイアウトや表示要素を決める設定ファイルになっています。

この設定ファイルを準備した上で、ルートフォルダでdashing startコマンドを実行することにより、dashingのサーバプロセスが起動し、3030ポートが開きます。

pi@raspberrypi ~/dashboard $ dashing start
Thin web server (v1.6.3 codename Protein Powder)
Maximum connections set to 1024
Listening on 0.0.0.0:3030, CTRL+C to stop

ダッシュボードの設定ですが、dashboardsフォルダに最初からあるsample.erbやsampletv.erbを参考に、というか、ここからコピペしてダッシュボード画面を作っていきます。このフォルダにtest.erbがあれば、http://192.168.1.xxx:3030/testにアクセスすることでtest.erbに設定した、ダッシュボードの内容を表示をすることができます。(192.168.1.xxxはdashingがインストールされているraspberry piのIPアドレスです。)

■時計
現在の時刻を表示する時計です。
デフォルトで準備されているので、以下の設定をすると表示することができます。

pi@raspberrypi ~/dashboard/dashboards $ more clock.erb 
<% content_for :title do %>My clock dashboard<% end %>
<div class="gridster">
  <ul>
    <li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
      <div data-id="my_widget" data-view="Clock"></div>
      <i class="icon-time icon-background"></i>
    </li>
  </ul>
</div>



■メッセージ(テキスト)
ダッシュボードにテキストでメッセージを書くことができます。
デフォルトで準備されているので、以下の設定をすると表示することができます。

pi@raspberrypi ~/dashboard/dashboards $ more text.erb 
<% content_for :title do %>My text dashboard<% end %>
<div class="gridster">
  <ul>
    <li data-row="1" data-col="1" data-sizex="2" data-sizey="1">
      <div data-id="my_event" data-view="Text" data-title="本日のイベント" data-text="今日は新年会があります。" data-moreinfo=" "></div>
    </li>
  </ul>

</div>


ダッシュボードのテキストの内容は、以下のコマンドでraspberry piにhttpのpostを送ることにより変更することができます。(httpなのでリモートのクライアントからテキストを変更できます)

$curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "text":"表示したいテキストをここに記載します"}' http://192.168.1.xxx:3030/widgets/my_event

■数字
数字を表示できます。現時点の数値(current)を表示するのに加え、前回の数値(last)からの変化率を自動で計算し%表記してくれます。

これもデフォルトで準備されているので、.erbファイルに記述するだけで表示できます。

pi@raspberrypi ~/dashboard/dashboards $ more number.erb 
<% content_for :title do %>My number dashboard<% end %>
<div class="gridster">
  <ul>
    <li data-row="1" data-col="1" data-sizex="1" data-sizey="1">
      <div data-id="my_number" data-view="Number" data-title="数値タイトル" style="background-color:#96bf48;"></div>
      <i class="icon-heart icon-background"></i>
    </li>
  </ul>
</div>

こちらもテキストと同様に、httpで数値をセットすることができます。

$curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "current":1000}' http://192.168.1.xxx:3030/widgets/my_number

$curl -d '{ "auth_token": "YOUR_AUTH_TOKEN", "last":800}' http://192.168.1.xxx:3030/widgets/my_number

とすると、以下のような表示になります。




■Twitter
TwitterのAPIを使ってTweetを取得し、ダッシュボードに表示することができます。これも最初から用意されていますが、Twitter APIにアクセスするためのキーをTwitterのデベロッパーサイトで取得し、dashingのtwitterジョブファイルに登録する必要があります。

ルートフォルダ配下のjobsフォルダにあるtwitter.rbファイルが、twitterを表示するためのジョブファイルになっていますので、具体的にはtwitter.rbファイルの中にある、以下の4つの文字列を、TwitterAPIサイトで取得した文字列に書き換えます。

config.consumer_key = 'YOUR_CONSUMER_KEY'
config.consumer_secret = 'YOUR_CONSUMER_SECRET'
config.access_token = 'YOUR_OAUTH_TOKEN'
config.access_token_secret = 'YOUR_OAUTH_SECRET'

twitter.rbは、デフォルトではハッシュタグ#todayilearnedを持つtweetsを検索し、表示させるスクリプトになっています。スクリプトでは、

search_term = URI::encode('#todayilearned')
tweets = twitter.search("#{search_term}")
が、ハッシュタグを指定し、そのtweetを引っ張ってくるプログラム部分です。

なのでこの'#todayilearned'を任意の文字列に変えれば、別のハッシュタグを検索した結果を表示することができます。

今回は、ハッシュタグではなく、任意のアカウントのtweetsを表示させたかったので、該当のスクリプト部分を

tweets = twitter.user_timeline("copywritebot", { count: 200 } )

というように変更しました。copywritebotに任意のTwitterアカウント名を入れれば、そのユーザのTweetを表示することができます。Twitter APIの詳しいことは調べていませんので、適当に変更してみたら出来ましたというレベルに終わっています。

Tweetを取得する準備はできたので、表示するためのerbファイルを作ります。

pi@raspberrypi ~/dashboard/dashboards $ more twitter.erb 
<% content_for :title do %>My twitter dashboard<% end %>
<div class="gridster">
  <ul>
    <li data-row="1" data-col="1" data-sizex="2" data-sizey="1">
      <div data-id="twitter_mentions" data-view="Comments" style="background-color:#ff9618;" data-moreinfo="Tweets by @copywritebot"></div>
      <i class="icon-twitter icon-background"></i>
    </li>
  </ul>
</div>

で、以下のような表示になります。


今回は、最初から用意されているいくつかのwidgetをダッシュボードに表示してみましたが、Dashingには、サードパーティによって作られている追加ウィジットがあり以下のサイトに公開されています。

次回は、このサードパーティウィジットを使って、天気と、写真のスライドショーをダッシュボードに表示させてみたいと思います。

2015年5月16日土曜日

サイネージ端末としてのraspberry pi ( dashing ) 〜インストール〜

raspberry pi 2にDashingというソフトウエアをインストールしてみました。
Dashingは、Shopifyという会社が公開しているオープンソースのソフトウエアで、rubyのgemという形式で配布されています。"The exceptionally handsome dashboard framework."ということで、様々な情報を一画面で表示するダッシュボードを作ることができるソフトウエアです。公式サイトによると、

・Dashingは、Sinatraベースで美しいダッシュボードを作ることができるフレームワーク
・すでに用意されたウィジットを使うこともできるし、自分でscss, html, coffeescriptを使ってウィジットを作ることができる
・APIを使ってダッシュボードにデータをプッシュ、もしくはruby DSLを使ってデータをフェッチできる
・Drag&Dropでウィジットを再配置できる
・Herokuに30秒でデプロイできる

というところが特徴だそうです。

1080pでの表示に対応しており、raspberry piにもインストールできるようなので、大画面テレビをサイネージ端末とするのに使えそうです。

一応公式サイトにもインストール手順が記載されていますが、以下の記事にraspberry piでdashingを使う際の手順が記載されていましたので、これを参考にセットアップを実行しました。

https://dyscribe.com/tutorial/dashing-dashboard-on-raspberry-pi/


■必要なパッケージのインストール
pi@raspberrypi ~ $ sudo apt-get install libssl-dev 
pi@raspberrypi ~ $ sudo apt-get install ruby-dev
pi@raspberrypi ~ $ sudo apt-get install nodejs
pi@raspberrypi ~ $ sudo apt-get install bundler
pi@raspberrypi ~ $ sudo apt-get install rubygems

■dashingをインストール
pi@raspberrypi ~ $ sudo gem install dashing
Fetching: sass-3.2.19.gem (100%)
Fetching: coffee-script-source-1.9.1.1.gem (100%)
Fetching: execjs-2.0.2.gem (100%)
Fetching: coffee-script-2.2.0.gem (100%)
Fetching: rack-1.5.2.gem (100%)
Fetching: tilt-1.4.1.gem (100%)
Fetching: rack-protection-1.5.3.gem (100%)
Fetching: sinatra-1.4.6.gem (100%)
Fetching: backports-3.6.4.gem (100%)
Fetching: rack-test-0.6.3.gem (100%)
Fetching: multi_json-1.11.0.gem (100%)
Fetching: sinatra-contrib-1.4.2.gem (100%)
Fetching: eventmachine-1.0.7.gem (100%)
Building native extensions.  This could take a while...
Fetching: daemons-1.2.2.gem (100%)
Fetching: thin-1.6.3.gem (100%)
Building native extensions.  This could take a while...
Fetching: thread_safe-0.3.5.gem (100%)
Fetching: tzinfo-1.2.2.gem (100%)
Fetching: rufus-scheduler-2.0.24.gem (100%)
Fetching: thor-0.18.1.gem (100%)
Fetching: hike-1.2.3.gem (100%)
Fetching: sprockets-2.10.2.gem (100%)
Fetching: dashing-1.3.4.gem (100%)
Successfully installed sass-3.2.19
Successfully installed coffee-script-source-1.9.1.1
Successfully installed execjs-2.0.2
Successfully installed coffee-script-2.2.0
Successfully installed rack-1.5.2
Successfully installed tilt-1.4.1
Successfully installed rack-protection-1.5.3
Successfully installed sinatra-1.4.6
Successfully installed backports-3.6.4
Successfully installed rack-test-0.6.3
Successfully installed multi_json-1.11.0
Successfully installed sinatra-contrib-1.4.2
Successfully installed eventmachine-1.0.7
Successfully installed daemons-1.2.2
Successfully installed thin-1.6.3
Successfully installed thread_safe-0.3.5
Successfully installed tzinfo-1.2.2
Successfully installed rufus-scheduler-2.0.24
Successfully installed thor-0.18.1
Successfully installed hike-1.2.3
Successfully installed sprockets-2.10.2
Successfully installed dashing-1.3.4
22 gems installed
Installing ri documentation for sass-3.2.19...
Installing ri documentation for coffee-script-source-1.9.1.1...
Installing ri documentation for execjs-2.0.2...
Installing ri documentation for coffee-script-2.2.0...
Installing ri documentation for rack-1.5.2...
Installing ri documentation for tilt-1.4.1...
Installing ri documentation for rack-protection-1.5.3...
Installing ri documentation for sinatra-1.4.6...
Installing ri documentation for backports-3.6.4...
Installing ri documentation for rack-test-0.6.3...
Installing ri documentation for multi_json-1.11.0...
Installing ri documentation for sinatra-contrib-1.4.2...
Installing ri documentation for eventmachine-1.0.7...
Installing ri documentation for daemons-1.2.2...
Installing ri documentation for thin-1.6.3...
Installing ri documentation for thread_safe-0.3.5...
Installing ri documentation for tzinfo-1.2.2...
Installing ri documentation for rufus-scheduler-2.0.24...
Installing ri documentation for thor-0.18.1...
Installing ri documentation for hike-1.2.3...
Installing ri documentation for sprockets-2.10.2...
Installing ri documentation for dashing-1.3.4...
Installing RDoc documentation for sass-3.2.19...
Installing RDoc documentation for coffee-script-source-1.9.1.1...
Installing RDoc documentation for execjs-2.0.2...
Installing RDoc documentation for coffee-script-2.2.0...
Installing RDoc documentation for rack-1.5.2...
Installing RDoc documentation for tilt-1.4.1...
Installing RDoc documentation for rack-protection-1.5.3...
Installing RDoc documentation for sinatra-1.4.6...
Installing RDoc documentation for backports-3.6.4...
Installing RDoc documentation for rack-test-0.6.3...
Installing RDoc documentation for multi_json-1.11.0...
Installing RDoc documentation for sinatra-contrib-1.4.2...
Installing RDoc documentation for eventmachine-1.0.7...
Installing RDoc documentation for daemons-1.2.2...
Installing RDoc documentation for thin-1.6.3...
Installing RDoc documentation for thread_safe-0.3.5...
Installing RDoc documentation for tzinfo-1.2.2...
Installing RDoc documentation for rufus-scheduler-2.0.24...
Installing RDoc documentation for thor-0.18.1...
Installing RDoc documentation for hike-1.2.3...
Installing RDoc documentation for sprockets-2.10.2...
Installing RDoc documentation for dashing-1.3.4...

ここまででインストールは完了です。

■dashingの基本設定ファイルの生成
pi@raspberrypi ~ $ dashing new dashboard
pi@raspberrypi ~ $ cd dashboard
pi@raspberrypi ~/dashboard $ bundle 
Fetching gem metadata from https://rubygems.org/...........
Fetching gem metadata from https://rubygems.org/..
Installing addressable (2.3.8) 
Using backports (3.6.4) 
Installing buftok (0.2.0) 
Using coffee-script-source (1.9.1.1) 
Using execjs (2.0.2) 
Using coffee-script (2.2.0) 
Using daemons (1.2.2) 
Using rack (1.5.2) 
Using thread_safe (0.3.5) 
Using tzinfo (1.2.2) 
Using rufus-scheduler (2.0.24) 
Using sass (3.2.19) 
Using rack-protection (1.5.3) 
Using tilt (1.4.1) 
Using sinatra (1.4.6) 
Using multi_json (1.11.0) 
Using rack-test (0.6.3) 
Using sinatra-contrib (1.4.2) 
Using hike (1.2.3) 
Using sprockets (2.10.2) 
Using eventmachine (1.0.7) 
Using thin (1.6.3) 
Using thor (0.18.1) 
Using dashing (1.3.4) 
Installing equalizer (0.0.11) 
Installing multipart-post (2.0.0) 
Installing faraday (0.9.1) 
Installing http_parser.rb (0.6.0) with native extensions 
Installing http (0.6.4) 
Installing json (1.8.2) with native extensions 
Installing memoizable (0.4.2) 
Installing naught (1.0.0) 
Installing simple_oauth (0.3.1) 
Installing twitter (5.14.0) 
Using bundler (1.1.4) 
Your bundle is complete! Use `bundle show [gemname]` to see where a bundled gem is installed.

これでDashing自体を動かすための準備は完了ですが、raspberry piに接続した大画面テレビにダッシュボード表示をさせるために必要となるソフトウエアを入れていきます。

■Unclutter、Chromiumのインストール

Dashingのダッシュボード画面は、thinというWebサーバにホスティングされるWebサイトなので、ダッシュボード端末からは、Webブラウザでアクセスすることになるのですが、ChromiumブラウザはKIOSKモードという全画面でWebを表示することができるので、今回の用途に適しています。また、全画面でダッシュボードを表示している時に、マウスポインタが出ていると不格好なので、unclutterというツールを入れて、マウスポインタを隠します。

pi@raspberrypi ~ $ sudo apt-get install unclutter
pi@raspberrypi ~ $ sudo apt-get install chromium-browser

■HDMIのディスプレイをスリープさせない設定

raspberry piのデフォルトでは、15分ほどでHDMIに接続したディスプレイがスリープして真っ黒になってしまうので、これをスリープさせない設定にしたいところです。

やり方を探してみると、/etc/xdg/lxsession/LXDE/autostartを編集するとできるという情報がありましたが、なにをどう設定しても変化なし。

~/.xinitrcで同様の設定ができるという情報もあり、試してみましたが、.xinitrcを作成すると、今まで問題なく立ち上がっていた、X windowsが、startxコマンドで立ち上がらなくなりました。

そこで、/etc/xdg/lxsession/フォルダを改めて見てみると、LXDEフォルダと並列にLXDE-piフォルダというものも有り、その中にもautostartというファイルがありました。

試しに、/etc/xdg/lxsession/LXDE-pi/autostartを編集してみると、スリープ解除の設定が有効になりました。詳細の内容は特定していませんが、raspberry pi 2では、読み込む設定がこちらのファイルに変わったということなのでしょうか?

まとめますと、以下のような設定にすることにより、HDMIがスリープしないようになりました。

pi@raspberrypi /etc/xdg/lxsession/LXDE-pi $ more autostart 
@lxpanel --profile LXDE-pi
@pcmanfm --desktop --profile LXDE-pi
@xscreensaver -no-splash

@xset s off
@xset -dpms

@xset s noblank

※参考にした情報
http://akiomik.hatenablog.jp/entry/2013/09/12/211523
http://azmwork.tumblr.com/post/90563391369/raspbian-hdmi
http://www.fusonic.net/en/blog/2013/07/31/diy-info-screen-using-raspberry-pi-dashing/

■X window起動、Dashing起動、Chromium起動

さて、準備が整ったので、dashingを起動し、raspberry pに接続したテレビでダッシュボード画面を表示してみます。

1. raspberry piを起動し、startxコマンドでX windowを起動させる。

2. pi@raspberrypi ~/dashboard_project $ dashing start
でDashingを起動させる。

3. 以下のようなシェルスクリプトでChromiumをkioskモードで起動させる。

pi@raspberrypi ~ $ more brstart.sh 
#!/bin/sh
export DISPLAY=:0.0

chromium --kiosk --ignore-certificate-errors --dsiable-sync --disable-restore-se
ssion-state http://localhost:3030/sampletv

以上で、raspberry piのHDMIディスプレイに、フルスクリーンでDashingのサンプルダッシュボード画面をを表示させることができるようになりました。

次回は、ダッシュボードに表示するウィジットの設定を行い、自分のダッシュボード画面を作ってみたいと思います。表示する情報は、時計、天気、メッセージ、数字、Twitter、写真の予定です。

2015年5月9日土曜日

サイネージ端末としてのraspberry pi ( screenly )

初期セットアップの完了したraspberry pi2ですが、HDMIで大画面テレビにつなげられることから、サイネージ端末にしてみることにしました。

必要なシステムを一式インストールしたマイクロSDを一度作ってしまえば、それをそのまま別のマイクロSDにコピーして、新しいraspberry piに入れれば、すぐに同じ端末を量産していくことができます。価格が安いこともありraspberry piのサイネージ端末としての利用はニーズがあるのではないかと思います。

そんなアイデアを、すでにプロダクト化している人たちがいました。Screenlyというソフトウエアです。
https://www.screenlyapp.com/


"Full HD video and images on your TV screens powered by a single Raspberry Pi mini computer and the revolutionary Screenly software stack."
ということで、まんまですね。

できることは、画像、動画、Webサイトを全画面でスライドショーしていくだけですが、WebベースのCMSが付いていて、コンテンツの登録、表示の管理が簡単にできるようになっています。Webが表示できるのでGoogleカレンダーを表示しておくといったような使い方もできます。

そして、複数端末の管理機能を省いたものが、オープンソースで公開されています。OSのカスタムイメージが以下のサイトで配布されており、記載されている手順でマイクロSDに展開するだけで、すぐに使えるようになります。
https://www.screenlyapp.com/ose.html

説明には一応Wifiには非対応と書かれていましたが、カスタムイメージは、ほぼraspbianな感じなので、前の記事に書いたように設定すればWifiドングルが有効になり、無線LAN環境でも問題なく動きました。

オープンソース版は、ビデオコーデックがH264 MPEG4 videosのみの対応ですが、ちゃんと1080pで表示できますし、動画のダダ流し端末としても、十分実用に耐えると思います。

サイネージ端末というよりダッシュボード端末として、一画面にもう少しいろんな情報を表示したい場合は、Dashingというソフトウエアもあります。そちらも、raspberry piにインストールして動かしてみましたので、次回の記事にインストール方法などを記載してみたいと思います。

2015年5月6日水曜日

raspberry pi 2 の初期インストールと無線アダプタWLI-UC-GNの設定

raspberry pi 2を購入してみました。昔使っていたぷらっとホーム社のOpenBlocksのようなサイズのマシンです。日本で買うともう少しかかりますが、定価$35ということで、なにもできなかったとしても、まあ気兼ねなく買える価格です。発売から三年で500万台出荷とのこと。



OSをインストールするためのマイクロSDカードは別で購入しないといけません。私は以下のものを購入しました。マイクロSDの取り替えで、システム環境一式がすぐに置き換えられるのがraspberry piの面白いところでもあります。



ここまでちゃんと手順を守らなくてもいいかもしれませんが、推奨されている。SDフォーマッター"https://www.sdcard.org/jp/downloads/formatter_4/"でマイクロSDカードをフォーマット。形式はFAT32で問題無しでした。以下、インストールの手順を簡単にメモ。

---
■インストールイメージの入手
raspberry piのサイト"https://www.raspberrypi.org/downloads/"からNOOBS 1.4.0をダウンロードし、zipを解凍したファイルをすべてマイクロSDカードへそのままコピー。

■OSインストール
起動するとインストール画面ができるので、一番上にあるRaspbian[RECOMMENDED]にチェックを入れてInstallを実行。マイクロSD内のファイルを上書きするよというワーニングがでるが、YESを選択してインストールを開始。待つ。OS installed successfullyが出るのでOKボタンを押すとraspberry piが起動。

■raspi-config
基本設定となるraspi-confiの画面が上がるので、以下の日本語に関わる設定を三点実施。

4 Internationalization Options

I1 Change Localeで ja_JP.UTF-8にチェック。次の画面でも ja_JP.UTF-8を選ぶ。

I2 Change Timezone で Asia Tokyoを選ぶ。

I3  Change Keyboard Layoutで、Generic 101-key PCを選び Other - Japanese - Japanese - The default for the keyboard layout - No compose key -YES を選択。

さらに、以下の画面サイズに関する設定を実施

8 Advanced Optionsで、A1 Overscanを選び、Disableを選択。

■無線LAN子機WLI-UC-GNのドライバ認識
昔、Let's Noteで使用していたバッファロー製のUSBドングル型無線LAN子機WLI-UC-GNが余っていたのでこれを使いました。

しかし、USBコネクタにさしただけではでは認識せず。。。
以下のサイトを参考に設定を追加したところ、認識させることができました。利用者の多いraspberry piならではの情報の豊富さです。
"http://ameblo.jp/red-ozemi/entry-11472528104.html"
"http://toronya.tumblr.com/post/38860903165/raspberry-pi-usb-lan-wli-uc-gn"
"https://forums.ubuntulinux.jp/viewtopic.php?id=10791"

pi@raspberrypi /etc/wpa_supplicant $ lsusb
Bus 001 Device 002: ID 0424:9514 Standard Microsystems Corp. 
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp. 
Bus 001 Device 004: ID 0411:014f BUFFALO INC. (formerly MelCo., Inc.) 
Bus 001 Device 005: ID 413c:3016 Dell Computer Corp. Optical 5-Button Wheel Mouse
Bus 001 Device 006: ID 413c:2105 Dell Computer Corp. Model L100 Keyboard

さしただけでも、lsusbコマンドの出力にDevice 004としてリストアップされるので、USB機器として認識はされている模様。

以下の2つのファイルを新規作成することにより、ドライバを読み込む設定を追加。

pi@raspberrypi /etc/udev/rules.d $ more 99-wireless.rules 
#BUFFALO WLI-UC-GN
ACTION=="add",SUBSYSTEM=="usb",ATTR{idVendor}=="0411",ATTR{idProduct}=="014f",RUN+="/sbin/modprobe -qba rt2800usb"

pi@raspberrypi /etc/modprobe.d $ more wireless.conf 
#BUFFALO WLI-UC-GN
install rt2800usb /sbin/modprobe --ignore-install rt2800usb $CMDLINE_OPTS;/bin/echo "0411 014f" > /sys/bus/usb/drivers/rt2800usb/new_id

echo で書き込む"0411 014f"の真ん中のスペースを忘れていて少しハマりました。

2つのファイルを作成して、リブートしたところ、iwconfigコマンドでwlan0のインタフェースが表示されるようになりました。

■無線LAN接続設定
Wifi接続する、SSIDとパスフレーズの登録を、wpa_passphraseコマンでwpa_supplicant.conファイルに書き出します。

$sudo sh -c "wpa_passphrase SSID パスフレーズ >> /etc/wpa_supplicant/wpa_supplicant.conf"

実行すると、以下のようにファイルに設定が追加されます。

pi@raspberrypi /etc/wpa_supplicant $ sudo more wpa_supplicant.conf 
ctrl_interface=DIR=/var/run/wpa_supplicant GROUP=netdev
update_config=1
network={
ssid="*************"
#psk="************"
psk=****************************************************************************
}

そして、システムを再度、リブート。

pi@raspberrypi /sys/bus/usb/drivers/rt2800usb $ iwconfig
wlan0     IEEE 802.11bgn  ESSID:"******"  
          Mode:Managed  Frequency:2.462 GHz  Access Point: *******   
          Bit Rate=108 Mb/s   Tx-Power=20 dBm   
          Retry short limit:7   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=51/70  Signal level=-59 dBm  
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:32  Invalid misc:67   Missed beacon:0

lo        no wireless extensions.

eth0      no wireless extensions.

これで、インターネット接続されました。

■ソフトウエアの更新
リポジトリにアクセスして、パッケージ管理データベースを最新化しておきます。

pi@raspberrypi ~ $ sudo apt-get update

さらに、インストールされているソフトウエアを最新化

pi@raspberrypi ~ $ sudo apt-get upgrade -y

■日本語入力のインストール
日本語入力のためのソフトウエアをインストールしておきます。

pi@raspberrypi ~ $ sudo apt-get install ibus-anthy

インストール後、X windowを立ち上げた画面の右上にあるキーボードアイコンを右クリックし、設定の「インプットメソッド」タブにて、日本語-Anthyを追加。

これで日本語入力できるようになりました。

無線LANの子機の設定で少しハマりましたが、初期設定はこんなところで完了です。

ClosedなiPhoneはおいておいたとして、まったく同じハードウエア構成のマシンをここまで多くのひとが所有することは、これまでなかったでしょうから、オープンソースの活動が加速するでしょうし、そこにはイノベーションの可能性を感じます。

これからそれなりに使ってみたいと思います。

SUUNTO SPARTANを買いました。

(昨年の11/2からBlogの下書きにほったらかしにされてありました。発売から日が過ぎでてしまいましたが、掲載しておきます。)

SUUNTO SPARTANという時計を買いました。フィンランドのコンパスメーカSUUNTOが作ったミリタリーウォッチです。


SUUNTOの時計を買うのは二回目で、大学時代にSUUNTO VECTORのイエローを買ったのが一つ目です。今、売っているVECTORイエローは黄色の色が濃いのと、文字盤がブラック反転していますが、当時のVECTORは軽いイエローで通常の液晶なのでよりポップな感でした。

そして、今回のSPARTANは液晶が黄色。ミリタリー用途ということで、雰囲気もシックでかっちょいい感じです。
シンプルなロゴもGOOD。
箱をあけるとこんな感じ。
思ったよりツルッとした感じです。
紙類一式。

つけてみたところ。

最初、ベルトが固くて、ベルト留めに入れたり外したりするのが、かなり困難でしたが、使っているうちに柔らかくなったのか、苦労せずに脱着できるようになりました。機能がどうこうではなく、見た感じがgoodな時計です。