JKBMS auslesen über BLE (Bluetooth) oder RS485 Adapter mittels EPS, ioBroker

https://akkudoktor.net/uploads/default/original/2X/a/ae24d922b3486df98bb5825c70ebb3bdfb72baa6.png hast du das so eingestellt ? sonst poste mal deine Fehlermeldung die beim Kompilieren kommen ?

Hallo,

Ist es eigentlich auch Möglich über den Arduino eine Einstellung im BMS zu verändern? Ich würde gerne Charge/Discharge aktivieren und deaktivieren können.

Gruß

Hi

Ich habe mir mal die Offsets analysiert und kann mir nun anzeigen welche Zelle gerade balanciert wird und von welcher die Spannung entnommen wird so wie es in der JK.APP auch angezeigt wird. – übermittelt wird dann per JOSN oder MQTT Balancing Zelle 1.2…..

Das Charge / Discharge an bzw auszuschalten würde bestimmt gehen. Dazu müsste ich den Offset bzw. RAW-Dump nochmal analysieren. Dann kommt die frage wie schalten?

Per MQTT oder zb. Im internen Webinterface ?

Aber wenn du PV bekommst und der/die Wechselrichter auf AKKU laufen und du dann charge/discharge aus schaltet wird der/die Wechselrichter bestimmt kurz ausgehen und auf netz Spannung umschatten. So ist es bei mir. Ein bisschen wie ein Cut/off .

Ist für den Winterberib bei wenig PV Input glaube ich besser die cut off Spannung im Wechselrichter etwas hör zu setzten und back to discharge auch.

Ich schau trotzdem mal ob sich da was machen lässt

Gruß Sralus

1 „Gefällt mir“

Das Übertragen des Balancing ist schonmal ne super Sache!

Ich würde es gerne per MQTT charge abschalten da mein WR immer wieder auf die Idee kommt nachts die Batterie mit Netzstrom zu laden obwohl ich es deaktiviert habe. Außerdem bekomme ich auch alle Werte aufs Handy geschickt und könnte so, wenn die Spannungen oder Temperaturen aus dem Ruder laufensollten, die Batterie zur Not auch von Extern abschalten.

Die Cut/off und Discharge stehen bei mir schon relativ weit oben.

Gruß Scherheinz

Ich habe mir in den letzten Wochen einen ESP32-Adapter für mein JK-BMS (JK_B2A20S20P) gebaut, der das komplette BMS per BLE ausliest, die Daten ins MQTT schiebt und zusätzlich ein kleines Webinterface mit Live-JSON und Dashboard bereitstellt. Damit kann ich alle Zellspannungen, Ströme, Temperaturen, SOC, Uptime, Balancing usw. sauber in ioBroker / HomeAssistant visualisieren – ganz ohne RS485-Dongle oder Original-WiFi-Modul.

Das Besondere an meinem Sketch: Neben der reinen Auswertung kann der ESP32 jetzt auch die Charge- und Discharge-MOSFETs direkt per MQTT schalten – also z.B. aus dem Smart Home heraus das Laden/Entladen der Batterie aktiv sperren oder freigeben. Die Kommandos werden dabei als echte JK-BLE-Frames (0x1D / 0x1E) gesendet, genau wie es die JK-App macht. Der aktuelle Schaltzustand kommt dann wieder zurück aus dem BMS-Frame und landet im JSON/MQTT, sodass App, ESP und Smart Home immer synchron sind.

Unten habe ich zusammengefasst, was der Sketch alles kann, welche Topics es gibt und welche Stellen man anpassen muss (WLAN, MQTT, Gerätename, Kapazität etc.). Wer ein ähnliches JK-BMS mit BLE hat und einen ESP32 rumliegen – einfach die .ino-Dateien ins Arduino-Projekt kopieren, die paar Parameter anpassen und schon hat man ein voll integriertes JK-BMS im eigenen Smart Home. - Danke an alle die dieses Projekt mit unterstützt haben - sondt hätte ich das nicht geschaft!!

1. Hardware / Voraussetzungen

ESP32 Dev-Board (z.B. ESP32-DevKitC, WROOM, WROVER)

JK-BMS mit BLE, bei dir konkret:
JK_B2A20S20P (JK02-Protokoll)

Stabile 5V/USB-Versorgung für den ESP32

WLAN im gleichen Netz wie:

ESP32

MQTT-Broker

ioBroker / HomeAssistant o.Ä.

2. Features, die dein ESP32-Sketch jetzt hat
BMS-Auswertung (BLE)

Verbindung per BLE zur JK-BMS-UUID ffe0/ffe1

Automatischer Scan & Reconnect, wenn Verbindung weg ist

Auswertung des JK-Hauptframes:

Zellspannungen 16x (0–15)

Battery_Voltage

Charge_Current (Lade/Entlade-Vorzeichen)

Battery_Power (gemeldet)

Temperaturen:

MOS-Temperatur

Battery_T1 / Battery_T2

SOC (Percent_Remain) vom BMS

Capacity_Remain / Nominal_Capacity

Delta_Cell_Voltage / Average_Cell_Voltage

Cycle_Count / Capacity_Cycle

Balancing-Strom und Status balanceCell[]

Uptime in:

Sekunden / Minuten / Stunden / Tage (Uptime_Sec/Min/Hr/Day)

Zusätzlich:

Eigenes SOC-Filtering (Coulomb-Zähler + Glättung → SOC_Calc)

Berechnete Werte:

Energy_Full_Wh

Energy_Remaining_Wh

Estimated_Runtime_h

Webinterface

Interner Webserver auf Port 80

Endpunkte:

/ → reines JSON mit:

"Cell": { "0":..., "1":..., ..., "15":... }

"Battery": { ... }

"Meta": { "WiFi": "online/offline", "BLE": "connected/disconnected" }

/raw → Text-Ansicht / Debug

/web/index.html (auch /web / /web/) → Grafisches Web-Dashboard
(Zellspannungen, SOC, Power, Temps etc.)

MQTT-Integration

MQTT aktiviert: const bool MQTT_ENABLE = true;

Basis-Prefix:

String mqttname = "jkbms";


Veröffentlicht werden u.a.:

Rohes JSON

Topic:
jkbms/json
→ Inhalt ist identisch mit HTTP-/ JSON

