../_images/bar.jfif

Framework Reference

Device Object

class PyPlcnextRsc.common.device.ExtraConfigure[source]

Additional configure for RscClient

  • timeout - default is 10s

  • useTls - default is True

  • keepAlive_ms - default is 30000ms

class PyPlcnextRsc.common.device.Device(ip: str, user: Optional[str] = None, passwd: Optional[str] = None, port: int = 41100, config: Optional[PyPlcnextRsc.common.device.ExtraConfigure] = None, secureInfoSupplier: Optional[Callable[[Optional[dict]], Tuple[str, str]]] = None)[source]

PLCnext Device Object ,this is the main object for end-user.

In order to get any RSC service , this object must be created and connect (log-in) successfully.

Warning

Always use secureInfoSupplier to supply security information instead of use ‘user’ and ‘passwd’ argument

Usage:

Typical way : using with-block for auto connect and dispose , and use secureInfoSupplier to provide secure login-information.

from PyPlcnextRsc import Device, GUISupplierExample

if __name__ == "__main__":
    with Device('192.168.1.10', secureInfoSupplier=GUISupplierExample) as device:
        ...
Parameters
  • ip (str) – the IP address of the target PLCnext for connecting

  • user (str) – user name for login if user authentication is enabled. (deprecated ,use secureInfoSupplier instead)

  • port (int) – socket port of target , default is set to 41100

  • passwd (str) – passwd for login if user authentication is enabled. (deprecated ,use secureInfoSupplier instead)

  • config (ExtraConfigure) – additional setting for this client , such as switch of TLS and socket time-out

  • secureInfoSupplier (Callable[[Optional[dict]],Tuple[str,str]]) –

    a callback function for getting secure info. the function’s signature can have no or only one argument, if one argument is in signature,then during login period the details about target (such as serial number ,firmware-version) will be passed by the argument

    Note

    The function will not be called if user-authentication is disabled on target PLCnext

Raises

#TODO

PyPlcnextRsc.common.device.GUISupplierExample(detail)[source]

A simple GUI for authentication login based on tkinter

Note

This GUI will not be called if user-authentication is disabled.

PyPlcnextRsc.common.device.ConsoleSupplierExample(detail)[source]

A simple console interface for authentication login based on getpass module

Note

This will not be called if user-authentication is disabled.

If is running by PyCharm , the getpass module’s behavior is changed, the password will be echoed. This will not happen if you run this directly through python

Type Tags

class PyPlcnextRsc.common.tag_type.RscType(value)[source]

Datatypes supported by Rsc.

Null = 0

No data type set

End = 255

End of stream (EOS)

Void = 1

void or null object

Bool = 2

bool type

Char = 3

16 bit character

Int8 = 4

signed 8 bit integer (I1)

Uint8 = 5

unsigned 8 bit integer (U1)

Int16 = 6

signed 16 bit integer (I2)

Uint16 = 7

unsigned 16 bit integer (U2)

Int32 = 8

signed 32 bit integer (I4)

Uint32 = 9

unsigned 32 bit integer (U4)

Int64 = 10

signed 64 bit integer (I8)

Uint64 = 11

unsigned 64 bit integer (U8)

Real32 = 12

32 bit floating point number (R4)

Real64 = 13

64 bit floating point number (R8)

Struct = 18

Complex datatype

Utf8String = 19

Utf-8 string

String = 14

String with undefined format. Deprecated with remoting version 4 used by common.In common context with at least remoting version 4 RscType String is mapped to Utf8String

Array = 20

Array type

Datetime = 23

Datetime

Version = 24

Version

Guid = 25

Universal unique ID

AnsiString = 26

Ansi string, not implemented in common context

Object = 28

Object type handled by common as RscVariant

Utf16String = 30

Utf-16 string, not implemented in common context

Stream = 34

Stream type to marshal large data packets

Enumerator = 35

Enumerator type

SecureString = 36

String for security context

Enum = 37

Enum type

Dictionary = 38

Dictionary type

SecurityToken = 39

Security token needed for security Services

Exception = 40

Exception

IecTime = 41

IEC type: TIME [int32]

IecTime64 = 42

IEC type: LTIME [int64]

IecDate = 43

IEC type: DATE [N/A]

IecDate64 = 44

IEC type: LDATE [int64]

IecDateTime = 45

IEC type: DATE_AND_TIME, DT [N/A]

IecDateTime64 = 46

IEC type: LDATE_AND_TIME, LDT [int64]

IecTimeOfDay = 47

IEC type: TIME_OF_DAY, TOD [N/A]

IecTimeOfDay64 = 48

IEC type: LTIME_OF_DAY, LTOD [int64]

