Source code for xcomcan.client

#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Warnings
--------

Changing parameters when the inverters are in operation should be done carefully.\r
The modification of parameters can restart the corresponding algorithm inside the inverter.\r
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, the “unsaved value” feature has been created. It enables to write directly
in RAM (volatile memory) without affecting the flash. You can write parameters in RAM by setting the “Part” field
to the value *0x4*.

**We strongly recommend, when you are using the Xcom-CAN Public protocol to control the
installation, to write in RAM instead of flash using the "unsaved value" part.**

"""

from stucancommon.driver import PythonCanDriver
from .node import StuCanPublicNode
from .node import ReadUserInfoRequest, ReadUserInfoResponse
from .node import WriteParameterRequest, WriteParameterResponse
from .node import ReadParameterRequest, ReadParameterResponse
from .node import MessageNotification


[docs]class StuCanPublicClient: """ Class representing a StuCan public client """
[docs] def __init__(self, source_address, can_bus_speed=125000, bustype='kvaser', debug=False): """ Parameters ---------- source_address : int Client source address can_bus_speed : int CAN bus speed as selected with dip-switches inside the XcomCAN device bustype: string Name of the CAN interface used, refer to : `python-can <https://python-can.readthedocs.io/en/master/configuration.html#interface-names>`_ debug : boolean Enable debug traces Example ------- .. code-block:: python # Usage of with statement mandatory ... with StuCanPublicClient(YourClientAddress, YourCanBusSpeed, YourInterface, True) as client: result = client.read_user_info(VT_1_DEVICE_ID, 11000) print('result:', result) ... """ self.source_address = source_address self.can_bus_speed = can_bus_speed self.bustype = bustype self.debug = debug
def __enter__(self): """ Initialize PythonCanDriver and StuCanPublicNode. Add required Response services to the node. Enter the runtime context related to this object. Use the with statement to bind this method's return value to the target specified in the as clause of the statement. """ can_driver = PythonCanDriver(self.can_bus_speed, self.bustype) self.node = StuCanPublicNode(can_driver, self.source_address, self.debug) self.node.add_service(ReadUserInfoResponse) self.node.add_service(WriteParameterResponse) self.node.add_service(ReadParameterResponse) self.node.add_service(MessageNotification) self.node.start() return self def __exit__(self, exc_type, exc_val, exc_tb): """ Stop the CAN node and wait Thread to terminate Exit the runtime context related to this object. """ self.node.stop() self.node.join()
[docs] def read_user_info(self, destination_address, info_id, timeout=1): """ Allow to read a Studer User Info from a targeted device 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 ---------- destination_address : int Targeted device address info_id : int User Info id number timeout : float Response timeout, default to 1 second Returns ------- float User Info value Example ------- .. code-block:: python # Read user info 3000, Battery voltage, from the first Xtender # Run this example within the 'examples/' folder using 'python ex_read_user_info.py' from a # CLI after installing xcomcan package with 'pip install xcomcan' from xcomcan.client import StuCanPublicClient from xcomcan.addresses import * from xcomcan.node import StuCanPublicError # your CAN bus speed as selected inside the XcomCAN device with the dip-switches CAN_BUS_SPEED = 250000 if __name__ == "__main__": # 'with' statement mandatory to call __enter__ / __exit__ context manager with StuCanPublicClient(0x00, CAN_BUS_SPEED, bustype='kvaser', debug=True) as client: # Read battery voltage value (user info n°3000) from first Xtender print('--- Read User Info ---') try: result = client.read_user_info(destination_address=XT_1_DEVICE_ID, info_id=3000) except StuCanPublicError as e: print(e) else: print('user info:', result) """ request = ReadUserInfoRequest(info_id) response = self.node.wait_response(destination_address, request, timeout) return response.value
[docs] def write_parameter(self, destination_address, parameter_id, part, value, timeout=1): """ Allow to write a Studer Parameter on a targeted device Parameters ---------- destination_address : int Targeted device address parameter_id : int Parameter id number part : int PARAMETER_PART_FLASH or PARAMETER_PART_RAM value : int The value to write timeout : float Response timeout, default to 1 second Returns ------- int Parameter identifier that has been written Example ------- .. code-block:: python # Write parameter 1286, AC out voltage, to the first Xtender # Run this example within the 'examples/' folder using 'python ex_write_param.py' from a CLI # after installing xcomcan package with 'pip install xcomcan' from xcomcan.client import StuCanPublicClient from xcomcan.addresses import * from xcomcan.node import StuCanPublicError # your CAN bus speed as selected inside the XcomCAN device with the dip-switches CAN_BUS_SPEED = 250000 if __name__ == "__main__": # 'with' statement mandatory to call __enter__ / __exit__ context manager with StuCanPublicClient(0x00, CAN_BUS_SPEED, bustype='kvaser', debug=True) as client: # Set AC Output voltage value (param n°1286) to 230 Vac on first Xtender, # value stored into RAM print('--- Write Parameter ---') value = 230.0 try: result = client.write_parameter(destination_address=XT_1_DEVICE_ID, parameter_id=1286, part=PARAMETER_PART_RAM, value=value) except StuCanPublicError as e: print(e) else: print('param write:', result) """ request = WriteParameterRequest(parameter_id, part, value) response = self.node.wait_response(destination_address, request, timeout) return response.parameter_id
[docs] def read_parameter(self, destination_address, parameter_id, part, timeout=1): """ Allow to read a Studer Parameter from a targeted device Parameters ---------- destination_address : int Targeted device address parameter_id : int Paramter id number part : int PARAMETER_PART_FLASH, PARAMETER_PART_FLASH_MIN, PARAMETER_PART_FLASH_MAX or PARAMETER_PART_RAM timeout : float Response timeout, default to 1 second Returns ------- float Parameter value Example ------- .. code-block:: python # Read param 1286, AC output voltage, from the first Xtender # Run this example within the 'examples/' folder using 'python ex_read_param.py' from a CLI # after installing xcomcan package with 'pip install xcomcan' from xcomcan.client import StuCanPublicClient from xcomcan.addresses import * from xcomcan.node import StuCanPublicError # your CAN bus speed as selected inside the XcomCAN device with the dip-switches CAN_BUS_SPEED = 250000 if __name__ == "__main__": # 'with' statement mandatory to call __enter__ / __exit__ context manager with StuCanPublicClient(0x00, CAN_BUS_SPEED, bustype='kvaser', debug=True) as client: # Read AC Output voltage value (param n°1286) from first Xtender, # from flash memory print('--- Read Parameter ---') try: result = client.read_parameter(destination_address=XT_1_DEVICE_ID, parameter_id=1286, part=PARAMETER_PART_FLASH) except StuCanPublicError as e: print(e) else: print('param flash:', result) # Read AC Output voltage Max allowed value (param n°1286) from first Xtender, # from flash memory try: result = client.read_parameter(destination_address=XT_1_DEVICE_ID, parameter_id=1286, part=PARAMETER_PART_FLASH_MAX) except StuCanPublicError as e: print(e) else: print('param max:', result) # Read AC Output voltage Min allowed value (param n°1286) from first Xtender, # from flash memory try: result = client.read_parameter(destination_address=XT_1_DEVICE_ID, parameter_id=1286, part=PARAMETER_PART_FLASH_MIN) except StuCanPublicError as e: print(e) else: print('param min:', result) # Read AC Output voltage value (param n°1286) from first Xtender, from ram memory # (not allowed, it will return value from flash) try: result = client.read_parameter(destination_address=XT_1_DEVICE_ID, parameter_id=1286, part=PARAMETER_PART_RAM) except StuCanPublicError as e: print(e) else: print('param ram:', result) # value stored in flash, ram reading not allowed """ request = ReadParameterRequest(parameter_id, part) response = self.node.wait_response(destination_address, request, timeout) return response.value
[docs] def messages(self): """ Allow to retreive the list of messages previously happened on the CAN bus Returns ------- list Notification messages Example ------ .. code-block:: python # Read messages present on the StuCan bus # Run this example within the 'examples/' folder using 'python ex_read_messages.py' from a CLI # after installing xcomcan package with 'pip install xcomcan' from xcomcan.client import StuCanPublicClient from xcomcan.node import StuCanPublicError # your CAN bus speed as selected inside the XcomCAN device with the dip-switches CAN_BUS_SPEED = 250000 if __name__ == "__main__": # 'with' statement mandatory to call __enter__ / __exit__ context manager with StuCanPublicClient(0x00, CAN_BUS_SPEED, bustype='kvaser', debug=True) as client: # Read messages notifications that have been present on the CAN bus print('--- Messages ---') try: msgs = client.messages() except StuCanPublicError as e: print(e) else: print('messages:', msgs) """ return self.node.messages()