├── .DS_Store ├── .gitattributes ├── .gitignore ├── HA.png ├── LICENSE ├── MQTTExplorerVictronToMQTT.png ├── README.md ├── Victron2MQTTv1 ├── .DS_Store ├── Victron2MQTTv1.ino └── config.h └── nodemcu.png /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/3532cfa84ce243cb6c4603ffb523d21378d202be/.DS_Store -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | # Auto detect text files and perform LF normalization 2 | * text=auto 3 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Prerequisites 2 | *.d 3 | 4 | # Compiled Object files 5 | *.slo 6 | *.lo 7 | *.o 8 | *.obj 9 | 10 | # Precompiled Headers 11 | *.gch 12 | *.pch 13 | 14 | # Compiled Dynamic libraries 15 | *.so 16 | *.dylib 17 | *.dll 18 | 19 | # Fortran module files 20 | *.mod 21 | *.smod 22 | 23 | # Compiled Static libraries 24 | *.lai 25 | *.la 26 | *.a 27 | *.lib 28 | 29 | # Executables 30 | *.exe 31 | *.out 32 | *.app 33 | Victron2MQTTv1.1/.DS_Store 34 | Victron2MQTTv1.1/Victron2MQTTv1/config.h 35 | Victron2MQTTv1.1/Victron2MQTTv1/.DS_Store 36 | -------------------------------------------------------------------------------- /HA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/3532cfa84ce243cb6c4603ffb523d21378d202be/HA.png -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 KinDR007 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /MQTTExplorerVictronToMQTT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/3532cfa84ce243cb6c4603ffb523d21378d202be/MQTTExplorerVictronToMQTT.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Victron MPPT ve.direct to MQTT 2 | 3 | 4 | Buy Me A Coffee 5 | 6 | Read data from #victron mppt charger and transport to #mqtt server with esp8266 nodemcu v1 7 | 8 | Home Assistant dashboard 9 | ![alt text](https://github.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/blob/master/HA.png?raw=true) 10 | 11 | 12 | ![alt text](https://github.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/blob/master/MQTTExplorerVictronToMQTT.png?raw=true) 13 | 14 | 15 | Set params in config.h 16 | ``` 17 | const char* ssid = "SSID"; 18 | const char* password = "password_to_your_wifi"; 19 | const char* mqtt_server = "ip_adress_to_MQTT_server eg.192.168.1.201"; 20 | const char* mqtt_user = ""; //username to mqtt leave blank if you dont use username 21 | const char* mqtt_pass = ""; //password to mqtt leave blank if you dont use password 22 | 23 | #define OTA_HOSTNAME "VictronMPPT" // name of esp8266 in LAN 24 | #define MQTT_ROOT "Victron" 25 | ``` 26 | 27 | 28 | Home Assitant example config 29 | 30 | ``` 31 | #. Victron 32 | - platform: mqtt 33 | name: "Victron - Battery voltage" 34 | state_topic: "Victron/Battery voltage, V" 35 | unit_of_measurement: "V" 36 | icon: mdi:mdi-battery 37 | unique_id: sensor.text.victron.battery.voltage 38 | 39 | - platform: mqtt 40 | name: "Victron - Battery current" 41 | state_topic: "Victron/Battery current, I" 42 | unit_of_measurement: "I" 43 | icon: mdi:mdi-current-dc 44 | unique_id: sensor.text.victron.panel.current 45 | 46 | - platform: mqtt 47 | name: "Victron PV power" 48 | state_topic: "Victron/Panel power, W" 49 | unit_of_measurement: "W" 50 | icon: mdi:gauge 51 | unique_id: sensor.text.victron.panel.power 52 | 53 | - platform: mqtt 54 | name: "Victron Panel voltage" 55 | state_topic: "Victron/Panel voltage" 56 | unit_of_measurement: "V" 57 | unique_id: sensor.text.victron.panel.voltage 58 | 59 | - platform: mqtt 60 | name: "Victron Tracker operation" 61 | state_topic: "Victron/Tracker operation" 62 | unique_id: sensor.text.victron.tracker.operation 63 | icon: mdi:mdi-solar-power 64 | 65 | - platform: mqtt 66 | name: "Victron Yield today" 67 | state_topic: "Victron/Yield today, kWh" 68 | unique_id: sensor.text.victron.yield.today 69 | icon: mdi:gauge 70 | unit_of_measurement: "Kw/h" 71 | 72 | - platform: mqtt 73 | name: "Victron - Maximum power today" 74 | state_topic: "Victron/Maximum power today, W" 75 | unique_id: sensor.text.victron.maximum.power.today 76 | unit_of_measurement: "W" 77 | icon: mdi:gauge 78 | 79 | - platform: mqtt 80 | name: "Victron/Yield total, kWh" 81 | state_topic: "Victron/Yield total, kWh" 82 | unique_id: sensor.text.victron.yield.total 83 | icon: mdi:gauge 84 | unit_of_measurement: "Kw/h" 85 | 86 | - platform: mqtt 87 | name: "Victron Charge state" 88 | state_topic: "Victron/Charge state" 89 | unique_id: sensor.text.victron.charge.state 90 | icon: mdi:mdi-solar-power 91 | ``` 92 | 93 | #NodeMCU pinout and wirring 94 | ![alt text](https://github.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/blob/master/nodemcu.png?raw=true) 95 | 96 | 97 | 98 | 99 | -------------------------------------------------------------------------------- /Victron2MQTTv1/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/3532cfa84ce243cb6c4603ffb523d21378d202be/Victron2MQTTv1/.DS_Store -------------------------------------------------------------------------------- /Victron2MQTTv1/Victron2MQTTv1.ino: -------------------------------------------------------------------------------- 1 | /* 2 | PID 0xA043 -- Product ID for BlueSolar MPPT 100/15 3 | FW 119 -- Firmware version of controller, v1.19 4 | SER# HQXXXXXXXXX -- Serial number 5 | V 13790 -- Battery voltage, mV 6 | I -10 -- Battery current, mA 7 | VPV 15950 -- Panel voltage, mV 8 | PPV 0 -- Panel power, W 9 | CS 5 -- Charge state, 0 to 9 10 | ERR 0 -- Error code, 0 to 119 11 | LOAD ON -- Load output state, ON/OFF 12 | IL 0 -- Load current, mA 13 | H19 0 -- Yield total, kWh 14 | H20 0 -- Yield today, kWh 15 | H21 397 -- Maximum power today, W 16 | H22 0 -- Yield yesterday, kWh 17 | H23 0 -- Maximum power yesterday, W 18 | HSDS 0 -- Day sequence number, 0 to 365 19 | Checksum l:A0002000148 -- Message checksum 20 | */ 21 | #include "config.h" 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | SoftwareSerial Vser(13, 15); // RX | TX on nodemcu 30 | 31 | 32 | 33 | WiFiClient espClient; 34 | PubSubClient client(espClient); 35 | 36 | 37 | //String value; 38 | String label, val; 39 | char mptt_location[16]; 40 | float floatValue; 41 | char buf[45]; 42 | char char_current[6]; 43 | char panel_power[6]; 44 | char laadstatus[12]; 45 | char prod_yesterday[6]; 46 | char max_power_h[6]; 47 | char prod_today[6]; 48 | byte len = 12; 49 | int intValue; 50 | 51 | 52 | 53 | void setup() { 54 | Serial.begin(115200); 55 | 56 | Vser.begin(19200); 57 | 58 | // Wait for hardware to initialize 59 | delay(1000); 60 | Serial.println("Booting"); 61 | WiFi.mode(WIFI_STA); 62 | WiFi.hostname(OTA_HOSTNAME); 63 | WiFi.begin(ssid, password); 64 | while (WiFi.waitForConnectResult() != WL_CONNECTED) { 65 | Serial.println("Connection Failed! Rebooting..."); 66 | delay(5000); 67 | ESP.restart(); 68 | } 69 | 70 | // Port defaults to 8266 71 | // ArduinoOTA.setPort(8266); 72 | // Hostname defaults to esp8266-[ChipID] 73 | ArduinoOTA.setHostname(OTA_HOSTNAME); 74 | 75 | // No authentication by default 76 | //ArduinoOTA.setPassword((const char *)"123"); 77 | 78 | ArduinoOTA.onStart([]() { 79 | Serial.println("Start"); 80 | }); 81 | ArduinoOTA.onEnd([]() { 82 | Serial.println("\nEnd"); 83 | }); 84 | ArduinoOTA.onProgress([](unsigned int progress, unsigned int total) { 85 | Serial.printf("Progress: %u%%\r", (progress / (total / 100))); 86 | }); 87 | ArduinoOTA.onError([](ota_error_t error) { 88 | // Serial.printf("Error[%u]: ", error); 89 | if (error == OTA_AUTH_ERROR) Serial.println("Auth Failed"); 90 | else if (error == OTA_BEGIN_ERROR) Serial.println("Begin Failed"); 91 | else if (error == OTA_CONNECT_ERROR) Serial.println("Connect Failed"); 92 | else if (error == OTA_RECEIVE_ERROR) Serial.println("Receive Failed"); 93 | else if (error == OTA_END_ERROR) Serial.println("End Failed"); 94 | }); 95 | ArduinoOTA.begin(); 96 | client.setServer(mqtt_server, 1883); 97 | client.publish("Victron/Live", "0"); 98 | 99 | 100 | } 101 | 102 | void reconnect() { 103 | // Loop until we're reconnected 104 | while (!client.connected()) { 105 | Serial.print("Attempting MQTT connection..."); 106 | // Attempt to connect 107 | if (client.connect("Victron", mqtt_user, mqtt_pass)) { 108 | Serial.println("connected"); 109 | client.publish("Victron/Live", "1"); 110 | // Once connected, publish an announcement... 111 | } else { 112 | // Wait 5 seconds before retrying 113 | delay(5000); 114 | } 115 | } 116 | } 117 | 118 | 119 | void loop() { 120 | ArduinoOTA.handle(); 121 | if (!client.connected()) { 122 | reconnect(); 123 | } 124 | client.loop(); 125 | 126 | 127 | if (Vser.available()) 128 | { 129 | label = Vser.readStringUntil('\t'); // this is the actual line that reads the label from the MPPT controller 130 | val = Vser.readStringUntil('\r\r\n'); // this is the line that reads the value of the label 131 | char charBufL[label.length() + 1]; 132 | label.toCharArray(charBufL, label.length() + 1); 133 | 134 | if (label == "PID") { 135 | 136 | 137 | String WorkingString = val; 138 | long A = strtol(WorkingString.c_str(), NULL, 0); 139 | WorkingString = String(A); 140 | 141 | switch (A) { 142 | case 0x203 : client.publish("Victron/PID", "BMV-700"); break; 143 | case 0x204 : client.publish("Victron/PID", "BMV-702"); break; 144 | case 0x205 : client.publish("Victron/PID", "BMV-700H"); break; 145 | case 0xA389 : client.publish("Victron/PID", "SmartShunt"); break; 146 | case 0xA381 : client.publish("Victron/PID", "BMV-712 Smart"); break; 147 | case 0xA04C : client.publish("Victron/PID", "BlueSolar MPPT 75/10"); break; 148 | case 0x300 : client.publish("Victron/PID", "BlueSolar MPPT 70/15"); break; 149 | case 0xA042 : client.publish("Victron/PID", "BlueSolar MPPT 75/15"); break; 150 | case 0xA043 : client.publish("Victron/PID", "BlueSolar MPPT 100/15"); break; 151 | case 0xA044 : client.publish("Victron/PID", "BlueSolar MPPT 100/30 rev1"); break; 152 | case 0xA04A : client.publish("Victron/PID", "BlueSolar MPPT 100/30 rev2"); break; 153 | case 0xA041 : client.publish("Victron/PID", "BlueSolar MPPT 150/35 rev1"); break; 154 | case 0xA04B : client.publish("Victron/PID", "BlueSolar MPPT 150/35 rev2"); break; 155 | case 0xA04D : client.publish("Victron/PID", "BlueSolar MPPT 150/45"); break; 156 | case 0xA040 : client.publish("Victron/PID", "BlueSolar MPPT 75/50"); break; 157 | case 0xA045 : client.publish("Victron/PID", "BlueSolar MPPT 100/50 rev1"); break; 158 | case 0xA049 : client.publish("Victron/PID", "BlueSolar MPPT 100/50 rev2"); break; 159 | case 0xA04E : client.publish("Victron/PID", "BlueSolar MPPT 150/60"); break; 160 | case 0xA046 : client.publish("Victron/PID", "BlueSolar MPPT 150/70"); break; 161 | case 0xA04F : client.publish("Victron/PID", "BlueSolar MPPT 150/85"); break; 162 | case 0xA047 : client.publish("Victron/PID", "BlueSolar MPPT 150/100"); break; 163 | case 0xA050 : client.publish("Victron/PID", "SmartSolar MPPT 250/100"); break; 164 | case 0xA051 : client.publish("Victron/PID", "SmartSolar MPPT 150/100"); break; 165 | case 0xA052 : client.publish("Victron/PID", "SmartSolar MPPT 150/85"); break; 166 | case 0xA053 : client.publish("Victron/PID", "SmartSolar MPPT 75/15"); break; 167 | case 0xA054 : client.publish("Victron/PID", "SmartSolar MPPT 75/10"); break; 168 | case 0xA055 : client.publish("Victron/PID", "SmartSolar MPPT 100/15"); break; 169 | case 0xA056 : client.publish("Victron/PID", "SmartSolar MPPT 100/30"); break; 170 | case 0xA057 : client.publish("Victron/PID", "SmartSolar MPPT 100/50"); break; 171 | case 0xA058 : client.publish("Victron/PID", "SmartSolar MPPT 150/35"); break; 172 | case 0xA059 : client.publish("Victron/PID", "SmartSolar MPPT 150/100 rev2"); break; 173 | case 0xA05A : client.publish("Victron/PID", "SmartSolar MPPT 150/85 rev2"); break; 174 | case 0xA05B : client.publish("Victron/PID", "SmartSolar MPPT 250/70"); break; 175 | case 0xA05C : client.publish("Victron/PID", "SmartSolar MPPT 250/85"); break; 176 | case 0xA05D : client.publish("Victron/PID", "SmartSolar MPPT 250/60"); break; 177 | case 0xA05E : client.publish("Victron/PID", "SmartSolar MPPT 250/45"); break; 178 | case 0xA05F : client.publish("Victron/PID", "SmartSolar MPPT 100/20"); break; 179 | case 0xA060 : client.publish("Victron/PID", "SmartSolar MPPT 100/20 48V"); break; 180 | case 0xA061 : client.publish("Victron/PID", "SmartSolar MPPT 150/45"); break; 181 | case 0xA062 : client.publish("Victron/PID", "SmartSolar MPPT 150/60"); break; 182 | case 0xA063 : client.publish("Victron/PID", "SmartSolar MPPT 150/70"); break; 183 | case 0xA064 : client.publish("Victron/PID", "SmartSolar MPPT 250/85 rev2"); break; 184 | case 0xA065 : client.publish("Victron/PID", "SmartSolar MPPT 250/100 rev2"); break; 185 | case 0xA201 : client.publish("Victron/PID", "Phoenix Inverter 12V 250VA 230V"); break; 186 | case 0xA202 : client.publish("Victron/PID", "Phoenix Inverter 24V 250VA 230V"); break; 187 | case 0xA204 : client.publish("Victron/PID", "Phoenix Inverter 48V 250VA 230V"); break; 188 | case 0xA211 : client.publish("Victron/PID", "Phoenix Inverter 12V 375VA 230V"); break; 189 | case 0xA212 : client.publish("Victron/PID", "Phoenix Inverter 24V 375VA 230V"); break; 190 | case 0xA214 : client.publish("Victron/PID", "Phoenix Inverter 48V 375VA 230V"); break; 191 | case 0xA221 : client.publish("Victron/PID", "Phoenix Inverter 12V 500VA 230V"); break; 192 | case 0xA222 : client.publish("Victron/PID", "Phoenix Inverter 24V 500VA 230V"); break; 193 | case 0xA224 : client.publish("Victron/PID", "Phoenix Inverter 48V 500VA 230V"); break; 194 | case 0xA231 : client.publish("Victron/PID", "Phoenix Inverter 12V 250VA 230V"); break; 195 | case 0xA232 : client.publish("Victron/PID", "Phoenix Inverter 24V 250VA 230V"); break; 196 | case 0xA234 : client.publish("Victron/PID", "Phoenix Inverter 48V 250VA 230V"); break; 197 | case 0xA239 : client.publish("Victron/PID", "Phoenix Inverter 12V 250VA 120V"); break; 198 | case 0xA23A : client.publish("Victron/PID", "Phoenix Inverter 24V 250VA 120V"); break; 199 | case 0xA23C : client.publish("Victron/PID", "Phoenix Inverter 48V 250VA 120V"); break; 200 | case 0xA241 : client.publish("Victron/PID", "Phoenix Inverter 12V 375VA 230V"); break; 201 | case 0xA242 : client.publish("Victron/PID", "Phoenix Inverter 24V 375VA 230V"); break; 202 | case 0xA244 : client.publish("Victron/PID", "Phoenix Inverter 48V 375VA 230V"); break; 203 | case 0xA249 : client.publish("Victron/PID", "Phoenix Inverter 12V 375VA 120V"); break; 204 | case 0xA24A : client.publish("Victron/PID", "Phoenix Inverter 24V 375VA 120V"); break; 205 | case 0xA24C : client.publish("Victron/PID", "Phoenix Inverter 48V 375VA 120V"); break; 206 | case 0xA251 : client.publish("Victron/PID", "Phoenix Inverter 12V 500VA 230V"); break; 207 | case 0xA252 : client.publish("Victron/PID", "Phoenix Inverter 24V 500VA 230V"); break; 208 | case 0xA254 : client.publish("Victron/PID", "Phoenix Inverter 48V 500VA 230V"); break; 209 | case 0xA259 : client.publish("Victron/PID", "Phoenix Inverter 12V 500VA 120V"); break; 210 | case 0xA25A : client.publish("Victron/PID", "Phoenix Inverter 24V 500VA 120V"); break; 211 | case 0xA25C : client.publish("Victron/PID", "Phoenix Inverter 48V 500VA 120V"); break; 212 | case 0xA261 : client.publish("Victron/PID", "Phoenix Inverter 12V 800VA 230V"); break; 213 | case 0xA262 : client.publish("Victron/PID", "Phoenix Inverter 24V 800VA 230V"); break; 214 | case 0xA264 : client.publish("Victron/PID", "Phoenix Inverter 48V 800VA 230V"); break; 215 | case 0xA269 : client.publish("Victron/PID", "Phoenix Inverter 12V 800VA 120V"); break; 216 | case 0xA26A : client.publish("Victron/PID", "Phoenix Inverter 24V 800VA 120V"); break; 217 | case 0xA26C : client.publish("Victron/PID", "Phoenix Inverter 48V 800VA 120V"); break; 218 | case 0xA271 : client.publish("Victron/PID", "Phoenix Inverter 12V 1200VA 230V"); break; 219 | case 0xA272 : client.publish("Victron/PID", "Phoenix Inverter 24V 1200VA 230V"); break; 220 | case 0xA274 : client.publish("Victron/PID", "Phoenix Inverter 48V 1200VA 230V"); break; 221 | case 0xA279 : client.publish("Victron/PID", "Phoenix Inverter 12V 1200VA 120V"); break; 222 | case 0xA27A : client.publish("Victron/PID", "Phoenix Inverter 24V 1200VA 120V"); break; 223 | case 0xA27C : client.publish("Victron/PID", "Phoenix Inverter 48V 1200VA 120V"); break; 224 | default: 225 | client.publish("Victron/PID", "model not detected "); 226 | } 227 | } 228 | else if (label == "I") 229 | { // In this case I chose to read charging current 230 | val.toCharArray(buf, sizeof(buf)); 231 | float floatValue = atof(buf); 232 | floatValue = floatValue / 1000; 233 | dtostrf(floatValue, len, 2, char_current); 234 | client.publish("Victron/Battery current, I", char_current); 235 | } 236 | else if (label == "V") 237 | { 238 | val.toCharArray(buf, sizeof(buf)); 239 | float floatValue = atof(buf); 240 | floatValue = floatValue / 1000; 241 | dtostrf(floatValue, len, 2, char_current); 242 | if (floatValue > 9) { 243 | client.publish("Victron/Battery voltage, V", char_current); 244 | } 245 | } 246 | else if (label == "PPV") 247 | { 248 | val.toCharArray(buf, sizeof(buf)); 249 | floatValue = atof(buf); 250 | dtostrf(floatValue, len, 0, panel_power); 251 | panel_power[len] = ' '; panel_power[len + 1] = 0; 252 | client.publish("Victron/Panel power, W", panel_power); 253 | } 254 | else if (label == "VPV") //Solar 255 | { 256 | val.toCharArray(buf, sizeof(buf)); 257 | float floatValue = atof(buf); 258 | floatValue = floatValue / 1000; 259 | dtostrf(floatValue, len, 2, char_current); 260 | client.publish("Victron/Panel voltage", char_current); 261 | } 262 | else if (label == "H20") 263 | { 264 | val.toCharArray(buf, sizeof(buf)); 265 | float floatValue = atof(buf); 266 | floatValue = floatValue / 100; 267 | dtostrf(floatValue, len, 2, prod_today); 268 | prod_today[len] = ' '; prod_today[len + 1] = 0; 269 | client.publish("Victron/Yield today, kWh", prod_today); 270 | } 271 | else if (label == "H22") //Yield yesterday, kWh 272 | { 273 | val.toCharArray(buf, sizeof(buf)); 274 | float floatValue = atof(buf); 275 | floatValue = floatValue / 100; 276 | dtostrf(floatValue, len, 2, prod_yesterday); 277 | prod_yesterday[len] = ' '; prod_yesterday[len + 1] = 0; 278 | client.publish("Victron/Yield yesterday, kWh", prod_yesterday); 279 | } 280 | else if (label == "H19") //-- Yield total, kWh 281 | { 282 | val.toCharArray(buf, sizeof(buf)); 283 | float floatValue = atof(buf); 284 | floatValue = floatValue / 100; 285 | dtostrf(floatValue, len, 2, prod_yesterday); 286 | prod_yesterday[len] = ' '; prod_yesterday[len + 1] = 0; 287 | client.publish("Victron/Yield total, kWh", prod_yesterday); 288 | } 289 | 290 | else if (label == "H21") //Maximum power today, W 291 | { 292 | val.toCharArray(buf, sizeof(buf)); 293 | floatValue = atof(buf); 294 | dtostrf(floatValue, len, 0, max_power_h); 295 | max_power_h[len] = ' '; max_power_h[len + 1] = 0; 296 | client.publish("Victron/Maximum power today, W", max_power_h); 297 | 298 | } 299 | else if (label == "H23") //Maximum power yesterday, W 300 | { 301 | val.toCharArray(buf, sizeof(buf)); 302 | floatValue = atof(buf); 303 | dtostrf(floatValue, len, 0, max_power_h); 304 | max_power_h[len] = ' '; max_power_h[len + 1] = 0; 305 | client.publish("Victron/Maximum power yesterday, W", max_power_h); 306 | 307 | } 308 | else if (label == "FW") //FW 119 -- Firmware version of controller, v1.19 309 | { 310 | val.toCharArray(buf, sizeof(buf)); 311 | float floatValue = atof(buf); 312 | floatValue = floatValue / 100; 313 | dtostrf(floatValue, len, 2, prod_today); 314 | prod_today[len] = ' '; prod_today[len + 1] = 0; 315 | client.publish("Victron/Firmware version", prod_today); 316 | 317 | } 318 | else if (label == "HSDS") //Day sequence number (0..364) 319 | { 320 | val.toCharArray(buf, sizeof(buf)); 321 | floatValue = atof(buf); 322 | dtostrf(floatValue, len, 0, panel_power); 323 | panel_power[len] = ' '; panel_power[len + 1] = 0; 324 | client.publish("Victron/Day sequence number", panel_power); 325 | 326 | } 327 | else if (label == "MPPT") 328 | { 329 | val.toCharArray(buf, sizeof(buf)); 330 | intValue = atof(buf); 331 | switch (intValue) { 332 | case 0 : client.publish("Victron/Tracker operation", "Off"); break; 333 | case 1 : client.publish("Victron/Tracker operation", "Limited"); break; 334 | case 2 : client.publish("Victron/Tracker operation", "Active"); break; 335 | default: 336 | client.publish("Victron/Tracker operation", "Tracker operation not detected !! "); 337 | } 338 | 339 | } 340 | // Adding BVM 712 support 341 | 342 | else if (label == "SOC") // State Of Charge of the battery 343 | { 344 | val.toCharArray(buf, sizeof(buf)); 345 | float floatValue = atof(buf); 346 | floatValue = floatValue / 10; 347 | dtostrf(floatValue, len, 2, char_current); 348 | client.publish("Victron/SOC", char_current); 349 | } 350 | else if (label == "TTG") // Time To Go in decimal hours 351 | { 352 | val.toCharArray(buf, sizeof(buf)); 353 | float floatValue = atof(buf); 354 | floatValue = floatValue / 60; 355 | dtostrf(floatValue, len, 2, char_current); 356 | client.publish("Victron/ttg", char_current); 357 | } 358 | else if (label == "P") // Instant power 359 | { 360 | val.toCharArray(buf, sizeof(buf)); 361 | float floatValue = atof(buf); 362 | dtostrf(floatValue, len, 2, char_current); 363 | client.publish("Victron/Power", char_current); 364 | 365 | } 366 | else if (label == "CE") //Consumption of engery in A/h 367 | { 368 | val.toCharArray(buf, sizeof(buf)); 369 | float floatValue = atof(buf); 370 | floatValue = floatValue / 1000; 371 | dtostrf(floatValue, len, 2, char_current); 372 | client.publish("Victron/AH", char_current); 373 | } 374 | else if (label == "H17") // Total discharged enery from the first power on in kWh 375 | { 376 | val.toCharArray(buf, sizeof(buf)); 377 | float floatValue = atof(buf); 378 | floatValue = floatValue / 100; 379 | dtostrf(floatValue, len, 2, char_current); 380 | client.publish("Victron/discharged, kWh", char_current); 381 | } 382 | else if (label == "H18") // Total charged enery from the first power on in kWh 383 | { 384 | val.toCharArray(buf, sizeof(buf)); 385 | float floatValue = atof(buf); 386 | floatValue = floatValue / 100; 387 | dtostrf(floatValue, len, 2, char_current); 388 | client.publish("Victron/charged", char_current); 389 | } 390 | else if (label == "ERR") // This routine reads the error code. 391 | { 392 | 393 | val.toCharArray(buf, sizeof(buf)); 394 | intValue = atoi(buf); 395 | switch (intValue) { 396 | case 0: client.publish("Victron/Error code", "No error"); break; 397 | case 2: client.publish("Victron/Error code", "Battery voltage too high"); break; 398 | case 17: client.publish("Victron/Error code", "Charger temperature too high"); break; 399 | case 18: client.publish("Victron/Error code", "Charger over current"); break; 400 | case 19: client.publish("Victron/Error code", "Charger current reversed"); break; 401 | case 20: client.publish("Victron/Error code", "Bulk time limit exceeded"); break; 402 | case 21: client.publish("Victron/Error code", "Current sensor issue"); break; 403 | case 26: client.publish("Victron/Error code", "Terminals overheated"); break; 404 | case 28: client.publish("Victron/Error code", "Converter issue"); break; 405 | case 33: client.publish("Victron/Error code", "Input voltage too high (solar panel)"); break; 406 | case 34: client.publish("Victron/Error code", "Input current too high (solar panel)"); break; 407 | case 38: client.publish("Victron/Error code", "Input shutdown (excessive battery voltage)"); break; 408 | case 39: client.publish("Victron/Error code", "Input shutdown (due to current flow during off mode)"); break; 409 | case 65: client.publish("Victron/Error code", "Lost communication with one of devices"); break; 410 | case 66: client.publish("Victron/Error code", "Synchronised charging device configuration issue"); break; 411 | case 67: client.publish("Victron/Error code", "BMS connection lost"); break; 412 | case 68: client.publish("Victron/Error code", "Network misconfigured"); break; 413 | case 116: client.publish("Victron/Error code", "Factory calibration data lost"); break; 414 | case 117: client.publish("Victron/Error code", "Invalid/incompatible firmware"); break; 415 | case 119: client.publish("Victron/Error code", "User settings invalid"); break; 416 | default: 417 | client.publish("Victron/Error code", "ERROR CODE not detected !! "); 418 | } 419 | 420 | } 421 | else if (label == "CS") // Charge Status 422 | { 423 | 424 | val.toCharArray(buf, sizeof(buf)); 425 | intValue = atoi(buf); 426 | switch (intValue) { 427 | case 0 : client.publish("Victron/Charge state", "Off"); break; 428 | case 2 : client.publish("Victron/Charge state", "Fault"); break; 429 | case 3 : client.publish("Victron/Charge state", "Bulk"); break; 430 | case 4 : client.publish("Victron/Charge state", "Absorption"); break; 431 | case 5 : client.publish("Victron/Charge state", "Float"); break; 432 | case 7 : client.publish("Victron/Charge state", "Equalize (manual)"); break; 433 | case 245 : client.publish("Victron/Charge state", "Starting-up"); break; 434 | case 247 : client.publish("Victron/Charge state", "Auto equalize / Recondition"); break; 435 | case 252 : client.publish("Victron/Charge state", "External control"); break; 436 | default: 437 | client.publish("Victron/Charge state", "Charge state not detected !! "); 438 | } 439 | } 440 | } 441 | } 442 | -------------------------------------------------------------------------------- /Victron2MQTTv1/config.h: -------------------------------------------------------------------------------- 1 | const char* ssid = "SSID"; 2 | const char* password = "hidden_password_to_my_wifi"; //password to wifi 3 | const char* mqtt_server = "192.168.0.10"; //ip to mqtt server 4 | const char* mqtt_user = ""; //mqtt user name 5 | const char* mqtt_pass = ""; //mqtt password 6 | 7 | #define OTA_HOSTNAME "VictronMPPT" 8 | #define MQTT_ROOT "Victron" 9 | -------------------------------------------------------------------------------- /nodemcu.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/KinDR007/Victron-MPPT-ve.direct-to-MQTT/3532cfa84ce243cb6c4603ffb523d21378d202be/nodemcu.png --------------------------------------------------------------------------------