TaskerからSwitchBotのAPIを使ってテレビを操作

## 🕑 更新履歴
- 2025/3/13 : ヘッダー作成のJavascriptが動かなくなってしまったので修正。全体を通して再度整理しました

## 🔥 やりたいこと

スマホ（Android）をシェイクしてテレビを消したりしたい！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670662/9900cf14-37fa-a544-01ff-1bea38e5e6a8.png)

## 📦 準備

### 必要なアプリ

https://play.google.com/store/apps/details?id=net.dinglisch.android.taskerm

https://play.google.com/store/apps/details?id=com.theswitchbot.switchbot

## 🔐 SwitchBotAPIのトークンとシークレットキーを取得
SwitchBotAPIを使うために必要なトークンとシークレットキーを取得します。

1. 右下のプロフィールボタンをタップ
1. 設定 > 基本データ > アプリバージョンを10回タップ
1. 開発者向けオプションが出現

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670662/530301e4-ec5c-4065-be93-87a7bb5910b2.png" width="300px">

詳細は公式サイトBlogへ(手順や画面が古いです)↓

https://blog.switchbot.jp/announcement/api-v1-1/

## ⚙️ Taskerでタスクを作成

必要なタスクを作成していきます。最低限必要なものを紹介します。

- ヘッダー作成
- デバイスID取得
- デバイス操作

デバイスID取得は、デバイスの操作をするタスクを作成する際に一度だけ使用することになります。

### ヘッダー作成 [SwitchBot_ヘッダー作成]

まず、APIの使用に必要なヘッダーを作成します。これは他タスクでも使用するため、「リターン」でヘッダーを呼び出せるようにします。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670662/ff1d2762-cd7d-472b-9a55-3b5bb58e4bc9.png" width="300px">

#### 1. Javascript(小) / JavaScriptlet

JavaScriptを使用して、APIに必要なヘッダーを作成します。

```javascript:コード(トークンとシークレットキーは先で取得したものに書き換えてください)
// SwitchBotアプリで取得したトークン、シークレットキーを入力
const token = "トークン";
const secret = "シークレットキー";

// タイムスタンプを取得
const t = Date.now();

// トークンとタイムスタンプを結合してHMAC-SHA256生成
const hmac = CryptoJS.HmacSHA256(`${token}${t}`, secret);

// ハッシュ値のバイト列をbase64エンコード
const sign = CryptoJS.enc.Base64.stringify(hmac);

// ヘッダを作成
const headers = {
    "Content-Type": "application/json",
    "Authorization": token,
    "sign": sign,
    "t": String(t)
};

// ヘッダをTasker用に加工し変数に格納
setLocal("switch_bot_header", JSON.stringify(headers).replace(/,/g, "\n").replace(/\{|\}|\"/g, ""));
```
 
```text:ライブラリ
https://cdnjs.cloudflare.com/ajax/libs/crypto-js/3.1.9-1/crypto-js.min.js
```

<details><summary>解説</summary>

SwitchBotのAPIを使用するには、以下手順を踏みます。
1. 13桁のタイムスタンプ(UTCでの1970/1/1 0:0:0から現在までの経過時間をミリ秒)とトークンを結合します
1. シークレットキーと前の手順で生成された文字列を使用して署名を作成します
1. 署名を大文字に変換する

JavaScriptで実装していきます。

ポイントは最終行のreplaceで文字置換している箇所。Json文字列をそのままヘッダとして使えず、Tasker独自の書式に書換えが必要です。具体的には以下の通りです。
1. カンマ区切りを改行に置換
1. 波括弧、ダブルクォーテーションを削除

```json:Before
{"Content-Type":"application/json","Authorization":"承認","sign":"署名","t":"1685093231634"}
```
```ya:After
Content-Type:application/json
Authorization:承認
sign:署名
t:1685093231634
```

</details>

#### 2. リターン / Return

他のタスクから実行したときの戻り値を、作成したヘッダー文字列にします。

```text:値
%switch_bot_header
```


### デバイスID取得 [SwitchBot_デバイスID取得]

デバイスを操作するために、デバイスIDを取得します。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670662/d8aa42a0-9265-4b77-818f-bde00a663ce8.png" width="300px">

タスクを実行すると以下のように、デバイス名一覧が表示され、タップすることでクリップボードにデバイスIDがコピーされます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670662/d3493c55-3d06-4dcf-996b-d0089809dc82.png" width="300px">

#### 1. タスク実行 / Perform Task

先に作成したタスクを実行してヘッダーを取得します。

```text:名前
SwitchBot_ヘッダー作成
```

```text:戻り値の変数
%switch_bot_header
```

#### 2. HTTP リクエスト

SwitchBotのAPIでデバイスリストを取得します。

```text:方式
GET
```

```text:URL
https://api.switch-bot.com/v1.1/devices
```

```text:ヘッダー
%switch_bot_header
```

#### 3. 変数を設定 / Variable Set

取得したデバイスリストのbodyの値を変数に格納します。

```text:名前
%devices
```

```text:これに
%http_data.body 
```

