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?

はじめてのAWSAdvent Calendar 2024

Day 1

冬の朝をもっと快適に!AWS×Nature Remoで実現するエアコン自動化プロジェクト

Last updated at Posted at 2025-01-01

1.はじめに

こんにちは!寒い日が続いていますね。私自身、寒さが苦手で、特に冬の朝は布団から出るのが本当に大変です。そこで、朝起きる少し前にエアコン(暖房)を自動でONにして、快適な目覚めを迎えられる仕組みを作りました。詳しい手順は、以下の記事で紹介していますので、ぜひ参考にしてください。

この仕組みでは、スマートリモコン「 Nature Remo 」と Google Cloud Platform(GCP) の「 Cloud Run 」と「 Cloud Scheduler 」を使って、この仕組みを実現しました。その際の記事では、最後に次のような注意点を書きました。

「エアコンの電源制御は、仮に仕組みが止まっても大きな問題は起こりませんが、業務に関わる重要なシステムで同様の仕組みを導入する場合はリスク対策が必要です。たとえば、今回使用したGoogle CloudのCloud RunやCloud Schedulerだけに依存するのではなく、他のサービスを併用したり、切り替えが可能な構成にするのも一つの方法です。その際は、三大クラウドである AWS(Amazon Web Services)、Azure(Microsoft Azure)、GCP(Google Cloud Platform) のいずれかを併用するのが効果的です。」

そこで今回は、 AWS(Amazon Web Services) を使って同様の仕組みづくりに挑戦します。具体的には、 AWS LambdaAWS App RunnerAmazon EventBridge を活用して、特定の時間になったらエアコンを自動でONにする仕組みを構築していきます。

さて、ここで「Nature Remoの公式アプリを使えば簡単にスケジュールを設定してエアコンをONにできるのでは?」と思う方もいるかもしれません。その通りです。実際、公式アプリを使うだけでスケジュール機能は十分に活用できます。

しかし、今回わざわざ面倒な方法を選択しているのには理由があります。それは、AWS LambdaやAmazon EventBridgeを学び、実践することを目的としているからです。このプロジェクトでは、単にエアコンを操作する仕組みを作るだけでなく、クラウド技術への理解を深めることを目指しています。これらの技術を活用すれば、エアコン以外の家電やシステムにも応用できる可能性が広がります。「効率」だけを追求するなら、公式アプリを使うのが簡単です。しかし、学びのためにあえて「回り道」を選び、新しい技術に挑戦してみたいと思いました。

2.Nature Remoとは

