[OCI]Cloud Deck: シンプルなマイコンでクラウドテナントの情報を自動化して取得 (2021/04/30)

Cloud Deck: シンプルなマイコンでクラウドテナントの情報を自動化して取得 (2021/04/30)

https://blogs.oracle.com/developers/cloud-deck:-automating-and-retrieving-info-from-your-cloud-tenancy-with-a-simple-microcontroller

投稿者:Todd Sharp



先月、私はStream Cheapというとてもクールなプロジェクトを発見しました。これは、大人気のElgato社のStream Deckを、安価なDIYバージョンにしたものです。

Stream Deckは、PCやラップトップに接続して、キーボードのコマンドをデッキのボタンにマッピングすることができる、便利なマクロキーボードです。ゲームストリーマーは、ストリームのシーンの切り替え、マイクのミュート、コメントの追加、ストリームのアノテーションなどのアクションに素早くアクセスするために、これらを多用します。

去年のクリスマスに息子と一緒にゲーミングコンピュータを作って以来、息子は自分のYouTubeチャンネルでゲームを配信するときに使えるようにストリームデッキを欲しがっていましたが、150ドルという価格のため手が届きませんでした-私がこの安いストリームデッキを見つけるまでは。

そこで先月の土曜日、私はケースを3Dプリントし、上のリンク先のチュートリアルの指示に従って、彼専用のストリームデッキを組み立てました。正直言って、出来栄えはとても良く、期待通りの働きをしてくれました。しかも、部品や材料に30ドルも払って、ストリームデッキを買うよりもずっと安上がりでした。



これはいじっていて楽しいプロジェクトでしたし、私自身も同じようなデバイスを日々の仕事でどのように使うかを考えるきっかけになりました。

最初に考えたのは、同じようなデバイスを作ることでしたが、マクロキーボードとして使うのではなく、OCI REST APIと対話してタスクを実行し、そのタスクの結果として通知を提供することで、Oracle Cloudのテナントを制御するために使用できないかと考えました。

もちろん、WiFi対応のマイコンから直接OCI REST APIを呼び出すことができるのかどうか、という疑問がまずありました。

この疑問を解決した後は、部品を集めて自分のケースを印刷し、最終的に「Cloud Deck」と呼ぶプロジェクトで使用することにしました。

この記事では、私がどのようにデバイスを構築し、OCIのテナントに対してちょっとした自動化を実行するようにプログラムしたかを紹介します。

Cloud Deckを自分で作ってみたい方は、この先を読む前に、Stream Cheapチュートリアルで説明されているプロセスに慣れることを強くお勧めします。


概要


このプロジェクトの目的は、自動化タスクを実行し、Oracle Cloud Infrastructure(OCI)のテナントから一般的な情報を取得するためのマクロキーボードを構築することでした。

ストリームデッキ」タイプのマクロキーボードとは異なり、Cloud Deckは私のラップトップから独立して動作します。

USBで電源を供給するだけで、WiFiネットワークに接続され、クラウド上の他の依存関係やサービスインスタンスを必要とせずに、内部のマイクロコントローラーから直接RESTコールを実行することができます。

私はまず、ESP32ボードと8つのスイッチ(実際にはCherry MXキー)を収納できるカスタムケースを3Dプリントすることから始めました。ケースを印刷した後、キーを取り付けて、ESP32のヘッダーピンに直接接続する直角ヘッダーコネクタにハンダ付けしました。

次に、マイクロコントローラーをプログラムし、スケッチをアップロードして、すべてをネジで固定しました。



素材や製造工程をもう少し掘り下げてみましょうか。


Bill of Materials

Stream Cheap」の部品表に従って、すべての同じコンポーネントを使用しましたが、注目すべきは、オリジナルのPro Micro ATmega32U4ボードの代わりにESP32を使用したことです。

Cloud DeckはREST APIを呼び出すので、もちろんインターネットに接続する必要がありますが、ESP32のオンボードWiFiを使用することで必要な接続を得ることができました。


    ESP-32マイクロコントローラ(リンク)

    Cherry MX Blueキースイッチ (リンク)

    Relegendableキーキャップ (リンク)

    M3 0.50×10mmボルト (リンク)

    直角ヘッダー (リンク)

    24gaワイヤ、はんだ


ケースの印刷と組み立て

Stream Cheapのオリジナルケースは、ESP-32を入れるには浅すぎました。

