stlehmann / pyads

Python wrapper for TwinCAT ADS
MIT License
252 stars 93 forks source link

How to create PLCVariable of type list #340

Closed tall-dan closed 1 year ago

tall-dan commented 1 year ago

Hello, I'm trying to write some tests which mock my plc. One of the variables I'm using is an array of strings, but I'm having trouble mocking it:

# Mock PLC:
test_server = AdsTestServer(logging=False, handler = AdvancedHandler(), port = port )
test_server.start()

test_server.handler.add_variable(PLCVariable(f'aBarcodes', bytes(), pyads.constants.ADST_STRING, 'STRING', 100)`

# client
plc = pyads.Connection('127.0.0.1.1.1', 48898)
plc.open()
plc.write_by_name('aBarcodes', ['1','2','3'], pyads.PLCTYPE_STRING)
# AttributeError: 'list' object has no attribute 'encode'

Any help would be much appreciated!

chrisbeardy commented 1 year ago

I haven't checked as on mobile but are their any examples in the tests folder of doing this in pyads's own tests?

tall-dan commented 1 year ago

Hi @chrisbeardy thanks for the quick response. I looked through the tests, specifically test_connection_class.py. There's a few examples of structs in there, but no lists

HectorBailey commented 1 year ago

If you haven't already found a solution, the way I achieved it was to create a byte array with the correct size (in this example, each element was 21 bytes, 20 for the chars in the string and a null terminator):


expected_string_array = ["hello", "world", "", ""]

# Set up the String array
string_char_size = 20
string_element_size = string_char_size + 1
string_bytes = len(expected_string_array)*(string_element_size*[0])
for i, element in enumerate(expected_string_array):
    current_offset = string_element_size * i
    string_bytes[current_offset: ((len(element)) + 1)] = element.encode("utf-8") + b"\x00"

# Add to test plc
self.handler.add_variable(PLCVariable(
    name = "str_test_array", 
    value = bytes(string_bytes), 
    ads_type = constants.ADST_STRING, 
    symbol_type = f"STRING({string_char_size})"))```
tall-dan commented 1 year ago

Thanks!