2
1

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.

TwinMakerで、バーチャルなキャラクターに現実の家事を手伝ってもらう

Last updated at Posted at 2023-07-01

この記事について

この記事をひとことで

・AWS IoT TwinMakerを使った、現実のお風呂の湯張りが終わったことを バーチャルなキャラクター(MMD)が教えてくれる仕組みの作り方を紹介します。

何が嬉しいの?

  • 現実世界の家事をバーチャルなキャラクターが手伝ってくれる体験ができます。
  • 3Dのキャラクターと現実世界のリンクがローコードで実装できます。
  • お風呂の監視が楽になります。

難しい?

  • TwinMakerを使うので、大部分をプログラミングなしで構築できます。
  • AWSの知識が必要です。
  • データベース、3Dソフト、IoT等のスキルは不要です。
  • プログラミングが少し必要になる場所:
    • TwinMakerのタグをMMDに置き換える部分にReactのコードを書きます
    • データを収集する部分にPythonのコードを書きます

予算は?

  • センサー代の2,000円があれば大丈夫です。

動いているところ: 動画(20秒)

前提条件: この記事で解決したいのはどんな課題?

筆者の家は水栓でお湯を入れるタイプの浴室です。このタイプです。

お湯をためるためには、手で栓を緩めてお湯を出して、いい水位までたまるのを待って、手で栓を締める必要があります。

時間が経つと勝手にお湯が止まる機能はないので、じぃっと目視でお湯を監視します。

お湯がたまるのを待っている時間は、2分間憎悪ならぬ10分間虚無です。ビッグ・ブラザーは僕を見ている時間があるなら我が家のお湯を見ていてください。結構大変です。

今回の記事では、これをテクノロジーで解決します。

課題の解決方法: VTuberにお湯張りを見てもらう

AWS IoT TwinMakerを使って、お風呂の監視を「兎田ぺこら」さんにお願いするシステムを作りました。

pekora-1.png

お湯を張り終わると、ぺこーらが教えてくれます。

pekora-2.png

補足:
MMDなら誰でも大丈夫です。ボーカロイド、アニメ、ゲーム、VTuber、色々なキャラクターが見つかると思いますので、気に入ったキャラクターで構築してください。

センサーはSwitchBotの防水温湿度計を使います。

1,980円(税込)とリーズナブルですが、精度は高く、セットアップは簡単で、電池の絶縁フィルムを引き抜くだけで測定が始まります。コンセントは不要で、Bluetooth(BLE)で無線通信ができます。お風呂でも安心して使えます。

センサーとTwinMakerで実装する概要は以下のとおりです。

センサー側ですること

①防水温湿度センサーを袋に入れて、浴槽の内側にぶら下げます。
②センサーの数値をBLEで受信、SiteWiseに転送します。

→ センサーがお湯に沈むと温度が跳ね上がるので、それを検知させます。

TwinMaker側ですること

①TwinMaker上で、3Dの部屋、データの受信ルール、センサーの値によって色が変わるタグを作ります。
②iot-app-kitでTwinMakerを表示する時に、タグの表示をMMDに置き換えて、タグの色変えイベントをMMDがサブスクライブします。

→ タグの色が変わると、対応するモーションが再生されるようにします。

もうこれで10分間の虚無を過ごさなくてもよくなります。

記事の構成

必要なものは以下の通りです

  • パソコン(Windows機、Bluetoothと接続できるもの)
  • スマートフォン(SwitchBotの初期設定ができるもの)
  • VSCode
  • AWSアカウント
  • SwitchBot 防水温湿度センサー
  • 輪ゴム、何か円形のひも状のもの
  • ビニルテープ
  • チャック付きポリ袋(ジップロックの小さいやつ)
  • ネックストラップ(首からぶら下げるやつ)
  • Python(v3.8以降のバージョンのもの)
  • Node.js(v14.15以降のバージョンのもの)

この記事では、以下のことを前提に記事を進めます

  • React, Pythonについて、プログラミングの基本的な知識があること
  • AWS(特にIAM、認証回り)の運用方法を知っており、ある程度の操作ができること

ソースコードはこちらにあります。手元で構築する際は、ローカル環境にダウンロードしてから作業していただきますようお願いいたします

AWSに必要な環境を構築する

すること

  • SiteWiseの環境を構築します
  • TwinMakerの環境を構築します

