Aanwezigheidsdetectie met Fibaro HC?

Garfield

UniFier
24 mrt 2020
18
15
3
Zijn er hier mensen die een vorm van aanwezigheidsdetectie aan de praat hebben gekregen in een Fibaro HomeCenter?
Ik zie hier wel een topic op het forum over aanwezigheidsdetectie in combinatie met een Homey, maar ik ben op zoek naar iets vergelijkbaars voor het Fibaro systeem.
 
Voor homeseer is een plugin die integreert met unifi controller. Afhankelijk van de hoeveelheid AP's kun je tracken waar een cliënt zich bevind. Je kunt dus ook zien als iemand thuis komt en op basis daarvan events starten in homeseer.
 
Ik heb geen Homeseer, maar een Fibaro; een plug-in die Edwin noemt kan ik niet vinden. De route via NodeRed en MQTT lijkt me een beetje een omweg. Daarbij; ik heb ze beiden niet draaien.
Maar het zou toch wel mogelijk moeten zijn om eens in de zoveel tijd de UniFi Controller te vragen of een bepaald device aanwezig is in het netwerk?
 
Ja dit is mogelijk, mocht je nog interesse hebben hierin.
Ik heb een HC3 met hierin aanwezigheid detectie in LUA/QA.
Dit is zonder tussenstappen mogelijk, direct vanuit de HC3 naar de controller.
In ieder geval met een losse VM controller op Debian.
Maar ik denk dat de rest hetzelfde werkt.
 
Voor homeseer is een plugin die integreert met unifi controller. Afhankelijk van de hoeveelheid AP's kun je tracken waar een cliënt zich bevind. Je kunt dus ook zien als iemand thuis komt en op basis daarvan events starten in homeseer.
Hi Edwin,

Heb jij toevallig de naam van de Homeseer plugin? Is dit een HS4 of legacy plugin?

Ben even aan het rondkijken, sinds het aanzetten van MFA is de koppeling met Nodered een beetje een uitdaging 🤔
 
Ja dit is mogelijk, mocht je nog interesse hebben hierin.
Ik heb een HC3 met hierin aanwezigheid detectie in LUA/QA.
Dit is zonder tussenstappen mogelijk, direct vanuit de HC3 naar de controller.
In ieder geval met een losse VM controller op Debian.
Maar ik denk dat de rest hetzelfde werkt.
Ja, zeker nog interesse!
Ik heb hier zelf nog een HC2 draaien, dus QA’s werken niet, maar met LUA kom ik een eind. De controller is hier een CloudKey 2+. Zo te zien dus net wel een andere situatie als bij jou.
Kan je ongeveer vertellen hoe je het aan de praat hebt gekregen?
 
Ik heb het ook niet zelf verzonnen hoor (in dit geval niet in ieder geval). ;-)
Op het Fibaro forum staat deze voor de HC2:
Maar daar heeft diegene wat problemen mee zo te zien.
Ik heb deze gebruikt volgens mij:
Weet je hoe een Quickapp werkt?

