xcom485i.client module

Warning

Changing parameters when the inverters are in operation should be done carefully. The modification of parameters can restart the corresponding algorithm inside the inverter. For example, the change of a delay can restart the timer attached to it.

When you are using the RCC remote control, the Xtender inverter/charger, VarioTrack and VarioString MPPT solar chargers store their parameter values in a non-volatile flash memory. Because of the endurance of this memory, the number of writes on a single parameter is only guaranteed for 1000 write operations. To allow the cyclic write of parameters without count limit, we suggest you to write the parameters in RAM only

Xcom485i.__init__(serial_port, offset=0, debug=False)[source]

serial device must be configured with :

  • EVEN parity
  • 1 start bit
  • 8 data bits, LSB first
  • 1 parity bit (Even)
  • 1 stop bit
  • timeout 1 second
Parameters:
  • serial_port – Instance of serial module
  • offset – The address offset as defined with the dip-switches
  • debug (boolean) – Activate debug traces for tx/rx frames
class xcom485i.client.Xcom485i(serial_port, offset=0, debug=False)[source]

Bases: object

This class act as a Modbus master in order to communicate with the Xcom-485i gateway (slave)

serial_port

Serial port used for communication with the gateway

Type:serial.Serial
addresses

Instance of Addresses class grouping all the ones accessible from the Xcom-485i

Type:xcom485i.addresses.Addresses
message_registers()[source]

Read pending messages stored into the gateway.

Note

Once a message is read, it is deleted inside the Xcom-485i, so use Xcom485i.pending_message_count in order to know how many messages are pending and iteratively call this function to retrieve all messages.

The response is like :

  • Input Register 0 (@ 0x0001)| 2 bytes | Device source
  • Input Register 1 (@ 0x0002)| 2 bytes | Message ID
  • Input Register 2 (@ 0x0003)| 2 bytes | Optional value Most significant word
  • Input Register 3 (@ 0x0004)| 2 bytes | Optional value Least significant word
Returns:Content of Input Register 0, 1, 2, 3
Return type:bytes

Example

# Read all pending messages stored into the gateway
# Run this example within the 'examples/' folder using 'python ex_read_messages.py' from a CLI
#   after installing xcom485i package with 'pip install xcom485i'

import serial
from xcom485i.client import Xcom485i

SERIAL_PORT_NAME = 'COM4'  # your serial port interface name
SERIAL_PORT_BAUDRATE = 9600  # baudrate used by your serial interface
DIP_SWITCHES_ADDRESS_OFFSET = 0  # your modbus address offset as set inside the Xcom485i device

if __name__ == "__main__":
    try:
        serial_port = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_BAUDRATE,
                                    parity=serial.PARITY_EVEN, timeout=1)
    except serial.serialutil.SerialException as e:
        print("Check your serial configuration : ", e)
    else:
        xcom485i = Xcom485i(serial_port, DIP_SWITCHES_ADDRESS_OFFSET, debug=True)
        # always check the number of pending messages
        pending_message_count = xcom485i.pending_message_count()
        print('pending_message_count:', pending_message_count)

        for _ in range(pending_message_count):
            message_registers = xcom485i.message_registers()
            print('Message N°:', _)
            print("  device source: ", message_registers[0])
            print("  message id: ", message_registers[1])
            print("  optionnal most significant word: ", message_registers[2])
            print("  optionnal least significant word: ", message_registers[3])
pending_message_count()[source]

Get the number of currently pending messages stored into the gateway, by reading the content of the 0x0000 input register.

Note

Within the Xtender system, any device (Xtender, VarioTrack, VarioString, BSP, Xcom-CAN BMS) can send messages. These messages are displayed on the RCC and also available on the Studer Portal whenever the installation is connected to the Internet.

Returns:The number of pending messages (up to 128)
Return type:int
read_info(slave_id, address)[source]

Read a user info from a targeted device as a float.

Note

The available user information is the same as the values that can be chosen to be displayed on the RCC. This user information gives the current state of the system. The user information can not be modified and their values change during the operation of the system.

Parameters:
  • slave_id – Slave identifier number (targeted device)
  • address – Register starting address, see Studer Modbus RTU Appendix for the complete list of accessible register per device
Returns:

User info read

Return type:

float

Example

# Read user info 3001, Battery temperature, (Modbus register 2) from the first Xtender
# Run this example within the 'examples/' folder using 'python ex_read_info.py' from a CLI
#   after installing xcom485i package with 'pip install xcom485i'

import serial
from xcom485i.client import Xcom485i

