[Bash/Lua] Presence Detection via MAC Address

Moderator: leecollings

ceedebee
Posts: 44
Joined: Sunday 08 March 2015 20:18
Target OS: -
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by ceedebee »

The script runs every minute, so arp scan is executed every minute, with 5 retries. There is an delay in the variable 'outdoorsdelay' to delay the switching off when a phone is not detected (in the example 5 minutes)
BigDog
Posts: 82
Joined: Tuesday 17 September 2013 13:59
Target OS: Raspberry Pi / ODroid
Domoticz version: V3.9269
Location: The Netherlands
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by BigDog »

i like it better with the IDX in the user variable i have larger names and then the string wil be to large :| can someone help me a bit?

the main script and then i 5 minute delay
or the new script but then with IDX instead of name :)

Thanks in advance :)

Greetz bigdog
1X Raspberry4B : Domoticz Version 2023.1 [Linux 5.10.63-v7l+ armv7l]
1X Conbee II : 2.25.3 - 26720700
1X RFXtrx433 USB Firmware:183
1X Mysensors Gateway 1.5 -3
6X ESP8266: Tosmota firmware
Zigbee : 6 Operators, 13 Sensors
lucalg
Posts: 8
Joined: Monday 31 August 2015 17:24
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by lucalg »

Hello to everybody,
i'm sorry if i make a stupid question but i'm very very interested to this feature.

I've read above:

Then the setup: I added three switches in domoticz with the name of the phone owners, but this name can be anything. After that I added a uservariable with the name 'Telefoonlijst' wich means 'Phonelist'. In this variable, per phone, separated by ";" sign three variables: MAC, name of the switch, 0. Followed by "|" symbol before the next phone entry. For example 00:11:22:33:44:55;Phone1;0|66:77:88:88:AA:BB;Phone2;0

Where i have to create this variable?
Can you post me the final code?

Tnx,
Luca
void
Posts: 26
Joined: Wednesday 04 November 2015 10:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by void »

Hi all,

Sorry to dig up such an old post, but for some reason I can't see to get the lua script working.
I keep getting this error in the log:
2015-11-09 15:44:02.623 Error: EventSystem: /home/pi/domoticz/scripts/lua/script_time_Presence.lua:73: bad argument #1 to 'lower' (string expected, got nil)
The exact line there is:

Code: Select all

if tonumber(currenttime) > (tonumber(phone[3]) + outdoorsdelay) and string.lower(switchstate) == 'on' then
Anyone knows if this script is not compatible with the latest version of raspbian+domoticz?

Cheers
jannl
Posts: 625
Joined: Thursday 02 October 2014 6:36
Target OS: Raspberry Pi / ODroid
Domoticz version: 2022.2
Location: Geleen
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by jannl »

You are absolutely sure all the variables used have values?
void
Posts: 26
Joined: Wednesday 04 November 2015 10:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by void »

The only variable in the script is 'phonelist' if my (very limited) scriping reading skills are right.
phoneslist= uservariables['Telefoonlijst']

I've created a Setup > More Options > User Variables > New entry with a String value of:
<MA:CA:DR:RE:SS>;71;0|<MA:CA:DR:RE:SS>;72;0
IDX 71 being phone number 1, 72 the second phone.

Under Switches I've created two virtual switches, name of the two phones.

So I'm pretty sure, but not 100% :)

*EDIT* Yes, the string variable name is Telefoonlijst, as the script expects.
jannl
Posts: 625
Joined: Thursday 02 October 2014 6:36
Target OS: Raspberry Pi / ODroid
Domoticz version: 2022.2
Location: Geleen
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by jannl »

In the if statement in your previous post alone are 4 variables. So please check if they all have correct values
ceedebee
Posts: 44
Joined: Sunday 08 March 2015 20:18
Target OS: -
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by ceedebee »