Zellspannungen pro Zelle

jkbms/Data/Zelle_01 … jkbms/Data/Zelle_16

Wichtige Battery-Werte (Auswahl)

jkbms/Data/Battery_Voltage

jkbms/Data/Charge_Current

jkbms/Data/Power_Reported

jkbms/Data/Power_Calc

jkbms/Data/MOS_Temp

jkbms/Data/Battery_T1

jkbms/Data/Battery_T2

jkbms/Data/Percent_Remain

jkbms/Data/SOC_Calc

Energie / Kapazität

jkbms/Data/Capacity_Remain_Ah

jkbms/Data/Nominal_Capacity_Ah

jkbms/Data/Capacity_Cycle_Ah

jkbms/Data/Energy_Full_Wh

jkbms/Data/Energy_Remaining_Wh

jkbms/Data/Estimated_Runtime_h

Uptime

jkbms/Data/Uptime_Sec

jkbms/Data/Uptime_Min

jkbms/Data/Uptime_Hr

jkbms/Data/Uptime_Day

Plus alte Struktur:

jkbms/Uptime/Sekunde

jkbms/Uptime/Minuten

jkbms/Uptime/Stunden

jkbms/Uptime/Tage

und als String: jkbms/Uptime (z.B. 184d 11h 42m 18s)

Charge / Discharge Status (BMS-seitig)

jkbms/Data/Charge → "on" / "off"

jkbms/Data/Discharge → "on" / "off"

Balancing

jkbms/Data/Balance_01 … Balance_16 → "0" / "1"

jkbms/Data/Balancing / BalancingActive

Status / Verfügbarkeit

jkbms/status → "online" / "offline"

jkbms/WiFi

jkbms/BLEconnection

MOSFET-Steuerung per MQTT (Charge / Discharge)

Das ist das neue Highlight 👇

MQTT-Topics:

Charge-MOS toggeln:
jkbms/cmd/Charge

Discharge-MOS toggeln:
jkbms/cmd/Discharge

Erlaubte Payloads (Groß/Kleinschreibung egal):

AN:

"ON", "1", "TRUE"

AUS:

"OFF", "0", "FALSE"

Beispiel:

Charge AUS:

Topic: jkbms/cmd/Charge

Payload: OFF

Discharge AUS:

Topic: jkbms/cmd/Discharge

Payload: OFF

Der ESP:

baut einen 20-Byte JK-BLE-Frame mit:

Command 0x1D (Charge) bzw. 0x1E (Discharge)

Wert 0x00000001 = ON bzw. 0x00000000 = OFF

einfacher 8-Bit-Checksumme am Ende

sendet ihn über pRemoteCharacteristic->writeValue(...) an das BMS

das BMS übernimmt den Schaltzustand (so wie in der JK-App)

beim nächsten Datenframe:

BLE_Data_analyse.ino liest die MOS-Statusbytes aus
(bei dir: Bytes 198/199 → "on"/"off")

JSON und MQTT-Topics Data/Charge & Data/Discharge spiegeln den echten BMS-Zustand

Watchdogs / Stabilität

WiFi-Watchdog:

Alle 10s wird WiFi.status() geprüft,

bei Verlust: ESP.restart();

BLE-Frame-Watchdog:

Wenn trotz ble_connected == true länger als 60s keine neuen BMS-Daten kamen:

BLE-Status zurücksetzen

Scan/Connect neu starten

optional MQTT-Status jkbms/status → "offline"

OTA (Over-the-Air Updates)

OTA aktiv über Port 3232

Hostname: ESP32__JKBMS

Passwort: 0000 (in meinem Sketch, sollte man hier im Forum evtl. als „bitte ändern“ erwähnen 😉)

Update z.B. mit Arduino IDE Netzwerk-Port oder espota.py

3. Was ein anderer Nutzer anpassen muss

Im Sketch (Hauptdatei JKBMS-WI.ino):

// WLAN
const char* ssid     = "XXXXX";
const char* password = "XXXXX";

// MQTT
const char* mqtt_server = "192.168.0.69";
const int   mqtt_port   = 1883;

// MQTT Basisname
String mqttname = "jkbms";

// OTA
const char* OTAName     = "ESP32__JKBMS";
const char* OTAPassword = "0000";

// BMS BLE-Gerätename
const char* Geraetename = "JK_B2A20S20P";

// Batteriekapazität (für SOC-Berechnung)
const float BATTERY_CAPACITY_AH = 320.0f;


Muss angepasst werden:

ssid / password → eigenes WLAN

mqtt_server / mqtt_port → MQTT-Broker-IP (-Port)

mqttname → wer möchte, z.B. hausbatterie o.Ä.

OTAName / OTAPassword → aus Sicherheitsgründen ändern

Geraetename → Name, den dein JK-BMS beim Scannen per BLE ausstrahlt

BATTERY_CAPACITY_AH → reale Ah-Kapazität der Batterie

4. Sonstige Hinweise für den Forum-Post

Du nutzt den ESP32 Arduino Core 3.3.3 (Boardverwalter).

Benötigte Libraries (kommen bei Core 3.3.3 i.d.R. mit):

WiFi.h

WebServer.h

BLEDevice.h

PubSubClient.h

ESPmDNS.h

ArduinoOTA.h

JSON-Seite ist direkt über die IP des ESP aufrufbar, z.B.:
http://192.168.0.X/

Die JK-App braucht kein extra Passwort, damit der ESP schalten darf – das App-Passwort 123456 ist nur fürs Menü in der App

JKBMS-WI.zip (24,8 KB)

Kleine Änderung 
Das BMS kann intern machen was es will,
aber im JSON springt Charge / Discharge nicht mehr von alleine auf "off",
sondern nur, wenn du den Befehl sendest.
2 „Gefällt mir“

Hallo
recht komplexer Beitrag mit vielen verschiedenen Lösungen. Dazu eine Frage beim JK Inverter BMS wenn man über das Modbus Protokoll ausliest, gibt es definitiv Limits was dort funktioniert und was nicht. Diese Limits in Datenmenge und/oder Auslesegeschwindigkeit unterscheiden sich beim Master BMS zu den Client BMS. Bei den Clients lassen sich wesentlich weniger Datenpunkte auslesen in Menge und Typ. Teils erhalte ich auch bei Lesezugriff eine "Illegal Access" Meldung.