補足と注意: リージョンについて
TwinMakerは東京リージョンにありません。
SiteWiseのリージョンも、TwinMakerが利用できるバージニア北部(us-east-1)に合わせてください。

構成図

aws.png

シンプルな構成図になります。登場するAWSサービスが少なく、VPCやEC2のような料金のかかるサービスも含まないため、ランニングコストも高くなりません。お風呂を見張るだけだと、1日1時間利用して1円かからないくらいだと思います。

補足:
筆者が1週間の開発でかかったAWS利用料金は3円でした。

SiteWiseの環境を構築します

SiteWiseの構築を始めます。

AWS IoT SiteWiseを簡単に説明すると、IoTの裏方を全部やってくれるサービスです。

sitewise.png

IoTから受け取ったデータを収集、整形、保存して、他のサービスに連携することができます。データを収集するエンドポイントとしての機能だけでなく、データを変換処理をする機能、データベースとしてデータを保管する機能も持っています。

1. リージョンをバージニア北部にする

AWSマネジメントコンソールにログインしたら、まずTwinMakerが利用できるリージョンに変更します。

region-versinia.png

2. IoT SiteWiseを開いて、モデルを作成します

IoT SiteWiseを開いて、「ビルド」→「モデル」を選択、「モデルの作成」を選びます。

init-sitewise.png

入力するパラメータ

大項目 項目 設定する値 備考
モデルの詳細 名前 SwitchBotTemperature ※好きな名前を付けます
モデルの詳細 説明 ※空欄にします
属性の定義 ※全て空欄にします
測定値の定義 名前 temperature ※今回は温度を測定するので、温度にします
測定値の定義 単位 c ※単位の名前を付けます
測定値の定義 データ型 ダブル ※ダブル型を選びます
以降の項目 ※全て空欄にします

3. アセットを作成します

モデルでデータの定義を設定したので、配置するセンサーの情報を作ります。

プログラミングで言うと、モデルがクラス定義、アセットがインスタンスになります。現実のセンサーはアセットに自分のデータを同期します。

init-asset.png

入力するパラメータ

大項目 項目 設定する値 備考
モデル情報 モデル SwitchBotTemperature ※先ほど作ったモデルを選びます
アセットの情報 名前 SensorA ※好きな名前を付けます
測定 temperature record/temperature パス形式で好きな名前を付けます
測定 MQTT通知ステータス アクティブ 有効にします

TwinMakerの環境を構築します

次に、IoT TwinMakerの環境を構築していきます

AWS IoT TwinMakerを簡単に説明すると、簡単に3D空間(メタバース)を作って、ほぼリアルタイムで現実世界と同期できるツールです。

AWSの資料では、3D世界に風車を作って、現実の風車のデータ(回転数、異常だとか)を表示するデモが出ています。

205143289-664e4a63-a421-497b-8265-a9a481a11db5.png

1. リージョンをバージニア北部にする

SiteWiseに続いて作業をするのなら作業開始時点からバージニア北部になっているはずです。もし違うリージョンになっているのなら、バージニア北部に変更します。

region-versinia.png

2.TwinMaker開いて、ワークスペースを作成します

create-workspace.png

入力項目は以下のように入力します。

  • 名前:自由に名前を付けます
  • 説明:空欄でもOKですが、必要があれば説明を書きます
  • S3バケット:1番上にある、S3バケットを作成を選択します
  • 実行ロール:1番上にある、新しいロールを自動生成を選択します

入力できたら、「確認をスキップして作成」 を選択します
 → スキップしないとGrafanaのダッシュボードの作成画面が出てきます。
   今回の手順では使わないため、Grafanaのダッシュボードは不要です。

3.ワークスペースを作成したら、シーンを作成します

scene.png

入力項目は以下のように入力します。

  • シーンID:自由に名前を付けます
  • 説明:空欄でもOKですが、必要があれば説明を書きます

シーンを開くと、TwinMakerの編集画面が出てきます

scene-open.png

4. IAMロールを編集します

ワークスペースを開いて、実行ロールを確認します。

workspace-1.png

実行ロールの名前を確認したら、IAMに移動して、実行ロールの内容を編集します。

policy-added.png

以下の2つのポリシーを許可するようにします

  • AWSIotSiteWiseFullAccess
  • AmazonS3FullAccess

