[Bash/Lua] Presence Detection via MAC Address

Moderator: leecollings

dadogiobbe
Posts: 3
Joined: Friday 23 May 2014 19:46
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

[Bash/Lua] Presence Detection via MAC Address

Post by dadogiobbe »

i wrote a script to detect presence of 1 or multiple devices in the home using MAC address of devices...

i obtain it using arp-scan

you have to create:

a virtual switch for every device to poll;
a variable (PRESENCE_LIST) in this format: MAC_Address1;IDX1|MAC2;IDX2 ....
if you have only 1 device it's like 11:22:33:44:55:66;100

i have a time script that launch a bash script to poll the device and send json command to domoticz to switch on or off the assigned virtual switch.

it's perfect and very quick (~2 seconds in my lan with 15 devices connected) and it's IP independent...


this is the script_time_Presence.lua

Code: Select all

function splitString(str, delim, maxNb)
    -- Eliminate bad cases...
    if string.find(str, delim) == nil then
        return { str }
    end
    if maxNb == nil or maxNb < 1 then
        maxNb = 0    -- No limit
    end
    local result = {}
    local pat = "(.-)" .. delim .. "()"
    local nb = 0
    local lastPos
    for part, pos in string.gmatch(str, pat) do
        nb = nb + 1
        result[nb] = part
        lastPos = pos
        if nb == maxNb then break end
    end
    -- Handle the last field
    if nb ~= maxNb then
        result[nb + 1] = string.sub(str, lastPos)
    end
    return result
end


commandArray = {}
maclist= uservariables['PRESENCE_LIST']
Lines=splitString(maclist,"|")

for i,line in pairs(Lines) do
	--print (i.." "..line)
	macs=splitString(line,";")
	print ("MAC Address to Poll: "..macs[1].." On IDX:"..macs[2])
        execcommand="sudo /home/pi/domoticz/scripts/bash/Check_MAC.sh "..macs[1].." "..macs[2].." &"
 	os.execute(execcommand) 

end
and this the Check_MAC.sh bash script

Code: Select all

#!/bin/bash
MAC=$1
IDX=$2

sudo arp-scan --localnet | grep -e $MAC 

if [ $? -eq 1 ]
then
echo "Device $MAC Not in LOCAL LAN"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=$IDX&switchcmd=Off"
else
echo "Device $MAC in LOCAL LAN"
curl "http://127.0.0.1:8080/json.htm?type=command&param=switchlight&idx=$IDX&switchcmd=On"
fi
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 »

I think this depends on how many switches you have in your network......

And this also depends on wifi being on.
dadogiobbe
Posts: 3
Joined: Friday 23 May 2014 19:46
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

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

Post by dadogiobbe »

i have 4 switches and 2 access points...
10 devices are on cable lan and 5 in wireless...

if you want you could filter hosts to check with arp-scan filters...like ip range, hostnames,....

in this way it's faster...
rijo78
Posts: 9
Joined: Monday 30 March 2015 20:47
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10717
Contact:

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

Post by rijo78 »

Hi, I love this idea, but I don't seem to get this working.
Maybe I have the mac-dress in the wrong place?

I have placed this script in domoticz/scripts/lua folder. The bash script is placed in the bash folder.

Could you help me out?

function splitString(str, delim, maxNb)
-- Eliminate bad cases...
if string.find(str, delim) == nil then
return { str }
end
if maxNb == nil or maxNb < 1 then
maxNb = 0 -- No limit
end
local result = {}
local pat = "(.-)" .. delim .. "()"
local nb = 0
local lastPos
for part, pos in string.gmatch(str, pat) do
nb = nb + 1
result[nb] = part
lastPos = pos
if nb == maxNb then break end
end
-- Handle the last field
if nb ~= maxNb then
result[nb + 1] = string.sub(str, lastPos)
end
return result
end


commandArray = {}
maclist= uservariables '44:xx:eb:xx:xx:xx;77|xx:6c:xx:xx:94:xx;78'
Lines=splitString(maclist,"|")

