Page 1 of 1

REST-API JSON Use MikroTik router as presence-detection in Domoticz (SOLVED)

Posted: Friday 19 August 2022 6:59
by Maikel76
Hello,
I'm reading my MikroTik router (RB2011UiAS-2HnD-IN) out through REST-API and get a json readout back like this;
I'm reading all dhcp-server-leases with status 'waiting', those are the devices away/not home/ The switch Earn will turn off then, like you see here;

Code: Select all

[{".id":"*123","address":"192.168.xx.xx","address-lists":"","blocked":"false","client-id":"123456789","comment":"Laptop Earn","dhcp-option":"","disabled":"false","dynamic":"false","host-name":"LAPTOP-2018","last-seen":"14h4m17s","mac-address":"123456789","radius":"false","server":"defconf","status":"waiting"},{".id":"*124","address":"192.168.xx.xx","address-lists":"","age":"6d23h13m33s","blocked":"false","client-id":"123456789","comment":"iPhone_Earn","dhcp-option":"","disabled":"false","dynamic":"false","last-seen":"5h23m42s","mac-address":"123456789","radius":"false","server":"defconf","status":"waiting"}]
through

Code: Select all

local api_data = domoticz.utils.fromJSON(item.data)
i'll convert this to something like this

Code: Select all

2022-08-17 12:31:01.922 Status: dzVents: 1:
2022-08-17 12:31:01.922 Status: dzVents:  client-id: 123456789
2022-08-17 12:31:01.922 Status: dzVents:  last-seen: 11h4m15s
2022-08-17 12:31:01.922 Status: dzVents:  .id: *123
2022-08-17 12:31:01.922 Status: dzVents:  host-name: LAPTOP-2018
2022-08-17 12:31:01.923 Status: dzVents:  disabled: false
2022-08-17 12:31:01.923 Status: dzVents:  address: 192.168.xx.xx
2022-08-17 12:31:01.923 Status: dzVents:  status: waiting
2022-08-17 12:31:01.923 Status: dzVents:  server: defconf
2022-08-17 12:31:01.923 Status: dzVents:  radius: false
2022-08-17 12:31:01.923 Status: dzVents:  address-lists:
2022-08-17 12:31:01.923 Status: dzVents:  blocked: false
2022-08-17 12:31:01.923 Status: dzVents:  mac-address: 123456789
2022-08-17 12:31:01.923 Status: dzVents:  dynamic: false
2022-08-17 12:31:01.923 Status: dzVents:  comment: Laptop Earn
2022-08-17 12:31:01.923 Status: dzVents:  dhcp-option:
2022-08-17 12:31:01.923 Status: dzVents: 2:
2022-08-17 12:31:01.923 Status: dzVents:  client-id: 123456789
2022-08-17 12:31:01.923 Status: dzVents:  last-seen: 4h57m41s
2022-08-17 12:31:01.923 Status: dzVents:  .id: *124
2022-08-17 12:31:01.923 Status: dzVents:  status: waiting
2022-08-17 12:31:01.923 Status: dzVents:  disabled: false
2022-08-17 12:31:01.923 Status: dzVents:  address: 192.168.xx.xx
2022-08-17 12:31:01.923 Status: dzVents:  age: 5d23h9m9s
2022-08-17 12:31:01.923 Status: dzVents:  server: defconf
2022-08-17 12:31:01.923 Status: dzVents:  radius: false
2022-08-17 12:31:01.923 Status: dzVents:  address-lists:
2022-08-17 12:31:01.923 Status: dzVents:  blocked: false
2022-08-17 12:31:01.923 Status: dzVents:  mac-address: 123456789
2022-08-17 12:31:01.923 Status: dzVents:  dynamic: false
2022-08-17 12:31:01.923 Status: dzVents:  comment: iPhone Earn
2022-08-17 12:31:01.923 Status: dzVents:  dhcp-option:
I'll then use

Code: Select all

notfound=string.upper(tostring(api_data[index].comment))
inside a for do loop to readout the lua table (two devices here)
If a 'waiting' device doesnt have a comment, and this notfound var is nil, it will show 'NIL' and the loop will return

Now we are at home it keeps the home switch switched on/at home
The problem that's happening is that once the person is away/not home, and the notfound var is filled with the name of the device
The actual value gathered by

