我正在尝试一些家庭自动化。我的目标是在我的 Android 手机离开我家的 Wifi 时发送一个 HTTP 请求,并在它重新加入时发送一个不同的 HTTP 请求。目标是当我离开家时 - 更具体地说,当我的手机离开家时 - 我的 IP 摄像机的运动检测已启用。然后,当我回到家时,它就解除了武装。IP 摄像机有一个 HTTP 接口,可以通过编程方式进行布防和撤防。
这意味着当我不在家时,网络摄像头会在检测到前门有动作时向我发送电子邮件。因为我的手机在我真正进入家前大约一分钟重新加入了 Wifi,所以在我走进门之前,运动检测被解除,因此我没有收到自己进来的警报。这也意味着因为我的手机在 Wifi 上当我走出门时,我也没有听到自己走出的警报。
我目前的方法涉及在我的 LAN 上运行 24/7 的 Linux 服务器上每分钟运行一个 cron 作业。它由两个 Bash 脚本组成。一个检测到我1
的手机的存在(如果手机存在则返回,0
如果不存在):
cat /usr/local/bin/detect-phone.sh
#!/bin/bash
arping -D -c 10 -I eth0 nexus4
...以及编写脚本以进行一些自动化的其他用户。它用于arping
检测网络上的设备以及 0 字节文件的存在/tmp/phone-presence
。如果一个人说电话存在,而另一个人不存在,那么它会发送必要的 HTTP 请求来启用或解除网络摄像头上的运动检测。
cat /usr/local/bin/toggle-webcam-alarm.sh
#!/bin/bash
/usr/local/bin/detect-phone.sh &> /dev/null
IS_HOME_NOW=$?
WAS_ALREADY_HOME=0
if [[ -f '/tmp/phone-presence' ]]; then
WAS_ALREADY_HOME=1
fi
ENABLE_WEBCAM=''
if [[ "$WAS_ALREADY_HOME" -eq 0 && "$IS_HOME_NOW" -eq 1 ]]; then
/usr/bin/logger "Phone just joined network, disarming webcam alarm"
ENABLE_WEBCAM=0
> /tmp/phone-presence
elif [[ "$WAS_ALREADY_HOME" -eq 1 && "$IS_HOME_NOW" -eq 0 ]]; then
/usr/bin/logger "Phone just left network, arming webcam alarm"
ENABLE_WEBCAM=1
rm /tmp/phone-presence
fi
if [[ ! -z "$ENABLE_WEBCAM" ]]; then
/usr/bin/curl "...some URL that accepts $ENABLE_WEBCAM..." &> /dev/null
fi
这确实有效,但存在检测不可靠。我的日志中充满了以下条目:
tail /var/log/messages
...
Sep 6 10:37:11 logger: Phone just left network, arming webcam alarm
Sep 6 10:38:01 logger: Phone just joined network, disarming webcam alarm
Sep 6 10:47:11 logger: Phone just left network, arming webcam alarm
Sep 6 10:48:02 logger: Phone just joined network, disarming webcam alarm
这些条目并不是因为我离开了家,也不是因为我根本没有碰过我的手机。我的手机应该一直在 Wifi 网络上(好吧,我至少没有告诉它断开连接,而且它有很强的信号)。
所以,我目前的解决方案并不可靠。当我进出时,我偶尔会通过电子邮件收到一张自己的照片。-c
增加使用for指定的计数arping
通常不会对提高手机检测的可靠性产生影响,此外,如果我将其设置得高得离谱,随着 cron 作业每分钟运行一次,它就会开始导致问题。
我真的不介意观察手机离开家是否需要额外的几分钟,但是从我的手机实际重新加入 Wifi 到我的网络摄像头运动检测被解除之间需要一分钟或更短的时间,所以我没有得到我自己的警报。网络摄像头不能在我在家时错误地武装,也不能在我离家时被错误地解除武装。
我考虑过但不知道如何实现的其他一些方法:
- 每分钟通过 SNMP 查询我的路由器(运行 Tomato)以查看设备是否仍在网络上,而不是使用
arping
. - 在路由器上配置
dnsmasq
以在由于电话连接到 Wifi 而向电话发出 DHCP 租约时运行脚本。但是,我不知道在电话掉线的相反情况下这将如何工作。电话有一个静态 DHCP 地址,因此虽然分配给电话的 IP 永远不会改变,但它仍然通过 DHCP 请求一个。 - 使用Llama处理存在检测。我已经在使用 Llama 根据我的位置成功地在我的手机上自动执行一些操作。当手机加入 Wifi 时发送请求很好,但离开 Wifi 时则不行,因为这两个HTTP 请求都必须在 LAN 上发送:它们包含敏感数据。现在,我确实可以选择使用 Apache 作为代理。我有一个运行面向公众的受 SSL 保护的 Apache 实例的 Linux 服务器,如果需要,我可以(好吧,在帮助下)将其配置为允许通过 Internet 上的 SSL 发出请求,然后转发到网络摄像头局域网。这样,HTTP 请求可以通过 Internet 发送,但由于无法猜测 URL,没有人能够访问它们,因为请求将被加密。
那么,您建议我采取什么方法来可靠地处理这种情况?再次,高层次的目标:当我的手机离开家时发送一个 HTTP 请求,并在它回到家时发送一个不同的请求。
感谢您迄今为止的建议。以下是一些更新:
- 我的手机无法可靠地响应正常的 ICMP ping。有时它会立即回复,有时它会超时。
- 番茄确实有
wl
,但似乎很不准确。特别是,它认为一个几个月没有在我的局域网上的设备仍然存在并且具有良好的信号强度。这似乎不太可能,因为它放在架子上,电池已卸下。 - 我对使用 IFTTT 没有任何问题(尽管我最初更喜欢完全本地的东西)。但是,虽然它可以轻松处理地理围栏方面,但我看不出它如何实际执行必要的触发器来武装和解除需要发送这两个 HTTP 请求的网络摄像头警报。
- 感谢 Java 类的建议,但除非事情变得非常绝望,否则我宁愿不必编写整个 Android 应用程序来处理这种情况。此外,借助 Llama 和 IFTTT,已经有多种选择可以处理地理围栏问题。Llama 还可以在 Wifi 连接或断开连接时执行各种操作。
我想我确实找到了一种显着提高当前方法可靠性的arping
方法。我在 Android 的设置中关闭了“Wi-Fi 优化”。从那以后,在过去 8 小时内,我的日志中只出现了一次误报下降,而通常情况下大约是每小时一次。我将禁用此设置一段时间,看看它是否真的有帮助。我的理论是它使 Wifi 连接更可靠地保持活动状态,因此手机更有可能响应任何 Wifi 流量。
我还能够为这两个请求设置 Apache SSL 代理(一个用于启用网络摄像头警报,另一个用于解除警报),因此,如果需要,我现在可以通过 Internet 安全地发送这些请求。
看了几天的日志,关闭手机上的“Wifi优化”后,现在看起来完全可靠了。如果一段时间后手机上没有程序或服务使用它,我猜 Wifi 连接有时会休眠并掉线。