class PyPlcnextRsc.common.tag_type.IecType[source]

Concrete annotation for IEC61131 data space

this is just a helper map from IEC61131 data type to RscType

Null = 0

Mapped to PyPlcnextRsc.common.tag_type.RscType.Null

TIME = 41

Mapped to PyPlcnextRsc.common.tag_type.RscType.IecTime

LTIME = 42

Mapped to PyPlcnextRsc.common.tag_type.RscType.IecTime64

LDATE = 44

Mapped to PyPlcnextRsc.common.tag_type.RscType.IecDate64

LDATE_AND_TIME = 46

Mapped to PyPlcnextRsc.common.tag_type.RscType.IecDateTime64

LTIME_OF_DAY = 48

Mapped to PyPlcnextRsc.common.tag_type.RscType.IecTimeOfDay64

BOOL = 2

Mapped to PyPlcnextRsc.common.tag_type.RscType.Bool

STRING = 19

Mapped to PyPlcnextRsc.common.tag_type.RscType.Utf8String

LREAL = 13

Mapped to PyPlcnextRsc.common.tag_type.RscType.Real64

REAL = 12

Mapped to PyPlcnextRsc.common.tag_type.RscType.Real32

LWORD = 11

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint64

DWORD = 9

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint32

WORD = 7

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint16

BYTE = 5

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint8

LINT = 10

Mapped to PyPlcnextRsc.common.tag_type.RscType.Int64

DINT = 8

Mapped to PyPlcnextRsc.common.tag_type.RscType.Int32

INT = 6

Mapped to PyPlcnextRsc.common.tag_type.RscType.Int16

SINT = 4

Mapped to PyPlcnextRsc.common.tag_type.RscType.Int8

ULINT = 11

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint64

UDINT = 9

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint32

UINT = 7

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint16

USINT = 5

Mapped to PyPlcnextRsc.common.tag_type.RscType.Uint8

Tools

DataTypeStore

PyPlcnextRsc.tools.PlcDataTypeSchema.NewSchemaInstance(schema)[source]

Construct a new data type instance defined by schema this instance is used for Write complex data to PLCnext

Note

In the created instance , all values have been set to its’ default value, means that if user don’t change the element (field) in it, it can also send to PLCnext successfully , but all elements (or fields) are 0 , 0.0 , False or “”(empty str)

Parameters

schema – type schema, get from PyPlcnextRsc.tools.PlcDataTypeSchema.DataTypeStore.__getitem__()

Returns

a new data type instance for user to fill elements or fields

PyPlcnextRsc.tools.PlcDataTypeSchema.ReceiveAsSchemaInstance(schema, variant: PyPlcnextRsc.common.objects.rsc_variant.RscVariant, builderMode: bool = False)[source]

Receive the certain value from RscVariant as data_type defined in schema

Parameters
  • schema – type schema

  • variant (RscVariant) – from IDataAccessService or ISubscriptionService or some other service , which represent the meta-value of the data_type defined in schema

  • builderMode (bool) – if set true, all the struct received will be the RscStructBuilder, so it is possible for user to change the fields’ value and send back to device directly.

Returns

final value , which has the same element type or fields defined in schema

class PyPlcnextRsc.tools.PlcDataTypeSchema.DataTypeStore(SIO)[source]

This is a helper function for python user to create the equivalent variable model to IEC61131, it is the most convenient way to construct a complex value such as Array and Struct for sending or receiving.

Basic usage:

from PyPlcnextRsc import Device, RscVariant, GUISupplierExample
from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService, WriteItem
from PyPlcnextRsc.tools import DataTypeStore

if __name__ == "__main__":
    TypeStore = DataTypeStore.fromString(
        '''
        TYPE
        DemoStruct : STRUCT
            Field1 : INT;
            Field2 : BOOL;
        END_STRUCT
        DemoArray : ARRAY[0..10] OF INT;
        END_TYPE
        ''')
    with Device('192.168.1.10', secureInfoSupplier=GUISupplierExample) as device:
        # create DemoStruct
        demo1 = TypeStore.NewSchemaInstance("DemoStruct")
        demo1.Field1 = 123
        demo1.Field2 = True
        # create DemoArray
        demo2 = TypeStore.NewSchemaInstance("DemoArray")
        demo2[:] = [i * 2 for i in range(11)]
        # get raw data access service
        data_access_service = IDataAccessService(device)
        # Write demo1 to PLCnext
        data_access_service.Write((WriteItem("Arp.Plc.Eclr/demo1", RscVariant.of(demo1)),))
        # Read demo1
        read_item = data_access_service.Read(("Arp.Plc.Eclr/demo1",))[0]
        rcv_demo1 = TypeStore.ReceiveAsSchemaInstance("DemoStruct", read_item.Value)
        print(rcv_demo1)
        # ---------------
        data_access_service.Write((WriteItem("Arp.Plc.Eclr/demo2", RscVariant.of(demo2)),))
        read_item = data_access_service.Read(("Arp.Plc.Eclr/demo2",))[0]
        rcv_demo2 = TypeStore.ReceiveAsSchemaInstance("DemoArray", read_item.Value)
        print(rcv_demo2)
