In this article, the PyPlcnextRsc API is used to explain the operations for reading and writing variables (single variables, arrays and structures) of the AXC F 2152 CPU, with sample code. This API is very useful and you can try it out if you like.
Reference Link
https://pyplcnextrsc.readthedocs.io/en/latest/index.html
The Access Path
To use PyPlcnextRsc to read a variable in PLCNEXT, you need to clarify the Access Path of the variable. For example, in this Example, first click on PLCnext(2).
My Cyclic Task has an OB11 Local Program.In the Component name, there is a name Arp.Plc.Eclr, which is part of the Access Path.
Implementation-1 Read Variable
In Implementation-1, I will read several variables in the PLCNEXT Runtime that are read on request: for Example, MyBoolDatat of BOOL Type, MyInt of 16Bit Integer and MyString of String Type are Targets. MyString.
Script Example
This is Script.
The access Path for MyBoolData is: Arp.Plc.EclrOB11/MyBoolData,
The access Path for MyString is: Arp.Plc.EclrOB11/OB11.MyString,
MyInt access Path is: Arp.Plc.EclrOB11/OB11.MyInt,.
The ReadSingle() Method is then used to read the current value of the variable.
from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem from PyPlcnextRsc.common.tag_type import IecType PLCNEXTIPADDRESS=’127.0.0.1′ PLCNEXTBASICPATH=’Arp.Plc.Eclr/’ with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device: device_info_service = IDeviceInfoService(device) device_status_service = IDeviceStatusService(device) info_items = [ “General.ArticleName”, “General.ArticleNumber”, “General.SerialNumber”, “General.Firmware.Version”, “General.Hardware.Version”, “Interfaces.Ethernet.1.0.Mac” ] status_items = [ “Status.Cpu.0.Load.Percent”, “Status.Memory.Usage.Percent”, “Status.ProgramMemoryIEC.Usage.Percent”, “Status.DataMemoryIEC.Usage.Percent”, “Status.Board.Temperature.Centigrade”, “Status.Board.Temperature.Centigrade”, “Status.Board.Humidity” ] for identifier, result in zip(info_items, device_info_service.GetItems(info_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) for identifier, result in zip(status_items, device_status_service.GetItems(status_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) data_access_service=IDataAccessService(device) Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData” String_port_name=PLCNEXTBASICPATH+”OB11.MyString” int_port_name=PLCNEXTBASICPATH+”OB11.MyInt” value=data_access_service.ReadSingle(Bool_port_name).Value.GetValue() print(value) print(data_access_service.ReadSingle(String_port_name).Value.GetValue()) print(data_access_service.ReadSingle(int_port_name).Value.GetValue()) data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True))) data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’))) |
Result
Done!The current value of the variable was taken.
Implementation-2 Try to write other variable
Next, try writing an Int variable using the WriteItem() Method.
data_access_service.WriteSingle(WriteItem(int_port_name,RscVariant.of(1234))) |
But the error is Returned.
Traceback (most recent call last): File “/opt/plcnext/RoboDKTesting/myapps.py”, line 58, in <module> data_access_service.WriteSingle(WriteItem(int_port_name,RscVariant.of(1234))) File “/opt/plcnext/.local/lib/python3.10/site-packages/PyPlcnextRsc/common/objects/rsc_variant.py”, line 74, in of raise InvalidOperationException(“Use __init__ to create RscVariant with its’ RscType instead !”) PyPlcnextRsc.common.exceptions.InvalidOperationException: Use __init__ to create RscVariant with its’ RscType instead ! |
Why?
You can see the Source Code of the WriteItem() Method from this LINK ↓.
All Data Tyoe other than Bool, Strucutre and String in it will also result in an Exception. It appears that you need to specify an explicit Data Type for the Target of the write. For example, just writing an integer 12 will not be accepted because the 12 is ambiguous as to 16Bit, 32Bit, Sign, Unsign, etc.
Implementation-3 Array Operation
You couldn’t write integers with the Implementation you just used. But with array INTs, there is no problem. Next, we will introduce the Method and other details.
Create Array
Create an array Data Type and declare a Local variable in Runtime.
Script Example
This time, use the DataTypeStore.fromString() function. The () parameter can be the data type of the variable you want to access as it is from PLCNEXT, or there is another function that reads from text and you can use that function.
TypeStore = DataTypeStore.fromString( “”” TYPE MyIntArray : ARRAY[0..10] OF INT; END_TYPE “”” ) |
Declare a variable Instance from TypeStore.NewSchemaInstance().
MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”) |
The last step is to read and write arrays.
read_item = data_access_service.Read((MyArray_port_name,))[0] print(read_item) print(read_item.Value) data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),)) |
This is the entire Script.
from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem from PyPlcnextRsc.common.tag_type import IecType from PyPlcnextRsc.tools import DataTypeStore PLCNEXTIPADDRESS=’127.0.0.1′ PLCNEXTBASICPATH=’Arp.Plc.Eclr/’ TypeStore = DataTypeStore.fromString( “”” TYPE MyIntArray : ARRAY[0..10] OF INT; END_TYPE “”” ) with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device: device_info_service = IDeviceInfoService(device) device_status_service = IDeviceStatusService(device) info_items = [ “General.ArticleName”, “General.ArticleNumber”, “General.SerialNumber”, “General.Firmware.Version”, “General.Hardware.Version”, “Interfaces.Ethernet.1.0.Mac” ] status_items = [ “Status.Cpu.0.Load.Percent”, “Status.Memory.Usage.Percent”, “Status.ProgramMemoryIEC.Usage.Percent”, “Status.DataMemoryIEC.Usage.Percent”, “Status.Board.Temperature.Centigrade”, “Status.Board.Temperature.Centigrade”, “Status.Board.Humidity” ] for identifier, result in zip(info_items, device_info_service.GetItems(info_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) for identifier, result in zip(status_items, device_status_service.GetItems(status_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) #Create Data access services data_access_service=IDataAccessService(device) #Create Port Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData” String_port_name=PLCNEXTBASICPATH+”OB11.MyString” int_port_name=PLCNEXTBASICPATH+”OB11.MyInt” MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″ #Print the values print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue()) print(data_access_service.ReadSingle(String_port_name).Value.GetValue()) print(data_access_service.ReadSingle(int_port_name).Value.GetValue()) data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True))) data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’))) #Array operation MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”) MyIntArrayData[:] = [i * 2 for i in range(11)] read_item = data_access_service.Read((MyArray_port_name,))[0] print(read_item) print(read_item.Value) data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),)) |
Result
When the Script was run on Terminal, data could be read and written without error.
You can also check the results from PLCNEXT.
Implementation-4 Structure
Next, let’s access a little structure: declare a structure in the PLCNEXT project. In this example, it is MyStructData_1 and contains the elements INT, BOOL, Real and LReal Type.
Create Structure
Define the STRUCT data type in PLCNEXT and declare Local variables in Runtime.
Script Example
DataTypeStore.fromString() should just paste the structure defined in PLCNEXT.
TypeStore = DataTypeStore.fromString( “”” TYPE MyIntArray : ARRAY[0..10] OF INT; MyStructData_1 : STRUCT Field1_INT : INT; Field2_BOOL : BOOL; Field3_Real : REAL; Field4_LReal :LREAL; END_STRUCT END_TYPE “”” ) |
The next step is to declare the variable Instance.
MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct” |
Get the current value of the variable from data_access_service.Read() and read_struct_item.Value.
# MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”) read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0] print(‘———————‘) print(read_struct_item.Value) |
This is the entire Script.
from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem from PyPlcnextRsc.common.tag_type import IecType from PyPlcnextRsc.tools import DataTypeStore IPADDRESS=’192.168.1.194′ PORT=20500 ROBOTNAME=’Fanuc_Robot’ PLCNEXTIPADDRESS=’127.0.0.1′ PLCNEXTBASICPATH=’Arp.Plc.Eclr/’ TypeStore = DataTypeStore.fromString( “”” TYPE MyIntArray : ARRAY[0..10] OF INT; MyStructData_1 : STRUCT Field1_INT : INT; Field2_BOOL : BOOL; Field3_Real : REAL; Field4_LReal :LREAL; END_STRUCT END_TYPE “”” ) with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device: device_info_service = IDeviceInfoService(device) device_status_service = IDeviceStatusService(device) info_items = [ “General.ArticleName”, “General.ArticleNumber”, “General.SerialNumber”, “General.Firmware.Version”, “General.Hardware.Version”, “Interfaces.Ethernet.1.0.Mac” ] status_items = [ “Status.Cpu.0.Load.Percent”, “Status.Memory.Usage.Percent”, “Status.ProgramMemoryIEC.Usage.Percent”, “Status.DataMemoryIEC.Usage.Percent”, “Status.Board.Temperature.Centigrade”, “Status.Board.Temperature.Centigrade”, “Status.Board.Humidity” ] for identifier, result in zip(info_items, device_info_service.GetItems(info_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) for identifier, result in zip(status_items, device_status_service.GetItems(status_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) #Create Data access services data_access_service=IDataAccessService(device) #Create Port Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData” String_port_name=PLCNEXTBASICPATH+”OB11.MyString” int_port_name=PLCNEXTBASICPATH+”OB11.MyInt” MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″ MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct” #Print the values print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue()) print(data_access_service.ReadSingle(String_port_name).Value.GetValue()) print(data_access_service.ReadSingle(int_port_name).Value.GetValue()) data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True))) data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’))) #Array operation MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”) MyIntArrayData[:] = [i * 2 for i in range(11)] read_item = data_access_service.Read((MyArray_port_name,))[0] print(read_item) print(read_item.Value) data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),)) # MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”) read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0] print(‘———————‘) print(read_struct_item.Value) |
Result
You can also check the results from PLCNEXT.
When the Script was run on Terminal, the data was read without error.
Implementation-5 Write the structure
The next step is to write the current value to a variable in the structure.
# MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”) MyTestStructData.Field1_INT=459 MyTestStructData.Field2_BOOL=True MyTestStructData.Field3_Real=3.14 MyTestStructData.Field4_LReal=991.41155 read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0] print(‘———————‘) print(read_struct_item.Value) |
Script Example
Write an appropriate value to the structure variable Instance, together with the variable name and data type defined as PLCNEXT.
# MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”) MyTestStructData.Field1_INT=459 MyTestStructData.Field2_BOOL=True MyTestStructData.Field3_Real=3.14 MyTestStructData.Field4_LReal=991.41155 |
Use data_access_service.Write() to send a write request.
data_access_service.Write((WriteItem(MyTestStruct_port_name, RscVariant.of(MyTestStructData)),)) |
This is the entire Script.
from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem from PyPlcnextRsc.common.tag_type import IecType from PyPlcnextRsc.tools import DataTypeStore PLCNEXTIPADDRESS=’127.0.0.1′ PLCNEXTBASICPATH=’Arp.Plc.Eclr/’ TypeStore = DataTypeStore.fromString( “”” TYPE MyIntArray : ARRAY[0..10] OF INT; MyStructData_1 : STRUCT Field1_INT : INT; Field2_BOOL : BOOL; Field3_Real : REAL; Field4_LReal :LREAL; END_STRUCT END_TYPE “”” ) with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device: device_info_service = IDeviceInfoService(device) device_status_service = IDeviceStatusService(device) info_items = [ “General.ArticleName”, “General.ArticleNumber”, “General.SerialNumber”, “General.Firmware.Version”, “General.Hardware.Version”, “Interfaces.Ethernet.1.0.Mac” ] status_items = [ “Status.Cpu.0.Load.Percent”, “Status.Memory.Usage.Percent”, “Status.ProgramMemoryIEC.Usage.Percent”, “Status.DataMemoryIEC.Usage.Percent”, “Status.Board.Temperature.Centigrade”, “Status.Board.Temperature.Centigrade”, “Status.Board.Humidity” ] for identifier, result in zip(info_items, device_info_service.GetItems(info_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) for identifier, result in zip(status_items, device_status_service.GetItems(status_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) #Create Data access services data_access_service=IDataAccessService(device) #Create Port Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData” String_port_name=PLCNEXTBASICPATH+”OB11.MyString” int_port_name=PLCNEXTBASICPATH+”OB11.MyInt” MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″ MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct” #Print the values print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue()) print(data_access_service.ReadSingle(String_port_name).Value.GetValue()) print(data_access_service.ReadSingle(int_port_name).Value.GetValue()) data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True))) data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’))) #Array operation MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”) MyIntArrayData[:] = [i * 2 for i in range(11)] read_item = data_access_service.Read((MyArray_port_name,))[0] print(read_item) print(read_item.Value) data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),)) # MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”) MyTestStructData.Field1_INT=459 MyTestStructData.Field2_BOOL=True MyTestStructData.Field3_Real=3.14 MyTestStructData.Field4_LReal=991.41155 read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0] print(‘———————‘) print(read_struct_item.Value) data_access_service.Write((WriteItem(MyTestStruct_port_name, RscVariant.of(MyTestStructData)),)) |
Result
When the Script was run on Terminal, data could be read and written without error.
Implementation-6 Encode the RsvVariant to Python object
The last step is to convert the RsvVariant into an Object that can be used in Python Script.
Script Example
Convert the RsvVariant from this Script to a Python Object.
complexStruct_Received = TypeStore.ReceiveAsSchemaInstance(“MyStructData_1”, read_struct_item.Value) print(“Field1_INT is:”+str(complexStruct_Received.Field1_INT)) print(“Field2_BOOL is “+str(complexStruct_Received.Field2_BOOL)) print(“Field3_Real is “+str(complexStruct_Received.Field3_Real)) print(“Field4_LReal is “+str(complexStruct_Received.Field4_LReal)) |
This is the entire Script.
from PyPlcnextRsc import Device, ConsoleSupplierExample , RscVariant from PyPlcnextRsc.Arp.Device.Interface.Services import IDeviceInfoService,IDeviceStatusService from PyPlcnextRsc.Arp.Plc.Gds.Services import IDataAccessService,WriteItem from PyPlcnextRsc.common.tag_type import IecType from PyPlcnextRsc.tools import DataTypeStore PLCNEXTIPADDRESS=’127.0.0.1′ PLCNEXTBASICPATH=’Arp.Plc.Eclr/’ TypeStore = DataTypeStore.fromString( “”” TYPE MyIntArray : ARRAY[0..10] OF INT; MyStructData_1 : STRUCT Field1_INT : INT; Field2_BOOL : BOOL; Field3_Real : REAL; Field4_LReal :LREAL; END_STRUCT END_TYPE “”” ) with Device(PLCNEXTIPADDRESS, secureInfoSupplier=ConsoleSupplierExample) as device: device_info_service = IDeviceInfoService(device) device_status_service = IDeviceStatusService(device) info_items = [ “General.ArticleName”, “General.ArticleNumber”, “General.SerialNumber”, “General.Firmware.Version”, “General.Hardware.Version”, “Interfaces.Ethernet.1.0.Mac” ] status_items = [ “Status.Cpu.0.Load.Percent”, “Status.Memory.Usage.Percent”, “Status.ProgramMemoryIEC.Usage.Percent”, “Status.DataMemoryIEC.Usage.Percent”, “Status.Board.Temperature.Centigrade”, “Status.Board.Temperature.Centigrade”, “Status.Board.Humidity” ] for identifier, result in zip(info_items, device_info_service.GetItems(info_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) for identifier, result in zip(status_items, device_status_service.GetItems(status_items)): print(identifier.rjust(40) + ” : ” + str(result.GetValue())) #Create Data access services data_access_service=IDataAccessService(device) #Create Port Bool_port_name=PLCNEXTBASICPATH+”OB11.MyBoolData” String_port_name=PLCNEXTBASICPATH+”OB11.MyString” int_port_name=PLCNEXTBASICPATH+”OB11.MyInt” MyArray_port_name=PLCNEXTBASICPATH+”OB11.MyIntArray1″ MyTestStruct_port_name=PLCNEXTBASICPATH+”OB11.MyTestStruct” #Print the values print(data_access_service.ReadSingle(Bool_port_name).Value.GetValue()) print(data_access_service.ReadSingle(String_port_name).Value.GetValue()) print(data_access_service.ReadSingle(int_port_name).Value.GetValue()) data_access_service.WriteSingle(WriteItem(Bool_port_name,RscVariant.of(True))) data_access_service.WriteSingle(WriteItem(String_port_name,RscVariant.of(‘abcdef’))) #Array operation MyIntArrayData = TypeStore.NewSchemaInstance(“MyIntArray”) MyIntArrayData[:] = [i * 2 for i in range(11)] read_item = data_access_service.Read((MyArray_port_name,))[0] print(read_item) print(read_item.Value) data_access_service.Write((WriteItem(MyArray_port_name, RscVariant.of(MyIntArrayData)),)) # MyTestStructData = TypeStore.NewSchemaInstance(“MyStructData_1”) MyTestStructData.Field1_INT=459 MyTestStructData.Field2_BOOL=True MyTestStructData.Field3_Real=3.14 MyTestStructData.Field4_LReal=991.41155 read_struct_item = data_access_service.Read((MyTestStruct_port_name,))[0] print(‘———————‘) print(read_struct_item.Value) data_access_service.Write((WriteItem(MyTestStruct_port_name, RscVariant.of(MyTestStructData)),)) complexStruct_Received = TypeStore.ReceiveAsSchemaInstance(“MyStructData_1”, read_struct_item.Value) print(“Field1_INT is:”+str(complexStruct_Received.Field1_INT)) print(“Field2_BOOL is “+str(complexStruct_Received.Field2_BOOL)) print(“Field3_Real is “+str(complexStruct_Received.Field3_Real)) print(“Field4_LReal is “+str(complexStruct_Received.Field4_LReal)) |
Result
The current values of CPU internal variables can be checked via the PLCNEXT Engineering software.
The value of the same reads!