0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【Bラボデジタルサイネージ16】開店/閉店を表示する「OpenCloseRModule」

Last updated at Posted at 2021-11-12

本記事は、株式会社 函館ラボラトリが運営する「Bラボ」における、大人向け「看板アプリ(デジタルサイネージ)を作るコース」用教材テキストです。

  1. 【Bラボデジタルサイネージ1】Processing+ラズパイでデジタルサイネージを作る!
  2. 【Bラボデジタルサイネージ2】ラズパイ初期設定
  3. 【Bラボデジタルサイネージ3】準備プログラム作成&機能実現の方針決定
  4. 【Bラボデジタルサイネージ4】レイアウトの基準になるグリッドを表示する「GridModule」
  5. 【Bラボデジタルサイネージ5】レイアウトの基準になる枠を表示する「PlaceholderModule」
  6. 【Bラボデジタルサイネージ6】画像を全画面表示する「FullImageModule」
  7. 【Bラボデジタルサイネージ7】ページの自動切り替え
  8. 【Bラボデジタルサイネージ8】設置されている場所の名前を表示する「LocationModule」
  9. 【Bラボデジタルサイネージ9】現在の時間を表示する「DateModule」
  10. 【Bラボデジタルサイネージ10】ページ切り替えの時間が分かる「ProgressBarModule」
  11. 【Bラボデジタルサイネージ11】現在の表示中のページが分かる「PageControlModule」
  12. 【Bラボデジタルサイネージ12】現在の天気を表示する「WeatherRModule」
  13. 【Bラボデジタルサイネージ13】直近2件のバス時刻表を表示する「BusRModule」
  14. 【Bラボデジタルサイネージ14】ごみ出しカレンダーを表示する「GomiRModule」
  15. 【Bラボデジタルサイネージ15】(発展編)ツイートを表示する「TwitterRModule」
  16. 【Bラボデジタルサイネージ16】開店/閉店を表示する「OpenCloseRModule」(本記事)
  17. 【Bラボデジタルサイネージ17】部屋の温度を表示する「TemperatureRModule」
  18. 【Bラボデジタルサイネージ18】部屋の明るさを表示する「BrightnessRModule」
  19. 【Bラボデジタルサイネージ19】起動画面を表示する「LaunchingScreenModule」
  20. 【Bラボデジタルサイネージ20】RModuleの影を実装

作るもの

スライドスイッチを使い、開店/閉店の表示を切り替えられるようにします。

0189.png

0010.png

画像の準備

OpenCloseRModuleの背景画像には、下の画像を使用します。

background_close.jpg

画像を2回保存し、それぞれ「background_open.jpg」と「background_close.jpg」という名前をつけます。
(.png形式など別の形式の場合は、.jpg形式に変換してください。)

Processingの画面上のタブで、「スケッチ > スケッチフォルダーを開く」を選ぶと、開いている.pdeファイルが一覧で表示されます。
「data」フォルダの中に、新たに「openclose」フォルダを作ってください。
先ほど名前をつけて保存した「background_open.jpg」と「background_close.jpg」を「data/openclose」フォルダの直下においてください。(ドラッグ&ドロップ)

ここで新しく作った「data/openclose」フォルダの位置を示すパスを、定数として定義します。

DigitalSignage.pde
/* 略 */

final String AD_PATH = "ad/";
final String WEATHER_PATH = "weather/";
final String BUS_PATH = "bus/";
final String GOMI_PATH = "gomi/";
final String TWITTER_PATH = "twitter/";
final String OPENCLOSE_PATH = "openclose/"
final String DUMMY_PATH = "dummy/";

/* 略 */

OpenCloseRModuleの背景を保持する変数を定義します。

DigitalSignage.pde
/* 略 */

/* ここから追加 */
// OpenCloseModule
PGraphics openCloseBackgroundOpen;
PGraphics openCloseBackgroundClose;
/* ここまで追加 */

/* 略 */

RModuleのリストに、OpenCloseRModuleを表す「OpenClose」を追加します。