SERIAL_PORT_NAME = 'COM4'  # your serial port interface name
SERIAL_PORT_BAUDRATE = 9600  # baudrate used by your serial interface
DIP_SWITCHES_ADDRESS_OFFSET = 0  # your modbus address offset as set inside the Xcom485i device

if __name__ == "__main__":
    try:
        serial_port = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_BAUDRATE,
                                    parity=serial.PARITY_EVEN, timeout=1)
    except serial.serialutil.SerialException as e:
        print("Check your serial configuration : ", e)
    else:
        xcom485i = Xcom485i(serial_port, DIP_SWITCHES_ADDRESS_OFFSET, debug=True)
        read_value = xcom485i.read_info(xcom485i.addresses.xt_1_device_id, 2)
        print('read_value:', read_value)
read_input_registers(slave_id, address, quantity)[source]

Get raw data from input registers.

Parameters:
  • slave_id – Slave identifier number (targeted device)
  • address – Register starting address
  • quantity – Quantity of registers to read
Returns:

Raw data from targeted registers

Return type:

bytes

read_parameter(slave_id, address)[source]

Read a parameter from a targeted device as a float.

Note

All parameters accessible from RCC can also be accessed with the Modbus protocol.

It is possible to read the actual value of the parameter from Flash, but also the minimum and the maximum value.

To distinguish between these, we use a different register address offset as explained below:

  • read value from flash : offset is 0 (READ_PARAM_FLASH_OFFSET)
  • read min allowed value : offset is 2000 (READ_PARAM_MIN_OFFSET)
  • read max allowed value : offset is 4000 (READ_PARAM_MAX_OFFSET)
Parameters:
  • slave_id (int) – Slave identifier number (targeted device)
  • address (int) – Register starting address, see Studer Modbus RTU Appendix for the complete list of accessible register per device
Returns:

parameter read

Return type:

float

Example

# Read parameter 1107, Maximum current of AC source, (Modbus register 14) from the first Xtender
# Run this example within the 'examples/' folder using 'python ex_read_param.py' from a CLI
#   after installing xcom485i package with 'pip install xcom485i'

import serial
from xcom485i.client import Xcom485i

SERIAL_PORT_NAME = 'COM4'  # your serial port interface name
SERIAL_PORT_BAUDRATE = 9600  # baudrate used by your serial interface
DIP_SWITCHES_ADDRESS_OFFSET = 0  # your modbus address offset as set inside the Xcom485i device

if __name__ == "__main__":
    try:
        serial_port = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_BAUDRATE,
                                    parity=serial.PARITY_EVEN, timeout=1)
    except serial.serialutil.SerialException as e:
        print("Check your serial configuration : ", e)
    else:
        xcom485i = Xcom485i(serial_port, DIP_SWITCHES_ADDRESS_OFFSET, debug=True)

        # read actual value stored into flash memory
        read_value = xcom485i.read_parameter(xcom485i.addresses.xt_1_device_id,
                                             14 + xcom485i.addresses.read_param_flash_offset)
        print('read_value:', read_value)

        # read minimum value of this parameter
        read_value = xcom485i.read_parameter(xcom485i.addresses.xt_1_device_id,
                                             14 + xcom485i.addresses.read_param_min_offset)
        assert read_value == 2.0  # only for 1107 parameter
        print('read_min_value:', read_value)

        # read maximum value of this parameter
        read_value = xcom485i.read_parameter(xcom485i.addresses.xt_1_device_id,
                                             14 + xcom485i.addresses.read_param_max_offset)
        assert read_value == 50.0  # only for 1107 parameter
        print('read_max_value:', read_value)
read_time(slave_id)[source]

Read the system time from a targeted installation.

Note

The system time is available at the address 0 of the device system.

The time registers are accessible separetely if needed by using the correct address and length.

Here is the list of time registers:

  • 0 -> Microsecond
  • 1 -> Second
  • 2 -> Minute
  • 3 -> Hour
  • 4 -> Weekday
  • 5 -> Day
  • 6 -> Month
  • 7 -> Year (format 2022 = 22)
Parameters:slave_id (int) – Slave identifier number (targeted device)
Returns:actual system time
Return type:datetime

Example

# Read the system time
# Run this example within the 'examples/' folder using 'python ex_read_time.py' from a CLI after installing
#   xcom485i package with 'pip install xcom485i'

import serial
from xcom485i.client import Xcom485i

SERIAL_PORT_NAME = 'COM4'  # your serial port interface name
SERIAL_PORT_BAUDRATE = 9600  # baudrate used by your serial interface
DIP_SWITCHES_ADDRESS_OFFSET = 0  # your modbus address offset as set inside the Xcom485i device

if __name__ == "__main__":
    try:
        serial_port = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_BAUDRATE, parity=serial.PARITY_EVEN, timeout=1)
    except serial.serialutil.SerialException as e:
        print("Check your serial configuration : ", e)
    else:
        xcom485i = Xcom485i(serial_port, DIP_SWITCHES_ADDRESS_OFFSET, debug=True)

        # read actual value stored into flash memory
        read_value = xcom485i.read_time(xcom485i.addresses.system_device_id)
        print('Read time:', read_value)
write_parameter(slave_id, address, value)[source]
Write a parameter value into a targeted device.

Note

All parameters accessible from RCC can also be accessed with the Modbus protocol.

In the Xtender system, it is possible to write a value in Flash (and RAM) or in RAM only.

To distinguish between both, we use a different register address offset as explained below:

  • write value into FLASH and RAM : offset is 0 (WRITE_PARAM_FLASH_RAM)
  • write value into RAM only : offset is 6000 (WRITE_PARAM_RAM_ONLY)
Parameters:
  • slave_id – Slave identifier number (targeted device)
  • address – Register starting address, see Studer Modbus RTU Appendix for the complete list of accessible register per device
  • value – The value to write
Returns:

Quantity of written registers (must be 2)

Return type:

int

Example

# Write parameter 1107 in RAM only, Maximum current of AC source, (Modbus register 14)
#   from the first Xtender
# Run this example within the 'examples/' folder using 'python ex_write_param.py' from a CLI
#   after installing xcom485i package with 'pip install xcom485i'

import serial
from xcom485i.client import Xcom485i

SERIAL_PORT_NAME = 'COM4'  # your serial port interface name
SERIAL_PORT_BAUDRATE = 9600  # baudrate used by your serial interface
DIP_SWITCHES_ADDRESS_OFFSET = 0  # your modbus address offset as set inside the Xcom485i device

if __name__ == "__main__":
    try:
        serial_port = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_BAUDRATE,
                                    parity=serial.PARITY_EVEN, timeout=1)
    except serial.serialutil.SerialException as e:
        print("Check your serial configuration : ", e)
    else:
        xcom485i = Xcom485i(serial_port, DIP_SWITCHES_ADDRESS_OFFSET, debug=True)

        value = 8  # 8 [A]
        echo = xcom485i.write_parameter(xcom485i.addresses.xt_1_device_id,
                                        14 + xcom485i.addresses.write_param_ram_only, value)
        # a value of 2 is expected on write action, represent the number of registers written
        assert echo == 2
        print('echo:', echo)
write_time(slave_id, value)[source]

Write the time of a targeted installation.

Note

It is only possible to set the time and date by writting all registers at the same time.

Here is the list of time registers:

  • 0 -> Microsecond
  • 1 -> Second
  • 2 -> Minute
  • 3 -> Hour
  • 4 -> Weekday
  • 5 -> Day
  • 6 -> Month
  • 7 -> Year (format 2022 = 22)
Parameters:
  • slave_id – Slave identifier number (targeted device)
  • value – The new datetime to write
Returns:

Quantity of written registers (must be 8)

Return type:

int

Example

# Write the system time
# Run this example within the 'examples/' folder using 'python ex_write_time.py' from a CLI after installing
#   xcom485i package with 'pip install xcom485i'

import serial
from xcom485i.client import Xcom485i
from datetime import datetime

SERIAL_PORT_NAME = 'COM4'  # your serial port interface name
SERIAL_PORT_BAUDRATE = 9600  # baudrate used by your serial interface
DIP_SWITCHES_ADDRESS_OFFSET = 0  # your modbus address offset as set inside the Xcom485i device

if __name__ == "__main__":
    try:
        serial_port = serial.Serial(SERIAL_PORT_NAME, SERIAL_PORT_BAUDRATE, parity=serial.PARITY_EVEN, timeout=1)
    except serial.serialutil.SerialException as e:
        print("Check your serial configuration : ", e)
    else:
        xcom485i = Xcom485i(serial_port, DIP_SWITCHES_ADDRESS_OFFSET, debug=True)

        # current date and time
        current_dt = datetime.now()
        print(current_dt)
        echo = xcom485i.write_time(xcom485i.addresses.system_device_id, current_dt)
        assert echo == 8  # a value of 2 is expected on write action, represent the number of registers written
        print('echo:', echo)