Habe dann etwas getestet mit dem Tool "Modbus Poll" und lese ich dann wieder einige von diesen Datenpunkten (Illegal Access) einzeln aus, funktioniert es.

Gibt es zu diesen praktisch bemerkten Limitis wenn man mehrere Datenpunkte zyklisch liest bekannte Informationen?

Aktuell habe ich nun wieder sehr sporadisch eine Fehlfunktion. Es werden die gewünschten Daten aller 3 BMS eingelesen, aber irgendwann zB nach 3 Tagen gibt es dann anscheinend eine Grenzverletzung und dann geht die Schnittstelle der BMS komplett "auf Störung" bis ich die Verbindung manuell neu aufbaue.

Bei gelesen 11 Registeradressen bin ich aktuell bei diesen Settings angekommen:

Daher gibt es Erkenntnisse dazu?

Das Verhalten ist gleich egal worüber (SPS, Heimautomatisierung oder ESP32-Lösung) ich über Modbus auslese.

@sralus

Guten Tag, ich habe mir Ihre Zipp Datei heruntergeladen und verstehe noch nicht ganz wie die alle zu kombinieren sind? Brauche ich davon nur eine für die Funktion? Ich bin auf Arduino noch starker Anfänger. Vielen Dank für Ihre Hinweise.

[TO-DO] JK-ESP32.zip auf einen ESP32 flashen (Anfänger)

[TO-DO] JK-ESP32.zip auf einen ESP32 flashen (Anfänger) – inkl. Einstellungen + BLE Name
Projekt:
- ZIP: JK-ESP32.zip
- Hauptdatei: JKBMS-WI.ino
Wichtig: Partition Scheme = "Minimal SPIFFS"

============================================================
0) ZIP herunterladen und entpacken
============================================================
[ ] JK-ESP32.zip herunterladen
[ ] JK-ESP32.zip in einen eigenen Ordner entpacken (nicht im ZIP arbeiten!)
    Beispiel:
    C:\Users\DEINNAME\Documents\Arduino\JK-ESP32\

[ ] Prüfen: Im entpackten Ordner liegt die Hauptdatei:
    JKBMS-WI.ino

============================================================
1) Arduino IDE starten
============================================================
[ ] Arduino IDE öffnen (2.x empfohlen)

============================================================
2) ESP32-Unterstützung hinzufügen (GANZ WICHTIG)
============================================================
[ ] Datei -> Voreinstellungen
[ ] Feld: "Zusätzliche Boardverwalter-URLs"
[ ] Diese URL einfügen:

    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

[ ] OK / Speichern

============================================================
3) ESP32 Boardpaket installieren
============================================================
[ ] Werkzeuge -> Board -> Boardverwalter…
[ ] Suche: esp32
[ ] Installiere: "esp32 by Espressif Systems"
[ ] Warten bis fertig

============================================================
4) Projekt öffnen (JKBMS-WI.ino)
============================================================
[ ] Datei -> Öffnen…
[ ] In den entpackten Ordner JK-ESP32 gehen
[ ] Datei öffnen: JKBMS-WI.ino

Hinweis:
- Wenn mehrere Tabs erscheinen: normal.

============================================================
5) VOREINSTELLUNGEN IM SKETCH ANPASSEN (WICHTIG!)
============================================================
Suche in JKBMS-WI.ino (oder den anderen Tabs) nach diesen Variablen
und passe sie an deine Umgebung an (STRG+F hilft):

[ ] ssid / password
    -> Dein WLAN Name + WLAN Passwort

[ ] mqtt_server / mqtt_port
    -> IP-Adresse (und Port) deines MQTT Brokers
       Beispiel: 192.168.178.10 und 1883

[ ] mqttname
    -> frei wählbarer Gerätename für MQTT (z.B. "hausbatterie")

[ ] OTAName / OTAPassword
    -> aus Sicherheitsgründen ändern (nicht Standard lassen!)

[ ] Geraetename
    -> Name, den dein JK-BMS beim Scannen per BLE ausstrahlt (muss 1:1 stimmen!)
       WICHTIG: Bei mir ist es mit "_" (Unterstrich) und NICHT mit "-"
       Beispiel:
       - richtig: "JK_PB2A16S20P"
       - falsch:  "JK-PB2A16S20P"

[ ] BATTERY_CAPACITY_AH
    -> echte Kapazität deiner Batterie in Ah (z.B. 280)

============================================================
6) BLE Gerätename "Geraetename" herausfinden (Android / iPhone)
============================================================
Warum?
- Den BLE-Namen kann man NICHT sicher erraten (modell-/einstellungsabhängig).
- Er muss exakt stimmen, sonst verbindet der ESP32 nicht.

ANDROID (empfohlen, einfach):
[ ] App installieren: "nRF Connect" ODER "BLE Scanner"
[ ] App öffnen -> Scan starten
[ ] Eintrag suchen, der wie JK / JKBMS / JK_... aussieht
[ ] Den angezeigten Namen EXAKT übernehmen (inkl. "_" / "-" / Groß-/Kleinbuchstaben)
    und im Sketch eintragen:
    Geraetename = "GENAU_DIESER_NAME";

iPHONE / iOS:
[ ] App installieren: "nRF Connect" (iOS Version) ODER "LightBlue"
[ ] App öffnen -> Scan starten
[ ] JK / JKBMS / JK_... Eintrag auswählen
[ ] Namen exakt abschreiben und in den Sketch übernehmen

============================================================
7) ESP32 anschließen + Port auswählen
============================================================
[ ] ESP32 per USB anschließen (WICHTIG: Datenkabel, kein reines Ladekabel)
[ ] Werkzeuge -> Port -> richtigen Port auswählen (z.B. COM6)

Wenn kein Port sichtbar ist:
[ ] anderes USB-Kabel testen (oft nur Ladekabel)
[ ] anderen USB-Port testen
[ ] ggf. Treiber installieren (CH340 oder CP2102 – je nach Board)

============================================================
8) Board auswählen
============================================================
[ ] Werkzeuge -> Board -> (meist passend) "ESP32 Dev Module"
    (Falls du dein exaktes ESP32-Board kennst: das passende auswählen)