Dit is de Quickapp code:
function QuickApp:setPresenceStatus(status) self:trace("setPresenceStatus() called: ", status) if status == "Away" then self:updateProperty('value', true) else self:updateProperty('value', false) end self:updateView("presenceStatus", "text", status) end function QuickApp:loginUnifi() if self.cookie == nil then self.http:request(self.controller .. "api/login", { options = { checkCertificate = false, method = 'POST', data = json.encode({ ['username'] = self.login, ['password'] = self.password }) }, success = function(response) if response.status == 200 then self.cookie = response.headers['Set-Cookie'] self:debug("loginUnifi() succeed") else self:error("loginUnifi() failed: ", json.encode(response.data)) end end, error = function(error) self:error("loginUnifi() failed: ", json.encode(error)) end }) end end function QuickApp:checkMacUnifi() local macInfo, lastSeen if self.cookie ~= nil then self.http:request(self.controller .. "api/s/" .. self.site .. "/stat/user/" .. self.mac, { options = { checkCertificate = false, method = 'GET', headers = { ['Cookie'] = self.cookie } }, success = function(response) if response.status == 200 then self:trace("checkMacUnifi() succeed") macInfo = json.decode(response.data) if macInfo['meta']['rc'] == "ok" then lastSeen = macInfo['data'][1]['last_seen'] if (lastSeen ~= nil) and ((os.time() - lastSeen) < self.awaydelay) then self:setPresenceStatus("Home") else self:setPresenceStatus("Away") end else self:setPresenceStatus("Away") end else self.cookie = nil self:error("checkMacUnifi() failed: ", json.encode(response.data)) end end, error = function(error) self.cookie = nil self:error("checkMacUnifi() failed: ", json.encode(error)) end }) end end function QuickApp:mainLoop() self:loginUnifi() self:checkMacUnifi() fibaro.setTimeout(self.frequency * 1000, function() self:mainLoop() end) end function QuickApp:onInit() self.controller = self:getVariable("controller") assert(self.controller ~= "", "controller is not set") if string.sub(self.controller, -1) ~= "/" then self.controller = self.controller .. "/" end self.site = self:getVariable("site") assert(self.site ~= "", "site is not set") self.login = self:getVariable("login") assert(self.login ~= "", "login is not set") self.password = self:getVariable("password") assert(self.password ~= "", "password is not set") self.frequency = self:getVariable("frequency") assert(self.frequency ~= "", "frequency is not set") self.frequency = tonumber(self.frequency) assert(self.frequency ~= nil, "frequency is not a number") self.mac = string.lower(self:getVariable("mac")) assert(self.mac ~= "", "mac is not set") assert(string.match(self.mac, '^[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]$') ~= nil, "mac address format is incorrect") self.awaydelay = tonumber(self:getVariable("away delay")) if self.awaydelay == nil then self:debug("onInit(): away delay equals frequency") self.awaydelay = self.frequency end self:setPresenceStatus("Unknown") self.cookie = nil self.http = net.HTTPClient({ timeout = 3000 }) self:mainLoop() end

Dit zijn de variabele die in de Quickapp worden gedefineerd, deze zul je in de HC2 LUA moeten defineren:
controller (String variable): https://[ip adres]:8443/
site (String variable): default
login (String variable): [username] | Unifi Administrator die je in de controller aanmaakt.
password (String variable): [wachtwoord]
frequency (String variable): 10
mac (String variable): [Mac adres van device]
away delay (String variable): 600
 
Ja dit is mogelijk, mocht je nog interesse hebben hierin.
Ik heb een HC3 met hierin aanwezigheid detectie in LUA/QA.
Dit is zonder tussenstappen mogelijk, direct vanuit de HC3 naar de controller.
In ieder geval met een losse VM controller op Debian.
Maar ik denk dat de rest hetzelfde werkt.
Ik heb nog wel wat problemen dit op de UDM Pro SE werkend te krijgen.
De endpoints zijn wat anders maar hij geeft aan dat er geen kloppende login gegevens zijn.
Ik heb speciaal in de UDM Pro SE UI een extra user aangemaakt, maar dit lijkt niet te werken.
Ik moet er nog eens een keer induiken.
Dit is de aangepaste code voor een UDM Pro (SE):
Code:
function QuickApp:setPresenceStatus(status)
    self:trace("setPresenceStatus() called: ", status)
    if status == "Away" then
        self:updateProperty('value', true)
    else
        self:updateProperty('value', false)
    end
    self:updateView("presenceStatus", "text", status)
end
function QuickApp:loginUnifi()
    if self.cookie == nil then
        self.http:request(self.controller .. "api/auth/login", {
            options = {
                checkCertificate = false,
                method = 'POST',
                data = json.encode({
                    ['username'] = self.login,
                    ['password'] = self.password
                })
            },
            success = function(response)
                if response.status == 200 then
                    self.cookie = response.headers['Set-Cookie']
                    self:debug("loginUnifi() succeed")
                else
                    self:error("loginUnifi() failed: ", json.encode(response.data))
                end
            end,
            error = function(error)
                self:error("loginUnifi() failed: ", json.encode(error))
            end
        })
    end