Code: Select all

(string.match(notfound, uearn) == uearn
seems correct
But supposedly there is something going on resulting in this situation Earn is turned on, 5 min later off, then on, then off, etc
I tried so many things already and really don't see what i'm doing wrong, could any of you please help me or point me in the right direction, a hint will be apreciated too
This is the script

Code: Select all

--MAIN
return {
	on = {
		devices = {'Motion',
		           'MotionCouch',
		           --'MotionLiving',
		           'MotionStairs',
		           'Maikel',
		           'PC_Maikel_locked',
		           'Earn',
		           'Sleep'
		          },
		timer = {'every 5 minutes'},
		shellCommandResponses = {
			       'restapi'  -- must match with the callback passed to the executeShellCommand
		          },
		variables = {},
		scenes = {},
		groups = {},
		security = {},
		httpResponses = {},
		customEvents = {},
		system = {},
	},
	data = {},
	logging = {},
	execute = function(domoticz, item)
        local motiondev=domoticz.devices('Motion')    -- motion sensor 
        local mocouch=domoticz.devices('MotionCouch')
        --local mowork=domoticz.devices('MotionWork')
        local motionliv=domoticz.devices('MotionLiving')
        local mostairs=domoticz.devices('MotionStairs')     --motion to detect upstairs/sleep
        local presencebed=domoticz.devices('MotionBed')     --switch to register presence in the bedroom + delay
        local someone=domoticz.devices('Home')        -- info
        local sleep=domoticz.devices('Sleep')       -- helpswitch gotosleep scene 
        local sleepmin=120                          --minimal amount minutes that sleep switch will be on
        local holidaybed=domoticz.devices('HolidayBed')   -- holiday 
        local holiday=domoticz.devices('Holiday')   -- holiday 
        local maikel=domoticz.devices('Maikel')       -- maikel home
        local earn=domoticz.devices('Earn')           -- earn home
        local maikellocked=domoticz.devices('PC_Maikel_locked')
        local laptopmaikel=domoticz.devices('LaptopMaikel')
        local laptopearn=domoticz.devices('LaptopEarn')
        local pm25us=domoticz.devices('AirQualityPM25us')
        local pm25lvl=domoticz.devices('AirQualityLevel25us')
        local pm25unsafe=56
        --local camhome=domoticz.devices('SecurityCamHome') --home switch for surveillance camera sw
        local dining=domoticz.devices('Dining')
        local couch=domoticz.devices('HueCouch')       -- light couch
        local stairs=domoticz.devices('HueStairs')     -- light stairs
        local delay=30
        local usermaikel=domoticz.variables('user1') --usermaikel.value holds 'Maikel'
        local userearn=domoticz.variables('user2')   --userearn.value holds 'Earn'
        --change MotionLiving according to any motion in the (living) room
        if (domoticz.time.matchesRule('every 4 hours') and holiday.state == 'Off' and (motiondev.lastUpdate.hoursAgo >= 15 or mocouch.lastUpdate.hoursAgo >= 15)) then  
            domoticz.notify('One of the motionsensors is offline')
        end    
        if (motiondev.state == 'On' or mocouch.state == 'On' or maikellocked.state == 'Off') then
            motionliv.switchOn().checkFirst()
        else
            motionliv.switchOff().checkFirst()
        end
        --turn sleepswitch off and system back on when awake again
        if (sleep.state == 'On' and mostairs.state == 'On' and presencebed.state == 'On' 
         and sleep.lastUpdate.minutesAgo > sleepmin and sleep.lastUpdate.minutesAgo < 1440 --sleep minimal 2 hours, 1440=one day    
         and not domoticz.time.matchesRule('at 5:40-7:15 on mon,tue,wed,thu,fri')          --during going to work
         and not domoticz.time.matchesRule('between 90 minutes before sunrise and sunrise') ) then --nighttime
            sleep.switchOff()
        end     
        if (sleep.state == 'On' and (sleep.lastUpdate.minutesAgo >= 1440
         or (maikel.state == 'Off' and earn.state == 'Off' and maikel.lastUpdate.minutesAgo > 5 and earn.lastUpdate.minutesAgo > 5) )) then
            sleep.switchOff()
        end 
        --maikel comes home
        if (maikel.lastUpdate.secondsAgo < 5 and maikel.active and maikel.state == 'On' and motiondev.state == 'Off') then    --motiondev because its in the middel ot room
            if (couch.state == 'Off' or stairs.state == 'Off' or someone.lastUpdate.minutesAgo < 5) then
                domoticz.notify('Welcome home Maikel, I turn the lights on for you')
            else
                domoticz.notify('Welcome home Maikel')
            end 
            --camhome.switchOn().checkFirst().silent()
            someone.updateAlertSensor(domoticz.ALERTLEVEL_GREEN,'SOMEONE IS IN THE LIVINGROOM')
        --maikel leaves home    
        elseif (maikel.lastUpdate.secondsAgo < 5 and maikel.active and maikel.state == 'Off') then     
            if (pm25us.sensorValue > pm25unsafe) then
                domoticz.notify('Have a safe trip Maikel, be careful, pm2.5 levels are '..pm25lvl.text..'!')
            else    
                domoticz.notify('Have a safe trip Maikel')
            end  
            --camhome.switchOff().checkFirst().silent()
        end    
        --earn comes home
        if (earn.lastUpdate.secondsAgo < 5 and earn.active and earn.state == 'On' and motiondev.state == 'Off') then    --motiondev because its in the middel ot room
            if (couch.state == 'Off' or stairs.state == 'Off' or someone.lastUpdate.minutesAgo < 5) then
                domoticz.notify('Welcome home Earn, I turn the lights on for you')
            else
                domoticz.notify('Welcome home Earn')
            end    
            --camhome.switchOn().checkFirst().silent()
            someone.updateAlertSensor(domoticz.ALERTLEVEL_GREEN,'SOMEONE IS IN THE LIVINGROOM')
        --earn leaves home
        elseif (earn.lastUpdate.secondsAgo < 5 and earn.active and earn.state == 'Off') then
            if (pm25us.sensorValue > pm25unsafe) then
                domoticz.notify('Have a safe trip Earn, be careful, pm2.5 levels are '..pm25lvl.text..'!')
            else    
                domoticz.notify('Have a safe trip Earn')
            end 
            --camhome.switchOff().checkFirst().silent()
        end
        --motion detected, someone home (cats downstair or were upstairs)
        --if ((motiondev.state == 'On' or mocouch.state == 'On' or mowork.state == 'On') and (motiondev.lastUpdate.secondsAgo <= 60 or mocouch.lastUpdate.secondsAgo <= 60 or mowork.lastUpdate.secondsAgo <= 60) and someone.lastUpdate.minutesAgo > 5) then  --someone.lastUpdate.minutesAgo > 5) then
        if (motionliv.state == 'On') then  --someone.lastUpdate.minutesAgo > 5) then    
            someone.updateAlertSensor(domoticz.ALERTLEVEL_GREEN,'SOMEONE IS IN THE LIVINGROOM') 
        --no motion for 30 min, noone there, if in sleep mode it will not check the motion detectors, the scene will turn off sleep mode after 35 min
        --elseif ((maikel.lastUpdate.minutesAgo > 5 and motiondev.state == 'Off' and mocouch.state == 'Off' and mowork.state == 'Off' and someone.lastUpdate.minutesAgo >= delay and someone.lastUpdate.minutesAgo < delay+5 and someone.color == 1) or sleep.state == 'On' and someone.color == 1) then
        elseif ((motionliv.state == 'Off' and  maikel.lastUpdate.minutesAgo > 5 and someone.lastUpdate.minutesAgo >= delay and 
            someone.lastUpdate.minutesAgo < delay+5 and someone.color == 1) or sleep.state == 'On' and someone.color == 1) then
            --camhome.switchOff().checkFirst()
            if (couch.state == 'On' or stairs.state == 'On') then
                domoticz.notify('No one is in the Livingroom for '..someone.lastUpdate.minutesAgo..' min, I turn the lights off for you')
            end    
            someone.updateAlertSensor(domoticz.ALERTLEVEL_GREY,'No one is in the Livingroom').silent()
        end
        --domoticz.log('VALUE: '..someone.color)
        --someone.updateAlertSensor(domoticz.ALERTLEVEL_GREY,'No one is in the Livingroom')
        --someone.updateAlertSensor(domoticz.ALERTLEVEL_GREEN,'SOMEONE IS IN THE LIVINGROOM')
        if (item.isTimer or item.name == 'Motion' or item.name == 'MotionCouch') then
			domoticz.executeShellCommand({
				command = 'curl --netrc-file /home/pi/domoticz/scripts/bashscrips/fietsdopje._netrc "https://MTrouter/rest/ip/dhcp-server/lease?status=waiting"',   
				callback = 'restapi', -- see shellCommandResponses above.
				timeout = 20, -- Max runtime 20 seconds
			})
        end --isTimer        
        if (item.isShellCommandResponse and item.statusCode~=0 and item.callback ~= 'restapi') then
            domoticz.log('ERROR item.statusCode: '..item.statusCode..' item.callback'..item.callback, domoticz.LOG_FORCE)
        end    

--FROM HERE THE MIKROTIK DATA IS PROCESSED
       if (item.isShellCommandResponse) then -- and item.statusCode==0 and item.callback == 'restapi') then
            local api_data = domoticz.utils.fromJSON(item.data)
            local umaikel = string.upper(usermaikel.value)
            local uearn = string.upper(userearn.value)
            local phone = string.upper('phone')
            local laptop = string.upper('laptop')
            --local comment1 = api_data[1].comment --array/table
            --local comment2 = api_data[2].comment
            for index, x in ipairs(api_data) do
                --domoticz.log(index .. ': '.. tostring(value), domoticz.LOG_FORCE)
                notfound=string.upper(tostring(api_data[index].comment))
                notfound2=string.upper(tostring(api_data[index].comment))
                --local text=string.match(notfound, uearn)
                --local text2=string.match(notfound, phone)
                --domoticz.log('earn: '..uearn,domoticz.LOG_FORCE)
                --domoticz.log('text: '..text,domoticz.LOG_FORCE)
                --domoticz.log('phone: '..text2,domoticz.LOG_FORCE) 
                if (notfound == 'NIL') then
                    do return end                 --break out of loop when item without comment is found
                end  
                domoticz.log('notfound: '..notfound, domoticz.LOG_FORCE)
                --earn phone
                if ((string.match(notfound, uearn) == uearn) and (string.match(notfound2, phone) == phone)) then     
                    earn.switchOff().checkFirst()   --finding EARN and PHONE because not home
                elseif not((string.match(notfound, uearn) == uearn) and (string.match(notfound2, phone) == phone)) then 
                    earn.switchOn().checkFirst()    --should NOT find earn AND phone when at home: NOT AND = NAND gate
                end
                --maikel phone
                if ((string.match(notfound, umaikel) == umaikel) and (string.match(notfound2, phone) == phone)) then
                    maikel.switchOff().checkFirst()
                elseif not((string.match(notfound, umaikel) == umaikel) and (string.match(notfound2, phone) == phone)) then
                    maikel.switchOn().checkFirst()
                end
                --earn laptop
                if ((string.match(notfound, uearn) == uearn) and (string.match(notfound2, laptop) == laptop)) then
                    laptopearn.switchOff().checkFirst()
                elseif not((string.match(notfound, uearn) == uearn) and (string.match(notfound2, laptop) == laptop)) then
                    laptopearn.switchOn().checkFirst()
                end   
            end -- end for
            if (api_data == nil) then
                    maikel.switchOn().checkFirst()
                    earn.switchOn().checkFirst()
                    laptopearn.switchOn().checkFirst()
            end    
        end --end shellCommandResponses
    end 
}
my Domoticz and dzvents versions;
Version: 2022.1
Build Hash: c9526851b
Compile Date: 2022-01-31 15:34:32
dzVents Version: 3.1.8