In my set-up the name of the switch is used in the variable "Telefoonlijst", not the IDX. Like this: <MA:CA:DR:RE:SS>;Phone1;0|<MA:CA:DR:RE:SS>;Phone2;0

(mac address without "<" and ">" signs of course)
void
Posts: 26
Joined: Wednesday 04 November 2015 10:26
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by void »

*EDIT* Well a reboot seems to have fixed it. Apparently the user variable is not being updates correctly.
So after changing it to the switch name instead of IDX and a reboot it works.

Thanks @jannl and @ceebedee for the tips.
Unfortunately changing the user variable from IDX to switch name did not change anything.

Is there a debug mode to run LUA scripts at the console, to see if vars etc are being parsed correctly?
Last edited by void on Wednesday 11 November 2015 12:37, edited 1 time in total.
jannl
Posts: 625
Joined: Thursday 02 October 2014 6:36
Target OS: Raspberry Pi / ODroid
Domoticz version: 2022.2
Location: Geleen
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by jannl »

You can add print statements in LUA and check the values of the variables in de Domoticz logging via the webinterface
kshesq
Posts: 12
Joined: Tuesday 05 January 2016 9:50
Target OS: Linux
Domoticz version: 2021.1
Location: Haarlem
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by kshesq »

Hi, thanks for the script.
The only thing I encounter is that the script slows all commands doen. It seems to make domoticz only handle one command each time the script is run (related to the script or not).
So when I switch on a light domoticz switches on the ligt after running the script.
When I start a scene it takes a long time, because every step is run after each script pass.
Here is a log;

2016-01-09 12:20:07.531 EventSystem: Script event triggered: script_time_on
2016-01-09 12:20:20.124 User: Admin initiated a scene/group command
2016-01-09 12:20:20.124 Activating Scene/Group: [Eten]
2016-01-09 12:20:20.125 Activating Scene/Group Device: Tafel (On)
2016-01-09 12:20:27.103 EventSystem: Script event triggered: script_time_on
2016-01-09 12:20:20.125 (433mhz) Lighting 2 (Tafel)
2016-01-09 12:20:27.155 Activating Scene/Group Device: Raam (On)
2016-01-09 12:20:34.211 EventSystem: Script event triggered: script_time_on
2016-01-09 12:20:27.155 (433mhz) Lighting 2 (Raam)
2016-01-09 12:20:34.263 Activating Scene/Group Device: Zithoek (On)
2016-01-09 12:20:41.241 EventSystem: Script event triggered: script_time_on
2016-01-09 12:20:34.263 (433mhz) Lighting 2 (Zithoek)
2016-01-09 12:20:41.293 Activating Scene/Group Device: Voordeur (On)
2016-01-09 12:20:48.269 EventSystem: Script event triggered: script_time_on
2016-01-09 12:20:41.293 (433mhz) Lighting 2 (Voordeur)

When I am running scenes with the script enabled I get a faster execution;

2016-01-09 12:21:37.159 User: Admin initiated a scene/group command
2016-01-09 12:21:37.160 Activating Scene/Group: [Alles uit]
2016-01-09 12:21:37.160 Activating Scene/Group Device: Raam (Off)
2016-01-09 12:21:37.211 Activating Scene/Group Device: Tafel (Off)
2016-01-09 12:21:37.262 Activating Scene/Group Device: Zithoek (Off)
2016-01-09 12:21:37.313 Activating Scene/Group Device: Mathmos (Off)
2016-01-09 12:21:37.364 Activating Scene/Group Device: Mathmos blimp (Off)
2016-01-09 12:21:37.415 Activating Scene/Group Device: Voordeur (Off)

does anyone have a solution for this slow down?

EDIT: figured it out myself. I put the script in the LUA page in the GUI. When i put it in the LUA folder it worked like a charm. Thanks!
User avatar
Siewert308SW
Posts: 288
Joined: Monday 29 December 2014 15:47
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: The Netherlands
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by Siewert308SW »