end
function QuickApp:checkMacUnifi()
    local macInfo, lastSeen
    if self.cookie ~= nil then
        self.http:request(self.controller .. "proxy/network/api/s/" .. self.site .. "/stat/user/" .. self.mac, {
            options = {
                checkCertificate = false,
                method = 'GET',
                headers = {
                    ['Cookie'] = self.cookie
                }
            },
            success = function(response)
                if response.status == 200 then
                    self:trace("checkMacUnifi() succeed")
                    macInfo = json.decode(response.data)
                    if macInfo['meta']['rc'] == "ok" then
                        lastSeen = macInfo['data'][1]['last_seen']
                        if (lastSeen ~= nil) and ((os.time() - lastSeen) < self.awaydelay) then
                            self:setPresenceStatus("Home")
                        else
                            self:setPresenceStatus("Away")
                        end
                    else
                        self:setPresenceStatus("Away")
                    end
                else
                    self.cookie = nil
                    self:error("checkMacUnifi() failed: ", json.encode(response.data))
                end
            end,
            error = function(error)
                self.cookie = nil
                self:error("checkMacUnifi() failed: ", json.encode(error))
            end
        })
    end
end
function QuickApp:mainLoop()
    self:loginUnifi()
    self:checkMacUnifi()
    fibaro.setTimeout(self.frequency * 1000, function()
        self:mainLoop()
    end)
end
function QuickApp:onInit()
    self.controller = self:getVariable("controller")
    assert(self.controller ~= "", "controller is not set")
    if string.sub(self.controller, -1) ~= "/" then
        self.controller = self.controller .. "/"
    end
    self.site = self:getVariable("site")
    assert(self.site ~= "", "site is not set")
    self.login = self:getVariable("login")
    assert(self.login ~= "", "login is not set")
    self.password = self:getVariable("password")
    assert(self.password ~= "", "password is not set")
    self.frequency = self:getVariable("frequency")
    assert(self.frequency ~= "", "frequency is not set")
    self.frequency = tonumber(self.frequency)
    assert(self.frequency ~= nil, "frequency is not a number")
    self.mac = string.lower(self:getVariable("mac"))
    assert(self.mac ~= "", "mac is not set")
    assert(string.match(self.mac, '^[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]:[0-9a-f][0-9a-f]$') ~= nil, "mac address format is incorrect")
    self.awaydelay = tonumber(self:getVariable("away delay"))
    if self.awaydelay == nil then
        self:debug("onInit(): away delay equals frequency")
        self.awaydelay = self.frequency
    end
    self:setPresenceStatus("Unknown")
    self.cookie = nil
    self.http = net.HTTPClient({ timeout = 3000 })
    self:mainLoop()
end
 
  • Leuk
Waarderingen: PcRene
Ik gebruik tegenwoordig home assistant maar wel met fibaro HC2 als Z-Wave controler.
Daar had ik een goed werkende detectie maar die staat nu uit omdat alles via HomeAssistant wordt gedaan.

via een franse site (aanrader)


1 LUA scene voor de mobiele telefoons

Code:
--[[
%% autostart
%% properties
%% globals
--]]
--------------------------------------------------
-- Scene   : Ubiquiti Unifi
-- Author  : Lazer
-- Version : 1.2
-- Date    : April 2020
--------------------------------------------------

-- User variables
local URL = "https://192.168.x.x:443"
local username = "USERNMAE"
local password = "PASSWORD"
local intervalle = 10
local LAN_Devices = {
    {
        mac = "xx:xx:xx:xx:xx:xx", -- Smartphone 1
        vg = "Unifi_Naam1WiFi"
    },
    {
        mac = "xx:xx:xx:xx:xx:xx", -- Smartphone 2
        vg = "Unifi_Naam2WiFi"
    },
    {
        mac = "xx:xx:xx:xx:xx:xx", -- Smartphone 3
        vg = "Unifi_Naam3WiFi"
    }
}