Re: REST-API JSON readout and inconsistent var readout

Posted: Monday 22 August 2022 8:29
by Maikel76
No one any idea??

Re: REST-API JSON readout and inconsistent var readout

Posted: Monday 22 August 2022 9:44
by waltervl
I found it useful in these cases to get things really back to basic and start with a minimal script, tracking for example only one user and see what happens.

Re: REST-API JSON readout and inconsistent var readout

Posted: Monday 22 August 2022 13:05
by Maikel76
waltervl wrote: Monday 22 August 2022 9:44 I found it useful in these cases to get things really back to basic and start with a minimal script, tracking for example only one user and see what happens.
Thanks, that's good advice. I used the Unify script and rewrote the for do iPair and read into how to use, will try a few things
Do you know if there is a possibility to make a wiki page yourself once i have this working?

Re: REST-API JSON readout and inconsistent var readout

Posted: Monday 22 August 2022 13:13
by waltervl
Yes you can, request a wiki account at user gizmocuz through PM.
But you could also create a new forum topic with the script and instructions.

Re: REST-API JSON readout and inconsistent var readout

Posted: Monday 22 August 2022 14:13
by Maikel76

Code: Select all

local api_data = domoticz.utils.fromJSON(item.data)
            local umaikel = string.upper(usermaikel.value)
            local uearn = string.upper(userearn.value)
            local phone = string.upper('phone')
            local laptop = string.upper('laptop')
            --local comment1 = api_data[1].comment --array/table
            --local comment2 = api_data[2].comment
            for key,field in ipairs(api_data) do
                    local value = string.upper(api_data[key].comment)
                    local a = string.match(value, uearn)
                    if a == uearn then 
                         notPresentEarn = true 
                    else notPresentEarn = false 
                    end  
                    local b = string.match(value, phone)
                    if b == phone then 
                         notPresentPhone = true 
                    else notPresentPhone = false 
                    end  
                    local c = string.match(value, umaikel)
                    if c == umaikel then 
                         notPresentMaikel = true 
                    else notPresentMaikel = false 
                    end  
                    -- switch on or off
                    if notPresentEarn then
                        earn.switchOff().checkFirst()
                    else
                        earn.switchOn().checkFirst()
                    end    
                    if notPresentMaikel then
                        maikel.switchOff().checkFirst()
                    else
                        maikel.switchOn().checkFirst()
                    end
            end --end for do     