@ceedebee

Since today i wanted to try your script, as i am fed up with my router which has a bug with static ip address.
But thats not the issue, i wanna ask you if you know where the following issue is and can be fixed.
Seems like the script runs i a loop and get the following error every 10minutes

Code: Select all

Error: EventSystem: Warning!, lua script /home/pi/domoticz/scripts/lua/script_time_devices.lua has been running for more than 10 seconds
The script runs fine but the error is bugging me.
Setup:
- RPi4 - Domo Stable / Aeotec Z-stick7 / PiHole Unbound Gemini
- RPi4 - PiHole / PiVPN Unbound Gemini
- Synology DS923+ / DS218j
- P1 Gas/Power, SmartGateway watermeter
- Fibaro switches, contacts, plugs, smoke/Co2 ect
- rootfs @ USB HDD
ceedebee
Posts: 44
Joined: Sunday 08 March 2015 20:18
Target OS: -
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by ceedebee »

I have no idea. Script is running ok here. The script will run every minute, I suppose it will end after runing and will be restarted after 1minute. Maybe the arp scan is delayed for some reason?
User avatar
Siewert308SW
Posts: 288
Joined: Monday 29 December 2014 15:47
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: The Netherlands
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by Siewert308SW »

Don't know, running arp-scan manual via shell then i don't see any delays.
For now i can't test anything as the event system is screwed in the latest beta
Setup:
- RPi4 - Domo Stable / Aeotec Z-stick7 / PiHole Unbound Gemini
- RPi4 - PiHole / PiVPN Unbound Gemini
- Synology DS923+ / DS218j
- P1 Gas/Power, SmartGateway watermeter
- Fibaro switches, contacts, plugs, smoke/Co2 ect
- rootfs @ USB HDD
User avatar
Siewert308SW
Posts: 288
Joined: Monday 29 December 2014 15:47
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: The Netherlands
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by Siewert308SW »

Still struggling with the arp-scan methode.
Although all available scripts are working besides snmp scripts as my provider blocked it on my modem/router.
But non of those scripts available could satisfy my needs or having some side effects on the PI.
Like high CPU usage while scanning for multiple devices in the ARP-Table.
Until today i think...

Why didn't i came up with the idea earlier.
I used the device online script by Chopper_Rob for some time now.
And it pings for devices on your network.
While my modem/router has a nasty static ip bug as writter earlier i search a way of using arp instead of ping.

Other scripts using arp are calling the arp in a way which first scans the table then picks the mac and processes it.
And it does that for every device, 1 device or 2 aint a big problem.
But 13 devices which almost all are determine is someone is home is causing issues when using those arp scripts
Every time the arp-scan runs it takes a big chuck of CPU resources which means when Domoticz is at his busiest moment (evening) it get sluggish on triggering events while scanning almost every minute for 13 devices.
Yes every minute as all my scripts/event are relying on almost instant SomeOneHome or not ;-)
Not all are devices are important for the SomeOneHome switch but still.

So after digging into the arp and searching Google for several days i noticed the different commands you can use in shell.
The one i used before was "sudo arp-scan 192.168.178.0/24" which took almost 5 seconds to complete on just one scan and all my network devices it takes 65 seconds.
So the scanning is still running while a new scan is already called and there for slowing down Domoticz and causing issues with triggering events and such.
I could take it to 3 or more minutes but this kills the instant SomeOneHome feature.
Also a side effect is the CPU, the average CPU usage went from 5% t0 40%.
So i search a way for only scanning for one device at a time.
Somewhere i found a command "sudo arp -n | grep -o <mac address>" which takes less then a second to check the arp-table and only search for one device.
This way the process of determine a device is on/offline takes less time and resources.
And i don't have to worry about ip addresses which change weekly and me seeking the correspondent ip to mac and adjusting them over and over again.