-- System variables
local debug = false
local VG_Unifi_Cookie = "Unifi_Cookie" -- Global Variable used to store Cookie


--
-- Message() function
--
function Message(color, text)
    if color and color ~= "" then
        fibaro:debug('<span style="color:'..color..';">'..(text or '<i>nil</i>')..'</span>')
    else
        fibaro:debug(text or '<i>nil</i>')
    end
end


--
-- Login function
--
function Login(command)

    Message("fuchsia", "Login")

    local httpClient = net.HTTPClient()
    if debug then
        Message("grey", URL .. "/api/login")
    end
    -- Login
    httpClient:request(URL .. "/api/login", {
        success = function(response)
            if debug then
                Message("gray", json.encode(response))
            end
            if response.status == 200 then
                if response.data and response.data ~= "" then
                    local jsonTable = json.decode(response.data)
                    if jsonTable.meta and jsonTable.meta.rc and jsonTable.meta.rc == "ok" then
                        -- Get cookie
                        if response.headers and response.headers['Set-Cookie'] then
                            -- "Set-Cookie": "unifises=L1IADETuhsX6AwY44w72nCKftDOa1c1j; Path=\/; Secure; HttpOnly, csrf_token=b5y9pwpKD5dIcLqAxfHxUO2dQ6HUuvcL; Path=\/; Secure",
                            if debug then
                                Message("yellow", response.headers['Set-Cookie'])
                            end
                            -- Store cookie
                            Cookie = response.headers['Set-Cookie']
                            fibaro:setGlobal(VG_Unifi_Cookie, Cookie)
                            -- Execute given function as argument
                            if command and type(command) == "function" then
                                setTimeout(function() command() end, 0)
                            end
                        else
                            Message("red", "Error : missing Cookie in Response Headers")
                        end
                    else
                        Message("red", "Error : status = " .. tostring(response.status) .. " - rc = " .. (jsonTable.meta and jsonTable.meta.rc or "???") .. " - msg = " .. (jsonTable.meta and jsonTable.meta.msg or "???"))
                    end
                else
                    Message("red", "Error : empty response")
                end
            else
                Message("red", "Error : status=" .. tostring(response.status))
            end
        end,
        error = function(err)
            Message("red", 'httpClient:request() : Error : ' .. err)
        end,
        options = {
            method = 'POST',
            checkCertificate = false,
            data = json.encode({username=username, password=password, strict=true})
--            data = '{"username":"'..username..'","password":"'..password..'","strict":true}'
        }
    })

end -- function


