Local SolaX data

I’ve recently installed a SolaX X1 Mini grid-tied inverter. This comes with a Wifi adapter and cloud offering where you can view the current system performance. This post covers how to redirect the underlying MQTT connection so you can read data from the inverter without data leaving your network.

The steps are:

  • Patch Mosquitto to accept packets with a zero packet identifier
  • Configure Mosquitto to also listen on port 2901
  • Change your DNS to map mqtt001.solaxcloud.com and mqtt002.solaxcloud.com to your MQTT broker
  • Configure Home Assistant or similar to unpack the updates

The uplink is implemented using an unencrypted MQTT connection to mqtt001.solaxcloud.com on port 2901. The inverter fails over to mqtt002.solaxcloud.com if the first is unavailable.

The PUBLISH packets sent by the inverter are invalid as the packet identifier is set to zero. This can be worked around by patching Mosquitto and removing this check from handle_publish.c. If you don’t do this then Mosquitto will detect a protocol violation and close the connection.

On connection the inverter subscribes to a set of topics, requests the current time, and reports as ‘up’. It then publishes the current state every five minutes. All topics contain the Wifi adapter serial number and all payloads are JSON.

An example update published on loc/$WIFI_SERIAL_NUMBER is:

{
  'type': 'X1-Boost-Air-Mini',
  'SN': '$WIFI_SERIAL_NUMBER',
  'ver': '2.033.20',
  'Data': [
    0.2, 0.0, 75.0, 0.0, 0.3, 228.8, 7, 18, 0.0, 1.1,
    0, 17, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0.0, 0.0, 0, 0, 0, 0, 0, 0, 0,
    49.99, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0.0, 0, 0, 0, 0, 0.0, 0, 0, 2,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
    0, 0, 0, 0],
  'Information': [
    1.1, 4,
    'X1-Boost-Air-Mini',
    '$INVERTER_SERIAL_NUMBER',
    1, 2.1, 0.0, 1.3, 0.0
  ]
}

Data contains the readings and these seem to correspond to the direct API fields decoded by Hobi and used by squishykid. For example, in the readings above:

  • The panels are delivering 0.2 A at 75 V
  • The grid is at 228.8 V
  • The system is delivering 8 W and has output 1.1 kWh over the system lifetime

These can be decoded in Home Assistant using MQTT sensor definitions like:

- platform: mqtt
  name: "solax_power_now"
  unique_id: "solax_power_now"
  state_topic: "loc/$WIFI_SERIAL_NUMBER"
  value_template: "{{ value_json.Data[6] }}"
  expire_after: 900
  unit_of_measurement: "W"  
  device_class: power

which will show as:

Power history

Notes

On connection, the inverter subscribes to:

  • respsynctime/$WIFI_SERIAL_NUMBER
  • set/$WIFI_SERIAL_NUMBER
  • set/$WIFI_SERIAL_NUMBER/init
  • update/version/$WIFI_SERIAL_NUMBER
  • base/down/$WIFI_SERIAL_NUMBER

I suspect the set topic is used for remote configuration and update is used to update the firmware.

It then:

  • publishes reqsynctime/$WIFI_SERIAL_NUMBER: {'wifisn': '$WIFI_SERIAL_NUMBER'}
  • receives respsynctime/$WIFI_SERIAL_NUMBER: {'month': '12', 'hour': '11', 'year': '2021', 'day': '4', 'taskId': '297868bb24194080bdf749ab26adc3d6', 'minute': '20', 'second': '30'}
  • publishes Synctime/$WIFI_SERIAL_NUMBER {'code': '2', 'message': 'setting failed'}
  • publishes base/up/$WIFI_SERIAL_NUMBER: {'type': 2, 'wifiSN': '$WIFI_SERIAL_NUMBER', 'domain': 'mqtt002.solaxcloud.com', 'port': 2901}
Avatar
Michael Hope
Software Engineer