Mais où est le soleil pour votre HomeCenter 2 ? La gestion thermique du bâtiment m’intéresse sous plusieurs aspects. L’économie d’énergie étant le principal objectif, mais aussi le confort thermique. J’habite une maison BBC (2O12) depuis plus de deux ans maintenant, et je constate que la conception pour les économies d’énergies l’hiver est plutôt adaptée, mais que la conception n’est pas pertinente en été pour se protéger de la chaleur.
1 – A l’origine
Il faut savoir que le poste de consommation énergétique chauffage est moins important que celui de la climatisation dans les régions sud. J’ai donc voulu trouver des alternatives physiques et technologiques aux périodes de chaleurs, par la réalisation d’un script permettant de calculer l’incidence solaire sur mes ouvrants.
Initialement développé en python et s’exécutant sur une Raspberry Pi, un script me permettait depuis quelques temps déjà de piloter mes volets roulants l’été en fonction de l’incidence solaire. Il y a déjà presque un an et demi que j’utilise cette technique pour limiter l’élévation thermique de ma maison l’été. Je n’ai pas collecté de données pour certifier le gain précisément, mais j’ai pu constater le retard sur l’élévation thermique journalier l’été. C’est environ 2° de moins en fin d’après-midi (déclin solaire) sur deux baies du living-room (Exposition Est et plein sud pour environ 80m3). Il faut savoir que globalement, l’été la température extérieure peut monter jusqu’à 16:00 heures environ. Les autres volets roulants sont aussi pilotés, et surtout celui de la cuisine afin de limiter l’incidence directe soleil sur mon réfrigérateur, et donc réduire de facto sa consommation. Il serait intéressant de faire la différence des consommations de climatisation et du réfrigérateur depuis ces changements.
Ceux qui habitent le nord trouveront des usages certains pour élever la température de leur logement l’hiver, et ceux du sud y trouveront plutôt la limitation de l’élévation thermique l’été.
2 – Pourquoi faire un périphérique virtuel sur le HC2 ?
Depuis quelques semaines, voir quelques mois, je constate que l’intérêt pour ce type de dispositif augmente sur les forums communautaires, et principalement sur le forum domotique-fibaro.fr, avec un post de co-développement d’un périphérique virtuel. Constatant cela, je me suis dit qu’il serait dommage de ne pas partager mon travail en re-développant mon script Python en Lua. Mais pourquoi faire ce portage ?
- Pour le challenge du portage logiciel python vers lua ;
- Pour embarquer toute la pertinence du dispositif sur le HC2 ;
- Pour ne plus maintenir un plateforme tierce ;
- Pour éviter les indisponibilités de communication et rendre autonome le HC2 ;
- Pour d’autres perspectives fonctionnelles, et particulièrement un lot de cas d’usages ;
- Pour partager un dispositif répondant au besoin de la communauté Fibaro HC2 ;
- Mais aussi pour le fun.
3 – Portage Lua du script Python
3.1 – Données utiles aux calculs
J’ai profité de ce portage pour remettre en question l’ensemble du protocole de calcul, et pour intégrer les données fondamentales dans la pondération réaliste du résultat en intégrant dynamiquement les indicateurs environnementaux aux données géographiques :
- Coordonnées géographiques WSG84 locales en degrés décimaux (source : élément de configuration HC2) ;
- Altitude du point géographique (source : API Google Elevation) ;
- Pression atmosphérique du lieu (source : API OpenWeatherMap) ;
- Température locale (source : API OpenWeatherMap) ;
- Humidité locale (source : API OpenWeatherMap) ;
- La nébulosité en Octa (source : Messages Synotic) ;
Il va de soi que les données environnementales peuvent s’appuyer sur des capteurs locaux plutôt que sur des API distantes. D’ailleurs, je préfère nettement cette approche mais tous le monde n’est pas forcément doté de ces capteurs. Je partagerai donc un dispositif autonome sans capteur pour satisfaire au plus grand nombre. Ceux intéressés par les mesures locales sauront je pense adapter le script.
3.2 – La nébulosité
Définition de la nébulosité par Infoclimat.fr :
Part de ciel couvert. On a coutume de diviser le ciel en 8 parties égales (Octa ou huitièmes). Une nébulosité égale à 8/8 représente un ciel couvert tandis qu’une nébulosité de 0 ou 1/8 correspond à un ciel parfaitement dégagé (ciel clair).
Ou encore pour le site Météociel :
C’est la donnée la plus importante pour pondérer le résultat théorique des calculs. Sans une vraie valeur de nébulosité en octa, il est impossible de connaitre l’ensoleillement « vrai » et potentiellement l’impact thermique du rayonnement. Attention tout de même, cela reste une approche par un modèle astronomique, mais le résultat est plutôt convainquant.
La nébulosité de tous les sites météo est dans la plupart des cas une données sans réalité physique. En effet, il existe une confusion entre couverture nuageuse qui représente un pourcentage de couverture de surface, et la nébulosité qui représente l’opacité des strates nuageuses. Avoir des nuages sur 50km² au dessus de moi ne représente pas la perméabilité à l’ensoleillent de cette couche nuageuse. Même les sites institutionnels nous offrent des API biaisées par cette confusion. Il a donc fallut trouver une source fiable. Je l’ai bien entendu trouvé, mais pas sans mal.
Le tout premier VD était dépendant d’une valeur absolue du couvert nuageux en pourcentage depuis OpenWeatherMap, que je transformais en octa (N/8) par une règle de trois, mais cette technique était totalement hasardeuse et sans réalité physique. J’ai donc dû m’atteler à la recherche d’une source fiable.
Force est de constater qu’aucun site doté d’une API n’offre réellement cette valeur. Après pas mal de recherche, j’ai constaté que les message aéronautique météo étaient quasi les seuls à fournir cette information, et de manière plutôt régulière qui plus est. Les message en question sont plus précisément les messages « Synoptic » plus simplement appelés SYNOP. Ces message sont semblables à des télégrammes codés. La structure des trames SYNOP permet d’embarquer beaucoup d’informations pour les pilotes aériens. Voici ci-dessous la méthode de décodage d’un message :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | Decoding Synops Explains how to decode a synoptic observation, used by weather stations around the world. A synop is a report of a surface observation from a land based station. A typical synop will have the following format : [AAAAA BCDEE FGGHH 1IJJJ 2KLLL 3MMMM 4NNNN 5OPPP 6QQQR 7SSSS 8TUVW ###...] and can be decoded as follows : AAAAA- Station's five digit identification number B - Indicator for inclusion or omission of precipitation data: 1 In section 1 (regional codes indicated by ###=111) 2 In section 3 (regional codes indicated by ###=333) 3 Precipitation amount=0 4 Precipitation amount not available C - Indicator for type of station operation: 1,2,3 Manned 4,5,6 Automatic D - Height above surface of the base of the lowest cloud seen: 0 0-50 meters 1 50-100 meters 2 100-200 meters 3 200-300 meters 4 300-600 meters 5 600-1000 meters 6 1000-1500 meters 7 1500-2000 meters 8 2000-2500 meters 9 2500 or more, or no clouds at all / Height at base of cloud not known or the base of the clouds is at a lower level and the tops are at a higher level than that of the station. EE - Horizontal visibility at the surface: For EE=00 to EE=50: visibility in tenths of kilometers (ex: 31=3.1km) For EE=56 to EE=80: visibility in kilometers + 50 (ex: 67=17km) 81 35km 86 60km 82 40km 87 65km 83 45km 88 70km 84 50km 89 >70km F - Total cloud cover in oktas (eights): 0 No cloud cover 1-8 Cloud cover in eights 9 Sky obscured by fog and/or other meteorological phenomena / Cloud cover is indiscernable for reasons other than fog or other meteorological phenomena, or the observation was not made. GG - True direction, in tens of degrees, from which the wind is blowing: Ex: 27=270 degrees (west wind) HH - Wind speed in meters per second: Ex: 13=13 meters per second (~ 26 mph) 1,2,3,4,5- Group number I - Sign of the following data: 0 Postive or zero 1 Negative JJJ - Temperature in tenths of degrees Celsius. Used in combination with "I": Ex: 0123= 12.3 degrees above zero 1034= 3.4 degress below zero K - Same as "I" LLL- Dew point temperature in tenths of degrees Celsius. Used the same as "JJJ". MMMM- Station pressure, not reduced to sea level: NNNN- Station pressure reduced to sea level: NNNN greater than 5000 Station pressure in tenths of millibars NNNN less than 5000 Add a preceding 1 to get the corrected surface pressure in tenths of millibars. Ex: 9872 = 987.2 millibars 0305 = 1030.5 millibars O - Pressure tendency during the three previous hours preceding the time of observation : 0 Increasing, then decreasing; atmospheric pressure the same or higher than 3 hours ago 1* Increasing, then steady; or increasing, then increasing more slowly 2* Increasing (steadily or unsteadily) 3* Decreasing or steady, then increasing; or increasing, then increasing more rapidly 4 Steady; atmospheric pressure the same as three hours ago 5 Decreasing, then increasing; atmospheric pressure the same or lower than three hours ago 6** Decreasing, then steady; or decreasing, then decreasing more slowly 7** Decreasing (steadily or unsteadily) 8** Steady or increasing, then decreasing; or decreasing, then decreasing more rapidly * indicates atmospheric pressure higher now than three hours ago ** indicates atmospheric pressure lower now than three hours ago PPP - Pressure rise or fall in tenths of millibars QQQ - Amount of precipitation which has fallen during the period preceding the time of observation, as indicated by "R": 000 Not used 001 1 mm 002 2mm (etc. up to 988) 989 989 mm or more 990 Trace 991 .1 mm 992 .2 mm (etc. up to 999 = .9mm) R - Time period for precipitation observation (not defined in WMO manual) SSSS - Indicators of past or present weather phenomena (refer to WMO manual for decoding procedure) T - Amount of the "U" cloud present, or if no "U" cloud is present, the amount of "V" cloud present: U - Clouds of the genera Stratocumulus, Stratus, Cumulus, or Cumulonimbus. V - Clouds of the genera Cirrus, Cirrocumulus, or Cirrostratus. W - Clouds of the genera Cirrus, Cirrocumulus, or Cirrostratus. For more information on the codes for "U", "V", and "W" refer to the WMO manual. |
Comme vous pouvez le voir les perspectives sont assez pointues, et permettraient d’aller plus loin dans la démarche de récupération d’informations. Cependant l’humidité et la température sont tout de même très localisées. De plus j’aimerai souligner que la nébulosité peut parfois exprimer des situations particulières comme par exemple le brouillard avec un indice de 9/8, ou un phénomène occultant spécifique (éclipse) par le symbole slash [/]. Je ne gère pas pour l’instant ces particularités, mais je pense devoir rapidement intégrer ces phénomènes. En l’absence de traitement spécifique, j’applique la valeur la plus pénalisante de nébulosité (8/8).
Savoir décoder les trames est une chose, mais où récupérer l’information ?
J’ai cherché quelques heures, pour trouver une API plutôt intéressante nommée Synoptic API, et destinée aux professionnels. Bien qu’ il soit annoncé un accès libre (free), je n’ai pu obtenir d’accès. Le seul service en ligne que j’ai pu trouvé est finalement un service en ligne espagnol sur le site Ogimet.
3.3 – Les éléments de calculs
La technique de calcul pour obtenir les données du périphérique virtuel est trouvable un peu partout sur internet. Je n’ai rien inventé ici, mais juste adapté mon code Python en code Lua en intégrant une collecte dynamique d’informations récentes. Il faut noter que le code n’a pas encore était expurger de plusieurs fonctions potentiellement utiles dans de futur version. De plus, j’ai constaté un petit bug au niveau de l’API Google Elevation. En effet, le retour json fait parfois des siennes. Le code sera nettoyer (car un peu crado) lors d’une futur release majeure.
Vous trouverez dans le code du bouton le script Lua suivant :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 | --------------------------------- -- 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 --------------------------------- -- Fonction déterminant si année bissextile function AnneeBissextile(annee) return annee%4==0 and (annee%100~=0 or annee%400==0) end --------------------------------- -- Fonction de chargement de label function setDevicePropertyValue(id, label, value) fibaro:call(id, "setProperty", "ui."..label..".value", value) end --------------------------------- -- Fonction spliter function split(s, delimiter) result = {}; for match in (s..delimiter):gmatch("(.-)"..delimiter) do table.insert(result, match); end return result; end --------------------------------- -- Fonction de calcul de la distance entre deux points géographique en D°.DD function geo_distance (lat1, lon1, lat2, lon2) if lat1 == nil or lon1 == nil or lat2 == nil or lon2 == nil then return nil end local dlat = math.rad(lat2-lat1) local dlon = math.rad(lon2-lon1) local sin_dlat = math.sin(dlat/2) local sin_dlon = math.sin(dlon/2) local a = sin_dlat * sin_dlat + math.cos(math.rad(lat1)) * math.cos(math.rad(lat2)) * sin_dlon * sin_dlon local c = 2 * math.atan2(math.sqrt(a), math.sqrt(1-a)) -- 6378 km est le rayon terrestre au niveau de l'équateur local d = 6378 * c return d end --------------------------------- -- Fonction Arrondir function 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 --------------------------------- -- Procedure principale --------------------------------- -- Initilise la variable local de l'ID du VD local VDid = fibaro:getSelfId() --------------------------------- -- Requête API loopback pour récupérer Latitude & Longitude des paramètres HC loopback = Net.FHttp("127.0.0.1",11111) local response = loopback:GET("/api/settings/location") jsonTable = json.decode(response) local Ville = (jsonTable.city) local Latitude = (jsonTable.latitude) local Longitude = (jsonTable.longitude) --------------------------------- -- Elevation Google API (Free) GoogleElevation = Net.FHttp("maps.googleapis.com") local response = GoogleElevation:GET("/maps/api/elevation/json?locations=".. Latitude .. "," .. Longitude .. "&sensor=false") --local jsonTable = json.decode(response["results"][1]) --local Altitude = jsonTable.elevation jsonTable = json.decode(response) Altitude = jsonTable.results[1].elevation --------------------------------- -- Meteo API OpenWeatherMap OpenWeatherMap = Net.FHttp("api.openweathermap.org") local response = OpenWeatherMap:GET("/data/2.5/weather?lat=".. Latitude .. "&lon=" .. Longitude .. "&units=metric") local jsonTable = json.decode(response) local Temperature = jsonTable.main.temp local PressionRelative = jsonTable.main.pressure local Humidite = jsonTable.main.humidity local Nebulosite = jsonTable.clouds.all --------------------------------- DateHeure = os.date("%Y-%m-%d %H:%M:%S", os.time()) -- Début debug fibaro:debug("=====================================") fibaro:debug(os.date("%Y-%m-%d %H:%M:%S", os.time())) fibaro:debug(Ville .. ", " .. Latitude .. ", " .. Longitude) fibaro:debug("Altitude = " .. tostring(Altitude) .. " m") local An = os.date("%Y") local NiemeJourDeLAnnee = os.date("%j") fibaro:debug("NiemeJourDeLAnnee = " .. NiemeJourDeLAnnee) if AnneeBissextile(An) == true then fibaro:debug( An .. " est bissextile.") JourDansLAnnee = 366 else fibaro:debug( An .. " n'est pas bissextile.") JourDansLAnnee = 365 end --------------------------------- -- Vitesse angulaire = Combien de degrés par jour VitesseAngulaire = 360/365.25 ----JourDansLAnnee -- ou approximativement 365.25 fibaro:debug("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)))))))) fibaro:debug("La déclinaison = " .. Declinaison .. "°") --------------------------------- -- Temps universel décimal (UTC) TempsDecimal = (os.date("!%H") + os.date("!%M") / 60) fibaro:debug("Temps universel decimal (UTC)".. TempsDecimal .." H.dd") --------------------------------- -- Temps solaire HeureSolaire = TempsDecimal + (4 * Longitude / 60 ) fibaro:debug("Temps solaire ".. HeureSolaire .." H.dd") --------------------------------- -- Angle horaire du soleil AngleHoraire = 15 * ( 12 - HeureSolaire ) fibaro:debug("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)))) fibaro:debug("Hauteur du soleil = " .. HauteurSoleil .. "°") 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 fibaro:debug("Azimut du soleil = " .. Azimut .. "°") --------------------------------- -- La durée d'insolation journalière - non stockée en VG DureeInsolation = math.deg(2/15 * math.acos(- math.tan(math.rad(Latitude)) * math.tan(math.rad(Declinaison)))) DureeInsolation = arrondir(DureeInsolation,2) fibaro:debug("La durée d'insolation journalière = " .. DureeInsolation .." H.dd") --------------------------------- -- Constantes Solaire ConstanteRatiationSolaire = 1361 -- W/m² ConstanteRadiationLux = 200000 -- Lux --------------------------------- -- Rayonnement solaire (en W/m²) présent à l'entrée de l'atmosphère. RadiationAtm = ConstanteRatiationSolaire * (1 +0.034 * math.cos( math.rad( 360 * NiemeJourDeLAnnee / JourDansLAnnee ))) fibaro:debug("Radiation max en atmosphère = " .. arrondir(RadiationAtm,2) .. " W/m²") --------------------------------- -- Coefficient d'attenuation M PressionAbsolue = PressionRelative - arrondir((Altitude/ 8.3),1) -- hPa fibaro:debug("Pression relative locale = " .. PressionRelative .. " hPa") fibaro:debug("Pression absolue atmosphère = " .. PressionAbsolue .. " hPa") SinusHauteurSoleil = math.sin(math.rad(HauteurSoleil)) M0 = math.sqrt(1229 + math.pow(614 * SinusHauteurSoleil,2)) - 614 * SinusHauteurSoleil M = M0 * PressionRelative/PressionAbsolue fibaro:debug("Coefficient d'attenuation = " .. M ) --------------------------------- -- Récupérer message SYNOP avec un Get HTTP sur le site Ogimet heureUTCmoins1 = os.date("!%H")-1 if string.len(heureUTCmoins1) == 1 then heureUTCmoins1 = "0" .. heureUTCmoins1 end UTC = os.date("%Y%m%d").. heureUTCmoins1.."00" -- os.date("!%M") fibaro:debug("Horodatage UTC = " .. UTC) -- WMOID = "07643" local WMOID = fibaro:get(fibaro:getSelfId(), "IPAddress") fibaro:debug("Station SYNOP = " .. WMOID) ogimet = Net.FHttp("www.ogimet.com") local synop = ogimet:GET("/cgi-bin/getsynop?block=".. WMOID.."&begin=" .. UTC) --fibaro:debug(synop) ---temporaire rslt = split(synop,",") CodeStation = rslt[1] Coupure = " ".. CodeStation .. " " --fibaro:debug(rslt[1]) rslt = split(synop, " "..CodeStation.. " ") -- fibaro:debug(rslt[2]) Trame = string.gsub(rslt[2], "=", "") Trame = CodeStation .." ".. Trame --fibaro:debug(Trame) rslt = split(Trame, " ") --------------------------------- -- Récupérer le premier caractere du 3eme mot = Nebulosité en Octa Octa = string.sub(rslt[3], 1, 1) fibaro:debug( Octa .. " Octa") -- 0 Pas de couverture nuageuse -- 1-8 Huitième -- 9 Brouillard -- / Couverture indiscernable -- cas particulier si valeur indéterminé un slash est renvoyé. Afin d'être le plus pénalisant 8 sera retenu. if Octa == "/" then Octa = 8 elseif Octa == "9" then Octa = 8 end --------------------------------- -- Facteur d'atténuation des couches nuageuses Kc -- Kc=1-(0.75*((OCTA)**(3.4)) Kc=1-0.75*(math.pow(Octa/8,3.4)) fibaro:debug("Kc = " .. Kc) --------------------------------- -- Au lever/coucher du soleil, on atteind les limites de précisions de ces calculs. -- J'interrompts donc le calcul de radiation dès 1°. if HauteurSoleil > 1 then -- Radiation directe RadiationDirecte = RadiationAtm * math.pow(0.6,M) * SinusHauteurSoleil fibaro:debug("RadiationDirecte = ".. arrondir(RadiationDirecte,2) .." W/m²") -- Radiation Diffuse RadiationDiffuse = RadiationAtm * (0.271 - 0.294 * math.pow(0.6,M)) * SinusHauteurSoleil fibaro:debug("Radiation Diffuse = ".. arrondir(RadiationDiffuse,2) .." W/m²") -- Radiation totale RadiationTotale = RadiationDiffuse + RadiationDirecte fibaro:debug("Radiation totale = " .. arrondir(RadiationTotale,2) .." W/m²") -- Radiation en Lux : -- 1 Lux = 0,0079 W/m² Lux = RadiationTotale / 0.0079 --Lux = ConstanteRadiationLux / ConstanteRatiationSolaire * RadiationTotale fibaro:debug("Radiation totale en lux = ".. arrondir(Lux,2).." Lux") -- Le rayonnement solaire avec ciel nuageux RTOTC = RadiationTotale * Kc fibaro:debug("Le rayonnement solaire avec pondération = " .. arrondir(RTOTC,2)) -- Radiation en Lux pondéré -- LuxPondere = ConstanteRadiationLux / ConstanteRatiationSolaire * RTOTC LuxPondere = RTOTC / 0.0079 fibaro:debug("Radiation totale en lux pondéré = ".. arrondir(LuxPondere,2).." Lux") else RadiationDirecte = 0 RadiationDiffuse = 0 RadiationTotale = 0 Lux = 0 RTOTC = 0 LuxPondere = 0 end --------------------------------- -- Stocker les variables globales -- Créer les variables globales suivantes : -- VDSoleilAzimut -- VDSoleilHauteur -- VDSoleilRadiDir -- VDSoleilRadiDif -- VDSoleilRadiTot -- VDSoleilLuxTot -- VDSoleilOcta -- VDSoleilRadiPon -- VDSoleilLuxPon fibaro:setGlobal("VDSoleilAzimut", arrondir(Azimut,2)) fibaro:setGlobal("VDSoleilHauteur", arrondir(HauteurSoleil,2)) fibaro:setGlobal("VDSoleilRadiDir", arrondir(RadiationDirecte,2)) fibaro:setGlobal("VDSoleilRadiDif", arrondir(RadiationDiffuse,2)) fibaro:setGlobal("VDSoleilRadiTot", arrondir(RadiationTotale,2)) fibaro:setGlobal("VDSoleilLuxTot", arrondir(Lux,2)) fibaro:setGlobal("VDSoleilOcta", Octa) fibaro:setGlobal("VDSoleilRadiPon", arrondir(RTOTC,2)) fibaro:setGlobal("VDSoleilLuxPon", arrondir(LuxPondere,2)) --------------------------------- -- Mise à jour des labels setDevicePropertyValue(VDid, "LabelAzimut", arrondir(Azimut,0).."°" ) setDevicePropertyValue(VDid, "LabelHauteur", arrondir(HauteurSoleil,0) .. "°" ) setDevicePropertyValue(VDid, "LabelNebulosite", Octa .. "/8") setDevicePropertyValue(VDid, "LabelNebPourCent", Nebulosite .. "%") setDevicePropertyValue(VDid, "LabelMaj",DateHeure) setDevicePropertyValue(VDid, "LabelRadiationDirecte", arrondir(RadiationDirecte,0) .. " W/m²") setDevicePropertyValue(VDid, "LabelRadiationDiffuse", arrondir(RadiationDiffuse,0) .. " W/m²") setDevicePropertyValue(VDid, "LabelRadiationTotale", arrondir(RadiationTotale,0) .. " W/m²") setDevicePropertyValue(VDid, "LabelLux",arrondir(Lux,0) .. " Lx") setDevicePropertyValue(VDid, "LabelRTOTC", arrondir(RTOTC,0) .. " W/m²") setDevicePropertyValue(VDid, "LabelLuxPondere", arrondir(LuxPondere,0) .. " Lx") --------------------------------- -- Tag widget fibaro:log(DateHeure) |
Dans le mainloop vous trouverez le code ci-dessous. C’est ici que vous devrez changer les IDs de vos icônes. Vous constaterez que le mainloop actionnera le bouton « mise à jour » toutes les 60 secondes par rapport au dernier timestamp retenue.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | maintenant = os.date("%H:%M", os.time()) --------------------------------- -- Fonction d'initialisation de label --------------------------------- function setDevicePropertyValue(id, label, value) fibaro:call(id, "setProperty", "ui."..label..".value", value) end --------------------------------- local myDeviceID = fibaro:getSelfId() if maintenant > fibaro:getValue(1, "sunriseHour") and maintenant < fibaro:getValue(1, "sunsetHour") then -- ID icône jour fibaro:call(myDeviceID, "setProperty", "currentIcon", 227) if type(n) == "nil" then n1 = tonumber(os.time()) fibaro:call(myDeviceID, "pressButton", "12") n = 1 end if tonumber(os.time()) > n1 + (60) then -- maj toutes les minutes fibaro:call(myDeviceID, "pressButton", "12") n1 = tonumber(os.time()) end else -- ID icône nuit fibaro:call(myDeviceID, "setProperty", "currentIcon", 229) end |
3.4 – Le périphérique virtuel
Ce VD ne sera finalement pas le périphérique virtuel de gestion des volets roulants et des brises soleil orientables. En effet, afin de capitaliser sur plusieurs cas d’usages, j’ai préféré décomposer l’usages des données de leur utilisation. Pour cela, ce VD aura pour objectif de seulement calculer et stocker dynamiquement les données utiles aux autres périphériques virtuels utiles à des actions, et traitements spécifiques. Ainsi, nous aurons une dépendance (librairie tronc commun) à tous les autres développements. J’ai quelques cas d’usages bien précis en tête, mais je pense que la communauté saura enrichir le potentiel. Voici donc ci-dessous le résultat d’affichage de ce périphérique virtuel :
Vous pouvez constater que j’ai conservé la nébulosité exprimée en pour-cent issue d’OpenWeatherMap pour démonter la différence qu’il peut y avoir au niveau des API météo. Il existe de grosse aberrations.
4 – Installation du périphérique virtuel
L’installation du périphérique virtuel est simple. Veuillez suivre les étapes suivantes.
4.1 Créer les variables globales pour stocker les valeurs
Avant toute chose, veuillez créer les neuf variables globales suivantes sur votre HC2 :
- VDSoleilAzimut
- VDSoleilHauteur
- VDSoleilRadiDir
- VDSoleilRadiDif
- VDSoleilRadiTot
- VDSoleilLuxTot
- VDSoleilOcta
- VDSoleilRadiPon
- VDSoleilLuxPon
4.2 Importer le VD
Pré-requis indispensable : Il faut avoir renseigné les coordonnées géographiques de votre domicile dans les paramètres du Homecenter.
- Téléchargez le fichier d’archive de la version 1 (V1) ;
- Décompressez le fichier ;
- Importez le VD ;
- Modifier les identifiants des icônes dans le mainloop.
- Sauvegardez.
4.3 Saisir la station SYNOP la plus proche de votre domicile
A ce stade, vous devez saisir le code station dans le champ adresse IP du périphérique virtuel et votre installation sera terminée.
Attention de bien mettre entre guillemets votre code de sorte à conserver de potentiels zéros en début de code.
Il est possible au travers des services Ogimet de trouver votre station SYNOP avec une carte.
Voici dans le tableau ci-dessous les codes stations diffusant des messages SYNOP :
ID | Nom |
---|---|
07005 | ABBEVILLE |
07015 | LILLE-LESQUIN |
07020 | PTE DE LA HAGUE |
07027 | CAEN-CARPIQUET |
07037 | ROUEN-BOOS |
07072 | REIMS-PRUNAY |
07110 | BREST-GUIPAVAS |
07117 | PLOUMANAC’H |
07130 | RENNES-ST JACQUES |
07139 | ALENCON |
07149 | ORLY |
07168 | TROYES-BARBEREY |
07181 | NANCY-OCHEY |
07190 | STRASBOURG-ENTZHEIM |
07207 | BELLE ILE-LE TALUT |
07222 | NANTES-BOUGUENAIS |
07240 | TOURS |
07255 | BOURGES |
07280 | DIJON-LONGVIC |
07299 | BALE-MULHOUSE |
07314 | PTE DE CHASSIRON |
07335 | POITIERS-BIARD |
07434 | LIMOGES-BELLEGARDE |
07460 | CLERMONT-FD |
07471 | LE PUY-LOUDES |
07481 | LYON-ST EXUPERY |
07510 | BORDEAUX-MERIGNAC |
07535 | GOURDON |
07558 | MILLAU |
07577 | MONTELIMAR |
07591 | EMBRUN |
07607 | MONT-DE-MARSAN |
07621 | TARBES-OSSUN |
07627 | ST GIRONS |
07630 | TOULOUSE-BLAGNAC |
07643 | MONTPELLIER |
07650 | MARIGNANE |
07661 | CAP CEPET |
07690 | NICE |
07747 | PERPIGNAN |
07761 | AJACCIO |
07790 | BASTIA |
61968 | GLORIEUSES |
61970 | JUAN DE NOVA |
61972 | EUROPA |
61976 | TROMELIN |
61980 | GILLOT-AEROPORT |
61996 | NOUVELLE AMSTERDAM |
61997 | CROZET |
61998 | KERGUELEN |
67005 | PAMANDZI |
71805 | ST-PIERRE |
78890 | LA DESIRADE METEO |
78894 | ST-BARTHELEMY METEO |
78897 | LE RAIZET AERO |
78922 | TRINITE-CARAVEL |
78925 | LAMENTIN-AERO |
81401 | SAINT LAURENT |
81405 | CAYENNE-MATOURY |
81408 | SAINT GEORGES |
81415 | MARIPASOULA |
89642 | DUMONT D’URVILLE |
Comme vous pouvez le constater le nombre de stations SYNOP françaises est assez réduit, et le choix de la proximité avec l’une d’entre elle n’est pas forcément le plus pertinent. Pour la métropole, on constate que les dépressions, et donc les fronts nuageux pénètrent le territoire Français le plus souvent d’Ouest en Est, voir de Sud-Ouest à Nord-Est. Donc à choisir entre deux stations à iso-distance, je vous conseille de prendre celle se trouvant à l’ouest voir sud-ouest de votre domicile pour bénéficier d’une forme d’anticipation sur les écarts entre chaque mesure.
5 – Les cas d’usages
A titre d’exemple, les perspectives envisageables sont :
- Un virtual device « Gestion des volets roulants » qui permettrait d’asservir les volets roulants à la position du soleil avec pour objectif le gain thermique l’hiver et la réduction thermique l’été. Ou encore piloter l’ouverture des volets dès 1000 Lux (calculé et pondéré) pour l’aube ou le crépuscule ;
- Un virtual device « Gestion des brises soleil orientables » pour la même chose que les volets roulants ;
- Un virtual device « Gestion d’un volet piscine » pour chauffer ou isolé la piscine si ensoleillé ou nuageux ;
- Un virtual device « Gestion de production photovoltaïque » pour comparer les courbes théoriques pondérées à la production effective, et déclencher des événements adaptés ;
- Un virtual device « Gestion d’un ESC solaire thermique pour connaitre le rendement et déclencher des actions en conséquences ;
- Un virtual device « Data Logger » pour archiver les mesures, afin que constituer un capital données valorisables par traitement intelligent à posteriori ;
- Un virtual device « Simulation PV » pour évaluer le potentiel production photovoltaïque de votre résidence.
- …
6 – Conclusion
J’espère vous avoir donné l’envie d’aller plus loin dans la démarche, et de développer vous-même des variations sur le thème. Pour ma part, je livrerai probablement un périphérique virtuel pour la gestion des volets roulants dès que j’aurai trouvé le temps de transposer la suite de mon projet initial. N’hésitez pas à commenter et apporter des remarques qui me permettrons d’adapter ou corriger la version Une de ce projet.
15 Comments
Bzh_Chris
Bonjour Séb!
Comme d’habitude … WAOUH!
Et tu n’es pas allé avec le dos de la cuiller !
Un paramètre que je ne suis jamais parvenu à faire fonctionner … l’orientation des lamelles des brise-soleil! tu as trouvé !
Christian
Sébastien Joly
Salut BZH_Chris,
Pas de raison de ne pas y arriver.
Par contre je n’ai pas de BSO…
Sébastien Joly
Pour la suite :
Changelog – Périphérique virtuel « Indicateurs Solaires » Release 1.1
Améliorations :
– Historisation des dernières valeurs et affichages des tendances
– Vérification de disponibilité des API en ligne (Socket 80) pour ne pas bloquer procédure.
– Stockage de la durée journalière d’ensoleilement.
– Utiliser le champ port du VD comme ajusteur du filtre sur horizon.
– Définition des masques.
Corrections :
– Message SYNOP, retard d’information d’une heure sur la tranche de 3 heures antérieure.
dwarfy
Impressionnant !
dans le champs d’application, il y a aussi la gestion de l’arrosage des espaces verts, potagers, …
Merci pour cette pépite.
dwarfy
Nico
Excellent ! Merci Captain !!
RSyrek
Ouhaaaa, Merci Seb.
David
Vraiment du beau boulot… je ne soupçonnais pas que l’on puisse disposer de tant d’infos via des sites… il y a l’aspect technique du VD mais aussi toute la partie amont pour savoir ou collecter ces données, c’est du sérieux…
Je l’ai installé, je vérifie les données retournées… c’est dommage effectivement que nous n’ayons pas plus de stations en France parce que suivant les régions, 40kms peuvent faire la différence mais c’est un autre sujet..
En tout cas félicitations…
Neutrino
Superbe script !
J’admire le temps passé à chercher et convertir les formules en LUA.
J’ai commencé à adapter ce script à Domoticz, la station Weather Underground proche de chez moi ne remontant plus la valeur de radiation totale depuis fin août, et je m’en servais pour le contrôle de mes volets roulants.
Un grand merci pour tout ça.
Jeremy Piaia
Epoustouflant!
Twist
Génial !
Bravo et merci pour ce VD dont je me sers dès à présent.
Ma première utilisation concerne la gestion des lumières !
Aurélien
Bonjour, Je ne sais absolument pas où poser ma question… quelqu’un pourrait-il m’aider à créer un thermostat virtuel avec la HC2. Je possède une sonde de température relié au module FGBS001, et un module FGS221 en contact sec pour la chaudière…
Une solution s’il vous plait ?
En vous remerciant tous !
Aurélien
Philippe
Sebastien, Merci pour ta V1. Je viens de la charger, ai remplacé les icons ds le main loop, ai mis entre quilement le station pour Orly « 07149 » mais quand je fais mise a jour, il se passé rien. Y a t il d autres parameter a remplacer ailleurs que ds le main loop?
Merci pour tes conseils.
Philippe
Sébastien Joly
Peut-être que toutes les variables globales ne sont pas bien déclarées :
VDSoleilAzimut
VDSoleilHauteur
VDSoleilRadiDir
VDSoleilRadiDif
VDSoleilRadiTot
VDSoleilLuxTot
VDSoleilOcta
VDSoleilRadiPon
VDSoleilLuxPon
Philippe
Non Elles sont bien la….
Fait il mettre port 80? C est ce que j ai pour le moment
Pourrais tu reposter la dernière mouture?
Merci,!
Aurélien
Bravo et merci !
Tiens nous au courant des évolutions surtout
Aurélien