5. TwinMakerがSiteWiseのデータを参照できるように設定します

「エンティティ」→「エンティティを作成」で、エンティティ情報を作成します。

create-entity.png

入力するパラメータ

大項目 項目 設定する値 備考
エンティティ情報 名前 SwitchBotTemperature ※任意の名前を付けます

作成したエンティティを選んで、「コンポーネントを追加」をします

create-component.png

入力するパラメータ

大項目 項目 設定する値 備考
コンポーネント情報 名前 Sensor ※任意の名前を付けます
コンポーネント情報 タイプ com.amazon.iotsitewise.connector ※接続先がSiteWiseだと指定します
コンポーネント情報 アセットモデル SwitchBotTemperature ※SiteWiseのモデル名を指定します
コンポーネント情報 モデル SensorA ※SiteWiseのアセット名を指定します
以降の項目 ※変更なしでOKです

コンポーネントが追加できたら、TwinMakerとSiteWiseの接続は完了です。

6. リソースに3Dモデルを登録します

TwinMakerに表示する3Dモデルを登録します。

「リソースライブラリ」→「リソースを追加」を選んで、ファイルをアップロードします。

add_resource.png

リソースには、GLTF、GLB形式のファイルを使うことができます。もしPNGの2Dイメージを使いたい場合は、筆者のツール(PNG画像をGLTFに変換するツール)を使うことで、TwinMakerに2D画像を取り込むことができます。

※ここでは背景だけ登録します。MMDのファイルはここで登録しなくても大丈夫です

補足: GLTF(GLB)ってどうやって用意するの?
Sketchfabで探すと、無料で公開されている3Dモデルをダウンロードすることができます。
欲しい3Dモデルの拡張子がobj形式にしか対応していなくても、obj2gltfでglbに変換することで利用できます。
スマートフォンの3Dスキャンアプリ(Scanniverse、Matterportなど)を使って、iPhoneで撮影した3Dデータを使うこともできます

7. シーンを開いて、3Dの空間を作っていきます

シーンの初期状態はこの状態です。

scene-open.png

「+」ボタンを押して、シーンに3Dのリソースを配置していきます。

scene_overview.png

カメラ、部屋、吹き出し画像を配置しました。

positioning.png

補足: 記事で使ったGLBデータ
部屋のモデルはSketchfabからお借りしました(ライセンスはCC 4.0です)
https://sketchfab.com/3d-models/studio-apartment-vray-baked-textures-included-cae2d96ede1d4112b1fd391099a43f77

吹き出し画像は、ふきだし素材専門サイト「フキダシデザイン」で作成したものを、筆者のツール(PNG画像をGLTFに変換するツール)でGLTFに変換して用意しました。

8. タグを作成します

部屋を作成したところに、「Add Tag」でタグを作成します。

add-tag.png

タグの位置は、MMDを配置したい場所の足もとを指定します。

visible-tag.jpg

タグにはMMDとして呼び出したいキャラクターの名前を付けてください。
記事では「Usada-Pekora」にします。

tag-name-changed.png

9. 表示ルールを作成する

SiteWiseのデータが変わった時に、TwinMakerでどう表示するのかを設定します。

「ルール」→temperature-ruleの名前で新規ルールを作成してください。

作成したルールを開いて、temperature<38の式と、temperature>=38の式を設定します。ターゲットには情報アイコンと警告アイコンを指定して、アイコンの見た目が変わるようにします。

以下のことを守って、正しいルールを設定する必要があります。

  • temperatureはSiteWiseアセットの測定値の名前と同じであること
  • temperatureがどの数字になっても、どれかのステートメント(式)に当てはまること(※temperature>40を作る時は、必ずtemperature<=40の式も作ってください)

temperature-rule.png

以下の3つのルールを作成します

ルール名 ステートメント 表示ルール
temperature-rule temperature<38 アイコン:情報
temperature-rule temperature>=38 アイコン:エラー
visible-rule temperature<38 不透明度:1
visible-rule temperature>=38 不透明度:0
initializer-rule temperature>=-999 不透明度:0
initializer-rule temperature<-999 不透明度:1

10. タグにルールを適用する

タグ(Usada-Pekora)を開いて、タグに表示ルールを設定します。

tag-visible-rule.png

