Aller au contenu
Inkew

Mettre à jour la valeur d'un QA depuis un autre QA

Recommended Posts

Bonjour, rapide question : peut-on mettre à jour la valeur d'un QA2 depuis un code se trouvant dans un QA1, et si oui quel est le code?

Ex. J'ai le QA "Indicateur Solaire" qui met à jour sa valeur Azimut, la hauteur du soleil est calculée et mise à jour dans un Label de ce QA. Je souhaiterai que cette hauteur soit la valeur d'un autre QA :

Citation

---------------------------------
-- Script de collecte de quelques indicateurs solaire
-- Auteur : Sébastien Joly
-- Date : 29 août 2015
-- Eléments de calculs :
-- http://www.plevenon-meteo.info/technique/theorie/enso/ensoleillement.html
-- http://herve.silve.pagesperso-orange.fr/solaire.htm
-- adpaté par Jean-Jacques NEFF pour la HC3 le 24/03/2020
---------------------------------

function QuickApp:onInit()
    __TAG = "QA_"..plugin.mainDeviceId.."_Indicateur Solaire"
    self:debug("onInit")
    self.offset = -0
    self:Main()
end
  
---------------------------------
-- Fonction déterminant si année bissextile
---------------------------------
function QuickApp:AnneeBissextile(annee)
    return annee%4==0 and (annee%100~=0 or annee%400==0)
end

---------------------------------
-- Fonction Arrondir
---------------------------------
function QuickApp:arrondir(num, dec)
    if num == 0 then
        return 0
    else
        local mult = 10^(dec or 0)
        return math.floor(num * mult + 0.5) / mult
    end
end

local location = api.get("/settings/location")
local Ville = location.city
local Latitude = location.latitude
local Longitude = location.longitude
local Altitude = 53 --Vendegies

---------------------------------
-- MAIN
---------------------------------
function QuickApp:Main()

    -- Début debug
    self:trace("=====================================")
    self:trace(os.date("%Y-%m-%d %H:%M:%S", os.time()))
    self:trace(Ville .. ", " .. Latitude .. ", " .. Longitude)
    self:trace("Altitude = " .. tostring(Altitude) .. " m")
      
    local NiemeJourDeLAnnee = os.date("%j")

    ---------------------------------
    -- Vitesse angulaire = Combien de degrés par jour
    ---------------------------------
    VitesseAngulaire = 360/365.25 ----JourDansLAnnee -- ou approximativement 365.25
    self:trace("Vitesse angulaire = " .. VitesseAngulaire .. " par jour")
    ---------------------------------
    -- Formule Declinaison = ArcSin(0,3978 x Sin(Va x (j - (81 - 2 x Sin(Va� x (j - 2))))))
    ---------------------------------
    local Declinaison = math.deg(math.asin(0.3978 * math.sin(math.rad(VitesseAngulaire) *(NiemeJourDeLAnnee - (81 - 2 * math.sin((math.rad(VitesseAngulaire) * (NiemeJourDeLAnnee - 2))))))))
    self:trace("La déclinaison = " .. Declinaison .. "°")
    ---------------------------------
    -- Temps universel décimal (UTC)
    ---------------------------------
    TempsDecimal = (os.date("!%H") + os.date("!%M") / 60)
    self:trace("Temps universel decimal (UTC)".. TempsDecimal .." H.dd")
    ---------------------------------
    -- Temps solaire
    ---------------------------------
    HeureSolaire = TempsDecimal + (4 * Longitude / 60 )
    self:trace("Temps solaire ".. HeureSolaire .." H.dd")
    ---------------------------------
    -- Angle horaire du soleil
    ---------------------------------
    AngleHoraire = 15 * ( 12 - HeureSolaire )
    self:trace("Angle Horaire = ".. AngleHoraire .. "°")
    ---------------------------------
    -- La hauteur du soleil (Elévation ou altitude)
    ---------------------------------
    HauteurSoleil = math.deg(math.asin(math.sin(math.rad(Latitude))* math.sin(math.rad(Declinaison)) + math.cos(math.rad(Latitude)) * math.cos(math.rad(Declinaison)) * math.cos(math.rad(AngleHoraire))))
    self:trace("Hauteur du soleil = " .. HauteurSoleil .. "°")
    
    self:updateView("LBL_Hauteur", "text", "Hauteur = "..tostring(self:arrondir(HauteurSoleil,0)) .. "°")
    
    ----
    -- Renseigne la global variable du nom
    ---
    fibaro.setGlobalVariable("toto", tostring(self:arrondir(HauteurSoleil,0)))

    local Azimut = math.acos((math.sin(math.rad(Declinaison)) - math.sin(math.rad(Latitude)) * math.sin(math.rad(HauteurSoleil))) / (math.cos(math.rad(Latitude)) * math.cos(math.rad(HauteurSoleil) ))) * 180 / math.pi
    local SinAzimut = (math.cos(math.rad(Declinaison)) * math.sin(math.rad(AngleHoraire))) / math.cos(math.rad(HauteurSoleil))
    if (SinAzimut<0) then Azimut=360-Azimut end
    self:trace("Azimut du soleil = " .. Azimut .. "°") --affichage sans offset
    
    self:updateView("LBL_Azimut", "text", "Azimut = "..tostring(self:arrondir(Azimut,0)+self.offset).."°")
    self:updateProperty("value", self:arrondir(Azimut,0)+self.offset)
    self:updateProperty("unit", " °")
    self:updateView("LBL_Update", "text", os.date("%d/%m/%Y %H:%M:%S",os.time()))
    self:trace("=====================================")

    --bouclage toutes les minutes
    fibaro.setTimeout(60*1000, function() self:Main() end)
