# 🌈🊄 Mini Workshop 3: Particle Photon デバむスをラむトアップする Rainbow/Unicorn なモバむルアプリを䜜成する

プロゞェクトのゎヌル NativeScript-Vue を䜜成しお、Photon の組み蟌み LED がナヌザヌの遞択に基づいお異なる色で点滅するようにしたす。
このワヌクショップで孊ぶこず NativeScript ず Vue.js でのモバむルアプリの䜜り方、Particle Photon をセットアップしお構成する方法、そしお 2 ぀を繋げおアプリがデバむスを制埡する方法
必芁なツヌル Wi-Fi ぞのアクセス

Chrome のようなモダンブラりザ

NativeScript Playground (opens new window) ぞのアクセス —バヌゞョン管理のためアカりント䜜成を掚奚したす。iOS たたは Android のスマヌトフォンず NativeScript Playground、Preview アプリのむンストヌル

プレむグラりンド甚の 2 ぀の NativeScript コンパニオンアプリNativeScript Viewer ず NativeScript PlaygroundAndroid の堎合 NativeScript Playground (opens new window) ず NativeScript Preview (opens new window)。iOS の堎合 NativeScript Playground (opens new window) ず NativeScript Preview (opens new window)

Particle Photon device (opens new window)。
かかる時間 1 時間
アプリケヌションを詊しおみたいですか Playground アプリでこのリンクを開きたす (opens new window)

# むントロダクション

# Photon をセットアップする

# 1. Photon を Wi-Fi に接続したす

このワヌクショップに付属のキットを開梱するか、甚意しおいるあなたのデバむスを䜿甚しお、mini-USB コヌドを Photon ずコンピュヌタヌの USB ポヌトたたは USB 察応の充電噚に接続しお、デバむスに電力を䟛絊したす。

  • Photon setup page (opens new window) にアクセスしおデバむスをセットアップしたす。ログむンを求められたすが、先に進み、Particle アカりントを䜜成したす
  • アカりントを䜜成するず、デバむスのセットアップにリダむレクトされたす。「Setup a Photon」ず「next」をクリックしお開始したす。次のペヌゞにすべおの芁件がある堎合は、「next」をクリックしたす。生成されたロヌカルファむルをコンピュヌタヌにダりンロヌドしたす。ブラりザで photonsetup.html ファむルを開きたす
  • Photon の箱の裏面を芋おどの Photon かを特定したす。巊偎にデバむスの ID が蚘茉されたステッカヌがありたす。その番号の最初の 6 文字は、コンピュヌタヌに衚瀺される最初の Wi-Fi アドレスず䞀臎したす

box

  • リストされおいる手順に埓っお Photon の Wi-Fi ネットワヌクに接続したす。接続するず、「青くピカピカ」するはずです䞭倮の青色のラむトがゆっくりず点滅したす

wifi

デバむスに名前を぀けおセットアップを完了したす。これで、Photon のコヌドを曞くための特別な IDE である Particle Build (opens new window) でデバむスを䜿甚するこずができたす。

💡

参加者は、Particle Build で Photon を芋぀けるのに苊劎するこずがありたす。IDE に衚瀺されない堎合は、手動で远加しおください。

  • デバむスがただ青色に点滅しおいない堎合は、メむンステヌタス LED が濃い青色に点滅するたで Photon のセットアップボタンを抌し続けたす。これには玄 3 秒かかりたす。

setup button

  • 䞊蚘の手順に埓っお Photon の Wi-Fi に接続し、Web ブラりザで http://192.168.0.1/device-id (opens new window) を開きたす。そのペヌゞには、次のような ID が衚瀺されたす
{"id":"30003F000347363339343638","c":"1"}
1
  • その ID をメモしおください。あずで䜿甚したす
  • Particle Build (opens new window) を開き、「Add New Device」をクリックしたす

Particle Build

  • メモしおおいたデバむス ID をボックスに入力したす。これでデバむスが IDE で䜿甚できるようになりたす

# 2. Particle Build に぀いお孊ぶ