============================================================
9) WICHTIG: Partition Scheme einstellen (Minimal SPIFFS)
============================================================
[ ] Werkzeuge -> Partition Scheme -> "Minimal SPIFFS"

============================================================
10) Kompilieren (Test)
============================================================
[ ] Auf "✔ Überprüfen" klicken

Wenn Fehlermeldungen wegen Bibliotheken kommen:
[ ] Sketch -> Bibliothek einbinden -> Bibliotheken verwalten…
[ ] Fehlende Bibliothek suchen -> Installieren
[ ] Danach nochmal "✔ Überprüfen"

============================================================
11) Flashen (Sketch hochladen)
============================================================
[ ] Auf "→ Hochladen" klicken

Wenn es bei "Connecting..." hängt:
[ ] BOOT Taste am ESP32 gedrückt halten
[ ] Upload starten
[ ] Sobald "Writing..." erscheint -> BOOT loslassen
[ ] ggf. kurz EN/RESET antippen (je nach Board)

============================================================
12) OPTIONAL: SPIFFS-Daten hochladen (nur wenn ein "data" Ordner existiert)
============================================================
Nur nötig, wenn im Projektordner JK-ESP32 ein Ordner "data" vorhanden ist
(z.B. für Web-Dateien).

Merke:
- Sketch hochladen = Programm
- SPIFFS Upload = Dateien (Web/Assets)

Wenn kein "data" Ordner vorhanden ist:
-> Schritt überspringen.

============================================================
13) Seriellen Monitor öffnen (Kontrolle)
============================================================
[ ] Werkzeuge -> Serieller Monitor
[ ] Baudrate: meist 115200
[ ] Prüfen ob Meldungen kommen (Start, WLAN, IP, MQTT, BLE, etc.)

============================================================
14) Häufige Anfänger-Fehler (Mini-Check)
============================================================
- falsches Board gewählt
- falscher Port gewählt
- USB-Kabel nur zum Laden
- Partition Scheme nicht auf "Minimal SPIFFS"
- BOOT-Taste beim Upload nicht genutzt (wenn "Connecting..." hängt)
- OTA Name/Passwort nicht geändert
- BLE Gerätename stimmt nicht 1:1 (Achtung "_" statt "-")
- (wenn Webprojekt) SPIFFS Upload vergessen

Fertig :)

1 „Gefällt mir“

Danke, klappt leider nicht, hier das Log

Bibliothek ESP32 in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/ESP32 wird verwendet
Bibliothek ESP32 BLE Arduino in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/BLE wird verwendet
Bibliothek WiFi in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/WiFi wird verwendet
Bibliothek WebServer in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/WebServer wird verwendet
Bibliothek PubSubClient in Version 2.8 im Ordner: /Volumes/NAS/Solar/Arudion_Files/libraries/PubSubClient wird verwendet
Bibliothek ESPmDNS in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/ESPmDNS wird verwendet
Bibliothek ArduinoOTA in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/ArduinoOTA wird verwendet
Bibliothek Update in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/Update wird verwendet
Bibliothek FS in Version 2.0.0 im Ordner: /Volumes/Daten/Benutzer/immer/Library/Arduino15/packages/esp32/hardware/esp32/2.0.11/libraries/FS wird verwendet
exit status 1

Compilation error: void value not ignored as it ought to be


Wenn ich aber z.B. das Projekt teste funktioniert es. https://github.com/roblatour/ESP32RemoteForVictron/

Die echte Fehlerzeile finden (Datei + Zeilennummer)

In der Arduino IDE:

  • Ausgabe-Fenster öffnen

  • Ganz nach oben scrollen bis zur ersten Zeile mit error:
    Da steht normalerweise sowas wie:

    • .../JKBMS-WI.ino:1234: error: void value not ignored as it ought to be

:backhand_index_pointing_right: Genau diese Zeile sagt, welche Datei und welche Zeilennummer.

2) Typische Fixes (sehr häufig bei WebServer / String.replace / return)
Fall A: return server.send(...) (häufigster bei WebServer)

server.send(...) gibt void zurück → darf man nicht returnen.

FALSCH

String handleRoot() {
  return server.send(200, "text/plain", "OK");  // server.send ist void
}


RICHTIG (Handler muss void sein)

void handleRoot() {
  server.send(200, "text/plain", "OK");
}


Oder wenn die Funktion unbedingt String zurückgeben muss:

String handleRoot() {
  server.send(200, "text/plain", "OK");
  return "";
}

Fall B: if (myString.replace(...)) (String.replace ist void)

FALSCH

if (myString.replace("a","b")) { ... }  // replace liefert void


RICHTIG

myString.replace("a","b");
if (myString.indexOf("b") >= 0) { ... }  // Beispiel-Check

Fall C: x = irgendwasVoid();

FALSCH

bool ok = server.send(200, "text/plain", "OK"); // void -> geht nicht


RICHTIG

server.send(200, "text/plain", "OK");

Mini-Checkliste für den Newbie

In der Ausgabe die erste error: Zeile suchen (mit Datei:Zeile)

In genau dieser Zeile prüfen, ob da steht:

return <void-funktion>(...)

if (<void-funktion>(...))

variable = <void-funktion>(...)

return / if / = entfernen oder Funktion/Return-Typ passend machen (siehe Beispiele oben)

Wenn du mir die 2–5 Zeilen aus der Arduino-Ausgabe postest, wo die Datei+Zeilennummer steht, sag ich dir genau, welche Stelle in JKBMS-WI.ino (oder welchem Tab) geändert werden muss und wie.

PS: Ich habe genau den skatch aus dem zip nochmal kompiliert: - kein Fehler . :

esptool v5.1.0
Creating ESP32 image...
Merged 2 ELF sections.
Successfully created ESP32 image.

Der Sketch verwendet 1765463 Bytes (89%) des Programmspeicherplatzes. Das Maximum sind 1966080 Bytes.
Globale Variablen verwenden 65736 Bytes (20%) des dynamischen Speichers, 261944 Bytes für lokale Variablen verbleiben. Das Maximum sind 327680 Bytes.

Guten Tag und Danke für Ihre Geduld.