end

 

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Il faut appeler la méthode updateProperty (la même que tu utilises pour mettre à jour le QA lui-même), sauf qu'au lieu d'utiliser self, il faut utiliser fibaro.call() avec l'IP du QA cible.

 

Par exemple pour mettre à jour la propriété "value" :

fibaro.call(ID, "updateProperty", "value", value)

 

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites
Le 31/08/2021 à 13:40, Lazer a dit :

Il faut appeler la méthode updateProperty (la même que tu utilises pour mettre à jour le QA lui-même), sauf qu'au lieu d'utiliser self, il faut utiliser fibaro.call() avec l'IP du QA cible.

 

Par exemple pour mettre à jour la propriété "value" :


fibaro.call(ID, "updateProperty", "value", value)

 

 

Du coup, si on veut mettre à jour la variable locale "toto" avec la valeur "1" du QA2 (destinataire ID2), via le QA1 (émetteur ID1) , comment écrire dans le QA1 ? :unsure:

Ca ça marche ???

fibaro.call(2, "updateProperty", "toto", 1)

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Non, avec updateProperty tu ne peux modifier que les propriétés, c'est à dire les valeurs qui sont dans la sous-table properties du JSON du module (visible via /api/devices/ID)

 

Si la variable est "locale", c'est qu'elle est dans la mémoire (pile) du code LUA en cours d'exécution, donc elle n'est absolument pas accessible depuis un autre QA. C'est l'isolation élémentaire des espaces mémoires des programmes informatiques. Encore heureux... encore que des bugs/failles existent, ce qui mène aux plantages ou piratages qu'on voit parfois passer...

 

En revanche, tu peux modifier les variables de QA (celles qui sont dans l'onglet Variables de l'interface Wzb), puisqu'elles sont stockées dans les properties du QA.

Mais attention, le format est un peu spécifique, c'est une sous-table qui liste toutes les variables et leurs valeurs, cela n'est donc pas modifiable avec updateProperty, il faut passer par l'API directement.... ou plus simplement appeler la méthode setVariable du QA cible : fibaro.call(ID, "setVariable", "ma_variable", "ma_valeur")

 