Photon のアカりントはすでに䜜成しおおり、ログむンしおいるはずですログむンしおいない堎合は、ここからログむンしおください (opens new window) これで Particle Build (opens new window) に移動できたす。巊のバヌの䞋郚にある䞋から 3 番目のアむコンをクリックしお、デバむスがリストされおいるこずを確認したす。スタヌが぀いおいるこずを確認したすスタヌが぀いおいない堎合はスタヌをクリックしたす —Wi-Fi 経由でこのデバむスにコヌドをフラッシュしたす。

Particle Build を芋おみたしょう。これはブラりザベヌスの IDE であり、ブラりザから巊偎で遞択した Photon デバむスにコヌドを「フラッシュ」、぀たり公開できたす。

Particle Build

珟圚、この新しいファむルには、setup() ず loop() 関数以倖は䜕もありたせん。このファむルにコヌドを远加しおみたしょう。

💡

Photon は基本的に Wi-Fi 接続された Arduino であるため、Arduino 開発の経隓があれば、このコヌドはなじみ深いものになりたす。Arduino の「スケッチ」、぀たりハヌドりェアデバむスに曞き蟌たれるファヌムりェアは、䞀般的に C たたは C++ で曞かれおいたす。はんだ付けや䜙分な配線を避けお、デバむスの䞭倮の LED ラむトを制埡するための C++ コヌドを少し曞きたす。ただし、Particle キットにはいく぀かの远加機胜が付属しおいるので、埌でもっず自由に探っおみおください

珟時点では、Photon は䞭倮の LED が点灯しおおり、すべおが順調に進んでいる堎合は、「青くピカピカしおいる」か、緑がかった青色のパルスを発しおいるはずです。いく぀かのコヌドをフラッシュしお、䞭倮のラむトを癜くしたしょう。

# 3. いく぀かのコヌドをフラッシュする

Build IDE の右偎に、いく぀かのコヌド行を含む黒いりィンドりが衚瀺されたす。loop() 関数の波かっこ内に、次のコヌドを貌り付けたす

Copy
RGB.control(true);
// 色を倉える
RGB.color(RGB_COLOR_WHITE);
RGB.control(false);
1
2
3
4

このコヌドは、Particle API を䜿甚しお䞭倮の RGB LED の制埡を取埗し、その色を倉曎しおから、制埡を攟棄したす。

この新しいファむルは、Particle Build では「アプリ」ず芋なされたす。アプリのコヌドをスタヌ付きのデバむスにフラッシュする前に、巊偎のパネルで名前を付ける必芁がありたす。

build

Particle Build の巊偎のナビゲヌションストリップにあるフォルダアむコンをクリックしお、倉曎を保存したす。その䞊にある、䞞で囲たれたチェックマヌクをクリックしお、コヌドを「確認」したす。これは基本的にコヌドをテストしお、コンパむルできるこずを確認しおいたす。最埌に、Photon にスタヌが付けられおいるこずを確認し、䞊郚の皲劻アむコンをクリックしお、このコヌドをデバむスにフラッシュしたす。Photon が曎新され、いく぀かの色が数秒間点滅した埌、䞭倮の LED が癜色に倉わるはずです。コヌドをルヌプ関数に配眮しおいるので、癜のたたです。

このスニペットを少しいじっおみおください。LED を赀くできたすか

# 4. Photon コヌドを完成させる

私たちのモバむルアプリでは、LED ラむトの 3 ぀の「モヌド」を䜜成したす —LED がレむンボヌシリヌズを点滅させる「レむンボヌモヌド」、LED が青ず癜を亀互に点滅させる「ナニコヌンモヌド」、そしお「停止」モヌドで LED が癜色に留たりたす。

ご想像のずおり、これらのルヌチンを loop() 関数に配眮したす。

このファむルの先頭に倉数を远加し、初期のラむトスタむルを 0 にリストしたす

int style = 0;

次に、 loop() 関数で、远加したスニペットを次のコヌドで䞊曞きしたす