So from there i just made a little adjustment to Chopper_Rob his check_device_online.py script
And replaced the ping command with the arp scan and (if i did right) added some extra imports to be able to run arp command.
Amended the crontab command from ip to my mac address:

# Siewert Laptop
*/10 * * * * sudo python /home/pi/domoticz/scripts/python/check_devices_online.py 192.168.178.2 119 60 60 > /dev/null 2>&1

to

# Siewert Laptop
*/10 * * * * sudo python /home/pi/domoticz/scripts/python/check_devices_online.py xx:xx:xx:xx:xx:xx 119 60 60 > /dev/null 2>&1

This went well and running fine, haven't test it yet with all my devices only tested it with three devices.
I did notice one device (Wife here android phone) is lost from the arp-table from time to time while online.
Setting the cooldown time a bit higher solved the issue.
Tomorrow i will test with all my devices and see how it behaves.
But for now it does work as planned.

If some else wants to test Chopper_Rob his adjusted script then you can use the script below.
Usage of the script is the same as written in the wiki only with use of mac addresses instead of ip.
Be aware you have to install arp-scan.

Code: Select all

#!/usr/bin/python
#   Title: check_device_online_arp.py
#   Original author: Chopper_Rob
#   Modified for ARP by    : Siewert308SW
#   Date: 27-02-2016
#   Info: Checks the presence of the given device on the network by checking your router by ARP Table and reports back to domoticz
#   Version : 1.0
 
import sys
import datetime
import time
import os
import subprocess
import urllib2
import json
import base64
import socket
import string
import asynchat
import asyncore


# Settings for Domoticz
domoticzserver="127.0.0.1:8080"
domoticzusername = " "
domoticzpassword = " "
 
# If enabled. The script will log to the file _.log
# Logging to file only happens after the check for other instances, before that it only prints to screen.
log_to_file = False
 
# The script supports two types to check if another instance of the script is running.
# One will use the ps command, but this does not work on all machine (Synology has problems)
# The other option is to create a pid file named _.pid. The script will update the timestamp
# every interval. If a new instance of the script spawns it will check the age of the pid file.
# If the file doesn't exist or it is older then 3 * Interval it will keep running, otherwise is stops.
# Please chose the option you want to use "ps" or "pid", if this option is kept empty it will not check and just run.
check_for_instances = "pid"
 
 
 
# DO NOT CHANGE BEYOND THIS LINE
if len(sys.argv) != 5 :
  print ("Not enough parameters. Needs %Host %Switchid %Interval %Cooldownperiod.")
  sys.exit(0)
 
device=sys.argv[1]
switchid=sys.argv[2]
interval=sys.argv[3]
cooldownperiod=sys.argv[4]
previousstate=-1
lastsuccess=datetime.datetime.now()
lastreported=-1
base64string = base64.encodestring('%s:%s' % (domoticzusername, domoticzpassword)).replace('\n', '')
domoticzurl = 'http://'+domoticzserver+'/json.htm?type=devices&filter=all&used=true&order=Name'
 
if check_for_instances.lower() == "pid":
  pidfile = sys.argv[0] + '_' + sys.argv[1] + '.pid'
  if os.path.isfile( pidfile ):
    print datetime.datetime.now().strftime("%H:%M:%S") + "- pid file exists"
    if (time.time() - os.path.getmtime(pidfile)) < (float(interval) * 3):
      print datetime.datetime.now().strftime("%H:%M:%S") + "- script seems to be still running, exiting"
      print datetime.datetime.now().strftime("%H:%M:%S") + "- If this is not correct, please delete file " + pidfile
      sys.exit(0)
    else:
      print datetime.datetime.now().strftime("%H:%M:%S") + "- Seems to be an old file, ignoring."
  else:
    open(pidfile, 'w').close()
 
if check_for_instances.lower() == "ps":
  if int(subprocess.check_output('ps x | grep \'' + sys.argv[0] + ' ' + sys.argv[1] + '\' | grep -cv grep', shell=True)) > 2 :
    print (datetime.datetime.now().strftime("%H:%M:%S") + "- script already running. exiting.")
    sys.exit(0)
 