--
-- GetDevices function
--
function GetDevices()

    Message("fuchsia", "GetDevices")

    local httpClient = net.HTTPClient()
    if debug then
        Message("grey", URL .. "/api/s/UniFi_Noordwal/stat/sta")
    end
    -- Get list of connected devices
    httpClient:request(URL .. "/api/s/UniFi_Noordwal/stat/sta", {
        success = function(response)
            if debug then
                Message("gray", json.encode(response))
            end
            if response.status == 200 then  -- HTTP 200 => OK
                if response.data and response.data ~= "" then
                    local jsonTable = json.decode(response.data)
                    if jsonTable.meta and jsonTable.meta.rc and jsonTable.meta.rc == "ok" then
                        if jsonTable.data then
                            local count = #jsonTable.data
                            if debug then
                                Message("yellow", "Found " .. count .. " devices")
                            end
                            -- Browse devices
                            local i
                            for i=1, count do
                                if debug then
                                    Message("blue", i.." hostname="..(jsonTable.data[i].hostname or "").." name="..(jsonTable.data[i].name or "").." mac="..(jsonTable.data[i].mac or "").." last_seen="..(jsonTable.data[i].last_seen or ""))
                                end
                                -- Look for device
                                local j
                                for j=1, #LAN_Devices do
                                    if string.lower(LAN_Devices[j].mac or "") == string.lower(jsonTable.data[i].mac or "") then
                                        local timestamp = fibaro:getGlobalValue(LAN_Devices[j].vg)
                                        if timestamp ~= jsonTable.data[i].last_seen then
                                            Message("green", "Found Host <b>"..(jsonTable.data[i].name or "").."</b> , MAC <b>"..(jsonTable.data[i].mac or "").."</b> , last seen <b>"..os.date('%d/%m/%Y %H:%M:%S', (jsonTable.data[i].last_seen or 0)).."</b>")
                                            fibaro:setGlobal(LAN_Devices[j].vg, jsonTable.data[i].last_seen or 0);
                                        end
                                        break
                                    end
                                end
                            end
                        else
                            Message("orange", "Warning : no device found")
                        end
                    else
                        Message("red", "Error : status = " .. tostring(response.status) .. " - rc = " .. (jsonTable.meta and jsonTable.meta.rc or "???") .. " - msg = " .. (jsonTable.meta and jsonTable.meta.msg or "???"))
                    end
                else
                    Message("red", "Error : empty response")
                end
            elseif response.status == 401 then  -- HTTP 401 => Unauthorized
                -- Need to login and get new cookie
                Message("orange", "Need to login and get new cookie")
                Login()
                return
            else
                if response.data and response.data ~= "" then
                    local jsonTable = json.decode(response.data)
                    Message("red", "Error : status = " .. tostring(response.status) .. " - rc = " .. (jsonTable.meta and jsonTable.meta.rc or "???") .. " - msg = " .. (jsonTable.meta and jsonTable.meta.msg or "???"))
                else
                    Message("red", "Error : status=" .. tostring(response.status))
                end
            end
        end,
        error = function(err)
            Message("red", 'httpClient:request() : Error : ' .. err)
        end,
        options = {
            method = 'GET',
            checkCertificate = false,
            headers = {
                ["Cookie"] = Cookie,
            }
        }
    })

    -- Wait
    if interval and interval > 0 then
        setTimeout(function() GetDevices() end, interval*1000)
    end

end -- function