for i,line in pairs(Lines) do
--print (i.." "..line)
macs=splitString(line,";")
print ("MAC Address to Poll: "..macs[1].." On IDX:"..macs[2])
execcommand="sudo /home/pi/domoticz/scripts/bash/Check_MAC.sh "..macs[1].." "..macs[2]..$
os.execute(execcommand)
Immo
Posts: 19
Joined: Wednesday 11 February 2015 11:01
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

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

Post by Immo »

Useless for iphones or any other phone that switches off the wifi in standby.
it will keep telling you you're home and left every other minute or so..
rijo78
Posts: 9
Joined: Monday 30 March 2015 20:47
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10717
Contact:

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

Post by rijo78 »

I don't have that problem. My Android phone does not switch off wifi
rijo78
Posts: 9
Joined: Monday 30 March 2015 20:47
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10717
Contact:

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

Post by rijo78 »

I have got it working now with another script from http://www.domoticz.com/forum/viewtopic ... 20#p27020.
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 »

Nice script, I took the liberty to change it a bit so you don't need to use the bash script anymore.
Why did you use this bash script anyway? It seems to me it's a bit nicer to have it all in one script.
realwheel
Posts: 1
Joined: Monday 06 April 2015 21:20
Target OS: Raspberry Pi / ODroid
Domoticz version:
Contact:

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

Post by realwheel »

Can you please post your version of the script which does not require the bash script anymore?
Thanks!
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 am just a beginner in lua coding, so maybe some improvements do apply (the script is not tested through and through):

Code: Select all

function splitString(str, delim, maxNb)
  -- Eliminate bad cases...
  if string.find(str, delim) == nil then
    return { str }
  end

  if maxNb == nil or maxNb < 1 then
    maxNb = 0    -- No limit
  end

  local result = {}
  local pat = "(.-)" .. delim .. "()"
  local nb = 0
  local lastPos
  for part, pos in string.gmatch(str, pat) do
    nb = nb + 1
    result[nb] = part
    lastPos = pos
    if nb == maxNb then break end
  end
  -- Handle the last field
  if nb ~= maxNb then
    result[nb + 1] = string.sub(str, lastPos)
  end

  return result

end


commandArray = {}

--Get the list of phones to check on	
phoneslist= uservariables['Telefoonlijst']

--Do an arp-scan on the localnet
--and search for the mac adresses
if phoneslist ~= nil then

  local newphonelist =""
  local currenttime = os.time()
  local outdoorsdelay = 5 * 60 

  --do the arp scan and store the result
  local command = "sudo arp-scan --interface=eth0 192.168.xxx.1-192.168.xxx.yyy --retry=5 --ignoredups"
  local handle = io.popen(command)
  local result = handle:read("*all")
  handle:close()
  
  --Get a list of all phones
  phones=splitString(phoneslist,"|")

  --Search arp-scan result for presence of MAC for each phone
  for i,line in pairs(phones) do

    --Get the data for this phone
    phone=splitString(line,";")
    --and the switch state
    switchstate = otherdevices[phone[2]]


    --Fill a new list with phones
    if i > 1 then newphonelist = newphonelist.."|" end

    newphonelist = newphonelist..phone[1]..";"..phone[2]

    -- If phone detected write current time and switch on 
    -- else switch off after the given delay time
    if string.find(result, string.lower(phone[1])) ~= nil then 
      phone[3]= currenttime 
      if string.lower(switchstate) == 'off' then commandArray[phone[2]] = 'On' end
    else
      if tonumber(currenttime) > (tonumber(phone[3]) + outdoorsdelay) and string.lower(switchstate) == 'on' then
        commandArray[phone[2]] = 'Off'
        print(phone[2].."; now:"..os.date("%Y-%m-%d %H:%M:%S", currenttime).."; last seen: "..os.date("%Y-%m-%d %H:%M:%S",tonumber(phone[3])))
      end
    end
    newphonelist = newphonelist..";"..phone[3]

  end
  --print(newphonelist)
  commandArray['Variable:Telefoonlijst']= newphonelist