def log(message):
  print message
  if log_to_file == True:
    logfile = open(sys.argv[0] + '_' + sys.argv[1] + '.log', "a")
    logfile.write(message + "\n")
    logfile.close()
 
def domoticzstatus ():
  json_object = json.loads(domoticzrequest(domoticzurl))
  status = 0
  switchfound = False
  if json_object["status"] == "OK":
    for i, v in enumerate(json_object["result"]):
      if json_object["result"][i]["idx"] == switchid and "Lighting" in json_object["result"][i]["Type"] :
        switchfound = True
        if json_object["result"][i]["Status"] == "On":
          status = 1
        if json_object["result"][i]["Status"] == "Off":
          status = 0
  if switchfound == False: print (datetime.datetime.now().strftime("%H:%M:%S") + "- Error. Could not find switch idx in Domoticz response. Defaulting to switch off.")
  return status
 
def domoticzrequest (url):
  request = urllib2.Request(url)
  request.add_header("Authorization", "Basic %s" % base64string)
  response = urllib2.urlopen(request)
  return response.read()
 
log (datetime.datetime.now().strftime("%H:%M:%S") + "- script started.")
 
lastreported = domoticzstatus()
if lastreported == 1 :
  log (datetime.datetime.now().strftime("%H:%M:%S") + "- according to Domoticz, " + device + " is online")
if lastreported == 0 :
  log (datetime.datetime.now().strftime("%H:%M:%S") + "- according to Domoticz, " + device + " is offline")
 
while 1==1:
  currentstate = subprocess.call('sudo arp -n | grep -o "' + device + '" > /dev/null', shell=True)
  if currentstate == 0 : lastsuccess=datetime.datetime.now()
  if currentstate == 0 and currentstate != previousstate and lastreported == 1 :
    log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, no need to tell Domoticz")
  if currentstate == 0 and currentstate != previousstate and lastreported != 1 :
    if domoticzstatus() == 0 :
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, tell Domoticz it's back")
      domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0")
    else:
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, but Domoticz already knew")
    lastreported=1
 
  if currentstate == 1 and currentstate != previousstate :
    log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, waiting for it to come back")
 
  if currentstate == 1 and (datetime.datetime.now()-lastsuccess).total_seconds() > float(cooldownperiod) and lastreported != 0 :
    if domoticzstatus() == 1 :
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, tell Domoticz it's gone")
      domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0")
    else:
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, but Domoticz already knew")
    lastreported=0
 
  time.sleep (float(interval))
 
  previousstate=currentstate
  if check_for_instances.lower() == "pid": open(pidfile, 'w').close()
Setup:
- RPi4 - Domo Stable / Aeotec Z-stick7 / PiHole Unbound Gemini
- RPi4 - PiHole / PiVPN Unbound Gemini
- Synology DS923+ / DS218j
- P1 Gas/Power, SmartGateway watermeter
- Fibaro switches, contacts, plugs, smoke/Co2 ect
- rootfs @ USB HDD
User avatar
bizziebis
Posts: 182
Joined: Saturday 19 October 2013 14:00
Target OS: Raspberry Pi / ODroid
Domoticz version: 3.8805
Location: The Netherlands
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by bizziebis »

I've tried your modified script and it seems to work half for me.

When I run 'sudo arp -n' I get an arp table which looks cached. It doesn't change when I remove a device from my wifi network.
The table does update after I run 'sudo arp-scan 10.0.0.0/24'.

Are you sure your table does get updated on it's own by using only 'sudo arp -n' ?
User avatar
Siewert308SW
Posts: 288
Joined: Monday 29 December 2014 15:47
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: The Netherlands
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by Siewert308SW »

bizziebis wrote:I've tried your modified script and it seems to work half for me.

