pysolarmanv5 API Reference#

pysolarmanv5 provides both sync and async interfaces.

PySolarmanV5#

class pysolarmanv5.PySolarmanV5(address, serial, **kwargs)[source]#

The PySolarmanV5 class establishes a TCP connection to a Solarman V5 data logging stick and exposes methods to send/receive Modbus RTU requests and responses.

For more detailed information on the Solarman V5 Protocol, see Solarman V5 Protocol

Parameters:
  • address (str) – IP address or hostname of data logging stick

  • serial (int) – Serial number of the data logging stick (not inverter!)

  • port (int, optional) – TCP port to connect to data logging stick, defaults to 8899

  • mb_slave_id (int, optional) – Inverter Modbus slave ID, defaults to 1

  • socket_timeout (int, optional) – Socket timeout duration in seconds, defaults to 60

  • v5_error_correction (bool, optional) – Enable naive error correction for V5 frames, defaults to False

New in version v2.4.0.

Parameters:
  • logger (Logger, optional) – Python logging facility

  • socket (Socket, optional) – TCP Socket connection to data logging stick. If socket argument is provided, address argument is unused (however, it is still required as a positional argument)

Raises:

NoSocketAvailableError – If no network socket is available

New in version v2.5.0.

Parameters:

auto_reconnect (Boolean, optional) – Activates the auto-reconnect functionality. PySolarmanV5 will try to keep the connection open. The default is False. Not compatible with custom sockets.

Deprecated since version v2.4.0.

Parameters:

verbose (bool, optional) – Enable verbose logging, defaults to False. Use logger instead. For compatibility purposes, verbose, if enabled, will create a logger, and set the logging level to DEBUG.

Basic example:
>>> from pysolarmanv5 import PySolarmanV5
>>> modbus = PySolarmanV5("192.168.1.10", 123456789)
>>> print(modbus.read_input_registers(register_addr=33022, quantity=6))

See Examples directory for further examples.

disconnect() None[source]#

Disconnect the socket and set a signal for the reader thread to exit

Returns:

None

static twos_complement(val, num_bits)[source]#

Calculate 2s Complement

Parameters:
  • val (int) – Value to calculate

  • num_bits (int) – Number of bits

Returns:

2s Complement value

Return type:

int

read_input_registers(register_addr, quantity)[source]#

Read input registers from modbus slave (Modbus function code 4)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

List containing register values

Return type:

list[int]

read_holding_registers(register_addr, quantity)[source]#

Read holding registers from modbus slave (Modbus function code 3)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

List containing register values

Return type:

list[int]

read_input_register_formatted(register_addr, quantity, **kwargs)[source]#

Read input registers from modbus slave and format as single value (Modbus function code 4)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

  • scale (int) – Scaling factor

  • signed (bool) – Signed value (2s complement)

  • bitmask (int) – Bitmask value

  • bitshift (int) – Bitshift value

Returns:

Formatted register value

Return type:

int

read_holding_register_formatted(register_addr, quantity, **kwargs)[source]#

Read holding registers from modbus slave and format as single value (Modbus function code 3)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

  • scale (int) – Scaling factor

  • signed (bool) – Signed value (2s complement)

  • bitmask (int) – Bitmask value

  • bitshift (int) – Bitshift value

Returns:

Formatted register value

Return type:

int

write_holding_register(register_addr, value)[source]#

Write a single holding register to modbus slave (Modbus function code 6)

Parameters:
  • register_addr (int) – Modbus register address

  • value (int) – value to write

Returns:

value written

Return type:

int

write_multiple_holding_registers(register_addr, values)[source]#

Write list of multiple values to series of holding registers on modbus slave (Modbus function code 16)

Parameters:
  • register_addr (int) – Modbus register start address

  • values (list[int]) – values to write

Returns:

values written

Return type:

list[int]

read_coils(register_addr, quantity)[source]#

Read coils from modbus slave and return list of coil values (Modbus function code 1)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

register values

Return type:

list[int]

read_discrete_inputs(register_addr, quantity)[source]#

