Integracja z HA inwertera jsdsolar j12000hc

Może komuś udało się uzyskać komunikacje z tym inwerterem? Mam przygotowany zestaw, kabel USB A do konwertera rs232 do ttl esp32. Zapytania gmod\r itd. Odpowiedź jest, ale same krzaki.

Typowy objaw niedopasowania prędkości portów szeregowych. Sprawdź ustawienia UARTa.

Sprawdziłem już wszystkie kombinacje RX/TX po obu stronach z prędkością od 2400 do 19200 .

Kombinacja RX/TX jest tylko jedna - ta która działa, ta druga nie działa.
UART oprócz prędkości ma też inne ustawienia - długość słowa, parzystośc i bit stopu.
Robisz to na podstawie jakiejkolwiek dokumentacji (gdzie jest link, gdzie są zdjęcia) lub masz jako-takie doświadczenie by rozpoznać (np. na podstawie konstrukcji płyty głównej) gdzie się podpinasz i czy to w ogóle jest RS232?

Inwerter ma gniazdo USB A. Pinout mam z githuba.

red - +5v

white - RX inv

green - TX inv

black - GND

Rx do gnd i tx do gnd ±10V. Czyli raczej rs232. Podłączone też standardowe jak w innych projektach.

id: jd_uart

tx_pin: ${uart_tx_pin}

rx_pin: ${uart_rx_pin}

baud_rate: 2400

stop_bits: 1

data_bits: 8

parity: NONE

Podaj może repo z którego korzstasz.

To coś nie jest YAMLem (źle wklejasz), w każdym razie taka konstrukcja tx_pin: ${uart_tx_pin} wymaga definicji pinu przez Substitutions

8N1 wydaje się być dość typowe, napięcia sugerują RS232, ale więcej pewności byś nabrał analizując płytę główną (musi mieć transceiver RS232)

między ESP32 a inwerterem masz moduł MAX3232? Bez niego komunikacja nie zadziała poprawnie.

ma


To jakiś eufemizm - MCU po prostu dym wypuści.

esphome:

name: jsdsolar

friendly_name: jsdsolar

esp32:

board: esp32dev

framework:

type: esp-idf

logger:

level: VERY_VERBOSE

api:

encryption:

key: ""

ota:

  • platform: esphome

    password: “”

web_server:

port: 80

wifi:

ssid: !secret wifi_ssid

password: !secret wifi_password

ap:

ssid: "Jsdsolar Fallback Hotspot"

password: "cLrUqMuwMunB"

captive_portal:

uart:

id: uart_jsd

tx_pin: GPIO18

rx_pin: GPIO19

baud_rate: 2400

data_bits: 8

stop_bits: 1

parity: NONE

interval:

  • interval: 5s

    then:

    • uart.write: “GBAT\r”

    • delay: 1500ms

    • uart.write: “GMOD\r”

  • interval: 1s

    then:

    • lambda: |-

      std::string str = “”;

      while (id(uart_jsd).available()) {

      char c;
      
      id(uart_jsd).read_byte((uint8_t\*)&c);
      
      str += c;
      

      }

      if (!str.empty()) {

      ESP_LOGD("UART", "%s", str.c_str());
      

      }

Jak prawidłowo zamieszczać YAML, inny kod lub logi w postach na forum

To issue to piękny przykład dlaczego nie pisać na githubie po polsku, ukraińsku, czy chińsku…
ale OK widzę z jakiego YAMLa wystartowałeś

substitutions:
  hostname: jdsolar-j5500hpc
  device_name: "Jdsolar J5500HPC"
  uart_rx_pin: GPIO16
  uart_tx_pin: GPIO17

esphome:
  name: ${hostname}
  friendly_name: ${device_name}

esp32:
  board: esp32dev
  framework:
    type: arduino

logger:
  level: DEBUG
  baud_rate: 0

api:
  encryption:
    key: !secret api_key

ota:
  - platform: esphome
    password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password
  ap:
    ssid: "${hostname} Fallback"
    password: "12345678"

captive_portal:
web_server:
  port: 80

uart:
  - id: jd_uart
    tx_pin: ${uart_tx_pin}
    rx_pin: ${uart_rx_pin}
    baud_rate: 2400
    stop_bits: 1
    data_bits: 8
    parity: NONE

# ========== СЕНСОРИ ==========

sensor:
  - platform: uptime
    name: "${device_name} Uptime"
  - platform: wifi_signal
    name: "${device_name} WiFi Signal"
    update_interval: 60s

  # === БАТАРЕЯ ===
  - platform: template
    name: "${device_name} Battery Voltage"
    id: battery_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Battery Current"
    id: battery_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 2
    
  - platform: template
    name: "${device_name} Battery Cells"
    id: battery_cells
    state_class: measurement
    
  - platform: template
    name: "${device_name} Battery EOD Voltage"
    id: battery_eod
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Battery Low Alarm"
    id: battery_low_alarm
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Battery Capacity"
    id: battery_capacity
    unit_of_measurement: "%"
    device_class: battery
    state_class: measurement

  # === МЕРЕЖА ===
  - platform: template
    name: "${device_name} Grid Voltage"
    id: grid_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Grid Frequency"
    id: grid_frequency
    unit_of_measurement: "Hz"
    device_class: frequency
    state_class: measurement
    accuracy_decimals: 2
    
  - platform: template
    name: "${device_name} Load Percentage"
    id: load_percentage
    unit_of_measurement: "%"
    state_class: measurement
    
  - platform: template
    name: "${device_name} Grid Daily Energy"
    id: grid_daily_energy
    unit_of_measurement: "Wh"
    device_class: energy
    state_class: total_increasing
    
  - platform: template
    name: "${device_name} Grid Total Energy"
    id: grid_total_energy
    unit_of_measurement: "Wh"
    device_class: energy
    state_class: total_increasing

  # === ВИХІД ===
  - platform: template
    name: "${device_name} Output Voltage"
    id: output_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Output Frequency"
    id: output_frequency
    unit_of_measurement: "Hz"
    device_class: frequency
    state_class: measurement
    accuracy_decimals: 2
    
  - platform: template
    name: "${device_name} Output Current"
    id: output_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 2
    
  - platform: template
    name: "${device_name} Output Power"
    id: output_power
    unit_of_measurement: "W"
    device_class: power
    state_class: measurement
    
  - platform: template
    name: "${device_name} Output Apparent Power"
    id: output_apparent_power
    unit_of_measurement: "VA"
    device_class: apparent_power
    state_class: measurement
    
  - platform: template
    name: "${device_name} Output Daily Energy"
    id: output_daily_energy
    unit_of_measurement: "Wh"
    device_class: energy
    state_class: total_increasing
    
  - platform: template
    name: "${device_name} Output Total Energy"
    id: output_total_energy
    unit_of_measurement: "Wh"
    device_class: energy
    state_class: total_increasing

  # === PV ===
  - platform: template
    name: "${device_name} PV Voltage"
    id: pv_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} PV Current"
    id: pv_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 2
    
  - platform: template
    name: "${device_name} PV Charge Current"
    id: pv_charge_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 2
    
  - platform: template
    name: "${device_name} PV Power"
    id: pv_power
    unit_of_measurement: "W"
    device_class: power
    state_class: measurement
    
  - platform: template
    name: "${device_name} PV Daily Energy"
    id: pv_daily_energy
    unit_of_measurement: "Wh"
    device_class: energy
    state_class: total_increasing
    
  - platform: template
    name: "${device_name} PV Total Energy"
    id: pv_total_energy
    unit_of_measurement: "Wh"
    device_class: energy
    state_class: total_increasing

  # === ЗАРЯД ===
  - platform: template
    name: "${device_name} Bus Voltage"
    id: bus_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Charge Voltage"
    id: charge_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Charge Current"
    id: charge_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Max Charge Current"
    id: max_charge_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 2

  # === ІНВЕРТОР ===
  - platform: template
    name: "${device_name} Inverter Voltage"
    id: inv_voltage
    unit_of_measurement: "V"
    device_class: voltage
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Inverter Frequency"
    id: inv_frequency
    unit_of_measurement: "Hz"
    device_class: frequency
    state_class: measurement
    accuracy_decimals: 2
    
  - platform: template
    name: "${device_name} Inverter Current"
    id: inv_current
    unit_of_measurement: "A"
    device_class: current
    state_class: measurement
    accuracy_decimals: 1

  # === ТЕМПЕРАТУРА ===
  - platform: template
    name: "${device_name} PV Temp"
    id: temp_pv
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Charger Temp"
    id: temp_charger
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} Ambient Temp"
    id: temp_ambient
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 1
    
  - platform: template
    name: "${device_name} MPPT1 Temp"
    id: temp_mppt1
    unit_of_measurement: "°C"
    device_class: temperature
    state_class: measurement
    accuracy_decimals: 1

  # === ВЕНТИЛЯТОР ===
  - platform: template
    name: "${device_name} Fan Speed"
    id: fan_speed
    unit_of_measurement: "%"
    state_class: measurement
    
  - platform: template
    name: "${device_name} Fan1 RPM"
    id: fan1_rpm
    unit_of_measurement: "RPM"
    state_class: measurement
    
  - platform: template
    name: "${device_name} Fan2 RPM"
    id: fan2_rpm
    unit_of_measurement: "RPM"
    state_class: measurement

# ===== ТЕКСТОВІ СЕНСОРИ =====
text_sensor:
  - platform: wifi_info
    ip_address:
      name: "${device_name} IP"
  - platform: template
    name: "${device_name} Mode"
    id: working_mode
  - platform: template
    name: "${device_name} Battery Type"
    id: battery_type
  - platform: template
    name: "${device_name} Charge Stage"
    id: charge_stage
  - platform: template
    name: "${device_name} PV Status"
    id: pv_status
  - platform: template
    name: "${device_name} Fault"
    id: fault_code
  - platform: template
    name: "${device_name} Warning"
    id: warning_code

# ===== БІНАРНІ СЕНСОРИ =====
binary_sensor:
  - platform: template
    name: "${device_name} Grid OK"
    id: grid_ok
    device_class: connectivity
  - platform: template
    name: "${device_name} PV Charging"
    id: pv_charging
    device_class: battery_charging
  - platform: template
    name: "${device_name} Battery Charging"
    id: battery_charging
    device_class: battery_charging
  - platform: template
    name: "${device_name} EQ Mode"
    id: eq_mode
  - platform: template
    name: "${device_name} Fan1 Fault"
    id: fan1_fault
    device_class: problem
  - platform: template
    name: "${device_name} Fan2 Fault"
    id: fan2_fault
    device_class: problem
  - platform: template
    name: "${device_name} Overload"
    id: overload
    device_class: problem
  - platform: template
    name: "${device_name} Over Temp"
    id: over_temp
    device_class: problem
  - platform: template
    name: "${device_name} Battery Low"
    id: battery_low
    device_class: problem

# ===== SWITCH =====
switch:
  - platform: template
    name: "${device_name} Power"
    id: inverter_power
    optimistic: true
    turn_on_action:
      - uart.write:
          id: jd_uart
          data: "SON\r"
    turn_off_action:
      - uart.write:
          id: jd_uart
          data: "SOFF\r"

# ===== ОПИТУВАННЯ =====
interval:
  - interval: 10s
    then:
      - uart.write: {id: jd_uart, data: "GBAT\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GLINE\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GOP\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GPV\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GCHG\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GTMP\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GINV\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GBUS\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "FAN???\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "BL\r"}
      - delay: 500ms
      - uart.write: {id: jd_uart, data: "GMOD\r"}

  # ===== ПАРСИНГ ВІДПОВІДЕЙ =====
  - interval: 100ms
    then:
      - lambda: |-
          static std::string buffer;
          
          while (id(jd_uart).available()) {
            uint8_t c;
            id(jd_uart).read_byte(&c);
            
            if (c == '\r') {
              if (buffer.length() > 0) {
                ESP_LOGD("jdsolar", "RX: %s", buffer.c_str());
                
                if (buffer[0] == '(') {
                  std::string data = buffer.substr(1);
                  std::vector<std::string> parts;
                  size_t pos = 0;
                  
                  while ((pos = data.find(" ")) != std::string::npos) {
                    parts.push_back(data.substr(0, pos));
                    data.erase(0, pos + 1);
                  }
                  if (data.length() > 0) parts.push_back(data);
                  
                  // GBAT - (AAA.A BBB.BB CC DD.D EE.E)
                  if (parts.size() == 5 && parts[0].find(".") != std::string::npos && parts[0].length() <= 5) {
                    id(battery_voltage).publish_state(atof(parts[0].c_str()));
                    id(battery_current).publish_state(atof(parts[1].c_str()));
                    id(battery_cells).publish_state(atoi(parts[2].c_str()));
                    id(battery_eod).publish_state(atof(parts[3].c_str()));
                    id(battery_low_alarm).publish_state(atof(parts[4].c_str()));
                  }
                  
                  // GLINE - (AAA.A BB.BB CCC.C DDD.D EEE.E FFF.F GG.GG HH.HH IIIII JJJ KKKKK LLLLL MMMMM)
                  else if (parts.size() == 13) {
                    id(grid_voltage).publish_state(atof(parts[0].c_str()));
                    id(grid_frequency).publish_state(atof(parts[1].c_str()));
                    id(load_percentage).publish_state(atof(parts[9].c_str()));
                    id(grid_daily_energy).publish_state(atof(parts[10].c_str()) * 10);
                    uint32_t ge_h = atoi(parts[11].c_str());
                    uint32_t ge_l = atoi(parts[12].c_str());
                    id(grid_total_energy).publish_state((ge_h * 100000 + ge_l) * 10);
                  }
                  
                  // GOP - (AAA.A BB.BB CCC.CC DD.DD EEEEE FFFFF GGGGG HHHHH IIIII JJJ KKKKK LLLLL MMMMM NNNNN OOOOO)
                  else if (parts.size() >= 15 && parts[0].find(".") != std::string::npos) {
                    id(output_voltage).publish_state(atof(parts[0].c_str()));
                    id(output_frequency).publish_state(atof(parts[1].c_str()));
                    id(output_current).publish_state(atof(parts[2].c_str()));
                    id(output_power).publish_state(atof(parts[4].c_str()));
                    id(output_apparent_power).publish_state(atof(parts[6].c_str()));
                    id(output_daily_energy).publish_state(atof(parts[13].c_str()) * 10);
                    if (parts.size() >= 16) {
                      uint32_t oe_h = atoi(parts[14].c_str());
                      uint32_t oe_l = atoi(parts[15].c_str());
                      id(output_total_energy).publish_state((oe_h * 100000 + oe_l) * 10);
                    }
                  }
                  
                  // GCHG - (AAA.A BBB.B CC DDD.D EEE.EE FFF.FF GG.G HH.H II.I JJJ.JJ KKKK LLL MMM NNN O P Q R ...)
                  else if (parts.size() >= 18) {
                    id(bus_voltage).publish_state(atof(parts[0].c_str()));
                    id(charge_voltage).publish_state(atof(parts[1].c_str()));
                    id(charge_current).publish_state(atof(parts[3].c_str()));
                    id(max_charge_current).publish_state(atof(parts[9].c_str()));
                    
                    id(eq_mode).publish_state(atoi(parts[14].c_str()) == 1);
                    
                    int btype = atoi(parts[15].c_str());
                    id(battery_type).publish_state(
                      btype == 0 ? "Lead Acid" : 
                      btype == 1 ? "Flooded" : 
                      btype == 2 ? "Lithium" : "Custom"
                    );
                    
                    int cmode = atoi(parts[17].c_str());
                    id(charge_stage).publish_state(
                      cmode == 0 ? "Stop" : 
                      cmode == 1 ? "CC" : 
                      cmode == 2 ? "CV" : "Float"
                    );
                    id(battery_charging).publish_state(cmode >= 1 && cmode <= 3);
                  }
                  
                  // GPV - (AAA.A BBB.B CC.CC DD.DD EEEEE FF G H ...)
                  else if (parts.size() >= 20 && parts[4].length() <= 5) {
                    id(pv_voltage).publish_state(atof(parts[0].c_str()));
                    id(pv_charge_current).publish_state(atof(parts[2].c_str()));
                    id(pv_current).publish_state(atof(parts[3].c_str()));
                    id(pv_power).publish_state(atof(parts[4].c_str()));
                    
                    int pvst = atoi(parts[5].c_str());
                    id(pv_status).publish_state(
                      pvst == 0 ? "Standby" : 
                      pvst == 1 ? "Ready" : 
                      pvst == 2 ? "CV" : "MPPT"
                    );
                    id(pv_charging).publish_state(atoi(parts[6].c_str()) == 1);
                    
                    if (parts.size() >= 21) {
                      id(pv_daily_energy).publish_state(atof(parts[18].c_str()) * 10);
                      uint32_t pe_h = atoi(parts[19].c_str());
                      uint32_t pe_l = atoi(parts[20].c_str());
                      id(pv_total_energy).publish_state((pe_h * 100000 + pe_l) * 10);
                    }
                  }
                  
                  // GTMP - (NNN.N MMM.M AAA.A III.I ZZZ.Z)
                  else if (parts.size() == 5 && parts[0].length() > 3) {
                    id(temp_pv).publish_state(atof(parts[0].c_str()));
                    id(temp_charger).publish_state(atof(parts[1].c_str()));
                    id(temp_ambient).publish_state(atof(parts[2].c_str()));
                    id(temp_mppt1).publish_state(atof(parts[3].c_str()));
                    
                    id(over_temp).publish_state(
                      atof(parts[0].c_str()) > 70 || 
                      atof(parts[1].c_str()) > 70 ||
                      atof(parts[2].c_str()) > 50
                    );
                  }
                  
                  // GINV - (AAA.A BB.BB CCC.C)
                  else if (parts.size() == 3 && parts[1].find(".") != std::string::npos) {
                    id(inv_voltage).publish_state(atof(parts[0].c_str()));
                    id(inv_frequency).publish_state(atof(parts[1].c_str()));
                    id(inv_current).publish_state(atof(parts[2].c_str()));
                  }
                  
                  // FAN - (AAA BBB CCC D E)
                  else if (parts.size() == 5 && parts[0].length() == 3) {
                    id(fan_speed).publish_state(atof(parts[0].c_str()));
                    id(fan1_rpm).publish_state(atof(parts[1].c_str()));
                    id(fan2_rpm).publish_state(atof(parts[2].c_str()));
                    id(fan1_fault).publish_state(atoi(parts[3].c_str()) == 1);
                    id(fan2_fault).publish_state(atoi(parts[4].c_str()) == 1);
                  }
                }
                
                // GMOD - (M)
                else if (buffer.length() == 3 && buffer[0] == '(') {
                  char mode = buffer[1];
                  id(working_mode).publish_state(
                    mode == 'P' ? "Power On" : 
                    mode == 'S' ? "Standby" : 
                    mode == 'L' ? "Line Mode" : 
                    mode == 'B' ? "Battery Mode" : 
                    mode == 'F' ? "Fault" : 
                    mode == 'D' ? "Shutdown" : "Test"
                  );
                  id(grid_ok).publish_state(mode == 'L');
                }
                
                // BL - BLAAA
                else if (buffer.substr(0, 2) == "BL" && buffer.length() == 5) {
                  int capacity = atoi(buffer.substr(2, 3).c_str());
                  id(battery_capacity).publish_state(capacity);
                  id(battery_low).publish_state(capacity < 20);
                }
              }
              buffer.clear();
            } else {
              buffer += (char)c;
            }
          }

Tak wyglądają te układy.

Nie da się tego stwierdzić na czuja jak napisy na układach są nieczytelne, trochę sobie poprawiłem to drugie zdjęcie


i układ wygląda na TPT3232E

więc, tak - to jest w jakimś stopniu zgodne z RS232 (przynajmniej jeśli chodzi o najbardziej interesujące linie Rx i Tx), nie udało mi się zgadnąć czym są te 2 układy na lewo (też jakieś wypusty 3PEAK) bo nawet intensywne poprawianie grafiki nie pomogło, a niemal cała reszta to transoptory odpowiadające za izolację galwaniczną.

Natomiast układ z 1 zdjęcia to ESP32-S3 (i nie wiem czy on stanowi tam główny kontroler, czy tylko tzw. datalogger WiFi, stawiam na drugie), to jest stosunkowo świeży układ na rynku, więc to może być zarówno dobra jak i zła wiadomość (dobra, bo wśród hobbystów jest dobrze znany, więc może się kiedyś pojawi na niego alternatywny wsad; a zła bo to dość nowa konstrukcja i może chińczykowi było wygodniej skorzystać np. z jakiegoś nowego protokołu danych własnego pomysłu częściowo lub całkowicie niezgodnego ze starszymi modelami) ← w nawiasie tylko potencjalne domysły.

Ale ze zgłoszeniem issue o takiej treści, to raczej masz tam marne szanse na pomoc

I get nothing but rubbish from the UART port USB A, marked as com.

bo z tego co widzę, to normalna komunikacja z takim inwerterem jak tam opisano na pierwszy rzut oka wygląda jak śmieci.

Kolejna próba. Znalazłem podobny układ i na tej bazie podłączyłem moje ESP. Gnd i 3.3V się zgadza. RX i TX kolejne dwa skrajne. Cisza.

Tak to formułujesz, że nawet gdybym miał szklaną kulę to nie zrozumiem co robisz nie mając na stole podobnego inwertera.

Dokumentacja, która jest w issue nie wygląda jak dokumentacja fabryczna, tylko jak zapiski z reverse-enigineeringu, ale skorzystaj z niej.
https://github.com/user-attachments/files/24748347/_20240131.pdf
może wygodniejsza do tłumaczenia z chińskiego jest ta wersja
https://github.com/user-attachments/files/24690715/protocol.JSDSOLAR.docx

Sorry mój błąd. Pierwsze co zrobiłem, to skorzystanie z tej dokumentacji. Zapewne jest do starszych wersji inwerterów jsdsolar.

Może przekierować DNS i dane z loggera wysyłać do HA. Tylko ten inwerter obsługuje wattseek, a nie smartess.

Ta komunikacja to takie śmieci, ale ktoś do tego napisał parser, widzę że próbowałeś z tego korzystać (ale tak jak wkleiłeś ten YAML, to się nie da nawet tego przeczytać…).

Natomiast sam fakt, że się generują “śmieci” może wynikać z działania fabrycznego loggera (który też żąda dane równolegle z twoją samoróbką). Sprawdzałeś czy jest możliwa praca bez loggera?

Mam mały sukces. Mimo informacje producenta, że to gniazdko USB a to rs232, działa z konwerterem rs485. Udało mi się odczytać kilka parametrów. AC 230 , 50Hz i kilka napięcie z baterii. Ogólnie te, które mają wartość różną od 0. Tylko mam problem z parserem. Dane z różnych ramek się nadpisując.

esphome:
  name: jsdsolar
  friendly_name: jsdsolar

esp32:
  board: esp32dev
  framework:
    type: esp-idf

# Enable logging
logger:
  level: VERY_VERBOSE
  baud_rate: 0

# Enable Home Assistant API
api:
  encryption:
    key: ""

ota:
  - platform: esphome
    password: ""

web_server:
  port: 80

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  
  ap:
    ssid: "Jsdsolar Fallback Hotspot"
    password: "cLrUqMuwMunB"

captive_portal:


uart:
  id: uart_bus
  rx_pin: GPIO18
  baud_rate: 9600

globals:
  - id: buffer
    type: std::vector<uint8_t>
    restore_value: no

sensor:
  - platform: template
    name: "AC Voltage"
    id: ac_voltage
    unit_of_measurement: "V"
    accuracy_decimals: 1

  - platform: template
    name: "Battery Voltage"
    id: battery_voltage
    unit_of_measurement: "V"
    accuracy_decimals: 1

  - platform: template
    name: "Frequency"
    id: frequency
    unit_of_measurement: "Hz"
    accuracy_decimals: 1

  - platform: template
    name: "Output Current"
    id: current
    unit_of_measurement: "A"
    accuracy_decimals: 1

  
  - platform: template
    name: "Grid Charge Current"
    id: grid_charge_current
    unit_of_measurement: "A"

  - platform: template
    name: "Max Charge Current"
    id: max_charge_current
    unit_of_measurement: "A"

  - platform: template
    name: "Battery Max Voltage"
    id: battery_max_voltage
    unit_of_measurement: "V"

  - platform: template
    name: "Float Voltage"
    id: float_voltage
    unit_of_measurement: "V"

  - platform: template
    name: "Battery Low Voltage"
    id: battery_low_voltage
    unit_of_measurement: "V"

  - platform: template
    name: "Battery Cutoff Voltage"
    id: battery_cutoff_voltage
    unit_of_measurement: "V"

  - platform: template
    name: "Max Discharge Current"
    id: max_discharge_current
    unit_of_measurement: "A"

interval:
  - interval: 200ms
    then:
      - lambda: |-
          
          while (id(uart_bus).available()) {
            uint8_t byte;
            id(uart_bus).read_byte(&byte);
            id(buffer).push_back(byte);
          }

          
          if (id(buffer).size() > 400) {
            id(buffer).erase(id(buffer).begin(), id(buffer).begin() + 150);
          }

          
          for (size_t i = 0; i + 6 < id(buffer).size(); i++) {

            if (id(buffer)[i] == 0x01 && id(buffer)[i+1] == 0x03) {

              uint8_t len = id(buffer)[i+2];

              if (i + 3 + len <= id(buffer).size()) {

                
                std::vector<uint16_t> regs;

                for (int j = 0; j < len; j += 2) {
                  uint16_t val = (id(buffer)[i+3+j] << 8) | id(buffer)[i+4+j];
                  regs.push_back(val);
                }

                
                for (int r = 0; r < regs.size(); r++) {
                  ESP_LOGD("MAP", "[%d] = %d", r, regs[r]);
                }

                for (auto val : regs) {

                  if (val > 2000 && val < 2600) {
                    id(ac_voltage).publish_state(val / 10.0);
                  }

                  else if (val > 400 && val < 600) {
                    id(frequency).publish_state(val / 10.0);
                  }

                  else if (val > 4000 && val < 6000) {
                    id(battery_voltage).publish_state(val / 100.0);
                  }

                  else if (val > 0 && val < 200) {
                    id(current).publish_state(val / 10.0);
                  }
                }
                if (regs.size() > 15) {

                  id(grid_charge_current).publish_state(regs[5] / 10.0);
                  id(max_charge_current).publish_state(regs[6] / 10.0);
                  id(battery_low_voltage).publish_state(regs[7] / 10.0);
                  id(battery_cutoff_voltage).publish_state(regs[8] / 10.0);
                  id(battery_max_voltage).publish_state(regs[9] / 10.0);
                  id(float_voltage).publish_state(regs[10] / 10.0);
                  id(max_discharge_current).publish_state(regs[11] / 10.0);
                }

                id(buffer).erase(id(buffer).begin(), id(buffer).begin() + i + 3 + len);
                break;
              }
            }
          }