I'm doing something terribly stupid but i don't see what
If you could look at this code for me??
BTW the comment1 and comment2 is working but i need a loop

Re: REST-API JSON readout and inconsistent var readout

Posted: Monday 22 August 2022 14:55
by waltervl
I do not see a mistake. Perhaps log the values that are read so you know if the switching is in the values from json or within the script.

Re: REST-API JSON readout and inconsistent var readout

Posted: Monday 22 August 2022 16:27
by Maikel76
waltervl wrote:I do not see a mistake. Perhaps log the values that are read so you know if the switching is in the values from json or within the script.
Ok I made some logging. Will test more tomorrow. Thanks for your replies


Sent from my iPhone using Tapatalk

Re: REST-API JSON readout and inconsistent var readout (SOLVED)

Posted: Tuesday 23 August 2022 6:16
by Maikel76
Thank you again Walter vl
Through meticulously logging every variable at every step I solved the issue
In the beginning of the script umaikel and uearn changed to a more general user1 and user2
I'll request a wiki account :)

Code: Select all

local user1=domoticz.variables('user1') --usermaikel.value holds 'Maikel'
local user2=domoticz.variables('user2')   --userearn.value holds 'Earn'
then the isShellCommandResponse is now;

Code: Select all

        if (item.isShellCommandResponse) then -- and item.statusCode==0 and item.callback == 'restapi') then
            local api_data = domoticz.utils.fromJSON(item.data)
            local u1 = string.upper(user1.value)
            local u2 = string.upper(user2.value)
            local phone = string.upper('phone')
            local laptop = string.upper('laptop')
            local notPresentu1=nil
            local notPresentu2=nil
            local notPresentPhone=nil
            
            --local comment1 = api_data[1].comment --array/table
            --local comment2 = api_data[2].comment
            for key,field in ipairs(api_data) do
                    --find device
                    local value = string.upper(api_data[key].comment)
                    domoticz.log('value: '..value,domoticz.LOG_FORCE)
                    --search user2
                    local a = string.match(value, u2)
                    --domoticz.log('u2: '..tostring(a),domoticz.LOG_FORCE)
                    if a == u2 then 
                         notPresentu2 = true 
                    elseif (a ~= u2) or (a == nil) then 
                         notPresentu2 = false 
                    end  
                    --domoticz.log('notPresentu2: '..tostring(notPresentu2),domoticz.LOG_FORCE)
                    --search phone
                    local b = string.match(value, phone)
                    --domoticz.log('phone: '..tostring(b),domoticz.LOG_FORCE)
                    if b == phone then 
                         notPresentPhone = true 
                    elseif (b ~= phone) or (b == nil) then
                         notPresentPhone = false 
                    end  
                    --domoticz.log('notPresentPhone: '..tostring(notPresentPhone),domoticz.LOG_FORCE)
                    --search laptop
                    local c = string.match(value, laptop)
                    --domoticz.log('laptop: '..tostring(c),domoticz.LOG_FORCE)
                    if c == laptop then 
                         notPresentLaptop = true 
                    elseif (c ~= laptop) or (c == nil) then
                         notPresentLaptop = false 
                    end
                    --domoticz.log('notPresentLaptop: '..tostring(notPresentLaptop),domoticz.LOG_FORCE)
                    --search user1
                    local d = string.match(value, u1)
                    --domoticz.log('u1: '..tostring(d),domoticz.LOG_FORCE)
                    if d == u1 then 
                         notPresentu1 = true 
                    elseif (d ~= u1) or (d == nil) then
                         notPresentu1 = false 
                    end  
                    --domoticz.log('notPresentu1: '..tostring(notPresentu1),domoticz.LOG_FORCE)
                    if notPresentu2 and notPresentPhone then
                        notPresentu2Phone = true
                    end
                    if notPresentu1 and notPresentPhone then
                        notPresentu1Phone = true
                    end
                    if notPresentu2 and notPresentLaptop then
                        notPresentu2Laptop = true
                    end    
            end --end for do           
            -- switch on or off
            domoticz.log('notPresentu2Phone: '..tostring(notPresentu2Phone), domoticz.LOG_FORCE)
            domoticz.log('notPresentu1Phone: '..tostring(notPresentu1Phone), domoticz.LOG_FORCE)
            domoticz.log('notPresentu2Laptop: '..tostring(notPresentu2Laptop), domoticz.LOG_FORCE)
            if notPresentu2Phone then
                earn.switchOff().checkFirst()
            else
                earn.switchOn().checkFirst()
            end   
            if notPresentu1Phone then
                maikel.switchOff().checkFirst()
            else
                maikel.switchOn().checkFirst()
            end
            if notPresentu2Laptop then
                laptopearn.switchOff().checkFirst()
            else
                laptopearn.switchOn().checkFirst()
            end
              
        end    