そこで、Thingiverseで「Teensy StreamDeck (Mini Macro Keyboard)」という気に入った代替品を見つけたので、それをダウンロードしてTinkerCadに取り込み、自分のニーズに合わせて少し修正しました。

最終的にはもっと背の高いものになりましたが、それでも机の上に置いても違和感のない程度には小さくなりました。これが私のバージョンのベースです。

ESP-32を使って自宅でプレイする場合は、私のバージョンのベースと、Teensy StreamDeckのプレート(ファイル名「stream_deck_plate」)を印刷してください。デザインが完成したら、Ender 3でプリントアウトしてみました。


キーキャップアイコンの印刷

私はあまり絵心がないので、キーキャップにはフリーのアイコンを使いました(FlaticonFreePikさんに感謝)。アイコンをダウンロードして、15mm×15mm程度に縮小して印刷しました。

それをキーキャップに合わせてトリミングし、デッキを組み立てるときに挿入しました。


クラウドデッキの組み立て

キーをESP32に接続する作業は、Stream Cheapチュートリアルと全く同じ手順で行いました。

各キーからの1本のリード線を直列に接続してからグランドピンに接続し、各キーからのもう1本のリード線をESP32の個別のGPIOピンに接続しました。


ESP32のプログラミング

Cloud Deckを完全に自給自足のスタンドアローンなデバイスにしたかったので、まずはマイコンデバイスからOCI REST APIを直接呼び出す方法を見つける必要がありました。Arduino/C++用の公式SDKはないので、ゼロからのスタートとなりました。

これはちょっとした作業だったので、独自のプロジェクトになりました。Cloud Deckを自作する場合は、まずそのプロジェクトについて読み、そのライブラリに慣れるようにしてください。


OCI REST APIを直接呼び出すためのライブラリができたら、あとは自分のCloud Deckに入れたい機能を決めて、キーを押したときに反応して必要なREST APIを呼び出すスケッチを作るだけです(ドキュメントのUsing OCI REST APIs and REST API Endpointsを参照)。

Cloud Deckでは以下のような作業を行うことにしました。

1. テナント情報の入力

2. ユーザーの詳細なプロフィール情報の表示

3. ユーザーが登録したAPIキーの一覧表示

4. DBインスタンスの詳細一覧

5. DB インスタンスの直近のバックアップ情報の取得

6. 新規VMの起動

