diff --git a/config-default.yaml b/config-default.yaml index 203b7dc..44ab97c 100644 --- a/config-default.yaml +++ b/config-default.yaml @@ -1,561 +1,591 @@ ###################################################################### # 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 + #~ 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/function.php b/function.php index aa76156..36df8d2 100644 --- a/function.php +++ b/function.php @@ -1,811 +1,835 @@ $perso1) { if ($key1 == 'deviceCorrespondance') { $config[$key1]=$perso1; } elseif (is_array($perso1)) { foreach($perso1 as $key2=>$perso2) { if (is_array($perso2)) { foreach($perso2 as $key3=>$perso3) { if (isset($config_perso[$key1][$key2][$key3])) { $config[$key1][$key2][$key3]=$perso3; } } }elseif (isset($config[$key1][$key2])) { $config[$key1][$key2]=$perso2; } } } elseif (isset($config[$key1])) { $config[$key1]=$perso1; } } $config['md5sum']=md5_file($config_dir.'/config.yaml'); return $config; } # Victron : détermine le type d'appareil # Source doc Victron "VE.Direct Protocol" function ve_type($ve_pid) { if (substr($ve_pid, 0, -1) == '0x20') { $ve_type_retour='BMV'; } else if (substr($ve_pid, 0, -2) == '0xA0' || $ve_pid == '0x300') { $ve_type_retour='MPPT'; } else if (substr($ve_pid, 0, -2) == '0xA2') { $ve_type_retour='PhoenixInverter'; } else { $ve_type_retour='Inconnu'; } return $ve_type_retour; } # Victron : détermine le modèle de l'appareil # Source doc Victron "VE.Direct Protocol" function ve_modele($ve_pid) { switch ($ve_pid) { case '0x203': $ve_modele_retour='BMV-700'; break; case '0x204': $ve_modele_retour='BMV-702'; break; case '0x205': $ve_modele_retour='BMV-700H'; break; case '0xA381': $ve_modele_retour='BMV-712 Smart'; break; case '0xA04C': $ve_modele_retour='BlueSolar MPPT 75/10'; break; case '0x300': $ve_modele_retour='BlueSolar MPPT 70/15'; break; case '0xA042': $ve_modele_retour='BlueSolar MPPT 75/15'; break; case '0xA043': $ve_modele_retour='BlueSolar MPPT 100/15'; break; case '0xA044': $ve_modele_retour='BlueSolar MPPT 100/30 rev1'; break; case '0xA04A': $ve_modele_retour='BlueSolar MPPT 100/30 rev2'; break; case '0xA041': $ve_modele_retour='BlueSolar MPPT 150/35 rev1'; break; case '0xA04B': $ve_modele_retour='BlueSolar MPPT 150/35 rev2'; break; case '0xA04D': $ve_modele_retour='BlueSolar MPPT 150/45'; break; case '0xA040': $ve_modele_retour='BlueSolar MPPT 75/50'; break; case '0xA045': $ve_modele_retour='BlueSolar MPPT 100/50 rev1'; break; case '0xA049': $ve_modele_retour='BlueSolar MPPT 100/50 rev2'; break; case '0xA04E': $ve_modele_retour='BlueSolar MPPT 150/60'; break; case '0xA046': $ve_modele_retour='BlueSolar MPPT 150/70'; break; case '0xA04F': $ve_modele_retour='BlueSolar MPPT 150/85'; break; case '0xA047': $ve_modele_retour='BlueSolar MPPT 150/100'; break; case '0xA050': $ve_modele_retour='SmartSolar MPPT 250/100'; break; case '0xA051': $ve_modele_retour='SmartSolar MPPT 150/100'; break; case '0xA052': $ve_modele_retour='SmartSolar MPPT 150/85'; break; case '0xA053': $ve_modele_retour='SmartSolar MPPT 75/15'; break; case '0xA054': $ve_modele_retour='SmartSolar MPPT 75/10'; break; case '0xA055': $ve_modele_retour='SmartSolar MPPT 100/15'; break; case '0xA056': $ve_modele_retour='SmartSolar MPPT 100/30'; break; case '0xA057': $ve_modele_retour='SmartSolar MPPT 100/50'; break; case '0xA058': $ve_modele_retour='SmartSolar MPPT 150/35'; break; case '0xA059': $ve_modele_retour='SmartSolar MPPT 150/100 rev2'; break; case '0xA05A': $ve_modele_retour='SmartSolar MPPT 150/85 rev2'; break; case '0xA05B': $ve_modele_retour='SmartSolar MPPT 250/70'; break; case '0xA05C': $ve_modele_retour='SmartSolar MPPT 250/85'; break; case '0xA05D': $ve_modele_retour='SmartSolar MPPT 250/60'; break; case '0xA05E': $ve_modele_retour='SmartSolar MPPT 250/45'; break; case '0xA05F': $ve_modele_retour='SmartSolar MPPT 100/20'; break; case '0xA060': $ve_modele_retour='SmartSolar MPPT 100/20 48V'; break; case '0xA061': $ve_modele_retour='SmartSolar MPPT 150/45'; break; case '0xA062': $ve_modele_retour='SmartSolar MPPT 150/60'; break; case '0xA063': $ve_modele_retour='SmartSolar MPPT 150/70'; break; case '0xA064': $ve_modele_retour='SmartSolar MPPT 250/85 rev2'; break; case '0xA065': $ve_modele_retour='SmartSolar MPPT 250/100 rev2'; break; case '0xA201': $ve_modele_retour='Phoenix Inverter 12V 250VA 230V'; break; case '0xA202': $ve_modele_retour='Phoenix Inverter 24V 250VA 230V'; break; case '0xA204': $ve_modele_retour='Phoenix Inverter 48V 250VA 230V'; break; case '0xA211': $ve_modele_retour='Phoenix Inverter 12V 375VA 230V'; break; case '0xA212': $ve_modele_retour='Phoenix Inverter 24V 375VA 230V'; break; case '0xA214': $ve_modele_retour='Phoenix Inverter 48V 375VA 230V'; break; case '0xA221': $ve_modele_retour='Phoenix Inverter 12V 500VA 230V'; break; case '0xA222': $ve_modele_retour='Phoenix Inverter 24V 500VA 230V'; break; case '0xA224': $ve_modele_retour='Phoenix Inverter 48V 500VA 230V'; break; case '0xA231': $ve_modele_retour='Phoenix Inverter 12V 250VA 230V'; break; case '0xA232': $ve_modele_retour='Phoenix Inverter 24V 250VA 230V'; break; case '0xA234': $ve_modele_retour='Phoenix Inverter 48V 250VA 230V'; break; case '0xA239': $ve_modele_retour='Phoenix Inverter 12V 250VA 120V'; break; case '0xA23A': $ve_modele_retour='Phoenix Inverter 24V 250VA 120V'; break; case '0xA23C': $ve_modele_retour='Phoenix Inverter 48V 250VA 120V'; break; case '0xA241': $ve_modele_retour='Phoenix Inverter 12V 375VA 230V'; break; case '0xA242': $ve_modele_retour='Phoenix Inverter 24V 375VA 230V'; break; case '0xA244': $ve_modele_retour='Phoenix Inverter 48V 375VA 230V'; break; case '0xA249': $ve_modele_retour='Phoenix Inverter 12V 375VA 120V'; break; case '0xA24A': $ve_modele_retour='Phoenix Inverter 24V 375VA 120V'; break; case '0xA24C': $ve_modele_retour='Phoenix Inverter 48V 375VA 120V'; break; case '0xA251': $ve_modele_retour='Phoenix Inverter 12V 500VA 230V'; break; case '0xA252': $ve_modele_retour='Phoenix Inverter 24V 500VA 230V'; break; case '0xA254': $ve_modele_retour='Phoenix Inverter 48V 500VA 230V'; break; case '0xA259': $ve_modele_retour='Phoenix Inverter 12V 500VA 120V'; break; case '0xA25A': $ve_modele_retour='Phoenix Inverter 24V 500VA 120V'; break; case '0xA25C': $ve_modele_retour='Phoenix Inverter 48V 500VA 120V'; break; case '0xA261': $ve_modele_retour='Phoenix Inverter 12V 800VA 230V'; break; case '0xA262': $ve_modele_retour='Phoenix Inverter 24V 800VA 230V'; break; case '0xA264': $ve_modele_retour='Phoenix Inverter 48V 800VA 230V'; break; case '0xA269': $ve_modele_retour='Phoenix Inverter 12V 800VA 120V'; break; case '0xA26A': $ve_modele_retour='Phoenix Inverter 24V 800VA 120V'; break; case '0xA26C': $ve_modele_retour='Phoenix Inverter 48V 800VA 120V'; break; case '0xA271': $ve_modele_retour='Phoenix Inverter 12V 1200VA 230V'; break; case '0xA272': $ve_modele_retour='Phoenix Inverter 24V 1200VA 230V'; break; case '0xA274': $ve_modele_retour='Phoenix Inverter 48V 1200VA 230V'; break; case '0xA279': $ve_modele_retour='Phoenix Inverter 12V 1200VA 120V'; break; case '0xA27A': $ve_modele_retour='Phoenix Inverter 24V 1200VA 120V'; break; case '0xA27C': $ve_modele_retour='Phoenix Inverter 48V 1200VA 120V'; break; default; $ve_modele_retour = 'Inconnu'; break; } return $ve_modele_retour; } # Victron : détermine plein de trucs en fonction du label # Source doc Victron "VE.Direct Protocol" function ve_label2($label, $valeur) { global $config; $veData['label']=$label; $veData['desc']=$label; $veData['value']=$valeur; $veData['units']=''; $veData['screen']=0; $veData['smallScreen']=0; if (in_array($label, $config['www']['dataPrimaire'])) { $veData['screen']=1; } if (in_array($label, $config['www']['dataPrimaireSmallScreen'])) { $veData['smallScreen']=1; } switch ($label) { case 'V': $veData['value']=round($valeur*0.001, 2); $veData['desc']='Tension de la batterie'; $veData['units']='V'; break; case 'VS': $veData['desc']='Auxiliary (starter) voltage'; $veData['value']=$valeur*0.001; $veData['units']='V'; break; case 'VM': $veData['desc']='Mid-point voltage of the battery bank'; $veData['value']=$valeur*0.001; $veData['units']='V'; break; case 'DM': $veData['desc']='Mid-point deviation of the battery bank'; $veData['units']='%'; break; case 'VPV': $veData['desc']='Voltage des panneaux'; $veData['units']='mV'; break; case 'PPV': $veData['desc']='Production des panneaux'; $veData['descShort']='PV'; $veData['units']='W'; break; case 'I': $veData['value']=$valeur*0.001; $veData['desc']='Courant de la batterie'; $veData['units']='A'; break; case 'IL': $veData['value']=$valeur*0.001; $veData['desc']='Courant de charge'; $veData['units']='A'; break; case 'LOAD': $veData['value']=$valeur; $veData['desc']='Charge sortie status'; break; case 'T': $veData['desc']='Température de la batterie'; $veData['units']='°C'; break; case 'P': $veData['desc']='Puissance instantané'; $veData['units']='W'; break; case 'CE': $veData['desc']='Ampères heures consommées'; $veData['value']=$valeur*0.001; $veData['units']='Ah'; break; case 'SOC': $veData['desc']='État de charge'; $veData['value']=$valeur/10; $veData['units']='%'; break; case 'TTG': if ($veData['value'] == '-1') { $veData['value'] = '∞'; } else { $total=$veData['value']*60; $jours=floor($total/86400); $reste=$total%86400; $heures=floor($reste/3600); $reste=$reste%3600; $minutes=floor($reste/60); $secondes=$reste%60; if ($veData['value'] > 1440) { $veData['value'] = $jours . 'j '. $heures. 'h ' . $minutes .'m'; } else { $veData['value'] = '.'.$heures. 'h ' . $minutes .'m'; } } $veData['desc']='Temps restant'; break; case 'Alarm': $veData['desc']='Condition d\'alarme active'; break; case 'Relay': $veData['desc']='Etat du relai'; break; case 'AR': $veData['desc']='Raison de l\'alarme'; switch ($veData['value']) { case 0: $veData['value']= 'Aucune'; break; case 1: $veData['value']= 'Low Voltage'; break; case 2: $veData['value']= 'High Voltage'; break; case 4: $veData['value']= 'Low SOC'; break; case 8: $veData['value']= 'Low Starter Voltage'; break; case 16: $veData['value']= 'High Starter Voltage'; break; case 32: $veData['value']= 'Low Temperature'; break; case 64: $veData['value']= 'High Temperature'; break; case 128: $veData['value']= 'Mid Voltage'; break; case 256: $veData['value']= 'Overload'; break; case 512: $veData['value']= 'DC-ripple'; break; case 1024: $veData['value']= 'Low V AC out'; break; case 2048: $veData['value']= 'High V AC out'; break; } break; case 'H1': $veData['desc']='Profondeur de la décharge la plus profonde'; $veData['value']=$valeur*0.001; $veData['units']='Ah'; break; case 'H2': $veData['desc']='Profondeur de la dernière décharge'; $veData['value']=$valeur*0.001; $veData['units']='Ah'; break; case 'H3': $veData['desc']='Profondeur de la décharge moyenne'; $veData['value']=$valeur*0.001; $veData['units']='Ah'; break; case 'H4': $veData['desc']='Nombre de cycles de charge'; break; case 'H5': $veData['desc']='Nombre de cycles de décharge'; break; case 'H6': $veData['desc']='Cumulative Amp Hours drawn'; $veData['value']=$valeur*0.001; $veData['units']='Ah'; break; case 'H7': $veData['desc']='Tension minimale batterie'; $veData['value']=$valeur*0.001; $veData['units']='V'; break; case 'H8': $veData['desc']='Tension maximale de la batterie'; $veData['value']=$valeur*0.001; $veData['units']='V'; break; case 'H9': $veData['desc']='Nombre de secondes depuis la dernière charge complète'; $veData['units']='s'; break; case 'H10': $veData['desc']='Nombre de synchronisations automatiques'; break; case 'H11': $veData['desc']='Nombre d\'alarmes de tension faible'; break; case 'H12': $veData['desc']='Nombre d\'alarmes de tension élevée'; break; case 'H13': $veData['desc']='Nombre d\'alarmes de tension faible sur l`auxiliaire'; break; case 'H14': $veData['desc']='Nombre d\'alarmes de tension élevée sur l`auxiliaire'; break; case 'H15': $veData['desc']='Tension minimale batterie auxiliaire'; $veData['value']=$valeur*0.001; $veData['units']='V'; break; case 'H16': $veData['desc']='Tension maximale de la batterie auxiliaire'; $veData['value']=$valeur*0.001; $veData['units']='V'; break; case 'H17': $veData['desc']='Quantité d\'énergie déchargée'; $veData['value']=$valeur*0.01; $veData['units']='kWh'; break; case 'H18': $veData['desc']='Quantité d\'énergie chargée'; $veData['value']=$valeur*0.01; $veData['units']='kWh'; break; case 'H19': $veData['value']=$valeur*0.01; $veData['desc']='Le rendement total'; $veData['units']='kWh'; break; case 'H20': $veData['value']=$valeur*0.01; $veData['desc']='Rendement aujourd\'hui'; $veData['units']='kWh'; break; case 'H21': $veData['desc']='Puissance maximum ce jour'; $veData['units']='W'; break; case 'H22': $veData['value']=$valeur*0.01; $veData['desc']='Rendement hier'; $veData['units']='kWh'; break; case 'H23': $veData['desc']='Puissance maximum hier'; $veData['units']='W'; break; case 'ERR': $veData['desc']='Présence d\'erreur'; if ($valeur == 0) { $veData['value']='Aucune'; } else { switch ($veData['value']) { case 2: $veData['value'] = 'Battery voltage too high'; break; case 17: $veData['value'] = 'Charger temperature too high'; break; case 18: $veData['value'] = 'Charger over current'; break; case 19: $veData['value'] = 'Charger current reversed'; break; case 20: $veData['value'] = 'Bulk time limit exceeded'; break; case 21: $veData['value'] = 'Current sensor issue (sensor bias/sensor broken)'; break; case 26: $veData['value'] = 'Terminals overheated'; break; case 33: $veData['value'] = 'Input voltage too high (solar panel)'; break; case 34: $veData['value'] = 'Input current too high (solar panel)'; break; case 38: $veData['value'] = 'Input shutdown (due to excessive battery voltage)'; break; case 116: $veData['value'] = 'Factory calibration data lost'; break; case 117: $veData['value'] = 'Invalid/incompatible firmware'; break; case 119: $veData['value'] = 'User settings invalid'; break; default: $veData['value'] = $dataSplit[1]; break; } } break; case 'CS': $veData['desc']='Status de charge'; switch ($veData['value']) { case 0: $veData['value']= 'Off'; break; case 1: $veData['value']= 'Faible puissance'; break; case 2: $veData['value']= 'Fault'; break; case 3: $veData['value']= 'Bulk'; break; case 4: $veData['value']= 'Absorption'; break; case 5: $veData['value']= 'Float'; break; case 9: $veData['value']= 'On'; break; } break; case 'HSDS': $veData['desc']='Numéro de séquence du jour'; break; case 'MODE': $veData['desc']='Device mode'; switch ($veData['value']) { case 2: $veData['value']= 'Inverter'; break; case 4: $veData['value']= 'Off'; break; case 5: $veData['value']= 'Eco'; break; } break; case 'AC_OUT_V': $veData['value']=$valeur*0.01; $veData['desc']='AC output voltage'; $veData['units']='V'; break; case 'AC_OUT_I': $veData['desc']='AC output current'; $veData['value']=$valeur*0.1; $veData['units']='A'; break; case 'WARN': $veData['desc']='Warning reason'; break; } return $veData; } function ve_nom($ve_serial) { return deviceCorrespondance($ve_serial); } function deviceCorrespondance($search) { global $config; $return=$search; foreach ($config['deviceCorrespondance'] as $id => $nom) { if ($search == $id) { $return=$nom; } } return $return; } # Hack value function ve_value($label, $value) { switch ($label) { case 'Relay': if ($value == 'ON') { $retour = 1; } else { $retour = 0; } break; default; $retour = $value; break; } return $retour; } # Fonction vedirect MPPT / BMV function vedirect_scan() { global $config; trucAdir(4, 'Recherche de périphérique vedirect'); $idDevice=0; foreach (scandir('/dev') as $unDev) { if (substr($unDev, 0, 6) == 'ttyUSB') { trucAdir(4, 'Un périphérique TTY à été trouvé : '.$unDev); unset($vedirect_sortie); unset($vedirect_retour); exec($config['vedirect']['usb']['bin'].' /dev/'.$unDev, $vedirect_sortie, $vedirect_retour); if ($vedirect_retour != 0){ trucAdir(1, 'Erreur à l\'exécution du script '.$config['vedirect']['usb']['bin'].' sur le '.$unDev); } else { // Pour gérer le BMV-600 $BMV600=false; $ve_nom=null; $ve_type='Inconnu'; $ve_modele='Inconnu'; foreach ($vedirect_sortie as $vedirect_ligne) { $vedirect_data = explode(':', $vedirect_ligne); switch ($vedirect_data[0]) { case 'PID': $ve_type=ve_type($vedirect_data[1]); $ve_modele=ve_modele($vedirect_data[1]); break; case 'SER#': $ve_serial=$vedirect_data[1]; $ve_nom=ve_nom($vedirect_data[1]); break; case 'BMV': $ve_type='BMV'; $ve_nom=str_replace(' ', '', $vedirect_data[1]); break; } } trucAdir(3, 'C\'est un '.$ve_type.', modèle "'.$ve_modele.'" du nom de '.$ve_nom); $vedirect_data_formate=''; foreach ($vedirect_sortie as $vedirect_ligne) { $vedirect_data = explode(':', $vedirect_ligne); switch ($ve_type) { case 'MPPT': if (in_array($vedirect_data[0], $config['vedirect']['data_ok']['mppt'])) { # éviter les doublons if (!stristr($vedirect_data_formate, $vedirect_data[0].':')) { trucAdir(5, 'Valeur trouvé : '.$vedirect_data[0].':'.$vedirect_data[1]); if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$vedirect_data[0].':'.ve_value($vedirect_data[0], $vedirect_data[1]); } else { trucAdir(5, 'Doublon, on passe'); } } break; case 'BMV': if (in_array($vedirect_data[0], $config['vedirect']['data_ok']['bmv'])) { # éviter les doublons if (!stristr($vedirect_data_formate, $vedirect_data[0].':')) { trucAdir(5, 'Valeur trouvé : '.$vedirect_data[0].':'.$vedirect_data[1]); if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$vedirect_data[0].':'.ve_value($vedirect_data[0], $vedirect_data[1]); } else { trucAdir(5, 'Doublon, on passe'); } } break; case 'PhoenixInverter': if (in_array($key, $config['vedirect']['data_ok']['phoenix'])) { # éviter les doublons if (!stristr($vedirect_data_formate, $vedirect_data[0].':')) { trucAdir(5, 'Valeur trouvé : '.$vedirect_data[0].':'.$vedirect_data[1]); if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$key.':'.ve_value($vedirect_data[0], $vedirect_data[1]); } else { trucAdir(5, 'Doublon, on passe'); } } break; default: if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$key.':'.ve_value($vedirect_data[0], $vedirect_data[1]); } } trucAdir(3, 'Les données sont formatées comme ceci : '.$vedirect_data_formate ); $vedirect_scan_return[$idDevice]['nom']=$ve_nom; $vedirect_scan_return[$idDevice]['type']=$ve_type; $vedirect_scan_return[$idDevice]['serial']=$ve_serial; $vedirect_scan_return[$idDevice]['modele']=$ve_modele; $vedirect_scan_return[$idDevice]['data']=$vedirect_data_formate; $idDevice++; } } } return $vedirect_scan_return; } function vedirect_parse_arduino($data) { global $config; // Pour gérer le BMV-600 $BMV600=false; $ve_nom=null; $ve_type='Inconnu'; $ve_modele='Inconnu'; $ve_serial='Inconnu'; foreach ($data as $key => $value) { switch ($key) { case 'PID': $ve_type=ve_type($value); $ve_modele=ve_modele($value); break; case 'SER#': $ve_serial=$value; $ve_nom=ve_nom($value); break; case 'BMV': $ve_type='BMV'; $ve_nom=$value; break; } } trucAdir(3, 'C\'est un '.$ve_type.', modèle "'.$ve_modele.'" du nom de '.$ve_nom); $vedirect_data_formate=''; krsort($data); foreach ($data as $key => $value) { switch ($ve_type) { case 'MPPT': if (in_array($key, $config['vedirect']['data_ok']['mppt'])) { # éviter les doublons if (!stristr($vedirect_data_formate, "$key:$value")) { trucAdir(5, 'Valeur trouvé : '.$key.':'.$value); if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$key.':'.ve_value($key, $value); } else { trucAdir(5, 'Doublon, on passe'); } } break; case 'BMV': if (in_array($key, $config['vedirect']['data_ok']['bmv'])) { if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$key.':'.ve_value($key, $value); } break; case 'PhoenixInverter': if (in_array($key, $config['vedirect']['data_ok']['phoenix'])) { if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$key.':'.ve_value($key, $value); } break; default: if ($vedirect_data_formate != '') { $vedirect_data_formate = $vedirect_data_formate.','; } $vedirect_data_formate = $vedirect_data_formate.$key.':'.ve_value($key, $value); } } trucAdir(3, 'Les données sont formatées comme ceci : '.$vedirect_data_formate ); $vedirect_scan_return['nom']=$ve_nom; $vedirect_scan_return['type']=$ve_type; $vedirect_scan_return['serial']=$ve_serial; $vedirect_scan_return['modele']=$ve_modele; $vedirect_scan_return['data']=$vedirect_data_formate; return $vedirect_scan_return; } # Fonction de debug function trucAdir($niveau, $msg) { global $config; if ($config['printMessage'] >= $niveau) { if (isset($_SERVER['SERVER_NAME'])) { echo ''; } else { echo date('c') . ' [' . $niveau . '] - ' . $msg."\n"; } } if ($config['printMessageLogfile'] != false) { if (is_file($config['printMessageLogfile']) && filesize($config['printMessageLogfile']) > 10000000) { unlink($config['printMessageLogfile']); } if (! is_file($config['printMessageLogfile'])) { touch($config['printMessageLogfile']); if (substr(sprintf('%o', fileperms($config['printMessageLogfile'])), -3) != '777') { chmod($config['printMessageLogfile'], 0777); } } file_put_contents($config['printMessageLogfile'], date('c') . ' [' . $niveau . '] - ' . $_SERVER['SCRIPT_NAME']. ' - ' . $msg . "\n", FILE_APPEND); } } # Récupérer les informations de la sonde de température function Temperature_USB($TEMPERV14_BIN) { global $config; # Exécussion du programme pour récupérer les inforamtions de la sonde de température exec($TEMPERV14_BIN, $temperv14_sortie, $temperv14_retour); if ($temperv14_retour != 0){ trucAdir(3, 'La sonde de température n\'est probablement pas connecté.'); trucAdir(5, 'Erreur '.$temperv14_retour.' à l\'exécussion du programme .'.$TEMPERV14_BIN); $temperature_retour='NODATA'; } else { trucAdir(4, 'La sonde de température indique '.$temperv14_sortie[0].'°C, il y aura peut être correction.'); $temperature_retour=$temperv14_sortie[0]; } return $temperature_retour; } function Amp_USB($bin) { global $config; $consommation_retour='NODATA'; for ($i = 1; $i <= 3; $i++) { trucAdir(3, 'Tentative '.$i.' de récupération de la sonde '); exec($bin.' | sed "s/A//" 2>/dev/null', $exec_consommation_sortie, $exec_consommation_retour); if ($exec_consommation_retour != 0){ trucAdir(3, 'L\'amphèrmètre n\'est probablement pas connecté.'); trucAdir(5, 'Erreur '.$exec_consommation_retour.' avec pour sortie .'.$exec_consommation_sortie); } else { if ($exec_consommation_sortie[0] != '') { trucAdir(3, 'Trouvé à la tentative '.$i.' : la La consommation trouvé est '.$exec_consommation_sortie[0].'A'); $re = '/^[0-9][0-9]+.[0-9]$/'; if (!preg_match_all($re, $exec_consommation_sortie[0])) { trucAdir(5, 'La vérification par expression régulière à échoué ('.$re.')'); } else { $conso_en_w=$exec_consommation_sortie[0]*230; trucAdir(1, 'La consommation est de '.$exec_consommation_sortie[0].'A soit '.$conso_en_w.'W'); if ($conso_en_w > $config['consoPlafond']) { trucAdir(1, 'C`est certainement une erreur, le plafond possible est atteind'); } else { $consommation_retour=$exec_consommation_sortie[0]; } } break; } else { trucAdir(5, 'Echec à la tentative '.$i.' : la La consommation trouvé est null'); sleep(1); } } } return $consommation_retour; } // Class source : http://abhinavsingh.com/how-to-use-locks-in-php-cron-jobs-to-avoid-cron-overlaps/ class cronHelper { private static $pid; function __construct() {} function __clone() {} private static function isrunning() { $pids = explode(PHP_EOL, `ps -e | awk '{print $1}'`); if(in_array(self::$pid, $pids)) return TRUE; return FALSE; } public static function lock() { global $config; global $argv; $lock_file = $config['emoncms']['lockFile']; if(file_exists($lock_file)) { //return FALSE; // Is running? self::$pid = file_get_contents($lock_file); if(self::isrunning()) { error_log("==".self::$pid."== Already in progress..."); return FALSE; } else { error_log("==".self::$pid."== Previous job died abruptly..."); } } self::$pid = getmypid(); file_put_contents($lock_file, self::$pid); //error_log("==".self::$pid."== Lock acquired, processing the job..."); return self::$pid; } public static function unlock() { global $argv; global $config; $lock_file = $config['emoncms']['lockFile']; if(file_exists($lock_file)) unlink($lock_file); //error_log("==".self::$pid."== Releasing lock..."); return TRUE; } } // Check cache expire function checkCacheTime($file) { global $config; if (!is_dir($config['cache']['dir'])) { mkdir($config['cache']['dir'], 0777); } if (!is_file($file)) { return false; } else if (filemtime($file)+$config['cache']['expir'] < time()) { return false; } else if (isset($_GET['nocache'])) { return false; } else { return true; } } # Domo gen json file function genDefaultJsonFile($type) { global $config; if ($type == 'etat') { $filePath = $config['domo']['jsonFile']['etatPath']; } elseif ($type == 'mod') { $filePath = $config['domo']['jsonFile']['modPath']; } $relay[] = null; for ($i = 1; $i <= $config['domo']['relayNb']; $i++) { if ($type == 'etat') { $relay[$type][$i] = 0; } else { $relay[$type][$i] = 1; } } file_put_contents($filePath, json_encode($relay[$type])); } +# Download weather +function getDataOpenWeathert() { + global $config; + $cacheFile=$config['cache']['dir'].'/openweathermap-forecast.json'; + if (!is_file($cacheFile) || filemtime($cacheFile)+$config['weather']['cache'] < time()) { + $opts = array('http' => + array( + 'method' => 'GET', + 'timeout' => 60 + ) + ); + $context = stream_context_create($opts); + $result = file_get_contents('https://api.openweathermap.org/data/2.5/forecast?id='.$config['weather']['openweathermapCityId'].'&appid='.$config['weather']['openweathermapAppId'], false, $context); + if ($result != '') { + file_put_contents($cacheFile, $result); + } + } + if (is_file($cacheFile)) { + $return = file_get_contents($cacheFile); + } else { + $return = ''; + } + return $return; +} ?> diff --git a/www/assets/css/style.css b/www/assets/css/style.css index edcfb61..4d9956c 100644 --- a/www/assets/css/style.css +++ b/www/assets/css/style.css @@ -1,326 +1,342 @@ /* Generated by http://www.cssportal.com */ @import url("reset.css"); body { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 13px; color:#333; } p { padding: 10px; } - +b { + font-weight: bold; +} #wrapper { margin: 0 auto; width: 1000px; } #headerwrap { width: 1000px; float: left; margin: 0 auto; } #header { color: #fff; background: #4d394b; border-radius: 10px; border: 1px solid #392537; margin: 5px; } #header a { color: #fff; } #header h1 { font-size: 130%; padding: 10px; } #header nav{ display:block; float:right; margin:10px 0 0 0; padding:20px 0; color:#ffa500; } #header nav ul{ padding:0 20px; } #header nav li{ display:inline; margin-right:25px; text-transform:uppercase; } #header nav li.last{ margin-right:0; } #header nav li a{ text-decoration:none; color:#ffa500; } #header nav li a:hover{ color:#fff; } #contentwrap { width: 1000; float: left; margin: 0 auto; } #content { background: #e5e4e0; border-radius: 10px; border: 1px solid #d1d0cc; margin: 5px; padding: 10px; } progress { background: #e5e4e0; border: none; width: 200px; } progress.jaugeRouge::-moz-progress-bar { background: #FF785B; } progress.jaugeOrange::-moz-progress-bar { background: #FFBB3E; } progress.jaugeVerte::-moz-progress-bar { background: #76D176; } progress.jaugeBleu::-moz-progress-bar { background: #8590F7; } .waitFirst { width: 100%; text-align:center; } .box { margin: 8px; width: 300px; background-color: #fff; border-radius: 10px 10px 0 0; float: left; } .box .plus { display: none; } .box .plusboutton, .box .moinsboutton { text-align: center; font-size: 80%; cursor: pointer; } .box .moinsboutton { display: none; } .box .title { border-radius: 10px 10px 0 0; background-color:#ffa500; padding: 5px; } .box .boxvaleur { padding: 5px; border-bottom: 1px solid #BCB7B7; color : #6B6B6B; } +.boxvaleur ul { + list-style: circle; +} +.boxvaleur li { + margin-left: 10px; + margin-top: 2px; + margin-bottom: 2px; +} .box h3 { font-size: 80%; } .box .ppv, .box .ppvt { height: 28px; padding-left: 38px; background-image: url("../images/PPV.png"); background-position: left top; background-repeat: no-repeat; } .box .vbat { height: 28px; padding-left: 38px; background-image: url("../images/VBAT.png"); background-position: left top; background-repeat: no-repeat; } .box .cs, .box .soc { height: 28px; padding-left: 38px; background-image: url("../images/CS.png"); background-position: left top; background-repeat: no-repeat; } .box .err, .box .ar { height: 28px; padding-left: 38px; background-image: url("../images/ERR.png"); background-position: left top; background-repeat: no-repeat; } .souligner { color: red; font-weight: bold; } .box .temp { height: 28px; padding-left: 38px; background-image: url("../images/TEMP.png"); background-position: left top; background-repeat: no-repeat; } .box .conso { height: 28px; padding-left: 38px; background-image: url("../images/CONSO.png"); background-position: left top; background-repeat: no-repeat; } .box .boxvaleur { margin: 3px; } #footerwrap { width: 1000px; float: left; margin: 0 auto; clear: both; } #footer { color: #fff; background: #4d394b; border-radius: 10px; border: 1px solid #392537; margin: 5px; } #footer a { color: #fff; text-decoration:none; } .footer_right { float: right; } @media screen and (max-width: 1000px) { #headerwrap { width: 100%; } #wrapper { width: 100%; } #footerwrap { width: 100%; } } @media screen and (max-width: 600px) { .box .plusplus { display: none; } #header { margin: 2px; } #header h1 { text-align: center; } #header p { display: none; } #header nav{ display:none; } } #box_domo .boxvaleur{ padding-bottom: 20px; border-bottom: none; } +#box_weatherProdForcast b.prodOk { + color:#4EA541; +} +#box_weatherProdForcast b.prodKo { + color:#C14C4C; +} .relayEtat { margin: 5px; padding: 5px; border-radius: 20px; border: 1px solid #AFAFAF; width: 5%; float: left; } .relayMod { padding: 10px; border-radius: 15px; border: 1px solid #AFAFAF; width: 75%; float: right; } .relayModButtons { float: right; } .relayChange { padding: 5px; border-radius: 15px; border: 1px solid #AFAFAF; } .etatNull { background-color: #C0C0C0; } .etat0{ background-color: #FFFFFF; } .etat1{ background-color: #FF9999; } .modNull{ background-color: #C0C0C0; } .mod0{ background-color: #FF9999; } .mod1{ background-color: #FFC042; } .mod2{ background-color: #FFC042; } .mod3{ background-color: #7BDF7B; } .relayChange.mod0 { color: #FF9999; background-color: #FFFFFF; } .relayChange.mod1 { color: #FFC042; background-color: #FFFFFF; } .relayChange.mod3 { color: #7BDF7B; background-color: #FFFFFF; } .requestWait { display: none; } .requestWaitList { display: none; } .formPassword { text-align: center; margin-top: 30px; margin-bottom: 30px; } #scriptEditList h1 { font-size: 180%; margin: 10px; } #scriptEditList h2{ font-size: 140%; margin: 10px; } #scriptEditList li { margin: 10px; } .exampleScriptsDesc { border-radius: 10px; border: 1px solid #2789D8; padding: 10px; } diff --git a/www/index.php b/www/index.php index 0d853db..aabb9d2 100755 --- a/www/index.php +++ b/www/index.php @@ -1,727 +1,831 @@ '.$title.''; } else { ?> Pv Monit v<?= VERSION ?>
    $value) { if ($name != 'submit') { $config_a_modifier['user'][$name]['value'] = $value; // Pour valider le nouvel affichage $config['user'][$name]['value'] = $value; } } if (isset($cloud)) { touch($config_dir.$config_file.'.change'); } else { @copy($config_dir.$config_file, $config_dir.$config_file.'.'.time()); } if (!yaml_emit_file($config_dir.$config_file, $config_a_modifier)) { echo 'Erreur à l\'enregistrement de la configuration'; } } echo ''; } ?>
    Patience...
    '; echo '
    Erreur
    '; echo '

    Heure du système :

    '; echo ''; echo 'incorrect, on ne collecte rien.'; echo ''; echo '
    '; echo '
    '; } ?> + + +
    Domo'; if ($config['www']['domoEdit'] == true) { echo ' - Edit'; } echo '
    '; if ($printDomo == true) { if (empty($cloud)) { if (!is_file($config['domo']['jsonFile']['etatPath'])) { genDefaultJsonFile('etat'); } if (!is_file($config['domo']['jsonFile']['modPath'])) { genDefaultJsonFile('mod'); } echo '
    '; echo '
    Requête en attente :
    '; for ($i = 1; $i <= $config['domo']['relayNb']; $i++) { echo '
    - '.$config['domo']['relayName'][$i].' : Off
    '; echo '
    - '.$config['domo']['relayName'][$i].' : Auto
    '; echo '
    - '.$config['domo']['relayName'][$i].' : On
    '; } echo '
    '; } for ($i = 1; $i <= $config['domo']['relayNb']; $i++) { echo '
    '; echo '
     
    '.$config['domo']['relayName'][$i].' Null Off Auto On
    '; echo '
    '; } echo '


    '; } else { echo '
    '; } echo '
    '; } ?>
    '; echo "Affichage du log ".$config['printMessageLogfile']."\n"; echo "===================================================\n"; $tab = file($config['printMessageLogfile']); for ($i=count($tab); $i >= count($tab)-400; $i=$i-1) { echo $tab[$i]; } echo ''; } ?>
    '; } ?>