Volumes/NAS/Solar/Arudion_Files/JK-ESP32/JKBMS-WI/BLE_BMS_Connection.ino: In function 'void enableNotify(BLERemoteCharacteristic*)':
/Volumes/NAS/Solar/Arudion_Files/JK-ESP32/JKBMS-WI/BLE_BMS_Connection.ino:63:48: error: void value not ignored as it ought to be
bool ok = desc->writeValue(v, sizeof(v), true);
^
/Volumes/NAS/Solar/Arudion_Files/JK-ESP32/JKBMS-WI/BLE_BMS_Connection.ino: In function 'bool connectToBLEServer()':
/Volumes/NAS/Solar/Arudion_Files/JK-ESP32/JKBMS-WI/BLE_BMS_Connection.ino:172:52: error: conversion from 'std::__cxx11::string' {aka 'std::__cxx11::basic_string'} to non-scalar type 'String' requested
String value = pRemoteCharacteristic->readValue();

@juf Alles klar: Ich nutzt ESP32 Core 3.3.3. Du hast 2.0.11 – daher die Compilerfehler. Du muss auf ESP32 Core 3.3.3 wechseln.

ESP32-Unterstützung hinzufügen (GANZ WICHTIG)
============================================================
[ ] Datei -> Voreinstellungen
[ ] Feld: "Zusätzliche Boardverwalter-URLs"
[ ] Diese URL einfügen:

    https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json

[ ] OK / Speichern


FIX für "void value not ignored..." / BLE Compile-Errors bei JK-ESP32 (JKBMS-WI)

Wenn der Sketch bei mir funktioniert, aber bei dir NICHT:
-> Du hast sehr wahrscheinlich die falsche ESP32-Core-Version installiert.

Bei mir läuft das Projekt mit:
- Arduino IDE: 2.3.6
- ESP32 Boardpaket ("esp32 by Espressif Systems"): 3.3.3

Du hast (sieht man am Pfad in der Ausgabe) aktuell:
- ESP32 Core 2.0.11
Damit gibt es BLE-API Unterschiede (z.B. writeValue() ist void, readValue() ist std::string) -> Compilerfehler.

------------------------------------------------------------
So stellst du es richtig ein (ESP32 Core auf 3.3.3):
------------------------------------------------------------
1) Arduino IDE öffnen
2) Werkzeuge -> Board -> Boardverwalter…
3) Suche nach: esp32
4) Wähle: "esp32 by Espressif Systems"
5) Bei "Version" (Dropdown) auswählen: 3.3.3
6) Installieren (oder Update durchführen)
7) Arduino IDE am besten einmal neu starten
8) Board wählen: "ESP32 Dev Module" (oder dein passendes)
9) Partition Scheme: "Minimal SPIFFS"
10) Nochmal kompilieren: ✔ Überprüfen

Danach sollten die Fehler weg sein.

------------------------------------------------------------
Warum das hilft?
------------------------------------------------------------
Mit ESP32 Core 2.0.11 sind einige BLE-Funktionen anders definiert.
Mein Sketch ist für den ESP32 Core 3.x (bei mir 3.3.3) gebaut/ getestet.

Gruß Sralus

2 „Gefällt mir“

:slight_smile: Ja Danke, das Kompilieren klappt.

Verbindung zum BMS klappt, x.x.x.x/web klappt nur sehe ich keine mqtt Meldungen im Homeassistent oder mqtt-borwser.

Ich habe in HA einen User und ein PW vergeben.. die Einstellung fehlt hier, daher sehe ich nichts, denke ich.

Teste mal :

MQTT TROUBLESHOOTING (JK-ESP32 / JKBMS-WI)
Symptom:
- Verbindung zum BMS klappt
- http://x.x.x.x/web klappt
- ABER: keine MQTT Meldungen in Home Assistant oder im MQTT Browser

Dann ist WLAN/Web ok, das Problem ist fast immer MQTT-Verbindung / Topic / Broker-Settings.
Bitte diese Schritte exakt so abarbeiten:

============================================================
1) SERIELLEN MONITOR PRÜFEN (Pflicht!)
============================================================
1) Arduino IDE -> Werkzeuge -> Serieller Monitor
2) Baudrate: 115200
3) ESP32 kurz neu starten (Reset drücken)
4) Im Log nach MQTT suchen, z.B.:
   - "Connecting to MQTT..."
   - "MQTT connected"
   - "MQTT failed, rc=..."

WICHTIG:
- Wenn im Log GAR NICHTS zu MQTT steht -> MQTT ist im Sketch evtl. nicht aktiv / wird nicht aufgerufen.
- Wenn "failed rc=..." kommt -> rc Wert merken (siehe unten).

Typische rc Werte:
- rc=-2  -> Broker IP/Port nicht erreichbar (falsche IP, falscher Port, Firewall, Broker down)
- rc=5   -> Broker verlangt Benutzer/Passwort oder Auth ist falsch
- rc=2/4 -> Verbindungsproblem oder Client-ID Konflikt (Name doppelt)

============================================================
2) MQTT SERVER/PORT IM SKETCH KONTROLLIEREN
============================================================
Im Sketch prüfen/setzen:
- mqtt_server = IP vom MQTT Broker (am besten echte IP, nicht .local)
- mqtt_port   = meist 1883 (ohne TLS)

WICHTIG:
- Wenn dein Broker TLS nutzt (oft 8883), funktioniert das NICHT ohne TLS-Sketch.
  Für normale HA/Mosquitto Setups: Port 1883.

============================================================
3) IM MQTT BROWSER AUF ALLES ABONNIEREN
============================================================
Im MQTT Explorer / MQTTX / MQTT-Browser:
- Subscribe Topic:   #
Damit siehst du wirklich alles.

Wenn du mit "#" NICHTS siehst:
-> Der ESP32 ist nicht verbunden oder published nicht.

============================================================
4) CHECK: TAUCHT DER ESP32 ALS MQTT CLIENT AUF?
============================================================
Im Broker prüfen, ob der ESP32 überhaupt connected ist:
- Mosquitto Add-on / Broker Log / Client-Liste
- MQTT Explorer zeigt oft auch die Clients

Wenn der ESP32 NICHT als Client auftaucht:
-> IP/Port falsch, Broker nicht erreichbar, Auth blockt, Firewall/VLAN trennt.

============================================================
5) HÄUFIGSTE URSACHEN + FIX
============================================================