大項目 項目名 設定値 備考
タグ デフォルトのアイコン ※空欄でOK
タグ エンティティID SwitchBotTemperature ※TwinMakerのエンティティがリスト表示されます
タグ コンポーネント名 Sensor ※TwinMakerに登録したコンポーネント名がリスト表示されます
タグ プロパティ名 temperature ※SiteWiseの測定値名を選びます

11. 吹き出しにルールを適用する

吹き出しを選んで、「+」から「モデルシェーダーを追加」をします

model-shader.png

モデルシェーダーを設置すると、タグと同じように、3Dモデルの見た目をSiteWiseのデータに合わせて変えることができるようになります。

model-shade-property.png

ルールID以外はタグ(Usada-Pekora)の表示ルールと同じ内容を設定します。

ルールIDをvisible-ruleにすると、タグ(Usada-Pekora)が情報状態になっているときだけ、吹き出しが消えるようになります。

ルールIDをinitialize-ruleにすると、SiteWiseにデータが入っているときは吹き出しが非表示に、データがないときは吹き出しが表示されるようになります。

吹き出しを2枚重ねて、手前の「データはどこにあるぺこ?」にはinitializer-ruleを、奥の「お風呂にお湯が入ったぺこ!」にはvisible-ruleを設定します。そうすることで、データがないとき注水中お湯はり完了後のメッセージを切り替えることができます。

fukidashi-double.png

iot-app-kitを使って、ブラウザ上でTwinMakerを表示する

iot-app-kitを使って、TwinMakerを読み込みます。

iot-app-kitについて説明すると、TwinMakerで作ったプロジェクトを、Reactのウェブアプリで表示できるようにするOSSです。AWSが開発、公開しています。

1. ソースコードをダウンロードしてください

記事冒頭で紹介した、こちらのソースコードをgitからダウンロードしてください。

2. npm installで必要なライブラリをインストールします

ソースコードを落としたら、Reactのディレクトリに移動して、必要なライブラリをインストールします。

cd projects/react-web
npm install

3. .envファイルを作って、必要な認証情報を登録します

package.jsonと同じ場所に、.envファイルを作ります

env-place-react-project.png

.envファイルには、認証情報、TwinMakerのワークスペースの情報、SiteWiseの情報を書き込みます。

.env
REACT_APP_AWS_ACCESS_KEY_ID="${AWSの認証情報: アクセスキーID}"
REACT_APP_AWS_SECRET_ACCESS_KEY="${AWSの認証情報: シークレットキー}"
REACT_APP_AWS_WORKSPACE_NAME="${TwinMakerのワークスペース名}"
REACT_APP_AWS_SCENE_NAME="${TwinMakerのシーン名}"
REACT_APP_AWS_REGION="${TwinMakerのリージョン: 例: us-east-1}"

REACT_APP_AWS_ENTITY_ID="${TwinMakerのエンティティID}"
REACT_APP_COMPONENT_NAME="${TwinMakerのコンポーネント名}"
REACT_APP_PROPERTY_NAME="${測定値のプロパティ名}"

ワークスペース名、シーン名、リージョンは、TwinMakerでシーンを開いたときのURLをコピーすれば、まとめて確認することができます。

https://us-east-1.console.aws.amazon.com/iottwinmaker/home?region=${リージョン}#/workspaces/${ワークスペース名}/scenes/${シーンID}

TwinMakerのエンティティ名、コンポーネント名、プロパティ名は、タグの表示ルールを設定したときに出ていた値をそのまま設定すればOKです。

tag-visible-rule.png

4. MMDファイルを配置します

MMDモデルはgitに上げられないので、MMDモデルとモーションは、ご自身の環境でダウンロードしたものをpublic以下に配置するようにしてください。

この記事では、こちらのモデルとモーションをお借りしています。

兎田ぺこら【公式】 投稿者:ホロライブ運営さん
https://3d.nicovideo.jp/works/td88332

【MMD】手を振るモーション【モーション配布あり】 投稿者:yuaoさん
https://www.nicovideo.jp/watch/sm40489290

【MMD】移動モーションv1.3 投稿者:むつごろうさん
https://bowlroll.net/file/154665

5. App.tsxを編集します

App.tsxの70行目付近の処理を、自分の環境に合わせて書き変えます。