else
  print("Uservariable 'Telefoonlijst' not found!")
end


p.s. change the xxx and yy in the ip addresses to your own range

I added an extra field in the user variable to store the latest time the phone has been seen. With a delay on this time the switch is switched off when the phone is out of reach. The second field in the user variable is changed to the name of the switch to switch on/off, one switch for every phone each.
Last edited by ceedebee on Tuesday 07 April 2015 19:34, edited 1 time in total.
Cannon
Posts: 16
Joined: Monday 09 March 2015 23:04
Target OS: Windows
Domoticz version: 3.5877
Location: New Zealand
Contact:

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

Post by Cannon »

Hi Ceedebee

Would you mind providing a step by step on how to set this up?

I'm happy if you just PM if no one else wants the info.


Cheers for your help
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 »

At first: one bugfix, I programmed a print statement for logging the case a phone gets out of reach (somewhere around line 73). The function 'date()' is wrong, must be 'os.date()'. I fixed it in the code, like I said: not all was checked although the scripts works just fine. It detects the presence of phone correctly, with the remark of course that the wifi must always be switched on.

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

The last field is the 'last time seen' field. Initially set to 0 but filled with the current time if the phone is detected on the network. Each minute the network is checked via arp-scan for the presence of phones. I changed the original arp-scan command a bit because I know my router isn't assigning IP addresses above the "100" so scanning all the range to 256 is not necessary . I also added the retry parameter and the ignore dups parameter.
The advantage of the script is that it only does one arp-scan each minute and not one for each phone listed like the original. So I could add some retries.

p.s. don't forget to install the arp-scan program via: sudo apt-get install arp-scan
User avatar
zmaster
Posts: 1
Joined: Saturday 11 April 2015 17:23
Target OS: Raspberry Pi / ODroid
Domoticz version: Latest
Location: The Netherlands
Contact:

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

Post by zmaster »

Your script works like a charm ceedebee! I just installed it. Phones going into standby is a bit tricky but I think the timeout in the script could minimize the flapping noise it might cause.
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 »

Nice to hear. I don't know if there is a better alternative to detect if the users are indoors. I considered use a geofence app but this is using wifi and gps so more battery drain. I hope the topic starter appreciates my changes to the original script.
rijo78
Posts: 9
Joined: Monday 30 March 2015 20:47
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10717
Contact:

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

Post by rijo78 »

Hi ceedebee, I like the script. It seems pretty straight forward. Where exactly do I have to place the mac-address, switchname and 0? Do I have to replace something?

Thanks
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 »

Just make a uservariable named 'Telefoonlijst' (Dutch for telephone list) or name it like you wish. And fill it with your phones MAC and switch names as follows:
MAC1;switchname1;0|MAC2;switchname2;0

ps if you change your variable name you have to change the line "phoneslist= uservariables['Telefoonlijst']" accordantly
rijo78
Posts: 9
Joined: Monday 30 March 2015 20:47
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10717
Contact:

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

Post by rijo78 »

Aah! I finally got it working.
two things I did wrong. 1st setting user variables, 2nd name of the script. When I got both correct, it was working like a charm. Great work ceedebee! Really great script (once you know how it is working).

For those who are struggling with this as well:

1st: The user variables have to be set in Domoticz (Setup>More Options)
2nd: The name of the script has to start with 'script_time_' (don't think the rest is that important for the functionality of the script)
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 »

Well, credits are for the topic starter. I only changed it a bit.
rijo78
Posts: 9
Joined: Monday 30 March 2015 20:47
Target OS: Raspberry Pi / ODroid
Domoticz version: V4.10717
Contact:

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

Post by rijo78 »

You are right.
Dadogiobbe Thanks for sharing your work! Greatly appreciated
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 »

great script btw

thanks i am using it now
but how do i change the time that the script is scanning the mac adreses?

thanks in advance!

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
Post Reply

Who is online

Users browsing this forum: No registered users and 1 guest