A) Broker verlangt Username/Passwort (sehr häufig in HA)
- Wenn rc=5 -> Broker verlangt Auth.
Fix:
- Entweder im Sketch MQTT Username/Passwort eintragen (falls vorgesehen)
- Oder zum Test am Broker kurzfristig anonymous erlauben

B) Client-ID / mqttname ist doppelt
- Wenn mehrere ESP32 den gleichen mqttname nutzen, kickt der Broker einen raus.
Fix:
- mqttname eindeutig machen, z.B. "hausbatterie_1" statt "hausbatterie"

C) Home Assistant zeigt keine Entities
- Selbst wenn MQTT läuft, erscheinen Entities in HA nur mit MQTT-Discovery oder manueller Sensor-Config.
Aber: Wenn im MQTT Browser auch nichts kommt -> erst MQTT Verbindung fixen (Schritte 1-4).

============================================================
6) WAS DU ZUR HILFE POSTEN SOLLTEST
============================================================
Bitte posten:
1) 10–30 Zeilen aus dem Seriellen Monitor rund um MQTT (mit "connected" oder "failed rc=...")
2) mqtt_server + mqtt_port (ohne Passwörter)
3) mqttname (damit man Client-ID Konflikte sieht)

Dann kann man sofort sagen, ob es IP/Port, Auth, Client-ID oder Broker-Settings sind.

so würde die jkbms.ino dann aussehen:

// JKBMS-WI.ino
#include <dummy.h>
#include <dummy.h>

#include <WiFi.h>
#include <WebServer.h>
#include <PubSubClient.h>
#include <ArduinoOTA.h>
#include <ESPmDNS.h>
#include <Update.h>
#include <FS.h>

#include <BLEDevice.h>
#include <BLEUtils.h>
#include <BLEScan.h>
#include <BLEAdvertisedDevice.h>

// ======================== Einstellungen ========================

// WiFi Settings
const char* ssid     = "XXXXX";
const char* password = "XXXXX";

// MQTT Settings
const char* mqtt_server = "192.168.0.69";
const int   mqtt_port   = 1883;

// MQTT Login (nur wenn dein Broker Username/Passwort verlangt)
// Wenn leer gelassen ("") wird ohne Login verbunden.
const char* mqtt_user     = "";
const char* mqtt_password = "";

// MQTT Basis-Prefix
String mqttname = "jkbms";
const bool MQTT_ENABLE = true;

// OTA Settings
const char* OTAName     = "ESP32__JKBMS";
const char* OTAPassword = "0000";

WiFiClient   espClient;
PubSubClient client(espClient);

// BLE Settings
bool BLEScanStatus = false;

// --- Balancing status ---
bool balanceCell[16] = {0};
bool balancingNow = false;

// --- Variables for BLE ---
BLEClient* pClient = nullptr;
BLERemoteCharacteristic* pRemoteCharacteristic = nullptr;
bool deviceConnected = false;
bool doConnect = false;
bool doScan = false;

static BLEUUID serviceUUID("0000ffe0-0000-1000-8000-00805f9b34fb");
static BLEUUID charUUID("0000ffe1-0000-1000-8000-00805f9b34fb");

// Dieser Gerätename MUSS exakt stimmen! (Achtung "_" statt "-")
String Geraetename = "JK_PB2A16S20P";

// Battery capacity
float BATTERY_CAPACITY_AH = 280.0;

// Webserver
WebServer server(80);

// Timings / Watchdogs
unsigned long lastBleAttempt = 0;
unsigned long lastBLEData = 0;
unsigned long lastReconnectAttempt = 0;
unsigned long lastPublish = 0;

// Debug switches via MQTT
bool debugging_aktive = false;
bool debugging_Full_Log_aktive = false;

// =============== Vorwärtsdeklarationen (damit der Compiler Ruhe gibt) ===============
void mqttCallback(char* topic, byte* payload, unsigned int length);
void mqtt_reconnect();
void publishToMQTT();
void setupWebRoutes();
void handleWebRoot();
void handleWebIndex();
void handleWebNotFound();
void check_BLE_connection();
bool connectToBLEServer();
void startScan();
void Datenanalyse(uint8_t* data, int len);

// ======================== Web: JSON Root ========================
void handleWebRoot() {
  String HTML = "{";
  HTML += "\"status\":\"ok\"";
  HTML += "}";
  server.send(200, "application/json", HTML);
}

// ======================== MQTT-Reconnect ========================
void mqtt_reconnect() {
  if (!MQTT_ENABLE) return;
  if (client.connected()) return;
  if (WiFi.status() != WL_CONNECTED) return;

  unsigned long now = millis();
  if (now - lastReconnectAttempt < 5000) return;
  lastReconnectAttempt = now;

  String clientId  = mqttname + "_client";
  String willTopic = mqttname + "/status";

  // Wenn mqtt_user gesetzt ist, mit Login verbinden, sonst ohne
  bool connected = false;

  if (strlen(mqtt_user) > 0) {
    connected = client.connect(
      clientId.c_str(),
      mqtt_user,
      mqtt_password,
      willTopic.c_str(),   // Will-Topic
      1,                   // QoS 1
      true,                // retained
      "offline"            // Will-Message
    );
  } else {
    connected = client.connect(
      clientId.c_str(),
      willTopic.c_str(),   // Will-Topic
      1,                   // QoS 1
      true,                // retained
      "offline"            // Will-Message
    );
  }

  if (connected) {
    Serial.println("[MQTT] connected");

    // Direkt nach erfolgreichem Connect: "online" (retained) senden
    client.publish(willTopic.c_str(), "online", true);

    // Debug-Parameter
    client.subscribe((mqttname + "/parameter/debugging_aktive").c_str());
    client.subscribe((mqttname + "/parameter/debugging_Full_Log_aktive").c_str());

    // MOS-Command-Topics
    String cmdChargeTopic    = mqttname + "/cmd/Charge";
    String cmdDischargeTopic = mqttname + "/cmd/Discharge";

    client.subscribe(cmdChargeTopic.c_str());
    client.subscribe(cmdDischargeTopic.c_str());

    // Optional: initiale Werte publishen (damit Topics sichtbar sind)
    client.publish(cmdChargeTopic.c_str(), "OFF", true);
    client.publish(cmdDischargeTopic.c_str(), "OFF", true);

    Serial.println("[MQTT] subscribed cmd/Charge & cmd/Discharge");
  } else {
    Serial.print("[MQTT] connect failed, state=");
    Serial.println(client.state());
  }
}