image.png
(引用元: Nature公式サイト

Nature Remoは、Nature株式会社が提供するスマートリモコンです。家電をスマートフォンや音声で操作できるスマートリモコンです。赤外線リモコンを一元化し、温度・湿度・照度・人感センサーを搭載。スマートスピーカー(Google Home、Amazon Echo、Apple HomePod)と連携し、オートメーション機能を活用して自動操作が可能です。既存の家電を簡単にIoT化し、快適なスマートホーム環境を実現します。

なお、今回はNature Remoの初期設定方法については触れません。初期設定について詳しくは、公式ページをご覧ください。

3.Nature Remoを操作する方法

この記事では、Nature RemoのAPIをNode.jsを使って操作する方法について説明します。コードの説明、アクセストークンの取得方法や事前の設定については、以前の記事を参考にしてください。

また、ファイルの拡張子は .mjs に設定してください。これは、Lambda上で正しく動作させるための重要なポイントです。拡張子が.jsのままだと、Lambdaがモジュール形式を正しく認識できず、エラーが発生することがあります。.mjsを使うことで、ESモジュール形式として認識され、正常に動作します。

3.1.エアコンの電源をOFFにするコード

以下のコードは、Nature RemoのAPIを使ってエアコンの電源をOFFにするものです。

import axios from 'axios';

// Nature Remo APIを動作させる関数を定義
async function setAirconSettings() {
	const token = '<3-1.アクセストークンを取得する で取得したトークン>'; // トークンを設定
    const deviceId = '<device_list.jsonで取得した登録している家電のID>'; // 家電のIDを設定
    const url = `https://api.nature.global/1/appliances/${deviceId}/aircon_settings`;
    
    try {
        // POSTリクエストを送信し、レスポンスを取得
        const response = await axios.post(
            url,
            'button=power-off', // データの内容を設定
            {
                headers: {
                    'Authorization': `Bearer ${token}`,
                    'accept': 'application/json',
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
            }
        );

        // ステータスコードが200の場合、レスポンスのデータを出力
        if (response.status === 200) {
            console.log('Nature Remo送信成功!');
            console.log('Response data:', response.data);
        } else {
            console.error('Unexpected status code:', response.status);
        }
    } catch (error) {
        // エラーが発生した場合
        console.error('Error:', error.message);
    }
}

// 関数を呼び出し
export const handler = async () => {
    await setAirconSettings();
};

3.2.エアコンの暖房モードを設定し、温度を24℃にするコード

次のコードでは、エアコンを暖房モードにし、温度を24℃に設定します。また、風量と風向きも自動調整に設定します。

import axios from 'axios';

// Nature Remo APIを動作させる関数を定義
async function setAirconSettings() {
    const token = '<3-1.アクセストークンを取得する で取得したトークン>'; // トークンを設定
    const deviceId = '<device_list.jsonで取得した登録している家電のID>'; // 家電のIDを設定
    const url = `https://api.nature.global/1/appliances/${deviceId}/aircon_settings`;
	// 送信するデータ
    const data = new URLSearchParams({
        operation_mode: 'warm',
        temperature: '24',
        temperature_unit: 'c',
        button: '',
        air_volume: 'auto',
        air_direction: 'auto',
        air_direction_h: 'auto',
    });

    try {
        // POSTリクエストを送信し、レスポンスを取得
        const response = await axios.post(
            url,
            data.toString(), // URLエンコードされたデータを送信
            {
                headers: {
                    'Authorization': `Bearer ${token}`,
                    'accept': 'application/json',
                    'Content-Type': 'application/x-www-form-urlencoded',
                },
            }
        );

        // ステータスコードが200の場合、レスポンスのデータを出力
        if (response.status === 200) {
            console.log('Nature Remo送信成功!');
            console.log('Response data:', response.data);
        } else {
            console.error('Unexpected status code:', response.status);
        }
    } catch (error) {
        // エラーが発生した場合
        console.error('Error:', error.message);
    }
}

// 関数を呼び出し
export const handler = async () => {
    await setAirconSettings();
};

3.3.エアコン操作APIの統合と活用

最後に、これまで紹介したエアコン操作の機能を統合し、APIとして提供するコード例をお見せします。このコードを使えば、エアコンの電源をオフにしたり、温度を設定したりする操作をWebリクエストを通じて簡単に実行できます。複数の機能を一つのコードベースにまとめているため、管理や拡張がしやすくなっています。なおこちらのコードのファイルの拡張子は .js に設定してください。

import axios from 'axios';
import express from 'express';
const app = express();

// トークンとデバイスIDを設定
const token = '<冬の朝をもっと快適に!Cloud Run×Cloud Scheduler×Nature Remoで実現するエアコン自動化プロジェクト で取得したトークン>'; // トークンを設定
const deviceId = '<device_list.jsonで取得した登録している家電のID>'; // 家電のIDを設定
const url = `https://api.nature.global/1/appliances/${deviceId}/aircon_settings`;


// 現在の日時を取得してフォーマットするヘルパー関数
function getCurrentDateTime() {
    const now = new Date();
    const options = {
        timeZone: 'Asia/Tokyo',
        year: 'numeric',
        month: '2-digit',
        day: '2-digit',
        hour: '2-digit',
        minute: '2-digit',
        second: '2-digit',
        fractionalSecondDigits: 3,
        hour12: false
    };
    return now.toLocaleString('ja-JP', options).replace(/\//g, '-').replace(',', '');
}

// 暖房をオフにする関数
async function turnHeatingOff(res) {
    const data = new URLSearchParams({
        button: 'power-off', // 電源オフボタン
    });

    try {
        console.log(`[${getCurrentDateTime()}] 暖房をオフにする操作開始...`);
        
        const response = await axios.post(url, data.toString(), {
            headers: {
                'Authorization': `Bearer ${token}`,
                'accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        });

        console.log(`[${getCurrentDateTime()}] 暖房をオフにする操作完了`);

        if (response.status === 200) {
            res.send('暖房をオフにしました!');
            console.log(`[${getCurrentDateTime()}] 操作成功: response.status = ${response.status}`);
            console.log(`[${getCurrentDateTime()}] Response data:`, response.data); // レスポンスデータを出力
        } else {
            res.status(500).send('暖房のオフ操作に失敗しました。');
            console.error(`[${getCurrentDateTime()}] 操作失敗: Unexpected status code ${response.status}`);
            console.error(`[${getCurrentDateTime()}] Response data:`, response.data); // レスポンスデータを出力
        }
    } catch (error) {
        res.status(500).send('暖房のオフ操作中にエラーが発生しました。');
        console.error(`[${getCurrentDateTime()}] エラー: ${error.message}`);
    }
}

// 暖房の温度を設定する関数
async function setHeatingTemperature(res, temperature) {
    const data = new URLSearchParams({
        operation_mode: 'warm',  // 暖房モード
        temperature: temperature.toString(),
        temperature_unit: 'c',
        air_volume: 'auto',
        air_direction: 'auto',
        air_direction_h: 'auto',
    });

    try {
        console.log(`[${getCurrentDateTime()}] 暖房の温度を${temperature}度に設定する操作開始...`);
        
        const response = await axios.post(url, data.toString(), {
            headers: {
                'Authorization': `Bearer ${token}`,
                'accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded',
            },
        });

        console.log(`[${getCurrentDateTime()}] 暖房の温度を${temperature}度に設定する操作完了`);

        if (response.status === 200) {
            res.send(`暖房の温度を${temperature}度に設定しました!`);
            console.log(`[${getCurrentDateTime()}] 操作成功: response.status = ${response.status}`);
            console.log(`[${getCurrentDateTime()}] Response data:`, response.data); // レスポンスデータを出力
        } else {
            res.status(500).send('温度設定に失敗しました。');
            console.error(`[${getCurrentDateTime()}] 操作失敗: Unexpected status code ${response.status}`);
            console.error(`[${getCurrentDateTime()}] Response data:`, response.data); // レスポンスデータを出力
        }
    } catch (error) {
        res.status(500).send('温度設定中にエラーが発生しました。');
        console.error(`[${getCurrentDateTime()}] エラー: ${error.message}`);
    }
}

// ルートエンドポイント
app.get('/', (req, res) => {
    res.send('暖房操作用APIにようこそ!');
});


// 暖房をオフにするルート
app.get('/heating/off', async (req, res) => {
    await turnHeatingOff(res);
});

// 暖房の温度を設定するルート(例:温度25度に設定)
app.get('/heating/temperature/:temp', async (req, res) => {
    const temperature = req.params.temp;
    await setHeatingTemperature(res, temperature);
});

// サーバーをポート8080で起動
const PORT = process.env.PORT || 8080;
app.listen(PORT, () => {
    console.log(`ac_automation_controller: listening on port ${PORT}`);
});

4.AWS Lambdaの設定方法

3.Nature Remoを操作する方法で紹介したコードは、同じネットワーク内でしか動作しません。つまり、外出先でエアコンを操作したい場合、http://localhost:8080/ では動作しません。これでは困りますよね。しかし、今回紹介する AWS Lambda を使えば、その悩みを解決できます。

AWS Lambdaを使えば、外出先でも自宅のエアコンを操作できるようになります。もちろん、いくつかの方から「同じネットワーク内で動けば十分だ」という意見があるかもしれません。しかし、もしこのステップを踏まないと、Amazon EventBridgeからエアコンのスケジュール実行ができなくなってしまいます。そのため、この章は必ず実施してください。基本的には公式ドキュメントの通りに行えば問題なくできますが、今回はその手順をわかりやすく解説します。

今回は、AWS(Amazon Web Services)のアカウント作成から、先ほど紹介したコードのデプロイまでを詳しく解説します。説明にはスクリーンショットを多用し、ステップごとに分かりやすく進めていきますので、安心して進めてください。

4.1.設定方法

1.公式サイトにアクセスし、新しいアカウントを作成してください。注意点として、以前に作成したアカウントを閉鎖してから90日以上経過している場合、そのアカウントは再開できません。 また、閉鎖した際に使用したメールアドレスは再利用できない点にもご注意ください。

2.アカウントの作成が完了したらホーム画面に行きます。画面左上にある検索窓に「Lambda」と入力し、検索結果から AWS Lambda を選択してください。
image.png

3.AWS Lambdaの画面に行くので「実行」ボタンを押下して、サンプルコードが動作するか確認してください
image.png

4.右上にある「関数の作成」ボタンを押下してください
image.png

5.関数名とランタイムを選択してください。今回はNode.jsのコードなので、「Node.js 22.x」を選択してください。完了したら「関数の作成」ボタンを押下してください
image.png

6.今回はエアコンの電源をOFFにする にする関数を作成します。

7.今回は、コマンドを使用してディレクトリを作成し、そのディレクトリに移動します。以下のコマンドを実行してください。

mkdir my_function
cd my_function

8.次に、以下のコマンドを実行して必要なライブラリをインストールしてください。

npm install axios

9.「3.1. エアコンの電源をOFFにするコード」をコピーし、index.mjs という名前のファイルに貼り付けて保存してください。その後、以下のファイルとフォルダを圧縮してください。

  • node_modules
  • index.mjs
  • package-lock.json

10.圧縮したファイルをアップロードしてください
image.png

8.次に表示された画面で、先ほど作成した「3. Nature Remoを操作する方法」のコードをコピーし、エディタ部分に貼り付けます。コードを貼り付けたら、画面にある「Deploy」ボタンをクリックしてデプロイを実行してください。
image.png

7.以下のメッセージが表示されたら成功です。
image.png

8.このコードを実行するために、「Create test event」ボタンを押下してください
image.png

9.「Event Name」を入力した後、「Save」ボタンをクリックしてください。
image.png

10.「TEST EVENTS」にある実行ボタンを押下してください。エアコンの電源がOFFになれば成功です。
image.png

11.「設定」と「関数URL」をクリックして、「関数URLを作成」をクリックしてください
image.png
image.png

12.「NONE」を選択してください、「保存」をクリックしてください
image.png

13.URLが発行されるので、外出先からでもこのURLを実行すればエアコンの操作ができます。
image.png

まとめ

これで、URLを通じてエアコンの操作ができるようになりました。ただし、 AWS LambdaはExpressを使用したルーティング処理には適していません。そのため、今回の「3.3. エアコン操作APIの統合と活用」のコードは、AWS Lambda上ではそのまま実行することができません。 よってExpressを使用したルーティング処理を使うためにはAWS App Runnerを使う必要があります。

5.AWS App Runnerの設定方法

この章では、AWS上でExpressを使ったルーティング処理を動作させる方法をご紹介します。具体的には、「3.3. エアコン操作APIの統合と活用」のコードを実際に動かす手順を解説します。今回は、AWS App Runnerを使用し、GitHub上のソースコードを活用してアプリを実行する方法を採用します。ほかにもいくつかの手法がありますが、調査した結果、この方法が最も簡単で実践しやすいと判断しました。それでは、具体的な手順を見ていきましょう。

5.1.設定方法

1.まずは、AWSに「AWS Connector for GitHub」というアプリをインストールする必要があります。そのためには、開発者ツールコンソールを開く必要があります。

2.「接続を作成」をクリックしてください
image.png

3.GitHubを選択して、接続名を入力して、「GitHub に接続する」をクリックしてください
image.png

4.「新しいアプリをインストールする」をクリックして、GithubとAWSを接続してください。接続が完了したら「接続」をクリックしてください。
image.png

5.GitHubに今回利用するコード専用のリポジトリを作成し、コードをPushしてください。具体的には、「3.3. エアコン操作APIの統合と活用」で紹介したコードをPushする形になります。

6.次にAWS App Runnerにコードをデプロイする方法を紹介します。ホーム画面から、画面左上にある検索窓に「AWS App Runner」と入力し、検索結果から AWS App Runner を選択してください。
image.png

7.「App Runner サービスを作成」をクリックしてください
image.png

8.「ソースコードリポジトリ」を選択して、先ほど作成したGitHub接続を選択します。レポジトリは今回使用するものを選択してください。デプロイ設定は「自動」を選択してください。その後、「次へ」をクリックして進みます。
image.png

9.「ここですべての設定を構成する」を選択して、ランタイムは「Nodejs 18」を選択して、構築コマンドは「npm install express axios」を入力して、開始コマンドは「node index.js」と入力してください。完了したら「次へ」をクリックしてください。
image.png

10.サービス名を入力して、「次へ」をクリックしてください。
image.png

11.「作成とデプロイ」をクリックしてください。
image.png

12.デプロイが完了するまで数分かかるので、待ってください。

13.デプロイが成功したら、下記のリンクをクリックしてください
image.png

14.以下のように表示されたら成功です。
image.png

15.エアコンを操作する際は、以下のルーティングを使用してください。

  • 暖房をオフにする場合
https://[8.で表示されているリンク]/heating/off
  • 暖房を24度に設定する場合
https://[8.で表示されているリンク]/heating/temperature/24

を実行してください。これで準備完了です。

16.「4. AWS Lambdaの設定方法」で説明した手順を参考に、今回作成されたURLをAWS Lambdaで実行できるように設定してください。以下に示したソースコードを使用して、設定を進めていきます。本来は、発行されたURLを使用してAmazon EventBridgeでスケジュール実行を行うことを予定していました。しかし、現状ではその設定が複雑で難しいため、代替案としてAWS Lambdaを使用することにしました。AWS Lambdaで、AWS App Runnerによって発行されたURLをGETリクエストで実行する方法が現時点ではより簡単で適切だと判断しました。今回は、この方法を採用して進めていきます。

import axios from 'axios';

// エアコン操作APIを呼び出す関数
async function executeGetRequest() {
    // リクエスト先のURL(適切なURLを設定してください)
    const url = 'https://[8.で表示されているリンク]/heating/off';

    try {
        // GETリクエストを送信
        const response = await axios.get(url, {
            headers: {
                'accept': 'application/json', // 必要に応じて適切なヘッダーを設定
            },
        });

        // ステータスコードが200の場合、レスポンスデータを出力
        if (response.status === 200) {
            console.log('GETリクエスト成功!');
            console.log('Response data:', response.data);
        } else {
            console.error('Unexpected status code:', response.status);
        }
    } catch (error) {
        // エラーが発生した場合の処理
        console.error('Error:', error.message);
    }
}

// 関数を呼び出し
export const handler = async () => {
    await executeGetRequest();
};

6.Amazon EventBridgeの設定方法

ここまで来たら、あともう一息です!残る作業は、Amazon EventBridgeの設定だけです。Amazon EventBridgeは、スケジュール実行を行うサービスです。実行のタイミングを細かく制御できるため、とても便利です。基本的には公式ドキュメントに従えば問題ありませんが、今回はより分かりやすく解説します。

6.1.設定方法

1.次にAmazon EventBridgeの設定方法を紹介します。ホーム画面から、画面左上にある検索窓に「Amazon EventBridge」と入力し、検索結果から Amazon EventBridge を選択してください。
image.png

2.「スケジュール」をクリックしてください
image.png

3.「スケジュールを作成」をクリックしてください
image.png

4.スケジュールを設定する際、まずスケジュール名を入力し、次に「定期的なスケジュール」を選択します。その後、タイムゾーンを「(UTC+09:00) Asia/Tokyo」に設定します。今回は月曜日から金曜日の日本標準時(JST)10:30に実行されるように、Cron式を設定します。このCron式は

30 10 ? * 2-6 

です。設定が完了したら「完了」をクリックしてください。
image.png

5.「AWS Lambda」を選択して、今回使用するLambda 関数を選択してください。今回は「ac_off」を選択してください。設定が完了したら「次へ」をクリックしてください。
image.png

6.次の画面でもそのまま「次へ」をクリックしてください。

7.すべてが完了したら「スケジュールを作成」をクリックしてください。これで月曜日から金曜日の日本標準時(JST)10:30に関数が実行されます。
image.png

まとめ

いかがでしたでしょうか?これで、毎日決まった時間にエアコン(暖房)を自動でONにできるようになり、快適な朝を迎えることができるようになりました。今回は、Nature Remo、AWS Lambda、AWS App Runner、Amazon EventBridgeの使い方を丁寧に解説したため、少し長文になってしまいましたが、ここまでお付き合いいただき、ありがとうございます。

今回の内容は、あくまでAmazon Web Services(AWS)のAWS Lambda、AWS App Runner、Amazon EventBridgeを使ったエアコンの電源制御に関するものでした。エアコンの電源制御は、仮に仕組みが止まっても大きな問題は起こりませんが、もし業務に関わる重要なシステムで同様の仕組みを導入する場合は、リスクへの備えが必要です。

たとえば、今回使用したAWS Lambda、AWS App Runner、Amazon EventBridgeだけに依存するのではなく、他のサービスを併用したり、切り替えが可能な構成にするのも一つの方法です。その際は、三大クラウドであるAWS(Amazon Web Services)、Azure(Microsoft Azure)、GCP(Google Cloud Platform)のいずれかを併用するのが効果的です。これらのクラウドサービスは利用者が多いため、トラブル時の情報が入手しやすいというメリットがあります。

GCP(Google Cloud Platform)を使った方法は前回私が書いた記事をご覧ください。

今回、AWS(Amazon Web Services)を利用してエアコン制御システムを開発しましたが、正直なところ、開発者目線では非常に難しいと感じる場面が多くありました。それに比べると、GCP(Google Cloud Platform)の方が操作が直感的で、開発がスムーズに進められた印象があります。

特にAWSでは、いくつかの点で苦労しました。例えば、AWS Lambdaでは関数を呼び出す際に、必ずexport const handlerという形式を含める必要があり、公式ドキュメントを読み込む必要がありました。また、AWS App Runnerで生成されたURLをそのままAmazon EventBridge上で実行することが難しく、最終的にAWS Lambdaを介して処理を行う方法に切り替える必要がありました。

それでも、AWS(Amazon Web Services)はクラウドサービス市場で非常に高いシェアを誇るため、利用方法を学んでおくことには大きな価値があると感じます。確かに難しい部分も多いですが、その分、使いこなせるようになれば非常に強力なツールになると実感しました。

最後までお読みいただき、ありがとうございました。

参考文献

スマートリモコンの仕組みとは?Natureスタッフが説明してみた。Nature公式サイト
アレクサとNature Remoでできること|照明やテレビを操作しよう - Nature
Nature RemoのAPIでターミナルから家電を操作してみた | DevelopersIO
Nature Remo API でエアコンを操作する(Slackでエアコン操作も) | yuu26-memo
Swagger UI - Nature Remo
Close an AWS account - AWS Account Management
What is AWS Lambda? - AWS Lambda
Deploy Node.js Lambda functions with .zip file archives - AWS Lambda
AWS/Azure/Google Cloudサービス比較 2023.12 #GoogleCloud - Qiita
What is AWS App Runner? - AWS App Runner
Create a connection to GitHub - Developer Tools console
[新機能] タイムゾーン指定でスケジュール起動できるAmazon EventBridge Schedulerがリリースされました | DevelopersIO
AWS Lambdaで遊ぼう #1 Lambda関数作成
Deploying Lambda functions as .zip file archives - AWS Lambda

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?