[LUA] Geolocalisation et info IPhone

Vous avez créé un script LUA dont vous êtes fier, un .sh génial, un programme Python hors du commun, un Tuto, c'est ici que vous pouvez les partager.
christophe2836
Messages : 195
Inscription : 26 déc. 2017, 22:27
Contact :

Re: Geolocalisation et info Iphone

Message par christophe2836 »

Parfait
Juste que je suis toujours à 5mn de chez moi
Pourtant la même adresse dans localiser mon iPhone et Waze.
Et dans les logs j’ai une demande de localisation de mon user toutes les secondes
(Domoticz sur synology)
damolc
Messages : 240
Inscription : 24 juil. 2016, 22:08

Re: Geolocalisation et info Iphone

Message par damolc »

Pour la localisation : regarde vers le bas , tu dois avoir oublié la localisation gps

Par contre le logiciel consomme a fond la batterie de l iPhone :oops:
landaisbenj
Messages : 695
Inscription : 12 mars 2017, 19:24

Re: Geolocalisation et info Iphone

Message par landaisbenj »

Pour la batterie je crois que le dzvent est activé toute les minutes. Il faudrait voir, j’avais adapter une fonction pour augmenter le temps suivant la distance entre le domicile et la maison. Par exemple -5% du temps de trajet. Et si le smartphone et détecter au domicile ne pas activer le script. Jusqu’à ce que l’alarme soit activé..
Rpbi3b: Domoticz + Homebridge + Monit + Freebox scripts + Shellinabox; Rpbi2: Jarvis
Domoticz: Derniere stable; RFLINK: Dernière stable; Xiaomi Gateway
christophe2836
Messages : 195
Inscription : 26 déc. 2017, 22:27
Contact :

Re: Geolocalisation et info Iphone

Message par christophe2836 »

damolc a écrit :Pour la localisation : regarde vers le bas , tu dois avoir oublié la localisation gps

Par contre le logiciel consomme a fond la batterie de l iPhone :oops:
Non la localisation fonctionne (car quand je me déplace, j’ai bien les adresses où je me situe) mais quand je suis chez moi et bien en fait il me reste toujours 5mn de route. lol
Bon j’habite la campagne aussi.
damolc
Messages : 240
Inscription : 24 juil. 2016, 22:08

Re: Geolocalisation et info Iphone

Message par damolc »

J ai eu la même chose
C est ta position gps du domicile qu il faut refaire
FredWst
Messages : 21
Inscription : 03 oct. 2017, 21:24

Re: Geolocalisation et info Iphone

Message par FredWst »

Pour la batterie je crois que le dzvent est activé toute les minutes. Il faudrait voir, j’avais adapter une fonction pour augmenter le temps suivant la distance entre le domicile et la maison. Par exemple -5% du temps de trajet. Et si le smartphone et détecter au domicile ne pas activer le script. Jusqu’à ce que l’alarme soit activé..
Il me semble ne pas avoir ce problème de batterie, j'ai un peu de mal à faire le lien.
En ce qui concerne le script pour faire l'essai il suffit de changer la fréquence et passer à 5 min, il n'y a pas d'impacte sur le fonctionnement.

En moyenne votre batterie se décharge en 1 journée ? plus/moins ?

Fred
FredWst
Messages : 21
Inscription : 03 oct. 2017, 21:24

Re: Geolocalisation et info Iphone

Message par FredWst »

Bonsoir,

J'ai modifié le code pour essayer d'arranger le problème de batterie.

En déplacement appel toutes les 2 minutes sinon 6 minutes. Paramétrable voir code ci-dessous

Edit code 19/10 -> dans callback adresse

--if compte.DistanceDomicile < Precision then
compte.deplacement = false
--end

Code : Tout sélectionner

-- *************************************************************************************************

-- Précision (en km) de detection de position au domicile ou de changement de position
local Precision=0.2
local TimerDeplacement = 2 --  Le timer à 1 minute ne peut pas être utilisé !
local TimerPositionFixe = 3 -- Le timer à 3 donne un appel à 2 * 3 minutes ! voir doc Dzvents pour + d'explication

-- Trace 
local debug=true

-- Déclaration des utilisateurs.
-- Par défaut 3 utilisateurs possible.
-- name = "" -> utilisateur non utilisé.
-- Les devices nécéssaires sont créés automatiquement.
-- En cas de suppression d'un utilisateur, il faut supprimer les devices manuellement.