// ======================== MQTT Callback ========================
void mqttCallback(char* topic, byte* payload, unsigned int length) {
  String t = String(topic);
  String msg;
  for (unsigned int i = 0; i < length; i++) msg += (char)payload[i];

  if (t == mqttname + "/parameter/debugging_aktive") {
    debugging_aktive = (msg == "1" || msg == "true" || msg == "ON");
    Serial.print("[MQTT] debugging_aktive = ");
    Serial.println(debugging_aktive ? "true" : "false");
  }
  if (t == mqttname + "/parameter/debugging_Full_Log_aktive") {
    debugging_Full_Log_aktive = (msg == "1" || msg == "true" || msg == "ON");
    Serial.print("[MQTT] debugging_Full_Log_aktive = ");
    Serial.println(debugging_Full_Log_aktive ? "true" : "false");
  }

  // Beispiel: Charge/Discharge (falls du es weiterverarbeitest)
  if (t == mqttname + "/cmd/Charge") {
    Serial.print("[MQTT] cmd/Charge: ");
    Serial.println(msg);
  }
  if (t == mqttname + "/cmd/Discharge") {
    Serial.print("[MQTT] cmd/Discharge: ");
    Serial.println(msg);
  }
}

// ======================== Web Routes ========================
void setupWebRoutes() {
  server.on("/", handleWebRoot);
  server.on("/web", handleWebIndex);
  server.onNotFound(handleWebNotFound);
}

void handleWebIndex() {
  // Minimal: nur Hinweis. In deiner funktionierenden Version wird hier vermutlich /web/index.html ausgeliefert.
  String HTML = "<html><body><h1>JK-BMS Web</h1><p>/web ok</p></body></html>";
  server.send(200, "text/html", HTML);
}

void handleWebNotFound() {
  server.send(404, "text/plain", "Not Found");
}

// ======================== Setup ========================
void setup() {
  Serial.begin(115200);
  delay(500);

  // WiFi
  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.print("[WiFi] connecting");
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();
  Serial.print("[WiFi] connected, IP: ");
  Serial.println(WiFi.localIP());

  // mDNS (optional)
  if (MDNS.begin("jkbms")) {
    Serial.println("[mDNS] started");
  }

  // OTA
  ArduinoOTA.setHostname(OTAName);
  ArduinoOTA.setPassword(OTAPassword);
  ArduinoOTA.begin();
  Serial.println("[OTA] ready");

  // Web
  setupWebRoutes();
  server.begin();
  Serial.println("[Web] server started");

  // MQTT
  if (MQTT_ENABLE) {
    client.setServer(mqtt_server, mqtt_port);
    client.setCallback(mqttCallback);
    Serial.println("[MQTT] enabled");
  }

  // BLE
  BLEDevice::init("");
  startScan();
}

// ======================== Loop ========================
void loop() {
  ArduinoOTA.handle();
  server.handleClient();

  if (MQTT_ENABLE) {
    if (!client.connected()) {
      mqtt_reconnect();
    }
    client.loop();
  }

  // BLE: Verbindung & Watchdog
  check_BLE_connection();

  // MQTT Publish zyklisch (Beispiel)
  if (MQTT_ENABLE && client.connected()) {
    unsigned long now = millis();
    if (now - lastPublish > 2000) { // alle 2 Sekunden (nur Beispiel)
      lastPublish = now;
      publishToMQTT();
    }
  }
}

// ======================== MQTT Publish (Beispiel) ========================
void publishToMQTT() {
  // Hier publishst du in deiner echten Version deine Werte.
  // Minimal-Beispiel, damit man im MQTT-Browser wenigstens was sieht:
  String topic = mqttname + "/test/alive";
  client.publish(topic.c_str(), "1", true);
}

// ======================== BLE Scan Start ========================
class MyAdvertisedDeviceCallbacks: public BLEAdvertisedDeviceCallbacks {
  void onResult(BLEAdvertisedDevice advertisedDevice) {
    String devName = advertisedDevice.getName().c_str();
    if (devName.length() > 0) {
      if (debugging_aktive) {
        Serial.print("[BLE] Found: ");
        Serial.println(devName);
      }
    }

    if (devName == Geraetename) {
      Serial.println("[BLE] Target found!");
      BLEDevice::getScan()->stop();
      doConnect = true;
    }
  }
};

void startScan() {
  BLEScan* pBLEScan = BLEDevice::getScan();
  pBLEScan->setAdvertisedDeviceCallbacks(new MyAdvertisedDeviceCallbacks());
  pBLEScan->setActiveScan(true);
  pBLEScan->start(5, false);
  BLEScanStatus = true;
  Serial.println("[BLE] scanning...");
}

// ======================== BLE Connection Watchdog ========================
void check_BLE_connection() {
  if (doConnect && !deviceConnected) {
    Serial.println("[BLE] connecting...");
    deviceConnected = connectToBLEServer();
    doConnect = false;
  }

  // Wenn keine Daten mehr kommen -> neu scannen (simple watchdog)
  if (deviceConnected) {
    if (millis() - lastBLEData > 15000) {
      Serial.println("[BLE] watchdog: no data -> rescan");
      deviceConnected = false;
      if (pClient) pClient->disconnect();
      startScan();
    }
  } else {
    // wenn nicht connected, ab und zu scannen
    if (!BLEScanStatus && millis() - lastBleAttempt > 10000) {
      lastBleAttempt = millis();
      startScan();
    }
  }
}

// ======================== BLE Connect ========================
void enableNotify(BLERemoteCharacteristic* pRemoteCharacteristic) {
  if (!pRemoteCharacteristic) return;

  BLERemoteDescriptor* desc = pRemoteCharacteristic->getDescriptor(BLEUUID((uint16_t)0x2902));
  if (desc) {
    uint8_t v[2] = {0x01, 0x00}; // notifications enable
    desc->writeValue(v, sizeof(v), true);
  }
  pRemoteCharacteristic->registerForNotify([](BLERemoteCharacteristic* c, uint8_t* data, size_t length, bool isNotify) {
    lastBLEData = millis();
    Datenanalyse(data, (int)length);
  });
}

