Re: Python plugin: Presence detection from wireless router
Posted: Tuesday 19 June 2018 23:36
Open source Home Automation System
https://forum.domoticz.com/
Code: Select all
....
#Select or create icons for devices
sleepingicon="idetect-sleeping"
if sleepingicon not in Images: Domoticz.Image('isleeping.zip').Create()
sleepingiconid=Images[sleepingicon].ID
#Create "Sleeping" device
if 254 not in Devices:
Domoticz.Device(Name="Sleeping", DeviceID="#Sleeping", Unit=254, TypeName="Switch", Used=1, Image=sleepingiconid).Create()
Domoticz.Log("Device created for sleeping state")
...
for dev in Devices:
if dev == 1:
continue
#Check if devices are still in use
Domoticz.Debug("monitoring device: " + Devices[dev].Name)
if Devices[dev].DeviceID in self.monitormacs: #prep for use
Domoticz.Debug(Devices[dev].Name + " is stil in use")
self.devid2domid.update({Devices[dev].DeviceID:dev})
else: #delete device
if dev != 1 and dev != 255 and dev !=254:
if self.deleteobsolete:
Domoticz.Log("deleting device unit: " + str(dev) + " named: " + Devices[dev].Name)
deletecandidates.append(dev)
else:
Devices[dev].Update(nValue=0, sValue="Off", TimedOut=1)
.....
for friendlyid, mac in self.monitormacs.items():
if mac in found:
homecount += 1
self.updatestatus(self.devid2domid[friendlyid], True)
if friendlyid in self.timelastseen:
self.timelastseen.pop(friendlyid, None)
else:
if Devices[254].nValue==1:
Domoticz.Debug("Sleeping, no need to put deivce offline")
else:
if friendlyid in self.timelastseen:
if not datetime.now() - self.timelastseen[friendlyid] > timedelta(seconds=self.graceoffline):
Domoticz.Debug("Check if realy offline: " + str(friendlyid))
else:
Domoticz.Debug("Considered absent: " + str(friendlyid))
self.updatestatus(self.devid2domid[friendlyid], False)
gonecount += 1
else:
self.timelastseen[friendlyid] = datetime.now()
Domoticz.Debug("Seems to have went offline: " + str(friendlyid))
......
def onCommand(self, Unit, Command, Level, Hue):
#only allow the override switch to be operated and only if overrides are enabled
if Unit == 255:
if str(Command)=='On' and self.overrideallow:
self.updatestatus(Unit, True)
self.updatestatus(1, True)
if self.overridefor:
self.overridestart=datetime.now()
if str(Command)=='Off':
self.updatestatus(Unit, False)
self.overridestart=None
if Unit == 254:
if str(Command)=='On':
self.updatestatus(Unit, True)
if str(Command)=='Off':
self.updatestatus(Unit, False)
return
On Asus with Merlin its even more easy: viewtopic.php?f=61&t=15531&hilit=phone+detectionEscApe wrote: ↑Tuesday 19 June 2018 22:08 Thanks! 8 minutes is not that bad. On my ASUS it sometimes took minutes, but would at times take many hours. You might want to check the presence log for a few days to see if it is consistently around 8 minutes. If so, then arp indeed looks like a usable (fall back) option for certain routers.
Code: Select all
#!/bin/sh
presencedetectloop () {
trap "rm -f /var/run/presencedetectord.pid;exit" SIGTERM SIGINT
trap "" SIGHUP
LOOPCOUNT=0
echo Start loop
PHONES='xx:xx:xx:xx:xx:xx|yy:yy:yy:yy:yy:yy'
NOTHERECOUNT=0
while true; do
echo loops $LOOPCOUNT
if [ "$LOOPCOUNT" -eq "0" ]; then
echo Haal huidige status op bij Domoticz
local DOMSTS=$(wget -qO- "http://192.168.0.2:8080/json.htm?type=devices&rid=64" | grep \"Status\"\ \:\ \"On\" )
if [ -n "$DOMSTS" ]; then
LASTSTATUS=On
else
LASTSTATUS=Off
fi
LOOPCOUNT=50
fi
INHOUSE=$(wl -i eth1 assoclist)
INHOUSE=$INHOUSE\ $(wl -i eth2 assoclist)
TEST=$(echo "$INHOUSE" | grep -E "$PHONES")
if [ -n "$TEST" ]; then
STATUS=On
else
STATUS=Off
fi
if [ "$STATUS" == "On" ]; then
NOTHERECOUNT=0
elif [ "$LASTSTATUS" == "On" ]; then
NOTHERECOUNT=$(( NOTHERECOUNT+1 ))
if [ "$NOTHERECOUNT" -lt "5" ]; then
STATUS="On"
echo $NOTHERECOUNT
fi
fi
if [ "$STATUS" != "$LASTSTATUS" ]; then
echo Ga status doorgeven: $STATUS vorige was $LASTSTATUS
RESULT=$(wget -qO- "http://192.168.0.2:8080/json.htm?type=command¶m=switchlight&idx=64&passcode=xxxx&switchcmd=$STATUS")
echo Wget resultaat: $RESULT
RESULT=$(echo $RESULT | grep OK)
if [ -n "$RESULT" ]; then
LASTSTATUS=$STATUS
fi
fi
LOOPCOUNT=$(( LOOPCOUNT-1 ))
echo vorige: $LASTSTATUS huidige: $STATUS test was: $TEST
sleep 10
done
}
if [ -f /var/run/presencedetectord.pid ]; then
if [ "$1" == "stop" ]; then
PID=$(cat /var/run/presencedetectord.pid)
echo Stopping proces $PID
kill $PID
exit
fi
echo Proces is already running. Exit.
exit
else
if [ "$1" == "stop" ]; then
echo Nothing to stop
exit
fi
fi
if [ "$1" == "start" ]; then
presencedetectloop </dev/null >/var/log/presencedetect.log 2>&1 &
echo $! > /var/run/presencedetectord.pid
else
echo $$ > /var/run/presencedetectord.pid
presencedetectloop
fi
Might be worth to consider the Python one from this thread.EscApe wrote: ↑Wednesday 20 June 2018 12:15 That’s how i started a couple of years ago. The script running on my (asus) router. Although mine was a little more elaborate. It would remember the last state and only update domoticz if a status changed (and verify the domoticz state every once in a while). Otherwise it would flood the device’s logs with on, on, on, on every few seconds.
I can share my old script if you like that method better(?) I don’t consider it easier though. Quite the opposite. You’ll have to install scripts on the router, create devices manually and manage the idx/script relationship. The plugin manages the creation and state of devices dynamically. Just add or change a new phone on the settings page and your done. Things like configurable grace period and the override switch also have their benefits.
great that was fast, updatet plugin added #forcegenericEscApe wrote: ↑Wednesday 20 June 2018 13:50 @devros
You can now force the plugin to use brctl (or arp if brctl is unavailable). Just add #forcegeneric behind the routers address (eg: 192.168.0.1#forcegeneric). That seems to be the safest field to combine some settings since a hostname or ip can never contain special characters and it won't break existing configurations.
brctl is now also the fall back when wl, iwinfo etc are not available (even before it tries arp).
Let's see how it holds up when testing longer than a few hours
Thanks for suggesting brctl. It's looking good so far
Code: Select all
2018-06-20 15:35:04.223 (presence) Fetching data from router using ssh
2018-06-20 15:35:04.223 (presence) command: ['sshpass', '-p', 'xxxx', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=1', '[email protected]', "export PATH=/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:$PATH;wlanconfig ath0 list | grep '^..:..:..:..:..:.. ' | cut -d' ' -f1;wlanconfig eth0 list | grep '^..:..:..:..:..:.. ' | cut -d' ' -f1;exit"]
2018-06-20 15:35:04.775 (presence) Returncode ssh command: 0
Ok you convinced me ..... switched to the Python plugin and all works good.EscApe wrote: ↑Wednesday 20 June 2018 13:42 Indeed. No hassle, and device management like every other type of hardware in Domoticz. Replaced your phone? Just change the mac on the configuration page and you are done. You even keep the history as long as you use the same name. Have a houseguest for a few weeks? Add the name and the phone's mac address on the configuration page and remove it when they leave. It is also easier to make it more intelligent, like the override button i added. Last but not least: if you replace your router you might have to get ssh key based authentication up and running again, but the plugin won't require any change or configuration. It will keep monitoring the same mac addresses and controlling the same Domoticz switches. Since the plugin detects the usable commands on the router it should work on a wide variety of routers. Not the (simple) ones without ssh obviously
There's no upside without a downside. Getting ssh working can be a challenge for some. Especially key based. Thats why i added a username/password option which i would not prefer myself. If you set the router to log ssh connections the log will get flooded by connections from the plugin. That's not a big deal, but can be annoying. I have not seen any negative impact on the network, router or domoticz performance, but there will be a bit more traffic and both domoticz and the router run a little more code. I think that's all negligible (comparing a grain of sand to a pebble.... in the dessert ).
Well I've bought myself a new router, the experiabox was crappy anyway.EscApe wrote: ↑Tuesday 19 June 2018 23:03 @drwurn
Yes, that is the router password.
I don't know the experia box, but why would you forward port 22? Port forwarding is normaly used to allow access to a host inside you local network (not being the router) from clients on the internet.
First please try to get ssh acces to the router from your domoticz machine's Linux command line to see if you can get that working. You can google for ssh access to experia box.
If -after that- the plugin fails please enable debug mode, retry and share the log. There's not much to tell from the basic logs.
Code: Select all
pi@raspberrypi:~ $ ssh [email protected]
[email protected]'s password:
admin@RT-AC68U:/tmp/home/root#
Code: Select all
2018-06-20 22:07:39.044 (WiFi Presence) Calling message handler 'onHeartbeat'.
2018-06-20 22:07:39.044 (WiFi Presence) devid2domid: {'phone1': 2}
2018-06-20 22:07:39.044 Error: (WiFi Presence) No usable commandline to check presence. Trying again to detect router capabilities.
2018-06-20 22:07:39.044 Error: (WiFi Presence) If you keep getting this message: check your (authentication) settings and router status.
2018-06-20 22:07:39.044 Error: (WiFi Presence) Make sure your router supports ssh and the commands used by this plugin. If this message persists disable the plugin (for now), or the plugin might flood the Domoticz eventsystem
2018-06-20 22:07:39.044 (WiFi Presence) Checking router capabilities and wireless interfaces
2018-06-20 22:07:39.044 (WiFi Presence) Using password instead of ssh public key authentication (less secure!)
2018-06-20 22:07:39.045 (WiFi Presence) Fetching data from router using ssh
2018-06-20 22:07:39.045 (WiFi Presence) command: ['sshpass', '-p', '<PASS>, 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=2', '[email protected]', '#!/bin/sh\n\t\t\t\t\texport PATH=/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:$PATH\n\t\t\t\t\ttest=$(which wl > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "wl@"\n\t\t\t\t\t\t\tfor iface in $(ifconfig | cut -d \' \' -f1| tr \':\' \'\n\' | grep \'^eth\\|^wlan\')\n\t\t\t\t\t\t\tdo\n\t\t\t\t\t\t\t\t\ttest=$(wl -i $iface assoclist > /dev/null 2>&1)\n\t\t\t\t\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\t\t\t\t\tprintf "$iface "\n\t\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\tdone\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\ttest=$(which iwinfo > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "iwinfo@"\n\t\t\t\t\t\t\tfor iface in $(ifconfig | cut -d \' \' -f1| tr \':\' \'\n\' | grep \'^eth\\|^wlan\\|^ath\')\n\t\t\t\t\t\t\tdo\n\t\t\t\t\t\t\t\t\ttest=$(iwinfo $iface assoclist > /dev/null 2>&1)\n\t\t\t\t\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\t\t\t\t\tprintf "$iface "\n\t\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\tdone\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\ttest=$(which wlanconfig > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "wlanconfig@"\n\t\t\t\t\t\t\tfor iface in $(ifconfig | cut -d \' \' -f1| tr \':\' \'\n\' | grep \'^eth\\|^wlan\\|^ath\')\n\t\t\t\t\t\t\tdo\n\t\t\t\t\t\t\t\t\ttest=$(wlanconfig $iface list > /dev/null 2>&1)\n\t\t\t\t\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\t\t\t\t\tprintf "$iface "\n\t\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\tdone\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\ttest=$(which arp > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "arp"\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\tif [ -f /proc/net/arp ]; then\n\t\t\t\t\t\tprintf "procarp"\n\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\tprintf none']
2018-06-20 22:07:40.053 (WiFi Presence) Returncode ssh command: 5
2018-06-20 22:07:40.053 (WiFi Presence) Output from router: b''
2018-06-20 22:07:40.053 Error: (WiFi Presence) Router authentication failed
2018-06-20 22:07:40.053 Error: (WiFi Presence) Could not determine router capabilities
Code: Select all
2018-06-20 23:15:12.791 (WiFi Presence) Calling message handler 'onHeartbeat'.
2018-06-20 23:15:12.791 Error: (WiFi Presence) 'onHeartbeat' failed 'AttributeError':''BasePlugin' object has no attribute 'beats''.
2018-06-20 23:15:12.791 Error: (WiFi Presence) ----> Line 479 in /home/pi/domoticz/plugins/iDetect/plugin.py, function onHeartbeat
2018-06-20 23:15:12.791 Error: (WiFi Presence) ----> Line 398 in /home/pi/domoticz/plugins/iDetect/plugin.py, function onHeartbeat
Code: Select all
2018-06-20 23:28:06.718 (WiFi Presence) Message handler 'onStop' not callable, ignored.
2018-06-20 23:28:06.913 (WiFi Presence) Exiting work loop...
2018-06-20 23:28:06.913 (WiFi Presence) Stopped.
2018-06-20 23:28:07.146 (WiFi Presence) Initialized version 0.4.1, author 'ESCape'
2018-06-20 23:28:07.199 (WiFi Presence) Debug log level set to: 'true'.
2018-06-20 23:28:07.200 (WiFi Presence) Not running on Windows
2018-06-20 23:28:07.215 (WiFi Presence) Checking if [ssh -V] will run: OK
2018-06-20 23:28:07.225 (WiFi Presence) Checking if [sshpass -V] will run: OK
2018-06-20 23:28:07.225 (WiFi Presence) Monitoring {'phone1': '04:D6:AA:72:9C:D1'} for presence.
2018-06-20 23:28:07.225 (WiFi Presence) Checking router capabilities and wireless interfaces
2018-06-20 23:28:07.225 (WiFi Presence) Using password instead of ssh public key authentication (less secure!)
2018-06-20 23:28:07.225 (WiFi Presence) Fetching data from router using ssh
2018-06-20 23:28:07.225 (WiFi Presence) command: ['sshpass', '-p', '<PASS>', 'ssh', '-o', 'StrictHostKeyChecking=no', '-o', 'ConnectTimeout=2', '[email protected]', '#!/bin/sh\n\t\t\t\t\texport PATH=/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin:/sbin:/bin:$PATH\n\t\t\t\t\ttest=$(which wl > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "wl@"\n\t\t\t\t\t\t\tfor iface in $(ifconfig | cut -d \' \' -f1| tr \':\' \'\n\' | grep \'^eth\\|^wlan\')\n\t\t\t\t\t\t\tdo\n\t\t\t\t\t\t\t\t\ttest=$(wl -i $iface assoclist > /dev/null 2>&1)\n\t\t\t\t\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\t\t\t\t\tprintf "$iface "\n\t\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\tdone\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\ttest=$(which iwinfo > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "iwinfo@"\n\t\t\t\t\t\t\tfor iface in $(ifconfig | cut -d \' \' -f1| tr \':\' \'\n\' | grep \'^eth\\|^wlan\\|^ath\')\n\t\t\t\t\t\t\tdo\n\t\t\t\t\t\t\t\t\ttest=$(iwinfo $iface assoclist > /dev/null 2>&1)\n\t\t\t\t\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\t\t\t\t\tprintf "$iface "\n\t\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\tdone\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\ttest=$(which wlanconfig > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "wlanconfig@"\n\t\t\t\t\t\t\tfor iface in $(ifconfig | cut -d \' \' -f1| tr \':\' \'\n\' | grep \'^eth\\|^wlan\\|^ath\')\n\t\t\t\t\t\t\tdo\n\t\t\t\t\t\t\t\t\ttest=$(wlanconfig $iface list > /dev/null 2>&1)\n\t\t\t\t\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\t\t\t\t\tprintf "$iface "\n\t\t\t\t\t\t\t\t\tfi\n\t\t\t\t\t\t\tdone\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\ttest=$(which arp > /dev/null 2>&1)\n\t\t\t\t\tif [ $? == 0 ]; then\n\t\t\t\t\t\t\tprintf "arp"\n\t\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\tif [ -f /proc/net/arp ]; then\n\t\t\t\t\t\tprintf "procarp"\n\t\t\t\t\t\texit\n\t\t\t\t\tfi\n\t\t\t\t\tprintf none']
2018-06-20 23:28:07.991 (WiFi Presence) Returncode ssh command: 0
2018-06-20 23:28:07.991 (WiFi Presence) Output from router: b'wl@eth1 eth2 '
2018-06-20 23:28:07.991 (WiFi Presence) Parsed data from router: ['wl', 'eth1 eth2 ']
2018-06-20 23:28:07.991 Error: (WiFi Presence) 'onStart' failed 'AttributeError':'module 'Domoticz' has no attribute 'Status''.
2018-06-20 23:28:07.991 Error: (WiFi Presence) ----> Line 475 in /home/pi/domoticz/plugins/iDetect/plugin.py, function onStart
2018-06-20 23:28:07.991 Error: (WiFi Presence) ----> Line 307 in /home/pi/domoticz/plugins/iDetect/plugin.py, function onStart
2018-06-20 23:28:07.991 Error: (WiFi Presence) ----> Line 194 in /home/pi/domoticz/plugins/iDetect/plugin.py, function routercommand