├── .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 |
5 |
6 | Read data from #victron mppt charger and transport to #mqtt server with esp8266 nodemcu v1
7 |
8 | Home Assistant dashboard
9 | 
10 |
11 |
12 | 
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 | 
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
--------------------------------------------------------------------------------