SwitchBot防水温湿度計のBluetoothデータ読み込みを試しましたが、SwitchBox APIのデータ読み込みも試しました。#自分の忘備録44
結果から
SwitchBot防水温湿度計だけで、SwitchBox APIを使用して温度湿度のデータが読み込めると思っていませんでしたが、それは出来なかった。
- SwitchBot防水温湿度計の温度湿度データはSwitchBoxアプリで確認出来るので、SwitchBox APIを使用しても読み込めると勘違いしていた
- それは、Fitbitトラッカーの各種データはFitbitアプリで確認出来て、Fitbit APIでも読み込みが出来るので、それと同様かと思っていた
各デバイスのデータの流れ
Fitbit Trackerの場合
Fitbit ---(ble)--> Fitbit ---(web)--> Fitbit --(webapi)--> [PC]
Tracker App Cloud
※今は、Fitbit App → Google Health App、Fitbit Cloud → Google Cloud、昔のTrackerはFitbitのままだが新しいのはGoogle Fitbit
- データの流れ
- TrackerからAppにBLEでデータが転送される
- 通常はリアルタイム的に表示されるデータのみが転送される模様
- 〇Appの同期操作で全データがAppに転送され、Cloudにも転送されている模様
- TrackerからAppにBLEでデータが転送される
- データ読み込み
- 〇WebAPIでCloudに転送されたデータを読み出せる
SwitchBot防水温湿度計の場合
SwitchBot --+--(ble)--> SwitchBot ---(web)--> SwitchBot ---(webapi)--> [PC]
Sensor | App Cloud
|
+--(ble)--> [PC]
- データの流れ
- SensorからAppにBLEでデータが転送される
- 通常はリアルタイム的に表示されるデータのみが転送される模様
- △Appの同期操作で全データがAppに転送され、ここでCloudにも転送されている?と思った(これが違ったみたい)
- SensorからAppにBLEでデータが転送される
- データ読み込み
- △WebAPIでCloudからデータが読み出せるが、どうもデバイスタイプ情報だけ(温度湿度は0で格納されていないことかな)
- 〇BLEアドバタイズデータで直接Sensorからデータを読み出せる
SwitchBot防水温湿度計の場合はこうするみたい
どうも温度湿度データをWebAPIで読み出すには、SwitchBot Hubも使わないといけないみたい。
今度、SwitchBot Hubを購入することがあったら試してみることにする。
+--(ble)--> SwitchBot ---(web)--> --+
| Hub |
| v
SwitchBot --+--(ble)--> SwitchBot ---(web)--> SwitchBot ---(webapi)--> [PC]
Sensor | App Cloud
|
+--(ble)--> [PC]
- データの流れ
- SensorからAppにBLEでデータが転送される
- 通常はリアルタイム的に表示されるデータのみが転送される模様
- 恐らく、Appからはデバイスタイプ情報だけがCloudに登録されて、データはHubによりリアルタイム的にCloudにも転送されてのではないかと
- SensorからAppにBLEでデータが転送される
- データ読み込み
- たぶん、WebAPIでCloudからデータが読み出せるようになるものかと
- BLEアドバタイズデータで直接Sensorからデータを読み出せる
SwitchBox APIでデータ取得プログラム
以下のGetting Startedのページを参考にして、テスト用のpython、JavaScript、C#のプログラムを作成した。テストプログラムなので、エラー処理なしで同期的動作にしている。
WebAPIなのでどの言語でプログラムを作成しても結果は同じですが、暇だったので試す![]()
OpenWonderLabs / SwitchBotAPI - SwitchBot API v1.1
Pythonテストプログラム
テストコード
import json
import time
import hashlib
import hmac
import base64
import uuid
import requests
# Declare empty header dictionary
apiHeader = {}
# open token
token = 'tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt' # copy and paste from the SwitchBot app V6.14 or later
# secret key
secret = 'ssssssssssssssssssssssssssssssss' # copy and paste from the SwitchBot app V6.14 or later
nonce = uuid.uuid4()
t = int(round(time.time() * 1000))
string_to_sign = '{}{}{}'.format(token, t, nonce)
string_to_sign = bytes(string_to_sign, 'utf-8')
secret = bytes(secret, 'utf-8')
sign = base64.b64encode(hmac.new(secret, msg=string_to_sign, digestmod=hashlib.sha256).digest())
##print ('Authorization: {}'.format(token))
##print ('t: {}'.format(t))
##print ('sign: {}'.format(str(sign, 'utf-8')))
##print ('nonce: {}'.format(nonce))
#Build api header JSON
apiHeader['Authorization']=token
apiHeader['Content-Type']='application/json'
apiHeader['charset']='utf8'
apiHeader['t']=str(t)
apiHeader['sign']=str(sign, 'utf-8')
apiHeader['nonce']=str(nonce)
url = 'https://api.switch-bot.com/v1.0/devices'
rsp = requests.get(url, headers=apiHeader)
print(f'status_code={rsp.status_code}')
print(rsp.json())
data = json.loads(rsp.content)
deviceId = data['body']['deviceList'][0]['deviceId']
print(f'deviceId={deviceId}')
url = f'https://api.switch-bot.com/v1.0/devices/{deviceId}/status'
rsp = requests.get(url, headers=apiHeader)
print(f'status_code={rsp.status_code}')
print(rsp.json())
(実行例)
>cd C:\TEST
>python -m venv switchbotapi
>cd switchbotapi
>Scripts\activate.bat
(switchbotapi) >pip install requests
(switchbotapi) >python -V
Python 3.14.6
(switchbotapi) >python SwitchBotAPI.py
status_code=200
{'statusCode': 100, 'body': {'deviceList': [{'deviceId': 'XXXXXXXXXXXX', 'deviceName': '防水温湿度計 3C', 'deviceType': 'WoIOSensor', 'enableCloudService': False, 'hubDeviceId': ''}], 'infraredRemoteList': []}, 'message': 'success'}
deviceId=XXXXXXXXXXXX
status_code=200
{'statusCode': 100, 'body': {'version': 'V0.9', 'temperature': 0, 'battery': 0, 'humidity': 0, 'deviceId': 'XXXXXXXXXXXX', 'deviceType': 'WoIOSensor', 'hubDeviceId': '000000000000'}, 'message': 'success'}
(switchbotapi) >
JavaScriptテストプログラム
テストコード
const crypto = require("crypto");
const https = require("https");
const token = "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt";
const secret = "ssssssssssssssssssssssssssssssss";
function getHeaders() {
const t = Date.now();
const nonce = "requestID";
const data = token + t + nonce;
const sign = crypto.createHmac("sha256", secret).update(data).digest("base64");
return {
Authorization: token,
sign: sign,
nonce: nonce,
t: t,
"Content-Type": "application/json",
};
}
function makeRequest(path) {
return new Promise((resolve, reject) => {
const options = {
hostname: "api.switch-bot.com",
port: 443,
path: path,
method: "GET",
headers: getHeaders(),
};
const req = https.request(options, (res) => {
let data = "";
res.on("data", (d) => {
data += d;
});
res.on("end", () => {
console.log(`statusCode=${res.statusCode}`);
console.log(data);
resolve(JSON.parse(data));
});
});
req.on("error", (error) => {
reject(error);
});
req.end();
});
}
async function main() {
const response = await makeRequest("/v1.1/devices");
const deviceId = response.body.deviceList[0].deviceId;
console.log(`deviceId=${deviceId}`);
await makeRequest(`/v1.1/devices/${deviceId}/status`);
}
main();
(実行例)
>cd C:\TEST\switchbotapi
>node -v
v24.15.0
>node SwitchBotAPI.js
statusCode=200
{"statusCode":100,"body":{"deviceList":[{"deviceId":"XXXXXXXXXXXX","deviceName":"防水温湿度計 3C","deviceType":"WoIOSensor","enableCloudService":false,"hubDeviceId":""}],"infraredRemoteList":[]},"message":"success"}
deviceId=XXXXXXXXXXXX
statusCode=200
{"statusCode":100,"body":{"version":"V0.9","temperature":0,"battery":0,"humidity":0,"deviceId":"XXXXXXXXXXXX","deviceType":"WoIOSensor","hubDeviceId":"000000000000"},"message":"success"}
>
C#テストプログラム
テストコード
using System;
using System.Text;
using System.Text.Json;
using System.Security.Cryptography;
using System.Net.Http;
using System.Threading.Tasks;
class Program
{
private static HttpClient client = new HttpClient();
private static string token = "tttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttttt";
private static string secret = "ssssssssssssssssssssssssssssssss";
private static DateTime dt1970 = new DateTime(1970, 1, 1);
private static DateTime current = DateTime.Now;
private static TimeSpan span = current - dt1970;
private static long time = Convert.ToInt64(span.TotalMilliseconds);
private static string nonce = Guid.NewGuid().ToString();
private static string data = token + time.ToString() + nonce;
private static Encoding utf8 = Encoding.UTF8;
private static HMACSHA256 hmac = new HMACSHA256(utf8.GetBytes(secret));
private static string signature = Convert.ToBase64String(hmac.ComputeHash(utf8.GetBytes(data)));
static void Main(string[] args)
{
string content = Req("/v1.1/devices");
var devices = JsonSerializer.Deserialize<Devices>(content);
string deviceId = devices.body.deviceList[0].deviceId;
Console.WriteLine($"deviceId={deviceId}");
Req($"/v1.1/devices/{deviceId}/status");
}
public static string Req(string path)
{
var request = new HttpRequestMessage(HttpMethod.Get, $"https://api.switch-bot.com{path}");
request.Headers.TryAddWithoutValidation("Authorization", token);
request.Headers.TryAddWithoutValidation("sign", signature);
request.Headers.TryAddWithoutValidation("nonce", nonce);
request.Headers.TryAddWithoutValidation("t", time.ToString());
var res = client.SendAsync(request).Result;
string content = res.Content.ReadAsStringAsync().Result;
Console.WriteLine($"StatusCode={res.StatusCode}");
Console.WriteLine(content);
return content;
}
//{"statusCode":100,"body":{"deviceList":[{"deviceId":"XXXXXXXXXXXX","deviceName":"防水温湿度計","deviceType":"WoIOSensor","enableCloudService":false,"hubDeviceId":""}],"infraredRemoteList":[]},"message":"success"}
public class DeviceList
{
public string deviceId { get; set; }
public string deviceName { get; set; }
public string deviceType { get; set; }
public bool enableCloudService { get; set; }
public string hubDeviceId { get; set; }
}
public class Body
{
public List<DeviceList> deviceList { get; set; }
public List<object> infraredRemoteList { get; set; }
}
public class Devices
{
public int statusCode { get; set; }
public Body body { get; set; }
public string message { get; set; }
}
}
(実行例)
>cd C:\TEST\switchbotapi
>dotnet new console -n sb
>cd sb
>dotnet build
>bin\Debug\net10.0\sb.exe
StatusCode=OK
{"statusCode":100,"body":{"deviceList":[{"deviceId":"XXXXXXXXXXXX","deviceName":"防水温湿度計","deviceType":"WoIOSensor","enableCloudService":false,"hubDeviceId":""}],"infraredRemoteList":[]},"message":"success"}
deviceId=XXXXXXXXXXXX
StatusCode=OK
{"statusCode":100,"body":{"version":"V0.9","temperature":0,"battery":0,"humidity":0,"deviceId":"XXXXXXXXXXXX","deviceType":"WoIOSensor","hubDeviceId":"000000000000"},"message":"success"}
>