7. QA/テスト環境の起動(VMとDBインスタンスの両方

8. QA/テスト環境の停止(VMとDBインスタンスの両方)


もちろんそのためには、取得した情報を印刷したり、自動化されたタスクの完了をフィードバックする方法が必要になります。そのためには、情報を簡単に配信できるOCI Notificationsが最適だと考えました。

専用のチャンネルに投稿するカスタムSlackアプリは素晴らしい選択肢のように思えましたが、Eメールのサブスクリプションを使用したり、必要であればサーバーレスのOracle Functionへのコールを開始することもできました。


すぐに冗長になってしまうので、この記事ではすべてのAPIコールを説明しません。

基本的には、コードには、OCI APIオブジェクトのインスタンスを作成するために必要ないくつかの変数、必要なREST APIを呼び出すためのFunctionの作成、(ArduinoJsonを使用して)返されたデータの解析、そして通知を送信するための通知APIの呼び出しが含まれています(これには、通知トピックにサブスクライブされたカスタムSlackアプリがあります)。

上記のように、OCI REST APIを呼び出すプロセスは、私の以前の投稿で詳細に説明されていますので、ライブラリに慣れるために、ぜひそれを読んでみてください


通知のルール  「Complete Developer's Guide to the Oracle Notifications Service」をチェックすべきです!


ここでは、REST APIを呼び出して、最初のキーが押されたときにテナントの情報を取得する方法を紹介します。

void getTenancyInfo() {
  char tenancyInfoPath[150] = "/20160918/tenancies/";
  strcat(tenancyInfoPath, tenancyOcid);
  
  OciApiRequest tenancyInfoRequest(iamHost, tenancyInfoPath, oci.HTTP_METHOD_GET, {}, 0, NULL);
  OciApiResponse tenancyInfoResponse;
  oci.apiCall(tenancyInfoRequest, tenancyInfoResponse);
  if( tenancyInfoResponse.statusCode == 200 ) {
    StaticJsonDocument<300> filter;
    filter["name"] = true;
    filter["id"] = true;
    filter["homeRegion"] = true;
    filter["homeRegionKey"] = false;
    filter["compartmentId"] = false;
    filter["description"] = false;
    filter["oracleMyServicesIdentifier"] = true;
    filter["timeCreated"] = false;
    
    DynamicJsonDocument doc(300);
    deserializeJson(doc, tenancyInfoResponse.response, DeserializationOption::Filter(filter));
    if(DEBUG_MODE){
      Serial.println(F("Tenancy Info JSON Doc (Filtered):"));
      serializeJsonPretty(doc, Serial);  
      Serial.println();  
    }
    char message[250] = "*Tenancy Info:* \n";
    strcat(message, "Name: ");
    strcat(message, doc["name"]);
    strcat(message, "\n");
    strcat(message, "OCID: ");
    strcat(message, doc["id"]);
    strcat(message, "\n");
    strcat(message, "Home Region: ");
    strcat(message, doc["homeRegion"]);
    strcat(message, "\n");
    strcat(message, "Support ID: ");
    strcat(message, doc["oracleMyServicesIdentifier"]);
    strcat(message, "\n");
    sendNotification((char*) message);
  }
  else {
    if(DEBUG_MODE){
      Serial.println(tenancyInfoResponse.statusCode);
      Serial.println(tenancyInfoResponse.errorMsg);
    }
  }

}


ご覧のように、APIリクエストとレスポンスのオブジェクトを構築し、OCIライブラリのapiCall()メソッドを呼び出し、レスポンスを処理しています。

呼び出しが成功した場合は、sendNotification()メソッドを呼び出し、API呼び出しの結果を含む文字列を渡しています。

void sendNotification(char* notification) {
  char notificationPath[150] = "/20181201/topics/";
  strcat(notificationPath, notificationTopicOcid);
  strcat(notificationPath, "/messages");
  
  char message[350] = "";
  {
    DynamicJsonDocument messageJson(350);
    messageJson["title"] = "Cloud Deck Notification";
    messageJson["body"] = notification;
    serializeJson(messageJson, message);
  }
  
  OciApiRequest sendNotificationRequest(notificationHost, notificationPath, oci.HTTP_METHOD_POST, {}, 0, NULL, message);
  OciApiResponse sendNotificationResponse;
  oci.apiCall(sendNotificationRequest, sendNotificationResponse);
  if( sendNotificationResponse.statusCode == 202 ) {
    DynamicJsonDocument doc(500);
    deserializeJson(doc, sendNotificationResponse.response);
    if(DEBUG_MODE){
      Serial.println(F("Send Notification Response:"));
      serializeJsonPretty(doc, Serial);  
      Serial.println();
    }
  }
  else {
    if(DEBUG_MODE){
      Serial.println(sendNotificationResponse.statusCode);
      Serial.println(sendNotificationResponse.errorMsg);
    }
  }
}



私が作ったライブラリを使ってREST APIを呼び出すのは、実に簡単だと思います。必要なHTTPコールに署名して作成する基本的なライブラリで、どのエンドポイントを呼び出したいかを伝えるだけです。


Cloud Deckのテスト


Cloud Deckを組み立て、スケッチをアップロードしたら、電源を入れてテストしてみました。動作の概要をビデオでご紹介します。




まとめ

この記事では、OCIのテナントから情報を取得したり、タスクを自動化するための便利なスタンドアロンデバイスを作った方法を紹介しました。

このようなデバイスの可能性は無限大です。他にどんなことができるでしょうか?


  •     アラームの確認
  •     テナントの請求書を監視し、請求書のサマリーを送る
  •     クラウド上のあらゆるものを起動/開始/停止
  •     サーバーレス機能の呼び出し
  •     稼働中のデータベースの把握
  •     Oracleストリームへの発行/ストリームからの消費


自分のテナントを自動化し、生活を少しでも楽にするために、自分のCloud Deckを作ってみることをお勧めします。

もし構築されたら、以下にコメントを残すか、Twitterで私と共有してください。あなたが作ったものを共有したいので、ぜひ教えてください。


コードを見せてください  私のCloud Deckのコードをご覧になりたい方は、GitHubのリポジトリ(https://github.com/recursivecodes/cloud-deck)をご覧ください。


コメント

このブログの人気の投稿

Oracle RACによるメンテナンスのためのドレインとアプリケーション・コンティニュイティの仕組み (2023/11/01)

Oracle Cloud Infrastructure Secure Desktopsを発表: デスクトップ仮想化のためのOracleのクラウドネイティブ・サービス (2023/06/28)

新しいOracle Container Engine for Kubernetesの機能強化により、大規模なKubernetesがさらに簡単になりました (2023/03/20)