Writing to Solax X1-Hybrid-5.0-N-I Modbus

I have a Solax X1 Hybrid system and a complex power plan which the in-built logic of the Solax system can't take full advantage of.

I also have a bit of a complex about sending my data overseas (still working on that, but these scripts help, along with documentation I have found in obscure places online).  Hopefully the information and the trivial scripts below are of use to others.

The key to this is described in a document I found online titled "Hybrid X1&X3-G3 ModbusTCP&RTU V3.21- English" online.  The discussion at https://github.com/squishykid/solax/issues/14 makes for very interesting reading.

I present here 3 trivial python scripts (indeed the first scripts I've written in Python!)  which communicate with the Solax inverter and write to it.    They require pymodbus - In Ubuntu I believe this can be installed with the command "pip3 install pymodbus".

I've connected my Solax Inverter to my network using its built in ethernet port. I note that the IP address of my Solax Inverter is 10.0.3.240 - so modify this as required for your setup.  Likewise, before you can write to registers it seems you need to unlock the unit so you can write to this.  My unit uses the default password "6868", which is coded in the scripts, and you may need to change this if your password is different.

Setting the time

This script sets the date on Modbus.  I run it once a day from crontab, so my Inverter can handle daylight savings time as my server keeps synced thanks to NTP (my power has different prices for different hours in the day, so its important that my inverters date is not an hour out half the year - and I like to set-and-forget.)

#! /usr/bin/python3.8
# See https://pymodbus.readthedocs.io/en/latest/readme.html
# https://raspberrypi.stackexchange.com/questions/66995/reading-registers-through-pymodbus

import os
from pymodbus.client.sync import ModbusTcpClient
from datetime import date,time,datetime

client=ModbusTcpClient('10.0.3.240')
if client.connect():
	# Before we can write, we need to unlock it (6868 = default password)
	result=client.write_register(0x00,6868)

	now=datetime.now()
	thedate=[ 

			int(now.strftime("%S")),
			int(now.strftime("%M")),
			int(now.strftime("%H")),
			int(now.strftime("%d")),
			int(now.strftime("%m")),
			int(now.strftime("%y"))
		]

	result=client.write_registers(0x00,thedate)
	client.close()
else:
	print ("Could not connect to Device")

Set the Work Mode

After writing and testing this script, I discovered its not appropriate to my use case, but it may well be useful to others, so here it is.   The various work modes allow the Hybrid inverter to perform differently - As it happens, I need to make heavy use of "Force Time Use" which controls when the inverter will charge the battery off the grid.

#! /usr/bin/python3.8

import sys
import re
import os
from pymodbus.client.sync import ModbusTcpClient

# IP Address of Modbus Device
connectip='10.0.3.240'


def helpmessage():
	print (f"Usage: {sys.argv[0]} mode\n")
	print ("Where mode is one of:")
	print ("0 - Self Use")
	print ("1 - Force Time Use")
	print ("2 - Back Up Mode")
	print ("3 - Feed in Priority")


if len(sys.argv) != 2:
	helpmessage()
	sys.exit("Exiting")


if not (re.match('^[0-3]+$',sys.argv[1])):
	helpmessage()
	sys.exit("Exiting")

workmode=int(sys.argv[1])
client=ModbusTcpClient(connectip)
if client.connect():
        # Before we can write, we need to unlock it (6868 = default password)
        result=client.write_register(0x00,6868)
        result=client.write_register(0x1f,workmode)
        client.close()
else:
        print ("Could not connect to Device")

Change the times and Maximum Charge Capacity on the Force Time Of Use Work mode

The below script will allow me to change the settings for Force Time Of Use mode (setting 1).   This is useful because I need 3 periods in a day where I want to charge the battery from the grid.  This, with a couple of cron entries allows me to "swap out" the time of use modes, allowing for more then 2 time of use settings.

 

#! /usr/bin/python3.8

import sys
import re
import os
from pymodbus.client.sync import ModbusTcpClient

# IP Address of Modbus Device
connectip='10.0.3.240'

#####################################################
# Note: this is quick and dirty and does not properly check time strings.
#####################################################

def helpmessage():
	print (f"Usage: {sys.argv[0]} StartTime EndTime MaxCapacity\n")
	print ("Where StartTime and EndTime is in form HH:MM")
	print ("      and  MaxCapacity is an Integer which represents a percentage")

if len(sys.argv) != 4:
	helpmessage()
	sys.exit("Exiting")

start=re.split(':',sys.argv[1])
starthour=int(start[0])
startmin=int(start[1])
starttime=startmin*256+starthour

endat=re.split(':',sys.argv[2])
endhour=int(endat[0])
endmin=int(endat[1])
endtime=endmin*256+endhour


chargemaxpct=int(sys.argv[3])

#print (f"Start Time: {starthour} : {startmin} -> {starttime}")
#print (f"End Time: {endhour} : {endmin} -> {endtime} ")
#print (f"Capacity: {chargemaxpct} ")

client=ModbusTcpClient(connectip)
if client.connect():
        # Before we can write, we need to unlock it (6868 = default password)
        result=client.write_register(0x00,6868)
        result=client.write_register(0x26,starttime)
        result=client.write_register(0x27,endtime)
        result=client.write_register(0xA4,chargemaxpct)
        client.close()
else:
        print ("Could not connect to Device")