local users = {
                user1 = {name = ""; username = "";   password = ""};
                user2 = {name = "";  username = "";    password = "};
                user3 = {name = "";         username = "adresse mail";                  password = "mot de passe"};
}

-- *************************************************************************************************



-- Fonction de calcul de distance
-- Renvoi la distance en kilometre a une decimale entre deux coordonées GPS
local function distancekm(latitude1, longitude1, latitude2, longitude2)
    rayonTerre = 6378137;   -- Rayon équatorial de la terre en metre
    radlatx = math.rad(latitude1);
    radlonx = math.rad(longitude1);
    radlaty = math.rad(latitude2);
    radlony = math.rad(longitude2);
    calculLatitude = (radlaty - radlatx) / 2;
    calculLongitude = (radlony - radlonx) / 2;
    detail = (math.sin(calculLatitude))^2 + math.cos(radlatx) * math.cos(radlaty) * (math.sin(calculLongitude))^2;
    calcul = 2 * math.atan(math.sqrt(detail), math.sqrt(1 - detail));
    output = math.floor((rayonTerre * calcul)/100)/10
    return output
end

-- Fonction de recuperation des informations icloud
-- Renvoi les informations du telephone (Position GPS, Batterie, Status...)      
local function iCloud(triggered)
    --On recherche le device associé au devicename de l'utilisateur
    for key,value in pairs(triggered.json.content) do
        if value.deviceClass == 'iPhone' then     
            --On verifie que le device est localisé depuis peu pour recuperer les valeurs importantes
            if value.isLocating == true and value.location ~= nil and value.location.isInaccurate ~= true and value.location.isOld ~= true then
                result = {
                            batlvl = math.floor(value.batteryLevel * 100 / 1);
                            batstat = value.batteryStatus;
                            accuracy = value.location.isInaccurate;
                            latitudeiPhone = value.location.latitude;
        	                longitudeiPhone = value.location.longitude;
                            positionType = value.location.positionType;
                            timestampupdate = value.location.timeStamp;
        	                horizontalAccuracy = value.location.horizontalAccuracy
                         }	
                return result
            elseif value.isLocating == false or value.location == nil or value.location.isInaccurate == true or value.location.isOld == true or value.location.locationFinished == false then
                return nil
            else
                return nil
            end
        end
    end
    return nil
end


-- Fonction de calcule d'itineraire
-- Renvoi dans une table le temps en minute et la distance en metre de trajet entre deux coordonées GPS
local function waze(dz, triggered)
    convert = dz.utils.fromJSON(triggered.data)
    routeTotalDistm = 0
    for key,value in pairs(convert.response.results) do
        routeTotalDistm = routeTotalDistm + value.length
    end
    if routeTotalDistm ~= nil and convert.response.totalRouteTime ~= nil then
        trajet = { temps = convert.response.totalRouteTime ; distance = routeTotalDistm }
        return trajet
    end
    return nil
end

-- Recherche le user ayant déclenché httpResponses callback
local function findUser(dz,triggered)
    for usr,cpt in pairs(dz.data.users) do
        if string.find(triggered.callback,usr) then 
            return usr
        end
    end
end   

--Codage base64
local function encodeb64(data)
    local bb='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    return ((data:gsub('.', function(x) 
        r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return bb:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

local function jsonAPI(dz, apiCall)
	url = 'curl -s "'..dz.settings['Domoticz url']..'/json.htm?'..apiCall..'"'
	handle = assert(io.popen(url))
	result = handle:read("*a")
	handle:close()
	return dz.utils.fromJSON(result)
end	

--Crée virtual harware
local function createVirtualHardware(dz)
    jsonAPI(dz,"type=command&param=addhardware&htype=15&port=1&name=GeolocalisationDummy&enabled=true")
end

--Retourne idx du virtual harware s'il existe
local function isVirtualHardwareExist(dz)
    output = jsonAPI(dz,"type=hardware&filter=all&used=true&order=Name")
    if output ~= nil then
	    for index,result in pairs(output.result) do
            if result.Type == 15 then
                return result.idx
    	    end
        end
    end
	return -1        
end

--Retourne idx du device s'il existe
local function isVirtualDeviceExist(dz,device)
    output = jsonAPI(dz,"type=devices&filter=all&used=true&order=Name")
    if output ~= nil then
	    for index,result in pairs(output.result) do
            if result.Name == device then
                return result.idx
    	    end
        end
    end
	return -1
end

local function createObject(dz,nom)
    
    --Teste l'existance d'un virtual hardware
    index = isVirtualHardwareExist(dz)
    
    --Crée virtual harware s'il n'existe pas 
    if index == -1  then
       createVirtualHardware(dz) 
       index = isVirtualHardwareExist(dz)
    end
    
    if index then
        if isVirtualDeviceExist(dz,'Presence '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Presence%20"..nom.."&sensortype=6")
            id = isVirtualDeviceExist(dz, 'Presence '..nom)
            if id then 
                jsonAPI(dz, "type=setused&idx="..id.."&name=Presence%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            end
        end
            
        if isVirtualDeviceExist(dz,'Adresse '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Adresse%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Adresse%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Adresse%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
        
        if isVirtualDeviceExist(dz,'Trajet '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Trajet%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Trajet%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Trajet%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
        
        if isVirtualDeviceExist(dz,'Batterie '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Batterie%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Batterie%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Batterie%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
    end
end  


return {

	active = true,

	on = {
		    timer = {
		                'every '..TimerDeplacement..' minutes',
		                'every '..TimerPositionFixe..' minutes'
		    },
		    httpResponses = {   'iClouduser1', 'wazeuser1', 'Adresseuser1',
		                        'iClouduser2', 'wazeuser2', 'Adresseuser2',
		                        'iClouduser3', 'wazeuser3', 'Adresseuser3'
                            }
	},
	
	--Variables persistantes initialisées au premier lancement du script par le système
	--Après les données sont mémorisées : obligation liée au principe du callback, les données doivent être non volatile entre appel
	--Le fichier de configuration ce trouve là -> domoticz/scripts/dzVents/data/ et se nomme __data_Geolocalisation.lua
    data = {
                users = { initial = {
                    
                                        user1 =  { 
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    delai = 1;
                                        },
                                        user2  =  {
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    delai = 6;
                                        },
                                        user3  =  {
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    delai = 12;
                                        },
                                    }
                }
    },


	execute = function(domoticz, triggeredItem)

        -- Latitude et Longitude du domicile:
        latitudeDomicile=domoticz.settings.location.latitude
        longitudeDomicile=domoticz.settings.location.longitude


        --Déclenchement toutes les minutes aucun impact sur la durée batterie de l'iPhone ?????
        if (triggeredItem.isTimer) then

            for user,compte1 in pairs(users) do    

                compte = domoticz.data.users[user]
        
                if compte1.name ~= '' then
 
                    createObject(domoticz, compte1.name)
                    
                    if ( triggeredItem.trigger == 'every '..TimerDeplacement..' minutes' and compte.deplacement == true ) or ( triggeredItem.trigger == 'every '..TimerPositionFixe..' minutes' and compte.deplacement == false ) then
                    
                        if debug then
                            print('Lancement demande de localisation '..compte1.name..' dans '..compte.delai..' seconde(s)')
                        end
                
                        domoticz.openURL({
                                            url =  'https://p43-fmipmobile.icloud.com/fmipservice/device/'..compte1.username..'/initClient',
                                            headers =  {
                                                            ["Authorization"] = "Basic "..encodeb64(compte1.username..':'..compte1.password), --Type authentification basic fonctionne avec authentification deux facteurs
                                                            ["Content-Type"] = "application/json",
                                                            ["charset"] = "utf-8",                                        
                                                            ["X-Apple-Find-Api-Ver"] = "2.0",
                                                            ["X-Apple-Authscheme"] = "UserIdGuest",
                                                            ["X-Apple-Realm-Support"] = "1.0",
                                                            ["User-agent"] = "Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)",
                                                            ["X-Client-Name"] = "iPad",
                                                            ["Accept-Language"] = "en-us",
                                                            ["Connection"] = "keep-alive",
                                                            ["Origin"] = "https://www.icloud.com"  
                                                        },
                                            method = 'POST',
                                            callback = 'iCloud'..user
                                        }).afterSec(compte.delai)     --compte.delai : Astuce pour décaler les demandes sinon waze n'aime pas !
                    end
                end
            end
            
        elseif triggeredItem.isHTTPResponse and triggeredItem.ok then
                    
    	    if (triggeredItem.isJSON) then 
    	    
    	        --Test type de callback
                if string.find(triggeredItem.callback,'iCloud') then
                    
                    --Récupère le user qui génère le callback                
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                    
                    --Fonction de recherche données uniquement deviceClass:iPhone voir filtre dans la fonction elle même en début de code
                    device = iCloud(triggeredItem)
                        
                    if device ~= nil then
                            
                        -- Ancienne position:
                        latitudePrecente = compte.latitudeiPhone
                        longitudePrecedente = compte.longitudeiPhone 
                            
                        -- Ancienne distance [position-domicile]:
                        DistanceDomicilePrecedente = distancekm(latitudePrecente, longitudePrecedente, latitudeDomicile, longitudeDomicile) 

                        -- Distance [nouvelle position-ancienne position]:       
                        EcartDistance = distancekm(device.latitudeiPhone, device.longitudeiPhone,latitudePrecente, longitudePrecedente)
                                    
                        -- Distance [nouvelle position-domicile]:       
                        compte.DistanceDomicile = distancekm(device.latitudeiPhone, device.longitudeiPhone, latitudeDomicile, longitudeDomicile)

                        --Presence: si la distance avec le domicile est inferieure à la précision souhaitée alors le smartphone est present au domicile
                        if compte.DistanceDomicile < Precision then --Presence
                            if domoticz.devices('Presence ' .. compte1.name).state == 'Off' then --Arrivée
                                domoticz.devices('Presence ' .. compte1.name).switchOn().silent()
                            end
                            compte.DistanceDomicile = 0
                        else
                            if domoticz.devices('Presence ' .. compte1.name).state == 'On' then
                                domoticz.devices('Presence ' .. compte1.name).switchOff().silent() 
                            end
                        end
                    
                        if debug then
                            print('Callback iCloud : '..compte1.name..': '..compte.DistanceDomicile..' km du domicile, '..device.batlvl..'% de batterie restante. Statut: "'..device.batstat..'". Precision: '..device.horizontalAccuracy)
                        end
                    
                        --Deplacement: si la distance avec l'ancienne position est superieure à la précision souhaitée alors le smartphone n'est plus au meme endroit et se deplace
                        if EcartDistance > Precision then
                            compte.deplacement = true
                            if DistanceDomicilePrecedente > compte.DistanceDomicile then
                                compte.position='En rapprochement du domicile'
                            else
                                compte.position='En éloignement du domicile'
                            end
                            
                            if debug then    
                                print('iPhone de '..compte1.name.. ': '..compte.position)
                            end
                        
                            domoticz.devices('Adresse '..compte1.name).updateText(compte.position)
                            if debug then
                                print('Lancement demande de trajet '..compte1.name)
                            end
                            
                            domoticz.openURL({
                                                url = 'https://www.waze.com/row-RoutingManager/routingRequest?from=x:'..longitudeDomicile..'+y:'..latitudeDomicile..'&to=x:'..device.longitudeiPhone..'+y:'..device.latitudeiPhone..'&at=0&returnJSON=true&returnGeometries=false&returnInstructions=false&timeout=30000&nPaths=1&clientVersion=1.0.0&options=AVOID_TRAILS:t,ALLOW_UTURNS:t',
                                                headers={["Content-Type"] = "application/json",["referer"]="https://www.waze.com"},
                                                method = 'POST',
                                                callback = 'waze'..user
                                            })                                   
                        else
                            if compte.deplacement == true then
                                if debug then
                                    print("Lancement demande de l'adresse de "..compte1.name) 
                                end

                                domoticz.openURL({
                                                    url =  'https://api-adresse.data.gouv.fr/reverse/?lon='.. device.longitudeiPhone .. '&lat=' .. device.latitudeiPhone,
                                                    method = 'GET',
                                                    callback = 'Adresse'..user
                                                }) 
                            end
                        end

                        domoticz.devices('Batterie '..compte1.name).updateText('Niveau : '..device.batlvl..'%.\13\10 Statut : '..device.batstat)
                        
                        --Mémorisation nouvelle coordonnée iPhone
                        --Mise a jour des informations
                        compte.latitudeiPhone = device.latitudeiPhone
                        compte.longitudeiPhone = device.longitudeiPhone
                        
                    else 
                        print('Retour iCloud problème : '..compte1.name) 
                    end	    		    
                end
                
                --Test type de callback    
                if string.find(triggeredItem.callback,'Adresse') then
                    
                    --Récupère le user qui génère le callback        
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                        
                    adresse = triggeredItem.json.features[1].properties.label
                    if adresse ~=nil then
                        compte.position=adresse..' ('..compte.DistanceDomicile..' km)'
                        if debug then
                            print('Callback Adresse : '..compte1.name..': '..compte.position)
                        end
                        domoticz.devices('Adresse '..compte1.name).updateText(compte.position)
                        --if compte.DistanceDomicile < Precision then
                            compte.deplacement = false
                        --end
                    else
                        print('Retour Adresse problème : '..compte1.name)
                        compte.position=domoticz.devices('Adresse '..compte1.name).state
                    end
                end
    	    else 
    	        --C'est bien un format JSON mais domoticz ne le detecte pas !
    	        --Test type de callback
    	        if string.find(triggeredItem.callback,'waze') then
    	            
    	            --Récupère le user qui génère le callback    
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                        
                    trajet = waze(domoticz,triggeredItem)
                    if trajet ~= nil then
                        --Fonction waze retourne pour le trajet entre deux coordonées une table avec le temps en seconde et la distance en metre
                        heures=math.floor(trajet.temps / 3600)
                        minutes=math.floor((trajet.temps % 3600) / 60)
                        secondes=math.floor((trajet.temps % 3600) % 60)
                        ETA=os.date("%Hh%M",os.time()+trajet.temps)
                        duree=heures..'h'..minutes..'min'
                        trafic='Heure d\'arrivée: '..ETA..' - '..tostring(((math.floor(trajet.distance/100))/10))..'Km, '..duree
                        if debug then
                            print('Callback waze : ' .. compte1.name .. ': '..trafic)
                        end
                        domoticz.devices('Trajet '..compte1.name).updateText(trafic)
                    else
                        print('Retour Waze problème : '..compte1.name)
                    end
                end
    	    end
        end
	end
	
}

Fred
Dernière modification par FredWst le 19 oct. 2019, 17:50, modifié 2 fois.
christophe2836
Messages : 195
Inscription : 26 déc. 2017, 22:27
Contact :

Re: Geolocalisation et info Iphone

Message par christophe2836 »

FredWst a écrit :Bonsoir,

J'ai modifié le code pour essayer d'arranger le problème de batterie.

En déplacement appel toutes les 2 minutes sinon 6 minutes. Paramétrable voir code ci-dessous

Code : Tout sélectionner

-- *************************************************************************************************

-- Précision (en km) de detection de position au domicile ou de changement de position
local Precision=0.2
local TimerDeplacement = 2 --  Le timer à 1 minute ne peut pas être utilisé !
local TimerPositionFixe = 3 -- Le timer à 3 donne un appel à 2 * 3 minutes ! voir doc Dzvents pour + d'explication

-- Trace 
local debug=true

-- Déclaration des utilisateurs.
-- Par défaut 3 utilisateurs possible.
-- name = "" -> utilisateur non utilisé.
-- Les devices nécéssaires sont créés automatiquement.
-- En cas de suppression d'un utilisateur, il faut supprimer les devices manuellement.

local users = {
                user1 = {name = ""; username = "";   password = ""};
                user2 = {name = "";  username = "";    password = "};
                user3 = {name = "";         username = "adresse mail";                  password = "mot de passe"};
}

-- *************************************************************************************************



-- Fonction de calcul de distance
-- Renvoi la distance en kilometre a une decimale entre deux coordonées GPS
local function distancekm(latitude1, longitude1, latitude2, longitude2)
    rayonTerre = 6378137;   -- Rayon équatorial de la terre en metre
    radlatx = math.rad(latitude1);
    radlonx = math.rad(longitude1);
    radlaty = math.rad(latitude2);
    radlony = math.rad(longitude2);
    calculLatitude = (radlaty - radlatx) / 2;
    calculLongitude = (radlony - radlonx) / 2;
    detail = (math.sin(calculLatitude))^2 + math.cos(radlatx) * math.cos(radlaty) * (math.sin(calculLongitude))^2;
    calcul = 2 * math.atan(math.sqrt(detail), math.sqrt(1 - detail));
    output = math.floor((rayonTerre * calcul)/100)/10
    return output
end

-- Fonction de recuperation des informations icloud
-- Renvoi les informations du telephone (Position GPS, Batterie, Status...)      
local function iCloud(triggered)
    --On recherche le device associé au devicename de l'utilisateur
    for key,value in pairs(triggered.json.content) do
        if value.deviceClass == 'iPhone' then     
            --On verifie que le device est localisé depuis peu pour recuperer les valeurs importantes
            if value.isLocating == true and value.location ~= nil and value.location.isInaccurate ~= true and value.location.isOld ~= true then
                result = {
                            batlvl = math.floor(value.batteryLevel * 100 / 1);
                            batstat = value.batteryStatus;
                            accuracy = value.location.isInaccurate;
                            latitudeiPhone = value.location.latitude;
        	                longitudeiPhone = value.location.longitude;
                            positionType = value.location.positionType;
                            timestampupdate = value.location.timeStamp;
        	                horizontalAccuracy = value.location.horizontalAccuracy
                         }	
                return result
            elseif value.isLocating == false or value.location == nil or value.location.isInaccurate == true or value.location.isOld == true or value.location.locationFinished == false then
                return nil
            else
                return nil
            end
        end
    end
    return nil
end


-- Fonction de calcule d'itineraire
-- Renvoi dans une table le temps en minute et la distance en metre de trajet entre deux coordonées GPS
local function waze(dz, triggered)
    convert = dz.utils.fromJSON(triggered.data)
    routeTotalDistm = 0
    for key,value in pairs(convert.response.results) do
        routeTotalDistm = routeTotalDistm + value.length
    end
    if routeTotalDistm ~= nil and convert.response.totalRouteTime ~= nil then
        trajet = { temps = convert.response.totalRouteTime ; distance = routeTotalDistm }
        return trajet
    end
    return nil
end

-- Recherche le user ayant déclenché httpResponses callback
local function findUser(dz,triggered)
    for usr,cpt in pairs(dz.data.users) do
        if string.find(triggered.callback,usr) then 
            return usr
        end
    end
end   

--Codage base64
local function encodeb64(data)
    local bb='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    return ((data:gsub('.', function(x) 
        r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return bb:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

local function jsonAPI(dz, apiCall)
	url = 'curl -s "'..dz.settings['Domoticz url']..'/json.htm?'..apiCall..'"'
	handle = assert(io.popen(url))
	result = handle:read("*a")
	handle:close()
	return dz.utils.fromJSON(result)
end	

--Crée virtual harware
local function createVirtualHardware(dz)
    jsonAPI(dz,"type=command&param=addhardware&htype=15&port=1&name=GeolocalisationDummy&enabled=true")
end

--Retourne idx du virtual harware s'il existe
local function isVirtualHardwareExist(dz)
    output = jsonAPI(dz,"type=hardware&filter=all&used=true&order=Name")
    if output ~= nil then
	    for index,result in pairs(output.result) do
            if result.Type == 15 then
                return result.idx
    	    end
        end
    end
	return -1        
end

--Retourne idx du device s'il existe
local function isVirtualDeviceExist(dz,device)
    output = jsonAPI(dz,"type=devices&filter=all&used=true&order=Name")
    if output ~= nil then
	    for index,result in pairs(output.result) do
            if result.Name == device then
                return result.idx
    	    end
        end
    end
	return -1
end

local function createObject(dz,nom)
    
    --Teste l'existance d'un virtual hardware
    index = isVirtualHardwareExist(dz)
    
    --Crée virtual harware s'il n'existe pas 
    if index == -1  then
       createVirtualHardware(dz) 
       index = isVirtualHardwareExist(dz)
    end
    
    if index then
        if isVirtualDeviceExist(dz,'Presence '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Presence%20"..nom.."&sensortype=6")
            id = isVirtualDeviceExist(dz, 'Presence '..nom)
            if id then 
                jsonAPI(dz, "type=setused&idx="..id.."&name=Presence%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            end
        end
            
        if isVirtualDeviceExist(dz,'Adresse '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Adresse%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Adresse%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Adresse%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
        
        if isVirtualDeviceExist(dz,'Trajet '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Trajet%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Trajet%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Trajet%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
        
        if isVirtualDeviceExist(dz,'Batterie '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Batterie%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Batterie%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Batterie%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
    end
end  


return {

	active = true,

	on = {
		    timer = {
		                'every '..TimerDeplacement..' minutes',
		                'every '..TimerPositionFixe..' minutes'
		    },
		    httpResponses = {   'iClouduser1', 'wazeuser1', 'Adresseuser1',
		                        'iClouduser2', 'wazeuser2', 'Adresseuser2',
		                        'iClouduser3', 'wazeuser3', 'Adresseuser3'
                            }
	},
	
	--Variables persistantes initialisées au premier lancement du script par le système
	--Après les données sont mémorisées : obligation liée au principe du callback, les données doivent être non volatile entre appel
	--Le fichier de configuration ce trouve là -> domoticz/scripts/dzVents/data/ et se nomme __data_Geolocalisation.lua
    data = {
                users = { initial = {
                    
                                        user1 =  { 
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    delai = 1;
                                        },
                                        user2  =  {
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    delai = 6;
                                        },
                                        user3  =  {
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    delai = 12;
                                        },
                                    }
                }
    },


	execute = function(domoticz, triggeredItem)

        -- Latitude et Longitude du domicile:
        latitudeDomicile=domoticz.settings.location.latitude
        longitudeDomicile=domoticz.settings.location.longitude


        --Déclenchement toutes les minutes aucun impact sur la durée batterie de l'iPhone ?????
        if (triggeredItem.isTimer) then

            for user,compte1 in pairs(users) do    

                compte = domoticz.data.users[user]
        
                if compte1.name ~= '' then
 
                    createObject(domoticz, compte1.name)
                    
                    if ( triggeredItem.trigger == 'every '..TimerDeplacement..' minutes' and compte.deplacement == true ) or ( triggeredItem.trigger == 'every '..TimerPositionFixe..' minutes' and compte.deplacement == false ) then
                    
                        if debug then
                            print('Lancement demande de localisation '..compte1.name..' dans '..compte.delai..' seconde(s)')
                        end
                
                        domoticz.openURL({
                                            url =  'https://p43-fmipmobile.icloud.com/fmipservice/device/'..compte1.username..'/initClient',
                                            headers =  {
                                                            ["Authorization"] = "Basic "..encodeb64(compte1.username..':'..compte1.password), --Type authentification basic fonctionne avec authentification deux facteurs
                                                            ["Content-Type"] = "application/json",
                                                            ["charset"] = "utf-8",                                        
                                                            ["X-Apple-Find-Api-Ver"] = "2.0",
                                                            ["X-Apple-Authscheme"] = "UserIdGuest",
                                                            ["X-Apple-Realm-Support"] = "1.0",
                                                            ["User-agent"] = "Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)",
                                                            ["X-Client-Name"] = "iPad",
                                                            ["Accept-Language"] = "en-us",
                                                            ["Connection"] = "keep-alive",
                                                            ["Origin"] = "https://www.icloud.com"  
                                                        },
                                            method = 'POST',
                                            callback = 'iCloud'..user
                                        }).afterSec(compte.delai)     --compte.delai : Astuce pour décaler les demandes sinon waze n'aime pas !
                    end
                end
            end
            
        elseif triggeredItem.isHTTPResponse and triggeredItem.ok then
                    
    	    if (triggeredItem.isJSON) then 
    	    
    	        --Test type de callback
                if string.find(triggeredItem.callback,'iCloud') then
                    
                    --Récupère le user qui génère le callback                
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                    
                    --Fonction de recherche données uniquement deviceClass:iPhone voir filtre dans la fonction elle même en début de code
                    device = iCloud(triggeredItem)
                        
                    if device ~= nil then
                            
                        -- Ancienne position:
                        latitudePrecente = compte.latitudeiPhone
                        longitudePrecedente = compte.longitudeiPhone 
                            
                        -- Ancienne distance [position-domicile]:
                        DistanceDomicilePrecedente = distancekm(latitudePrecente, longitudePrecedente, latitudeDomicile, longitudeDomicile) 

                        -- Distance [nouvelle position-ancienne position]:       
                        EcartDistance = distancekm(device.latitudeiPhone, device.longitudeiPhone,latitudePrecente, longitudePrecedente)
                                    
                        -- Distance [nouvelle position-domicile]:       
                        compte.DistanceDomicile = distancekm(device.latitudeiPhone, device.longitudeiPhone, latitudeDomicile, longitudeDomicile)

                        --Presence: si la distance avec le domicile est inferieure à la précision souhaitée alors le smartphone est present au domicile
                        if compte.DistanceDomicile < Precision then --Presence
                            if domoticz.devices('Presence ' .. compte1.name).state == 'Off' then --Arrivée
                                domoticz.devices('Presence ' .. compte1.name).switchOn().silent()
                            end
                            compte.DistanceDomicile = 0
                        else
                            if domoticz.devices('Presence ' .. compte1.name).state == 'On' then
                                domoticz.devices('Presence ' .. compte1.name).switchOff().silent() 
                            end
                        end
                    
                        if debug then
                            print('Callback iCloud : '..compte1.name..': '..compte.DistanceDomicile..' km du domicile, '..device.batlvl..'% de batterie restante. Statut: "'..device.batstat..'". Precision: '..device.horizontalAccuracy)
                        end
                    
                        --Deplacement: si la distance avec l'ancienne position est superieure à la précision souhaitée alors le smartphone n'est plus au meme endroit et se deplace
                        if EcartDistance > Precision then
                            compte.deplacement = true
                            if DistanceDomicilePrecedente > compte.DistanceDomicile then
                                compte.position='En rapprochement du domicile'
                            else
                                compte.position='En éloignement du domicile'
                            end
                            
                            if debug then    
                                print('iPhone de '..compte1.name.. ': '..compte.position)
                            end
                        
                            domoticz.devices('Adresse '..compte1.name).updateText(compte.position)
                            if debug then
                                print('Lancement demande de trajet '..compte1.name)
                            end
                            
                            domoticz.openURL({
                                                url = 'https://www.waze.com/row-RoutingManager/routingRequest?from=x:'..longitudeDomicile..'+y:'..latitudeDomicile..'&to=x:'..device.longitudeiPhone..'+y:'..device.latitudeiPhone..'&at=0&returnJSON=true&returnGeometries=false&returnInstructions=false&timeout=30000&nPaths=1&clientVersion=1.0.0&options=AVOID_TRAILS:t,ALLOW_UTURNS:t',
                                                headers={["Content-Type"] = "application/json",["referer"]="https://www.waze.com"},
                                                method = 'POST',
                                                callback = 'waze'..user
                                            })                                   
                        else
                            if compte.deplacement == true then
                                if debug then
                                    print("Lancement demande de l'adresse de "..compte1.name) 
                                end

                                domoticz.openURL({
                                                    url =  'https://api-adresse.data.gouv.fr/reverse/?lon='.. device.longitudeiPhone .. '&lat=' .. device.latitudeiPhone,
                                                    method = 'GET',
                                                    callback = 'Adresse'..user
                                                }) 
                            end
                        end

                        domoticz.devices('Batterie '..compte1.name).updateText('Niveau : '..device.batlvl..'%.\13\10 Statut : '..device.batstat)
                        
                        --Mémorisation nouvelle coordonnée iPhone
                        --Mise a jour des informations
                        compte.latitudeiPhone = device.latitudeiPhone
                        compte.longitudeiPhone = device.longitudeiPhone
                        
                    else 
                        print('Retour iCloud problème : '..compte1.name) 
                    end	    		    
                end
                
                --Test type de callback    
                if string.find(triggeredItem.callback,'Adresse') then
                    
                    --Récupère le user qui génère le callback        
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                        
                    adresse = triggeredItem.json.features[1].properties.label
                    if adresse ~=nil then
                        compte.position=adresse..' ('..compte.DistanceDomicile..' km)'
                        if debug then
                            print('Callback Adresse : '..compte1.name..': '..compte.position)
                        end
                        domoticz.devices('Adresse '..compte1.name).updateText(compte.position)
                        if compte.DistanceDomicile < Precision then
                            compte.deplacement = false
                        end
                    else
                        print('Retour Adresse problème : '..compte1.name)
                        compte.position=domoticz.devices('Adresse '..compte1.name).state
                    end
                end
    	    else 
    	        --C'est bien un format JSON mais domoticz ne le detecte pas !
    	        --Test type de callback
    	        if string.find(triggeredItem.callback,'waze') then
    	            
    	            --Récupère le user qui génère le callback    
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                        
                    trajet = waze(domoticz,triggeredItem)
                    if trajet ~= nil then
                        --Fonction waze retourne pour le trajet entre deux coordonées une table avec le temps en seconde et la distance en metre
                        heures=math.floor(trajet.temps / 3600)
                        minutes=math.floor((trajet.temps % 3600) / 60)
                        secondes=math.floor((trajet.temps % 3600) % 60)
                        ETA=os.date("%Hh%M",os.time()+trajet.temps)
                        duree=heures..'h'..minutes..'min'
                        trafic='Heure d\'arrivée: '..ETA..' - '..tostring(((math.floor(trajet.distance/100))/10))..'Km, '..duree
                        if debug then
                            print('Callback waze : ' .. compte1.name .. ': '..trafic)
                        end
                        domoticz.devices('Trajet '..compte1.name).updateText(trafic)
                    else
                        print('Retour Waze problème : '..compte1.name)
                    end
                end
    	    end
        end
	end
	
}

Fred
Merci , je vais tester ça et voir demain si la batterie dure plus longtemps Image
FredWst
Messages : 21
Inscription : 03 oct. 2017, 21:24

Re: Geolocalisation et info Iphone

Message par FredWst »

Bonjour,

local TimerDeplacement = 3
local TimerPositionFixe = 5

Après essaie ces deux valeurs semblent un bon compromis avec la petite modification apporté au code voir ci-dessus.

Fred
FredWst
Messages : 21
Inscription : 03 oct. 2017, 21:24

Re: Geolocalisation et info Iphone

Message par FredWst »

Bonjour,

Modification de la gestion timer. Plus de contrainte comme dans la version précédente.
Une variable global dans la structure utilisateur a été ajouté pour cette gestion.
Il faut pour être certain que script fonctionne correctement supprimer dans le répertoire suivant:
domoticz/scripts/dzVents/data/ le fichier script nommé __data_nom du script.lua
En ayant auparavant stoppé l'exécution du script.

Mon iPhone 5s arrive à 50% de batterie en fin de journée, mais cela va dépendre de l'utilisation que vous en avez.

Edit 23/10 : en rapprochement ou éloignement indique l'adresse

Code : Tout sélectionner

-- *************************************************************************************************

-- Précision (en km) de detection de position au domicile ou de changement de position
local Precision=0.2

local TimerDeplacement = 5 --Temps en minutes pour l'interrogation quand détection déplacement
local TimerPositionFixe = 10 --Temps en minute pour l'interrogation quand détection position fixe

-- Trace 
local debug = true 

-- Déclaration des utilisateurs.
-- Par défaut 3 utilisateurs possible.
-- name = "" -> utilisateur non utilisé.
-- Les devices nécéssaires sont créés automatiquement.
-- En cas de suppression d'un utilisateur, il faut supprimer les devices manuellement.

local users = {
                user1 = {name = ""; username = "";   password = ""};
                user2 = {name = "";  username = "";    password = ""};
                user3 = {name = "";         username = "adresse mail";                  password = "mot de passe"};
}

-- *************************************************************************************************



-- Fonction de calcul de distance
-- Renvoi la distance en kilometre a une decimale entre deux coordonées GPS
local function distancekm(latitude1, longitude1, latitude2, longitude2)
    rayonTerre = 6378137;   -- Rayon équatorial de la terre en metre
    radlatx = math.rad(latitude1);
    radlonx = math.rad(longitude1);
    radlaty = math.rad(latitude2);
    radlony = math.rad(longitude2);
    calculLatitude = (radlaty - radlatx) / 2;
    calculLongitude = (radlony - radlonx) / 2;
    detail = (math.sin(calculLatitude))^2 + math.cos(radlatx) * math.cos(radlaty) * (math.sin(calculLongitude))^2;
    calcul = 2 * math.atan(math.sqrt(detail), math.sqrt(1 - detail));
    output = math.floor((rayonTerre * calcul)/100)/10
    return output
end

-- Fonction de recuperation des informations icloud
-- Renvoi les informations du telephone (Position GPS, Batterie, Status...)      
local function iCloud(triggered)
    --On recherche le device associé au devicename de l'utilisateur
    for key,value in pairs(triggered.json.content) do
        if value.deviceClass == 'iPhone' then     
            --On verifie que le device est localisé depuis peu pour recuperer les valeurs importantes
            if value.isLocating == true and value.location ~= nil and value.location.isInaccurate ~= true and value.location.isOld ~= true then
                result = {
                            batlvl = math.floor(value.batteryLevel * 100 / 1);
                            batstat = value.batteryStatus;
                            accuracy = value.location.isInaccurate;
                            latitudeiPhone = value.location.latitude;
        	                longitudeiPhone = value.location.longitude;
                            positionType = value.location.positionType;
                            timestampupdate = value.location.timeStamp;
        	                horizontalAccuracy = value.location.horizontalAccuracy
                         }	
                return result
            elseif value.isLocating == false or value.location == nil or value.location.isInaccurate == true or value.location.isOld == true or value.location.locationFinished == false then
                return nil
            else
                return nil
            end
        end
    end
    return nil
end


-- Fonction de calcule d'itineraire
-- Renvoi dans une table le temps en minute et la distance en metre de trajet entre deux coordonées GPS
local function waze(dz, triggered)
    convert = dz.utils.fromJSON(triggered.data)
    routeTotalDistm = 0
    for key,value in pairs(convert.response.results) do
        routeTotalDistm = routeTotalDistm + value.length
    end
    if routeTotalDistm ~= nil and convert.response.totalRouteTime ~= nil then
        trajet = { temps = convert.response.totalRouteTime ; distance = routeTotalDistm }
        return trajet
    end
    return nil
end

-- Recherche le user ayant déclenché httpResponses callback
local function findUser(dz,triggered)
    for usr,cpt in pairs(dz.data.users) do
        if string.find(triggered.callback,usr) then 
            return usr
        end
    end
end   

--Codage base64
local function encodeb64(data)
    local bb='ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/'
    return ((data:gsub('.', function(x) 
        r,b='',x:byte()
        for i=8,1,-1 do r=r..(b%2^i-b%2^(i-1)>0 and '1' or '0') end
        return r;
    end)..'0000'):gsub('%d%d%d?%d?%d?%d?', function(x)
        if (#x < 6) then return '' end
        c=0
        for i=1,6 do c=c+(x:sub(i,i)=='1' and 2^(6-i) or 0) end
        return bb:sub(c+1,c+1)
    end)..({ '', '==', '=' })[#data%3+1])
end

local function jsonAPI(dz, apiCall)
	url = 'curl -s "'..dz.settings['Domoticz url']..'/json.htm?'..apiCall..'"'
	handle = assert(io.popen(url))
	result = handle:read("*a")
	handle:close()
	return dz.utils.fromJSON(result)
end	

--Crée virtual harware
local function createVirtualHardware(dz)
    jsonAPI(dz,"type=command&param=addhardware&htype=15&port=1&name=GeolocalisationDummy&enabled=true")
end

--Retourne idx du virtual harware s'il existe
local function isVirtualHardwareExist(dz)
    output = jsonAPI(dz,"type=hardware&filter=all&used=true&order=Name")
    if output ~= nil then
	    for index,result in pairs(output.result) do
            if result.Type == 15 then
                return result.idx
    	    end
        end
    end
	return -1        
end

--Retourne idx du device s'il existe
local function isVirtualDeviceExist(dz,device)
    output = jsonAPI(dz,"type=devices&filter=all&used=true&order=Name")
    if output ~= nil then
	    for index,result in pairs(output.result) do
            if result.Name == device then
                return result.idx
    	    end
        end
    end
	return -1
end

local function createObject(dz,nom)
    
    --Teste l'existance d'un virtual hardware
    index = isVirtualHardwareExist(dz)
    
    --Crée virtual harware s'il n'existe pas 
    if index == -1  then
       createVirtualHardware(dz) 
       index = isVirtualHardwareExist(dz)
    end
    
    if index then
        if isVirtualDeviceExist(dz,'Presence '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Presence%20"..nom.."&sensortype=6")
            id = isVirtualDeviceExist(dz, 'Presence '..nom)
            if id then 
                jsonAPI(dz, "type=setused&idx="..id.."&name=Presence%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            end
        end
            
        if isVirtualDeviceExist(dz,'Adresse '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Adresse%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Adresse%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Adresse%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
        
        if isVirtualDeviceExist(dz,'Trajet '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Trajet%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Trajet%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Trajet%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
        
        if isVirtualDeviceExist(dz,'Batterie '..nom) == -1 then 
            jsonAPI(dz, "type=createvirtualsensor&idx="..index.."&sensorname=Batterie%20"..nom.."&sensortype=5")
            --id = isVirtualDeviceExist(dz, 'Batterie%20'..nom)
            --if id then 
            --    jsonAPI(dz, "type=setused&idx="..id.."&name=Batterie%20"..nom.."&description=&strparam1&strparam2&protected=false&switchtype=0&customimage=18&used=true&addjvalue=0&addjvalue2=0&option")  
            --end
        end
    end
end  


return {

	active = true,

	on = {
		    timer = {
		                'every minute'
		    },
		    httpResponses = {   'iClouduser1', 'wazeuser1', 'Adresseuser1',
		                        'iClouduser2', 'wazeuser2', 'Adresseuser2',
		                        'iClouduser3', 'wazeuser3', 'Adresseuser3'
                            }
	},
	
	--Variables persistantes initialisées au premier lancement du script par le système
	--Après les données sont mémorisées : obligation liée au principe du callback, les données doivent être non volatile entre appel
	--Le fichier de configuration ce trouve là -> domoticz/scripts/dzVents/data/ et se nomme __data_Geolocalisation.lua
    data = {
                users = { initial = {
                    
                                        user1 =  { 
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    passage = TimerDeplacement - 1;
	                                                    delai = 1;
                                        },
                                        user2  =  {
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    passage = TimerDeplacement - 1;
	                                                    delai = 6;
                                        },
                                        user3  =  {
                                                        latitudeiPhone = 0;
	                                                    longitudeiPhone = 0;
	                                                    DistanceDomicile = 0;
	                                                    deplacement = true;
	                                                    position = '';
	                                                    passage = TimerDeplacement - 1;
	                                                    delai = 12;
                                        },
                                    }
                }
    },


	execute = function(domoticz, triggeredItem)

        -- Latitude et Longitude du domicile:
        latitudeDomicile=domoticz.settings.location.latitude
        longitudeDomicile=domoticz.settings.location.longitude


        --Déclenchement toutes les minutes aucun impact sur la durée batterie de l'iPhone ?????
        if (triggeredItem.isTimer) then

            for user,compte1 in pairs(users) do    

                compte = domoticz.data.users[user]
        
                if compte1.name ~= '' then
 
                    createObject(domoticz, compte1.name)
                    
                    --Incrément du compteur de passage toutes les minutes
                    compte.passage = compte.passage + 1
                    
                    --RAZ tous les 100 jours, c'est arbitraire !
                    if compte.passage > 144000 then 
                        compte.passage = 0 
                    end
                    
                    --Teste du compteur fonction du dépacement et modulo des timers définis
                    if ( compte.deplacement == true and compte.passage % TimerDeplacement == 0 ) or ( compte.deplacement == false and compte.passage % TimerPositionFixe == 0) then
                    
                        if debug then
                            print('Lancement demande de localisation '..compte1.name..' dans '..compte.delai..' seconde(s)')
                        end
                
                        domoticz.openURL({
                                            url =  'https://p43-fmipmobile.icloud.com/fmipservice/device/'..compte1.username..'/initClient',
                                            headers =  {
                                                            ["Authorization"] = "Basic "..encodeb64(compte1.username..':'..compte1.password), --Type authentification basic fonctionne avec authentification deux facteurs
                                                            ["Content-Type"] = "application/json",
                                                            ["charset"] = "utf-8",                                        
                                                            ["X-Apple-Find-Api-Ver"] = "2.0",
                                                            ["X-Apple-Authscheme"] = "UserIdGuest",
                                                            ["X-Apple-Realm-Support"] = "1.0",
                                                            ["User-agent"] = "Find iPhone/1.3 MeKit (iPad: iPhone OS/4.2.1)",
                                                            ["X-Client-Name"] = "iPad",
                                                            ["Accept-Language"] = "en-us",
                                                            ["Connection"] = "keep-alive",
                                                            ["Origin"] = "https://www.icloud.com"  
                                                        },
                                            method = 'POST',
                                            callback = 'iCloud'..user
                                        }).afterSec(compte.delai)     --compte.delai : Astuce pour décaler les demandes sinon waze n'aime pas !
                    end
                end
            end
            
        elseif triggeredItem.isHTTPResponse and triggeredItem.ok then
                    
    	    if (triggeredItem.isJSON) then 
    	    
    	        --Test type de callback
                if string.find(triggeredItem.callback,'iCloud') then
                    
                    --Récupère le user qui génère le callback                
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                    
                    --Fonction de recherche données uniquement deviceClass:iPhone voir filtre dans la fonction elle même en début de code
                    device = iCloud(triggeredItem)
                        
                    if device ~= nil then
                            
                        -- Ancienne position:
                        latitudePrecente = compte.latitudeiPhone
                        longitudePrecedente = compte.longitudeiPhone 
                            
                        -- Ancienne distance [position-domicile]:
                        DistanceDomicilePrecedente = distancekm(latitudePrecente, longitudePrecedente, latitudeDomicile, longitudeDomicile) 

                        -- Distance [nouvelle position-ancienne position]:       
                        EcartDistance = distancekm(device.latitudeiPhone, device.longitudeiPhone,latitudePrecente, longitudePrecedente)
                                    
                        -- Distance [nouvelle position-domicile]:       
                        compte.DistanceDomicile = distancekm(device.latitudeiPhone, device.longitudeiPhone, latitudeDomicile, longitudeDomicile)

                        --Presence: si la distance avec le domicile est inferieure à la précision souhaitée alors le smartphone est present au domicile
                        if compte.DistanceDomicile < Precision then --Presence
                            if domoticz.devices('Presence ' .. compte1.name).state == 'Off' then --Arrivée
                                domoticz.devices('Presence ' .. compte1.name).switchOn().silent()
                            end
                            compte.DistanceDomicile = 0
                        else
                            if domoticz.devices('Presence ' .. compte1.name).state == 'On' then
                                domoticz.devices('Presence ' .. compte1.name).switchOff().silent() 
                            end
                        end
                    
                        if debug then
                            print('Callback iCloud : '..compte1.name..': '..compte.DistanceDomicile..' km du domicile, '..device.batlvl..'% de batterie restante. Statut: "'..device.batstat..'". Precision: '..device.horizontalAccuracy)
                        end
                    
                        --Deplacement: si la distance avec l'ancienne position est superieure à la précision souhaitée alors le smartphone n'est plus au meme endroit et se deplace
                        if EcartDistance > Precision then
                            compte.deplacement = true
                            if DistanceDomicilePrecedente > compte.DistanceDomicile then
                                compte.position='En rapprochement du domicile'
                            else
                                compte.position='En éloignement du domicile'
                            end
                            
                            if debug then    
                                print('iPhone de '..compte1.name.. ': '..compte.position)
                            end
                        
                            if debug then
                                print('Lancement demande de trajet '..compte1.name)
                            end
                            
                            domoticz.openURL({
                                                url = 'https://www.waze.com/row-RoutingManager/routingRequest?from=x:'..longitudeDomicile..'+y:'..latitudeDomicile..'&to=x:'..device.longitudeiPhone..'+y:'..device.latitudeiPhone..'&at=0&returnJSON=true&returnGeometries=false&returnInstructions=false&timeout=30000&nPaths=1&clientVersion=1.0.0&options=AVOID_TRAILS:t,ALLOW_UTURNS:t',
                                                headers={["Content-Type"] = "application/json",["referer"]="https://www.waze.com"},
                                                method = 'POST',
                                                callback = 'waze'..user
                                            })                                   
                        else
                            --Lancement demande d'adresse au cas
                            compte.position = ''
                            if compte.deplacement == true then
                                if debug then
                                    print("Lancement demande de l'adresse de "..compte1.name) 
                                end

                                domoticz.openURL({
                                                    url =  'https://api-adresse.data.gouv.fr/reverse/?lon='.. device.longitudeiPhone .. '&lat=' .. device.latitudeiPhone,
                                                    method = 'GET',
                                                    callback = 'Adresse'..user
                                                }) 
                            end
                        end

                        domoticz.devices('Batterie '..compte1.name).updateText('Niveau : '..device.batlvl..'%.\13\10 Statut : '..device.batstat)
                        
                        --Mémorisation nouvelle coordonnée iPhone
                        --Mise a jour des informations
                        compte.latitudeiPhone = device.latitudeiPhone
                        compte.longitudeiPhone = device.longitudeiPhone
                        
                    else 
                        print('Retour iCloud problème : '..compte1.name) 
                    end	    		    
                end
                
                --Test type de callback    
                if string.find(triggeredItem.callback,'Adresse') then
                    
                    --Récupère le user qui génère le callback        
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                        
                    adresse = triggeredItem.json.features[1].properties.label
                    if adresse ~=nil then
                        
                        if compte.position == '' then
                            compte.position = adresse..' ('..compte.DistanceDomicile..' km)'
                            compte.deplacement = false
                        else
                            compte.position = compte.position..'.\13\10'..adresse..' ('..compte.DistanceDomicile..' km)'
                        end
                
                         domoticz.devices('Adresse '..compte1.name).updateText(compte.position)
                         
                        if debug then
                            print('Callback Adresse : '..compte1.name..': '..compte.position)
                        end
                        
                    else
                        print('Retour Adresse problème : '..compte1.name)
                        compte.position=domoticz.devices('Adresse '..compte1.name).state
                    end
                end
    	    else 
    	        --C'est bien un format JSON mais domoticz ne le detecte pas !
    	        --Test type de callback
    	        if string.find(triggeredItem.callback,'waze') then
    	            
    	            --Récupère le user qui génère le callback    
                    user = findUser(domoticz,triggeredItem)
                    compte = domoticz.data.users[user]
                    compte1 = users[user]
                        
                    trajet = waze(domoticz,triggeredItem)
                    if trajet ~= nil then
                        --Fonction waze retourne pour le trajet entre deux coordonées une table avec le temps en seconde et la distance en metre
                        heures=math.floor(trajet.temps / 3600)
                        minutes=math.floor((trajet.temps % 3600) / 60)
                        secondes=math.floor((trajet.temps % 3600) % 60)
                        ETA=os.date("%Hh%M",os.time()+trajet.temps)
                        duree=heures..'h'..minutes..'min'
                        distance = ((math.floor(trajet.distance/100))/10)
                        trafic='Heure d\'arrivée: '..ETA..' - '..tostring(((math.floor(trajet.distance/100))/10))..'Km, '..duree
                        
                        if distance < Precision then
                            compte.position = ''
                        end
                        if compte.deplacement == true then
                            if debug then
                                print("Lancement demande de l'adresse de "..compte1.name) 
                            end
                            domoticz.openURL({
                                                url =  'https://api-adresse.data.gouv.fr/reverse/?lon='.. compte.longitudeiPhone .. '&lat=' .. compte.latitudeiPhone,
                                                method = 'GET',
                                                callback = 'Adresse'..user
                                            }) 
                        end
                        
                        if debug then
                            print('Callback waze : ' .. compte1.name .. ': '..trafic)
                        end
                        domoticz.devices('Trajet '..compte1.name).updateText(trafic)
                    else
                        print('Retour Waze problème : '..compte1.name)
                    end
                end
    	    end
        end
	end
	
}

Fred
Répondre