#### 4. 変数を設定 / Variable Set

プラグミニなどのデバイス（deviceList）とハブミニなどで設定したリモコン（infraredRemoteList）が別リストのため結合して扱いやすくします。

```text:名前
%devices
```

```text:これに
{
  "list": [
    %devices.deviceList(),
    %devices.infraredRemoteList()
  ]
}
```

#### 5. For (繰り返し開始) 

前で作成したリストを順番に取り出します。

```text:変数
%device_info
```

```text:項目
devices.list() 
```

#### 6.配列に追加 / Array Push

デバイス名だけを取得し、配列に追加します。この時、位置を9999と大きい数字にして、配列の後ろに追加しています。

```text:変数の配列
%device_names
```

```text:位置
9999
````

```text:値
%device_info.deviceName
```

#### 7. End For(繰り返し終了)

設定なし

#### 8. リストのダイアログ / List Dialog

作成したデバイス名の配列を使用して、リストのダイアログを作成します。

```text:タイトル
SwitchBot devices
```

```text:項目
%device_names
```

#### 9. 変数を設定 / Variable Set

リストで選択された、デバイス情報を取り出します。

```text:名前
%device
```

```text:これに
%devices.list(%ld_selected_index)
```

#### 10. フラッシュ表示 / Flash

確認の表示をします。

```text:文字
%device.deviceName のデバイスIDをコピーしました。%device.deviceId
```

#### 11. クリップボードにコピー / Set Clipboard

デバイスIDをクリックボードにコピーします。

```text:文字
%device.deviceld
```

<details><summary>解説</summary>

機器を操作するため、固有のデバイスIDを調べる必要があります。先に作成したヘッダーを使って、以下URLにアクセスすることでリストを取得することができます。
https://api.switch-bot.com/v1.1/devices

入手できる情報としては、以下のような情報で、使用するのはdeviceIdとなる。

```json:TVのデバイス情報
{
   "deviceId": "00-202123456789-12345678",
   "deviceName": "テレビSwitchBot",
   "remoteType": "TV",
   "hubDeviceId": "ABCDEFGHIJKL"
}
```

デバイスによって出力される内容が異なるので、以下を参照してください。
https://github.com/OpenWonderLabs/SwitchBotAPI?tab=readme-ov-file#get-device-list

Taskerとしては、上記のデバイスリストを加工してリストのダイアログに流し込んでいます。
選択したIndexから選択したデバイスのdeviceIdを取得しクリップボードに送っています。

Jsonから直接読み取ってもよいですが、デバイスが増えると大変なので、少々面倒ですが、このやり方をしています。

</details>



### デバイス操作 [SwitchBot_デバイス操作]

ここでやっと、操作に入れます。

<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670662/dffc2863-e3b8-489e-b93e-01ceba357aa8.png" width="300px">

#### 1. タスク実行 / Perform Task

先に作成したタスクを実行してヘッダーを取得します。

```text:名前
SwitchBot_ヘッダー作成 
```

```text:戻り値の変数
%switch_bot_header
```

#### 2. 変数を設定 / Variable Set 

デバイス一覧からコピーしてきたデバイスIDを変数に設定します。

```text:名前
%device_id
```

```text:これに
コピーしたデバイスIDを張り付ける
```

#### 3. HTTP リクエスト / Request 

デバイスの操作をAPIに送ります。これでデバイスが動いていればOKです！

```text:方式
POST
```

```text:URL
https://api.switch-bot.com/v1.1/devices/%device_id/commands
```

```text:ヘッダー
%switch_bot_header
```

```json:本文
{
  "command": "turnOn",
  "parameter": "default",
  "commandType": "command"
}
```

:::note info
本文（Body）に記述しているコマンドは、操作したい機器によって変わります。
https://github.com/OpenWonderLabs/SwitchBotAPI#send-device-control-commands
:::


<details><summary>解説</summary>

先に作成したヘッダーとデバイスIDを使って、以下URLにアクセスすることデバイスを操作できます。
https://api.switch-bot.com/v1.1/devices/デバイスID/commands

その際、本文（Body）に操作する内容を入れていきます。
こちらも、デバイスによって出力される内容が異なるので、以下を参照してください。
https://github.com/OpenWonderLabs/SwitchBotAPI?tab=readme-ov-file#send-device-control-commands

</details>

## 🤖 TaskerでProfilesを作成
ここは自由に作成してみてください。
私は、誤動作を防ぐため、ホーム画面の状態＆自宅Wifiに接続＆スマホシェイクという条件にしてみました。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2670662/e1ca479a-005c-5494-cb0c-24a9236ed558.png)

## 👐 最後に
今回はテレビの電源オフを題材にしましたが、もちろん他の家電、操作も可能です。さらに、SwitchBotアプリで作成したシーンも実行できますのでアイデア次第で何でもできそうです。
是非皆様もやってみてください。

https://github.com/OpenWonderLabs/SwitchBotAPI

最近、TaskerのWidget V2が出たので、Widgetから操作するやり方も書いていきたいです。