From 291ea55e624b9686f2376955e5000c5dcfe6aa51 Mon Sep 17 00:00:00 2001 From: Mathieu Carbou Date: Sun, 19 Jan 2025 01:42:34 +0100 Subject: [PATCH] (ui) New Dashboard UI --- include/i18n/en.h | 150 +-- include/i18n/fr.h | 72 +- include/yasolr_dashboard.h | 47 +- lib/ESPDASHPro | 2 +- lib/MycilaRouter/MycilaRouterOutput.cpp | 4 + lib/MycilaRouter/MycilaRouterOutput.h | 2 +- src/yasolr_dashboard.cpp | 1641 +++++++++++++---------- src/yasolr_router.cpp | 2 +- src/yasolr_web_server.cpp | 4 +- 9 files changed, 1057 insertions(+), 867 deletions(-) diff --git a/include/i18n/en.h b/include/i18n/en.h index 0c7a676c..797adf3c 100644 --- a/include/i18n/en.h +++ b/include/i18n/en.h @@ -4,7 +4,6 @@ */ #pragma once -#define YASOLR_LBL_087 "Network" #define YASOLR_LBL_001 "Application: Name" #define YASOLR_LBL_002 "Application: Model" #define YASOLR_LBL_003 "Application: Version" @@ -16,24 +15,28 @@ #define YASOLR_LBL_009 "Device: Heap Memory Used (bytes)" #define YASOLR_LBL_010 "Device: ID" #define YASOLR_LBL_011 "Device: Model" -// #define YASOLR_LBL_012 +#define YASOLR_LBL_012 "Electricity Measurement" #define YASOLR_LBL_013 "Firmware: Build Hash" #define YASOLR_LBL_014 "Firmware: Build Timestamp" #define YASOLR_LBL_015 "Firmware: Filename" #define YASOLR_LBL_016 "Grid: Energy (kWh)" #define YASOLR_LBL_017 "Grid: Energy Returned (kWh)" #define YASOLR_LBL_018 "Grid: Frequency (Hz)" -#define YASOLR_LBL_019 YASOLR_LBL_087 ": Hostname" -#define YASOLR_LBL_020 YASOLR_LBL_087 ": Interface" -#define YASOLR_LBL_021 YASOLR_LBL_087 ": Access Point IP Address" -#define YASOLR_LBL_022 YASOLR_LBL_087 ": Access Point MAC Address" -#define YASOLR_LBL_023 YASOLR_LBL_087 ": Ethernet IP Address" -#define YASOLR_LBL_024 YASOLR_LBL_087 ": Ethernet MAC Address" -#define YASOLR_LBL_025 YASOLR_LBL_087 ": WiFi IP Address" -#define YASOLR_LBL_026 YASOLR_LBL_087 ": WiFi MAC Address" -#define YASOLR_LBL_027 YASOLR_LBL_087 ": WiFi SSID" -#define YASOLR_LBL_028 YASOLR_LBL_087 ": WiFi RSSI (dBm)" -#define YASOLR_LBL_029 YASOLR_LBL_087 ": WiFi Signal (%)" +#define YASOLR_LBL_019 "Network : Hostname" +#define YASOLR_LBL_020 "Network : Interface" +#define YASOLR_LBL_021 "Network : Access Point IP Address" +#define YASOLR_LBL_022 "Network : Access Point MAC Address" +#define YASOLR_LBL_023 "Network : Ethernet IP Address" +#define YASOLR_LBL_024 "Network : Ethernet MAC Address" +#define YASOLR_LBL_025 "Network : WiFi IP Address" +#define YASOLR_LBL_026 "Network : WiFi MAC Address" +#define YASOLR_LBL_027 "Network : WiFi SSID" +#define YASOLR_LBL_028 "Network : WiFi RSSI (dBm)" +#define YASOLR_LBL_029 "Network : WiFi Signal (%)" +#define YASOLR_LBL_030 "Relay: Output 1 Bypass Relay Switch Count" +#define YASOLR_LBL_031 "Relay: Output 2 Bypass Relay Switch Count" +#define YASOLR_LBL_032 "Relay: Relay 1 Switch Count" +#define YASOLR_LBL_033 "Relay: Relay 2 Switch Count" #define YASOLR_LBL_034 "Time" #define YASOLR_LBL_035 "Uptime" #define YASOLR_LBL_036 "Routed Power" @@ -45,12 +48,12 @@ #define YASOLR_LBL_042 "Router Resistance" #define YASOLR_LBL_043 "Routed Energy" #define YASOLR_LBL_044 "Grid Power" -#define YASOLR_LBL_048 "Temperature" -#define YASOLR_LBL_045 "Router " YASOLR_LBL_048 +#define YASOLR_LBL_045 "Router Temperature" #define YASOLR_LBL_046 "Output 1" #define YASOLR_LBL_047 "Status" -#define YASOLR_LBL_050 "Dimmer" +#define YASOLR_LBL_048 "Temperature" #define YASOLR_LBL_049 "Remove Server Certificate" +#define YASOLR_LBL_050 "Dimmer" #define YASOLR_LBL_051 "Bypass" #define YASOLR_LBL_052 "Power" #define YASOLR_LBL_053 "Apparent Power" @@ -60,25 +63,25 @@ #define YASOLR_LBL_057 "Current" #define YASOLR_LBL_058 "Resistance" #define YASOLR_LBL_059 "Energy" -#define YASOLR_LBL_060 YASOLR_LBL_050 " Automatic Control" +#define YASOLR_LBL_060 "Dimmer Automatic Control" #define YASOLR_LBL_061 "Excess Power Limiter (W)" #define YASOLR_LBL_062 "Dimmer Limiter" -#define YASOLR_LBL_063 YASOLR_LBL_050 " " YASOLR_LBL_048 " Limiter (°C)" +#define YASOLR_LBL_063 "Dimmer Temperature Limiter (°C)" #define YASOLR_LBL_064 "Bypass Automatic Control" -#define YASOLR_LBL_065 "Bypass Start " YASOLR_LBL_048 " (°C)" -#define YASOLR_LBL_066 "Bypass Stop " YASOLR_LBL_048 " (°C)" +#define YASOLR_LBL_065 "Bypass Start Temperature (°C)" +#define YASOLR_LBL_066 "Bypass Stop Temperature (°C)" #define YASOLR_LBL_067 "Bypass Start Time" #define YASOLR_LBL_068 "Bypass Stop Time" #define YASOLR_LBL_069 "Bypass Week Days" #define YASOLR_LBL_070 "Output 2" #define YASOLR_LBL_071 "Relays" +#define YASOLR_LBL_072 "Relay 1 Automatic Control: Connected Load (Watts)" +#define YASOLR_LBL_073 "Relay 1 Manual Control" #define YASOLR_LBL_074 "Relay 1" -#define YASOLR_LBL_072 YASOLR_LBL_074 " Automatic Control: Connected Load (Watts)" -#define YASOLR_LBL_073 YASOLR_LBL_074 " Manual Control" +#define YASOLR_LBL_075 "Relay 2 Automatic Control: Connected Load (Watts)" +#define YASOLR_LBL_076 "Relay 2 Manual Control" #define YASOLR_LBL_077 "Relay 2" -#define YASOLR_LBL_075 YASOLR_LBL_077 " Automatic Control: Connected Load (Watts)" -#define YASOLR_LBL_076 YASOLR_LBL_077 " Manual Control" -#define YASOLR_LBL_078 "Management" +#define YASOLR_LBL_078 "System" #define YASOLR_LBL_079 "Configuration Backup" #define YASOLR_LBL_080 "Configuration Restore" #define YASOLR_LBL_081 "Restart in SafeBoot mode" @@ -87,6 +90,7 @@ #define YASOLR_LBL_084 "Console" #define YASOLR_LBL_085 "Energy Reset" #define YASOLR_LBL_086 "Factory Reset" +#define YASOLR_LBL_087 "Network" #define YASOLR_LBL_088 "Admin Password" #define YASOLR_LBL_089 "NTP Server" #define YASOLR_LBL_090 "Timezone" @@ -99,26 +103,24 @@ #define YASOLR_LBL_097 "Port" #define YASOLR_LBL_098 "Username" #define YASOLR_LBL_099 "Password" -#define YASOLR_LBL_100 "SSL / TLS" +#define YASOLR_LBL_100 "Encryption (SSL / TLS)" #define YASOLR_LBL_101 "Server Certificate (PEM)" #define YASOLR_LBL_102 "Publish Interval" #define YASOLR_LBL_103 "Base Topic" #define YASOLR_LBL_104 "Home Assistant Integration" -#define YASOLR_LBL_105 "Home Assistant Discovery Topic" -#define YASOLR_LBL_106 "Grid Voltage MQTT Topic" -#define YASOLR_LBL_107 "Grid Power MQTT Topic" +#define YASOLR_LBL_105 "Discovery Topic" +#define YASOLR_LBL_106 "Grid Voltage" +#define YASOLR_LBL_107 "Grid Electricity and Measurements" #define YASOLR_LBL_108 "GPIO" #define YASOLR_LBL_109 "Unknown" #define YASOLR_LBL_110 "No electricity" -#define YASOLR_LBL_127 "Display" -#define YASOLR_LBL_111 YASOLR_LBL_127 " SCL (CLOCK)" -#define YASOLR_LBL_112 YASOLR_LBL_127 " SDA (DATA)" +#define YASOLR_LBL_111 "Display SCL (CLOCK)" +#define YASOLR_LBL_112 "Display SDA (DATA)" #define YASOLR_LBL_113 "Disconnected" #define YASOLR_LBL_114 "Read error" #define YASOLR_LBL_115 "Disabled" -#define YASOLR_LBL_128 "JSY" -#define YASOLR_LBL_116 YASOLR_LBL_128 " (TX) Serial RX" -#define YASOLR_LBL_117 YASOLR_LBL_128 " (RX) Serial TX" +#define YASOLR_LBL_116 "JSY (TX) Serial RX" +#define YASOLR_LBL_117 "JSY (RX) Serial TX" #define YASOLR_LBL_118 "LED Green" #define YASOLR_LBL_119 "LED Red" #define YASOLR_LBL_120 "LED Yellow" @@ -127,44 +129,46 @@ #define YASOLR_LBL_123 "Pending" #define YASOLR_LBL_124 "Restart required / Failed to start" #define YASOLR_LBL_125 "Zero-Cross Detection" -#define YASOLR_LBL_126 "Hardware" +#define YASOLR_LBL_126 "GPIO Assignments" +#define YASOLR_LBL_127 "Display" +#define YASOLR_LBL_128 "JSY" #define YASOLR_LBL_129 "LEDs" #define YASOLR_LBL_130 "Enabled" -#define YASOLR_LBL_131 YASOLR_LBL_046 " Dimmer" -#define YASOLR_LBL_132 YASOLR_LBL_046 " DS18" -#define YASOLR_LBL_133 YASOLR_LBL_046 " PZEM" -#define YASOLR_LBL_134 YASOLR_LBL_046 " Bypass Relay" -#define YASOLR_LBL_135 YASOLR_LBL_070 " Dimmer" -#define YASOLR_LBL_136 YASOLR_LBL_070 " DS18" -#define YASOLR_LBL_137 YASOLR_LBL_070 " PZEM" -#define YASOLR_LBL_138 YASOLR_LBL_070 " Bypass Relay" -#define YASOLR_LBL_139 "Router DS18" -#define YASOLR_LBL_140 YASOLR_LBL_126 " Config" +#define YASOLR_LBL_131 "'I/O' means Input and Output, 'Input' means Input only. Set to '-1' to disable the mapping." +#define YASOLR_LBL_132 "DS18" +#define YASOLR_LBL_133 "PZEM Measurement" +#define YASOLR_LBL_134 "Bypass Relay" +#define YASOLR_LBL_135 "Router" +#define YASOLR_LBL_136 "Dimmer Configuration" +#define YASOLR_LBL_137 "Bypass Configuration" +#define YASOLR_LBL_138 "Output 1 Config" +#define YASOLR_LBL_139 "Output 2 Config" +#define YASOLR_LBL_140 "Connected Load" #define YASOLR_LBL_141 "Nominal Grid Frequency (Hz)" -#define YASOLR_LBL_142 YASOLR_LBL_127 " Speed" -#define YASOLR_LBL_143 YASOLR_LBL_127 " Type" -#define YASOLR_LBL_144 YASOLR_LBL_127 " Rotation (°)" -#define YASOLR_LBL_145 YASOLR_LBL_046 " Resistance (Ω)" -#define YASOLR_LBL_146 YASOLR_LBL_070 " Resistance (Ω)" -#define YASOLR_LBL_147 YASOLR_LBL_046 " PZEM Pairing" -#define YASOLR_LBL_148 YASOLR_LBL_070 " PZEM Pairing" -#define YASOLR_LBL_149 YASOLR_LBL_046 " Bypass Relay Type" -#define YASOLR_LBL_150 YASOLR_LBL_070 " Bypass Relay Type" -#define YASOLR_LBL_151 YASOLR_LBL_074 " Type" -#define YASOLR_LBL_152 YASOLR_LBL_077 " Type" +#define YASOLR_LBL_142 "Display Speed" +#define YASOLR_LBL_143 "Display Type" +#define YASOLR_LBL_144 "Display Rotation (°)" +#define YASOLR_LBL_145 "Resistance (Ω)" +// #define YASOLR_LBL_146 "Output 2 Resistance (Ω)" +#define YASOLR_LBL_147 "Output 1 PZEM Pairing" +#define YASOLR_LBL_148 "Output 2 PZEM Pairing" +// #define YASOLR_LBL_149 "Output 1 Bypass Relay Type" +// #define YASOLR_LBL_150 "Output 2 Bypass Relay Type" +#define YASOLR_LBL_151 "Type" +// #define YASOLR_LBL_152 "Relay 2 Type" #define YASOLR_LBL_153 "Duplicate" #define YASOLR_LBL_154 "Invalid" #define YASOLR_LBL_155 "Input" #define YASOLR_LBL_156 "I/O" -#define YASOLR_LBL_157 YASOLR_LBL_128 " Remote UDP (msg/s)" -// #define YASOLR_LBL_158 -#define YASOLR_LBL_159 "PID Controller" +#define YASOLR_LBL_157 "JSY Remote UDP (msg/s)" +#define YASOLR_LBL_158 "NTP" +#define YASOLR_LBL_159 "PID" #define YASOLR_LBL_160 "Proportional Mode" #define YASOLR_LBL_161 "Derivative Mode" #define YASOLR_LBL_162 "Integral Correction" +#define YASOLR_LBL_163 "Setpoint (Target Grid Power in W)" #define YASOLR_LBL_164 "Output Min (W)" #define YASOLR_LBL_165 "Output Max (W)" -#define YASOLR_LBL_163 "Setpoint (Target Grid Power in W)" #define YASOLR_LBL_166 "Kp" #define YASOLR_LBL_167 "Ki" #define YASOLR_LBL_168 "Kd" @@ -176,28 +180,24 @@ #define YASOLR_LBL_174 "P Term (W)" #define YASOLR_LBL_175 "I Term (W)" #define YASOLR_LBL_176 "D Term (W)" -// #define YASOLR_LBL_177 -#define YASOLR_LBL_178 YASOLR_LBL_083 " Information" -// #define YASOLR_LBL_179 +#define YASOLR_LBL_177 "Hardware" +#define YASOLR_LBL_178 "Debug Information" +#define YASOLR_LBL_179 "Optional MQTT Topic Subscriptions" #define YASOLR_LBL_180 "Not paired" -#define YASOLR_LBL_181 YASOLR_LBL_046 " " YASOLR_LBL_048 " MQTT Topic" -#define YASOLR_LBL_182 YASOLR_LBL_070 " " YASOLR_LBL_048 " MQTT Topic" -#define YASOLR_LBL_183 YASOLR_LBL_046 " Dimmer Min/Max Remapping" -#define YASOLR_LBL_184 YASOLR_LBL_070 " Dimmer Min/Max Remapping" +#define YASOLR_LBL_181 "Output 1 Temperature" +#define YASOLR_LBL_182 "Output 2 Temperature" +#define YASOLR_LBL_183 "Min/Max Remapping" +// #define YASOLR_LBL_184 "Output 2 Dimmer Min/Max Remapping" #define YASOLR_LBL_185 "Restart required!" -#define YASOLR_LBL_186 "Output Resistance Calibration" +#define YASOLR_LBL_186 "Resistance Calibration" #define YASOLR_LBL_187 "JSY Remote" -#define YASOLR_LBL_030 "Relay: " YASOLR_LBL_046 " Bypass Relay Switch Count" -#define YASOLR_LBL_031 "Relay: " YASOLR_LBL_070 " Bypass Relay Switch Count" -#define YASOLR_LBL_032 "Relay: " YASOLR_LBL_074 " Switch Count" -#define YASOLR_LBL_033 "Relay: " YASOLR_LBL_077 " Switch Count" #define YASOLR_LBL_188 "Static IP Address" #define YASOLR_LBL_189 "Subnet Mask" #define YASOLR_LBL_190 "Gateway" #define YASOLR_LBL_191 "DNS Server" #define YASOLR_LBL_192 "Device: Reboot Reason" -#define YASOLR_LBL_193 YASOLR_LBL_046 " Dimmer Type" -#define YASOLR_LBL_194 YASOLR_LBL_070 " Dimmer Type" +// #define YASOLR_LBL_193 "Dimmer Type" +// #define YASOLR_LBL_194 "Output 2 Dimmer Type" // #define YASOLR_LBL_195 // #define YASOLR_LBL_196 // #define YASOLR_LBL_197 diff --git a/include/i18n/fr.h b/include/i18n/fr.h index 9ff5a451..cf7eaaf1 100644 --- a/include/i18n/fr.h +++ b/include/i18n/fr.h @@ -15,7 +15,7 @@ #define YASOLR_LBL_009 "Micro-contrôleur: Mémoire Heap: utilisée (bytes)" #define YASOLR_LBL_010 "Micro-contrôleur: ID" #define YASOLR_LBL_011 "Micro-contrôleur: Modèle" -// #define YASOLR_LBL_012 +#define YASOLR_LBL_012 "Mesure électrique" #define YASOLR_LBL_013 "Micro-logiciel: Hachage de construction" #define YASOLR_LBL_014 "Micro-logiciel: Date de construction" #define YASOLR_LBL_015 "Micro-logiciel: Nom de fichier" @@ -38,7 +38,7 @@ #define YASOLR_LBL_032 "Relais: Déclenchements relais 1" #define YASOLR_LBL_033 "Relais: Déclenchements relais 2" #define YASOLR_LBL_034 "Temps" -#define YASOLR_LBL_035 "Temps de fonctionnement" +#define YASOLR_LBL_035 "Durée de fonctionnement" #define YASOLR_LBL_036 "Puissance routée" #define YASOLR_LBL_037 "Puissance apparente routée" #define YASOLR_LBL_038 "Facteur de puissance routeur" @@ -47,7 +47,7 @@ #define YASOLR_LBL_041 "Intensité routée" #define YASOLR_LBL_042 "Résistance totale connectée" #define YASOLR_LBL_043 "Énergie totale routée" -#define YASOLR_LBL_044 "Puissance réseau électrique" +#define YASOLR_LBL_044 "Puissance réseau" #define YASOLR_LBL_045 "Température du routeur" #define YASOLR_LBL_046 "Sortie 1" #define YASOLR_LBL_047 "État" @@ -81,7 +81,7 @@ #define YASOLR_LBL_075 "Contrôle automatique du relais 2: Charge connectée (Watts)" #define YASOLR_LBL_076 "Contrôle manuel du relais 2" #define YASOLR_LBL_077 "Relais 2" -#define YASOLR_LBL_078 "Gestion" +#define YASOLR_LBL_078 "Système" #define YASOLR_LBL_079 "Backup de la configuration" #define YASOLR_LBL_080 "Restauration de la configuration" #define YASOLR_LBL_081 "Redémarrer en mode SafeBoot" @@ -103,14 +103,14 @@ #define YASOLR_LBL_097 "Port" #define YASOLR_LBL_098 "Nom d'utilisateur" #define YASOLR_LBL_099 "Mot de passe" -#define YASOLR_LBL_100 "SSL / TLS" +#define YASOLR_LBL_100 "Encryption (SSL / TLS)" #define YASOLR_LBL_101 "Certificat serveur (PEM)" #define YASOLR_LBL_102 "Interval de publication" #define YASOLR_LBL_103 "Topic de base" #define YASOLR_LBL_104 "Intégration Home Assistant" -#define YASOLR_LBL_105 "Topic de découverte Home Assistant" -#define YASOLR_LBL_106 "Topic MQTT pour la tension réseau" -#define YASOLR_LBL_107 "Topic MQTT pour la puissance réseau" +#define YASOLR_LBL_105 "Topic de découverte" +#define YASOLR_LBL_106 "Tension réseau" +#define YASOLR_LBL_107 "Réseau électrique et mesures" #define YASOLR_LBL_108 "GPIO" #define YASOLR_LBL_109 "Inconnu" #define YASOLR_LBL_110 "Pas d'électricité" @@ -129,46 +129,46 @@ #define YASOLR_LBL_123 "En attente" #define YASOLR_LBL_124 "Redémarrage requis / En erreur" #define YASOLR_LBL_125 "Détection de passage par zéro" -#define YASOLR_LBL_126 "Matériel" +#define YASOLR_LBL_126 "Assignations GPIO" #define YASOLR_LBL_127 "Écran" #define YASOLR_LBL_128 "JSY" #define YASOLR_LBL_129 "LEDs" #define YASOLR_LBL_130 "Activé" -#define YASOLR_LBL_131 "Sortie 1: Variateur" -#define YASOLR_LBL_132 "Sortie 1: DS18" -#define YASOLR_LBL_133 "Sortie 1: PZEM" -#define YASOLR_LBL_134 "Sortie 1: Relais Marche forcée" -#define YASOLR_LBL_135 "Sortie 2: Variateur" -#define YASOLR_LBL_136 "Sortie 2: DS18" -#define YASOLR_LBL_137 "Sortie 2: PZEM" -#define YASOLR_LBL_138 "Sortie 2: Relais Marche forcée" -#define YASOLR_LBL_139 "Router DS18" -#define YASOLR_LBL_140 "Configuration du matériel" +#define YASOLR_LBL_131 "'E/S' signifie Entrée/Sortie, 'Entrée' signifie Entrée seulement. Mettre '-1' pour désactiver l'assignation." +#define YASOLR_LBL_132 "DS18" +#define YASOLR_LBL_133 "Mesures PZEM" +#define YASOLR_LBL_134 "Relais marche forcée" +#define YASOLR_LBL_135 "Routeur" +#define YASOLR_LBL_136 "Configuration du variateur" +#define YASOLR_LBL_137 "Configuration de la marche forcée" +#define YASOLR_LBL_138 "Config Sortie 1" +#define YASOLR_LBL_139 "Config Sortie 2" +#define YASOLR_LBL_140 "Charge connectée" #define YASOLR_LBL_141 "Fréquence nominale du réseau (Hz)" #define YASOLR_LBL_142 "Écran: Vitesse" #define YASOLR_LBL_143 "Écran: Type" #define YASOLR_LBL_144 "Écran: Rotation (°)" -#define YASOLR_LBL_145 "Sortie 1: Résistance (Ω)" -#define YASOLR_LBL_146 "Sortie 2: Résistance (Ω)" +#define YASOLR_LBL_145 "Résistance (Ω)" +// #define YASOLR_LBL_146 "Sortie 2: Résistance (Ω)" #define YASOLR_LBL_147 "Sortie 1: Association du PZEM" #define YASOLR_LBL_148 "Sortie 2: Association du Pairing" -#define YASOLR_LBL_149 "Sortie 1: Type de relais (marche forcée)" -#define YASOLR_LBL_150 "Sortie 2: Type de relais (marche forcée)" -#define YASOLR_LBL_151 "Relais 1: Type de relais" -#define YASOLR_LBL_152 "Relais 2: Type de relais" +// #define YASOLR_LBL_149 "Sortie 1: Type de relais (marche forcée)" +// #define YASOLR_LBL_150 "Sortie 2: Type de relais (marche forcée)" +#define YASOLR_LBL_151 "Type" +// #define YASOLR_LBL_152 "Relais 2: Type de relais" #define YASOLR_LBL_153 "Dupliqué" #define YASOLR_LBL_154 "Invalide" #define YASOLR_LBL_155 "Entrée" #define YASOLR_LBL_156 "E/S" #define YASOLR_LBL_157 "JSY Remote UDP: Débit (msg/s)" -// #define YASOLR_LBL_158 -#define YASOLR_LBL_159 "Contrôleur PID" +#define YASOLR_LBL_158 "NTP" +#define YASOLR_LBL_159 "PID" #define YASOLR_LBL_160 "Mode proportionnel" #define YASOLR_LBL_161 "Mode dérivé" #define YASOLR_LBL_162 "Correction d'Intégrale" +#define YASOLR_LBL_163 "Consigne (puissance cible du réseau en W)" #define YASOLR_LBL_164 "Sortie Min (W)" #define YASOLR_LBL_165 "Sortie Max (W)" -#define YASOLR_LBL_163 "Consigne (puissance cible du réseau en W)" #define YASOLR_LBL_166 "Kp" #define YASOLR_LBL_167 "Ki" #define YASOLR_LBL_168 "Kd" @@ -180,14 +180,14 @@ #define YASOLR_LBL_174 "Terme P (W)" #define YASOLR_LBL_175 "Terme I (W)" #define YASOLR_LBL_176 "Terme D (W)" -// #define YASOLR_LBL_177 +#define YASOLR_LBL_177 "Matériel" #define YASOLR_LBL_178 "Informations de debug" -// #define YASOLR_LBL_179 +#define YASOLR_LBL_179 "Souscription optionnelle aux topics MQTT" #define YASOLR_LBL_180 "Non associé" -#define YASOLR_LBL_181 "Topic MQTT pour la température sortie 1" -#define YASOLR_LBL_182 "Topic MQTT pour la température sortie 2" -#define YASOLR_LBL_183 "Redéfinition Min/Max Variateur Sortie 1" -#define YASOLR_LBL_184 "Redéfinition Min/Max Variateur Sortie 2" +#define YASOLR_LBL_181 "Température sortie 1" +#define YASOLR_LBL_182 "Température sortie 2" +#define YASOLR_LBL_183 "Redéfinition Min/Max" +// #define YASOLR_LBL_184 "Redéfinition Min/Max Variateur Sortie 2" #define YASOLR_LBL_185 "Redémarrage requis!" #define YASOLR_LBL_186 "Détection valeur résistances" #define YASOLR_LBL_187 "JSY Remote" @@ -196,8 +196,8 @@ #define YASOLR_LBL_190 "Passerelle" #define YASOLR_LBL_191 "Serveur DNS" #define YASOLR_LBL_192 "Micro-contrôleur: Raison du reboot" -#define YASOLR_LBL_193 "Sortie 1: Type de variateur" -#define YASOLR_LBL_194 "Sortie 2: Type de variateur" +// #define YASOLR_LBL_193 "Type de variateur" +// #define YASOLR_LBL_194 "Sortie 2: Type de variateur" // #define YASOLR_LBL_195 // #define YASOLR_LBL_196 // #define YASOLR_LBL_197 diff --git a/include/yasolr_dashboard.h b/include/yasolr_dashboard.h index 24200531..80f5b907 100644 --- a/include/yasolr_dashboard.h +++ b/include/yasolr_dashboard.h @@ -16,9 +16,9 @@ namespace YaSolR { void initCards(); void updateCards(); void updateCharts(); - void updatePID(); - void resetPID(); - bool pidCharts() const; + void updatePIDCharts(); + void resetPIDCharts(); + bool realTimePIDEnabled() const; private: void _boolConfig(dash::SwitchCard& card, const char* key) { @@ -86,6 +86,19 @@ namespace YaSolR { }); } + template + void _numConfig(dash::TextInputCard& card, const char* key) { + card.onChange([key, &card](const std::optional& value) { + if (value.has_value()) { + config.set(key, dash::to_string(value.value())); + } else { + config.unset(key); + } + card.setValue(config.getFloat(key)); + dashboard.refresh(card); + }); + } + template , bool> = true> void _numConfig(dash::DropdownCard& card, const char* key) { card.onChange([key, &card](const T& value) { @@ -95,15 +108,28 @@ namespace YaSolR { }); } - void _pinConfig(dash::FeedbackTextInputCard& card, const char* key) { - card.onChange([key, &card, this](const std::optional value) { + template + void _numConfig(dash::FeedbackTextInputCard& card, const char* key) { + card.onChange([key, &card](const std::optional& value) { + if (value.has_value()) { + config.set(key, dash::to_string(value.value())); + } else { + config.unset(key); + } + card.setValue(config.getFloat(key)); + dashboard.refresh(card); + }); + } + + template , bool> = true> + void _numConfig(dash::FeedbackTextInputCard& card, const char* key) { + card.onChange([key, &card, this](const std::optional value) { if (value.has_value()) { config.set(key, std::to_string(value.value())); } else { config.unset(key); } card.setValue(config.getInt(key)); - initCards(); dashboard.refresh(card); }); } @@ -133,6 +159,15 @@ namespace YaSolR { }); } + void _rangeConfig(dash::RangeSliderCard& card, const char* keyMin, const char* keyMax) { + card.onChange([keyMin, keyMax, &card](const dash::Range& range) { + config.set(keyMin, std::to_string(range.low())); + config.set(keyMax, std::to_string(range.high())); + card.setValue({static_cast(config.getInt(keyMin)), static_cast(config.getInt(keyMax))}); + dashboard.refresh(card); + }); + } + void _pinout(dash::FeedbackTextInputCard& card, const char* key, std::unordered_map*>& pinout) { int32_t pin = config.getInt(key); card.setValue(pin); diff --git a/lib/ESPDASHPro b/lib/ESPDASHPro index 297afebc..cb54d2af 160000 --- a/lib/ESPDASHPro +++ b/lib/ESPDASHPro @@ -1 +1 @@ -Subproject commit 297afebc7c7a170c3a27aedfbd6ba2123b3d5f6d +Subproject commit cb54d2af662a7afa1fc5bd6635054b1612f48fdb diff --git a/lib/MycilaRouter/MycilaRouterOutput.cpp b/lib/MycilaRouter/MycilaRouterOutput.cpp index bf65dfb2..9d1c1f1c 100644 --- a/lib/MycilaRouter/MycilaRouterOutput.cpp +++ b/lib/MycilaRouter/MycilaRouterOutput.cpp @@ -162,6 +162,10 @@ float Mycila::RouterOutput::autoDivert(float gridVoltage, float availablePowerTo return 0; } + if (isnan(config.calibratedResistance) || config.calibratedResistance <= 0) { + return 0; + } + // maximum power of the load based on the calibrated resistance value const float maxPower = gridVoltage * gridVoltage / config.calibratedResistance; diff --git a/lib/MycilaRouter/MycilaRouterOutput.h b/lib/MycilaRouter/MycilaRouterOutput.h index 57e2a0ff..4133932b 100644 --- a/lib/MycilaRouter/MycilaRouterOutput.h +++ b/lib/MycilaRouter/MycilaRouterOutput.h @@ -43,7 +43,7 @@ namespace Mycila { } Metrics; typedef struct { - float calibratedResistance = 0; + float calibratedResistance = NAN; bool autoDimmer = false; uint8_t dimmerTempLimit = 0; bool autoBypass = false; diff --git a/src/yasolr_dashboard.cpp b/src/yasolr_dashboard.cpp index 51c7f844..ed8a2be3 100644 --- a/src/yasolr_dashboard.cpp +++ b/src/yasolr_dashboard.cpp @@ -14,33 +14,37 @@ #endif #ifdef APP_MODEL_PRO -static const dash::Widget::Size chartSize = {.xs = 12, .sm = 12, .md = 12, .lg = 12, .xl = 12, .xxl = 12}; +static constexpr dash::Widget::Size FULL_SIZE = {.xs = 12, .sm = 12, .md = 12, .lg = 12, .xl = 12, .xxl = 12}; // tabs icons: // https://en.wikipedia.org/wiki/List_of_Unicode_characters#Miscellaneous_Symbols // https://en.wikipedia.org/wiki/List_of_Unicode_characters#Dingbats // tabs are declared early in order to have the smallest IDs that never change -dash::Tab _output1Tab(dashboard, "\u2600 " YASOLR_LBL_046); -dash::Tab _output2Tab(dashboard, "\u2600 " YASOLR_LBL_070); -dash::Tab _relaysTab(dashboard, "\u2600 " YASOLR_LBL_071); -dash::Tab _managementTab(dashboard, "\u2764 " YASOLR_LBL_078); -dash::Tab _networkConfigTab(dashboard, "\u2728 " YASOLR_LBL_087); -dash::Tab _mqttConfigTab(dashboard, "\u2728 " YASOLR_LBL_095); -dash::Tab _pinConfigTab(dashboard, "\u21C6 " YASOLR_LBL_108); -dash::Tab _hardwareEnableTab(dashboard, "\u2699 " YASOLR_LBL_126); -dash::Tab _hardwareConfigTab(dashboard, "\u2699 " YASOLR_LBL_140); -dash::Tab _pidTab(dashboard, "\u2699 " YASOLR_LBL_159); +dash::Tab _output1Tab(dashboard, "\u26A1 " YASOLR_LBL_046); +dash::Tab _output2Tab(dashboard, "\u26A1 " YASOLR_LBL_070); +dash::Tab _relaysTab(dashboard, "\u26A1 " YASOLR_LBL_071); +dash::Tab _pidTab(dashboard, "\u2672 " YASOLR_LBL_159); +dash::Tab _networkTab(dashboard, "\u2601 " YASOLR_LBL_087); +dash::Tab _ntpTab(dashboard, "\u23F2 " YASOLR_LBL_158); +dash::Tab _mqttTab(dashboard, "\u21C6 " YASOLR_LBL_095); +dash::Tab _gpioTab(dashboard, "\u26EC " YASOLR_LBL_108); +dash::Tab _hardwareConfigTab(dashboard, "\u23DA " YASOLR_LBL_177); +dash::Tab _output1ConfigTab(dashboard, "\u2699 " YASOLR_LBL_138); +dash::Tab _output2ConfigTab(dashboard, "\u2699 " YASOLR_LBL_139); +dash::Tab _systemTab(dashboard, "\u26EB " YASOLR_LBL_078); +dash::Tab _debugTab(dashboard, "\u2757 " YASOLR_LBL_083); + #endif int8_t _historyX[YASOLR_GRAPH_POINTS] = {0}; // statistics + dash::StatisticValue _appName(dashboard, YASOLR_LBL_001); dash::StatisticValue _appModel(dashboard, YASOLR_LBL_002); dash::StatisticValue _appVersion(dashboard, YASOLR_LBL_003); dash::StatisticValue _appManufacturer(dashboard, YASOLR_LBL_004); - dash::StatisticValue _deviceBootCount(dashboard, YASOLR_LBL_005); dash::StatisticValue _deviceBootReason(dashboard, YASOLR_LBL_192); dash::StatisticValue _deviceCores(dashboard, YASOLR_LBL_006); @@ -49,38 +53,31 @@ dash::StatisticValue _deviceHeapUsage(dashboard, YASOLR_LBL_008); dash::StatisticValue _deviceHeapUsed(dashboard, YASOLR_LBL_009); dash::StatisticValue _deviceID(dashboard, YASOLR_LBL_010); dash::StatisticValue _deviceModel(dashboard, YASOLR_LBL_011); - dash::StatisticValue _firmwareBuildHash(dashboard, YASOLR_LBL_013); dash::StatisticValue _firmwareBuildTimestamp(dashboard, YASOLR_LBL_014); dash::StatisticValue _firmwareFilename(dashboard, YASOLR_LBL_015); - dash::StatisticValue _gridEnergy(dashboard, YASOLR_LBL_016); dash::StatisticValue _gridEnergyReturned(dashboard, YASOLR_LBL_017); dash::StatisticValue _gridFrequency(dashboard, YASOLR_LBL_018); - dash::StatisticValue _udpMessageRateBuffer(dashboard, YASOLR_LBL_157); - dash::StatisticValue _networkHostname(dashboard, YASOLR_LBL_019); dash::StatisticValue _networkInterface(dashboard, YASOLR_LBL_020); dash::StatisticValue _networkAPIP(dashboard, YASOLR_LBL_021); dash::StatisticValue _networkAPMAC(dashboard, YASOLR_LBL_022); -#ifdef ESPCONNECT_ETH_SUPPORT dash::StatisticValue _networkEthIP(dashboard, YASOLR_LBL_023); dash::StatisticValue _networkEthMAC(dashboard, YASOLR_LBL_024); -#endif dash::StatisticValue _networkWiFiIP(dashboard, YASOLR_LBL_025); dash::StatisticValue _networkWiFiMAC(dashboard, YASOLR_LBL_026); dash::StatisticValue _networkWiFiSSID(dashboard, YASOLR_LBL_027); dash::StatisticValue _networkWiFiRSSI(dashboard, YASOLR_LBL_028); dash::StatisticValue _networkWiFiSignal(dashboard, YASOLR_LBL_029); - dash::StatisticValue _output1RelaySwitchCount(dashboard, YASOLR_LBL_030); dash::StatisticValue _output2RelaySwitchCount(dashboard, YASOLR_LBL_031); dash::StatisticValue _relay1SwitchCount(dashboard, YASOLR_LBL_032); dash::StatisticValue _relay2SwitchCount(dashboard, YASOLR_LBL_033); - dash::StatisticValue _time(dashboard, YASOLR_LBL_034); dash::StatisticValue _uptime(dashboard, YASOLR_LBL_035); + #ifdef APP_MODEL_TRIAL dash::StatisticValue _trialRemainingTime(dashboard, "Trial Remaining Time"); #endif @@ -101,12 +98,10 @@ dash::TemperatureCard _routerDS18State(dashboard, YASOLR_LBL_045); #ifdef APP_MODEL_OSS dash::SwitchCard _relay1Switch(dashboard, YASOLR_LBL_073); dash::SwitchCard _relay2Switch(dashboard, YASOLR_LBL_076); - dash::FeedbackCard _output1State(dashboard, YASOLR_LBL_046); dash::TemperatureCard _output1DS18State(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_048); dash::SliderCard _output1DimmerSlider(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_050, 0.0f, 100.0f, 0.01f, "%"); dash::SwitchCard _output1Bypass(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_051); - dash::FeedbackCard _output2State(dashboard, YASOLR_LBL_070); dash::TemperatureCard _output2DS18State(dashboard, YASOLR_LBL_070 ": " YASOLR_LBL_048); dash::SliderCard _output2DimmerSlider(dashboard, YASOLR_LBL_070 ": " YASOLR_LBL_050, 0.0f, 100.0f, 0.01f, "%"); @@ -123,16 +118,18 @@ dash::BarChart _routerTHDiHistory(dashboard, YASOLR_LBL_039 " ( #ifdef APP_MODEL_OSS dash::SwitchCard _output1PZEMSync(dashboard, YASOLR_LBL_147); dash::SwitchCard _output2PZEMSync(dashboard, YASOLR_LBL_148); -dash::SwitchCard _resistanceCalibration(dashboard, YASOLR_LBL_186); +dash::SwitchCard _output1ResistanceCalibration(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_186); +dash::SwitchCard _output2ResistanceCalibration(dashboard, YASOLR_LBL_070 ": " YASOLR_LBL_186); #endif #ifdef APP_MODEL_PRO +// tab: output 1 + dash::FeedbackCard _output1State(dashboard, YASOLR_LBL_047); dash::TemperatureCard _output1DS18State(dashboard, YASOLR_LBL_048); +dash::SwitchCard _output1DimmerAuto(dashboard, YASOLR_LBL_060); dash::SliderCard _output1DimmerSlider(dashboard, YASOLR_LBL_050, 0.0f, 100.0f, 0.01f, "%"); dash::ProgressCard _output1DimmerSliderRO(dashboard, YASOLR_LBL_050, 0.0f, 100.0f, "%"); -dash::SwitchCard _output1Bypass(dashboard, YASOLR_LBL_051); -dash::FeedbackCard _output1BypassRO(dashboard, YASOLR_LBL_051); dash::EnergyCard _output1Power(dashboard, YASOLR_LBL_052, "W"); dash::EnergyCard _output1ApparentPower(dashboard, YASOLR_LBL_053, "VA"); dash::EnergyCard _output1PowerFactor(dashboard, YASOLR_LBL_054); @@ -141,23 +138,17 @@ dash::EnergyCard _output1Voltage(dashboard, YASOLR_LBL_056, "V"); dash::EnergyCard _output1Current(dashboard, YASOLR_LBL_057, "A"); dash::EnergyCard _output1Resistance(dashboard, YASOLR_LBL_058, "Ω"); dash::EnergyCard _output1Energy(dashboard, YASOLR_LBL_059, "kWh"); -dash::PercentageSliderCard _output1DimmerDutyLimiter(dashboard, YASOLR_LBL_062); -dash::TextInputCard _output1DimmerTempLimiter(dashboard, YASOLR_LBL_063); -dash::TextInputCard _output1DimmerExcessLimiter(dashboard, YASOLR_LBL_061); -dash::SwitchCard _output1DimmerAuto(dashboard, YASOLR_LBL_060); dash::SwitchCard _output1BypassAuto(dashboard, YASOLR_LBL_064); -dash::TextInputCard _output1AutoStartTemp(dashboard, YASOLR_LBL_065); -dash::TextInputCard _output1AutoStoptTemp(dashboard, YASOLR_LBL_066); -dash::TextInputCard _output1AutoStartTime(dashboard, YASOLR_LBL_067); -dash::TextInputCard _output1AutoStoptTime(dashboard, YASOLR_LBL_068); -dash::WeekCard _output1AutoStartWDays(dashboard, YASOLR_LBL_069); +dash::SwitchCard _output1Bypass(dashboard, YASOLR_LBL_051); +dash::FeedbackCard _output1BypassRO(dashboard, YASOLR_LBL_051); + +// tab: output 2 dash::FeedbackCard _output2State(dashboard, YASOLR_LBL_047); dash::TemperatureCard _output2DS18State(dashboard, YASOLR_LBL_048); +dash::SwitchCard _output2DimmerAuto(dashboard, YASOLR_LBL_060); dash::SliderCard _output2DimmerSlider(dashboard, YASOLR_LBL_050, 0.0f, 100.0f, 0.01f, "%"); dash::ProgressCard _output2DimmerSliderRO(dashboard, YASOLR_LBL_050, 0.0f, 100.0f, "%"); -dash::SwitchCard _output2Bypass(dashboard, YASOLR_LBL_051); -dash::FeedbackCard _output2BypassRO(dashboard, YASOLR_LBL_051); dash::EnergyCard _output2Power(dashboard, YASOLR_LBL_052, "W"); dash::EnergyCard _output2ApparentPower(dashboard, YASOLR_LBL_053, "VA"); dash::EnergyCard _output2PowerFactor(dashboard, YASOLR_LBL_054); @@ -166,43 +157,52 @@ dash::EnergyCard _output2Voltage(dashboard, YASOLR_LBL_056, "V"); dash::EnergyCard _output2Current(dashboard, YASOLR_LBL_057, "A"); dash::EnergyCard _output2Resistance(dashboard, YASOLR_LBL_058, "Ω"); dash::EnergyCard _output2Energy(dashboard, YASOLR_LBL_059, "kWh"); -dash::PercentageSliderCard _output2DimmerDutyLimiter(dashboard, YASOLR_LBL_062); -dash::TextInputCard _output2DimmerTempLimiter(dashboard, YASOLR_LBL_063); -dash::TextInputCard _output2DimmerExcessLimiter(dashboard, YASOLR_LBL_061); -dash::SwitchCard _output2DimmerAuto(dashboard, YASOLR_LBL_060); dash::SwitchCard _output2BypassAuto(dashboard, YASOLR_LBL_064); -dash::TextInputCard _output2AutoStartTemp(dashboard, YASOLR_LBL_065); -dash::TextInputCard _output2AutoStoptTemp(dashboard, YASOLR_LBL_066); -dash::TextInputCard _output2AutoStartTime(dashboard, YASOLR_LBL_067); -dash::TextInputCard _output2AutoStoptTime(dashboard, YASOLR_LBL_068); -dash::WeekCard _output2AutoStartWDays(dashboard, YASOLR_LBL_069); +dash::SwitchCard _output2Bypass(dashboard, YASOLR_LBL_051); +dash::FeedbackCard _output2BypassRO(dashboard, YASOLR_LBL_051); + +// tab: relays dash::SwitchCard _relay1Switch(dashboard, YASOLR_LBL_073); dash::FeedbackCard _relay1SwitchRO(dashboard, YASOLR_LBL_074); dash::SwitchCard _relay2Switch(dashboard, YASOLR_LBL_076); dash::FeedbackCard _relay2SwitchRO(dashboard, YASOLR_LBL_077); +// tab: system + dash::LinkCard _configBackup(dashboard, YASOLR_LBL_079); dash::FileUploadCard _configRestore(dashboard, YASOLR_LBL_080, ".txt"); dash::PushButtonCard _restart(dashboard, YASOLR_LBL_082); dash::PushButtonCard _safeBoot(dashboard, YASOLR_LBL_081); -dash::PushButtonCard _energyReset(dashboard, YASOLR_LBL_085); -dash::PushButtonCard _reset(dashboard, YASOLR_LBL_086); -dash::LinkCard _consoleLink(dashboard, YASOLR_LBL_084); + +// tab: debug + +dash::FeedbackSwitchCard _debugMode(dashboard, YASOLR_LBL_083); dash::LinkCard _debugInfo(dashboard, YASOLR_LBL_178); +dash::LinkCard _consoleLink(dashboard, YASOLR_LBL_084); +dash::PushButtonCard _reset(dashboard, YASOLR_LBL_086); +dash::PushButtonCard _energyReset(dashboard, YASOLR_LBL_085); + +// tab: network dash::PasswordCard _adminPwd(dashboard, YASOLR_LBL_088, YASOLR_HIDDEN_PWD); -dash::TextInputCard _ntpServer(dashboard, YASOLR_LBL_089); -dash::AsyncDropdownCard _ntpTimezone(dashboard, YASOLR_LBL_090, "/timezones"); -dash::TimeSyncCard _ntpSync(dashboard, YASOLR_LBL_091); dash::TextInputCard _wifiSSID(dashboard, YASOLR_LBL_092); dash::PasswordCard _wifiPwd(dashboard, YASOLR_LBL_093, YASOLR_HIDDEN_PWD); +dash::SwitchCard _apMode(dashboard, YASOLR_LBL_094); dash::TextInputCard _staticIP(dashboard, YASOLR_LBL_188); dash::TextInputCard _subnetMask(dashboard, YASOLR_LBL_189); dash::TextInputCard _gateway(dashboard, YASOLR_LBL_190); dash::TextInputCard _dnsServer(dashboard, YASOLR_LBL_191); -dash::SwitchCard _apMode(dashboard, YASOLR_LBL_094); +// tab: ntp + +dash::TextInputCard _ntpServer(dashboard, YASOLR_LBL_089); +dash::AsyncDropdownCard _ntpTimezone(dashboard, YASOLR_LBL_090, "/timezones"); +dash::TimeSyncCard _ntpSync(dashboard, YASOLR_LBL_091); + +// tab: mqtt + +dash::FeedbackSwitchCard _mqtt(dashboard, YASOLR_LBL_095); dash::TextInputCard _mqttServer(dashboard, YASOLR_LBL_096); dash::TextInputCard _mqttPort(dashboard, YASOLR_LBL_097); dash::TextInputCard _mqttUser(dashboard, YASOLR_LBL_098); @@ -210,75 +210,25 @@ dash::PasswordCard _mqttPwd(dashboard, YASOLR_LBL_099, YASOLR_HIDDEN_PWD); dash::SwitchCard _mqttSecured(dashboard, YASOLR_LBL_100); dash::FileUploadCard _mqttServerCert(dashboard, YASOLR_LBL_101, ".pem"); dash::PushButtonCard _mqttServerCertDelete(dashboard, YASOLR_LBL_049); -dash::SliderCard _mqttPublishInterval(dashboard, YASOLR_LBL_102, 1, 30, 1, "s"); dash::TextInputCard _mqttTopic(dashboard, YASOLR_LBL_103); -dash::SwitchCard _haDiscovery(dashboard, YASOLR_LBL_104); -dash::TextInputCard _haDiscoveryTopic(dashboard, YASOLR_LBL_105); +dash::SliderCard _mqttPublishInterval(dashboard, YASOLR_LBL_102, 1, 30, 1, "s"); +dash::SeparatorCard _mqttSep1(dashboard, YASOLR_LBL_179); dash::TextInputCard _mqttGridVoltage(dashboard, YASOLR_LBL_106); -dash::TextInputCard _mqttGridPower(dashboard, YASOLR_LBL_107); +dash::TextInputCard _mqttGridPower(dashboard, YASOLR_LBL_044); dash::TextInputCard _mqttTempO1(dashboard, YASOLR_LBL_181); dash::TextInputCard _mqttTempO2(dashboard, YASOLR_LBL_182); +dash::FeedbackSwitchCard _haDiscovery(dashboard, YASOLR_LBL_104); +dash::TextInputCard _haDiscoveryTopic(dashboard, YASOLR_LBL_105); -dash::FeedbackTextInputCard _pinDisplayClock(dashboard, YASOLR_LBL_111); -dash::FeedbackTextInputCard _pinDisplayData(dashboard, YASOLR_LBL_112); -dash::FeedbackTextInputCard _pinJsyRX(dashboard, YASOLR_LBL_116); -dash::FeedbackTextInputCard _pinJsyTX(dashboard, YASOLR_LBL_117); -dash::FeedbackTextInputCard _pinLEDGreen(dashboard, YASOLR_LBL_118); -dash::FeedbackTextInputCard _pinLEDRed(dashboard, YASOLR_LBL_119); -dash::FeedbackTextInputCard _pinLEDYellow(dashboard, YASOLR_LBL_120); -dash::FeedbackTextInputCard _pinDimmerO1(dashboard, YASOLR_LBL_131); -dash::FeedbackTextInputCard _pinDS18O1(dashboard, YASOLR_LBL_132); -dash::FeedbackTextInputCard _pinRelayO1(dashboard, YASOLR_LBL_134); -dash::FeedbackTextInputCard _pinDimmerO2(dashboard, YASOLR_LBL_135); -dash::FeedbackTextInputCard _pinDS18O2(dashboard, YASOLR_LBL_136); -dash::FeedbackTextInputCard _pinRelayO2(dashboard, YASOLR_LBL_138); -dash::FeedbackTextInputCard _pinPZEMRX(dashboard, YASOLR_LBL_121); -dash::FeedbackTextInputCard _pinPZEMTX(dashboard, YASOLR_LBL_122); -dash::FeedbackTextInputCard _pinRelay1(dashboard, YASOLR_LBL_074); -dash::FeedbackTextInputCard _pinRelay2(dashboard, YASOLR_LBL_077); -dash::FeedbackTextInputCard _pinDS18Router(dashboard, YASOLR_LBL_139); -dash::FeedbackTextInputCard _pinZCD(dashboard, YASOLR_LBL_125); - -dash::FeedbackSwitchCard _debugMode(dashboard, YASOLR_LBL_083); -dash::FeedbackSwitchCard _display(dashboard, YASOLR_LBL_127); -dash::FeedbackSwitchCard _jsy(dashboard, YASOLR_LBL_128); -dash::FeedbackSwitchCard _jsyRemote(dashboard, YASOLR_LBL_187); -dash::FeedbackSwitchCard _led(dashboard, YASOLR_LBL_129); -dash::FeedbackSwitchCard _mqtt(dashboard, YASOLR_LBL_095); -dash::FeedbackSwitchCard _output1Relay(dashboard, YASOLR_LBL_134); -dash::FeedbackSwitchCard _output1Dimmer(dashboard, YASOLR_LBL_131); -dash::FeedbackSwitchCard _output1DS18(dashboard, YASOLR_LBL_132); -dash::FeedbackSwitchCard _output1PZEM(dashboard, YASOLR_LBL_133); -dash::FeedbackSwitchCard _output2Relay(dashboard, YASOLR_LBL_138); -dash::FeedbackSwitchCard _output2Dimmer(dashboard, YASOLR_LBL_135); -dash::FeedbackSwitchCard _output2DS18(dashboard, YASOLR_LBL_136); -dash::FeedbackSwitchCard _output2PZEM(dashboard, YASOLR_LBL_137); -dash::FeedbackSwitchCard _relay1(dashboard, YASOLR_LBL_074); -dash::FeedbackSwitchCard _relay2(dashboard, YASOLR_LBL_077); -dash::FeedbackSwitchCard _routerDS18(dashboard, YASOLR_LBL_139); -dash::FeedbackSwitchCard _zcd(dashboard, YASOLR_LBL_125); - -dash::SliderCard _displaySpeed(dashboard, YASOLR_LBL_142, 1, 10, 1, "s"); -dash::DropdownCard _displayType(dashboard, YASOLR_LBL_143, "SH1106,SH1107,SSD1306"); -dash::DropdownCard _displayRotation(dashboard, YASOLR_LBL_144, "0,90,180,270"); -dash::DropdownCard _gridFreq(dashboard, YASOLR_LBL_141, "Auto-detect,50 Hz,60 Hz"); -dash::DropdownCard _output1RelayType(dashboard, YASOLR_LBL_149, "NO,NC"); -dash::RangeSliderCard _output1DimmerMapper(dashboard, YASOLR_LBL_183, 0, 100, 1, "%"); -dash::DropdownCard _output1DimmerType(dashboard, YASOLR_LBL_193, YASOLR_DIMMER_LSA_GP8211S "," YASOLR_DIMMER_LSA_GP8403 "," YASOLR_DIMMER_LSA_GP8413 "," YASOLR_DIMMER_LSA_PWM "," YASOLR_DIMMER_LSA_PWM_ZCD "," YASOLR_DIMMER_RANDOM_SSR "," YASOLR_DIMMER_ROBODYN "," YASOLR_DIMMER_TRIAC "," YASOLR_DIMMER_ZC_SSR); -dash::SwitchCard _output1PZEMSync(dashboard, YASOLR_LBL_147); -dash::FeedbackTextInputCard _output1ResistanceInput(dashboard, YASOLR_LBL_145); -dash::DropdownCard _output2RelayType(dashboard, YASOLR_LBL_150, "NO,NC"); -dash::RangeSliderCard _output2DimmerMapper(dashboard, YASOLR_LBL_184, 0, 100, 1, "%"); -dash::DropdownCard _output2DimmerType(dashboard, YASOLR_LBL_194, YASOLR_DIMMER_LSA_GP8211S "," YASOLR_DIMMER_LSA_GP8403 "," YASOLR_DIMMER_LSA_GP8413 "," YASOLR_DIMMER_LSA_PWM "," YASOLR_DIMMER_LSA_PWM_ZCD "," YASOLR_DIMMER_RANDOM_SSR "," YASOLR_DIMMER_ROBODYN "," YASOLR_DIMMER_TRIAC "," YASOLR_DIMMER_ZC_SSR); -dash::SwitchCard _output2PZEMSync(dashboard, YASOLR_LBL_148); -dash::FeedbackTextInputCard _output2ResistanceInput(dashboard, YASOLR_LBL_146); -dash::SwitchCard _resistanceCalibration(dashboard, YASOLR_LBL_186); - -dash::TextInputCard _relay1Load(dashboard, YASOLR_LBL_072); -dash::DropdownCard _relay1Type(dashboard, YASOLR_LBL_151, "NO,NC"); -dash::TextInputCard _relay2Load(dashboard, YASOLR_LBL_075); -dash::DropdownCard _relay2Type(dashboard, YASOLR_LBL_152, "NO,NC"); +// tab: pid +int16_t _pidInputHistoryY[YASOLR_GRAPH_POINTS] = {0}; +int16_t _pidOutputHistoryY[YASOLR_GRAPH_POINTS] = {0}; +int16_t _pidErrorHistoryY[YASOLR_GRAPH_POINTS] = {0}; +int16_t _pidSumHistoryY[YASOLR_GRAPH_POINTS] = {0}; +int16_t _pidPTermHistoryY[YASOLR_GRAPH_POINTS] = {0}; +int16_t _pidITermHistoryY[YASOLR_GRAPH_POINTS] = {0}; +int16_t _pidDTermHistoryY[YASOLR_GRAPH_POINTS] = {0}; dash::SwitchCard _pidView(dashboard, YASOLR_LBL_169); dash::DropdownCard _pidPMode(dashboard, YASOLR_LBL_160, YASOLR_PID_P_MODE_1 "," YASOLR_PID_P_MODE_2 "," YASOLR_PID_P_MODE_3); dash::DropdownCard _pidDMode(dashboard, YASOLR_LBL_161, YASOLR_PID_D_MODE_1 "," YASOLR_PID_D_MODE_2 "," YASOLR_PID_D_MODE_3); @@ -289,15 +239,6 @@ dash::TextInputCard _pidKi(dashboard, YASOLR_LBL_167); dash::TextInputCard _pidKd(dashboard, YASOLR_LBL_168); dash::TextInputCard _pidOutMin(dashboard, YASOLR_LBL_164); dash::TextInputCard _pidOutMax(dashboard, YASOLR_LBL_165); - -// input,output,error,pTerm,iTerm,dTerm,sum -int16_t _pidInputHistoryY[YASOLR_GRAPH_POINTS] = {0}; -int16_t _pidOutputHistoryY[YASOLR_GRAPH_POINTS] = {0}; -int16_t _pidErrorHistoryY[YASOLR_GRAPH_POINTS] = {0}; -int16_t _pidPTermHistoryY[YASOLR_GRAPH_POINTS] = {0}; -int16_t _pidITermHistoryY[YASOLR_GRAPH_POINTS] = {0}; -int16_t _pidDTermHistoryY[YASOLR_GRAPH_POINTS] = {0}; -int16_t _pidSumHistoryY[YASOLR_GRAPH_POINTS] = {0}; dash::LineChart _pidInputHistory(dashboard, YASOLR_LBL_170); dash::LineChart _pidOutputHistory(dashboard, YASOLR_LBL_171); dash::LineChart _pidErrorHistory(dashboard, YASOLR_LBL_172); @@ -305,34 +246,182 @@ dash::BarChart _pidSumHistory(dashboard, YASOLR_LBL_173); dash::LineChart _pidPTermHistory(dashboard, YASOLR_LBL_174); dash::LineChart _pidITermHistory(dashboard, YASOLR_LBL_175); dash::LineChart _pidDTermHistory(dashboard, YASOLR_LBL_176); + +// tab: gpio + +dash::SeparatorCard _gpioTitle(dashboard, YASOLR_LBL_126); +dash::SeparatorCard _gpioSep1(dashboard, YASOLR_LBL_046); +dash::FeedbackTextInputCard _pinDimmerO1(dashboard, YASOLR_LBL_050); +dash::FeedbackTextInputCard _pinRelayO1(dashboard, YASOLR_LBL_134); +dash::FeedbackTextInputCard _pinDS18O1(dashboard, YASOLR_LBL_132); +dash::SeparatorCard _gpioSep2(dashboard, YASOLR_LBL_070); +dash::FeedbackTextInputCard _pinDimmerO2(dashboard, YASOLR_LBL_050); +dash::FeedbackTextInputCard _pinRelayO2(dashboard, YASOLR_LBL_134); +dash::FeedbackTextInputCard _pinDS18O2(dashboard, YASOLR_LBL_132); +dash::SeparatorCard _gpioSep3(dashboard, YASOLR_LBL_071); +dash::FeedbackTextInputCard _pinRelay1(dashboard, YASOLR_LBL_074); +dash::FeedbackTextInputCard _pinRelay2(dashboard, YASOLR_LBL_077); +dash::SeparatorCard _gpioSep4(dashboard, YASOLR_LBL_012); +dash::FeedbackTextInputCard _pinJsyRX(dashboard, YASOLR_LBL_116); +dash::FeedbackTextInputCard _pinJsyTX(dashboard, YASOLR_LBL_117); +dash::FeedbackTextInputCard _pinPZEMRX(dashboard, YASOLR_LBL_121); +dash::FeedbackTextInputCard _pinPZEMTX(dashboard, YASOLR_LBL_122); +dash::FeedbackTextInputCard _pinZCD(dashboard, YASOLR_LBL_125); +dash::SeparatorCard _gpioSep5(dashboard, YASOLR_LBL_078); +dash::FeedbackTextInputCard _pinDS18Router(dashboard, YASOLR_LBL_132); +dash::FeedbackTextInputCard _pinLEDGreen(dashboard, YASOLR_LBL_118); +dash::FeedbackTextInputCard _pinLEDYellow(dashboard, YASOLR_LBL_120); +dash::FeedbackTextInputCard _pinLEDRed(dashboard, YASOLR_LBL_119); +dash::FeedbackTextInputCard _pinDisplayClock(dashboard, YASOLR_LBL_111); +dash::FeedbackTextInputCard _pinDisplayData(dashboard, YASOLR_LBL_112); + +// tab: hardware + +// grid +dash::SeparatorCard _gridSep(dashboard, YASOLR_LBL_107); +dash::DropdownCard _gridFreq(dashboard, YASOLR_LBL_141, "Auto-detect,50 Hz,60 Hz"); +dash::FeedbackSwitchCard _jsy(dashboard, YASOLR_LBL_128); +dash::FeedbackSwitchCard _jsyRemote(dashboard, YASOLR_LBL_187); +dash::FeedbackSwitchCard _zcd(dashboard, YASOLR_LBL_125); + +// output 1 dimmer +dash::FeedbackSwitchCard _output1Dimmer(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_050); +dash::DropdownCard _output1DimmerType(dashboard, YASOLR_LBL_151, YASOLR_DIMMER_LSA_GP8211S "," YASOLR_DIMMER_LSA_GP8403 "," YASOLR_DIMMER_LSA_GP8413 "," YASOLR_DIMMER_LSA_PWM "," YASOLR_DIMMER_LSA_PWM_ZCD "," YASOLR_DIMMER_RANDOM_SSR "," YASOLR_DIMMER_ROBODYN "," YASOLR_DIMMER_TRIAC "," YASOLR_DIMMER_ZC_SSR); +dash::RangeSliderCard _output1DimmerMapper(dashboard, YASOLR_LBL_183, 0, 100, 1, "%"); +dash::FeedbackSwitchCard _output1PZEM(dashboard, YASOLR_LBL_133); +dash::SwitchCard _output1PZEMSync(dashboard, YASOLR_LBL_147); + +// output 1 bypass relay +dash::FeedbackSwitchCard _output1Relay(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_134); +dash::DropdownCard _output1RelayType(dashboard, YASOLR_LBL_151, "NO,NC"); + +// output 1 ds18 +dash::FeedbackSwitchCard _output1DS18(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_132); + +// output 2 dimmer +dash::FeedbackSwitchCard _output2Dimmer(dashboard, YASOLR_LBL_070 ": " YASOLR_LBL_050); +dash::DropdownCard _output2DimmerType(dashboard, YASOLR_LBL_151, YASOLR_DIMMER_LSA_GP8211S "," YASOLR_DIMMER_LSA_GP8403 "," YASOLR_DIMMER_LSA_GP8413 "," YASOLR_DIMMER_LSA_PWM "," YASOLR_DIMMER_LSA_PWM_ZCD "," YASOLR_DIMMER_RANDOM_SSR "," YASOLR_DIMMER_ROBODYN "," YASOLR_DIMMER_TRIAC "," YASOLR_DIMMER_ZC_SSR); +dash::RangeSliderCard _output2DimmerMapper(dashboard, YASOLR_LBL_183, 0, 100, 1, "%"); +dash::FeedbackSwitchCard _output2PZEM(dashboard, YASOLR_LBL_133); +dash::SwitchCard _output2PZEMSync(dashboard, YASOLR_LBL_148); + +// output 2 bypass relay +dash::FeedbackSwitchCard _output2Relay(dashboard, YASOLR_LBL_070 ": " YASOLR_LBL_134); +dash::DropdownCard _output2RelayType(dashboard, YASOLR_LBL_151, "NO,NC"); + +// output 2 ds18 +dash::FeedbackSwitchCard _output2DS18(dashboard, YASOLR_LBL_046 ": " YASOLR_LBL_132); + +// relay1 +dash::FeedbackSwitchCard _relay1(dashboard, YASOLR_LBL_074); +dash::DropdownCard _relay1Type(dashboard, YASOLR_LBL_151, "NO,NC"); +dash::TextInputCard _relay1Load(dashboard, YASOLR_LBL_072); + +// relay2 +dash::FeedbackSwitchCard _relay2(dashboard, YASOLR_LBL_077); +dash::DropdownCard _relay2Type(dashboard, YASOLR_LBL_151, "NO,NC"); +dash::TextInputCard _relay2Load(dashboard, YASOLR_LBL_075); + +// router ds18 +dash::FeedbackSwitchCard _routerDS18(dashboard, YASOLR_LBL_135 ": " YASOLR_LBL_132); + +// router led +dash::FeedbackSwitchCard _led(dashboard, YASOLR_LBL_135 ": " YASOLR_LBL_129); + +// display +dash::FeedbackSwitchCard _display(dashboard, YASOLR_LBL_135 ": " YASOLR_LBL_127); +dash::DropdownCard _displayType(dashboard, YASOLR_LBL_143, "SH1106,SH1107,SSD1306"); +dash::DropdownCard _displayRotation(dashboard, YASOLR_LBL_144, "0,90,180,270"); +dash::SliderCard _displaySpeed(dashboard, YASOLR_LBL_142, 1, 10, 1, "s"); + +// tab: output 1 config + +dash::SeparatorCard _output1ConfigSep0(dashboard, YASOLR_LBL_140); +dash::FeedbackTextInputCard _output1ResistanceInput(dashboard, YASOLR_LBL_145); +dash::SwitchCard _output1ResistanceCalibration(dashboard, YASOLR_LBL_186); +dash::SeparatorCard _output1ConfigSep1(dashboard, YASOLR_LBL_136); +dash::PercentageSliderCard _output1DimmerDutyLimiter(dashboard, YASOLR_LBL_062); +dash::TextInputCard _output1DimmerTempLimiter(dashboard, YASOLR_LBL_063); +dash::TextInputCard _output1DimmerExcessLimiter(dashboard, YASOLR_LBL_061); +dash::SeparatorCard _output1ConfigSep2(dashboard, YASOLR_LBL_137); +dash::TextInputCard _output1AutoStartTemp(dashboard, YASOLR_LBL_065); +dash::TextInputCard _output1AutoStoptTemp(dashboard, YASOLR_LBL_066); +dash::TextInputCard _output1AutoStartTime(dashboard, YASOLR_LBL_067); +dash::TextInputCard _output1AutoStoptTime(dashboard, YASOLR_LBL_068); +dash::WeekCard _output1AutoStartWDays(dashboard, YASOLR_LBL_069); + +// tab: output 2 config + +dash::SeparatorCard _output2ConfigSep0(dashboard, YASOLR_LBL_140); +dash::FeedbackTextInputCard _output2ResistanceInput(dashboard, YASOLR_LBL_145); +dash::SwitchCard _output2ResistanceCalibration(dashboard, YASOLR_LBL_186); +dash::SeparatorCard _output2ConfigSep1(dashboard, YASOLR_LBL_136); +dash::PercentageSliderCard _output2DimmerDutyLimiter(dashboard, YASOLR_LBL_062); +dash::TextInputCard _output2DimmerTempLimiter(dashboard, YASOLR_LBL_063); +dash::TextInputCard _output2DimmerExcessLimiter(dashboard, YASOLR_LBL_061); +dash::SeparatorCard _output2ConfigSep2(dashboard, YASOLR_LBL_137); +dash::TextInputCard _output2AutoStartTemp(dashboard, YASOLR_LBL_065); +dash::TextInputCard _output2AutoStoptTemp(dashboard, YASOLR_LBL_066); +dash::TextInputCard _output2AutoStartTime(dashboard, YASOLR_LBL_067); +dash::TextInputCard _output2AutoStoptTime(dashboard, YASOLR_LBL_068); +dash::WeekCard _output2AutoStartWDays(dashboard, YASOLR_LBL_069); #endif +void _onChangeResistanceCalibration(bool value) { + if (value && !router.isCalibrationRunning()) { + config.set(KEY_ENABLE_OUTPUT1_AUTO_BYPASS, YASOLR_FALSE, false); + config.set(KEY_ENABLE_OUTPUT1_AUTO_DIMMER, YASOLR_FALSE, false); + config.set(KEY_OUTPUT1_DIMMER_LIMIT, "100", false); + config.set(KEY_ENABLE_OUTPUT2_AUTO_BYPASS, YASOLR_FALSE, false); + config.set(KEY_ENABLE_OUTPUT2_AUTO_DIMMER, YASOLR_FALSE, false); + config.set(KEY_OUTPUT2_DIMMER_LIMIT, "100", false); + + router.beginCalibration([]() { + config.set(KEY_OUTPUT1_RESISTANCE, Mycila::string::to_string(router.getOutputs()[0]->config.calibratedResistance, 2)); + config.set(KEY_OUTPUT2_RESISTANCE, Mycila::string::to_string(router.getOutputs()[1]->config.calibratedResistance, 2)); + }); + + // because we set false to trigger events + dashboardInitTask.resume(); + if (mqttPublishConfigTask) + mqttPublishConfigTask->resume(); + if (mqttPublishTask) + mqttPublishTask->requestEarlyRun(); + } + + _output1ResistanceCalibration.setValue(router.isCalibrationRunning()); + _output2ResistanceCalibration.setValue(router.isCalibrationRunning()); + dashboard.refresh(_output1ResistanceCalibration); + dashboard.refresh(_output2ResistanceCalibration); +} + void YaSolR::Website::begin() { logger.info(TAG, "Initialize dashboard layout..."); for (int i = 0; i < YASOLR_GRAPH_POINTS; i++) _historyX[i] = i - YASOLR_GRAPH_POINTS; - // overview - - _gridPowerHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _routedPowerHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _routerTHDiHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + // home + if (relay1) + _relaySwitch(_relay1Switch, *relay1); + if (relay2) + _relaySwitch(_relay2Switch, *relay2); if (output1) { _outputBypassSwitch(_output1Bypass, *output1); _outputDimmerSlider(_output1DimmerSlider, *output1); } - if (output2) { _outputBypassSwitch(_output2Bypass, *output2); _outputDimmerSlider(_output2DimmerSlider, *output2); } - if (relay1) - _relaySwitch(_relay1Switch, *relay1); - if (relay2) - _relaySwitch(_relay2Switch, *relay2); + _gridPowerHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _routedPowerHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _routerTHDiHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + + _output1ResistanceCalibration.onChange(_onChangeResistanceCalibration); + _output2ResistanceCalibration.onChange(_onChangeResistanceCalibration); _output1PZEMSync.onChange([](bool value) { pzemO1PairingTask->resume(); @@ -346,158 +435,87 @@ void YaSolR::Website::begin() { dashboard.refresh(_output2PZEMSync); }); - _resistanceCalibration.onChange([this](bool value) { - if (value && !router.isCalibrationRunning()) { - config.set(KEY_ENABLE_OUTPUT1_AUTO_BYPASS, YASOLR_FALSE, false); - config.set(KEY_ENABLE_OUTPUT1_AUTO_DIMMER, YASOLR_FALSE, false); - config.set(KEY_OUTPUT1_DIMMER_LIMIT, "100", false); - config.set(KEY_ENABLE_OUTPUT2_AUTO_BYPASS, YASOLR_FALSE, false); - config.set(KEY_ENABLE_OUTPUT2_AUTO_DIMMER, YASOLR_FALSE, false); - config.set(KEY_OUTPUT2_DIMMER_LIMIT, "100", false); - - router.beginCalibration([]() { - config.set(KEY_OUTPUT1_RESISTANCE, Mycila::string::to_string(router.getOutputs()[0]->config.calibratedResistance, 2)); - config.set(KEY_OUTPUT2_RESISTANCE, Mycila::string::to_string(router.getOutputs()[1]->config.calibratedResistance, 2)); - }); - - // because we set false to trigger events - dashboardInitTask.resume(); - if (mqttPublishConfigTask) - mqttPublishConfigTask->resume(); - if (mqttPublishTask) - mqttPublishTask->requestEarlyRun(); - } - - _resistanceCalibration.setValue(router.isCalibrationRunning()); - dashboard.refresh(_resistanceCalibration); - }); - #ifdef APP_MODEL_PRO dashboard.setChartAnimations(false); - // overview graphs - - _gridPowerHistory.setSize(chartSize); - _routedPowerHistory.setSize(chartSize); - _routerTHDiHistory.setSize(chartSize); - - // PID - - _pidInputHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _pidOutputHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _pidErrorHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _pidPTermHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _pidITermHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _pidDTermHistory.setX(_historyX, YASOLR_GRAPH_POINTS); - _pidSumHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + // tab: home - _pidInputHistory.setSize(chartSize); - _pidOutputHistory.setSize(chartSize); - _pidPTermHistory.setSize(chartSize); - _pidITermHistory.setSize(chartSize); - _pidDTermHistory.setSize(chartSize); - _pidErrorHistory.setSize(chartSize); - _pidSumHistory.setSize(chartSize); + _gridPowerHistory.setSize(FULL_SIZE); + _routedPowerHistory.setSize(FULL_SIZE); + _routerTHDiHistory.setSize(FULL_SIZE); - // output 1 + // tab: output 1 _output1State.setTab(_output1Tab); _output1DS18State.setTab(_output1Tab); + _output1DimmerAuto.setTab(_output1Tab); _output1DimmerSlider.setTab(_output1Tab); _output1DimmerSliderRO.setTab(_output1Tab); - _output1Bypass.setTab(_output1Tab); - _output1BypassRO.setTab(_output1Tab); - _output1Power.setTab(_output1Tab); + _output1ApparentPower.setTab(_output1Tab); _output1PowerFactor.setTab(_output1Tab); _output1THDi.setTab(_output1Tab); - _output1Energy.setTab(_output1Tab); - - _output1ApparentPower.setTab(_output1Tab); _output1Voltage.setTab(_output1Tab); _output1Current.setTab(_output1Tab); _output1Resistance.setTab(_output1Tab); - + _output1Energy.setTab(_output1Tab); _output1BypassAuto.setTab(_output1Tab); - _output1DimmerAuto.setTab(_output1Tab); - _output1AutoStartTemp.setTab(_output1Tab); - _output1AutoStartTime.setTab(_output1Tab); - _output1AutoStartWDays.setTab(_output1Tab); - _output1AutoStoptTemp.setTab(_output1Tab); - _output1AutoStoptTime.setTab(_output1Tab); - _output1DimmerExcessLimiter.setTab(_output1Tab); - _output1DimmerDutyLimiter.setTab(_output1Tab); - _output1DimmerTempLimiter.setTab(_output1Tab); + _output1Bypass.setTab(_output1Tab); + _output1BypassRO.setTab(_output1Tab); - _boolConfig(_output1BypassAuto, KEY_ENABLE_OUTPUT1_AUTO_BYPASS); _boolConfig(_output1DimmerAuto, KEY_ENABLE_OUTPUT1_AUTO_DIMMER); - _daysConfig(_output1AutoStartWDays, KEY_OUTPUT1_DAYS); - _numConfig(_output1AutoStartTemp, KEY_OUTPUT1_TEMPERATURE_START); - _numConfig(_output1AutoStoptTemp, KEY_OUTPUT1_TEMPERATURE_STOP); - _numConfig(_output1DimmerTempLimiter, KEY_OUTPUT1_DIMMER_TEMP_LIMITER); - _numConfig(_output1DimmerExcessLimiter, KEY_OUTPUT1_EXCESS_LIMITER); - _sliderConfig(_output1DimmerDutyLimiter, KEY_OUTPUT1_DIMMER_LIMIT); - _textConfig(_output1AutoStartTime, KEY_OUTPUT1_TIME_START); - _textConfig(_output1AutoStoptTime, KEY_OUTPUT1_TIME_STOP); + _boolConfig(_output1BypassAuto, KEY_ENABLE_OUTPUT1_AUTO_BYPASS); - // output 2 + // tab: output 2 _output2State.setTab(_output2Tab); _output2DS18State.setTab(_output2Tab); + _output2DimmerAuto.setTab(_output2Tab); _output2DimmerSlider.setTab(_output2Tab); _output2DimmerSliderRO.setTab(_output2Tab); - _output2Bypass.setTab(_output2Tab); - _output2BypassRO.setTab(_output2Tab); - _output2Power.setTab(_output2Tab); + _output2ApparentPower.setTab(_output2Tab); _output2PowerFactor.setTab(_output2Tab); _output2THDi.setTab(_output2Tab); - _output2Energy.setTab(_output2Tab); - - _output2ApparentPower.setTab(_output2Tab); _output2Voltage.setTab(_output2Tab); _output2Current.setTab(_output2Tab); _output2Resistance.setTab(_output2Tab); - + _output2Energy.setTab(_output2Tab); _output2BypassAuto.setTab(_output2Tab); - _output2DimmerAuto.setTab(_output2Tab); - _output2AutoStartTemp.setTab(_output2Tab); - _output2AutoStartTime.setTab(_output2Tab); - _output2AutoStartWDays.setTab(_output2Tab); - _output2AutoStoptTemp.setTab(_output2Tab); - _output2AutoStoptTime.setTab(_output2Tab); - _output2DimmerExcessLimiter.setTab(_output2Tab); - _output2DimmerDutyLimiter.setTab(_output2Tab); - _output2DimmerTempLimiter.setTab(_output2Tab); + _output2Bypass.setTab(_output2Tab); + _output2BypassRO.setTab(_output2Tab); - _boolConfig(_output2BypassAuto, KEY_ENABLE_OUTPUT2_AUTO_BYPASS); _boolConfig(_output2DimmerAuto, KEY_ENABLE_OUTPUT2_AUTO_DIMMER); - _daysConfig(_output2AutoStartWDays, KEY_OUTPUT2_DAYS); - _numConfig(_output2AutoStartTemp, KEY_OUTPUT2_TEMPERATURE_START); - _numConfig(_output2AutoStoptTemp, KEY_OUTPUT2_TEMPERATURE_STOP); - _numConfig(_output2DimmerTempLimiter, KEY_OUTPUT2_DIMMER_TEMP_LIMITER); - _numConfig(_output2DimmerExcessLimiter, KEY_OUTPUT2_EXCESS_LIMITER); - _sliderConfig(_output2DimmerDutyLimiter, KEY_OUTPUT2_DIMMER_LIMIT); - _textConfig(_output2AutoStartTime, KEY_OUTPUT2_TIME_START); - _textConfig(_output2AutoStoptTime, KEY_OUTPUT2_TIME_STOP); + _boolConfig(_output2BypassAuto, KEY_ENABLE_OUTPUT2_AUTO_BYPASS); - // relays + // tab: relays _relay1Switch.setTab(_relaysTab); _relay1SwitchRO.setTab(_relaysTab); _relay2Switch.setTab(_relaysTab); _relay2SwitchRO.setTab(_relaysTab); - // management + // tab: system + + _configBackup.setTab(_systemTab); + _configRestore.setTab(_systemTab); + _restart.setTab(_systemTab); + _safeBoot.setTab(_systemTab); + + _restart.onPush([]() { restartTask.resume(); }); + _safeBoot.onPush([]() { safeBootTask.resume(); }); + + // tab: debug + + _debugMode.setTab(_debugTab); + _debugInfo.setTab(_debugTab); + _consoleLink.setTab(_debugTab); + _energyReset.setTab(_debugTab); + _reset.setTab(_debugTab); - _configBackup.setTab(_managementTab); - _configRestore.setTab(_managementTab); - _consoleLink.setTab(_managementTab); - _debugInfo.setTab(_managementTab); - _safeBoot.setTab(_managementTab); - _reset.setTab(_managementTab); - _restart.setTab(_managementTab); - _energyReset.setTab(_managementTab); + _debugMode.setSize(FULL_SIZE); + + _boolConfig(_debugMode, KEY_ENABLE_DEBUG); _energyReset.onPush([]() { if (jsy) @@ -507,75 +525,84 @@ void YaSolR::Website::begin() { if (pzemO2) pzemO2->resetEnergy(); }); - _reset.onPush([]() { resetTask.resume(); }); - _restart.onPush([]() { restartTask.resume(); }); - _safeBoot.onPush([]() { safeBootTask.resume(); }); - // network (config) + _reset.onPush([]() { resetTask.resume(); }); - _adminPwd.setTab(_networkConfigTab); - _apMode.setTab(_networkConfigTab); - _ntpServer.setTab(_networkConfigTab); - _ntpSync.setTab(_networkConfigTab); - _ntpTimezone.setTab(_networkConfigTab); - _wifiPwd.setTab(_networkConfigTab); - _wifiSSID.setTab(_networkConfigTab); - _staticIP.setTab(_networkConfigTab); - _subnetMask.setTab(_networkConfigTab); - _gateway.setTab(_networkConfigTab); - _dnsServer.setTab(_networkConfigTab); + // tab: network - _ntpTimezone.onChange([](const char* value) { - config.set(KEY_NTP_TIMEZONE, value); - _ntpTimezone.setValue(value); - dashboard.refresh(_ntpTimezone); - }); + _adminPwd.setTab(_networkTab); + _wifiSSID.setTab(_networkTab); + _wifiPwd.setTab(_networkTab); + _apMode.setTab(_networkTab); + _staticIP.setTab(_networkTab); + _subnetMask.setTab(_networkTab); + _gateway.setTab(_networkTab); + _dnsServer.setTab(_networkTab); - _boolConfig(_apMode, KEY_ENABLE_AP_MODE); _passwordConfig(_adminPwd, KEY_ADMIN_PASSWORD); - _passwordConfig(_wifiPwd, KEY_WIFI_PASSWORD); - _textConfig(_ntpServer, KEY_NTP_SERVER); + _boolConfig(_apMode, KEY_ENABLE_AP_MODE); _textConfig(_wifiSSID, KEY_WIFI_SSID); + _passwordConfig(_wifiPwd, KEY_WIFI_PASSWORD); _textConfig(_staticIP, KEY_NET_IP); _textConfig(_subnetMask, KEY_NET_SUBNET); _textConfig(_gateway, KEY_NET_GATEWAY); _textConfig(_dnsServer, KEY_NET_DNS); + // tab: ntp + + _ntpServer.setTab(_ntpTab); + _ntpTimezone.setTab(_ntpTab); + _ntpSync.setTab(_ntpTab); + + _textConfig(_ntpServer, KEY_NTP_SERVER); + + _ntpTimezone.onChange([](const char* value) { + config.set(KEY_NTP_TIMEZONE, value); + _ntpTimezone.setValue(value); + dashboard.refresh(_ntpTimezone); + }); + _ntpSync.onSync([](const timeval& tv) { Mycila::NTP.sync(tv); }); - // mqtt (config) - - _haDiscovery.setTab(_mqttConfigTab); - _haDiscoveryTopic.setTab(_mqttConfigTab); - _mqttGridPower.setTab(_mqttConfigTab); - _mqttGridVoltage.setTab(_mqttConfigTab); - _mqttPort.setTab(_mqttConfigTab); - _mqttPublishInterval.setTab(_mqttConfigTab); - _mqttPwd.setTab(_mqttConfigTab); - _mqttSecured.setTab(_mqttConfigTab); - _mqttServer.setTab(_mqttConfigTab); - _mqttServerCert.setTab(_mqttConfigTab); - _mqttServerCertDelete.setTab(_mqttConfigTab); - _mqttTopic.setTab(_mqttConfigTab); - _mqttUser.setTab(_mqttConfigTab); - _mqttTempO1.setTab(_mqttConfigTab); - _mqttTempO2.setTab(_mqttConfigTab); + // tab: mqtt + + _mqtt.setTab(_mqttTab); + _mqttServer.setTab(_mqttTab); + _mqttPort.setTab(_mqttTab); + _mqttUser.setTab(_mqttTab); + _mqttPwd.setTab(_mqttTab); + _mqttSecured.setTab(_mqttTab); + _mqttServerCert.setTab(_mqttTab); + _mqttServerCertDelete.setTab(_mqttTab); + _mqttTopic.setTab(_mqttTab); + _mqttPublishInterval.setTab(_mqttTab); + _mqttSep1.setTab(_mqttTab); + _mqttGridVoltage.setTab(_mqttTab); + _mqttGridPower.setTab(_mqttTab); + _mqttTempO1.setTab(_mqttTab); + _mqttTempO2.setTab(_mqttTab); + _haDiscovery.setTab(_mqttTab); + _haDiscoveryTopic.setTab(_mqttTab); + + _mqtt.setSize(FULL_SIZE); + _haDiscovery.setSize(FULL_SIZE); - _boolConfig(_haDiscovery, KEY_ENABLE_HA_DISCOVERY); - _boolConfig(_mqttSecured, KEY_MQTT_SECURED); + _boolConfig(_mqtt, KEY_ENABLE_MQTT); + _textConfig(_mqttServer, KEY_MQTT_SERVER); _numConfig(_mqttPort, KEY_MQTT_PORT); + _textConfig(_mqttUser, KEY_MQTT_USERNAME); _passwordConfig(_mqttPwd, KEY_MQTT_PASSWORD); + _boolConfig(_mqttSecured, KEY_MQTT_SECURED); + _textConfig(_mqttTopic, KEY_MQTT_TOPIC); _sliderConfig(_mqttPublishInterval, KEY_MQTT_PUBLISH_INTERVAL); - _textConfig(_haDiscoveryTopic, KEY_HA_DISCOVERY_TOPIC); - _textConfig(_mqttGridPower, KEY_GRID_POWER_MQTT_TOPIC); _textConfig(_mqttGridVoltage, KEY_GRID_VOLTAGE_MQTT_TOPIC); + _textConfig(_mqttGridPower, KEY_GRID_POWER_MQTT_TOPIC); _textConfig(_mqttTempO1, KEY_OUTPUT1_TEMPERATURE_MQTT_TOPIC); _textConfig(_mqttTempO2, KEY_OUTPUT2_TEMPERATURE_MQTT_TOPIC); - _textConfig(_mqttServer, KEY_MQTT_SERVER); - _textConfig(_mqttTopic, KEY_MQTT_TOPIC); - _textConfig(_mqttUser, KEY_MQTT_USERNAME); + _boolConfig(_haDiscovery, KEY_ENABLE_HA_DISCOVERY); + _textConfig(_haDiscoveryTopic, KEY_HA_DISCOVERY_TOPIC); _mqttServerCertDelete.onPush([this]() { if (LittleFS.exists(YASOLR_MQTT_SERVER_CERT_FILE) && LittleFS.remove(YASOLR_MQTT_SERVER_CERT_FILE)) { @@ -584,167 +611,15 @@ void YaSolR::Website::begin() { } }); - // GPIO (configuration) - - _pinDimmerO1.setTab(_pinConfigTab); - _pinDimmerO2.setTab(_pinConfigTab); - _pinDisplayClock.setTab(_pinConfigTab); - _pinDisplayData.setTab(_pinConfigTab); - _pinDS18O1.setTab(_pinConfigTab); - _pinDS18O2.setTab(_pinConfigTab); - _pinDS18Router.setTab(_pinConfigTab); - _pinJsyRX.setTab(_pinConfigTab); - _pinJsyTX.setTab(_pinConfigTab); - _pinLEDGreen.setTab(_pinConfigTab); - _pinLEDRed.setTab(_pinConfigTab); - _pinLEDYellow.setTab(_pinConfigTab); - _pinPZEMRX.setTab(_pinConfigTab); - _pinPZEMTX.setTab(_pinConfigTab); - _pinRelay1.setTab(_pinConfigTab); - _pinRelay2.setTab(_pinConfigTab); - _pinRelayO1.setTab(_pinConfigTab); - _pinRelayO2.setTab(_pinConfigTab); - _pinZCD.setTab(_pinConfigTab); - - _pinConfig(_pinDimmerO1, KEY_PIN_OUTPUT1_DIMMER); - _pinConfig(_pinDimmerO2, KEY_PIN_OUTPUT2_DIMMER); - _pinConfig(_pinDisplayClock, KEY_PIN_DISPLAY_SCL); - _pinConfig(_pinDisplayData, KEY_PIN_DISPLAY_SDA); - _pinConfig(_pinDS18O1, KEY_PIN_OUTPUT1_DS18); - _pinConfig(_pinDS18O2, KEY_PIN_OUTPUT2_DS18); - _pinConfig(_pinDS18Router, KEY_PIN_ROUTER_DS18); - _pinConfig(_pinJsyRX, KEY_PIN_JSY_RX); - _pinConfig(_pinJsyTX, KEY_PIN_JSY_TX); - _pinConfig(_pinLEDGreen, KEY_PIN_LIGHTS_GREEN); - _pinConfig(_pinLEDRed, KEY_PIN_LIGHTS_RED); - _pinConfig(_pinLEDYellow, KEY_PIN_LIGHTS_YELLOW); - _pinConfig(_pinPZEMRX, KEY_PIN_PZEM_RX); - _pinConfig(_pinPZEMTX, KEY_PIN_PZEM_TX); - _pinConfig(_pinRelay1, KEY_PIN_RELAY1); - _pinConfig(_pinRelay2, KEY_PIN_RELAY2); - _pinConfig(_pinRelayO1, KEY_PIN_OUTPUT1_RELAY); - _pinConfig(_pinRelayO2, KEY_PIN_OUTPUT2_RELAY); - _pinConfig(_pinZCD, KEY_PIN_ZCD); - - // Hardware - - _debugMode.setTab(_hardwareEnableTab); - _display.setTab(_hardwareEnableTab); - _jsy.setTab(_hardwareEnableTab); - _jsyRemote.setTab(_hardwareEnableTab); - _led.setTab(_hardwareEnableTab); - _mqtt.setTab(_hardwareEnableTab); - _output1Dimmer.setTab(_hardwareEnableTab); - _output1PZEM.setTab(_hardwareEnableTab); - _output1Relay.setTab(_hardwareEnableTab); - _output1DS18.setTab(_hardwareEnableTab); - _output2Dimmer.setTab(_hardwareEnableTab); - _output2PZEM.setTab(_hardwareEnableTab); - _output2Relay.setTab(_hardwareEnableTab); - _output2DS18.setTab(_hardwareEnableTab); - _relay1.setTab(_hardwareEnableTab); - _relay2.setTab(_hardwareEnableTab); - _routerDS18.setTab(_hardwareEnableTab); - _zcd.setTab(_hardwareEnableTab); + // tab: pid - _boolConfig(_debugMode, KEY_ENABLE_DEBUG); - _boolConfig(_display, KEY_ENABLE_DISPLAY); - _boolConfig(_jsy, KEY_ENABLE_JSY); - _boolConfig(_jsyRemote, KEY_ENABLE_JSY_REMOTE); - _boolConfig(_led, KEY_ENABLE_LIGHTS); - _boolConfig(_mqtt, KEY_ENABLE_MQTT); - _boolConfig(_output1Dimmer, KEY_ENABLE_OUTPUT1_DIMMER); - _boolConfig(_output1DS18, KEY_ENABLE_OUTPUT1_DS18); - _boolConfig(_output1PZEM, KEY_ENABLE_OUTPUT1_PZEM); - _boolConfig(_output1Relay, KEY_ENABLE_OUTPUT1_RELAY); - _boolConfig(_output2Dimmer, KEY_ENABLE_OUTPUT2_DIMMER); - _boolConfig(_output2DS18, KEY_ENABLE_OUTPUT2_DS18); - _boolConfig(_output2PZEM, KEY_ENABLE_OUTPUT2_PZEM); - _boolConfig(_output2Relay, KEY_ENABLE_OUTPUT2_RELAY); - _boolConfig(_relay1, KEY_ENABLE_RELAY1); - _boolConfig(_relay2, KEY_ENABLE_RELAY2); - _boolConfig(_routerDS18, KEY_ENABLE_DS18_SYSTEM); - _boolConfig(_zcd, KEY_ENABLE_ZCD); - - // Hardware (config) - - _displayRotation.setTab(_hardwareConfigTab); - _displaySpeed.setTab(_hardwareConfigTab); - _displayType.setTab(_hardwareConfigTab); - _gridFreq.setTab(_hardwareConfigTab); - _output1DimmerMapper.setTab(_hardwareConfigTab); - _output1DimmerType.setTab(_hardwareConfigTab); - _output1PZEMSync.setTab(_hardwareConfigTab); - _output1RelayType.setTab(_hardwareConfigTab); - _output1ResistanceInput.setTab(_hardwareConfigTab); - _output2DimmerMapper.setTab(_hardwareConfigTab); - _output2DimmerType.setTab(_hardwareConfigTab); - _output2PZEMSync.setTab(_hardwareConfigTab); - _output2RelayType.setTab(_hardwareConfigTab); - _output2ResistanceInput.setTab(_hardwareConfigTab); - _relay1Load.setTab(_hardwareConfigTab); - _relay1Type.setTab(_hardwareConfigTab); - _relay2Load.setTab(_hardwareConfigTab); - _relay2Type.setTab(_hardwareConfigTab); - _resistanceCalibration.setTab(_hardwareConfigTab); - - _gridFreq.onChange([](const char* value) { - if (strcmp(value, "50 Hz") == 0) - config.set(KEY_GRID_FREQUENCY, "50"); - else if (strcmp(value, "60 Hz") == 0) - config.set(KEY_GRID_FREQUENCY, "60"); - else - config.unset(KEY_GRID_FREQUENCY); - _gridFreq.setValue(config.get(KEY_GRID_FREQUENCY)); - dashboard.refresh(_gridFreq); - }); - - _numConfig(_displayRotation, KEY_DISPLAY_ROTATION); - _numConfig(_relay1Load, KEY_RELAY1_LOAD); - _numConfig(_relay2Load, KEY_RELAY2_LOAD); - _sliderConfig(_displaySpeed, KEY_DISPLAY_SPEED); - _textConfig(_displayType, KEY_DISPLAY_TYPE); - _textConfig(_output1DimmerType, KEY_OUTPUT1_DIMMER_TYPE); - _textConfig(_output1RelayType, KEY_OUTPUT1_RELAY_TYPE); - _textConfig(_output2DimmerType, KEY_OUTPUT2_DIMMER_TYPE); - _textConfig(_output2RelayType, KEY_OUTPUT2_RELAY_TYPE); - _textConfig(_relay1Type, KEY_RELAY1_TYPE); - _textConfig(_relay2Type, KEY_RELAY2_TYPE); - - _output1ResistanceInput.onChange([](const std::optional value) { - if (value.has_value()) - config.set(KEY_OUTPUT1_RESISTANCE, dash::to_string(value.value())); - else - config.unset(KEY_OUTPUT1_RESISTANCE); - _output1ResistanceInput.setValue(config.getFloat(KEY_OUTPUT1_RESISTANCE)); - dashboard.refresh(_output1ResistanceInput); - }); - _output2ResistanceInput.onChange([](const std::optional value) { - if (value.has_value()) - config.set(KEY_OUTPUT2_RESISTANCE, dash::to_string(value.value())); - else - config.unset(KEY_OUTPUT2_RESISTANCE); - _output2ResistanceInput.setValue(config.getFloat(KEY_OUTPUT2_RESISTANCE)); - dashboard.refresh(_output2ResistanceInput); - }); - - _output1DimmerMapper.onChange([](const dash::Range& range) { - config.set(KEY_OUTPUT1_DIMMER_MIN, std::to_string(range.low())); - config.set(KEY_OUTPUT1_DIMMER_MAX, std::to_string(range.high())); - _output1DimmerMapper.setValue({static_cast(config.getInt(KEY_OUTPUT1_DIMMER_MIN)), - static_cast(config.getInt(KEY_OUTPUT1_DIMMER_MAX))}); - dashboard.refresh(_output1DimmerMapper); - }); - - _output2DimmerMapper.onChange([](const dash::Range& range) { - config.set(KEY_OUTPUT2_DIMMER_MIN, std::to_string(range.low())); - config.set(KEY_OUTPUT2_DIMMER_MAX, std::to_string(range.high())); - _output2DimmerMapper.setValue({static_cast(config.getInt(KEY_OUTPUT2_DIMMER_MIN)), - static_cast(config.getInt(KEY_OUTPUT2_DIMMER_MAX))}); - dashboard.refresh(_output2DimmerMapper); - }); - - // PID + _pidInputHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _pidOutputHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _pidErrorHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _pidSumHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _pidPTermHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _pidITermHistory.setX(_historyX, YASOLR_GRAPH_POINTS); + _pidDTermHistory.setX(_historyX, YASOLR_GRAPH_POINTS); _pidView.setTab(_pidTab); _pidPMode.setTab(_pidTab); @@ -756,7 +631,6 @@ void YaSolR::Website::begin() { _pidKd.setTab(_pidTab); _pidOutMin.setTab(_pidTab); _pidOutMax.setTab(_pidTab); - _pidInputHistory.setTab(_pidTab); _pidOutputHistory.setTab(_pidTab); _pidErrorHistory.setTab(_pidTab); @@ -765,6 +639,29 @@ void YaSolR::Website::begin() { _pidITermHistory.setTab(_pidTab); _pidDTermHistory.setTab(_pidTab); + _pidInputHistory.setSize(FULL_SIZE); + _pidOutputHistory.setSize(FULL_SIZE); + _pidErrorHistory.setSize(FULL_SIZE); + _pidSumHistory.setSize(FULL_SIZE); + _pidPTermHistory.setSize(FULL_SIZE); + _pidITermHistory.setSize(FULL_SIZE); + _pidDTermHistory.setSize(FULL_SIZE); + + _numConfig(_pidSetpoint, KEY_PID_SETPOINT); + _numConfig(_pidKp, KEY_PID_KP); + _numConfig(_pidKi, KEY_PID_KI); + _numConfig(_pidKd, KEY_PID_KD); + _numConfig(_pidOutMin, KEY_PID_OUT_MIN); + _numConfig(_pidOutMax, KEY_PID_OUT_MAX); + + _pidView.onChange([this](bool value) { + _pidView.setValue(value); + if (value) + resetPIDCharts(); + dashboard.refresh(_pidView); + dashboardInitTask.resume(); + }); + _pidPMode.onChange([](const char* value) { if (strcmp(value, YASOLR_PID_P_MODE_1) == 0) config.set(KEY_PID_P_MODE, "1"); @@ -804,42 +701,214 @@ void YaSolR::Website::begin() { dashboard.refresh(_pidICMode); }); - _numConfig(_pidSetpoint, KEY_PID_SETPOINT); - _numConfig(_pidOutMin, KEY_PID_OUT_MIN); - _numConfig(_pidOutMax, KEY_PID_OUT_MAX); - - _pidView.onChange([this](bool value) { - _pidView.setValue(value); - if (value) - resetPID(); - dashboard.refresh(_pidView); - dashboardInitTask.resume(); - }); - - _pidKp.onChange([](const std::optional value) { - if (value.has_value()) - config.set(KEY_PID_KP, dash::to_string(value.value())); - else - config.unset(KEY_PID_KP); - _pidKp.setValue(config.getFloat(KEY_PID_KP)); - dashboard.refresh(_pidKp); - }); - _pidKi.onChange([](const std::optional value) { - if (value.has_value()) - config.set(KEY_PID_KI, dash::to_string(value.value())); - else - config.unset(KEY_PID_KI); - _pidKi.setValue(config.getFloat(KEY_PID_KI)); - dashboard.refresh(_pidKi); - }); - _pidKd.onChange([](const std::optional value) { - if (value.has_value()) - config.set(KEY_PID_KD, dash::to_string(value.value())); + // tab: gpio + + _gpioTitle.setTab(_gpioTab); + _gpioSep1.setTab(_gpioTab); + _pinDimmerO1.setTab(_gpioTab); + _pinDS18O1.setTab(_gpioTab); + _pinRelayO1.setTab(_gpioTab); + _gpioSep2.setTab(_gpioTab); + _pinDimmerO2.setTab(_gpioTab); + _pinDS18O2.setTab(_gpioTab); + _pinRelayO2.setTab(_gpioTab); + _gpioSep3.setTab(_gpioTab); + _pinRelay1.setTab(_gpioTab); + _pinRelay2.setTab(_gpioTab); + _gpioSep4.setTab(_gpioTab); + _pinJsyRX.setTab(_gpioTab); + _pinJsyTX.setTab(_gpioTab); + _pinPZEMRX.setTab(_gpioTab); + _pinPZEMTX.setTab(_gpioTab); + _pinZCD.setTab(_gpioTab); + _gpioSep5.setTab(_gpioTab); + _pinDisplayClock.setTab(_gpioTab); + _pinDisplayData.setTab(_gpioTab); + _pinDS18Router.setTab(_gpioTab); + _pinLEDGreen.setTab(_gpioTab); + _pinLEDRed.setTab(_gpioTab); + _pinLEDYellow.setTab(_gpioTab); + + _gpioTitle.setCaption(YASOLR_LBL_131); + + _numConfig(_pinDimmerO1, KEY_PIN_OUTPUT1_DIMMER); + _numConfig(_pinDS18O1, KEY_PIN_OUTPUT1_DS18); + _numConfig(_pinRelayO1, KEY_PIN_OUTPUT1_RELAY); + _numConfig(_pinDimmerO2, KEY_PIN_OUTPUT2_DIMMER); + _numConfig(_pinDS18O2, KEY_PIN_OUTPUT2_DS18); + _numConfig(_pinRelayO2, KEY_PIN_OUTPUT2_RELAY); + _numConfig(_pinRelay1, KEY_PIN_RELAY1); + _numConfig(_pinRelay2, KEY_PIN_RELAY2); + _numConfig(_pinJsyRX, KEY_PIN_JSY_RX); + _numConfig(_pinJsyTX, KEY_PIN_JSY_TX); + _numConfig(_pinPZEMRX, KEY_PIN_PZEM_RX); + _numConfig(_pinPZEMTX, KEY_PIN_PZEM_TX); + _numConfig(_pinZCD, KEY_PIN_ZCD); + _numConfig(_pinDisplayClock, KEY_PIN_DISPLAY_SCL); + _numConfig(_pinDisplayData, KEY_PIN_DISPLAY_SDA); + _numConfig(_pinDS18Router, KEY_PIN_ROUTER_DS18); + _numConfig(_pinLEDGreen, KEY_PIN_LIGHTS_GREEN); + _numConfig(_pinLEDRed, KEY_PIN_LIGHTS_RED); + _numConfig(_pinLEDYellow, KEY_PIN_LIGHTS_YELLOW); + + // tab: hardware + + // grid + _gridSep.setTab(_hardwareConfigTab); + _gridFreq.setTab(_hardwareConfigTab); + _jsy.setTab(_hardwareConfigTab); + _jsyRemote.setTab(_hardwareConfigTab); + _zcd.setTab(_hardwareConfigTab); + _boolConfig(_jsy, KEY_ENABLE_JSY); + _boolConfig(_jsyRemote, KEY_ENABLE_JSY_REMOTE); + _boolConfig(_zcd, KEY_ENABLE_ZCD); + _gridFreq.onChange([](const char* value) { + if (strcmp(value, "50 Hz") == 0) + config.set(KEY_GRID_FREQUENCY, "50"); + else if (strcmp(value, "60 Hz") == 0) + config.set(KEY_GRID_FREQUENCY, "60"); else - config.unset(KEY_PID_KD); - _pidKd.setValue(config.getFloat(KEY_PID_KD)); - dashboard.refresh(_pidKd); + config.unset(KEY_GRID_FREQUENCY); + _gridFreq.setValue(config.get(KEY_GRID_FREQUENCY)); + dashboard.refresh(_gridFreq); }); + + // output 1 dimmer + _output1Dimmer.setTab(_hardwareConfigTab); + _output1Dimmer.setSize(FULL_SIZE); + _output1DimmerType.setTab(_hardwareConfigTab); + _output1DimmerMapper.setTab(_hardwareConfigTab); + _output1PZEM.setTab(_hardwareConfigTab); + _output1PZEMSync.setTab(_hardwareConfigTab); + _boolConfig(_output1Dimmer, KEY_ENABLE_OUTPUT1_DIMMER); + _textConfig(_output1DimmerType, KEY_OUTPUT1_DIMMER_TYPE); + _rangeConfig(_output1DimmerMapper, KEY_OUTPUT1_DIMMER_MIN, KEY_OUTPUT1_DIMMER_MAX); + _boolConfig(_output1PZEM, KEY_ENABLE_OUTPUT1_PZEM); + + // output 1 bypass relay + _output1Relay.setTab(_hardwareConfigTab); + _output1Relay.setSize(FULL_SIZE); + _output1RelayType.setTab(_hardwareConfigTab); + _boolConfig(_output1Relay, KEY_ENABLE_OUTPUT1_RELAY); + _textConfig(_output1RelayType, KEY_OUTPUT1_RELAY_TYPE); + + // output 1 ds18 + _output1DS18.setTab(_hardwareConfigTab); + _output1DS18.setSize(FULL_SIZE); + _boolConfig(_output1DS18, KEY_ENABLE_OUTPUT1_DS18); + + // output 2 dimmer + _output2Dimmer.setTab(_hardwareConfigTab); + _output2Dimmer.setSize(FULL_SIZE); + _output2DimmerType.setTab(_hardwareConfigTab); + _output2DimmerMapper.setTab(_hardwareConfigTab); + _output2PZEM.setTab(_hardwareConfigTab); + _output2PZEMSync.setTab(_hardwareConfigTab); + _boolConfig(_output2Dimmer, KEY_ENABLE_OUTPUT2_DIMMER); + _textConfig(_output2DimmerType, KEY_OUTPUT2_DIMMER_TYPE); + _rangeConfig(_output2DimmerMapper, KEY_OUTPUT2_DIMMER_MIN, KEY_OUTPUT2_DIMMER_MAX); + _boolConfig(_output2PZEM, KEY_ENABLE_OUTPUT2_PZEM); + + // output 2 bypass relay + _output2Relay.setTab(_hardwareConfigTab); + _output2Relay.setSize(FULL_SIZE); + _output2RelayType.setTab(_hardwareConfigTab); + _boolConfig(_output2Relay, KEY_ENABLE_OUTPUT2_RELAY); + _textConfig(_output2RelayType, KEY_OUTPUT2_RELAY_TYPE); + + // output 2 ds18 + _output2DS18.setTab(_hardwareConfigTab); + _output2DS18.setSize(FULL_SIZE); + _boolConfig(_output2DS18, KEY_ENABLE_OUTPUT2_DS18); + + // relay1 + _relay1.setTab(_hardwareConfigTab); + _relay1.setSize(FULL_SIZE); + _relay1Type.setTab(_hardwareConfigTab); + _relay1Load.setTab(_hardwareConfigTab); + _boolConfig(_relay1, KEY_ENABLE_RELAY1); + _numConfig(_relay1Load, KEY_RELAY1_LOAD); + _textConfig(_relay1Type, KEY_RELAY1_TYPE); + + // relay2 + _relay2.setTab(_hardwareConfigTab); + _relay2.setSize(FULL_SIZE); + _relay2Type.setTab(_hardwareConfigTab); + _relay2Load.setTab(_hardwareConfigTab); + _boolConfig(_relay2, KEY_ENABLE_RELAY2); + _textConfig(_relay2Type, KEY_RELAY2_TYPE); + _numConfig(_relay2Load, KEY_RELAY2_LOAD); + + // router ds18 + _routerDS18.setTab(_hardwareConfigTab); + _routerDS18.setSize(FULL_SIZE); + _boolConfig(_routerDS18, KEY_ENABLE_DS18_SYSTEM); + + // router led + _led.setTab(_hardwareConfigTab); + _led.setSize(FULL_SIZE); + _boolConfig(_led, KEY_ENABLE_LIGHTS); + + // display + _display.setTab(_hardwareConfigTab); + _display.setSize(FULL_SIZE); + _displayType.setTab(_hardwareConfigTab); + _displayRotation.setTab(_hardwareConfigTab); + _displaySpeed.setTab(_hardwareConfigTab); + _boolConfig(_display, KEY_ENABLE_DISPLAY); + _textConfig(_displayType, KEY_DISPLAY_TYPE); + _numConfig(_displayRotation, KEY_DISPLAY_ROTATION); + _sliderConfig(_displaySpeed, KEY_DISPLAY_SPEED); + + // tab: output 1 config + + _output1ConfigSep0.setTab(_output1ConfigTab); + _output1ResistanceInput.setTab(_output1ConfigTab); + _output1ResistanceCalibration.setTab(_output1ConfigTab); + _output1ConfigSep1.setTab(_output1ConfigTab); + _output1DimmerDutyLimiter.setTab(_output1ConfigTab); + _output1DimmerTempLimiter.setTab(_output1ConfigTab); + _output1DimmerExcessLimiter.setTab(_output1ConfigTab); + _output1ConfigSep2.setTab(_output1ConfigTab); + _output1AutoStartTemp.setTab(_output1ConfigTab); + _output1AutoStoptTemp.setTab(_output1ConfigTab); + _output1AutoStartTime.setTab(_output1ConfigTab); + _output1AutoStoptTime.setTab(_output1ConfigTab); + _output1AutoStartWDays.setTab(_output1ConfigTab); + _numConfig(_output1ResistanceInput, KEY_OUTPUT1_RESISTANCE); + _sliderConfig(_output1DimmerDutyLimiter, KEY_OUTPUT1_DIMMER_LIMIT); + _numConfig(_output1DimmerTempLimiter, KEY_OUTPUT1_DIMMER_TEMP_LIMITER); + _numConfig(_output1DimmerExcessLimiter, KEY_OUTPUT1_EXCESS_LIMITER); + _numConfig(_output1AutoStartTemp, KEY_OUTPUT1_TEMPERATURE_START); + _numConfig(_output1AutoStoptTemp, KEY_OUTPUT1_TEMPERATURE_STOP); + _textConfig(_output1AutoStartTime, KEY_OUTPUT1_TIME_START); + _textConfig(_output1AutoStoptTime, KEY_OUTPUT1_TIME_STOP); + _daysConfig(_output1AutoStartWDays, KEY_OUTPUT1_DAYS); + + // tab: output 2 config + + _output2ConfigSep0.setTab(_output2ConfigTab); + _output2ResistanceInput.setTab(_output2ConfigTab); + _output2ResistanceCalibration.setTab(_output2ConfigTab); + _output2ConfigSep1.setTab(_output2ConfigTab); + _output2DimmerDutyLimiter.setTab(_output2ConfigTab); + _output2DimmerTempLimiter.setTab(_output2ConfigTab); + _output2DimmerExcessLimiter.setTab(_output2ConfigTab); + _output2ConfigSep2.setTab(_output2ConfigTab); + _output2AutoStartTemp.setTab(_output2ConfigTab); + _output2AutoStoptTemp.setTab(_output2ConfigTab); + _output2AutoStartTime.setTab(_output2ConfigTab); + _output2AutoStoptTime.setTab(_output2ConfigTab); + _output2AutoStartWDays.setTab(_output2ConfigTab); + _numConfig(_output2ResistanceInput, KEY_OUTPUT2_RESISTANCE); + _sliderConfig(_output2DimmerDutyLimiter, KEY_OUTPUT2_DIMMER_LIMIT); + _numConfig(_output2DimmerTempLimiter, KEY_OUTPUT2_DIMMER_TEMP_LIMITER); + _numConfig(_output2DimmerExcessLimiter, KEY_OUTPUT2_EXCESS_LIMITER); + _numConfig(_output2AutoStartTemp, KEY_OUTPUT2_TEMPERATURE_START); + _numConfig(_output2AutoStoptTemp, KEY_OUTPUT2_TEMPERATURE_STOP); + _textConfig(_output2AutoStartTime, KEY_OUTPUT2_TIME_START); + _textConfig(_output2AutoStoptTime, KEY_OUTPUT2_TIME_STOP); + _daysConfig(_output2AutoStartWDays, KEY_OUTPUT2_DAYS); #endif initCards(); @@ -849,13 +918,14 @@ void YaSolR::Website::begin() { void YaSolR::Website::initCards() { logger.debug(TAG, "Initialize dashboard cards..."); - // Statistics + const Mycila::ESPConnect::Mode mode = espConnect.getMode(); + + // statistics - Mycila::ESPConnect::Mode mode = espConnect.getMode(); - _appManufacturer.setValue(Mycila::AppInfo.manufacturer.c_str()); - _appModel.setValue(Mycila::AppInfo.model.c_str()); _appName.setValue(Mycila::AppInfo.name.c_str()); + _appModel.setValue(Mycila::AppInfo.model.c_str()); _appVersion.setValue(Mycila::AppInfo.version.c_str()); + _appManufacturer.setValue(Mycila::AppInfo.manufacturer.c_str()); _deviceBootCount.setValue(Mycila::System::getBootCount()); _deviceBootReason.setValue(Mycila::System::getLastRebootReason()); _deviceCores.setValue(ESP.getChipCores()); @@ -864,19 +934,37 @@ void YaSolR::Website::initCards() { _firmwareBuildHash.setValue(Mycila::AppInfo.buildHash.c_str()); _firmwareBuildTimestamp.setValue(Mycila::AppInfo.buildDate.c_str()); _firmwareFilename.setValue(Mycila::AppInfo.firmware.c_str()); - _networkAPIP.setValue(espConnect.getIPAddress(Mycila::ESPConnect::Mode::AP).toString().c_str()); - _networkAPMAC.setValue(espConnect.getMACAddress(Mycila::ESPConnect::Mode::AP)); _networkHostname.setValue(Mycila::AppInfo.defaultHostname.c_str()); - _networkInterface.setValue(mode == Mycila::ESPConnect::Mode::AP ? "AP" : (mode == Mycila::ESPConnect::Mode::STA ? "WiFi" : (mode == Mycila::ESPConnect::Mode::ETH ? "Ethernet" : ""))); - _networkWiFiIP.setValue(espConnect.getIPAddress(Mycila::ESPConnect::Mode::STA).toString().c_str()); - _networkWiFiMAC.setValue(espConnect.getMACAddress(Mycila::ESPConnect::Mode::STA)); - _networkWiFiSSID.setValue(espConnect.getWiFiSSID()); -#ifdef ESPCONNECT_ETH_SUPPORT - _networkEthIP.setValue(espConnect.getIPAddress(Mycila::ESPConnect::Mode::ETH).toString().c_str()); - _networkEthMAC.setValue(espConnect.getMACAddress(Mycila::ESPConnect::Mode::ETH).empty() ? std::string("N/A") : espConnect.getMACAddress(Mycila::ESPConnect::Mode::ETH)); -#endif + + switch (mode) { + case Mycila::ESPConnect::Mode::AP: + _networkInterface.setValue("Access Point"); + _networkAPIP.setValue(espConnect.getIPAddress(Mycila::ESPConnect::Mode::AP).toString().c_str()); + _networkAPMAC.setValue(espConnect.getMACAddress(Mycila::ESPConnect::Mode::AP)); + break; + + case Mycila::ESPConnect::Mode::ETH: + _networkInterface.setValue("Ethernet"); + _networkEthIP.setValue(espConnect.getIPAddress(Mycila::ESPConnect::Mode::ETH).toString().c_str()); + _networkEthMAC.setValue(espConnect.getMACAddress(Mycila::ESPConnect::Mode::ETH).empty() ? std::string("N/A") : espConnect.getMACAddress(Mycila::ESPConnect::Mode::ETH)); + break; + + case Mycila::ESPConnect::Mode::STA: + _networkInterface.setValue("WiFi"); + _networkWiFiIP.setValue(espConnect.getIPAddress(Mycila::ESPConnect::Mode::STA).toString().c_str()); + _networkWiFiMAC.setValue(espConnect.getMACAddress(Mycila::ESPConnect::Mode::STA)); + _networkWiFiSSID.setValue(espConnect.getWiFiSSID()); + break; + + default: + _networkInterface.setValue("Unknown"); + break; + } + + // home if (!output1) { + // initialize values for OSS components which cannot be hidden _output1State.setFeedback("DISABLED", dash::Status::IDLE); _output1DS18State.setValue(NAN); _output1DimmerSlider.setValue(0); @@ -884,6 +972,7 @@ void YaSolR::Website::initCards() { } if (!output2) { + // initialize values for OSS components which cannot be hidden _output2State.setFeedback("DISABLED", dash::Status::IDLE); _output2DS18State.setValue(NAN); _output2DimmerSlider.setValue(0); @@ -891,54 +980,61 @@ void YaSolR::Website::initCards() { } #ifdef APP_MODEL_PRO - const bool jsyEnabled = config.getBool(KEY_ENABLE_JSY) && jsy && jsy->isEnabled(); - - // output 1 + const bool debugEnabled = config.getBool(KEY_ENABLE_DEBUG); + const bool jsyEnabled = config.getBool(KEY_ENABLE_JSY); + const bool mqttEnabled = config.getBool(KEY_ENABLE_MQTT); + const bool pidViewEnabled = realTimePIDEnabled(); + const bool displayEnabled = config.getBool(KEY_ENABLE_DISPLAY); + const bool serverCertExists = LittleFS.exists(YASOLR_MQTT_SERVER_CERT_FILE); - const bool dimmer1Enabled = config.getBool(KEY_ENABLE_OUTPUT1_DIMMER) && output1 && output1->isDimmerEnabled(); - const bool dimmer1Online = dimmer1Enabled && output1->isDimmerOnline(); - const bool output1RelayEnabled = config.getBool(KEY_ENABLE_OUTPUT1_RELAY) && output1 && output1->isBypassRelayEnabled(); - const bool bypass1Possible = dimmer1Online || output1RelayEnabled; + const bool dimmer1Enabled = config.getBool(KEY_ENABLE_OUTPUT1_DIMMER); + const bool output1RelayEnabled = config.getBool(KEY_ENABLE_OUTPUT1_RELAY); + const bool bypass1Possible = dimmer1Enabled || output1RelayEnabled; const bool autoDimmer1Activated = config.getBool(KEY_ENABLE_OUTPUT1_AUTO_DIMMER); const bool autoBypass1Activated = config.getBool(KEY_ENABLE_OUTPUT1_AUTO_BYPASS); - const bool output1TempEnabled = output1 && !output1->temperature().neverUpdated(); - const bool pzem1Enabled = config.getBool(KEY_ENABLE_OUTPUT1_PZEM) && pzemO1 && pzemO1->isEnabled(); - const char* output1Days = config.get(KEY_OUTPUT1_DAYS); + const bool output1TempReceived = output1 && !output1->temperature().neverUpdated(); + const bool pzem1Enabled = config.getBool(KEY_ENABLE_OUTPUT1_PZEM); + + const bool dimmer2Enabled = config.getBool(KEY_ENABLE_OUTPUT2_DIMMER); + const bool output2RelayEnabled = config.getBool(KEY_ENABLE_OUTPUT2_RELAY); + const bool bypass2Possible = dimmer2Enabled || output2RelayEnabled; + const bool autoDimmer2Activated = config.getBool(KEY_ENABLE_OUTPUT2_AUTO_DIMMER); + const bool autoBypass2Activated = config.getBool(KEY_ENABLE_OUTPUT2_AUTO_BYPASS); + const bool output2TempReceived = output2 && !output2->temperature().neverUpdated(); + const bool pzem2Enabled = config.getBool(KEY_ENABLE_OUTPUT2_PZEM); + + const bool relay1Enabled = config.getBool(KEY_ENABLE_RELAY1); + const bool relay2Enabled = config.getBool(KEY_ENABLE_RELAY2); + const uint16_t load1 = config.getInt(KEY_RELAY1_LOAD); + const uint16_t load2 = config.getInt(KEY_RELAY2_LOAD); + + // statistics + + _udpMessageRateBuffer.setDisplay(config.getBool(KEY_ENABLE_JSY_REMOTE)); + _networkAPIP.setDisplay(mode == Mycila::ESPConnect::Mode::AP); + _networkAPMAC.setDisplay(mode == Mycila::ESPConnect::Mode::AP); + _networkEthIP.setDisplay(mode == Mycila::ESPConnect::Mode::ETH); + _networkEthMAC.setDisplay(mode == Mycila::ESPConnect::Mode::ETH); + _networkWiFiIP.setDisplay(mode == Mycila::ESPConnect::Mode::STA); + _networkWiFiMAC.setDisplay(mode == Mycila::ESPConnect::Mode::STA); + _networkWiFiSSID.setDisplay(mode == Mycila::ESPConnect::Mode::STA); + _output1RelaySwitchCount.setDisplay(output1 && output1->isBypassRelayEnabled()); + _output2RelaySwitchCount.setDisplay(output2 && output2->isBypassRelayEnabled()); + _relay1SwitchCount.setDisplay(relay1 && relay1->isEnabled()); + _relay2SwitchCount.setDisplay(relay2 && relay2->isEnabled()); + + // tabs + + _output1Tab.setDisplay(dimmer1Enabled || output1RelayEnabled || output1TempReceived); + _output2Tab.setDisplay(dimmer2Enabled || output2RelayEnabled || output2TempReceived); + _relaysTab.setDisplay(relay1Enabled || relay2Enabled); + _output1ConfigTab.setDisplay(dimmer1Enabled || output1RelayEnabled); + _output2ConfigTab.setDisplay(dimmer2Enabled || output2RelayEnabled); + + // tab: output 1 _output1DimmerAuto.setValue(autoDimmer1Activated); - _output1DimmerExcessLimiter.setValue(config.getInt(KEY_OUTPUT1_EXCESS_LIMITER)); - _output1DimmerDutyLimiter.setValue(config.getInt(KEY_OUTPUT1_DIMMER_LIMIT)); - _output1DimmerTempLimiter.setValue(config.getInt(KEY_OUTPUT1_DIMMER_TEMP_LIMITER)); _output1BypassAuto.setValue(autoBypass1Activated); - _output1AutoStartWDays.setValue(strcmp(output1Days, YASOLR_WEEK_DAYS_EMPTY) == 0 ? "" : output1Days); - _output1AutoStartTemp.setValue(config.getInt(KEY_OUTPUT1_TEMPERATURE_START)); - _output1AutoStartTime.setValue(config.get(KEY_OUTPUT1_TIME_START)); - _output1AutoStoptTemp.setValue(config.getInt(KEY_OUTPUT1_TEMPERATURE_STOP)); - _output1AutoStoptTime.setValue(config.get(KEY_OUTPUT1_TIME_STOP)); - - _output1Tab.setDisplay(dimmer1Enabled || output1RelayEnabled || output1TempEnabled); - _output1DimmerSlider.setDisplay(dimmer1Online && !autoDimmer1Activated); - _output1DimmerSliderRO.setDisplay(dimmer1Enabled && autoDimmer1Activated); - _output1Bypass.setDisplay(bypass1Possible && !autoBypass1Activated); - _output1BypassRO.setDisplay(bypass1Possible && autoBypass1Activated); - _output1Power.setDisplay(dimmer1Online && pzem1Enabled); - _output1ApparentPower.setDisplay(dimmer1Online && pzem1Enabled); - _output1PowerFactor.setDisplay(dimmer1Online && pzem1Enabled); - _output1THDi.setDisplay(dimmer1Online && pzem1Enabled); - _output1Voltage.setDisplay(dimmer1Online && pzem1Enabled); - _output1Current.setDisplay(dimmer1Online && pzem1Enabled); - _output1Resistance.setDisplay(dimmer1Online && pzem1Enabled); - _output1Energy.setDisplay(dimmer1Online && pzem1Enabled); - _output1DimmerAuto.setDisplay(dimmer1Enabled); - _output1DimmerExcessLimiter.setDisplay(dimmer1Enabled); - _output1DimmerDutyLimiter.setDisplay(dimmer1Enabled); - _output1DimmerTempLimiter.setDisplay(dimmer1Enabled && output1TempEnabled); - _output1BypassAuto.setDisplay(bypass1Possible); - _output1AutoStartWDays.setDisplay(bypass1Possible && autoBypass1Activated); - _output1AutoStartTime.setDisplay(bypass1Possible && autoBypass1Activated); - _output1AutoStoptTime.setDisplay(bypass1Possible && autoBypass1Activated); - _output1AutoStartTemp.setDisplay(bypass1Possible && autoBypass1Activated && output1TempEnabled); - _output1AutoStoptTemp.setDisplay(bypass1Possible && autoBypass1Activated && output1TempEnabled); if (!output1) { _output1DimmerSliderRO.setValue(0); @@ -953,52 +1049,25 @@ void YaSolR::Website::initCards() { _output1Energy.setValue(0); } - // output 2 - - const bool dimmer2Enabled = config.getBool(KEY_ENABLE_OUTPUT2_DIMMER) && output2 && output2->isDimmerEnabled(); - const bool dimmer2Online = dimmer2Enabled && output2->isDimmerOnline(); - const bool output2RelayEnabled = config.getBool(KEY_ENABLE_OUTPUT2_RELAY) && output2 && output2->isBypassRelayEnabled(); - const bool bypass2Possible = dimmer2Online || output2RelayEnabled; - const bool autoDimmer2Activated = config.getBool(KEY_ENABLE_OUTPUT2_AUTO_DIMMER); - const bool autoBypass2Activated = config.getBool(KEY_ENABLE_OUTPUT2_AUTO_BYPASS); - const bool output2TempEnabled = output2 && !output2->temperature().neverUpdated(); - const bool pzem2Enabled = config.getBool(KEY_ENABLE_OUTPUT2_PZEM) && pzemO2 && pzemO2->isEnabled(); - const char* output2Days = config.get(KEY_OUTPUT2_DAYS); - - _output2DimmerAuto.setValue(autoDimmer2Activated); - _output2DimmerExcessLimiter.setValue(config.getInt(KEY_OUTPUT2_EXCESS_LIMITER)); - _output2DimmerDutyLimiter.setValue(config.getInt(KEY_OUTPUT2_DIMMER_LIMIT)); - _output2DimmerTempLimiter.setValue(config.getInt(KEY_OUTPUT2_DIMMER_TEMP_LIMITER)); - _output2BypassAuto.setValue(autoBypass2Activated); - _output2AutoStartWDays.setValue(strcmp(output2Days, YASOLR_WEEK_DAYS_EMPTY) == 0 ? "" : output2Days); - _output2AutoStartTemp.setValue(config.getInt(KEY_OUTPUT2_TEMPERATURE_START)); - _output2AutoStartTime.setValue(config.get(KEY_OUTPUT2_TIME_START)); - _output2AutoStoptTemp.setValue(config.getInt(KEY_OUTPUT2_TEMPERATURE_STOP)); - _output2AutoStoptTime.setValue(config.get(KEY_OUTPUT2_TIME_STOP)); - - _output2Tab.setDisplay(dimmer2Enabled || output2RelayEnabled || output2TempEnabled); - _output2DimmerSlider.setDisplay(dimmer2Online && !autoDimmer2Activated); - _output2DimmerSliderRO.setDisplay(dimmer2Enabled && autoDimmer2Activated); - _output2Bypass.setDisplay(bypass2Possible && !autoBypass2Activated); - _output2BypassRO.setDisplay(bypass2Possible && autoBypass2Activated); - _output2Power.setDisplay(dimmer2Online && pzem2Enabled); - _output2ApparentPower.setDisplay(dimmer2Online && pzem2Enabled); - _output2PowerFactor.setDisplay(dimmer2Online && pzem2Enabled); - _output2THDi.setDisplay(dimmer2Online && pzem2Enabled); - _output2Voltage.setDisplay(dimmer2Online && pzem2Enabled); - _output2Current.setDisplay(dimmer2Online && pzem2Enabled); - _output2Resistance.setDisplay(dimmer2Online && pzem2Enabled); - _output2Energy.setDisplay(dimmer2Online && pzem2Enabled); - _output2DimmerAuto.setDisplay(dimmer2Enabled); - _output2DimmerExcessLimiter.setDisplay(dimmer2Enabled); - _output2DimmerDutyLimiter.setDisplay(dimmer2Enabled); - _output2DimmerTempLimiter.setDisplay(dimmer2Enabled && output2TempEnabled); - _output2BypassAuto.setDisplay(bypass2Possible); - _output2AutoStartWDays.setDisplay(bypass2Possible && autoBypass2Activated); - _output2AutoStartTime.setDisplay(bypass2Possible && autoBypass2Activated); - _output2AutoStoptTime.setDisplay(bypass2Possible && autoBypass2Activated); - _output2AutoStartTemp.setDisplay(bypass2Possible && autoBypass2Activated && output2TempEnabled); - _output2AutoStoptTemp.setDisplay(bypass2Possible && autoBypass2Activated && output2TempEnabled); + _output1DimmerAuto.setDisplay(dimmer1Enabled); + _output1DimmerSlider.setDisplay(dimmer1Enabled && !autoDimmer1Activated); + _output1DimmerSliderRO.setDisplay(dimmer1Enabled && autoDimmer1Activated); + _output1Power.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1ApparentPower.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1PowerFactor.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1THDi.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1Voltage.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1Current.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1Resistance.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1Energy.setDisplay(dimmer1Enabled && pzem1Enabled); + _output1BypassAuto.setDisplay(bypass1Possible); + _output1Bypass.setDisplay(bypass1Possible && !autoBypass1Activated); + _output1BypassRO.setDisplay(bypass1Possible && autoBypass1Activated); + + // tab: output 2 + + _output2DimmerAuto.setValue(autoDimmer2Activated); + _output2BypassAuto.setValue(autoBypass2Activated); if (!output2) { _output2DimmerSliderRO.setValue(0); @@ -1013,156 +1082,94 @@ void YaSolR::Website::initCards() { _output2Energy.setValue(0); } - // relays + _output2DimmerAuto.setDisplay(dimmer2Enabled); + _output2DimmerSlider.setDisplay(dimmer2Enabled && !autoDimmer2Activated); + _output2DimmerSliderRO.setDisplay(dimmer2Enabled && autoDimmer2Activated); + _output2Power.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2ApparentPower.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2PowerFactor.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2THDi.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2Voltage.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2Current.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2Resistance.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2Energy.setDisplay(dimmer2Enabled && pzem2Enabled); + _output2BypassAuto.setDisplay(bypass2Possible); + _output2Bypass.setDisplay(bypass2Possible && !autoBypass2Activated); + _output2BypassRO.setDisplay(bypass2Possible && autoBypass2Activated); + + // tab: relays - const uint16_t load1 = config.getInt(KEY_RELAY1_LOAD); - const uint16_t load2 = config.getInt(KEY_RELAY2_LOAD); - const bool relay1Enabled = config.getBool(KEY_ENABLE_RELAY1) && relay1 && relay1->isEnabled(); - const bool relay2Enabled = config.getBool(KEY_ENABLE_RELAY2) && relay2 && relay2->isEnabled(); - _relaysTab.setDisplay(relay1Enabled || relay2Enabled); _relay1Switch.setDisplay(relay1Enabled && load1 <= 0); _relay1SwitchRO.setDisplay(relay1Enabled && load1 > 0); _relay2Switch.setDisplay(relay2Enabled && load2 <= 0); _relay2SwitchRO.setDisplay(relay2Enabled && load2 > 0); - // management + // tab: system _configBackup.setValue("/api/config/backup"); _configRestore.setValue("/api/config/restore"); - _consoleLink.setValue("/console"); + + // tab: debug + + _status(_debugMode, KEY_ENABLE_DEBUG, logger.isDebugEnabled()); _debugInfo.setValue("/api/debug"); - _energyReset.setDisplay(jsyEnabled || pzem1Enabled || pzem2Enabled); - _consoleLink.setDisplay(logger.isDebugEnabled()); - _debugInfo.setDisplay(logger.isDebugEnabled()); + _consoleLink.setValue("/console"); + + _debugInfo.setDisplay(debugEnabled); + _consoleLink.setDisplay(debugEnabled); + _reset.setDisplay(debugEnabled); + _energyReset.setDisplay(debugEnabled && (jsyEnabled || pzem1Enabled || pzem2Enabled)); - // network + // tab: network _adminPwd.setValue(config.get(KEY_ADMIN_PASSWORD)); - _apMode.setValue(config.getBool(KEY_ENABLE_AP_MODE)); - _ntpServer.setValue(config.get(KEY_NTP_SERVER)); - _ntpTimezone.setValue(config.get(KEY_NTP_TIMEZONE)); - _wifiPwd.setValue(config.get(KEY_WIFI_PASSWORD)); _wifiSSID.setValue(config.get(KEY_WIFI_SSID)); + _wifiPwd.setValue(config.get(KEY_WIFI_PASSWORD)); + _apMode.setValue(config.getBool(KEY_ENABLE_AP_MODE)); _staticIP.setValue(config.get(KEY_NET_IP)); _subnetMask.setValue(config.get(KEY_NET_SUBNET)); _gateway.setValue(config.get(KEY_NET_GATEWAY)); _dnsServer.setValue(config.get(KEY_NET_DNS)); - // mqtt + // tab: ntp - _haDiscovery.setValue(config.getBool(KEY_ENABLE_HA_DISCOVERY)); - _haDiscoveryTopic.setValue(config.get(KEY_HA_DISCOVERY_TOPIC)); - _mqttGridPower.setValue(config.get(KEY_GRID_POWER_MQTT_TOPIC)); - _mqttGridVoltage.setValue(config.get(KEY_GRID_VOLTAGE_MQTT_TOPIC)); - _mqttTempO1.setValue(config.get(KEY_OUTPUT1_TEMPERATURE_MQTT_TOPIC)); - _mqttTempO2.setValue(config.get(KEY_OUTPUT2_TEMPERATURE_MQTT_TOPIC)); + _ntpServer.setValue(config.get(KEY_NTP_SERVER)); + _ntpTimezone.setValue(config.get(KEY_NTP_TIMEZONE)); + + // tab: mqtt + + _mqttServer.setValue(config.get(KEY_MQTT_SERVER)); + _mqttServer.setDisplay(mqttEnabled); _mqttPort.setValue(config.getInt(KEY_MQTT_PORT)); - _mqttPublishInterval.setValue(config.getInt(KEY_MQTT_PUBLISH_INTERVAL)); + _mqttPort.setDisplay(mqttEnabled); + _mqttUser.setValue(config.get(KEY_MQTT_USERNAME)); + _mqttUser.setDisplay(mqttEnabled); _mqttPwd.setValue(config.get(KEY_MQTT_PASSWORD)); + _mqttPwd.setDisplay(mqttEnabled); _mqttSecured.setValue(config.getBool(KEY_MQTT_SECURED)); - _mqttServer.setValue(config.get(KEY_MQTT_SERVER)); + _mqttSecured.setDisplay(mqttEnabled); _mqttServerCert.setValue("/api/config/mqttServerCertificate"); + _mqttServerCert.setDisplay(mqttEnabled && !serverCertExists); + _mqttServerCertDelete.setDisplay(mqttEnabled && serverCertExists); _mqttTopic.setValue(config.get(KEY_MQTT_TOPIC)); - _mqttUser.setValue(config.get(KEY_MQTT_USERNAME)); - - const bool serverCertExists = LittleFS.exists(YASOLR_MQTT_SERVER_CERT_FILE); - _mqttConfigTab.setDisplay(config.getBool(KEY_ENABLE_MQTT)); - _mqttServerCert.setDisplay(!serverCertExists); - _mqttServerCertDelete.setDisplay(serverCertExists); - - _haDiscoveryTopic.setDisplay(config.getBool(KEY_ENABLE_HA_DISCOVERY)); - - // GPIO - - std::unordered_map*> pinout = {}; - _pinout(_pinDimmerO1, KEY_PIN_OUTPUT1_DIMMER, pinout); - _pinout(_pinDimmerO2, KEY_PIN_OUTPUT2_DIMMER, pinout); - _pinout(_pinDisplayClock, KEY_PIN_DISPLAY_SCL, pinout); - _pinout(_pinDisplayData, KEY_PIN_DISPLAY_SDA, pinout); - _pinout(_pinDS18O1, KEY_PIN_OUTPUT1_DS18, pinout); - _pinout(_pinDS18O2, KEY_PIN_OUTPUT2_DS18, pinout); - _pinout(_pinDS18Router, KEY_PIN_ROUTER_DS18, pinout); - _pinout(_pinJsyRX, KEY_PIN_JSY_RX, pinout); - _pinout(_pinJsyTX, KEY_PIN_JSY_TX, pinout); - _pinout(_pinLEDGreen, KEY_PIN_LIGHTS_GREEN, pinout); - _pinout(_pinLEDRed, KEY_PIN_LIGHTS_RED, pinout); - _pinout(_pinLEDYellow, KEY_PIN_LIGHTS_YELLOW, pinout); - _pinout(_pinPZEMRX, KEY_PIN_PZEM_RX, pinout); - _pinout(_pinPZEMTX, KEY_PIN_PZEM_TX, pinout); - _pinout(_pinRelay1, KEY_PIN_RELAY1, pinout); - _pinout(_pinRelay2, KEY_PIN_RELAY2, pinout); - _pinout(_pinRelayO1, KEY_PIN_OUTPUT1_RELAY, pinout); - _pinout(_pinRelayO2, KEY_PIN_OUTPUT2_RELAY, pinout); - _pinout(_pinZCD, KEY_PIN_ZCD, pinout); - pinout.clear(); - - // Hardware - - _status(_debugMode, KEY_ENABLE_DEBUG, logger.isDebugEnabled()); - _status(_display, KEY_ENABLE_DISPLAY, display && display->isEnabled()); - _status(_jsyRemote, KEY_ENABLE_JSY_REMOTE, udp && udp->connected()); - _status(_led, KEY_ENABLE_LIGHTS, lights.isEnabled()); - _status(_output1Relay, KEY_ENABLE_OUTPUT1_RELAY, output1 && output1->isBypassRelayEnabled()); - _status(_output2Relay, KEY_ENABLE_OUTPUT2_RELAY, output2 && output2->isBypassRelayEnabled()); - _status(_relay1, KEY_ENABLE_RELAY1, relay1 && relay1->isEnabled()); - _status(_relay2, KEY_ENABLE_RELAY2, relay2 && relay2->isEnabled()); - - // Hardware Config - - switch (config.getInt(KEY_GRID_FREQUENCY)) { - case 50: - _gridFreq.setValue("50 Hz"); - break; - case 60: - _gridFreq.setValue("60 Hz"); - break; - default: - _gridFreq.setValue("Auto-detect"); - break; - } - - _displayRotation.setValue(config.getInt(KEY_DISPLAY_ROTATION)); - _displaySpeed.setValue(config.getInt(KEY_DISPLAY_SPEED)); - _displayType.setValue(config.get(KEY_DISPLAY_TYPE)); - _output1DimmerType.setValue(config.get(KEY_OUTPUT1_DIMMER_TYPE)); - _output1RelayType.setValue(config.get(KEY_OUTPUT1_RELAY_TYPE)); - _output1ResistanceInput.setValue(config.getFloat(KEY_OUTPUT1_RESISTANCE)); - _output1ResistanceInput.setStatus(_output1ResistanceInput.value() > 0 ? dash::Status::SUCCESS : dash::Status::DANGER); // needs to be after set value - _output2DimmerType.setValue(config.get(KEY_OUTPUT2_DIMMER_TYPE)); - _output2RelayType.setValue(config.get(KEY_OUTPUT2_RELAY_TYPE)); - _output2ResistanceInput.setValue(config.getFloat(KEY_OUTPUT2_RESISTANCE)); - _output2ResistanceInput.setStatus(_output2ResistanceInput.value() > 0 ? dash::Status::SUCCESS : dash::Status::DANGER); // needs to be after set value - _relay1Load.setValue(load1); - _relay1Type.setValue(config.get(KEY_RELAY1_TYPE)); - _relay2Load.setValue(load2); - _relay2Type.setValue(config.get(KEY_RELAY2_TYPE)); - _output1DimmerMapper.setValue({static_cast(config.getInt(KEY_OUTPUT1_DIMMER_MIN)), - static_cast(config.getInt(KEY_OUTPUT1_DIMMER_MAX))}); - _output2DimmerMapper.setValue({static_cast(config.getInt(KEY_OUTPUT2_DIMMER_MIN)), - static_cast(config.getInt(KEY_OUTPUT2_DIMMER_MAX))}); - _displayRotation.setDisplay(config.getBool(KEY_ENABLE_DISPLAY)); - _displaySpeed.setDisplay(config.getBool(KEY_ENABLE_DISPLAY)); - _displayType.setDisplay(config.getBool(KEY_ENABLE_DISPLAY)); - _output1DimmerMapper.setDisplay(dimmer1Enabled); - _output1PZEMSync.setDisplay(pzem1Enabled); - _output1DimmerType.setDisplay(config.getBool(KEY_ENABLE_OUTPUT1_DIMMER)); - _output1RelayType.setDisplay(config.getBool(KEY_ENABLE_OUTPUT1_RELAY)); - _output1ResistanceInput.setDisplay(dimmer1Enabled); - _output2DimmerMapper.setDisplay(dimmer2Enabled); - _output2PZEMSync.setDisplay(pzem2Enabled); - _output2DimmerType.setDisplay(config.getBool(KEY_ENABLE_OUTPUT2_DIMMER)); - _output2RelayType.setDisplay(config.getBool(KEY_ENABLE_OUTPUT2_RELAY)); - _output2ResistanceInput.setDisplay(dimmer2Enabled); - _relay1Load.setDisplay(relay1Enabled); - _relay1Type.setDisplay(relay1Enabled); - _relay2Load.setDisplay(relay2Enabled); - _relay2Type.setDisplay(relay2Enabled); - _resistanceCalibration.setDisplay((dimmer1Online && jsyEnabled) || - (dimmer1Online && pzem1Enabled) || - (dimmer2Online && jsyEnabled) || - (dimmer2Online && pzem2Enabled)); + _mqttTopic.setDisplay(mqttEnabled); + _mqttPublishInterval.setValue(config.getInt(KEY_MQTT_PUBLISH_INTERVAL)); + _mqttPublishInterval.setDisplay(mqttEnabled); + _mqttSep1.setDisplay(mqttEnabled); + _mqttGridVoltage.setValue(config.get(KEY_GRID_VOLTAGE_MQTT_TOPIC)); + _mqttGridVoltage.setDisplay(mqttEnabled); + _mqttGridPower.setValue(config.get(KEY_GRID_POWER_MQTT_TOPIC)); + _mqttGridPower.setDisplay(mqttEnabled); + _mqttTempO1.setValue(config.get(KEY_OUTPUT1_TEMPERATURE_MQTT_TOPIC)); + _mqttTempO1.setDisplay(mqttEnabled); + _mqttTempO2.setValue(config.get(KEY_OUTPUT2_TEMPERATURE_MQTT_TOPIC)); + _mqttTempO2.setDisplay(mqttEnabled); + _haDiscovery.setValue(config.getBool(KEY_ENABLE_HA_DISCOVERY)); + _haDiscovery.setDisplay(mqttEnabled); + _haDiscoveryTopic.setValue(config.get(KEY_HA_DISCOVERY_TOPIC)); + _haDiscoveryTopic.setDisplay(mqttEnabled && config.getBool(KEY_ENABLE_HA_DISCOVERY)); - // PID + // tab: pid switch (config.getInt(KEY_PID_P_MODE)) { case 1: @@ -1178,6 +1185,7 @@ void YaSolR::Website::initCards() { _pidPMode.setValue(""); break; } + switch (config.getInt(KEY_PID_D_MODE)) { case 1: _pidDMode.setValue(YASOLR_PID_D_MODE_1); @@ -1189,6 +1197,7 @@ void YaSolR::Website::initCards() { _pidDMode.setValue(""); break; } + switch (config.getInt(KEY_PID_IC_MODE)) { case 0: _pidICMode.setValue(YASOLR_PID_IC_MODE_0); @@ -1203,6 +1212,7 @@ void YaSolR::Website::initCards() { _pidICMode.setValue(""); break; } + _pidSetpoint.setValue(config.getInt(KEY_PID_SETPOINT)); _pidKp.setValue(config.getFloat(KEY_PID_KP)); _pidKi.setValue(config.getFloat(KEY_PID_KI)); @@ -1210,7 +1220,6 @@ void YaSolR::Website::initCards() { _pidOutMin.setValue(config.getInt(KEY_PID_OUT_MIN)); _pidOutMax.setValue(config.getInt(KEY_PID_OUT_MAX)); - const bool pidViewEnabled = pidCharts(); _pidInputHistory.setDisplay(pidViewEnabled); _pidOutputHistory.setDisplay(pidViewEnabled); _pidErrorHistory.setDisplay(pidViewEnabled); @@ -1218,6 +1227,149 @@ void YaSolR::Website::initCards() { _pidPTermHistory.setDisplay(pidViewEnabled); _pidITermHistory.setDisplay(pidViewEnabled); _pidDTermHistory.setDisplay(pidViewEnabled); + + // tab: gpio + + std::unordered_map*> pinout = {}; + _pinout(_pinDimmerO1, KEY_PIN_OUTPUT1_DIMMER, pinout); + _pinout(_pinDS18O1, KEY_PIN_OUTPUT1_DS18, pinout); + _pinout(_pinRelayO1, KEY_PIN_OUTPUT1_RELAY, pinout); + _pinout(_pinDimmerO2, KEY_PIN_OUTPUT2_DIMMER, pinout); + _pinout(_pinDS18O2, KEY_PIN_OUTPUT2_DS18, pinout); + _pinout(_pinRelayO2, KEY_PIN_OUTPUT2_RELAY, pinout); + _pinout(_pinRelay1, KEY_PIN_RELAY1, pinout); + _pinout(_pinRelay2, KEY_PIN_RELAY2, pinout); + _pinout(_pinJsyRX, KEY_PIN_JSY_RX, pinout); + _pinout(_pinJsyTX, KEY_PIN_JSY_TX, pinout); + _pinout(_pinPZEMRX, KEY_PIN_PZEM_RX, pinout); + _pinout(_pinPZEMTX, KEY_PIN_PZEM_TX, pinout); + _pinout(_pinZCD, KEY_PIN_ZCD, pinout); + _pinout(_pinDisplayClock, KEY_PIN_DISPLAY_SCL, pinout); + _pinout(_pinDisplayData, KEY_PIN_DISPLAY_SDA, pinout); + _pinout(_pinDS18Router, KEY_PIN_ROUTER_DS18, pinout); + _pinout(_pinLEDGreen, KEY_PIN_LIGHTS_GREEN, pinout); + _pinout(_pinLEDRed, KEY_PIN_LIGHTS_RED, pinout); + _pinout(_pinLEDYellow, KEY_PIN_LIGHTS_YELLOW, pinout); + + // tab: hardware + + // grid + switch (config.getInt(KEY_GRID_FREQUENCY)) { + case 50: + _gridFreq.setValue("50 Hz"); + break; + case 60: + _gridFreq.setValue("60 Hz"); + break; + default: + _gridFreq.setValue("Auto-detect"); + break; + } + _status(_jsyRemote, KEY_ENABLE_JSY_REMOTE, udp && udp->connected(), YASOLR_LBL_113); + + // output 1 dimmer + _output1DimmerType.setValue(config.get(KEY_OUTPUT1_DIMMER_TYPE)); + _output1DimmerType.setDisplay(dimmer1Enabled); + _output1DimmerMapper.setValue({static_cast(config.getInt(KEY_OUTPUT1_DIMMER_MIN)), static_cast(config.getInt(KEY_OUTPUT1_DIMMER_MAX))}); + _output1DimmerMapper.setDisplay(dimmer1Enabled); + _output1PZEM.setDisplay(dimmer1Enabled); + _output1PZEMSync.setDisplay(dimmer1Enabled && pzem1Enabled); + + // output 1 bypass relay + _status(_output1Relay, KEY_ENABLE_OUTPUT1_RELAY, output1 && output1->isBypassRelayEnabled()); + _output1RelayType.setValue(config.get(KEY_OUTPUT1_RELAY_TYPE)); + _output1RelayType.setDisplay(output1RelayEnabled); + + // output 2 dimmer + _output2DimmerType.setValue(config.get(KEY_OUTPUT2_DIMMER_TYPE)); + _output2DimmerType.setDisplay(dimmer2Enabled); + _output2DimmerMapper.setValue({static_cast(config.getInt(KEY_OUTPUT2_DIMMER_MIN)), static_cast(config.getInt(KEY_OUTPUT2_DIMMER_MAX))}); + _output2DimmerMapper.setDisplay(dimmer2Enabled); + _output2PZEM.setDisplay(dimmer2Enabled); + _output2PZEMSync.setDisplay(dimmer2Enabled && pzem2Enabled); + + // output 2 bypass relay + _status(_output2Relay, KEY_ENABLE_OUTPUT2_RELAY, output2 && output2->isBypassRelayEnabled()); + _output2RelayType.setValue(config.get(KEY_OUTPUT2_RELAY_TYPE)); + _output2RelayType.setDisplay(output2RelayEnabled); + + // relay1 + _status(_relay1, KEY_ENABLE_RELAY1, relay1 && relay1->isEnabled()); + _relay1Type.setValue(config.get(KEY_RELAY1_TYPE)); + _relay1Type.setDisplay(relay1Enabled); + _relay1Load.setValue(load1); + _relay1Load.setDisplay(relay1Enabled); + + // relay2 + _status(_relay2, KEY_ENABLE_RELAY2, relay2 && relay2->isEnabled()); + _relay2Type.setValue(config.get(KEY_RELAY2_TYPE)); + _relay2Type.setDisplay(relay2Enabled); + _relay2Load.setValue(load2); + _relay2Load.setDisplay(relay2Enabled); + + // router led + _status(_led, KEY_ENABLE_LIGHTS, lights.isEnabled()); + + // display + _status(_display, KEY_ENABLE_DISPLAY, display && display->isEnabled()); + _displayType.setValue(config.get(KEY_DISPLAY_TYPE)); + _displayType.setDisplay(displayEnabled); + _displayRotation.setValue(config.getInt(KEY_DISPLAY_ROTATION)); + _displayRotation.setDisplay(displayEnabled); + _displaySpeed.setValue(config.getInt(KEY_DISPLAY_SPEED)); + _displaySpeed.setDisplay(displayEnabled); + + // tab: output 1 config + + _output1ConfigSep0.setDisplay(dimmer1Enabled); + _output1ResistanceInput.setValue(config.getFloat(KEY_OUTPUT1_RESISTANCE)); + _output1ResistanceInput.setStatus(_output1ResistanceInput.value() > 0 ? dash::Status::SUCCESS : dash::Status::DANGER); // needs to be after set value + _output1ResistanceInput.setDisplay(dimmer1Enabled); + _output1ResistanceCalibration.setDisplay((dimmer1Enabled && jsyEnabled) || (dimmer1Enabled && pzem1Enabled)); + _output1ConfigSep1.setDisplay(dimmer1Enabled); + _output1DimmerDutyLimiter.setValue(config.getInt(KEY_OUTPUT1_DIMMER_LIMIT)); + _output1DimmerDutyLimiter.setDisplay(dimmer1Enabled); + _output1DimmerTempLimiter.setValue(config.getInt(KEY_OUTPUT1_DIMMER_TEMP_LIMITER)); + _output1DimmerTempLimiter.setDisplay(dimmer1Enabled); + _output1DimmerExcessLimiter.setValue(config.getInt(KEY_OUTPUT1_EXCESS_LIMITER)); + _output1DimmerExcessLimiter.setDisplay(dimmer1Enabled); + _output1ConfigSep2.setDisplay(bypass1Possible); + _output1AutoStartTemp.setValue(config.getInt(KEY_OUTPUT1_TEMPERATURE_START)); + _output1AutoStartTemp.setDisplay(bypass1Possible); + _output1AutoStoptTemp.setValue(config.getInt(KEY_OUTPUT1_TEMPERATURE_STOP)); + _output1AutoStoptTemp.setDisplay(bypass1Possible); + _output1AutoStartTime.setValue(config.get(KEY_OUTPUT1_TIME_START)); + _output1AutoStartTime.setDisplay(bypass1Possible); + _output1AutoStoptTime.setValue(config.get(KEY_OUTPUT1_TIME_STOP)); + _output1AutoStoptTime.setDisplay(bypass1Possible); + _output1AutoStartWDays.setValue(config.isEqual(KEY_OUTPUT1_DAYS, YASOLR_WEEK_DAYS_EMPTY) ? "" : config.get(KEY_OUTPUT1_DAYS)); + _output1AutoStartWDays.setDisplay(bypass1Possible); + + // tab: output 2 config + + _output2ConfigSep0.setDisplay(dimmer2Enabled); + _output2ResistanceInput.setValue(config.getFloat(KEY_OUTPUT2_RESISTANCE)); + _output2ResistanceInput.setStatus(_output2ResistanceInput.value() > 0 ? dash::Status::SUCCESS : dash::Status::DANGER); // needs to be after set value + _output2ResistanceInput.setDisplay(dimmer2Enabled); + _output2ResistanceCalibration.setDisplay((dimmer2Enabled && jsyEnabled) || (dimmer2Enabled && pzem2Enabled)); + _output2ConfigSep1.setDisplay(dimmer2Enabled); + _output2DimmerDutyLimiter.setValue(config.getInt(KEY_OUTPUT2_DIMMER_LIMIT)); + _output2DimmerDutyLimiter.setDisplay(dimmer2Enabled); + _output2DimmerTempLimiter.setValue(config.getInt(KEY_OUTPUT2_DIMMER_TEMP_LIMITER)); + _output2DimmerTempLimiter.setDisplay(dimmer2Enabled); + _output2DimmerExcessLimiter.setValue(config.getInt(KEY_OUTPUT2_EXCESS_LIMITER)); + _output2DimmerExcessLimiter.setDisplay(dimmer2Enabled); + _output2ConfigSep2.setDisplay(bypass2Possible); + _output2AutoStartTemp.setValue(config.getInt(KEY_OUTPUT2_TEMPERATURE_START)); + _output2AutoStartTemp.setDisplay(bypass2Possible); + _output2AutoStoptTemp.setValue(config.getInt(KEY_OUTPUT2_TEMPERATURE_STOP)); + _output2AutoStoptTemp.setDisplay(bypass2Possible); + _output2AutoStartTime.setValue(config.get(KEY_OUTPUT2_TIME_START)); + _output2AutoStartTime.setDisplay(bypass2Possible); + _output2AutoStoptTime.setValue(config.get(KEY_OUTPUT2_TIME_STOP)); + _output2AutoStoptTime.setDisplay(bypass2Possible); + _output2AutoStartWDays.setValue(config.isEqual(KEY_OUTPUT2_DAYS, YASOLR_WEEK_DAYS_EMPTY) ? "" : config.get(KEY_OUTPUT2_DAYS)); + _output2AutoStartWDays.setDisplay(bypass2Possible); #endif } @@ -1225,22 +1377,27 @@ void YaSolR::Website::updateCards() { Mycila::Grid::Metrics gridMetrics; grid.getGridMeasurements(gridMetrics); - // stats + Mycila::Router::Metrics routerMetrics; + router.getRouterMeasurements(routerMetrics); + Mycila::System::Memory memory; Mycila::System::getMemory(memory); - _output1RelaySwitchCount.setValue(output1 ? output1->getBypassRelaySwitchCount() : 0); - _output2RelaySwitchCount.setValue(output2 ? output2->getBypassRelaySwitchCount() : 0); + + // statistics + _deviceHeapTotal.setValue(memory.total); - _deviceHeapUsed.setValue(memory.used); _deviceHeapUsage.setValue(memory.usage); + _deviceHeapUsed.setValue(memory.used); _gridEnergy.setValue(gridMetrics.energy); _gridEnergyReturned.setValue(gridMetrics.energyReturned); _gridFrequency.setValue(yasolr_frequency()); + _udpMessageRateBuffer.setValue(udpMessageRateBuffer ? udpMessageRateBuffer->rate() : 0); _networkWiFiRSSI.setValue(espConnect.getWiFiRSSI()); _networkWiFiSignal.setValue(espConnect.getWiFiSignalQuality()); + _output1RelaySwitchCount.setValue(output1 ? output1->getBypassRelaySwitchCount() : 0); + _output2RelaySwitchCount.setValue(output2 ? output2->getBypassRelaySwitchCount() : 0); _relay1SwitchCount.setValue(relay1 ? relay1->getSwitchCount() : 0); _relay2SwitchCount.setValue(relay2 ? relay2->getSwitchCount() : 0); - _udpMessageRateBuffer.setValue(udpMessageRateBuffer ? udpMessageRateBuffer->rate() : 0); _time.setValue(Mycila::Time::getLocalStr()); _uptime.setValue(Mycila::Time::toDHHMMSS(Mycila::System::getUptime())); #ifdef APP_MODEL_TRIAL @@ -1249,9 +1406,6 @@ void YaSolR::Website::updateCards() { // home - Mycila::Router::Metrics routerMetrics; - router.getRouterMeasurements(routerMetrics); - _routerPower.setValue(routerMetrics.power); _routerApparentPower.setValue(routerMetrics.apparentPower); _routerPowerFactor.setValue(routerMetrics.powerFactor); @@ -1263,7 +1417,8 @@ void YaSolR::Website::updateCards() { _gridPower.setValue(gridMetrics.power); _routerDS18State.setValue(ds18Sys ? ds18Sys->getTemperature().value_or(0.0f) : 0); - // output 1 + _relay1Switch.setValue(relay1 && relay1->isOn()); + _relay2Switch.setValue(relay1 && relay2->isOn()); if (output1) { switch (output1->getState()) { @@ -1287,8 +1442,6 @@ void YaSolR::Website::updateCards() { _output1Bypass.setValue(output1->isBypassOn()); } - // output 2 - if (output2) { switch (output2->getState()) { case Mycila::RouterOutput::State::OUTPUT_DISABLED: @@ -1311,26 +1464,19 @@ void YaSolR::Website::updateCards() { _output2Bypass.setValue(output2->isBypassOn()); } - // relay - - _relay1Switch.setValue(relay1 && relay1->isOn()); - _relay2Switch.setValue(relay1 && relay2->isOn()); - - // Hardware (config) - _output1PZEMSync.setValue(pzemO1PairingTask && !pzemO1PairingTask->isPaused()); _output2PZEMSync.setValue(pzemO2PairingTask && !pzemO2PairingTask->isPaused()); - _resistanceCalibration.setValue(router.isCalibrationRunning()); + _output1ResistanceCalibration.setValue(router.isCalibrationRunning()); + _output2ResistanceCalibration.setValue(router.isCalibrationRunning()); #ifdef APP_MODEL_PRO - // Output 1 + // tab: output 1 if (output1) { Mycila::RouterOutput::Metrics output1Measurements; output1->getOutputMeasurements(output1Measurements); _output1DimmerSliderRO.setValue(output1->getDimmerDutyCycleLive() * 100); - _output1BypassRO.setFeedback(YASOLR_STATE(output1->isBypassOn()), output1->isBypassOn() ? dash::Status::SUCCESS : dash::Status::IDLE); _output1Power.setValue(output1Measurements.power); _output1ApparentPower.setValue(output1Measurements.apparentPower); _output1PowerFactor.setValue(output1Measurements.powerFactor); @@ -1339,16 +1485,16 @@ void YaSolR::Website::updateCards() { _output1Current.setValue(output1Measurements.current); _output1Resistance.setValue(output1Measurements.resistance); _output1Energy.setValue(output1Measurements.energy); + _output1BypassRO.setFeedback(YASOLR_STATE(output1->isBypassOn()), output1->isBypassOn() ? dash::Status::SUCCESS : dash::Status::IDLE); } - // output 2 + // tab: output 2 if (output2) { Mycila::RouterOutput::Metrics output2Measurements; output2->getOutputMeasurements(output2Measurements); _output2DimmerSliderRO.setValue(output2->getDimmerDutyCycleLive() * 100); - _output2BypassRO.setFeedback(YASOLR_STATE(output2->isBypassOn()), output2->isBypassOn() ? dash::Status::SUCCESS : dash::Status::IDLE); _output2Power.setValue(output2Measurements.power); _output2ApparentPower.setValue(output2Measurements.apparentPower); _output2PowerFactor.setValue(output2Measurements.powerFactor); @@ -1357,25 +1503,30 @@ void YaSolR::Website::updateCards() { _output2Current.setValue(output2Measurements.current); _output2Resistance.setValue(output2Measurements.resistance); _output2Energy.setValue(output2Measurements.energy); + _output2BypassRO.setFeedback(YASOLR_STATE(output2->isBypassOn()), output2->isBypassOn() ? dash::Status::SUCCESS : dash::Status::IDLE); } - // relays + // tab: relays _relay1SwitchRO.setFeedback(YASOLR_STATE(relay1 && relay1->isOn()), relay1 && relay1->isOn() ? dash::Status::SUCCESS : dash::Status::IDLE); _relay2SwitchRO.setFeedback(YASOLR_STATE(relay2 && relay2->isOn()), relay2 && relay2->isOn() ? dash::Status::SUCCESS : dash::Status::IDLE); - // Hardware + // tab: mqtt - _status(_jsy, KEY_ENABLE_JSY, jsy && jsy->isEnabled(), jsy && jsy->isConnected(), YASOLR_LBL_110); _status(_mqtt, KEY_ENABLE_MQTT, mqtt && mqtt->isEnabled(), mqtt && mqtt->isConnected(), mqtt && mqtt->getLastError() ? mqtt->getLastError() : YASOLR_LBL_113); + _status(_haDiscovery, KEY_ENABLE_HA_DISCOVERY, mqtt && mqtt->isEnabled(), mqtt && mqtt->isConnected(), mqtt && mqtt->getLastError() ? mqtt->getLastError() : YASOLR_LBL_113); + + // tab: hardware + + _status(_jsy, KEY_ENABLE_JSY, jsy && jsy->isEnabled(), jsy && jsy->isConnected(), YASOLR_LBL_110); + _status(_zcd, KEY_ENABLE_ZCD, pulseAnalyzer && pulseAnalyzer->isEnabled(), pulseAnalyzer && pulseAnalyzer->isOnline(), YASOLR_LBL_110); _status(_output1Dimmer, KEY_ENABLE_OUTPUT1_DIMMER, output1 && output1->isDimmerEnabled(), output1 && output1->isDimmerOnline(), YASOLR_LBL_110); - _status(_output1DS18, KEY_ENABLE_OUTPUT1_DS18, ds18O1 && ds18O1->isEnabled(), ds18O1 && ds18O1->getLastTime() > 0, YASOLR_LBL_114); _status(_output1PZEM, KEY_ENABLE_OUTPUT1_PZEM, pzemO1 && pzemO1->isEnabled(), pzemO1 && pzemO1->isConnected() && pzemO1->getDeviceAddress() == YASOLR_PZEM_ADDRESS_OUTPUT1, pzemO1 && pzemO1->isConnected() ? YASOLR_LBL_180 : YASOLR_LBL_110); + _status(_output1DS18, KEY_ENABLE_OUTPUT1_DS18, ds18O1 && ds18O1->isEnabled(), ds18O1 && ds18O1->getLastTime() > 0, YASOLR_LBL_114); _status(_output2Dimmer, KEY_ENABLE_OUTPUT2_DIMMER, output2 && output2->isDimmerEnabled(), output2 && output2->isDimmerOnline(), YASOLR_LBL_110); - _status(_output2DS18, KEY_ENABLE_OUTPUT2_DS18, ds18O2 && ds18O2->isEnabled(), ds18O2 && ds18O2->getLastTime() > 0, YASOLR_LBL_114); _status(_output2PZEM, KEY_ENABLE_OUTPUT2_PZEM, pzemO2 && pzemO2->isEnabled(), pzemO2 && pzemO2->isConnected() && pzemO2->getDeviceAddress() == YASOLR_PZEM_ADDRESS_OUTPUT2, pzemO2 && pzemO2->isConnected() ? YASOLR_LBL_180 : YASOLR_LBL_110); + _status(_output2DS18, KEY_ENABLE_OUTPUT2_DS18, ds18O2 && ds18O2->isEnabled(), ds18O2 && ds18O2->getLastTime() > 0, YASOLR_LBL_114); _status(_routerDS18, KEY_ENABLE_DS18_SYSTEM, ds18Sys && ds18Sys->isEnabled(), ds18Sys && ds18Sys->getLastTime() > 0, YASOLR_LBL_114); - _status(_zcd, KEY_ENABLE_ZCD, pulseAnalyzer && pulseAnalyzer->isEnabled(), pulseAnalyzer && pulseAnalyzer->isOnline(), YASOLR_LBL_110); #endif } @@ -1400,7 +1551,7 @@ void YaSolR::Website::updateCharts() { _routerTHDiHistory.setY(_routerTHDiHistoryY, YASOLR_GRAPH_POINTS); } -void YaSolR::Website::updatePID() { +void YaSolR::Website::updatePIDCharts() { #ifdef APP_MODEL_PRO // shift array memmove(&_pidInputHistoryY[0], &_pidInputHistoryY[1], sizeof(_pidInputHistoryY) - sizeof(*_pidInputHistoryY)); @@ -1431,7 +1582,7 @@ void YaSolR::Website::updatePID() { #endif } -void YaSolR::Website::resetPID() { +void YaSolR::Website::resetPIDCharts() { #ifdef APP_MODEL_PRO memset(_pidOutputHistoryY, 0, sizeof(_pidOutputHistoryY)); memset(_pidInputHistoryY, 0, sizeof(_pidInputHistoryY)); @@ -1443,7 +1594,7 @@ void YaSolR::Website::resetPID() { #endif } -bool YaSolR::Website::pidCharts() const { +bool YaSolR::Website::realTimePIDEnabled() const { #ifdef APP_MODEL_PRO return _pidView.optional().value_or(false); #else diff --git a/src/yasolr_router.cpp b/src/yasolr_router.cpp index c6d84878..77ae22da 100644 --- a/src/yasolr_router.cpp +++ b/src/yasolr_router.cpp @@ -243,7 +243,7 @@ void yasolr_divert() { if (voltage.has_value() && grid.getPower().isPresent()) { router.divert(voltage.value(), grid.getPower().get()); - if (website.pidCharts()) { + if (website.realTimePIDEnabled()) { dashboardUpdateTask.requestEarlyRun(); } } diff --git a/src/yasolr_web_server.cpp b/src/yasolr_web_server.cpp index ba141457..285c037d 100644 --- a/src/yasolr_web_server.cpp +++ b/src/yasolr_web_server.cpp @@ -32,8 +32,8 @@ Mycila::Task dashboardInitTask("Init Dashboard", Mycila::TaskType::ONCE, [](void }); Mycila::Task dashboardUpdateTask("Dashboard", [](void* params) { - if (website.pidCharts()) - website.updatePID(); + if (website.realTimePIDEnabled()) + website.updatePIDCharts(); website.updateCards(); website.updateCharts(); dashboard.sendUpdates();