Edited at

スマートコンセントをHackして普通のフロアライトを人感センサーで点灯するようにしてみた


スマートコンセント(スマートプラグ)を買いました。


Charlesで通信を調べてみる

iOSアプリの設定を済ませて、どんな通信をしているのか覗いてみました。

Artboard.png

payload.togglex.onoff ってやつが怪しい

sign とか messageId の生成ルールが解析できないと詰みそう・・・


とりあえずそのままCurlで送ってみる

$ curl --request POST \

--url http://172.16.00.000/config \
--header 'content-type: application/json' \
--data '{
"payload": {
"togglex": {
"onoff": 1,
"channel": 0
}
},
"header": {
"messageId": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"method": "SET",
"namespace": "Appliance.Control.ToggleX",
"timestamp": 1556035842,
"sign": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
"payloadVersion": 1
}
}'

カチッて音とともにライトが点いた。

普通に操作できてしまった。


onoffを1と0で切り替えるとチカチカできる。

blink.gif

signmessageId も使い回せた。。。

headerにもBasic認証っぽいやつとかもあったけど、使わないでも通信できた。。。

セキュリティ的には気になるけど、結果的にはOK


人感センサーでライトを操作したい。

ということで本命の、

部屋に人いるときはライトを点けて、いなくなったら消すって装置を作っていきます。


材料。


  • Raspberry Pi

  • 焦電型赤外線センサーモジュール(焦電人感センサ) SB612A


人感センサーの値を取得したい。

Untitled Sketch_bb.png

ラズパイの5V・17番・GNDとセンサーを繋げます。


test.py

import RPi.GPIO as GPIO

import time

PIN = 17

GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN, GPIO.IN)
GPIO.setwarnings(False)

count = 0

while True:
res = GPIO.input(PIN)
print(res)
time.sleep(1)



実行!

$ python test.py

0
0
0
0
1
1
1
1
1
1
1

センサーの前に立って動いている最中に1が返ってってくればOK


スマートコンセントに送るプログラム。


main.py

import RPi.GPIO as GPIO

import time
import requests

PIN = 17
URL = "http://172.16.00.000/config"

GPIO.setmode(GPIO.BCM)
GPIO.setup(PIN, GPIO.IN)
GPIO.setwarnings(False)

count = 0

try:
while True:
res = GPIO.input(PIN)
if res == 1:
if count < 0:
count = 0
else:
count += 1
else:
if count > 0:
count = 0
else:
count -= 1

if count == -3000:
payload = "{\n\t\"payload\": {\n\t\t\"togglex\": {\n\t\t\t\"onoff\": 0,\n\t\t\t\"channel\": 0\n\t\t}\n\t},\n\t\"header\": {\n\t\t\"messageId\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n\t\t\"method\": \"SET\",\n\t\t\"namespace\": \"Appliance.Control.ToggleX\",\n\t\t\"timestamp\": 1556029697,\n\t\t\"sign\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n\t\t\"payloadVersion\": 1\n\t}\n}"
headers = {'content-type': 'application/json'}
response = requests.request("POST", URL, data=payload, headers=headers)
print("send off", response.ok)

if count == 10:
payload = "{\n\t\"payload\": {\n\t\t\"togglex\": {\n\t\t\t\"onoff\": 1,\n\t\t\t\"channel\": 0\n\t\t}\n\t},\n\t\"header\": {\n\t\t\"messageId\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n\t\t\"method\": \"SET\",\n\t\t\"namespace\": \"Appliance.Control.ToggleX\",\n\t\t\"timestamp\": 1556029697,\n\t\t\"sign\": \"xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx\",\n\t\t\"payloadVersion\": 1\n\t}\n}"
headers = {'content-type': 'application/json'}
response = requests.request("POST", URL, data=payload, headers=headers)
print("send on", response.ok)

print(count)
time.sleep(0.2)

finally:
print("error")
GPIO.cleanup()


0.2秒ずつセンサーの値を取得し、

2秒間連続でセンサーが反応したらライトを点け、

10分間何もなかったらライトを切るという仕組みです。


ライトの麓に置いておいた。

IMG_3788.jpg


近寄ってみる。

walk.gif


おわり。

もしかしてルンバに反応してしまうんじゃ、と思ったけど意外と大丈夫だった。

そこまで熱くないか