--Variables à éditer-------------- local Ville = "pws:ILAGACIL2" --Ville de référence local idxLux = '320' --Capteur virtuel de Luminosité local idxOcta = '5' -- idx de la variable Utilisateur local wuAPIkey = "48a08328a93a18a1" local DEBUG = 'OUI' --import des fontions pour lire le JSON json = (loadfile "/opt/domoticz/scripts/lua/JSON.lua")() -- Fonction déterminant si année bissextile function AnneeBissextile(annee) return annee%4==0 and (annee%100~=0 or annee%400==0) 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 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 --------------------------------- --------------------------------- -- Meteo API Wunderground local config=assert(io.popen('curl http://api.wunderground.com/api/'..wuAPIkey..'/conditions/q/FR/'..Ville..'.json')) local location = config:read('*all') config:close() local jsonLocation = json:decode(location) local Latitude = jsonLocation.current_observation.display_location.latitude local Longitude = jsonLocation.current_observation.display_location.longitude local Altitude = jsonLocation.current_observation.display_location.elevation PressionRelative = jsonLocation.current_observation.pressure_mb ---------------------------------- local An = os.date("%Y") local NiemeJourDeLAnnee = os.date("%j") --------------------------------- DateHeure = os.date("%Y-%m-%d %H:%M:%S", os.time()) -- Début debug if( DEBUG == 'OUI') then print("=====================================") print(os.date("%Y-%m-%d %H:%M:%S", os.time())) print(Ville .. ", " .. Latitude .. ", " .. Longitude) print("Altitude = " .. tostring(Altitude) .. " m") print("NiemeJourDeLAnnee = " .. NiemeJourDeLAnnee) end --------------------------------- --calcul de l'année bissextile if AnneeBissextile(An) == true then if( DEBUG == 'OUI') then print( An .. " est bissextile.") end JourDansLAnnee = 366 else if( DEBUG == 'OUI') then print( An .. " n'est pas bissextile.") end JourDansLAnnee = 365 end --------------------------------- -- Vitesse angulaire = Combien de degrés par jour VitesseAngulaire = 360/365.25 ----JourDansLAnnee -- ou approximativement 365.25 if( DEBUG == 'OUI') then print("Vitesse angulaire = " .. VitesseAngulaire .. " par jour") end --------------------------------- -- 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)))))))) if( DEBUG == 'OUI') then print("La déclinaison = " .. Declinaison .. "°") end --------------------------------- -- Temps universel décimal (UTC) TempsDecimal = (os.date("!%H") + os.date("!%M") / 60) if( DEBUG == 'OUI') then print("Temps universel decimal (UTC)".. TempsDecimal .." H.dd") end --------------------------------- -- Temps solaire HeureSolaire = TempsDecimal + (4 * Longitude / 60 ) if( DEBUG == 'OUI') then print("Temps solaire ".. HeureSolaire .." H.dd") end --------------------------------- -- Angle horaire du soleil AngleHoraire = 15 * ( 12 - HeureSolaire ) if( DEBUG == 'OUI') then print("Angle Horaire = ".. AngleHoraire .. "°") end --------------------------------- -- 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)))) if( DEBUG == 'OUI') then print("Hauteur du soleil = " .. HauteurSoleil .. "°") end 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 if( DEBUG == 'OUI') then print("Azimut du soleil = " .. Azimut .. "°") end --------------------------------- -- 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) if( DEBUG == 'OUI') then print("La durée d'insolation journalière = " .. DureeInsolation .." H.dd") end --------------------------------- -- 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 ))) if( DEBUG == 'OUI') then print("Radiation max en atmosphère = " .. arrondir(RadiationAtm,2) .. " W/m²") end --------------------------------- -- Coefficient d'attenuation M PressionAbsolue = PressionRelative - arrondir((Altitude/ 8.3),1) -- hPa SinusHauteurSoleil = math.sin(math.rad(HauteurSoleil)) M0 = math.sqrt(1229 + math.pow(614 * SinusHauteurSoleil,2)) - 614 * SinusHauteurSoleil M = M0 * PressionRelative/PressionAbsolue if( DEBUG == 'OUI') then print("Pression relative locale = " .. PressionRelative .. " hPa") print("Pression absolue atmosphère = " .. PressionAbsolue .. " hPa") print("Coefficient d'attenuation = " .. M ) end --------------------------------- -- Récupérer message SYNOP 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") local WMOID = jsonLocation.current_observation.display_location.wmo print("WMOID="..WMOID) local ogimet=assert(io.popen('curl "http://www.ogimet.com/cgi-bin/getsynop?block='..WMOID..'&begin='..UTC..'"')) local synop = ogimet:read('*all') ogimet:close() rslt = split(synop,",") CodeStation = rslt[1] rslt = split(synop, " "..CodeStation.. " ") Trame = string.gsub(rslt[2], "=", "") Trame = CodeStation .." ".. Trame rslt = split(Trame, " ") if( DEBUG == 'OUI') then print("Horodatage UTC = " .. UTC) print("Station SYNOP = " .. WMOID) end --------------------------------- -- Récupérer le premier caractere du 3eme mot = Nebulosité en Octa Octa = string.sub(rslt[3], 1, 1) --print(rslt[3]) -- 0 Pas de couverture nuageuse -- 1-8 Huitième -- 9 Brouillard -- / Couverture indiscernable -- cas particulier si valeur indéterminé un slash est renvoyé. if Octa == "/" then -- si la couverture est indiscernable, on reprend l'ancienne valeur -- cela evite les violentes cassures dans la courbe --Octa = uservariables['octa'] Octa = arg[1] elseif Octa == "9" then Octa = 8 end if( DEBUG == 'OUI') then print( Octa .. " Octa") end -- stockage de la variable octa --commandArray['Variable:octa']=tostring(Octa) os.execute('/usr/bin/curl "http://127.0.0.1:8080/json.htm?type=command¶m=updateuservariable&idx='..idxOcta..'&vname=octa&vtype=0&vvalue='..tostring(Octa)..'"') --------------------------------- -- 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)) if( DEBUG == 'OUI') then print("Kc = " .. Kc) end --------------------------------- -- 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 -- Radiation Diffuse RadiationDiffuse = RadiationAtm * (0.271 - 0.294 * math.pow(0.6,M)) * SinusHauteurSoleil -- Radiation totale RadiationTotale = RadiationDiffuse + RadiationDirecte -- Radiation en Lux : -- 1 Lux = 0,0079 W/m² Lux = RadiationTotale / 0.0079 --Lux = ConstanteRadiationLux / ConstanteRatiationSolaire * RadiationTotale -- Le rayonnement solaire avec ciel nuageux RTOTC = RadiationTotale * Kc -- Radiation en Lux pondéré -- LuxPondere = ConstanteRadiationLux / ConstanteRatiationSolaire * RTOTC LuxPondere = RTOTC / 0.0079 print("Radiation totale en lux pondéré = ".. arrondir(LuxPondere,2).." Lux") if( DEBUG == 'OUI') then print("RadiationDirecte = ".. arrondir(RadiationDirecte,2) .." W/m²") print("Radiation Diffuse = ".. arrondir(RadiationDiffuse,2) .." W/m²") print("Radiation totale = " .. arrondir(RadiationTotale,2) .." W/m²") print("Radiation totale en lux = ".. arrondir(Lux,2).." Lux") print("Le rayonnement solaire avec pondération = " .. arrondir(RTOTC,2)) end else --le soleil est trop bas RTOTC = 0 LuxPondere = 0 end --mise à jour du dispositif os.execute('/usr/bin/curl "http://127.0.0.1:8080/json.htm?type=command¶m=udevice&idx='..idxLux..'&svalue="'..tostring(LuxPondere)..' -s -o /dev/null')