【工具】【HA智能家居】主人回家自动开灯,离家自动关灯
前提环境:
安装有home assistant(以下简称ha)
安装有mosquitto (mqtt服务端)
有ha可控制的灯
原理:
监视光猫管理页面的无线终端设备列表,存在指定mac设备即被认定为主人回家,否则被认定为离家。
//自动化操作 import win.ui; /*DSG{{*/ var winform = win.form(text="使用webform调用网页上的对象、函数";right=848;bottom=585) winform.add( edit={cls="edit";text="f0:8f:49:8f:f1:3f";left=671;top=496;right=819;bottom=526;edge=1;z=2}; edit2={cls="edit";text="mosquitto_pub -h 192.168.1.100 -p 1883 -t cmnd/tasmota_95EA2A/POWER -m on";left=125;top=539;right=825;bottom=569;edge=1;z=3}; static={cls="static";text="指定mac存在则触发mqtt";left=493;top=502;right=664;bottom=527;transparent=1;z=1}; static2={cls="static";text="mqtt指令";left=50;top=544;right=107;bottom=565;transparent=1;z=4} ) /*}}*/ //创建web窗体 import web.form; import process; var wb = web.form( winform ); wb.noScriptErr = true; var randomi=0 //打开光猫管理网页 wb.go("http://192.168.1.1/cgi-bin/luci#login_form") //显示窗口 winform.show(); //登录光猫 wb.waitEle("username") ele = wb.getEle( "login_username" ) ele2= wb.getEle( "login_password" ) ele.value="useradmin"; ele2.value="ypwxu"; var ele3 = wb.queryEles( innerHTML="确认登录"; tagName="BUTTON"; className="btn" ); ele3.click() //////////////////////点击设备管理 wb.waitEle("first_menu_device") ele = wb.getEle("first_menu_device") ele.click() //点击无线终端设备 ele=wb.waitEle("sub_second_menu_device_wifi") ele.click() //无限循环检测指定mac是否存在,mac存在则发出mqtt指令,让home assistant开灯。 do{ //每隔3秒检测网页文本,是否存在指定mac //mac存在(主人回家)则开灯,mac不存在(主人离家)则关灯 for(i=1;3;1){ url= "http://192.168.1.1/cgi-bin/luci/admin/device/wifi?"++randomi; randomi=randomi+1 //wb.go(url) win.delay(3000) wb.waitEle("device_iframe") ele = wb.queryEles( innerHTML='@\n\t <div id="wifi_lists">\n\t\t\t<form id="wired_for'; parent="device_iframe"; tagName="BODY"; className="main_config_body" ); //win.msgbox(ele.outerText) htmltxt=ele.outerText if(string.find(htmltxt,"@"++winform.edit.text)){ //win.msgbox("y") cmds=winform.edit2.text var prcs,err = process(cmds); prcs.wait() //assert(prcs,err); }else { cmds=`mosquitto_pub -h 192.168.1.100 -p 1883 -t cmnd/tasmota_95EA2A/POWER -m off` var prcs,err = process(cmds); prcs.wait() } } //防超时无操作被光猫踢,每隔9秒点击一次网页上的“无线终端设备” win.delay(300) ele=wb.waitEle("sub_second_menu_device_wifi") ele.click() win.delay(500) }while(true) win.loopMessage();
MQTT协议其实也是建立在tcp协议上的,理论上来说只要支持MQTT协议的设备都可以进行跨平台通讯。
我用Golang实现了一下,感觉挺好玩的。
我想到一个使用场景,就是家里的电热水器。平时上班的时候电热水器可以关掉,而回家的时候电热水器自动启动,这样比较省电。我经常是忘记回家去开电热水器,等想洗澡的时候又要等很长时间。
package main import ( "fmt" mqtt "github.com/eclipse/paho.mqtt.golang" "time" ) var messagePubHandler mqtt.MessageHandler = func(client mqtt.Client, msg mqtt.Message) { fmt.Printf("Received message: %s from topic: %s\n", msg.Payload(), msg.Topic()) } var connectHandler mqtt.OnConnectHandler = func(client mqtt.Client) { fmt.Println("Connected") } var connectLostHandler mqtt.ConnectionLostHandler = func(client mqtt.Client, err error) { fmt.Printf("Connect lost: %v", err) } func main() { var broker = "192.168.23.244" var port = 1883 opts := mqtt.NewClientOptions() opts.AddBroker(fmt.Sprintf("tcp://%s:%d", broker, port)) opts.SetClientID("go_mqtt_client") //opts.SetUsername("emqx") //opts.SetPassword("public") opts.SetDefaultPublishHandler(messagePubHandler) opts.OnConnect = connectHandler opts.OnConnectionLost = connectLostHandler client := mqtt.NewClient(opts) if token := client.Connect(); token.Wait() && token.Error() != nil { panic(token.Error()) } sub(client) publish(client) client.Disconnect(250) } func publish(client mqtt.Client) { num := 10 for i := 0; i < num; i++ { text := fmt.Sprintf("Message %d", i) token := client.Publish("topic/test", 0, false, text) token.Wait() time.Sleep(time.Second) } } func sub(client mqtt.Client) { topic := "topic/test" token := client.Subscribe(topic, 1, nil) token.Wait() fmt.Printf("Subscribed to topic: %s\n", topic) }
显示:
D:\GoProjects\hello\go_build_main_go.exe Connected Subscribed to topic: topic/test Received message: Message 0 from topic: topic/test Received message: Message 1 from topic: topic/test Received message: Message 2 from topic: topic/test Received message: Message 3 from topic: topic/test Received message: Message 4 from topic: topic/test Received message: Message 5 from topic: topic/test Received message: Message 6 from topic: topic/test Received message: Message 7 from topic: topic/test Received message: Message 8 from topic: topic/test Received message: Message 9 from topic: topic/test 进程 已完成,退出代码为 0
好久没登录了,上来填坑,一楼的办法非常不好,
后来在GitHub上找到一个更好的办法.(详细请访问https://github.com/brannondorsey/sniff-probes),基于此方案修改一下:
sniff-probes-mod.sh
#!/bin/bash OUTPUT="${OUTPUT:-probes.txt}" CHANNEL_HOP="${CHANNEL_HOP:-0}" # channel hop every 2 seconds channel_hop() { IEEE80211bg="1 2 3 4 5 6 7 8 9 10 11" IEEE80211bg_intl="$IEEE80211b 12 13 14" IEEE80211a="36 40 44 48 52 56 60 64 149 153 157 161" IEEE80211bga="$IEEE80211bg $IEEE80211a" IEEE80211bga_intl="$IEEE80211bg_intl $IEEE80211a" while true ; do for CHAN in $IEEE80211bg ; do # echo "switching $IFACE to channel $CHAN" iwconfig $IFACE channel $CHAN sleep 2 done done } if ! [ -x "$(command -v gawk)" ]; then echo 'gawk (GNU awk) is not installed. Please install gawk.' >&2 exit 1 fi if [ -z "$IFACE" ] ; then echo "IFACE env variable must be set. Type \"ifconfig\" to view network interaces." exit 1 fi if [ "$CHANNEL_HOP" -eq 1 ] ; then # channel hop in the background channel_hop & fi #beacon | awk -f parse-tcpdump.awk | tee filter with awk, then use sed to convert tabs to spaces and remove front and back quotes around SSID| tee -a "$OUTPUT" tcpdump -l -i "$IFACE" -e -s 256 type mgt subtype probe-req and \(ether host aa:bb:cc:dd:ee:f1 or ether host aa:bb:cc:dd:ee:f2\) |awk -f parsescript.awk # and \(ether host aa:bb:cc:dd:ee:f1 or ether host aa:bb:cc:dd:ee:f2\)
parsescript.awk
#{ #print $21 #mac=$21 #print mac #} match($21, "SA:aa:bb:cc:dd:ee:f1") { print $21 system("mosquitto_pub -h 192.168.1.100 -p 1883 -t cmnd/athome -m yes") system("") # flush the buffer } match($21, "SA:aa:bb:cc:dd:ee:f2") { print $21 system("mosquitto_pub -h 192.168.1.100 -p 1883 -t cmnd/athome -m yes") system("") # flush the buffer }
其原理是wifi被动侦测,我们手机wifi功能在打开的时候,会后台不停地探测手机周边是否有可以连接的wifi路由器,这个探测的动作,就会被openwrt无线路由器里执行的tcpdump脚本记录到.就算你手机当时没有连上无线路由器,仅仅是靠近该路由器你都被记录了,然后按第二个脚本触发mqtt命令
回复#9 @hi_aardio :
是的靠近即刻被记录到。
遇到的是开放式不需要密码的 wifi, tcpdump一样是会记录任何靠近的默认开启WiFi功能的手机,
只要手机尝试搜索附近的WiFi就会发出Probe requests动作,发生此探测动作就会被tcpdump记录到。(附近的WiFi无线路由器收到手机探测动作,也会回应一个Probe Respond动作.....后面才会有可能发生WiFi连接握手之类的请求)
你不想被记录到,只有暂时关闭手机的WiFi功能,总之你开了WiFi功能,不管你连或者不连WiFi,仅仅靠近ap(WiFi无线路由)而已,都会被有心的tcpdump记忆到你手机的探测动作。
登录后方可回帖
有意思,就是没硬件设备,(●—●),改天去淘宝弄个集成IO网络控制板,也玩玩物联网