diff --git a/config-default.yaml b/config-default.yaml index 44ab97c..2f5594d 100644 --- a/config-default.yaml +++ b/config-default.yaml @@ -1,591 +1,594 @@ ###################################################################### # PvMonit - By David Mercereau : http://david.mercereau.info/contact/ # Licence BEERWARE ###################################################################### ############################## # # NE MODIFIER PAS CE FICHIER ! # copier config-default.yaml dans config.yaml et modifier config.yaml (supprimer tout ce qui ne vous intéresse pas de modifier) # ############################## # Niveau d'affichage des messages printMessage: 0 # 0=0 5=debug printMessageLogfile: false # path or fase # URL data urlDataXml: http://pvmonit.local/data-xml.php # N'utilisez pas 127.0.0.1 mais plutôt l'ip local si vous restez en local (192.168.1.2 ? commande "ip a s" pour l'obtenir, vous ne pouvez pas être en DHCP, mais en IP fixe donc), ou un nom de domain résolu en local et à l'exterieur si c'est publié sur internet tmpFileDataXml: /tmp/PvMonit_data-xml.php.tmp scriptDataXml: /opt/PvMonit/www/data-xml.php dir: bin: /opt/PvMonit/bin/ bin_enabled: /opt/PvMonit/bin-enabled/ lcd: /opt/PvMonit/lcd/ domo: /opt/PvMonit/domo/ bin: php-cli: /usr/bin/php data: ppv_total: false # production total des régulateurs (utilisé si vous avez plusieurs régulateur) conso_calc: false # Calculé avec : la puissance instantané (P du BMV) - ppv_total ppv_total at true for use this #~ dataCheck: # Donnée minimum pour que l'XML soit considéré comme valide #~ PPV: # Production des MPPT #~ regex: (^[0-9]+\.?[0-9]+?$)|(^[0-9]$) #~ number: 2 # Si vous avez 2 MPPT il faut le préciser #~ SOC: #~ regex: (^[0-9]+\.?[0-9]+?$)|(^[0-9]$) # BMV : % SOC #~ P: #~ regex: (^-?[0-9]+\.?[0-9]+?$)|(^-?[0-9]$) # BMV : P #~ PPVT: # Total des PPVT (si plusieurs MPPT #~ regex: (^[0-9]+\.?[0-9]+?$)|(^[0-9]$) #~ CS: # MPPT etat (float, bulk...) #~ regex: ^Off$|Fault$|Bulk|Faible|Abs|Float|On$ #~ Relay: # SmartSolar MPPT Relay ou BMV #~ Si aucun regex n'est précisé alors la vérification ne ce fait pas sur la valeur mais uniquement sur la présence de la donnée cache: dir: /tmp/PvMonit_cache # in tmpfs expir: 15 # in second expirLimit: 60 # If dataCheck error... # Methode de récupération des données VE DIRECT (par USB - vedirect OU serial par Arduino) vedirect: by: usb # usb OR arduino usb: # Binaire de vedirect.py USB bin: /usr/bin/sudo /usr/bin/python /opt/PvMonit/bin/vedirect.py arduino: # Fichier de data YAML enregistré par le script vedirectOnArduinoRemote.py cohérence avec config-vedirectOnArduinoRemote.yaml data_file: /tmp/PvMonit_getSerialArduino.data.yaml data_file_expir: 300 # Expiration serial: port: /dev/ttyAMA0 # ttyAMA0 pour le serial via GPIO, ttyUSB0 pour le port USB... timeout: 0 # Débit du serial 0 qui va vers l'Arduino (doit être cohérent entre les 2, diffère selon la distance de câble) # Débit Longueur (m) # 2400 60 # 4 800 30 # 9 600 15 # 19 200 7,6 # https://fr.wikipedia.org/wiki/RS-232#Limites baudRate: 4800 whileSleep: 0.001 whileSleepAfterStop: 3 # donnée récolté (voir la doc victron sur le protocole VE.Direct) data_ok: mppt: - CS - PPV - V - ERR - I - VPV - H19 - H20 - H21 - H22 - H23 - Relay bmv: - V - VS - VM - DM - I - T - P - CE - SOC - TTG - AR - H1 - H2 - H3 - H4 - H5 - H6 - H7 - H8 - H9 - H10 - H11 - H12 - H13 - h14 - H15 - H16 - H17 - H18 - Relay phoenix: - P - CS - MODE - AC_OUT_V - AC_OUT_I - WARN wks: enable: false # Passer a true pour activer bin: "/usr/bin/sudo /usr/bin/python3 /opt/PvMonit/bin/wks.py" # Script qui récupère les informations du WKS data: printAll: true # Afficher toutes les valeurs mêmes si elles n'ont pas de libellé QPIRI: # Ordre name: "Paramètre" # Le nom #~ 1: # La position de 1 à X #~ id: ConfGirdRatV # Id : doit être unique, sans caractères spéciaux ni espace, ni accent... #~ desc: "Grid rating voltage" # Description #~ units: "V" # Unité de messur (V / % / A...) #~ regex: /^[0-9]+.[0-9]$/ # Regex a valider sinon la valeur ne s'affiche pas, Si pas de regex, pas de validation #~ hide: true # true = caché, false or null = affiché 1: id: ConfGirdRatV desc: "Grid rating voltage" units: "V" regex: /^[0-9]+.[0-9]$/ 2: id: GirdRatA desc: "Grid rating current" units: "A" #~ regex: false #~ hide: true 3: id: ConfAcOutRV desc: "AC output rating voltage" units: "V" 4: id: ConfAcOutRF desc: "AC output rating frequency" units: "Hz" 5: id: ConfAcOutRI desc: "AC output rating current" units: "A" 6: id: ConfAcOutVA desc: "AC output rating apparent power" units: "VA" 7: id: ConfAcOutRP desc: "AC output rating active power" units: "W" 8: id: ConfBatRV desc: "Battery rating voltage" units: "V" 9: id: ConfBatReCV desc: "Battery re-charge voltage" units: "V" 10: id: ConfBatUV desc: "Battery under voltage" units: "V" 11: id: ConfBatBV desc: "Battery bulk voltage " units: "V" 12: id: ConfBatFV desc: "Battery float voltage" units: "V" 13: id: ConfBatT desc: "Battery type" value2text: 0: "AGM" 1: "Flooded" 2: "User" 14: id: ConfCurMaxACcharge desc: "Current max AC charging current" units: "A" 15: id: ConfCurMaxCharge desc: "Current max charging current" units: "A" 16: id: ConfInputVR desc: "Input voltage range" value2text: 0: "Appliance (From 90V to 280V AC)" 1: "UPS (From 170V to 280V AC)" 17: id: ConfOutputSP desc: "Output source priority" value2text: 0: "Utility first" 1: "Solar first" 2: "SBU first" 18: id: ConfChargeSP desc: "Charger source priority" value2text: 0: "Utility first" 1: "Solar first" 2: "Solar + Utility" 3: "Only solar charging permitted" 19: id: ConfBatReDV desc: "Battery re-discharge voltage" units: "V" QPIGS: name: "Donnée" 1: id: GirdV desc: "Grid voltage" units: "V" regex: /^[0-9]+.[0-9]$/ 2: id: GirdF desc: "Grid frequency" units: "Hz" 3: id: ACoutV desc: "AC output voltage" units: "V" 4: id: ACoutF desc: "AC output frequency" units: "Hz" 5: id: ACoutP desc: "AC output apparent power" units: "VA" 6: id: CONSO desc: "AC output active power" units: "W" 7: id: LOAD desc: "AC output load percent" units: "%" 8: id: BusV desc: "BUS voltage" units: "V" 9: id: V desc: "Battery voltage" units: "V" 10: id: Ic desc: "Battery charging current" units: "A" 11: id: SOC desc: "Battery capacity" units: "%" 12: id: BatFloatV desc: "Battery float voltage" units: "V" 13: id: BatVsoc desc: "Battery voltage from SCC 1" units: "V" 14: id: Id desc: "Battery discharge current" units: "A" 15: id: T desc: "Inverter heat sink temperature" units: "°C" 16: id: IPV desc: "PV Input current 1" units: "A" 17: id: VPV desc: "PV Input voltage 1 " units: "A" 18: id: PPV desc: "PV Charging power 1 " units: "W" 19: id: Status desc: "Device status" QPIWS: name: "Alarme" 1: id: ERR_OC desc: "Over charge current" 2: id: ERR_T desc: "Over temperature" 3: id: ERR_BVU desc: "Battery voltage under" 4: id: ERR_BVH desc: "Battery voltage high" 5: id: ERR_PVHL desc: "PV high loss" 6: id: ERR_BT desc: "Battery temperature too low" 7: id: ERR_BTH desc: "Battery temperature too high" 8: id: ERR_PVLL desc: "PV low loss" 9: id: ERR_PVHD desc: "PV high derating" 10: id: ERR_THD desc: "Temperature high derating" 11: id: ERR_BTA desc: "Battery temperature low alarm" # Numéro de série (champs SER#) en correspondance avec des nom buvables deviceCorrespondance: HQXXXXXXXX: MpttGarage HQYYYYYYYY: MpttToit OTHER: Divers # Plafont de consommation en W impossible à dépasser (techniquement, sinon c'est une erreur de sonde) consoPlafond: 1500 # Tension standard du réseau (110V ou 230V) tensionNorme: 230 ### Export vers Emoncms emoncms: daemon: false # Interval entre 2 récupération de donnée (en minute) getInterval: 5 # Interval entre 2 envoi à emoncms sendInterval: 30 # Test la connexion internet testInternetHost: emoncms.org testInternetPort: 80 # emoncms URL du post.json & API key urlInputJsonPost: https://emoncms.org/input/post.json apiKey: XXXXXXXXXXXXXXXXXXXXXXXX # Répertoire de collecte de données dataCollecte: /tmp/PvMonit_collecteData # Dossier ou ranger les erreurs dataCollecteError: /tmp/PvMonit_collecteDataError # Attente entre deux requête OK sleepOk: 1 # Attente entre deux requête échoué sleepNok: 3 # Fichier de lock pour éviter les doublons lockFile: /tmp/PvMonit_sendToEmoncms.lock ### Page Web : www: # Mot de passe d'accès à la page web password: false # http://www.passwordtool.hu/md5-password-hash-generator passwordLife: 86400 # Durée de vie du mot de passe en seconde # Délais de raffraichissement de la page (en seconde) 300 = 5 minutes refreshTime: 300 # Max de la jauge voltage batterie (en V) vbatMax: 17 # Max de la jauge puissance PV (en W) PpvMax: 500 # max Jauge puissance PV (en W) # Max de la jauge puissance PV total (si plusieurs régulateur) (en W) PpvtMax: 500 # max Jauge puissance PV (en W) dataPrimaire: - V - PPV - ERR - CS - SOC - AR - P - TTG - MODE - AC_OUT_V - AC_OUT_I - WARN - PPVT - CONSO dataPrimaireSmallScreen: - SOC - P - PPVT - PPV menu: -
  • EmonCMS (historique)
  • -
  • PvMonit projet
  • -
  • Soutenir l'auteur
  • checkUpdate: 43200 # false for disable, or seconds checks domo: false # Enable domo on web interface ? domoRefreshTime: 5 # Refresh time domo in second domoPassword: false # Domo password in MD5 - http://www.passwordtool.hu/md5-password-hash-generator domoEdit: true # Script edit on web /domo-edit-script.php page domoEditPassword: false # DomoEdit password in MD5 - http://www.passwordtool.hu/md5-password-hash-generator help: false # Active l'assistance domoEditExampleDir: /opt/PvMonit/domo/relay.script.d/example weatherForcast: false # Prévision météo a afficher dans l'interface web weatherForcastNbDayPrint: 1 # Nombre de jour a afficher pour les prévisions météos weatherProdForcast: false # Prévision de productoin a afficher dans l'interface web # Ecran LCD (avec script PvMonit/lcd lcd: daemon: false rafraichissement: 0.1 # en seconde pour les boutons dataUpdate: 45 # en seconde pour le rafraichissement des données onTimer: 60 # en seconde le temps que l'écran reste allumé si par défaut éteind estCeLaNuitTimer: 600 # détection de la nuit tout les x secondes dataPrint: - SOC - P - PPVT onAt: 8 # heure d'allumage du LCD offAt: 21 # heure d'extinction du LCD # Domotique (avec script PvMonit/domo) domo: daemon: false dataCheckTime: 60 # Check du XML dbFile: /tmp/PvMonit_domo.sqlite3 jsonFile: modPath: /tmp/PvMonit_domo_mod etatPath: /tmp/PvMonit_domo_etat prefixFileData: /tmp/PvMonit_domo_data_ binGpio: /usr/bin/sudo /usr/bin/gpio fileExpir: 500 # Age en seconde après laquel le fichier n'est plus considéré comme ok xmlDataExpir: 500 # Age en seconde avant expiration des données XML (et donc arrêt du heartbeat) valueUse: - SOC # BMV : % SOC #~ - P # BMV : P #~ - PPVT # Total des PPVT (si plusieurs MPPT #~ - PPV # Production des MPPT #~ - CS # MPPT etat (float, bulk...) #~ - Relay # SmartSolar MPPT Relay ou BMV valueSimu: # Les valeurs pour la simulation blockly des "valueUse" SOC: - type:number - value:90 - min:0 - max:100 - output:Number - tooltip:"% des batteries" Relay: - type:dropdown - value:0|1 - output:Number - tooltip:"Etat du relai (sur le victron)" CS: - type:dropdown - value:Float|Absorption|Bulk|Off|Fault - output:String - tooltip:"Statut du régulateur" P: - type:number - value:200 - min:-5000 - max:5000 - output:Number - tooltip:"Puissance (BMV)" PPV: - type:number - value:400 - min:0 - max:5000 - output:Number - tooltip:"Puissance des panneaux" PPVT: - type:number - value:400 - min:0 - max:5000 - output:Number - tooltip:"Puissance total des panneaux" EXEMPLEINPUT: - type:input - value:Test - output:String - tooltip:"Juste un exemple d'input" relay: scriptDir: /opt/PvMonit/domo/relay.script.d scriptExecInterval: 60 # Interval d'execution des script de relais secuDownNoData: 600 # Temps (en seconde) après lequel on coupe tout les relay s'il n'y a pas eu de nouvelle données relayNb: 8 relayName: # A commencer par 1 1: aDefinir 2: aDefinir 3: aDefinir 4: aDefinir 5: aDefinir 6: aDefinir 7: aDefinir 8: aDefinir relayWiringPi: # WiringPI is no GPIO number : https://fr.pinout.xyz/pinout/ 1: 4 2: 5 3: 10 4: 21 5: 22 6: 27 7: 28 8: 29 relayActionRefresh: 2 # delay (in second) to refresh etat relay (script relay-action.php) tm1638: daemon: false refresh: 0.3 actionButtonDelay: 2 # délais (en seconde) avant que les actions boutton n'est un effet cloud: # Cloud service, visit http://pvmonit.zici.fr daemon: false url: http://pvmonit.zici.fr/id/ api: XXXXXXXXXXXXXXX sendDelay: 300 # Délai d'envoi de donnée (en seconde) weather: enable: false cache: 3600 # in seconde openweathermapCityId: XXXXXXX # OpenWeatherMap city ID # Tout les city id sont là : http://bulk.openweathermap.org/sample/city.list.json.gz # Sinon tu peux faire un recherche https://openweathermap.org/city et l'ID se trouve dans l'URL (exemple pour Paris FR : https://openweathermap.org/city/2988507 l'ID est 2988507 ) openweathermapAppId: XXXXXXXXXXXXXXXXXXXXXXXX # Creat account on openweathermap.org for APP ID (api key) forecastDay: 5 # Nombre de jour de prévision au delà de ce jour (min 1, max 5) prod: 1000 # Wc panel installed dalyConsumption: 1000 # Wh/d need (calculé pour le dimmensionnement prod_yield_global: 0.80 # Rendement global de l'installation ($prod * 0.80) prod_mini: 0.03 # Production minimum (%) abatementSurise: # Abattement sur la production au levé du soleil 0: 0 # Exemple : à l'heure du levé du soleil on applique un coef de 0.1 sur la prod 1: 0.1 2: 0.3 3: 0.6 4: 0.8 5: 0.9 abatementSunset: # Abattement sur la production au couché du soleil 5: 0.9 # Exemple : 5 h avant le couché du soleil on applique un abattement de 0.6 4: 0.8 3: 0.6 2: 0.3 1: 0.1 0: 0 - + abatementHour: # Abattement / h (UTC) + #~ 8: 0.2 # Exemple Si vous avez un masque solaire entre 10 et 12h en été à Paris c'est 8-10h UTC (Paris l'été c'est GTM +2) + #~ 9: 0.2 + #~ user: # Ok for text/number/password... #~ startTime: # name in form #~ id: startTime #~ label: "Heure de début" #~ type: number #~ value: 1 #~ min: 0 #~ max: 23 #~ step: 1 #~ endTime: #~ id: startTime #~ label: "Heure de début" #~ type: number #~ value: 6 #~ min: 0 #~ max: 23 #~ step: 1 diff --git a/www/weatherForcast.php b/www/weatherForcast.php new file mode 100644 index 0000000..236eae0 --- /dev/null +++ b/www/weatherForcast.php @@ -0,0 +1,34 @@ + + diff --git a/www/weatherProdForcast.php b/www/weatherProdForcast.php new file mode 100644 index 0000000..9675742 --- /dev/null +++ b/www/weatherProdForcast.php @@ -0,0 +1,157 @@ +\n"; + //~ echo "sunset : " ; + //~ echo date('H:m:s', $resultArray['city']['sunset']); + //~ $sunsetSecond = timeHms2s($resultArray['city']['sunset']); + //~ } + $forecast['sunset']=$resultArray['city']['sunset']; + $forecast['surise']=$resultArray['city']['sunrise']; + //~ echo "
    \n"; + //~ echo "H : comprendre H-3h"; + //~ echo "
    \n"; + foreach($resultArray as $key=>$weather) { + global $config; + if ($key == 'list') { + foreach($weather as $no=>$weatherDay) { + // On cherche l'interval de date + $dateNow = new DateTime(date('Y-m-d', time())); + $datePrevision = new DateTime(date('Y-m-d', $weatherDay['dt'])); + $interval = date_diff($dateNow, $datePrevision); + $diffIntervalOperation = $interval->format('%R%a'); + $diffDay = $interval->format('%a'); + // On s'arrête à J+2 en prévision + if ($diffDay > $config['weather']['forecastDay']){ + continue; + } + // Moyenne des nuages duprant la journée + //~ average cloud during the day + //~ if (date('G', $weatherDay['dt']) >= date('G', $forecast['surise']) && date('G', $weatherDay['dt']) <= date('G', $forecast['sunset'])) { + //~ if (isset($avenage[$diffDay])) + //~ echo date('G', $weatherDay['dt']); + //~ } + $forecast[$diffDay][date('G', $weatherDay['dt']-3600-3600)]=$weatherDay['clouds']['all']; + $forecast[$diffDay][date('G', $weatherDay['dt']-3600)]=$weatherDay['clouds']['all']; + $forecast[$diffDay][date('G', $weatherDay['dt'])]=$weatherDay['clouds']['all']; + } + } + } + //~ echo json_encode($forecast); + //~ exit(); + function prodForecast($forecast) { + global $config; + global $include; + # On cherche la différence entre l'heure configuré (time zone) et l'UTC + $dateTimeZoneUTC = new DateTimeZone("UTC"); + $dateTimeZoneGet = new DateTimeZone(date_default_timezone_get()); + $dateTimeUTC = new DateTime("now", $dateTimeZoneUTC); + //~ $dateTimeGet = new DateTime("now", $dateTimeZoneGet); + $diffUTC = round($dateTimeZoneGet->getOffset($dateTimeUTC)/3600); + trucAdir(5, "La timezone ".date_default_timezone_get()." est à $diffUTC h d'UTC"); + for ($day = 0; $day <= $config['weather']['forecastDay']; $day++) { + if (empty($forecast[$day])) { + continue; + } + foreach ($forecast[$day] as $hour=>$cloud) { + trucAdir(5, "Day $day, $hour H - Cloud : $cloud % "); + $abatementCloud=(100-$cloud)/100+$config['weather']['prod_mini']; + if ($hour >= date('G', $forecast['surise']) && $hour <= date('G', $forecast['sunset'])) { + $diffSunrise=$hour-date('G', $forecast['surise']); + $diffSunset=date('G', $forecast['sunset'])-$hour; + if (isset($config['weather']['abatementSurise'][$diffSunrise])) { + $abatement=$config['weather']['abatementSurise'][$diffSunrise]; + } elseif (isset($config['weather']['abatementSunset'][$diffSunset])) { + $abatement=$config['weather']['abatementSunset'][$diffSunset]; + } else { + $abatement=1; + } + //~ exit(); + $hourUtc=$hour-$diffUTC; + $abatementHour=1; + if (isset($config['weather']['abatementHour'][$hourUtc])) { + $abatementHour=$config['weather']['abatementHour'][$hourUtc]; + trucAdir(5, "Un abattement horraire de $abatementHour s'applique à $hour H ($hourUtc H UTC))"); + } + $prodForcast[$day]['byHour'][$hour]['prod']=round($config['weather']['prod']*$abatementCloud*$config['weather']['prod_yield_global']*$abatement*$abatementHour, 0); + $prodForcast[$day]['byHour'][$hour]['cloud']=$cloud; + $prodForcast[$day]['byHour'][$hour]['sun']=1; + trucAdir(5, "Prod estimé : ".$prodForcast[$day]['byHour'][$hour]['prod']."W - Abatement config $abatement - "); + } else { + $prodForcast[$day]['byHour'][$hour]['prod']=0; + $prodForcast[$day]['byHour'][$hour]['cloud']=$cloud; + $prodForcast[$day]['byHour'][$hour]['sun']=0; + trucAdir(5, "Prod estimé : ".$prodForcast[$day]['byHour'][$hour]['prod']); + } + } + $prodCumul=0; + $cloudAvg=0; + $cloudAvgNb=0; + foreach ($prodForcast[$day]['byHour'] as $byHour) { + $prodCumul=$prodCumul+$byHour['prod']; + if ($byHour['sun'] == 1) { + $cloudAvg=$cloudAvg+$byHour['cloud']; + $cloudAvgNb++; + } + } + $prodForcast[$day]['prodCumul']=round($prodCumul, 0); + $prodForcast[$day]['cloudAvg']=round($cloudAvg/$cloudAvgNb, 0); + ksort($prodForcast[$day]['byHour']); + } + return $prodForcast; + } + file_put_contents($cacheFileProd, json_encode(prodForecast($forecast))); +} else { + trucAdir(5, "Le cache est service pour la prod forcast"); +} +echo file_get_contents($cacheFileProd); + +?> +