je l'ai déjà dit plusieurs fois sur le forum, mais toutes les méthodes (= fonctions) d'un QuickApp sont automatiquement exposées, elles peuvent donc être exécutées depuis un autre QA, ou bien depuis n'importe où dans le monde en passant par l'API HTTP de la box.

Cela inclue donc des fonctions aussi élémentaires que self:debug() ===> fibaro.call(ID, "debug", "Injection d'un message dans le log du QA cible")

 

Cela étant dit, tu peux créer une fonction dans un QA, qui permet de modifier une variable locale.

Exemple tout simple :

function QuickApp:onInit()
	self.mavariable = "Hello"
end

function QuickApp:ModifyVariable(value)
	self.mavariable = value
end

Il suffit d'appeler depuis un autre QA :

fibaro.call(ID, "ModifyVariable", "Goodbye")

 

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci d’avoir pris le temps de m’expliquer et pardon si je t’ai fait répéter :P

Même si j’essaie de suivre un max de sujets, on en oublie parfois :D

Ta réponse m’éclaire tel un laser dans l’obscurité :2:

  • Haha 1

Partager ce message


Lien à poster
Partager sur d’autres sites

@Lazer dans le doute je viens d'aller relire d'autres sujets avant de poser la question pour essayer de me répondre tout seul, mais je ne suis pas sûr d'avoir trouvé la réponse.

 

Par curiosité j'ai aussi testé cette écriture et ça fonctionne également :

function QuickApp:onInit()
	mavariable = "Hello"
end

function QuickApp:ModifyVariable(value)
	mavariable = value
end

En gros, sans le self. devant la variable.

 

 

Quelle est la différence avec l'écriture que tu as proposé qui fonctionne évidemment ? :unsure:

 

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Dans mon exemple, mavariable est affectée à l'objet self, c'est à dire l'objet QuickApp, cette variable n'est donc accessible que depuis l'une des fonctions membres de QuickApp (avant de me faire reprendre par les experts : en pratique on peut y accéder d'ailleurs, mais chut, on va pas compliquer inutilement pour l'instant)

 

Dans ton dernier exemple, mavariable est une variable globale dans le code LUA de ton QA.

C'est qui n'est pas idéal, car une bonne pratique c'est toujours de limiter la portée d'une variable au strict nécessaire.

C'est un sujet qui a été abordé plusieurs fois sur le forum, mais l'information étant diluée ça et là au fil des discussions, c'est pas évident à retrouver.

 

On pourrait transformer ta variable globale en variable locale en l'écrivant ainsi :

local mavariable

function QuickApp:onInit()
	mavariable = "Hello"
end

function QuickApp:ModifyVariable(value)
	mavariable = value
end

 

En revanche attention ce code est faux, car la variable serait alors locale uniquement à la fonction onInit() et ne serait donc pas accessible depuis la fonction ModifyVariable (qui créerait alors une autre variable, globale cette fois-ci, portant le même nom)

function QuickApp:onInit()
	local mavariable = "Hello"
end

function QuickApp:ModifyVariable(value)
	mavariable = value
end

 

Quelques bonnes lectures :

 

 

  • Like 1

Partager ce message


Lien à poster
Partager sur d’autres sites

Merci pour cette explication très claire, comme souvent :P

 

Comme discuté ensemble dans un autre sujet il y a quelques temps, j'étais justement en train de virer presque toutes mes variables globales "persistantes" pour utiliser un maximum de variables locales dans mes QA ;)

Purée :15: j'étais tout content d'y être arrivé cette semaine, mais ton explication éclairée vient à l'instant de me faire comprendre que je me suis planté, comme le décrit mon exemple précédent.

Car je n'ai pas précisé soit self. ou soit local suivant le besoin que tu décris :D

Donc sans le vouloir j'ai créé pléthore de nouvelles variables globales...

 

Bon ben je retourne lire et modifier ma manière de déclarer mes variables dans mes QA :wacko::2:

Partager ce message


Lien à poster
Partager sur d’autres sites