classmethod fromFile(file_or_filename: Union[str, TextIO])[source]

Create the DataTypeStore using local file.

Parameters

file_or_filename (TextIO or str) – file object or the path of the local file.

classmethod fromString(string: str)[source]

Using DataType string to create the DataTypeStore

Parameters

string (str) – the DataType code.

__getitem__(item) any[source]

Get type schema

Parameters

item (str) – type named defined in DataTypeStore

Returns

type schema

NewSchemaInstance(data_type_name: str)[source]

Construct a new data type instance defined by schema this instance is used for Write complex data to PLCnext

Note

In the created instance , all values have been set to its’ default value, means that if user don’t change the element (field) in it, it can also send to PLCnext successfully ,but all elements (or fields) are 0,*0.0*,*False* or “”(empty str)

Parameters

data_type_name (str) – type named defined in DataTypeStore

Returns

a new data type instance for user to fill elements or fields

ReceiveAsSchemaInstance(data_type_name: str, variant: PyPlcnextRsc.common.objects.rsc_variant.RscVariant, builderMode: bool = False)[source]

Receive the certain value from PLCnext as data_type defined in schema

Parameters
  • data_type_name (str) – type named defined in DataTypeStore

  • variant (RscVariant) – from IDataAccessService or ISubscriptionService or some other service , which represent the meta-value of the data_type defined in schema

  • builderMode (bool) – if set true, all the struct received will be the RscStructBuilder, so it is possible for user to change the fields’ value and send back to device directly.

Returns

final value , which has the same element type or fields defined in schema

Data Objects

General Object

RscVariant

class PyPlcnextRsc.common.objects.rsc_variant.RscVariant(value, rscType: PyPlcnextRsc.common.tag_type.RscType)[source]

This is used to represent an data-object (py-value with its’ RscType)

Create a RscVariant object by providing both the definite RscType and python value

Parameters
  • value – Python value which to be wrapped in.

  • rscType (RscType) –

    the definite type of the value.

    Note

    If you are just make RscVariant object mapped to IEC61131, use IecType is more concrete

classmethod of(value)[source]

Create RscVariant from some special python object that RscType is clearly to tell from

Warning

This is not suitable for some value that is ambiguous , for example you give number 100 use this method, but for this method it is not possible to know which INT (or in other word, which RscType)you are talking about: it shell be PyPlcnextRsc.common.tag_type.RscType.Uint8 ? PyPlcnextRsc.common.tag_type.RscType.Int16 ? or PyPlcnextRsc.common.tag_type.RscType.Int64 …?

So in this case, you must use __init__() to give the RscType explicitly.

Returns

RscVariant instance

GetValue() any[source]

Get the python value in this RscVariant object.

Returns

any python value that represent the corresponding value from PLC

Note

Special case of RscType

GetType() PyPlcnextRsc.common.tag_type.RscType[source]

Get the RscType corresponding to the contained value.

Return type

RscType

GetArrayElementCtx()[source]

This method is mainly for internal use, to get the element context while this object contains Array

GetFieldCount()[source]

This method is mainly for internal use, to get the field counts while this object contain Struct

RscStream

class PyPlcnextRsc.common.objects.rsc_stream.RscStream(bytesBuffer)[source]

This is used to represent a stream object

Normally used to transfer files with device

classmethod ofFile(filePath: str)[source]

create a RscStream from local file directly

Parameters

filePath (str) – file path of the local file

classmethod ofData(data: Union[str, bytes, bytearray])[source]

create a RscStream from data directly

Parameters

data (str,bytes,bytearray) – data to be wrapped in stream object

getBufferIO() _io.BytesIO[source]

get the inner IO reference

Returns

bytesIO in this stream

Return type

BytesIO

getValue() bytes[source]

get all bytes in this stream

Returns

data

Return type

bytes

saveToFile(filePath: str)[source]

save the current stream to file

Note

this method only call open(filePath, “wb”) internal , so you must create directory before execute this method if necessary.

Parameters

filePath (str) – path of the target file to Write

getSize()[source]

get the current byte size in this stream object

Returns