Re: REST-API JSON readout and inconsistent var readout (SOLVED)

Posted: Tuesday 23 August 2022 8:37
by waltervl
Great!

Use MikroTik router as presence-detection in Domoticz

Posted: Thursday 25 August 2022 16:07
by Maikel76
Since i didn't hear anything from gizmocuz here my script and a document howto is anyone interested.
It might contain small errors so if you see something please let me know. I know i should change the code in the case none of the devices are detected, working on that (Edit: changed this). It's working in our house already.
Documentation:
Use MikroTik router as presence-detection in Domoticz

MikroTik router (at least RouterOS v7.1beta4, tested on 7.4.1 stable):
Users:
Goto system/users and add user, in this scrip user domoticz is used
Goto groups and create api-domoticz with policies; ssh, (write), read, api, restapi (write probably not needed)
Add domoticz to api-domoticz group
Certificates:
First install certificates on MikroTik router, follow this doc:
https://help.mikrotik.com/docs/display/ROS/Certificates
make sure the name of the common-name=”server” is the name of your router, setup in DNS;
DNS:
make sure dns-static includes the name used as “server” in the certificate and in the api-command in the dzvents-script
DNSserver needs to be running (default settings ok)
Services:
make sure under ip/services api-ssl is enabled and has the correct cert assigned
DHCP:
in DHCP under leases please first find the devices to be controlled in domoticz (phones laptops), makes these devices Static and add comment as follows:
<nameperson><typedevice> or <typedevice><nameperson>
e.g. iPhone Maikel, Earns-Laptop
symbols like _ , - or space are allowed, symbols like “ or ‘ should be avoided
API doc;
https://help.mikrotik.com/docs/display/ROS/REST+API

