更新:2017-06-30 11:15:57
此帖原方法已弃用,改为blindlight推荐的方法,此方法结合wifi与蓝牙,实现每分钟检测,延时低。
新方法原帖:https://www.domoticz.com/forum/viewtopi ... 23&t=12570
简单介绍:
新方法通过fping来ping手机无线IP来检测wifi在线状态,通过l2ping来检测手机蓝牙mac(只需要手机开启蓝牙,不需要配对)。
脚本中先ping一次wifiIP,如果不通,再检测一次蓝牙,如果还是不通,重复监测一遍wifi蓝牙。
将脚本添加到系统计划任务,每分钟执行一次。可以保证状态更改后一分钟内更新到domoticz。
脚本代码
代码: 全选
#!/bin/bash
# Set Parameters
Name='Bens Mobile Phone(名称随便写)'
domoticzserverip='127.0.0.1:8080' #domoticz服务器IP:端口,这里是
IDX='108'
IP='192.168.0.80' #手机wifiIP,在路由中配置静态IP
bluetoothmac='04:9C:02:57:23:F5' #手机蓝牙mac地址,在关于手机中查看
# First network ping attempt
fping -c1 -b 32 -t1000 $IP 2>/dev/null 1>/dev/null
if [ "$?" = 0 ] ; then
device=$(echo "On")
technology="Wifi 1st attempt"
success="yes"
sleep 1
else
success="no"
technology=''
fi
# First bluetooth ping attempt
if [[ $success != 'yes' ]]; then
bt1=$(l2ping -c1 -s32 -t1 "$bluetoothmac" > /dev/null && echo "On" || echo "Off")
if [[ $bt1 == 'On' ]]; then
device=$(echo "On")
technology="Bluetooth 1st attempt"
success="yes"
fi
fi
# Second network ping attempt
if [[ $success != 'yes' ]]; then
fping -c1 -b 32 -t1000 $IP 2>/dev/null 1>/dev/null
if [ "$?" = 0 ] ; then
device=$(echo "On")
technology="Wifi 2nd attempt"
success="yes"
fi
fi
# Second bluetooth ping attempt
if [[ $success != 'yes' ]]; then
bt1=$(l2ping -c1 -s32 -t1 "$bluetoothmac" > /dev/null && echo "On" || echo "Off")
if [[ $bt1 == 'On' ]]; then
device=$(echo "On")
technology="Bluetooth 2nd attempt"
success="yes"
fi
fi
# If the device is still offline, declare it for processing
if [[ $success != 'yes' ]]; then
device=$(echo "Off")
fi
# Check Online / Offline state of Domoticz device
domoticzstatus=$(curl -s "http://"$domoticzserverip"/json.htm?type=devices&rid="$IDX"" | grep '"Data" :' | awk '{ print $3 }' | sed 's/[!@#\$%",^&*()]//g')
# Compare ping result to Domoticz device status
if [ "$device" = "$domoticzstatus" ] ; then
echo "Status in sync $technology"
else
echo "Status out of sync, correcting..."
if [ "$device" = On ] ; then
echo "$Name" "Online"
curl -s "http://"$domoticzserverip"/json.htm?type=command¶m=switchlight&idx="$IDX"&switchcmd=On" 2>/dev/null 1>/dev/null
else
echo "$Name" "Offline"
curl -s "http://"$domoticzserverip"/json.htm?type=command¶m=switchlight&idx="$IDX"&switchcmd=Off" 2>/dev/null 1>/dev/null
fi
fi
通过监测手机在不在线可间接判断人在不在家
- 此脚本在树莓派上运行正常
- 无需定时执行,仅设置开机启动即可
- 局域网设备扫描使用arp-scan,安装命令 sudo apt-get install arp-scan
- 由于iOS设备的wifi休眠特性,设备离线时无法立即判定离线
person.py
代码: 全选
#!/usr/bin/python
# -*- coding: UTF-8 -*-
import subprocess
import urllib2
from time import sleep
from threading import Thread
#此脚本在树莓派上运行正常
#无需定时执行,仅设置开机启动即可
#需要先安装Python模块urllib2
#局域网设备扫描使用arp-scan,安装命令 sudo apt-get install arp-scan
#由于iOS设备的wifi休眠特性,设备离线时无法立即判定离线
#Domoticz服务器地址及端口号
domoticzserver = "127.0.0.1:8080"
#此方法向Domoticz服务器发送请求
def domoticzrequest (url):
request = urllib2.Request(url)
response = urllib2.urlopen(request)
return response.read()
# 要检测的设备
device = ["myPhone","herPhone"]
# 设备是否会将WIFI休眠,iOS设备请设置1
type = ["0","1"]
# 设备MAC地址
address = ["00:00:00:00:00:00","00:00:00:00:00:00"]
# 设备在Domoticz中对应虚拟开关的IDX
idxs = ["21","22"]
#延时,防止刚开机时获取失败
#print("30秒后开始运行")
sleep(30)
# 记录设备状态
firstRun = [1] * len(device)
presentSent = [0] * len(device)
notPresentSent = [0] * len(device)
counter = [0] * len(device)
# Function that checks for device presence
def whoIsHere(i):
#print("休息30秒,以供主线程完成arp-scan并输出")
sleep(30)
# Loop through checking for devices and counting if they're not present
while True:
# 键盘输入后退出
if stop == True:
print "退出"
exit()
else:
pass
# 设备在线
#print("开始分析output数据")
if address[i] in output:
# 检测到设备在线
#print(device[i] + " 已连接"+bytes(i))
if presentSent[i] == 0:
# 向外输出
#print(device[i] + " 向外输出设备在线")
domoticzrequest("http://"+domoticzserver+"/json.htm?type=command¶m=switchlight&idx="+idxs[i]+"&switchcmd=On")
# Reset counters so another stream isn't sent if the device
# is still present
firstRun[i] = 0
presentSent[i] = 1
notPresentSent[i] = 0
counter[i] = 0
#print("输出在线状态后休息15分钟")
sleep(900)
else:
#print("之前已向外输出,重置计数器并休息15分钟")
counter[i] = 0
sleep(900)
else:
#print(device[i] + " 离线"+bytes(i))
# Wifi会休眠的设备
if type[i] == 1:
# 第一次执行或累计15分钟内30次扫描均离线
if counter[i] == 30 or firstRun[i] == 1:
firstRun[i] = 0
if notPresentSent[i] == 0:
# 未发送离线状态
#print(device[i] + " 向外输出设备离线")
domoticzrequest("http://"+domoticzserver+"/json.htm?type=command¶m=switchlight&idx="+idxs[i]+"&switchcmd=Off")
# 设置已输出
notPresentSent[i] = 1
presentSent[i] = 0
counter[i] = 0
else:
# 发送过离线状态
counter[i] = 0
sleep(30)
else:
# Count how many 30 second intervals have happened since the device
# disappeared from the network
counter[i] = counter[i] + 1
#print(device[i] + "计数器 " + str(counter[i]))
#print("休息30秒")
sleep(30)
else:
# 第一次执行或累计5分钟内10次扫描均离线
if counter[i] == 10 or firstRun[i] == 1:
firstRun[i] = 0
if notPresentSent[i] == 0:
# 未发送离线状态
#print(device[i] + " 向外输出设备离线")
domoticzrequest("http://"+domoticzserver+"/json.htm?type=command¶m=switchlight&idx="+idxs[i]+"&switchcmd=Off")
# 设置已输出
notPresentSent[i] = 1
presentSent[i] = 0
counter[i] = 0
else:
# 发送过离线状态
counter[i] = 0
sleep(30)
else:
# Count how many 30 second intervals have happened since the device
# disappeared from the network
counter[i] = counter[i] + 1
#print(device[i] + "计数器 " + str(counter[i]))
#print("休息30秒")
sleep(30)
# Main thread
try:
global stop
stop = False
# Start the thread(s)
for i in range(len(device)):
t = Thread(target=whoIsHere, args=(i,))
#print("开始进程"+bytes(i))
t.start()
while True:
global output
# 获取局域网所有设备
output = subprocess.check_output("sudo arp-scan --interface=wlan0 --localnet", shell=True)
# 每次扫描间隔30秒
#print("本次扫描结束并已输出到output,30秒后进行下一次扫描...")
sleep(30)
except KeyboardInterrupt:
stop = True
exit()
①为了让py脚本保持后台运行,可以新建一个person.sh文件,文件内容
代码: 全选
#! /bin/sh
python /home/pi/person.py &
代码: 全选
sudo chmod +x /home/pi/person.sh
代码: 全选
sudo nano /etc/rc.local
代码: 全选
sudo sh /home/pi/domoticz/scripts/person.sh