REST-API JSON Use MikroTik router as presence-detection in Domoticz (SOLVED)
Posted: Friday 19 August 2022 6:59
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;
through i'll convert this to something like this
I'll then use 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 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
my Domoticz and dzvents versions;
Version: 2022.1
Build Hash: c9526851b
Compile Date: 2022-01-31 15:34:32
dzVents Version: 3.1.8
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"}]
Code: Select all
local api_data = domoticz.utils.fromJSON(item.data)
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:
Code: Select all
notfound=string.upper(tostring(api_data[index].comment))
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
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
}
Version: 2022.1
Build Hash: c9526851b
Compile Date: 2022-01-31 15:34:32
dzVents Version: 3.1.8