本シリーズ前回の記事 SwitchBot を ROS から利用する – データ取得編 掲載以降,手元にある SwitchBot デバイスの種類が増えてきました.
そこで今回の記事では switchbot_ros でまだ対応していないデバイスのデータを取得・パブリッシュするためにコードを追加する様子を紹介します.追加例としてデバイス「SwitchBot CO2センサー(温湿度計)」のデータを取得して ROS Topic としてパブリッシュできるようにします.
追加したいデバイスが SwitchBot API で対応していないと switchbot_ros 側でも対応はできないので最初に SwitchBot API のドキュメントを調べます.
SwitchBot API v1.1 ドキュメント にデバイスのリスト取得とステータス取得の項目に「Meter Pro CO2」の記述があり,これが今回追加してみたデバイス「SwitchBot CO2センサー(温湿度計)」に対応したものとなっていました.
制御コマンドの一覧には CO2 センサーらしき記述が(少なくとも本記事執筆時には)ありませんので「SwitchBot CO2センサー(温湿度計)」には取得系コマンドのみが対応していて,制御系コマンドは無いようです.
SwitchBot API ドキュメントにある「SwitchBot CO2センサー(温湿度計)」のステータス取得で返されるデータの表を下に抜粋しましたので確認してみます.
Key | Value Type | Description |
---|---|---|
deviceId | String | device ID |
deviceType | String | device type. MeterPro(CO2) |
hubDeviceId | String | device’s parent Hub ID |
battery | Integer | the current battery level, 0-100 |
version | String | the current firmware version, e.g. V4.2 |
temperature | Float | temperature in celsius |
humidity | Integer | humidity percentage |
CO2 | Integer | CO2 ppm value, 0-9999 |
二酸化炭素濃度が単位 [ppm](百万分率)で範囲 0〜9999 の整数型データとして返されることが分かります.他は SwitchBot の温湿度計と同じように各測定値が得られるようです.
switchbot_ros に機能追加したいデバイス「SwitchBot CO2センサー(温湿度計)」について SwitchBot API が対応していることと API により取得できる測定値が分かりましたので実装してゆきます.もう少し具体化すると「SwitchBot CO2センサー(温湿度計)」から API 経由で得られた
の4つの値を ROS Topic としてパブリッシュします.
SwitchBot API によるデータの取得と ROS Topic のパブリッシュプロセスは switchbot_ros にある既存のルーチンをそのまま利用できますので今回新たに実装する部分は大まかには次の2つです.
先に結論としてコードの追加部分を下に記載してしまいます.ファイルとしては3点,追加箇所としては5点です.
今回追加する「SwitchBot CO2センサー(温湿度計)」に対応したメッセージ型 MeterProCO2.msg を定義します.
パブリッシュする4つのデータ「温度」「湿度」「バッテリーレベル」「CO2濃度」のうち3つ 温度,湿度,バッテリーレベル は Meter.msg と同じなので Meter.msg を複製してファイル名を MeterProCO2.msg に変更して CO2濃度 のデータ型を追加する方法で作成しました.
switchbot_ros / msg / MeterProCO2.msg
1 2 3 4 5 6 7 | Header header # timestamp float64 temperature # temperature in celsius float64 humidity # humidity percentage float64 battery # the current battery level, 0-100 int64 co2ppm # CO2 ppm value, 0-9999 |
新しいメッセージ型を定義した場合はパッケージの CMakeLists.txt 内の add_message_files()
に追記する必要があります.
switchbot_ros / CMakeLists.txt
13 14 15 16 17 18 19 20 21 22 23 | add_message_files( FILES Device.msg DeviceArray.msg Meter.msg MeterProCO2.msg PlugMini.msg Hub2.msg Bot.msg StripLight.msg ) |
新しいメッセージ型 MeterProCO2.msg の準備ができましたので取得データの代入などの機能をパブリッシャーの Python のプログラムファイル switchbot_ros / scripts / switchbot_status_publisher.py に追加記述します.
追加した MeterProCO2.msg を switchbot_status_publisher.py 内で利用するためにメッセージクラス MeterProCO2
を import
しておきます.
switchbot_ros / scripts / switchbot_status_publisher.py
1 2 3 4 5 6 7 8 | #!/usr/bin/env python import os.path from requests import ConnectionError import rospy from switchbot_ros.switchbot import SwitchBotAPIClient from switchbot_ros.switchbot import DeviceError, SwitchBotAPIError from switchbot_ros.msg import Meter, PlugMini, Hub2, Bot, StripLight, MeterProCO2 |
初期化関数定義 def __init__(self):
内のパブリッシャーのメッセージクラス設定を行う部分にデバイスタイプ MeterPro(CO2)
の場合の条件分岐を追加して MeterProCO2
をメッセージクラスとして設定します.
switchbot_ros / scripts / switchbot_status_publisher.py
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 | # Publisher Message Class for each device type if self .device_type = = 'Remote' : rospy.logerr( 'Device Type: "' + self .device_type + '" has no status in specifications.' ) return else : if self .device_type = = 'Meter' : self .msg_class = Meter elif self .device_type = = 'MeterPlus' : self .msg_class = Meter elif self .device_type = = 'WoIOSensor' : self .msg_class = Meter elif self .device_type = = 'Hub 2' : self .msg_class = Hub2 elif self .device_type = = 'Plug Mini (JP)' : self .msg_class = PlugMini elif self .device_type = = 'Plug Mini (US)' : self .msg_class = PlugMini elif self .device_type = = 'Bot' : self .msg_class = Bot elif self .device_type = = 'Strip Light' : self .msg_class = StripLight elif self .device_type = = 'MeterPro(CO2)' : self .msg_class = MeterProCO2 else : rospy.logerr( 'No publisher process for "' + self .device_type + '" in switchbot_status_publisher.py' ) return |
繰り返し関数定義 def spin(self):
内のパブリッシュするメッセージクラスごとの場合分けに MeterProCO2
を追加して SwitchBot API により取得した各データを MeterProCO2
メッセージの各要素に代入します.
switchbot_ros / scripts / switchbot_status_publisher.py
120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | if status: time = rospy.get_rostime() if self .msg_class = = Meter: msg = Meter() msg.header.stamp = time msg.temperature = status[ 'temperature' ] msg.humidity = status[ 'humidity' ] msg.battery = status[ 'battery' ] elif self .msg_class = = Hub2: msg = Hub2() msg.header.stamp = time msg.temperature = status[ 'temperature' ] msg.humidity = status[ 'humidity' ] msg.light_level = status[ 'lightLevel' ] elif self .msg_class = = PlugMini: msg = PlugMini() msg.header.stamp = time msg.voltage = status[ 'voltage' ] msg.weight = status[ 'weight' ] msg.current = status[ 'electricCurrent' ] msg.minutes_day = status[ 'electricityOfDay' ] elif self .msg_class = = Bot: msg = Bot() msg.header.stamp = time msg.battery = status[ 'battery' ] if status[ 'power' ] = = 'on' : msg.power = True else : msg.power = False msg.device_mode = status[ 'deviceMode' ] elif self .msg_class = = StripLight: msg = StripLight() msg.header.stamp = time if status[ 'power' ] = = 'on' : msg.power = True else : msg.power = False msg.brightness = status[ 'brightness' ] rgb_string = status[ 'color' ] r, g, b = map ( int , rgb_string.split( ':' )) msg.color_r = r msg.color_g = g msg.color_b = b elif self .msg_class = = MeterProCO2: msg = MeterProCO2() msg.header.stamp = time msg.temperature = status[ 'temperature' ] msg.humidity = status[ 'humidity' ] msg.battery = status[ 'battery' ] msg.co2ppm = status[ 'CO2' ] else : return |
今回の「SwitchBot CO2センサー(温湿度計)」のデータ取得とその ROS Topic へのパブリッシュに関するファイルの追加・コード変更は以上です.
今回の変更で新しいメッセージ型を定義して導入していますのでパッケージのビルドを行い,環境設定を改めて行います.
switchbot_ros を含む jsk_3rdparty のビルド
$ source /opt/ros/noetic/setup . bash $ cd ~ /switchbot_ws $ catkin build $ source ~ /switchbot_ws/devel/setup . bash |
まず利用可能な SwitchBot デバイス名リストを取得・確認してから,得られた新規追加したデバイス名を指定して SwitchBot デバイスのステータスデータの取得と ROS Topic へのパブリッシュを行い,実際にパブリッシュされているかを ROS Topic を表示して確認します.
実行方法は今回機能追加するより前の方法と同じで,launch 時にオプション指定するデバイス名を変えるだけです.
ターミナル 1 : switchbot_ros の実行
SwitchBot API 経由で今回追加した「SwitchBot CO2センサー(温湿度計)」の「デバイス名」と「デバイスタイプ」が取得できることを確認します.ユーザの SwitchBot アカウントで登録されているデバイスの「デバイス名」と「デバイスタイプ」は switchbot.launch を実行すると表示されます.
(下記 launch オプションの YOUR_TOKEN
と YOUR_SECRET
をそれぞれユーザアカウントのトークンとシークレットに置き換えて実行)
switchbot.launch 実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ roslaunch switchbot_ros switchbot.launch token:=YOUR_TOKEN secret:=YOUR_SECRET |
switchbot.launch 実行出力例
... logging to /home/robotuser/ .ros /log/999f113c-b07d-11ef-9b82-a11b8fd4bdd2/roslaunch-robotuser-PC-7718 .log Checking log directory for disk usage. This may take a while . Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http: //robotuser-PC :43087/ SUMMARY ======== PARAMETERS * /rosdistro : noetic * /rosversion : 1.17.0 * /switchbot_ros/secret : (シークレットの上位数桁が表示)... * /switchbot_ros/token : (トークンの上位数桁が表示)... NODES / switchbot_ros (switchbot_ros /switchbot_ros_server .py) auto-starting new master process[master]: started with pid [7726] ROS_MASTER_URI=http: //localhost :11311 setting /run_id to 999f113c-b07d-11ef-9b82-a11b8fd4bdd2 process[rosout-1]: started with pid [7736] started core service [ /rosout ] process[switchbot_ros-2]: started with pid [7743] [INFO] [1733123900.102425]: Switchbot API Client initialized. [INFO] [1733123900.104175]: Using SwitchBot API v1.1 [INFO] [1733123900.106131]: Switchbot Device List: 9 Item(s) deviceName: bot74a, deviceID: (固有のID番号が表示), deviceType: Bot deviceName: cam-entrance01, deviceID: (固有のID番号が表示), deviceType: None deviceName: co2sensor-ba1, deviceID: (固有のID番号が表示), deviceType: MeterPro(CO2) deviceName: hub2a, deviceID: (固有のID番号が表示), deviceType: Hub 2 deviceName: plugmini7a1, deviceID: (固有のID番号が表示), deviceType: Plug Mini (JP) deviceName: remote-button10a, deviceID: (固有のID番号が表示), deviceType: Remote deviceName: tapelight7a1, deviceID: (固有のID番号が表示), deviceType: Strip Light deviceName: thermo-hygrometer-f7a, deviceID: (固有のID番号が表示), deviceType: Meter deviceName: trackcard01, deviceID: (固有のID番号が表示), deviceType: None [INFO] [1733123900.107799]: Switchbot Remote List: 2 Item(s) deviceName: air-conditioner, deviceID: (固有のID番号が表示), remoteType: Air Conditioner deviceName: pendant-light, deviceID: (固有のID番号が表示), remoteType: DIY Light [INFO] [1733123900.109488]: Switchbot Scene List: 2 Item(s) sceneName: turnoff-all-lights, sceneID: (固有のID番号が表示) sceneName: turnon-all-lights, sceneID: (固有のID番号が表示) [INFO] [1733123900.139015]: Ready. |
追加した「SwitchBot CO2センサー(温湿度計)」のデバイス名 co2sensor-ba1
がコンソール出力されたので一旦 Ctrl-C にて switchbot.launch を終了します.
「SwitchBot CO2センサー(温湿度計)」のステータスデータを取得してパブリッシュされている ROS Topic を表示して確認してみます.前述の switchbot.launch の実行出力例からデバイス名が co2sensor-ba1
となっています.
ステータスデータを取得する場合は switchbot.launch 実行時に次の2つのオプションを追加します.
pub_status:=true
ステータスを取得・パブリッシュを実行するオプション true/falsepub_device_name:=
デバイス名の指定(今回の例 co2sensor-ba1
)ターミナル 1 : switchbot_ros の実行
switchbot.launch 実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ roslaunch switchbot_ros switchbot.launch token:=YOUR_TOKEN secret:=YOUR_SECRET pub_status:= true pub_device_name:=co2sensor-ba1 pub_status_rate:=0.016666 |
YOUR_TOKEN
と YOUR_SECRET
は各々の SwitchBot アカウントのトークンとシークレットに置き換えて実行してください.pub_status:=true
でステータスを取得・パブリッシュを実行します.pub_device_name:=co2sensor-ba1
の co2sensor-ba1
は各ユーザ利用のデバイス名に変更してください.pub_status_rate:=0.016666
でステータスを取得・パブリッシュする周波数 [Hz] を設定します.(本例では 0.016666[Hz] = 約60秒に1回)switchbot.launch 実行出力例
... logging to /home/robotuser/ .ros /log/e454822a-b07d-11ef-9b82-a11b8fd4bdd2/roslaunch-robotuser-PC-7804 .log Checking log directory for disk usage. This may take a while . Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http: //robotuser-PC :36557/ SUMMARY ======== PARAMETERS * /rosdistro : noetic * /rosversion : 1.17.0 * /switchbot_ros/secret : (シークレットの上位数桁が表示)... * /switchbot_ros/token : (トークンの上位数桁が表示)... * /switchbot_status_publisher/device_name : co2sensor-ba1 * /switchbot_status_publisher/rate : 0.016666 * /switchbot_status_publisher/secret : (シークレットの上位数桁が表示)... * /switchbot_status_publisher/token : (トークンの上位数桁が表示)... NODES / switchbot_ros (switchbot_ros /switchbot_ros_server .py) switchbot_status_publisher (switchbot_ros /switchbot_status_publisher .py) auto-starting new master process[master]: started with pid [7812] ROS_MASTER_URI=http: //localhost :11311 setting /run_id to e454822a-b07d-11ef-9b82-a11b8fd4bdd2 process[rosout-1]: started with pid [7822] started core service [ /rosout ] process[switchbot_ros-2]: started with pid [7829] process[switchbot_status_publisher-3]: started with pid [7830] [INFO] [1733124025.952044]: Switchbot API Client initialized. [INFO] [1733124025.953872]: Using SwitchBot API v1.1 [INFO] [1733124025.955817]: Switchbot Device List: 9 Item(s) deviceName: bot74a, deviceID: (固有のID番号が表示), deviceType: Bot deviceName: cam-entrance01, deviceID: (固有のID番号が表示), deviceType: None deviceName: co2sensor-ba1, deviceID: (固有のID番号が表示), deviceType: MeterPro(CO2) deviceName: hub2a, deviceID: (固有のID番号が表示), deviceType: Hub 2 deviceName: plugmini7a1, deviceID: (固有のID番号が表示), deviceType: Plug Mini (JP) deviceName: remote-button10a, deviceID: (固有のID番号が表示), deviceType: Remote deviceName: tapelight7a1, deviceID: (固有のID番号が表示), deviceType: Strip Light deviceName: thermo-hygrometer-f7a, deviceID: (固有のID番号が表示), deviceType: Meter deviceName: trackcard01, deviceID: (固有のID番号が表示), deviceType: None [INFO] [1733124025.957387]: Switchbot Remote List: 2 Item(s) deviceName: air-conditioner, deviceID: (固有のID番号が表示), remoteType: Air Conditioner deviceName: pendant-light, deviceID: (固有のID番号が表示), remoteType: DIY Light [INFO] [1733124025.959085]: Switchbot Scene List: 2 Item(s) sceneName: turnoff-all-lights, sceneID: (固有のID番号が表示) sceneName: turnon-all-lights, sceneID: (固有のID番号が表示) [INFO] [1733124025.981926]: Ready. [INFO] [1733124026.191206]: Switchbot API Client initialized. [INFO] [1733124026.192948]: Using SwitchBot API v1.1 [INFO] [1733124026.195299]: Rate: 0.016666 [INFO] [1733124026.197702]: deviceName: co2sensor-ba1 / deviceType: MeterPro(CO2) [INFO] [1733124026.200537]: Ready: SwitchBot Status Publisher for co2sensor-ba1 |
ターミナル 2 : ROS Topic の確認
rostopic list の実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ rostopic list |
rostopic list の実行出力例
/rosout /rosout_agg /switchbot_ros/devices /switchbot_ros/switch/cancel /switchbot_ros/switch/feedback /switchbot_ros/switch/goal /switchbot_ros/switch/result /switchbot_ros/switch/status /switchbot_status_publisher/co2sensor_ba1 |
rostopic echo 実行入力
$ rostopic echo /switchbot_status_publisher/co2sensor_ba1 |
rostopic echo の実行出力例
header: seq : 1 stamp: secs: 1733124088 nsecs: 5677223 frame_id: '' temperature: 25.4 humidity: 35.0 battery: 100.0 co2ppm: 562 --- header: seq : 2 stamp: secs: 1733124147 nsecs: 910016298 frame_id: '' temperature: 25.4 humidity: 35.0 battery: 100.0 co2ppm: 562 --- |
「SwitchBot CO2センサー(温湿度計)」のステータスデータとして CO2濃度 などが取得されて ROS Topic にパブリッシュされている様子が見て取れるかと思います.
今回の記事はここまでです.
本シリーズ前回の記事 SwitchBot を ROS から利用する – コマンド操作編2 では SwitchBot を ROS から利用する switchbot_ros のサンプルのソースコードで扱われていた SwitchBot デバイス以外のものを ROS から操作するために SwitchBot API のコマンドセットを調べて control_switchbot.py に実装する過程について紹介しました.
今回は SwitchBot デバイスのステータスデータの取得と ROS トピックへのパブリッシュを行ってみます.
前回の記事 SwitchBot を ROS から利用する – コマンド操作編2 を公開した後に GitHub 上の switchbot_ros が更新されて SwitchBot デバイスのステータスデータの取得とパブリッシュを行うソフトウェアソースコードが追加されました.
更新された switchbot_ros を実際に動作させる Ubuntu PC 内の switchbot_ros に適用してビルドします.
既に前回の記事の時点の switchbot_ros を含む jsk_3rdparty をクローンして利用している場合は次の手順で更新された GitHub 上の jsk_3rdparty を git でプル(ダウンロード更新)してビルドします.
switchbot_ros を含む jsk_3rdparty の更新とビルド
$ source ~ /switchbot_ws/devel/setup . bash $ cd ~ /switchbot_ws/src/jsk_3rdparty $ git checkout master $ git pull origin master $ catkin build $ source ~ /switchbot_ws/devel/setup . bash |
ターミナル 1 : switchbot_ros の実行
前回記事と同じですがユーザの SwitchBot アカウントで登録されているデバイスの「デバイス名」と「デバイスタイプ」は switchbot.launch を実行すると表示されます.
(下記 launch オプションの YOUR_TOKEN
と YOUR_SECRET
をそれぞれユーザアカウントのトークンとシークレットに置き換えて実行)
switchbot.launch 実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ roslaunch switchbot_ros switchbot.launch token:=YOUR_TOKEN secret:=YOUR_SECRET |
switchbot.launch 実行出力例
... logging to /home/robotuser/ .ros /log/87b6e5c8-c1a2-11ee-bce7-1d89a9d14e1f/roslaunch-robotuser-PC-62866 .log Checking log directory for disk usage. This may take a while . Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http: //robotuser-PC :40731/ SUMMARY ======== PARAMETERS * /rosdistro : noetic * /rosversion : 1.16.0 * /switchbot_ros/secret : (シークレットの上位数桁が表示)... * /switchbot_ros/token : (トークンの上位数桁が表示)... NODES / switchbot_ros (switchbot_ros /switchbot_ros_server .py) auto-starting new master process[master]: started with pid [62874] ROS_MASTER_URI=http: //localhost :11311 setting /run_id to 87b6e5c8-c1a2-11ee-bce7-1d89a9d14e1f process[rosout-1]: started with pid [62884] started core service [ /rosout ] process[switchbot_ros-2]: started with pid [62891] [INFO] [1706861436.195243]: Switchbot API Client initialized. [INFO] [1706861436.199678]: Using SwitchBot API v1.1 [INFO] [1706861436.204957]: Switchbot Device List: 6 Item(s) deviceName: bot74a, deviceID: (固有のID番号が表示), deviceType: Bot deviceName: hub2a, deviceID: (固有のID番号が表示), deviceType: Hub 2 deviceName: plugmini7a1, deviceID: (固有のID番号が表示), deviceType: Plug Mini (JP) deviceName: remote-button10a, deviceID: (固有のID番号が表示), deviceType: Remote deviceName: tapelight7a1, deviceID: (固有のID番号が表示), deviceType: Strip Light deviceName: thermo-hygrometer-f7a, deviceID: (固有のID番号が表示), deviceType: Meter [INFO] [1706861436.208853]: Switchbot Remote List: 2 Item(s) deviceName: air-conditioner, deviceID: (固有のID番号が表示), remoteType: Air Conditioner deviceName: pendant-light, deviceID: (固有のID番号が表示), remoteType: DIY Light [INFO] [1706861436.214168]: Switchbot Scene List: 3 Item(s) sceneName: turnoff-all-lights, sceneID: (固有のID番号が表示) sceneName: turnon-all-lights, sceneID: (固有のID番号が表示) sceneName: turnon-all-lights, sceneID: (固有のID番号が表示) [INFO] [1706861436.254126]: Ready. |
利用可能なデバイス名がコンソール出力されたので一旦 Ctrl-C にて switchbot.launch を終了します.
上記の switchbot.launch 実行出力例にある SwitchBot デバイスのうち取得するステータスがない Remote 以外の次のデバイスタイプは switchbot_ros にてステータスデータを取得することができます.
また上記リスト以外のデータ取得 API 提供がされている SwitchBot デバイスについては switchbot_ros のコードに組み込まれていませんが適宜情報をコードに加えれば switchbot_ros からもデータ取得できるようになると思います.
実行例として今回は SwitchBot の温湿度計(デバイスタイプ Meter)のステータスデータを取得してパブリッシュされている ROS トピックを表示してみます.先述の switchbot.launch の実行出力例から読み取ると,該当するデバイス名が thermo-hygrometer-f7a
となっています.
ステータスデータを取得する場合は switchbot.launch 実行時に次の2つのオプションを追加します.
pub_status:=true
ステータスを取得・パブリッシュを実行するオプション true/falsepub_device_name:=thermo-hygrometer-f7a
デバイス名の指定(本例では thermo-hygrometer-f7a)ターミナル 1 : switchbot_ros の実行
switchbot.launch 実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ roslaunch switchbot_ros switchbot.launch token:=YOUR_TOKEN secret:=YOUR_SECRET pub_status:= true pub_device_name:=thermo-hygrometer-f7a |
YOUR_TOKEN
と YOUR_SECRET
は各々の SwitchBot アカウントのトークンとシークレットに置き換えて実行してください.pub_status:=true
でステータスを取得・パブリッシュを実行します.pub_device_name:=thermo-hygrometer-f7a
の thermo-hygrometer-f7a
は各ユーザ利用のデバイス名に変更してください.switchbot.launch 実行出力例
... logging to /home/robotuser/ .ros /log/81bc64b6-faf2-11ee-8dad-e57ee950b51d/roslaunch-robotuser-PC-28197 .log Checking log directory for disk usage. This may take a while . Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http: //robotuser-PC :35371/ SUMMARY ======== PARAMETERS * /rosdistro : noetic * /rosversion : 1.16.0 * /switchbot_ros/secret : (シークレットの上位数桁が表示)... * /switchbot_ros/token : (トークンの上位数桁が表示)... * /switchbot_status_publisher/device_name : thermo-hygrometer... * /switchbot_status_publisher/rate : 0.1 * /switchbot_status_publisher/secret : (シークレットの上位数桁が表示)... * /switchbot_status_publisher/token : (トークンの上位数桁が表示)... NODES / switchbot_ros (switchbot_ros /switchbot_ros_server .py) switchbot_status_publisher (switchbot_ros /switchbot_status_publisher .py) auto-starting new master process[master]: started with pid [28205] ROS_MASTER_URI=http: //localhost :11311 setting /run_id to 81bc64b6-faf2-11ee-8dad-e57ee950b51d process[rosout-1]: started with pid [28215] started core service [ /rosout ] process[switchbot_ros-2]: started with pid [28222] process[switchbot_status_publisher-3]: started with pid [28223] [INFO] [1713163000.937913]: Switchbot API Client initialized. [INFO] [1713163000.938005]: Switchbot API Client initialized. [INFO] [1713163000.940084]: Using SwitchBot API v1.1 [INFO] [1713163000.940382]: Using SwitchBot API v1.1 [INFO] [1713163000.942545]: Switchbot Device List: 6 Item(s) deviceName: bot74a, deviceID: (固有のID番号が表示), deviceType: Bot deviceName: hub2a, deviceID: (固有のID番号が表示), deviceType: Hub 2 deviceName: plugmini7a1, deviceID: (固有のID番号が表示), deviceType: Plug Mini (JP) deviceName: remote-button10a, deviceID: (固有のID番号が表示), deviceType: Remote deviceName: tapelight7a1, deviceID: (固有のID番号が表示), deviceType: Strip Light deviceName: thermo-hygrometer-f7a, deviceID: (固有のID番号が表示), deviceType: Meter [INFO] [1713163000.944131]: Switchbot Remote List: 2 Item(s) deviceName: air-conditioner, deviceID: (固有のID番号が表示), remoteType: Air Conditioner deviceName: pendant-light, deviceID: (固有のID番号が表示), remoteType: DIY Light [INFO] [1713163000.944268]: Rate: 0.1 [INFO] [1713163000.945732]: Switchbot Scene List: 2 Item(s) sceneName: turnoff-all-lights, sceneID: (固有のID番号が表示) sceneName: turnon-all-lights, sceneID: (固有のID番号が表示) [INFO] [1713163000.947428]: deviceName: thermo-hygrometer-f7a / deviceType: Meter [INFO] [1713163000.951801]: Ready: SwitchBot Status Publisher for thermo-hygrometer-f7a [INFO] [1713163000.966800]: Ready. |
ターミナル 2 : ROS トピックの確認
rostopic list の実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ rostopic list |
rostopic list の実行出力例
/rosout /rosout_agg /switchbot_ros/devices /switchbot_ros/switch/cancel /switchbot_ros/switch/feedback /switchbot_ros/switch/goal /switchbot_ros/switch/result /switchbot_ros/switch/status /switchbot_status_publisher/thermo_hygrometer_f7a |
rostopic echo 実行入力
$ rostopic echo /switchbot_status_publisher/thermo_hygrometer_f7a |
rostopic echo の実行出力例
header: seq : 1 stamp: secs: 1713163093 nsecs: 412018775 frame_id: '' temperature: 26.9 humidity: 36.0 battery: 100.0 --- header: seq : 2 stamp: secs: 1713163103 nsecs: 447003364 frame_id: '' temperature: 26.9 humidity: 36.0 battery: 100.0 --- header: seq : 3 stamp: secs: 1713163113 nsecs: 380291700 frame_id: '' temperature: 26.9 humidity: 36.0 battery: 100.0 |
SwitchBot 温湿度計 Meter のステータスデータとして温度・湿度などが取得されて ROS トピックにパブリッシュされている様子がわかるかと思います.
ステータスの取得とパブリッシュの間隔は switchbot.launch のデフォルト設定で 0.1 [Hz] = 10秒間隔 になっています.これを変更する場合には switchbot.launch のオプションで pub_status_rate:=0.05
のように追加します.温湿度のように急に変化しなさそうなデータの場合はもっと長めの間隔でも良いかもしれません.
今回の記事はここまでです.
本シリーズ前回の記事 SwitchBot を ROS から利用する – コマンド操作編1 では SwitchBot を ROS から利用する switchbot_ros の導入とサンプル Python コードの実行の様子を紹介しました.
今回は前回の記事の続きとしてサンプルのソースコードで扱われていた SwitchBot デバイス以外のものを ROS から操作するために SwitchBot API のコマンドセットを調べて control_switchbot.py に実装する過程について紹介します.
switchbot_ros のサンプル Python コード control_switchbot.py においてボット(スイッチ)をオンにする命令は次のようになっていて「デバイス名」とそれに対する「コマンド」の2つを指定する必要があります.
client.control_device( 'bot74a' , 'turnOn' ) |
client.control_device( 'デバイス名' , 'コマンド' ) |
このうち「コマンド」は SwitchBot API にてデバイスタイプごとに設定されているので「デバイスタイプ」が何かを知る必要があります.
ユーザのアカウントで登録されているデバイスの「デバイス名」と「デバイスタイプ」は switchbot.launch を実行すると表示されます.
(下記 launch オプションの YOUR_TOKEN と YOUR_SECRET をそれぞれユーザアカウントのトークンとシークレットに置き換えて実行)
switchbot.launch 実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ roslaunch switchbot_ros switchbot.launch token:=YOUR_TOKEN secret:=YOUR_SECRET |
switchbot.launch 実行出力例
... logging to /home/robotuser/ .ros /log/87b6e5c8-c1a2-11ee-bce7-1d89a9d14e1f/roslaunch-robotuser-PC-62866 .log Checking log directory for disk usage. This may take a while . Press Ctrl-C to interrupt Done checking log file disk usage. Usage is <1GB. started roslaunch server http: //robotuser-PC :40731/ SUMMARY ======== PARAMETERS * /rosdistro : noetic * /rosversion : 1.16.0 * /switchbot_ros/secret : (シークレットの上位数桁が表示)... * /switchbot_ros/token : (トークンの上位数桁が表示)... NODES / switchbot_ros (switchbot_ros /switchbot_ros_server .py) auto-starting new master process[master]: started with pid [62874] ROS_MASTER_URI=http: //localhost :11311 setting /run_id to 87b6e5c8-c1a2-11ee-bce7-1d89a9d14e1f process[rosout-1]: started with pid [62884] started core service [ /rosout ] process[switchbot_ros-2]: started with pid [62891] [INFO] [1706861436.195243]: Switchbot API Client initialized. [INFO] [1706861436.199678]: Using SwitchBot API v1.1 [INFO] [1706861436.204957]: Switchbot Device List: 6 Item(s) deviceName: bot74a, deviceID: (固有のID番号が表示), deviceType: Bot deviceName: hub2a, deviceID: (固有のID番号が表示), deviceType: Hub 2 deviceName: plugmini7a1, deviceID: (固有のID番号が表示), deviceType: Plug Mini (JP) deviceName: remote-button10a, deviceID: (固有のID番号が表示), deviceType: Remote deviceName: tapelight7a1, deviceID: (固有のID番号が表示), deviceType: Strip Light deviceName: thermo-hygrometer-f7a, deviceID: (固有のID番号が表示), deviceType: Meter [INFO] [1706861436.208853]: Switchbot Remote List: 2 Item(s) deviceName: air-conditioner, deviceID: (固有のID番号が表示), remoteType: Air Conditioner deviceName: pendant-light, deviceID: (固有のID番号が表示), remoteType: DIY Light [INFO] [1706861436.214168]: Switchbot Scene List: 3 Item(s) sceneName: turnoff-all-lights, sceneID: (固有のID番号が表示) sceneName: turnon-all-lights, sceneID: (固有のID番号が表示) sceneName: turnon-all-lights, sceneID: (固有のID番号が表示) [INFO] [1706861436.254126]: Ready. |
switchbot.launch 実行出力から次の1行を例にとると「デバイス名」が plugmini7a1
で「デバイスタイプ」が Plug Mini (JP)
です.
deviceName: plugmini7a1, deviceID: (固有のID番号が表示), deviceType: Plug Mini (JP) |
操作したい SwitchBot デバイスタイプが分かればそのコマンドセットを調べます.SwitchBot API のコマンドセットは下記の Web ページで知ることができます.
今回はデバイスタイプ Plug Mini (JP) と Strip Light のデバイスを操作したいのでそれらのコマンドセットについて調べます.
電源プラグの On/Off を行う SwitchBot デバイスである Plug Mini (JP) のコマンドセットの説明は次のリンク先にあります.
上記 Web ページの Plug Mini (JP) コマンドセットの表をそのまま貼り付けたものが次の表です.
deviceType | commandType | Command | command parameter | Description |
---|---|---|---|---|
Plug Mini (JP) | command | turnOn | default | set to ON state |
Plug Mini (JP) | command | turnOff | default | set to OFF state |
Plug Mini (JP) | command | toggle | default | toggle state |
デバイスの機能どおりに電源入 turnOn
,電源切 turnOff
,電源入切の切替 toggle
の3つのコマンドにより構成されています.
テープライト形状の SwitchBot デバイスである Strip Light のコマンドセットの説明は次のリンク先にあります.
上記 Web ページの Strip Light コマンドセットの表をそのまま貼り付けたものが次の表です.
deviceType | commandType | Command | command parameter | Description |
---|---|---|---|---|
Strip Light | command | turnOn | default | set to ON state |
Strip Light | command | turnOff | default | set to OFF state |
Strip Light | command | toggle | default | toggle state |
Strip Light | command | setBrightness | {1-100} |
set brightness |
Strip Light | command | setColor | "{0-255}:{0-255}:{0-255}" |
set RGB color value |
点灯 turnOn
,消灯 turnOff
,明滅切替 toggle
,輝度設定 setBrightness
,色設定 setColor
の5つのコマンドにより構成されていて,そのうち輝度設定では{1-100}
の範囲で輝度設定, "{0-255}:{0-255}:{0-255}"
の値で RGB 色設定を行います.
デバイス名 plugmini7a1
の Plug Mini (JP) を操作します. ROS からコマンドを送って On/Off の切り替え toggle
をしてみます.
サンプルコード control_switchbot.py に client.control_device('plugmini7a1', 'toggle')
を追加します.(下記ソースコードの 16行目)
control_switchbot.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | #!/usr/bin/env python import rospy from switchbot_ros.switchbot_ros_client import SwitchBotROSClient rospy.init_node( 'controler_node' ) client = SwitchBotROSClient() devices = client.get_devices() print (devices) # client.control_device('pendant-light', 'turnOn') # client.control_device('bot74a', 'turnOn') client.control_device( 'plugmini7a1' , 'toggle' ) |
ここでは元々サンプルコードにあったペンダントライトとボット(スイッチ)の操作をする行(上記ソースコードの12,14行目)は行頭に #
を入れてコメントアウトして実行されないようにしています.
変更を加えた control_switchbot.py ファイルを保存してから実行します.
ターミナル 1 : switchbot.launch 実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ roslaunch switchbot_ros switchbot.launch token:=YOUR_TOKEN secret:=YOUR_SECRET |
ターミナル 2 : control_switchbot.py 実行入力
$ source ~ /switchbot_ws/devel/setup . bash $ rosrun switchbot_ros control_switchbot.py |
デバイス名 tapelight7a1
の Strip Light (テープライト)を操作します. ROS からコマンドを送って次の動作をしてみます.
'255:255:255'
に設定'255:0:0'
に設定'0:255:0'
に設定'0:0:255'
に設定サンプルコード control_switchbot.py に下記ソースコードの18行目以降を追加します.
値を設定する setBrightness
や setColor
といったコマンドでは各数値を control_device()
の引数 parameter
に文字列として渡します.
また control_device()
の中ではコマンドを Action サーバにゴールとして送っているので新しいコマンドが前のコマンドに置き換わらないように1つ1つのコマンド実行を終えるのを待つように引数 wait
に True
を渡しています.
control_switchbot.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/usr/bin/env python import rospy from switchbot_ros.switchbot_ros_client import SwitchBotROSClient rospy.init_node( 'controler_node' ) client = SwitchBotROSClient() devices = client.get_devices() print (devices) # client.control_device('pendant-light', 'turnOn') # client.control_device('bot74a', 'turnOn') # client.control_device('plugmini7a1', 'toggle') client.control_device( 'tapelight7a1' , 'turnOff' , wait = True ) client.control_device( 'tapelight7a1' , 'turnOn' , wait = True ) client.control_device( 'tapelight7a1' , 'setBrightness' , parameter = '100' , wait = True ) client.control_device( 'tapelight7a1' , 'setColor' , parameter = '255:255:255' , wait = True ) client.control_device( 'tapelight7a1' , 'setColor' , parameter = '255:0:0' , wait = True ) client.control_device( 'tapelight7a1' , 'setColor' , parameter = '0:255:0' , wait = True ) client.control_device( 'tapelight7a1' , 'setColor' , parameter = '0:0:255' , wait = True ) client.control_device( 'tapelight7a1' , 'setBrightness' , parameter = '1' , wait = True ) client.control_device( 'tapelight7a1' , 'turnOff' , wait = True ) |
前述の Plug Mini (JP) のときと同様に変更を加えた control_switchbot.py ファイルを保存してから実行します.
筆者が試した範囲では時々 client.control_device()
が実行されない不具合が見受けられ,それが SwitchBotROSClient インスタンス作成時 client = SwitchBotROSClient()
に Action サーバの起動やサーバへの接続が不十分であることが原因のように思われました.
そこで下記の switchbot_ros_client.py の21行目のように self.action_client.wait_for_server()
を入れて Action サーバが起動して接続されるのを待つようにしたところ,現状では安定して client.control_device()
が実行されているように感じます.
switchbot_ros_client.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 | import rospy import actionlib from switchbot_ros.msg import SwitchBotCommandAction from switchbot_ros.msg import SwitchBotCommandGoal from switchbot_ros.msg import DeviceArray class SwitchBotROSClient( object ): def __init__( self , actionname = 'switchbot_ros/switch' , topicname = 'switchbot_ros/devices' ): self .actionname = actionname self .topicname = topicname self .action_client = actionlib.SimpleActionClient( actionname, SwitchBotCommandAction ) rospy.loginfo( "Waiting for action server to start." ) self .action_client.wait_for_server() def get_devices( self , timeout = None ): return rospy.wait_for_message( self .topicname, DeviceArray, timeout = timeout ) def control_device( self , device_name, command, parameter = '', command_type = '', wait = False ): goal = SwitchBotCommandGoal() goal.device_name = device_name goal.command = command goal.parameter = parameter goal.command_type = command_type self .action_client.send_goal(goal) if wait: self .action_client.wait_for_result() return self .action_client.get_result() |
今回の記事はここまでです.