【工具】【HA智能家居】主人回家自动开灯,离家自动关灯

By the100s at 2022-11-14 • 1人收藏 • 1460人看过

前提环境:

安装有home assistant(以下简称ha)

安装有mosquitto (mqtt服务端)

有ha可控制的灯


原理:

监视光猫管理页面的无线终端设备列表,存在指定mac设备即被认定为主人回家,否则被认定为离家。


QQ截图20221114220816.png

//自动化操作
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();


aardio工程4光猫在线设备触发开灯.7z


11 个回复 | 最后更新于 2024-05-30
2022-11-14   #1

有意思,就是没硬件设备,(●—●),改天去淘宝弄个集成IO网络控制板,也玩玩物联网

2022-11-14   #2

回复#1 @admin :

某鱼买的13块的sonoff basic(卖家已刷了tasmota固件);windows10安装HassWP_2022.8.6(GitHub上的绿色免装版ha);windows版的mosquitto服务端。合计花费:13块。不要跟说没硬件,半斤肉都不到

2022-11-15   #3

跟起来....

跳起来...

哈哈


2022-11-15   #4

大神可以试试如何连接 emq 服务器,这样更好玩。  aardio应该可以使用 mqtt.js库。 有熟悉的朋友可以展示下哈

2022-11-15   #5

话说,可以搞个定时光照闹钟,到点了把人照醒。

2022-11-15   #6

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


2024-05-16   #7

好久没登录了,上来填坑,一楼的办法非常不好,

后来在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命令

2024-05-24   #8

我噻。。。我以为原来第一种方式是王者了,想不到来了个更

2024-05-24   #9

回复#7 @the100s :

如果遇到的是开放式不需要密码的 wifi,有没有可能实现手机靠近,tcpdump 也可以探测到内容?


2024-05-30   #10

回复#9 @hi_aardio :

是的靠近即刻被记录到。

遇到的是开放式不需要密码的 wifi, tcpdump一样是会记录任何靠近的默认开启WiFi功能的手机,

只要手机尝试搜索附近的WiFi就会发出Probe requests动作,发生此探测动作就会被tcpdump记录到。(附近的WiFi无线路由器收到手机探测动作,也会回应一个Probe Respond动作.....后面才会有可能发生WiFi连接握手之类的请求)

你不想被记录到,只有暂时关闭手机的WiFi功能,总之你开了WiFi功能,不管你连或者不连WiFi,仅仅靠近ap(WiFi无线路由)而已,都会被有心的tcpdump记忆到你手机的探测动作。

2024-05-30   #11

#7楼的代码,已经在刷了OpenWRT路由固件的无线路由器上成功运行过。你们可以尝试刷个玩玩看,需要改的是你们手机的MAC地址,代码里的是假设的aa:bb:cc:dd:ee:f1   aa:bb:cc:dd:ee:f2

登录后方可回帖

登 录
信息栏
 私人小站

本站域名

ChengXu.XYZ

投诉联系:  popdes@126.com



快速上位机开发学习,本站主要记录了学习过程中遇到的问题和解决办法及上位机代码分享

这里主要专注于学习交流和经验分享.
纯私人站,当笔记本用的,学到哪写到哪.
如果侵权,联系 Popdes@126.com

友情链接
Aardio官方
Aardio资源网


才仁机械


网站地图SiteMap

Loading...