bool connectToBLEServer() {
  BLEAddress address(BLEUUID((uint16_t)0x0000));
  // Hinweis: In deiner echten Version hast du hier vermutlich die korrekte Address/Device Speicherung.
  // Diese Minimal-Version ist nur als Platzhalter.

  // ---- Hier muss in deiner echten Version die Verbindung aufgebaut werden ----
  // Wenn du eine funktionierende connectToBLEServer() hast, lass sie 그대로.

  // Dummy:
  return false;
}

// ======================== Datenanalyse Platzhalter ========================
void Datenanalyse(uint8_t* data, int len) {
  // In deiner echten Version: komplette JK-BMS Parsing Logik
  (void)data;
  (void)len;
}

2 „Gefällt mir“

:slight_smile: rennt :slight_smile:

sehe Daten im mqtt explorer

Ich müsste auch auf die 3.3.3 aktualisieren aber die Installation wird immer abgebrochen. Nach ein bisschen Internet Suche kam ich dann auf ein Timeout sprich mein Internet scheint zu langsam zu sein momentan. Weiß jemand ob man das auch manuell runterladen und installieren kann?

Hallo und besten Dank an alle für die Arbeit.

Ich habe das System von Scotty89 (V3.6) erfolgreich am Laufen und habe nun die Version von sralus probiert.

Nach einigen Schwierigkeiten beim Kompilieren (diese inkompatiblen ESP-Board-Versionen sind wirklich ein Pain in the Ass) konnte ich den Sketch auf den ESP schieben und er läuft auch.

Allerdings bekomme ich keine BLE-Verbindung, das BMS erscheint zwar beim Scan, aber verbinden tut er sich nicht. Wie gesagt, die Version von Scotty89 läuft. Kann es sein, dass das System von sralus nur mit den "Inverter"-BMSen von JK läuft? Ich habe hier nur eine "kleines" JK-B1A24S15P?

EDIT: Funktioniert jetzt, wahrscheinlich ein kaputter ESP. Hab offenbar eine ganze Serie davon bekommen. Mit einem ESP aus einer anderen Lieferung hat's auf Anhieb funktioniert. Lediglich die MQTT-Authentifizierung schlug fehl, hab die aus dem Broker mal rausgenommen, dann gehts. Möglicherweise hab ich auch noch irgendwas zum Einschalten im Code übersehen.

Im source von sralus fehlte der user und password im connect für mqtt. Man konnte sich nicht verbinden mit dem im source definierten user und password..

Also besser so:

if (client.connect(
        clientId.c_str(),
        mqtt_user, mqtt_password,
        willTopic.c_str(),   // Will-Topic
        1,                   // QoS 1
        true,                // retained
        "offline"            // Will-Message
      )) {
    Serial.println("[MQTT] connected");

1 „Gefällt mir“

sorry hatte ich im zip nicht mit eingebunden aber beschrieben wie es aussssehen müsste um MQTT user und pass. einzubinden : // MQTT Settings
const char* mqtt_server = "192.168.0.69";
const int mqtt_port = 1883;

// MQTT Login (nur wenn dein Broker Username/Passwort verlangt)
// Wenn leer gelassen ("") wird ohne Login verbunden.
const char* mqtt_user = "";
const char* mqtt_password = "";

Gruß Sralus

Hallo, danke für das Projekt und die rein gesteckte Arbeit. Ich habe mir jetzt auch ein JK Bms mit 16 Batterie Zellen zugelegt und wollte die Anbindungen über den ESP32 realisieren. Doch jetzt haben sich einige Probleme ergeben. Ein kurzer Ist Stand, das kompilieren von JKBMS-WI hat geklappt. Ich sehe auch das ESP im WLAN, kann aber keine Verbindung über den Browser herstellen. Über den seriellen Monitor kann ich zwar sehen, wie der ESP eine Verbindung aufbauen will, aber es kommt jedesmal ein Time out. Die SID und der Password stimmen. Ich habe das jetzt schon bei mehreren ESPs probiert, aber immer das gleiche Problem. Ich möchte mir jetzt explizit neue ESPs kaufen, dabei bin ich auf Chips mit der Bezeichnung CH340 und CP2102 gestoßen. Gibt es da eine Empfehlung, zwecks problemlosen Betrieb?

Update: Das Wlan Problem hat sich von selbst erledigt. ich bekomme jetzt einen Output

BLE] Notify frame len=150
[BLE] Notify frame len=4
[BLE] Notify frame len=4
[BLE] Notify frame len=150
[BLE] Notify frame len=150
[BLE] Notify frame len=4
[BLE] Notify frame len=4
[BLE] Notify frame len=150
[BLE] Notify frame len=150

Das kommt jetzt Seitenweise, ab und zu gibt es auch andere Meldungen

DBG] t=349897 ms heap=27768 minHeap=13596 WiFi=OK BLE=OK mqttname=jkbms01

MQTT] connect failed
[KICK] getInfo sent (delayed WR)
[DBG] t=22308 ms heap=28136 minHeap=23544 WiFi=OK BLE=OK mqttname=jkbms01
[JK-CONF] Settings-Frame dekodiert:
Cell_UVP_V = 2.500
Cell_OVP_V = 3.650
Balance_Start_V = 0.010
Charge_Voltage_Limit_V = 55.20
Power_Off_Voltage_V = 2.49
Charge_Current_Limit_A = 200.00
Discharge_Current_Limit_A = 200.00
Max_Balance_Current (Config) = 2.00

Aber einen Aufruf über den Browser ist nach wie vor nicht möglich, ich sehe auch keinen Eintrag über mqtt. Hat jemand vielleicht eine Idee wegen den fehlenden Aufruf über den Browser?

Der MQTT Fehler ist auch seltsam, die connet Daten zum MQTT Server sind korrekt, habe ich über einen Linux Client mit mosquitto-clients getestet.

Diese Einträge habe ich in arduino gesetzt.

// MQTT Settings

const char* mqtt_server = "192.168.4.122";

const int mqtt_port = 1883;

// MQTT Login (nur wenn dein Broker Username/Passwort verlangt)

// Wenn leer gelassen ("") wird ohne Login verbunden.

const char* mqtt_user = "kurt";

const char* mqtt_password = "Geheim";

// MQTT Basis-Prefix

String mqttname = "jkbms01";

const bool MQTT_ENABLE = true;