When I run 'sudo arp -n' I get an arp table which looks cached. It doesn't change when I remove a device from my wifi network.
The table does update after I run 'sudo arp-scan 10.0.0.0/24'.

Are you sure your table does get updated on it's own by using only 'sudo arp -n' ?
Yep... Ran into some issues this morning also and looking into it.
When using arp-scan it takes to much resources and slowing down domoticz when scanning for more then 3 devices.

Arp is cached and noticed some devices get removed while still online.
And some even refuse to be cached.
Still Arp is faster and less resources.
I did notice when pinging a device from the raspberry it will be available in Arp for some time.

So I did some work around.
I created a bash which fpings my entire network every 5 minutes.
This way the Arp is up to date and the arp - n | grep -o <mac> works as expected.
Devices going offline are really going offline within the minute.
But sometimes there is a delay of devices coming online due to a empty arp but when the fping kicks in it is coming line.
More important is that going offline is fast to suit my needs for SomeOneHome

For now testing it for a few hours.
But if it works then we have something which runs on arp, no need for static IPs on my buggy modem/router and less resource taken.
Only (no python experience) need to implant the fping in the script to kick in as sidecheck when a device is reported online and the script awaits the cool down periode.
Setup:
- RPi4 - Domo Stable / Aeotec Z-stick7 / PiHole Unbound Gemini
- RPi4 - PiHole / PiVPN Unbound Gemini
- Synology DS923+ / DS218j
- P1 Gas/Power, SmartGateway watermeter
- Fibaro switches, contacts, plugs, smoke/Co2 ect
- rootfs @ USB HDD
User avatar
Westcott
Posts: 423
Joined: Tuesday 09 December 2014 17:04
Target OS: Raspberry Pi / ODroid
Domoticz version: Beta
Location: UK - Glos
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by Westcott »

Hi Siewert308SW,

Are you using something like fping -c 1 -g 172.16.176.0/24
It's possible that this does the same ping -b -c1 172.16.176.255

Anyhow I've taken the liberty of trying to implement the Python script directly in Lua.
So far I'm capturing the active arp entries in a table to get the current IP address for each MAC address.

Code: Select all

macaddr = {}
data = assert(io.popen('arp -n'))