Linux (tested on raspbian buster 10):
Define a directory where the password file resides; in the script the following is used and needs to be changed;
/home/pi/domoticz/scripts/bashscrips/ as path change to your own location
The password file is named: fietsdopje._netrc change if needed but leave .netrc the same
Fill the file with;

machine MT-PietjePuk ← this is the name used as “server” used earlier
login domoticz ← user can be changed, needs to be changed in the router too
password xxxxxxxxxxxxxxxxxxxxx

Domoticz (tested on 2022.1 stable, dvvents 3.1.8):
user variable:
In Setup-More options-User variables: add two users; user1 and user2 and give them both a name
you have to use user1 and user2 as variable name, or edit the script
The var type is string
It is recommended that the var value doesn’t contain a space



events:
Make a new script as dvvents-minimal
Then copy paste the scriptcode and edit the following values;

devicenames under on={devices according to your own devices, same as starting line 24;

Code: Select all

	local motiondev=domoticz.devices('Motion')    -- motion sensor 
	local mocouch=domoticz.devices('MotionCouch')
	local maikel=domoticz.devices('Maikel')       -- maikel home
	local earn=domoticz.devices('Earn')               -- earn home
	local laptopmaikel=domoticz.devices('LaptopMaikel')
	local laptopearn=domoticz.devices('LaptopEarn')
leave

Code: Select all

	local user1=domoticz.variables('user1') --usermaikel.value holds 'Maikel'
	local user2=domoticz.variables('user2')   --userearn.value holds 'Earn'
edit

Code: Select all

	if (item.isTimer or item.name == 'Motion' or item.name == 'MotionCouch') then
so that devices Motion and/or MotionCouch are devicenames you use to trigger if someone enters the house/livingroom

edit

Code: Select all

	command = 'curl --netrc-file /home/pi/domoticz/scripts/bashscrips/fietsdopje._netrc "https://MT-PietjePuk/rest/ip/dhcp-server/lease?status=waiting"',   
command = 'curl --netrc-file /home/pi/domoticz/scripts/bashscrips/fietsdopje._netrc "https://MT-PietjePuk/rest/ip/dhcp-server/lease?status=waiting"',
so that the path is correct and the router-dns-name is correct (in bold)

recommended to not change any settings under line 40
please note that all commented out lines beginning with domoticz.log( are for debug purposes

This script works as follows in short;
When someone walks in the living room the script is triggered, sends the api-request for dhcp-leases with status ‘waiting’, receives json data, converts that to a lua-table and reads the devices from that table as follows;
look at the comment of the device, if empty, skip, else search if the word ‘laptop’ or ‘phone’ is present together with a name of user1 or user2 (if comment with only phone or name is used this will not work)

If found than this device or person is marked notpresent and turned off
e.g. in the first comment the words ‘phone’ and ‘maikel’ in the comment ‘iPhone Maikel’ are found and the user1, which is person Maikel, is turned off. Accordingly AC and lights could be turned off
The default timeout of a dhcp-lease is 10 min, so the maximum waiting time can be 15 min (+ 5 min script execution time) after you leave the house. When entering the house the system will turn on triggered by a sensor immediately.

Code:

Code: Select all

--MAIN
return {
	on = {
		devices = {'Motion',
		           'MotionCouch',
		           'Maikel',
		           'Earn',
		          },
		timer = {'every 5 minutes'},
		shellCommandResponses = {
			       'restapi'  -- must match with the callback passed to the executeShellCommand
		          },
		variables = {},
		scenes = {},
		groups = {},
		security = {},
		httpResponses = {},
		customEvents = {},
		system = {},
	},
	data = {},
	logging = {},
	execute = function(domoticz, item)
        local motiondev=domoticz.devices('Motion')    -- motion sensor 
        local mocouch=domoticz.devices('MotionCouch')
        local maikel=domoticz.devices('Maikel')       -- maikel home
        local earn=domoticz.devices('Earn')           -- earn home
        local laptopmaikel=domoticz.devices('LaptopMaikel')
        local laptopearn=domoticz.devices('LaptopEarn')
        local user1=domoticz.variables('user1') --usermaikel.value holds 'Maikel'
        local user2=domoticz.variables('user2')   --userearn.value holds 'Earn'

        if (item.isTimer or item.name == 'Motion' or item.name == 'MotionCouch') then
			domoticz.executeShellCommand({
				command = 'curl --netrc-file /home/pi/domoticz/scripts/bashscrips/fietsdopje._netrc "https://MT-PietjePuk/rest/ip/dhcp-server/lease?status=waiting"',   
				callback = 'restapi', -- see shellCommandResponses above.
				timeout = 20, -- Max runtime 20 seconds
			})
        end --isTimer    
		--DONT CHANGE ANY SETTING UNDER THIS LINE 
        if (item.isShellCommandResponse and item.statusCode~=0 and item.callback ~= 'restapi') then
            domoticz.log('ERROR item.statusCode: '..item.statusCode..' item.callback'..item.callback, domoticz.LOG_FORCE)
        end    
        if (item.isShellCommandResponse) then 
            local api_data = domoticz.utils.fromJSON(item.data)
            local u1 = string.upper(user1.value)
            local u2 = string.upper(user2.value)
            --domoticz.log('user2: '..tostring(u2),domoticz.LOG_FORCE)
            local phone = string.upper('phone')
            local laptop = string.upper('laptop')
            for key,field in ipairs(api_data) do
                    --find device
                    local value = string.upper(tostring((api_data[key].comment)))	--Edit: changed so nil is detected properly
                    domoticz.log('value: '..tostring(value),domoticz.LOG_FORCE)
                    --search user2
                    local a = string.match(value, u2)
                    --domoticz.log('u2: '..tostring(a),domoticz.LOG_FORCE)
                    if a == u2 then 
                         notPresentu2 = true 
                    elseif (a ~= u2) or (a == 'NIL') then 
                         notPresentu2 = false 
                    end  
                    --domoticz.log('notPresentu2: '..tostring(notPresentu2),domoticz.LOG_FORCE)
                    --search phone
                    local b = string.match(value, phone)
                    --domoticz.log('phone: '..tostring(b),domoticz.LOG_FORCE)
                    if b == phone then 
                         notPresentPhone = true 
                    elseif (b ~= phone) or (b == 'NIL') then
                         notPresentPhone = false 
                    end  
                    --domoticz.log('notPresentPhone: '..tostring(notPresentPhone),domoticz.LOG_FORCE)
                    --search laptop
                    local c = string.match(value, laptop)
                    --domoticz.log('laptop: '..tostring(c),domoticz.LOG_FORCE)
                    if c == laptop then 
                         notPresentLaptop = true 
                    elseif (c ~= laptop) or (c == 'NIL') then
                         notPresentLaptop = false 
                    end
                    --domoticz.log('notPresentLaptop: '..tostring(notPresentLaptop),domoticz.LOG_FORCE)
                    --search user1
                    local d = string.match(value, u1)
                    --domoticz.log('u1: '..tostring(d),domoticz.LOG_FORCE)
                    if d == u1 then 
                         notPresentu1 = true 
                    elseif (d ~= u1) or (d == 'NIL') then
                         notPresentu1 = false 
                    end  
                    --domoticz.log('notPresentu1: '..tostring(notPresentu1),domoticz.LOG_FORCE)
                    if notPresentu2 and notPresentPhone then
                        notPresentu2Phone = true
                    end
                    if notPresentu1 and notPresentPhone then
                        notPresentu1Phone = true
                    end
                    if notPresentu2 and notPresentLaptop then
                        notPresentu2Laptop = true
                    end    
            end --end for do           
            -- switch on or off
            domoticz.log('notPresentu2Phone: '..tostring(notPresentu2Phone), domoticz.LOG_FORCE)
            domoticz.log('notPresentu1Phone: '..tostring(notPresentu1Phone), domoticz.LOG_FORCE)
            domoticz.log('notPresentu2Laptop: '..tostring(notPresentu2Laptop), domoticz.LOG_FORCE)
            if notPresentu2Phone then
                earn.switchOff().checkFirst()
            else
                earn.switchOn().checkFirst()
            end   
            if notPresentu1Phone then
                maikel.switchOff().checkFirst()
            else
                maikel.switchOn().checkFirst()
            end
            if notPresentu2Laptop then
                laptopearn.switchOff().checkFirst()
            else
                laptopearn.switchOn().checkFirst()
            end
              
        end --end isShellCommandResponse   
    end --end execute 
}
Edit: changed so nil is detected properly