DigitalSignage.pde
/* 略 */

enum RModule {
  Weather,
  Bus,
  Gomi,
  Twitter,
  OpenClose /* 追加 */
}

/* 略 */

background_open.jpgbackground_close.jpgを用いて、モジュールの背景画像を生成します。
initializeRModuleBackground()内で実装します。

Initialize.pde
/* 略 */

void initializeRModuleBackground() {
  /* 中略 */
  gomiBackground.rect(0, 0, w, h);
  gomiBackground.endDraw();
  gomiBackground.mask( sizeToModuleMask( moduleSize(module) ) );

  /* ここから追加 */
  module = RModule.OpenClose;
  w = moduleWidth( moduleSize(module) );
  h = moduleHeight( moduleSize(module) );
  back = loadImage(OPENCLOSE_PATH + "background_open.jpg");
  openCloseBackgroundOpen = createGraphics(w, h);
  openCloseBackgroundOpen.beginDraw();
  openCloseBackgroundOpen.colorMode(HSB, 360, 100, 100, 100);
  openCloseBackgroundOpen.image( pImageCut(back, CENTER, CENTER, w, h) , 0, 0);
  openCloseBackgroundOpen.fill(0, 0, 0, 40);
  openCloseBackgroundOpen.noStroke();
  openCloseBackgroundOpen.rect(0, 0, w, h);
  openCloseBackgroundOpen.endDraw();
  openCloseBackgroundOpen.mask( sizeToModuleMask( moduleSize(module) ) );
  
  back = loadImage(OPENCLOSE_PATH + "background_close.jpg");
  openCloseBackgroundClose = createGraphics(w, h);
  openCloseBackgroundClose.beginDraw();
  openCloseBackgroundClose.colorMode(HSB, 360, 100, 100, 100);
  openCloseBackgroundClose.image( pImageCut(back, CENTER, CENTER, w, h) , 0, 0);
  openCloseBackgroundClose.fill(0, 0, 0, 40);
  openCloseBackgroundClose.noStroke();
  openCloseBackgroundClose.rect(0, 0, w, h);
  openCloseBackgroundClose.endDraw();
  openCloseBackgroundClose.mask( sizeToModuleMask( moduleSize(module) ) );
  /* ここまで追加 */

/* 略 */

OpenCloseRModule用関数と変数の準備

新しいファイルRM_OpenClose.pdeを作ります。
OpenCloseRModuleの描画用関数drawOpenCloseRModule()、ごみカレンダー更新用の関数updateOpenClose()を作ります。

RM_OpenClose.pde
void drawOpenCloseRModule(Area area) {
  
}

boolean updateOpenClose() {
  return false;
}

開店/閉店の状態を表す変数、値が更新されたことを示す変数を定義します。

DigitalSignage.pde
/* 略 */

// OpenCloseModule
boolean isUpdatedOpenClose = false; /* 追加 */
boolean isOpen = false; /* 追加 */
PGraphics openCloseBackgroundOpen;
PGraphics openCloseBackgroundClose;

/* 略 */

電子部品の配置

電子部品を組み替えるときは、ラズパイの電源を切り、電源ケーブルをコンセントから抜いてください。

以降、ラズパイと電子部品を接続するときのピンの番号は、下記サイトのGPIOピンの配置カードを参考にしてください。

まずブレッドボードへ電気を送るための配線を作ります。
ブレッドボードの「+」と「-」にそれぞれ、ジャンパワイヤをさします。
「+」は2番ピン(5V)、「-」は6番ピン(GND)に繋いでください。

IMG_2204.JPG

スライドスイッチ、3本のジャンパワイヤ、1kΩ抵抗を下図のように配置します。
1kΩ抵抗に繋いだジャンパワイヤは、ラズパイの16番ピン(GPIO23)に繋いでください。

IMG_2205.jpg

これで電子部品の配置が完了しました。

スライドスイッチの値取得

ラズパイのGPIOピン経由で値をやり取りするため、ライブラリprocessing.io.*をインポートしておきます。

DigitalSignage.pde
import processing.io.*;

/* 略 */

今回、スライドスイッチと値をやりとりするピンは「GPIO23」のため、番号を定数として定義しておきます。

DigitalSignage.pde
/* 略 */

// OpenCloseModule
boolean isUpdatedOpenClose = false;
boolean isOpen = false;
PGraphics openCloseBackgroundOpen;
PGraphics openCloseBackgroundClose;
final int SWITCH_PIN = 23; /* 追加 */

/* 略 */

関数setup()内で、GPIOピンから入力を受け取るための設定をします。

DigitalSignage.pde
/* 略 */

void setup() {
  frameRate(1);
  noCursor();
  colorMode(HSB, 360, 100, 100, 100);
  WHITE_COLOR = color(0, 0, 100);
  NEARLY_WHITE_COLOR = color(100, 2, 98);
  NEARLY_GREEN_COLOR = color(100, 5, 98);
  BLACK_COLOR = color(0, 0, 0);
  LIGHT_COLOR = color(0, 0, 80);
  GRAY_COLOR = color(0, 0, 50);
  GREEN_COLOR = color(150, 100, 60);
  
  textFont(createFont("NotoSansCJKjp-Bold", 32));
  
  background = pImageCut(loadImage("background.jpg"), CENTER, CENTER, width, height);
  
  GPIO.pinMode(SWITCH_PIN, GPIO.INPUT); /* 追加 */
  
  initialize();
}

/* 略 */

関数updateOpenClose()内で、GPIOピンに送られてきた値を取得する処理を記述します。
スライドスイッチがONのときGPIO.LOW、OFFのときGPIO.HIGHという値が取得できます。

RM_OpenClose.pde
boolean updateOpenClose() {
  try {
    if (GPIO.digitalRead(SWITCH_PIN) == GPIO.LOW) {
      isOpen = true;
    } else {
      isOpen = false;
    }
  } catch (Exception e) {
    return false;
  }
  
  return true;
}

関数updateOpenClose()が実装できたので、この関数を呼び出すようにします。
スライドスイッチから値を取得するタイミングは、以下の2つとします。

  • デジタルサイネージを起動したとき
  • 毎秒
Initialize.pde
void initialize() {
  initializeDate();
  initializeImage();
  initializeGrid();
  initializePlaceholder();
  initializeRModuleBackground();
  
  isUpdatedWeather = updateWeather();
  isUpdatedBus = updateBus();
  isUpdatedGomi = updateGomi();
  isUpdatedTwitter = updateTwitter();
  
  isUpdatedOpenClose = updateOpenClose(); /* 追加 */
}

/* 略 */
DigitalSignage.pde
/* 略 */

void updateDatas() {
  updateDate();
  isUpdatedOpenClose = updateOpenClose(); /* 追加 */

  /* 略 */

OpenCloseRModuleの描画

データが変数に代入できている状態になったので、画面上に表示するところまで実装します。

置換可能なReplaceableModuleを実装するとき、最低限定めなければいけないことは以下です。

  • 描画時の基準となるエリア(Area.area1〜Area.area8のいずれか)
  • 描画時のサイズ(Size.S〜Size.Lのいずれか)

まずはOpenCloseRModuleの描画時の基準となるエリアについて説明します。
OpenCloseRModuleの描画の基準になるのは、8つある表示エリアのうちArea.area5です。

0038e.png

0189.png

関数moduleSize()をOpenCloseRModuleに対応させます。
TwitterRModuleのサイズはSize.Mです。

DigitalSignage.pde
Size moduleSize(RModule module) {
  if (module == RModule.Weather) return Size.M;
  if (module == RModule.Bus) return Size.L;
  if (module == RModule.Gomi) return Size.M;
  if (module == RModule.Twitter) return Size.L;
  if (module == RModule.OpenClose) return Size.M;
  return Size.S;
}

次に関数drawOpenCloseRModule()を実装します。
Area.area5の左上の座標、OpenCloseRModuleの幅と高さを取得します。

RM_OpenClose.pde
void drawOpenCloseRModule(Area area) {
  RModule module = RModule.OpenClose;
  Size size = moduleSize(module);
  
  int x = layoutGuideX(area);
  int y = layoutGuideY(area);
  int w = moduleWidth(size);
  int h = moduleHeight(size);
}

/* 略 */

スイッチからデータを取得できなかったときの表示を実装します。

RM_OpenClose.pde
void drawOpenCloseRModule(Area area) {
  RModule module = RModule.OpenClose;
  Size size = moduleSize(module);
  
  int x = layoutGuideX(area);
  int y = layoutGuideY(area);
  int w = moduleWidth(size);
  int h = moduleHeight(size);

  /* ここから追加 */
  if (isUpdatedOpenClose) {
    
  } else {
    fill(0, 0, 0, 50);
    noStroke();
    rect(x, y, w, h, MODULE_RECT_ROUND);
    
    drawText(CENTER, CENTER, WHITE_COLOR, 24, "OpenCloseModule\nデータを取得できません", x+w/2, y+h/2);
  }
  /* ここまで追加 */
}

スイッチの値によって、OpenCloseRModuleの背景とテキストを切り替えられるようにします。

RM_OpenClose.pde
void drawOpenCloseRModule(Area area) {
  RModule module = RModule.OpenClose;
  Size size = moduleSize(module);
  
  int x = layoutGuideX(area);
  int y = layoutGuideY(area);
  int w = moduleWidth(size);
  int h = moduleHeight(size);

  /* ここから追加 */
  if (isOpen) {
    image(openCloseBackgroundOpen, x, y, w, h);
  } else {
    image(openCloseBackgroundClose, x, y, w, h);
  }
  /* ここまで追加 */
  
  if (isUpdatedOpenClose) {
    /* ここから追加 */
    if (isOpen) {
      drawText(LEFT, BASELINE, WHITE_COLOR, 128, "OPEN", x+50, y+50);
      drawText(LEFT, BASELINE, WHITE_COLOR, 32, "開店しています。", x+50, y+250);
    } else {
      drawText(LEFT, BASELINE, WHITE_COLOR, 128, "CLOSE", x+50, y+50);
      drawText(LEFT, BASELINE, WHITE_COLOR, 32, "閉店しています。\n14時から開店します。", x+50, y+250);
    }
    /* ここまで追加 */
  } else {
    fill(0, 0, 0, 50);
    noStroke();
    rect(x, y, w, h, MODULE_RECT_ROUND);
    
    drawText(CENTER, CENTER, WHITE_COLOR, 24, "OpenCloseModule\nデータを取得できません", x+w/2, y+h/2);
  }
}

drawOpenCloseRModuleが実装できたので、関数drawModules()内で実装します。

DigitalSignage.pde
/* 略 */

void drawModules() {
  if (nowPageID == 0) {
    drawFullImageModule(background);
    drawGridModule();
    drawPlaceholderModule();
    drawWeatherRModule(Area.area1);
    drawBusRModule(Area.area3);
    drawGomiRModule(Area.area5);
  } else if (nowPageID == 1) {
    drawFullImageModule(background);
    drawGridModule();
    drawPlaceholderModule();
    drawTwitterRModule(Area.area3);
    drawOpenCloseRModule(Area.area5); /* 追加 */
  } else if (nowPageID == 2) {
    drawFullImageModule(adImage[0]);
  }
  drawDateModule();
  drawLocationModule();
  drawProgressBarModule();
  drawPageControlModule();
}

/* 略 */

実行してスイッチを切り替えると、表示が変わるようになっているはずです。

0189.png

0010.png

最後に

これで開店/閉店を表示する「OpenCloseRModule」が実装できました。
次は、**部屋の温度を表示する「TemperatureRModule」**を作ってみましょう。

0
0
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
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?