Attention de ne pas confondre :

  • les variables LUA (qui existent dans le code LUA, qu'elles soient locales, globales, ou attribuées à un objet via self) => elles résident uniquement en RAM, elle sont créées à chaque démarrage du QuickApp, et perdues lors de son arrêt
  • les variables persistantes de la box (globales, de QuickApp, ou de Scène) => elles sont stockées dans la DB, donc conservées à chaque redémarrage du QA ou reboot de la box.

 

Modifié par Lazer

Partager ce message


Lien à poster
Partager sur d’autres sites

Bon pardon pour le hors-sujet à force... Si tu souhaites supprimer/déplacer, ce serait normal, mais du travail pour toi.

Mais du coup bien que tu l'aies déjà répété, j'ai mélangé les notions de variables "persistantes" écrites dans l'onglet Général/Variables ou dans l'onglet Variables d'un QA, avec la notion de leur portée dans le code LUA... :(

 

#1 Donc finalement j'ai bien limité au maximum l'écriture en dur des variables en les supprimant de ces onglets. Bon point pour l'usure du contrôleur et la vitesse de calcul, car c'était mon premier objectif :D

 

#2 Par contre j'ai créé beaucoup de variables à portée globales dans mes QA (sans préciser local ou self), ce qui n'est pas catastrophique dans mon usage mais pas le mieux d'un point de vue calcul et risque d'erreur en réutilisation. Je peux donc encore améliorer mes codes en réduisant la portée des variables si nécessaire.

Quand Lazer dit : "Reprenons :"

Le 25/07/2021 à 13:06, Lazer a dit :

-- Cette fonction est membre de la classe QuickApp. Elle est donc automatiquement publiée et accessible depuis l extérieur du QA
function QuickApp:test()
	self:debug("hello")
end

-- Cette fonction est "globale" (par défaut), c'est à dire accessible dans tous les fichiers du QA :
function test(self)
	self:debug("hello")
end

-- Cette fonction est locale (car spécifié) donc accessible uniquement dans le fichier en cours (ou bloc de code en cours si la fonction a été définie à l'intérieur d'une autre fonction/boucle/etc) :
local function test(self)
	self:debug("hello")
end

 

Partager ce message


Lien à poster
Partager sur d’autres sites

Ah voilà tu as retrouvé où on en a parlé il y a quelques temps :)

 

Outre les problématiques de portée et de risque d'erreur de réutilisation, précisons, au sujet des performances, qu'il est plus rapide d'utiliser des variables locales que des variables globales (en LUA, ce n'est pas le cas avec d'autres langages)

En effet, en LUA, accéder à une variable globale requiert de parcourir la table super-globale _G (une table qui contient toutes les variables globales, les fonctions, etc), ce qui prend des cycles CPU à chaque accès.

Mais on parle là de micro-optimisations.

Il n'y aura un gain sensible à ce niveau que pour un algorithme très lourd, avec une boucle qui effectue des millions d'accès à la même variable.

 

Cela n'a rien à voir avec la différence de performance lors de l'accès à une variable persistante en DB, pour laquelle la différence de performance est considérable.

Partager ce message


Lien à poster
Partager sur d’autres sites

Yes :D

C'est pour ça que de mon côté aidé par le forum comme la première étape est majoritairement atteinte : DB quasi vide, scènes remplacées par QA, et ça tourne de manière stable, je laisse désormais fonctionner quelques jours/semaines pour essayer de piéger d'éventuels cas de vie oubliés dans mes validations et apporter quelques corrections ou nouvelles idées de fonctionnement (sachant qu'il y a quelques temps, je venais de 6,5 ans de HCL avec pleins de scènes blocs, des VG et des VD).

 

Pour l'optimisation de la portée de variables et des gains de perf (encore négligeables dans mon usage), je le ferai par principe, mais dans un second temps dans le cadre de l'amélioration continue durant les longues journées pluvieuses d’automne :2:

 

Partager ce message


Lien à poster
Partager sur d’autres sites

×