size of bytes

Return type

int

Struct

class PyPlcnextRsc.common.objects.rsc_struct.RscStructBuilder(prototype, defaults=None)[source]

This is a wrapper around RscStruct , supporting filling fields step by step

Normally this is auto created by PyPlcnextRsc.tools.PlcDataTypeSchema

Note

This class has overload the __eq__ method , so this builder instance is compareable to RscStruct

Tip

Since V0.1.4 :

‘_friendlyMode’:

A syntactic sugar for Array (as a field in Struct) operation has been added ‘Struct.ArrField = [100, 200, 300]’ in now allowed (the old way is ‘Struct.ArrField[:] = [100, 200, 300]’).

Usage:

class ST_Prototype(RscStruct):
    F0: IecAnnotation.INT
    F1: IecAnnotation.INT
    F2: IecAnnotation.BOOL


# Not possible to init fields' value separately:
# st = ST_Prototype()
# st.F0 = 0
# st.F1 = 100 # Illegal ! , because 'RscStruct' is tuple in fact
# st.F2 = False

# You can only instance it by the following way:
# st = ST_Prototype(0,100,False)

# use RscStructBuilder:
builder = RscStructBuilder(ST_Prototype)
builder(F0 = 0,F1 = 100,F2 = False) # by __call__
builder.F1 = 200    # by set attribute
builder.F2 = True

# not necessary for user to call _getRscStruct because it will auto invoke while sending to PLC
st = builder._getRscStruct()
Parameters
  • prototype (RscStruct) – RscStruct prototype

  • defaults (dict) – dict with field name and it’s default value if supplied, default it None.

class PyPlcnextRsc.common.objects.rsc_struct.RscStructMeta(iterable=(), /)[source]

Meta-data to represent Struct for transferring with device, it carriers all necessary information of each fields such as RscType

Should always used as a value in RscVariant , and every element are always RscVariant too

classmethod fromInstance(struct_instance)[source]

Create RscStructMeta from a RscStruct instance or RscStructBuilder

Parameters

struct_instance (RscStruct instance or RscStructBuilder) – struct instance, which can be an instance of RscStruct directly or RscStructBuilder

GetAsRscStruct(struct_type, strictMode=True) NamedTuple[source]

Generate certain RscStruct instances from provided RscStruct type.

Parameters
  • struct_type (RscStruct type) – the type of RscStruct.

  • strictMode (bool) – check the shape and type in meta before generate, default is True.

Returns

the instance of RscStruct with all fields filled.

Return type

RscStruct

PyPlcnextRsc.common.objects.rsc_struct.RscStruct

alias of NamedTuple

PyPlcnextRsc.common.objects.rsc_struct.isRscStructInstance(value)[source]

Test whether the given value is the instance of RscStruct

PyPlcnextRsc.common.objects.rsc_struct.isRscStructType(value)[source]

Test whether the given value is the prototype (or called ‘type’) of RscStruct

Array

class PyPlcnextRsc.common.objects.rsc_sequence.RscSequence[source]

Bases: object

COMMON ABSTRACT CLASS FOR RscList & RscTuple

ALSO USED IN USER STRUCT DEF

setElementRscType(rscType: PyPlcnextRsc.common.tag_type.RscType)[source]

Configure the sequence by passing in primitive type (RscType)

Warning

This method only support primitive types,

If next-dimension is Array, use setNextDimension() instead.

else if element is Struct, use setElementAnnotate() instead.

Parameters

rscType (RscType) – the element type

Returns

self

setElementAnnotate(annotate)[source]

Configure by annotate

Used if element type is Primitive type or RscStruct

Parameters

annotate

field type annotation ,

such as ‘RscTpAnnotate[int, Marshal(rscType=RscType.Int16)]’ or defined RscStruct

Returns

self

setNextDimension(nextDimension)[source]

Configure by next RscSequence or RscList

Warning

Only used for define a multi-dimension array.

Parameters

nextDimension (RscSequence or factory of RscList) – next configured RscSequence or RscList

Returns

self

getElementRscType() PyPlcnextRsc.common.tag_type.RscType[source]

Get the RscType of the element.

Returns

the RscType of the element.

Return type

RscType

setElementContext(context)[source]

Set the DataTagContext of the element, this is used internally.

Parameters

context – DataTagContext of the element

getElementContext()[source]

Get the DataTagContext of the element,, this is used internally.

Returns

DataTagContext

setDesireLength(length)[source]

if the desire length is set, the framework will check the length before sending to device. this will auto set by PyPlcnextRsc.tools.PlcDataTypeSchema internally.

Parameters

length (int) – the desired length of this sequence.