replaceTagToMMDは、TwinMakerにあるUsada-Pekoraのタグを、MMDファイルに置き換える処理です。MMDモデルの場所をpmxPathで指定してください。モーションデータはmotionMapのパスに配置します。

TwinMakerのデータの状態が変わると、bindOnStateChangeEventが呼ばれます。DefaultAnchorStatus.Errorが警告アイコン、DefaultAnchorStatus.Infoが情報アイコンのことです。

アイコンの状態に応じて、MMDで再生するモーションのモーション名を配列で返します。(※配列で返したものは同時に再生されます。MMDは表情と体のモーションでファイルが分かれていることがあるため、このような形にしています)

App.tsx
      new SceneController(composerId, {
        /** TwinMakerのタグを上書きする */
        overrideTags(rootScene) {
          return {
            // TwinMakerのタグをMMDモデルに置き換える
            "Usada-Pekora": (ref, anchor) =>
              replaceTagToMMD(ref, anchor, getObject3DBySceneNodeRef)
                ?.create({
                  rootScene, // ルートになるシーン
                  scale: 0.088, // オプション: 表示スケール
                  angle: -20, // オプション: MMDの角度(単位はDegree)
                  pmxPath: "mmd/UsadaPekora/PMX/UsadaPekora.pmx", // MMDファイル
                  motionMap: {
                    // モーションファイル
                    "swing-hand":
                      "mmd/motion/手を振るモーション2/手振_スタンダード(右手).vmd",
                    "swing-hand-body":
                      "mmd/motion/手を振るモーション2/体_スタンダード(右手用).vmd",
                    "swing-hand-face":
                      "mmd/motion/手を振るモーション2/表情.vmd",
                    "motion-waiting":
                      "mmd/motion/5.待機モーション・その他/待機モーション/1.呼吸_(90f_移動なし).vmd",
                  },
                })
                .bindOnStateChangeEvent({
                  /** タグの状態が変わったのであれば通知を受ける */
                  onChangeState(mesh, model, state) {
                    // 初期化実行の時は、モーションを実行しない
                    if (state === SystemLoadingStatus.Init) {
                      return [];
                    }
                    // 今のタグの状態に応じて、モーションを変更する
                    switch (stringToDefaultAnchorStatus(state)) {
                      case DefaultAnchorStatus.Error:
                        // モーションファイルのキーを返却してモーション再生
                        // 配列で投げたモーションは同時に再生する(合成される)
                        // ※MMDは表情と体の一部のモーションが別ファイルで提供されることがあるため
                        return [
                          "swing-hand",
                          "swing-hand-body",
                          "swing-hand-face",
                        ];
                      default: // DefaultAnchorStatus.Info
                        // モーションファイルのキーを返却してモーション再生
                        return ["motion-waiting"];
                    }
                  },
                }),

タグをMMDファイルに置き換えるだけですので、ご自身の環境に合わせたものを作りこんでいただければと思います。

6. 実行する

以下のコマンドを実行して、Webサーバを立ち上げます。

npm run start

Chromeでhttp://localhost:3000を開いて、画面を確認します。

MMDモデルがタグの位置に立っていればOKです。

pekora-1.png

補足:
MMDの光源設定はTwinMakerの光源設定に比べてかなり明るく、そのまま表示するとMMDが白飛びしてしまうため、MMDの光源設定に合わせる処理を入れています。ですので、TwinMakerで表示した3Dモデルと比べると、やや暗い見た目で表示されるようになっています。

お湯張りセンサーを作る

お湯張りセンサーはSwitchBotの防水温湿度計を使います。

bousui-file-1.jpg

センサーの小ささを伝えるために、10円玉とサイズ比較をしています。ボンタンアメの箱に入るくらい、グリコのおまけの箱に入るくらいのサイズ感です。

1. センサーの初期設定

初期設定にはスマートフォンのSwitchBotアプリが必要になります。電池の絶縁フィルムを抜いて、ペアリングのボタンを押しながら、Switchbotアプリと紐づけます。

初期設定が完了するとアプリ上でMACアドレスが分かるので、それを手元にメモします。

2. センサーで湯量を計れるように工作する

  • 円形のひも(輪ゴムでOK)
  • チャック付きポリ袋
  • ネックストラップ(首からぶら下げるストラップ)
  • ビニルテープ

を用意します。どれも100円均一にあります。

センサーのストラップを通す場所に円形のひも(輪ゴム)を通します

bousui-file-2.jpg

チャック付きポリ袋にセンサーを入れて、ひもの先を袋の口から出します

bousui-file-3.jpg

チャックをしめたら、ひもとチャックの隙間から水が入ってこないように、袋の口を念入りにビニルテープでふさぎます。ひもの端はビニルテープから出ている状態にします。

bousui-file-4.jpg

ひもにネックストラップを付けます。

bousui-file-5.jpg

水栓にネックストラップをぶら下げれば完成です。

bousui-file-6.jpg

袋が弱ってきたら、はさみで輪ゴムと袋を切って新しいものに交換してください(※ストラップをセンサーに直接結んでしまうとストラップを切ることになるので、切ってもいい輪ゴムを間に挟むようにします)。

3. 測れるのかを見る

(この手順はスキップ可能です)

下の画像は、お湯を入れて、センサーの温度がどう変化していくのかを確認したところです。

bousui-file-7.jpg

湯気でじわじわと上がった後、センサーがお湯に沈んでからは一気に上昇します。温度センサーが38度を超えたら「センサーがお湯に沈んだ=お湯張りが終わった」と判定できそうです。

4. センサーデータの受信機をダウンロードする

記事冒頭で紹介した、こちらのソースコードをgitからダウンロードしてください(TwinMakerの手順でダウンロード済みであればこの作業は不要です)。

補足: 受信機の仕様について
SwitchBotの開発元が、防水温湿度計のセンサーデータの受信機のソースコードを公開しています。今回利用する受信機は、それをWindowsで動かせるように書き変えたものになります。

https://github.com/OpenWonderLabs/python-host/blob/master/switchbot.py

5. 受信機をセットアップする

受信機はboto3を使ってSiteWiseにデータを転送します。もし認証情報の設定が済んでいないのであれば、あらかじめ設定をお願いします。

venvを使って、受信機のセットアップをします。

cd projects\python-sensor-gateway
python -m venv .

仮想環境の構築ができたら、仮想環境を立ち上げます。

Scripts\activate.bat

仮想環境に必要なライブラリをインストールします

pip install -r requirements.txt

.envファイルを作成します

.env
MAC_ADDRESS=${Macアドレス}
ASSET_ID=${SiteWiseのアセットID}
PROPERTY_ID=${SiteWiseのプロパティID}

.envファイルを配置する場所はこちらです

projects\python-sensor-gateway\src

env-file-python.png

7. 受信機を動かす

Scripts\activate.batした環境で以下のコマンドを実行して、受信機を動かします

cd src
python app.py

補足:
センサーからした受信データではなく、任意に設定したデータをSiteWiseに送りたいときは、
python app.py --value 99.9
のように実行すると、データを1件だけ送信して終了します。
99.9の部分は任意の数字です。

6. お疲れ様です、これで全手順が完了しました

08.png

センサーの値に応じて、MMDが動いているはずです。

補足: 外出先でもTwinMakerでセンサ値を監視したいときの注意点
TwinMakerのプロジェクトをWebサーバにデプロイするときは、Amplifyなどを使ってログイン画面を設置して、AWSの認証情報をCognito経由で取るようにしてください(絶対に固定値の認証情報をクラウドに上げないでください)。

あとがき

この記事はシリーズで続ける予定です

  • 「ぺこら、エアコンつけて」で家電を操作する
  • Azure系のAIと連携して、TwinMakerの中にいる3Dキャラと会話をする

についても記事を書く予定です。ソニーのELF-SR2 空間再現ディスプレイとTwinMakerの連携も、お金と機会があったらやりたいです。。。

TwinMakerは産業用のIoT基盤をベースにしており、対応するデータソースも幅広いです。
活用事例はまだ少ないのですが、メタバースをブラウザだけで簡単に作ることができる、フルセットのThree.jsを組み込めるだけでなく、スマートホームのセンサーを丸ごと取り込む、大量の監視カメラの映像を自分の目にする、といったことが簡単にできるサービスです。

自由度が高い一方で、TwinMakerはソースコードを書く場所が少ないことも特徴です。吹き出しを切り替えるような場所はローコードで動いていますし、データベースも意識することがありません。少ないコーディングで何でもできる、面白いサービスだと思っています。

2
1
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
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?