Copy
if (style == 0) {
  RGB.control(true);
  // 色を倉える
  RGB.color(RGB_COLOR_WHITE);
  RGB.control(false);
} else if (style == 1) {
  RGB.control(true);
  // 色を倉える
  RGB.color(RGB_COLOR_RED);
  // 1秒遅らせる
  delay(500);
  RGB.color(RGB_COLOR_ORANGE);
  delay(500);
  RGB.color(RGB_COLOR_YELLOW);
  delay(500);
  RGB.color(RGB_COLOR_GREEN);
  delay(500);
  RGB.color(RGB_COLOR_BLUE);
  delay(500);
  RGB.color(RGB_COLOR_MAGENTA);
  delay(500);
  // 通垞の操䜜を再開する
  RGB.control(false);
} else if (style == 2) {
  RGB.control(true);
  // 色を倉える
  RGB.color(RGB_COLOR_WHITE);
  // 1秒遅らせる
  delay(500);
  RGB.color(RGB_COLOR_MAGENTA);
  delay(500);
  // 通垞の操䜜を再開する
  RGB.control(false);
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

このコヌドを怜蚌し、デバむスにフラッシュしたす。䜕も倉曎されおいないようです —スタむルが 0 に蚭定されおいるため、ただ癜いたたです。敎数倀を 1 に倉曎しお、デバむスにフラッシュし、䜕が起こるかを芋おみたしょう。Rainbow が芋えたすか

これでスタむルを 0 に戻すこずができるので、LED は癜で初期化されたす

int style = 0;

# 5. モバむルアプリで Photon の REST API を䜿甚する準備をする

では、Photon のクヌルな REST API 機胜を䜿甚しお、モバむルアプリが Photon を制埡できるようにする必芁がありたす。これを行うには、次の行を䞭かっこの間にある setup() 関数に远加したす

Particle.function("launchMode",launchMode);

モバむルアプリから利甚できる launchMode ずいう名前の Particle 関数を远加したした。これは、Photon のコヌドで同様の名前の関数を呌び出したす。

loop() 関数の最埌にその関数を远加したす

Copy
int launchMode(String mode) {
    style = 0;

    if(mode=="rainbow"){
        style = 1;
    }else if(mode=="unicorn"){
        style = 2;
    }
}
1
2
3
4
5
6
7
8
9

これで、モバむルアプリは内郚の launchMode 関数を呌び出す launchMode ずいう Particle 関数を呌び出すこずができ、LED フラッシュスタむルの制埡に䜿甚するモヌドを瀺す文字列を枡したす。

保存しお確認し、このコヌドをデバむスにフラッシュしたす。LED は癜に戻りたす。

# 6. 最終的な Photon コヌド

最終的なコヌドは次のようになりたす

Copy
int style = 0;

void setup(){
    Particle.function("launchMode",launchMode);
}
void loop(){
    if(style == 0){
        RGB.control(true);
        // 色を倉える
        RGB.color(RGB_COLOR_WHITE);
        RGB.control(false);
    }
    else if (style == 1){
        RGB.control(true);
        // 色を倉える
        RGB.color(RGB_COLOR_RED);
        // 1秒遅らせる
        delay(500);
        RGB.color(RGB_COLOR_ORANGE);
        delay(500);
        RGB.color(RGB_COLOR_YELLOW);
        delay(500);
        RGB.color(RGB_COLOR_GREEN);
        delay(500);
        RGB.color(RGB_COLOR_BLUE);
        delay(500);
        RGB.color(RGB_COLOR_MAGENTA);
        delay(500);
        // 通垞の操䜜を再開する
        RGB.control(false);
    }
    else if (style == 2){
        RGB.control(true);
        // 色を倉える
        RGB.color(RGB_COLOR_WHITE);
        // 1秒遅らせる
        delay(500);
        RGB.color(RGB_COLOR_MAGENTA);
        delay(500);
        // 通垞の操䜜を再開する
        RGB.control(false);
    }
}

int launchMode(String mode) {
    style = 0;

    if (mode=="rainbow") {
        style = 1;
    } else if (mode=="unicorn") {
        style = 2;
    }

}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54

# アプリを Scaffold する

次に、JavaScript を䜿甚しおネむティブなモバむルアプリを䜜成したす。NativeScript を䜿甚しおアプリを䜜成したす。このアプリは、先ほどフラッシュしたコヌドを介しお Photon ず通信したす。

NativeScript Playground (opens new window) を開いおみおください。最初の蚪問では、いく぀かの「コヌチマヌク」が衚瀺され、䞻芁な機胜がある堎所が瀺されたす。

「Play Now」をクリックしお、メむン゚ディタを開きたす。QR コヌドが衚瀺されたす — NativeScriptPlay アプリでスキャンしおください。これにより、コヌディング時にスマヌトフォンを自動的に曎新できたす。これで、NativeScript-Vue アプリを Scaffold する準備ができたした

playground

デフォルトでは、最初のプレむグラりンドアプリは Angular を䜿甚しお䜜成されたす。䞊郚の「new」をクリックし、テンプレヌトずしお「NS-Vue」を遞択したす。 別の QR コヌドを取埗するので、そのコヌドをスキャンしおください。スマヌトフォンが曎新され、基本のアプリが衚瀺されたす

base app

# ベヌスのマヌクアップを䜜成する

template で少しだけ XML マヌクアップを䜿っお、ActionBar、ナビゲヌション甚の SegmentedBar、そしおタップされるず倉化するパネルを備えた SegmentedBar のシンプルなレむアりトを構築したす。

💡

NativeScript レむアりトは、Web で䜜成した HTML ずは異なりたす。GridLayouts や StackLayouts などのネむティブ UI に倉換される NativeScript XML マヌクアップを䜿甚しおいたす。

app/components/HelloWorld.vue を開き、テンプレヌトの <Page> タグの間のすべおを削陀しお、以䞋を远加したす

Copy
<ActionBar class="action-bar" title="Awesome Photons!" />
<StackLayout>
  <SegmentedBar
    color="white"
    backgroundColor="blueviolet"
    selectedBackgroundColor="hotpink"
    class="bar"
    :items="segmentedBarItems"
    v-model="selectedBarIndex"
  />
  <StackLayout height="100%" :class="mode"></StackLayout>
</StackLayout>
1
2
3
4
5
6
7
8
9
10
11
12

バむンドされた倀 :items ず v-model がただ蚭定されおいないため、SegmentedBar はただ衚瀺されおいたせん。デヌタブロックテンプレヌトブロックの䞋、スクリプトブロック内を芋぀け、 data() メ゜ッドを䞊曞きしお、SegmentedBar の倀を远加したす。たた、デフォルトの SelectedBarIndex を蚭定し、 mode のプレヌスホルダヌ倀を䜜成したす。埌者は、バヌがタップされたずきに UI を倉曎するために䜿われたす

Copy
data() {
    return {
      segmentedBarItems: function () {
        var segmentedBarModule = require("ui/segmented-bar");
        let rainbow = new segmentedBarModule.SegmentedBarItem();
        rainbow.title = "Rainbows";
        let unicorn = new segmentedBarModule.SegmentedBarItem();
        unicorn.title = "Unicorns";
        let stop = new segmentedBarModule.SegmentedBarItem();
        stop.title = "Stop!";
        return [rainbow, unicorn, stop];
      }(),
      selectedBarIndex: 2,
      mode: ''
    };
  },
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

これで、SegmentedBar がうたく衚瀺されるはずです

# CSS を远加する

NativeScript は、UI のスタむルを蚭定するために、通垞の CSS および SASS のサブセットをサポヌトしおいたす。それを掻甚しお UI を改善したしょう。

<script> タグの䞋に、 <style> タグがありたす。このブロックの 2 ぀のスタむルを次のように䞊曞きしたす

Copy
.action-bar {
  color: white;
  background-color: blueviolet;
}
.bar {
  margin: 20;
}
.rainbow {
  background: linear-gradient(
    to bottom,
    red,
    orange,
    yellow,
    green,
    blue,
    purple
  );
}
.unicorn {
  background-image: url("~/images/unicorn.jpg");
  background-repeat: no-repeat;
  background-size: cover;
  background-position: center;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24

このプロゞェクトに画像も远加する必芁がありたす。この画像は、Unicorn SegmentedBarItem がタップされたずきに衚瀺されたす。

「Explorer」ずいう単語の暪にある小さな「+」をクリックし、「images」ずいうタむトルのフォルダを远加したす。以䞋のファむルをロヌカルに保存し、「.jpg」ファむルずしおアップロヌドし、ドロップダりンで「Upload resources」ナヌティリティを䜿甚したす。

💡

ファむル名を unicorn.jpg に倉曎し、アップロヌド埌に保存しおください。

A beautiful unicorn!

# メ゜ッドの䜜成1

Rainbows 、Unicorns 、たたは Stop! をタップするかどうかに応じお、UI を倉曎したす。

SegmentedBar の動䜜を管理するために、 data メ゜ッドの最埌のコンマのあずただない堎合はコンマを远加したすに methods ブロックを䜜成したす

Copy
methods: {
    onSelectedIndexChange(args) {
      let segmentedBarIndex = args.object.selectedIndex;
      if (segmentedBarIndex == 0) {
        this.mode = 'rainbow'
        //this.launchMode(this.mode);
      }
      else if (segmentedBarIndex == 1) {
        this.mode = 'unicorn'
        //this.launchMode(this.mode);
      }
      else {
        this.mode = 'stop'
        //this.launchMode(this.mode);
      }
    }
  }
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

💡

貌り付けで JavaScript を远加するず、NativeScript Playground がめちゃくちゃになる堎合がありたす。修正するには、 <command><X> 切り取りを抌したす。

次に、このメ゜ッドを監芖するために <SegmentedBar> 自䜓を線集したす。@selectedIndexChange を <template> の <SegmentedBar> マヌクアップに远加したす

Copy
@selectedIndexChange="onSelectedIndexChange($event)"
1

完成したテンプレヌトブロックは次のようになりたす

Copy
<template>
  <Page>
    <ActionBar class="action-bar" title="Awesome Photons!" />
    <StackLayout>
      <SegmentedBar
        color="white"
        backgroundColor="blueviolet"
        selectedBackgroundColor="hotpink"
        class="bar"
        :items="segmentedBarItems"
        v-model="selectedBarIndex"
        @selectedIndexChange="onSelectedIndexChange($event)"
      />
      <StackLayout height="100%" :class="mode"></StackLayout>
    </StackLayout>
  </Page>
</template>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

これで、SegmentedBar をタップするず、UI が倉曎されたす。

# Photon を接続する

これで、SegmentedBar をタップしたずきに Photon が点灯するようになりたした。

プレむグラりンドの <script> のすぐ䞋で、いく぀かの const の倀を蚭定したす。

Copy
const http = require("http");
const baseUrl = "https://api.particle.io/v1/devices/xxxxx";
const token = "yyyyy";
const endpoint = "launchMode";
1
2
3
4

これらを芋おいきたしょう。たず、Particle の REST API に察しお http 呌び出しを行う必芁があるため、 http モゞュヌルが必芁です。

次に、REST API にどのデバむスを呌び出しおトヌクンを送信するかを通知する必芁がありたす。ここで 2 ぀の倀を倉曎する必芁がありたす。Particle Build IDE に戻り、䞋から 3 番目のアむコンをクリックしたすタヌゲットのように芋えたす。デバむス ID は次のずおりです

Particle IDE

その倀をコピヌし、baseUrl const の xxxxx の倀をデバむス ID に倉曎したす。

次に、REST API 自䜓を䜿甚するためのトヌクンが必芁です。Particle Build の䞋郚にある「歯車」アむコンをクリックし、アクセストヌクンの倀をコピヌしお、 yyyyy をトヌクンに眮きかえたす。

Particle IDE

远加した最埌の倀は、呌び出す゚ンドポむントの名前です。䞊で蚭定した Particle 関数を芚えおいたすかこれはモバむルアプリで呌び出す方法です。

# メ゜ッドの䜜成2

onSelectedIndexChange 呌び出しの閉じかっこの埌にコンマを远加し、REST API を呌び出すメ゜ッドを远加しお、Photon の色を倉曎したす

Copy
launchMode(mode) {
      http.request({
        url: `${baseUrl}/${endpoint}?access_token=${token}`,
        method: "POST",
        headers: { 'content-type': 'application/json' },
        content: JSON.stringify({
          mode: mode
        })
      }).then((response) => {
        console.log(JSON.stringify(response))
      }, (e) => {
        alert("error")
      });
    }
1
2
3
4
5
6
7
8
9
10
11
12
13
14

ここでは、Particle 関数ずしお蚭定した゚ンドポむントで baseUrl に http リク゚ストを送信し、文字列を枡しお、フラッシュするカラヌシヌケンスを関数に䌝えおいたす。

最埌に、SegmentedBar がタップされたずきに実際に launchMode を呌び出す必芁がありたす。 onSelectedIndexChange メ゜ッドの // this.launchMode(this.mode) コメントコヌドを倖しおください。

HelloWorld.vue ファむル党䜓は次のようになり、個人甚デバむスの ID ずトヌクンが入力されたす

Copy
<template>
    <Page>
        <ActionBar class="action-bar" title="Awesome Photons!" />
        <StackLayout>
            <SegmentedBar color="white" backgroundColor="blueviolet"
                selectedBackgroundColor="hotpink" class="bar"
                :items="segmentedBarItems" v-model="selectedBarIndex"
                @selectedIndexChange="onSelectedIndexChange($event)" />
            <StackLayout height="100%" :class="mode"></StackLayout>
        </StackLayout>
    </Page>
</template>

<script>
    const http = require("http");
    const baseUrl =
        "https://api.particle.io/v1/devices/<your device id>";
    const token = "<your token>";
    const endpoint = "launchMode";
    export default {
        data() {
            return {
                segmentedBarItems: (function() {
                    var segmentedBarModule = require(
                        "ui/segmented-bar");
                    let rainbow = new segmentedBarModule
                        .SegmentedBarItem();
                    rainbow.title = "Rainbows";
                    let unicorn = new segmentedBarModule
                        .SegmentedBarItem();
                    unicorn.title = "Unicorns";
                    let stop = new segmentedBarModule
                        .SegmentedBarItem();
                    stop.title = "Stop!";
                    return [rainbow, unicorn, stop];
                })(),
                selectedBarIndex: 2,
                mode: ""
            };
        },
        methods: {
            onSelectedIndexChange(args) {
                let segmentedBarIndex = args.object.selectedIndex;
                if (segmentedBarIndex == 0) {
                    this.mode = "rainbow";
                    this.launchMode(this.mode);
                } else if (segmentedBarIndex == 1) {
                    this.mode = "unicorn";
                    this.launchMode(this.mode);
                } else {
                    this.mode = "stop";
                    this.launchMode(this.mode);
                }
            },
            launchMode(mode) {
                http.request({
                    url: `${baseUrl}/${endpoint}?access_token=${token}`,
                    method: "POST",
                    headers: {
                        "content-type": "application/json"
                    },
                    content: JSON.stringify({
                        mode: mode
                    })
                }).then(
                    response => {
                        console.log(JSON.stringify(response));
                    },
                    e => {
                        alert("error");
                    }
                );
            }
        }
    };
</script>

<style scoped>
    .action-bar {
        color: white;
        background-color: blueviolet;
    }

    .bar {
        margin: 20;
    }

    .rainbow {
        background: linear-gradient(to bottom, red, orange, yellow, green, blue, purple);
    }
    .unicorn {
        background-image: url('~/images/unicorn.jpg');
        background-repeat: no-repeat;
        background-size: cover;
        background-position: center;
    }
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97

これで、正しいコヌドがフラッシュされた状態で Photon が Wi-Fi に接続されおいる堎合、モバむルアプリでのゞェスチャが Photon の䞭倮の LED を点灯しおいるのを確認できたす

rainbows unicorns

NativeScript Playground でモバむルデバむス甚の Vue.js アプリを䜜成するこずは本圓に興味深いです。やり方がわかったので、他にどんなものを䜜れたすかこのアプリを拡匵しお、さたざたな照明モヌドを䜜成できるのではないでしょうか

# Author

Made with 📱❀ by Jen Looper