--
-- Function : Create global variable
--
function CreateVG(varName, varValue, varEnum)
    Message("fuchsia", "CreateVG : <b>" .. (varName or "<i>nil</i>") .. "</b>")
    local isEnum = type(varEnum) == "table" and (#(varEnum or {}) > 0) and true or false
    local payload = {name=varName, value=(varValue or "")}
    if debug then
        Message("gray", json.encode(payload))
    end
    local response, status = api.post("/globalVariables", payload)
    if (tonumber(status) == 200 or tonumber(status) == 201) and response ~= nil and response ~= "" then
        Message("", 'Global variable "'..varName..'" created')
        if isEnum then
            local payload = {name=varName, value=(varValue or ""), isEnum=true, enumValues=varEnum}
            local response, status = api.put("/globalVariables/"..varName, payload)
            if (tonumber(status) == 200 or tonumber(status) == 201) and response ~= nil and response ~= "" then
                Message("", 'Global variable "'..varName..'" modified with enum values')
            else
                Message("red", 'Error : Can not modify enum global variable, status='..status..', payload='..json.encode(payload)..', response='..(response or ""))
            end
        end
    else
        Message("red", 'Error : Can not create global variable, status='..status..', payload='..json.encode(payload)..', response='..(response or ""))
    end
end -- function


--
-- Main loop
--

-- Check if global variables exist
local VG = {
    [VG_Unifi_Cookie] = {['default']='', ['enum']={}},
}
local i
for i=1, #LAN_Devices do
    VG[LAN_Devices[i].vg] = {['default']='0', ['enum']={}}
end
local vg, param
for vg, param in pairs(VG) do
    if debug then
        Message("gray", "Check if global variable '"..vg.."' exists")
    end
    local variable = api.get("/globalVariables/"..vg)
    -- {"created":1496865902,"modified":1497036821,"value":"XXXXX","isEnum":false,"name":"Unifi_Cookie","readOnly":false}
    if not variable then
        if debug then
            Message("gray", 'Global variable "'..vg..'" does not exist')
        end
        CreateVG(vg, param['default'], param['enum'])
    elseif debug then
        Message("green", 'Global variable "'..vg..'" exist')
    end
end

-- Get Cookie
Cookie = fibaro:getGlobalValue(VG_Unifi_Cookie)

-- Get trigger
local trigger = fibaro:getSourceTrigger()
if trigger["type"] == "autostart" then
    Message(nil, os.date('%d/%m/%Y').." : Scene instance autostart")
    interval = intervalle
    -- Call GetDevices function recursively
    setTimeout(function() GetDevices() end, 0)
elseif trigger["type"] == "other" then
    Message(nil, os.date('%d/%m/%Y').." : Scene instance manual launch")
    interval = 0
    -- Call GetDevices function only once
    if Cookie == nil or Cookie == "" then
        Login(GetDevices)
    else
        setTimeout(function() GetDevices() end, 0)
    end
else
    Message(nil, os.date('%d/%m/%Y').." : Unknown trigger : "..trigger["type"])
end

en daarna een LUA scene voor de home status



Code:
--[[
--[[
%% autostart
%% properties
%% globals
Unifi_TomWiFi
Unifi_PatriciaWiFi
Unifi_PeterWiFi
--]]

function Check()
 
        local timestamp = os.time()
        local homestatus = fibaro:getGlobalValue("HomeStatus")
          local TomWiFi = fibaro:getGlobalValue("TomWiFi")
          local PatriciaWiFi = fibaro:getGlobalValue("PatriciaWiFi")
          --fibaro:debug(homestatus);
           local tom = tonumber(fibaro:getGlobalValue("Unifi_TomWiFi"))
         --fibaro:debug(tom);
          local patricia = tonumber(fibaro:getGlobalValue("Unifi_PatriciaWiFi"))
         --fibaro:debug(patricia);
        local peter = tonumber(fibaro:getGlobalValue("Unifi_PeterWiFi"))
         --fibaro:debug(peter);
          local AbsenceTime = 6 --10 minutes
        local AbsenceTime2 = timestamp - (AbsenceTime * 60)
 
             if tonumber(tom) < AbsenceTime2 and tonumber(patricia) < AbsenceTime2 and tonumber(peter) < AbsenceTime2 then
                 fibaro:setGlobal("HomeStatus", "0")
                fibaro:debug('homestatus='..homestatus);
                 else
                fibaro:setGlobal("HomeStatus", "1")
                fibaro:debug('homestatus='..homestatus);
        end
                   if tonumber(tom) < AbsenceTime2 then
                 fibaro:setGlobal("TomWiFi", "0");
                fibaro:debug('TomWiFi='..TomWiFi);
                 else
                fibaro:setGlobal("TomWiFi", "1")
                fibaro:debug('TomWiFi='..TomWiFi);
    end
                if tonumber(patricia) < AbsenceTime2 then
                 fibaro:setGlobal("PatriciaWiFi", "0");
                fibaro:debug('PatriciaWiF='..PatriciaWiFi);
                 else
                fibaro:setGlobal("PatriciaWiFi", "1")
                fibaro:debug('PatriciaWiF='..PatriciaWiFi);
    end
end



local trigger = fibaro:getSourceTrigger()

if trigger["type"] == "autostart" then
    fibaro:debug(os.date('%d/%m/%Y').." : Autostart infinite loop...")
    while true do
        Check()
        fibaro:sleep(150*1000) -- 5 minutes
    end
elseif trigger["type"] == "global" then
    fibaro:debug("Global variable change : "..trigger['name'])
    Check()
elseif trigger["type"] == "other" then
    fibaro:debug(os.date('%d/%m/%Y').." : Started manually")
    Check()
elseif trigger["type"] == "property" then
    fibaro:debug(os.date('%d/%m/%Y').." : Property changed : ".. trigger['deviceID'].." => "..trigger['propertyName'])
else
    fibaro:debug(os.date('%d/%m/%Y').." : Unknown trigger : "..trigger["type"])
end
 
Laatst bewerkt:
  • Leuk
Waarderingen: SDeath
Activiteit
Er wordt op dit moment (nog) geen nieuwe reactie gepost.