for line in data:lines() do
    ip  = string.match(line, "172%.16%.176%.%d+")
    mac = string.match(line, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
    if (ip ~= nil and mac ~= nil) then
        macaddr[mac] = ip
    end
end
  
data:close()
Zwave - Sigma Z+ stick, Fibaro, Horstmann, Neo Coolcam, EUROtronic
RFlink - IR detectors and temperatures
Wifi - YeeLights, ESP32s, Anoop sockets
Zigbee - lots with zigbee2mqtt and ZbBridge
User avatar
Siewert308SW
Posts: 288
Joined: Monday 29 December 2014 15:47
Target OS: Raspberry Pi / ODroid
Domoticz version: Stable
Location: The Netherlands
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by Siewert308SW »

Westcott wrote:Hi Siewert308SW,

Are you using something like fping -c 1 -g 172.16.176.0/24
It's possible that this does the same ping -b -c1 172.16.176.255

Anyhow I've taken the liberty of trying to implement the Python script directly in Lua.
So far I'm capturing the active arp entries in a table to get the current IP address for each MAC address.

Code: Select all

macaddr = {}
data = assert(io.popen('arp -n'))

for line in data:lines() do
    ip  = string.match(line, "172%.16%.176%.%d+")
    mac = string.match(line, "%x%x:%x%x:%x%x:%x%x:%x%x:%x%x")
    if (ip ~= nil and mac ~= nil) then
        macaddr[mac] = ip
    end
end
  
data:close()
Yep...
Use that fping command, the ping command you suggested doesn't work overhere.
It only tries to scan the .255 ip and not the entire range.

Have been running the following combination since this morning and until now no issues and devices are triggering the virtual switches as i think it would do.
My cooldown and report time are 1minute and this works great for all devices like t.v, phones, mediabox and laptops.
Have a simple bash with "fping -c 1 -g 192.168.178.0/24" which is called via crontab every 3 minutes and takes 2 seconds to complete.
Then i run the python script (by Chopper_Rob) which i adjusted a little bit (just arp command).

Code: Select all

#!/usr/bin/python
#   Title: check_device_online_arp.py
#   Original author: Chopper_Rob
#   Modified for ARP by    : Siewert308SW
#   Date: 27-02-2016
#   Info: Checks the presence of the given device on the network by checking your router by ARP Table and reports back to domoticz
#   Version : 1.0
 
import sys
import datetime
import time
import os
import subprocess
import urllib2
import json
import base64
import socket
import string
import asynchat
import asyncore


# Settings for Domoticz
domoticzserver="127.0.0.1:8080"
domoticzusername = " "
domoticzpassword = " "
 
# If enabled. The script will log to the file _.log
# Logging to file only happens after the check for other instances, before that it only prints to screen.
log_to_file = False
 
# The script supports two types to check if another instance of the script is running.
# One will use the ps command, but this does not work on all machine (Synology has problems)
# The other option is to create a pid file named _.pid. The script will update the timestamp
# every interval. If a new instance of the script spawns it will check the age of the pid file.
# If the file doesn't exist or it is older then 3 * Interval it will keep running, otherwise is stops.
# Please chose the option you want to use "ps" or "pid", if this option is kept empty it will not check and just run.
check_for_instances = "pid"
 
 
 
# DO NOT CHANGE BEYOND THIS LINE
if len(sys.argv) != 5 :
  print ("Not enough parameters. Needs %Host %Switchid %Interval %Cooldownperiod.")
  sys.exit(0)
 
device=sys.argv[1]
switchid=sys.argv[2]
interval=sys.argv[3]
cooldownperiod=sys.argv[4]
previousstate=-1
lastsuccess=datetime.datetime.now()
lastreported=-1
base64string = base64.encodestring('%s:%s' % (domoticzusername, domoticzpassword)).replace('\n', '')
domoticzurl = 'http://'+domoticzserver+'/json.htm?type=devices&filter=all&used=true&order=Name'
 
if check_for_instances.lower() == "pid":
  pidfile = sys.argv[0] + '_' + sys.argv[1] + '.pid'
  if os.path.isfile( pidfile ):
    print datetime.datetime.now().strftime("%H:%M:%S") + "- pid file exists"
    if (time.time() - os.path.getmtime(pidfile)) < (float(interval) * 3):
      print datetime.datetime.now().strftime("%H:%M:%S") + "- script seems to be still running, exiting"
      print datetime.datetime.now().strftime("%H:%M:%S") + "- If this is not correct, please delete file " + pidfile
      sys.exit(0)
    else:
      print datetime.datetime.now().strftime("%H:%M:%S") + "- Seems to be an old file, ignoring."
  else:
    open(pidfile, 'w').close()
 
if check_for_instances.lower() == "ps":
  if int(subprocess.check_output('ps x | grep \'' + sys.argv[0] + ' ' + sys.argv[1] + '\' | grep -cv grep', shell=True)) > 2 :
    print (datetime.datetime.now().strftime("%H:%M:%S") + "- script already running. exiting.")
    sys.exit(0)
 
def log(message):
  print message
  if log_to_file == True:
    logfile = open(sys.argv[0] + '_' + sys.argv[1] + '.log', "a")
    logfile.write(message + "\n")
    logfile.close()
 
def domoticzstatus ():
  json_object = json.loads(domoticzrequest(domoticzurl))
  status = 0
  switchfound = False
  if json_object["status"] == "OK":
    for i, v in enumerate(json_object["result"]):
      if json_object["result"][i]["idx"] == switchid and "Lighting" in json_object["result"][i]["Type"] :
        switchfound = True
        if json_object["result"][i]["Status"] == "On":
          status = 1
        if json_object["result"][i]["Status"] == "Off":
          status = 0
  if switchfound == False: print (datetime.datetime.now().strftime("%H:%M:%S") + "- Error. Could not find switch idx in Domoticz response. Defaulting to switch off.")
  return status
 
def domoticzrequest (url):
  request = urllib2.Request(url)
  request.add_header("Authorization", "Basic %s" % base64string)
  response = urllib2.urlopen(request)
  return response.read()
 
log (datetime.datetime.now().strftime("%H:%M:%S") + "- script started.")
 
lastreported = domoticzstatus()
if lastreported == 1 :
  log (datetime.datetime.now().strftime("%H:%M:%S") + "- according to Domoticz, " + device + " is online")
if lastreported == 0 :
  log (datetime.datetime.now().strftime("%H:%M:%S") + "- according to Domoticz, " + device + " is offline")
 
while 1==1:
  currentstate = subprocess.call('sudo arp -n | grep -o "' + device + '" > /dev/null', shell=True)
  if currentstate == 0 : lastsuccess=datetime.datetime.now()
  if currentstate == 0 and currentstate != previousstate and lastreported == 1 :
    log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, no need to tell Domoticz")
  if currentstate == 0 and currentstate != previousstate and lastreported != 1 :
    if domoticzstatus() == 0 :
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, tell Domoticz it's back")
      domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=On&level=0")
    else:
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " online, but Domoticz already knew")
    lastreported=1
 
  if currentstate == 1 and currentstate != previousstate :
    log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, waiting for it to come back")
 
  if currentstate == 1 and (datetime.datetime.now()-lastsuccess).total_seconds() > float(cooldownperiod) and lastreported != 0 :
    if domoticzstatus() == 1 :
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, tell Domoticz it's gone")
      domoticzrequest("http://" + domoticzserver + "/json.htm?type=command&param=switchlight&idx=" + switchid + "&switchcmd=Off&level=0")
    else:
      log (datetime.datetime.now().strftime("%H:%M:%S") + "- " + device + " offline, but Domoticz already knew")
    lastreported=0
 
  time.sleep (float(interval))
 
  previousstate=currentstate
  if check_for_instances.lower() == "pid": open(pidfile, 'w').close()