Read discrete inputs from modbus slave and return list of input values (Modbus function code 2)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

register values

Return type:

list[int]

write_single_coil(register_addr, value)[source]#

Write single coil value to modbus slave (Modbus function code 5)

Parameters:
  • register_addr (int) – Modbus register start address

  • value (int) – value to write; 0xFF00 (On) or 0x0000 (Off)

Returns:

value written

Return type:

int

write_multiple_coils(register_addr, values)[source]#

Write multiple coil values to modbus slave (Modbus function code 15)

Parameters:
  • register_addr (int) – Modbus register start address

  • values (list[int]) – values to write; 1 (On) or 0 (Off)

Returns:

values written

Return type:

list[int]

masked_write_holding_register(register_addr, **kwargs)[source]#

Mask write a single holding register to modbus slave (Modbus function code 22)

Used to set or clear individual bits within a holding register

If default values are provided for both or_mask and and_mask, the write element of this function is a NOP.

Warning

This is not implemented as a native Modbus function. It is a software implementation using a combination of read_holding_registers() and write_holding_register().

It is therefore not atomic.

Parameters:
  • register_addr (int) – Modbus register address

  • or_mask (int) – OR mask (set bits), defaults to 0x0000 (no change)

  • and_mask (int) – AND mask (clear bits), defaults to 0xFFFF (no change)

Returns:

value written

Return type:

int

send_raw_modbus_frame(mb_request_frame)[source]#

Send raw modbus frame and return modbus response frame

Wrapper around internal method _send_receive_modbus_frame()

Parameters:

mb_request_frame (bytearray) – Modbus frame

Returns:

Modbus frame

Return type:

bytearray

send_raw_modbus_frame_parsed(mb_request_frame)[source]#

Send raw modbus frame and return parsed modbusresponse list

Wrapper around internal method _get_modbus_response()

Parameters:

mb_request_frame (bytearray) – Modbus frame

Returns:

Modbus RTU decoded values

Return type:

list[int]

PySolarmanV5Async#

class pysolarmanv5.PySolarmanV5Async(address, serial, **kwargs)[source]#

The PySolarmanV5Async class establishes a TCP connection to a Solarman V5 data logging stick on a call to connect() and exposes methods to send/receive Modbus RTU requests and responses asynchronously.

For more detailed information on the Solarman V5 Protocol, see Solarman V5 Protocol

Parameters:
  • address (str) – IP address or hostname of data logging stick

  • serial (int) – Serial number of the data logging stick (not inverter!)

  • port (int, optional) – TCP port to connect to data logging stick, defaults to 8899

  • mb_slave_id (int, optional) – Inverter Modbus slave ID, defaults to 1

  • v5_error_correction (bool, optional) – Enable naive error correction for V5 frames, defaults to False

  • auto_reconnect (bool, optional) – Auto reconnect to the data logging stick on error

Basic example:
>>> import asyncio
>>> from pysolarmanv5 import PySolarmanV5Async
>>> modbus = PySolarmanV5Async("192.168.1.10", 123456789)
>>> modbus2 = PySolarmanV5Async("192.168.1.11", 123456790)
>>> loop = asyncio.get_event_loop()
>>> loop.run_until_complete(asyncio.gather(*[modbus.connect(), modbus2.connect()], return_exceptions=True)
>>>
>>> print(loop.run_until_complete(modbus.read_input_registers(register_addr=33022, quantity=6)))
>>> print(loop.run_until_complete(modbus2.read_input_registers(register_addr=33022, quantity=6)))

See Examples directory for further examples.

async connect() None[source]#

Connect to the data logging stick and start the socket reader loop

Returns:

None

Raises:

NoSocketAvailableError – When connection cannot be established

async reconnect() None[source]#

Reconnect to the data logging stick. Called automatically if the auto-reconnect option is enabled

Returns:

None

Raises:

NoSocketAvailableError – When connection cannot be re-established

async disconnect() None[source]#

Disconnect the socket and set a signal for the reader thread to exit

Returns:

None

async read_input_registers(register_addr, quantity)[source]#

Read input registers from modbus slave (Modbus function code 4)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

List containing register values

Return type:

list[int]

async read_holding_registers(register_addr, quantity)[source]#

Read holding registers from modbus slave (Modbus function code 3)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

List containing register values

Return type:

list[int]

async read_input_register_formatted(register_addr, quantity, **kwargs)[source]#

Read input registers from modbus slave and format as single value (Modbus function code 4)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

  • scale (int) – Scaling factor

  • signed (bool) – Signed value (2s complement)

  • bitmask (int) – Bitmask value

  • bitshift (int) – Bitshift value

Returns:

Formatted register value

Return type:

int

async read_holding_register_formatted(register_addr, quantity, **kwargs)[source]#

Read holding registers from modbus slave and format as single value (Modbus function code 3)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

  • scale (int) – Scaling factor

  • signed (bool) – Signed value (2s complement)

  • bitmask (int) – Bitmask value

  • bitshift (int) – Bitshift value

Returns:

Formatted register value

Return type:

int

async write_holding_register(register_addr, value)[source]#

Write a single holding register to modbus slave (Modbus function code 6)

Parameters:
  • register_addr (int) – Modbus register address

  • value (int) – value to write

Returns:

value written

Return type:

int

async write_multiple_holding_registers(register_addr, values)[source]#

Write list of multiple values to series of holding registers on modbus slave (Modbus function code 16)

Parameters:
  • register_addr (int) – Modbus register start address

  • values (list[int]) – values to write

Returns:

values written

Return type:

list[int]

async read_coils(register_addr, quantity)[source]#

Read coils from modbus slave and return list of coil values (Modbus function code 1)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

register values

Return type:

list[int]

async read_discrete_inputs(register_addr, quantity)[source]#

Read discrete inputs from modbus slave and return list of input values (Modbus function code 2)

Parameters:
  • register_addr (int) – Modbus register start address

  • quantity (int) – Number of registers to query

Returns:

register values

Return type:

list[int]

async write_single_coil(register_addr, value)[source]#

Write single coil value to modbus slave (Modbus function code 5)

Parameters:
  • register_addr (int) – Modbus register start address

  • value (int) – value to write; 0xFF00 (On) or 0x0000 (Off)

Returns:

value written

Return type:

int

async write_multiple_coils(register_addr, values)[source]#

Write multiple coil values to modbus slave (Modbus function code 15)

Parameters:
  • register_addr (int) – Modbus register start address

  • values (list[int]) – values to write; 1 (On) or 0 (Off)

Returns:

values written

Return type:

list[int]

async masked_write_holding_register(register_addr, **kwargs)[source]#

Mask write a single holding register to modbus slave (Modbus function code 22)

Used to set or clear individual bits within a holding register

If default values are provided for both or_mask and and_mask, the write element of this function is a NOP.

Warning

This is not implemented as a native Modbus function. It is a software implementation using a combination of read_holding_registers() and write_holding_register()

It is therefore not atomic.

Parameters:
  • register_addr (int) – Modbus register address

  • or_mask (int) – OR mask (set bits), defaults to 0x0000 (no change)

  • and_mask (int) – AND mask (clear bits), defaults to 0xFFFF (no change)

Returns:

value written

Return type:

int

async send_raw_modbus_frame(mb_request_frame)[source]#

Send raw modbus frame and return modbus response frame

Wrapper around internal method :func:`_send_receive_modbus_frame()

Parameters:

mb_request_frame (bytearray) – Modbus frame

Returns:

Modbus frame

Return type:

bytearray

async send_raw_modbus_frame_parsed(mb_request_frame)[source]#

Send raw modbus frame and return parsed modbus response list

Wrapper around internal method :func:`_get_modbus_response()

Parameters:

mb_request_frame (bytearray) – Modbus frame

Returns:

Modbus RTU decoded values

Return type:

list[int]

Exceptions#

exception pysolarmanv5.V5FrameError[source]#

V5 Frame Validation Error

exception pysolarmanv5.NoSocketAvailableError[source]#

No Socket Available Error