getDesireLength()[source]

Get the desired length internal. if not set return -1

Returns

the desired length , -1 if not set

Return type

int

class PyPlcnextRsc.common.objects.rsc_sequence.RscList(iterable=(), /)[source]

Bases: list, PyPlcnextRsc.common.objects.rsc_sequence.RscSequence

Use List to represent an array for transferring with device.

Tip

Since V0.1.4 :

‘_friendlyMode’ :

if an element is struct type in this array , use this method is quick !

MyArrayOfStruct[1] = {"Field1": 200, "Field2": False}  # or (200,False) or [200,False]
MyArrayOfStruct[2] = (300, True)

and this can override all above values (this example showed ‘[:]’ you can use other slice which you want such as ‘[0:8]’ ‘[1:-1]’… )

MyArrayOfStruct[:] = [{"Field1": 200, "Field2": False}, (200, True), (300, True)]
classmethod factory(funcName, *args)[source]

Make a RscList factory, this is only a helper function to create RscList of same structure.

Usage:

middle_layer_factory = RscList.factory('createNextDimension', RscType.Int16, 3)
middle1 = middle_layer_factory.create()
middle1[0].extend((1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 11))
middle1[1].extend((1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 11))
middle1[2].extend((1, 3, 2, 1, 1, 1, 1, 1, 1, 1, 11))

middle2 = middle_layer_factory.create()
middle2[0].extend((2, 1, 0, 1, 1, 1, 1, 1, 1, 1, 11))
middle2[1].extend((2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 11))
middle2[2].extend((2, 3, 2, 1, 1, 1, 1, 1, 1, 1, 11))

outer = RscList((middle1, middle2)).setNextDimension(middle_layer_factory)
Parameters
  • funcName (str) – the exist function name for configure the RscList.

  • args – the function arguments corresponding to the ‘funcName’.

Returns

return a factory instance , which has a create() method to call for construct a new RscList by the provided parameters.

setOffset(offset: int)[source]

Set the start offset of this array object , because in IEC61131, an array can be defined with lower bound not equal to 0

Warning

Although lower bound not equal to 0 is acceptable by this method, but still not recommend to use that kind of array definition! because it can be confused. and slice function of python can not work normally if use negative index.

Parameters

offset (int) – lower bound of the array

createNextDimension(elementRscType: PyPlcnextRsc.common.tag_type.RscType, count: int, reserve: int = 0, default: Optional[any] = None)[source]

Helper function to create next dimension ,only support for primitive python type as next dimension’s element type!

Parameters
  • elementRscType (RscType) – RscType of the element

  • count (int) – the count of element in current dimension to reserve

  • reserve – the count of element in next dimension to reserve

  • default – the value to fill in next dimension

Returns

self

reserve(reserve: int = 0, default: Optional[any] = None, use_deepcopy: bool = False)[source]

Use the provided value(default) to fill the array

Parameters
  • reserve (int) – element count to reserve

  • default – the value to fill

  • use_deepcopy (bool) – true if use deepcopy to fill the element,default is False

setElementRscType(rscType: PyPlcnextRsc.common.tag_type.RscType, reserve: int = 0, default: Optional[any] = None)[source]

Overload the setElementRscType(), add the reserve() method.

Parameters
  • rscType (RscType) – the element type

  • reserve (int) – element count to reserve

  • default – the value to fill

setElementAnnotate(annotate, reserve: int = 0, default: Optional[any] = None)[source]

Overload the setElementAnnotate(), add the reserve() method.

Parameters
  • annotate

    field type annotation ,

    such as ‘RscTpAnnotate[int, Marshal(rscType=RscType.Int16)]’ or defined RscStruct

  • reserve (int) – element count to reserve

  • default – the value to fill

setNextDimension(nextDimension, count: Optional[int] = None)[source]

Overload the setNextDimension(), add support for reserve.

Parameters
Returns

self

__eq__(other)[source]

Overload the list.__eq__, now must the other element’s RscType same with self’s element type is possible to return True

Parameters

other – other instance to compare

Returns

true if ‘other’ is same with self

class PyPlcnextRsc.common.objects.rsc_sequence.RscTuple(iterable=(), /)[source]

Bases: tuple, PyPlcnextRsc.common.objects.rsc_sequence.RscSequence

Use Tuple to represent an array for transferring with device

setOffset(offset)[source]

see doc from PyPlcnextRsc.common.objects.rsc_sequence.RscList.setOffset()

__eq__(other)[source]

Overload the tuple.__eq__, now must the other element’s RscType same with self’s element type is possible to return True

Parameters

other – other instance to compare

Returns

true if ‘other’ is same with self