Which is called via crontab with the follow line as we know from his wiki but now with a mac adress instead of a ip

Code: Select all

# Siewert GSM
*/10 * * * * sudo python /home/pi/domoticz/scripts/python/check_devices_online_arp.py xx:xx:xx:xx:xx:xx 209 60 60 > /dev/null 2>&1
Until now it works as planned.
One little downside, it uses a bit more cpu resources and went from a average 5/6% usage to 12%.
But hey... it works and i don't have to worry that my crappy modem/router provided by my provider screws up the static IPs again.
For now i leave it as it is a will see how it works and keeps working.
Setup:
- RPi4 - Domo Stable / Aeotec Z-stick7 / PiHole Unbound Gemini
- RPi4 - PiHole / PiVPN Unbound Gemini
- Synology DS923+ / DS218j
- P1 Gas/Power, SmartGateway watermeter
- Fibaro switches, contacts, plugs, smoke/Co2 ect
- rootfs @ USB HDD
TheFobion
Posts: 1
Joined: Thursday 21 December 2017 16:46
Target OS: Windows
Domoticz version:
Contact:

Re: [Bash/Lua] Presence Detection via MAC Address

Post by TheFobion »

Im not so long a domoticz user, am i doing something wrong here?

I copied the code into the domoticz events as a lua.

In the log i get the following error:

2017-12-21 16:49:00.977 Error: EventSystem: in script_time_Presence.lua: [string "function splitString(str, delim, maxNb) ..."]:73: bad argument #1 to 'lower' (string expected, got nil)
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest