Skip to content

[sx126x,sx127x] Hoymiles HMS Inverter RF protocol/gateway #3203

@LorbusChris

Description

@LorbusChris

Describe the problem you have/What new integration you would like

I'd like to use esphome as a gateway to communicate with an Hoymiles HMS solar inverter on 865MHz using an sx126x/sx127x RF transceiver in order to:

  • read power data
  • set power limit
  • on/off/restart

Please describe your use case for this integration and alternatives you've tried:

I need support configuring the sx127x radio and decoding the Hoymiles RF data.
I'm using the following yaml:

esphome:
  name: "hoymiles-gateway"
  friendly_name: Hoymiles Inverter RF Gateway

esp32:
  board: adafruit_feather_esp32_v2
  framework:
    type: arduino

spi:
  clk_pin: GPIO5
  mosi_pin: GPIO19
  miso_pin: GPIO21

sx127x:
  dio0_pin: GPIO27 # IRQ
  #dio1_pin: GPIO26 # A0
  #dio2_pin: GPIO25 # A1
  cs_pin: GPIO33
  rst_pin: GPIO15
  frequency: 865000000
  modulation: FSK
  shaping: GAUSSIAN_BT_0_5
  bitrate: 20000
  bitsync: true
  deviation: 20000
  #crc_enable: true
  rx_floor: -90
  rx_start: true
  sync_value: [0x4D, 0x48, 0x5A, 0x48]
  preamble_size: 30
  preamble_detect: 2
  preamble_errors: 8
  preamble_polarity: 0xAA
  payload_length: 0
  packet_mode: true
  on_packet:
    then:
      - lambda: |-
          std::string res;
          size_t len = x.size();
          char buf[5];
          for (size_t i = 0; i < len; i++) {
            if (i > 0) {
              res += " ";
            }
            sprintf(buf, "%02X", x[i]);
            res += buf;
          }
          ESP_LOGD("lambda", "%s", res.c_str());

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret api_encryption_key

ota:
  - platform: esphome
    password: !secret ota_password

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

#sensor:
#  - platform: template
#    name: "Temperature (°C)"
#    id: inverter_temperature
#  - platform: template
#    name: "Power (W)"
#    id: inverter_power

Additional context

Two implementation for Hoymiles gateways are:

There a CMT2300A transceiver initialized with the following config is used:

Details
;---------------------------------------
;  CMT2300A Configuration File
;  Generated by CMOSTEK RFPDK 1.53_Update3
;  2023.03.24 17:29
;---------------------------------------
; Mode                      = Advanced
; Part Number               = CMT2300A
; Frequency                 = 860.000 MHz
; Xtal Frequency            = 26.0000 MHz
; Demodulation              = GFSK
; AGC                       = On
; Data Rate                 = 20.0 kbps
; Deviation                 = 20.0 kHz
; Tx Xtal Tol.              = 19 ppm
; Rx Xtal Tol.              = 20 ppm
; TRx Matching Network Type = 20 dBm
; Tx Power                  = +20 dBm
; Gaussian BT               = 0.5
; Bandwidth                 = Auto-Select kHz
; CDR Type                  = Counting
; CDR DR Range              = NA
; AFC                       = On
; AFC Method                = Auto-Select
; Data Representation       = 0:F-low 1:F-high
; Rx Duty-Cycle             = Off
; Tx Duty-Cycle             = Off
; Sleep Timer               = Off
; Sleep Time                = NA
; Rx Timer                  = Off
; Rx Time T1                = NA
; Rx Time T2                = NA
; Rx Exit State             = STBY
; Tx Exit State             = STBY
; SLP Mode                  = Disable
; RSSI Valid Source         = PJD
; PJD Window                = 8 Jumps
; LFOSC Calibration         = On
; Xtal Stable Time          = 155 us
; RSSI Compare TH           = NA
; Data Mode                 = Packet
; Whitening                 = Disable
; Whiten Type               = NA
; Whiten Seed Type          = NA
; Whiten Seed               = NA
; Manchester                = Disable
; Manchester Type           = NA
; FEC                       = Enable
; FEC Type                  = x^3+x^2+1
; Tx Prefix Type            = 0
; Tx Packet Number          = 1
; Tx Packet Gap             = 32
; Packet Type               = Variable Length
; Node-Length Position      = First Node, then Length
; Payload Bit Order         = Start from msb
; Preamble Rx Size          = 2
; Preamble Tx Size          = 30
; Preamble Value            = 170
; Preamble Unit             = 8-bit
; Sync Size                 = 4-byte
; Sync Value                = 1296587336
; Sync Tolerance            = None
; Sync Manchester           = Disable
; Node ID Size              = NA
; Node ID Value             = NA
; Node ID Mode              = None
; Node ID Err Mask          = Disable
; Node ID Free              = Disable
; Payload Length            = 32
; CRC Options               = IBM-16
; CRC Seed                  = 0 crc_seed
; CRC Range                 = Entire Payload
; CRC Swap                  = Start from MSB
; CRC Bit Invert            = Normal
; CRC Bit Order             = Start from bit 15
; Dout Mute                 = Off
; Dout Adjust Mode          = Disable
; Dout Adjust Percentage    = NA
; Collision Detect          = Off
; Collision Detect Offset   = NA
; RSSI Detect Mode          = At PREAM_OK
; RSSI Filter Setting       = 32-tap
; RF Performance            = High
; LBD Threshold             = 2.4 V
; RSSI Offset               = 26
; RSSI Offset Sign          = 0

esphome output from yaml above:

[21:09:06][D][lambda:050]: 70 6A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 68 C0 00 5C 00 01 A4 66 9A 1A 65
[21:09:06][D][lambda:050]: 72 5A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 60 03 40 00 00 34 00 D1 B7 00 0D
[21:09:06][D][lambda:050]: 72 5A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 60 05 F9 65 B9 2C 00 00 0D 1C E8
[21:09:06][D][lambda:050]: E6 5A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 68 C6 80 00 00 00 00 00 00 00

expected (logged from OpenDTU):

21:09:06.075 > Nothing received, resend whole request
21:09:06.075 > TX RealTimeRunData 865.00 MHz --> 15 83 76 24 23 80 19 06 08 80 0B 00 68 6D 6C D1 00 00 00 00 00 00 00 00 EC 56 F9 
21:09:06.122 > Interrupt received
21:09:06.128 > RX 865.00 MHz --> 95 83 76 24 23 80 19 06 08 01 00 01 01 1B 01 1A 00 01 00 01 00 04 00 03 00 05 F3 | -78 dBm
21:09:06.167 > Interrupt received
21:09:06.174 > RX 865.00 MHz --> 95 83 76 24 23 80 19 06 08 02 EC B9 00 06 7D E8 02 65 02 62 09 16 13 88 00 00 B7 | -78 dBm
21:09:06.215 > Interrupt received
21:09:06.226 > RX 865.00 MHz --> 95 83 76 24 23 80 19 06 08 83 00 00 00 00 00 00 00 BD 00 11 CA 69 7C | -78 dBm
21:09:06.582 > RX Period 

so

// actual (logged on esphome/sx127x):
msg 1: 70 6A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 68 C0 00 5C 00 01 A4 66 9A 1A 65
msg 2: 72 5A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 60 03 40 00 00 34 00 D1 B7 00 0D
msg 3: 72 5A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 60 05 F9 65 B9 2C 00 00 0D 1C E8
msg 4: E6 5A E8 C6 9C B4 2E 8C B9 A8 C0 06 CB 00 D0 04 68 C6 80 00 00 00 00 00 00 00

// expected (logged on OpenDTU):
msg 1: 15 83 76 24 23 80 19 06 08 80 0B 00 68 6D 6C D1 00 00 00 00 00 00 00 00 EC 56 F9 
msg 2: 95 83 76 24 23 80 19 06 08 01 00 01 01 1B 01 1A 00 01 00 01 00 04 00 03 00 05 F3
msg 3: 95 83 76 24 23 80 19 06 08 02 EC B9 00 06 7D E8 02 65 02 62 09 16 13 88 00 00 B7
msg 4: 95 83 76 24 23 80 19 06 08 83 00 00 00 00 00 00 00 BD 00 11 CA 69 7C

It recognizes the sync word, but I'm probably missing something obvious from the CMT2300A init, like the x^3+x^2+1 polynomial FEC (Forward Error Correction). Any guidance on how to properly receive/decode/parse this data would be appreciated.

ref: lumapu/ahoy#1630

@swoboda1337 @lumapu @stefan123t

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions