-
Notifications
You must be signed in to change notification settings - Fork 98
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Feature Request: RPC Method Calls #190
Comments
@chrisbeardy sounds like a nice-to-have feature. Maybe you can contact @pbruenn from Beckhoff directly on this matter or open an issue on https://github.com/Beckhoff/ADS. |
Link to issue in Beckhoff repo: Beckhoff/ADS#131 This looks promising. |
I suggest to keep it similar with the .NET implementation, they have this signiture: // Call a Method that has the following signature (within MAIN Program)
/* {attribute 'TcRpcEnable'}
METHOD PUBLIC M_Add : INT
VAR_INPUT
i1 : INT := 0;
i2 : INT := 0;
END_VAR
*/
short result = (short)main.InvokeRpcMethod("M_Add", new object[] {(short) 3, (short) 4});}); we could create a method in the def invoke_rpc_method(method_path: str, method_name: str parameters: Optional[List[Any]] = None) -> Any:
"""Invokes an RPC method from the PLC, PLC methods must have the {attribute 'TcRpcEnable'}.
Args:
method_path: full variable path to method, e.g MAIN.fbTest
method_name: method name, e.g. M_Add
parameters: list of the methods paramers, None, if method has no parameters
Returns:
value: return value of the method
"""
variable = f"{method_path}#{method_name}"
# need to do some stuff to figure out size of params
# do readwrite etc
# pass back Some thoughts:
I think i just prefer telling the use they have to use method_name = method_path .split(".")[-1]
method_path = method_path .replace(f".{method_name}", f"#{method_name}")
|
This looks very promising indeed.
I prefer passing method_path as one parameter for the reasons you already named. If the #-way is the official way to go we should stick to it and not support the "."-way.
For simple data types we could map a list and/or dict to a ctypes structure. The question is whether it's possible to read parameter types from the target or not. If not the use would always need to provide a structure definition. Otherwise he could omit the parameter definition for simple parameter types.
I could imagine passing a structure_def for the return type if necessary. So the method could look something like this: def invoke_rpc_method(
method_path: str,
param_vals: Optional[Union[List[Any], Dict[str, Any]]] = None,
param_def: Optional[StructureDef] = None,
return_type: Optional[Union[int, StructureDef]] = None) -> Any: |
This appears to be the c# sample that @dayaftereh was reffering too. And it seems that they kindly translated it to C for us. It looks to me that the user in both examples needs to know the parameter types up front. Or at least to query them you need to know what the variables are called, in which case you may as well define a structure anyway. namespace _30_ADS.NET_MethodCall
{
public partial class Form1 : Form
{
TcAdsClient tcClient;
AdsStream readStream, writeStream;
AdsBinaryReader binReader;
AdsBinaryWriter binWriter;
int hMethod = 0;
public Form1()
{
//Create a new instance of class TcAdsClient
tcClient = new TcAdsClient();
//Allocate memory [2 bytes] for read parameter (sum in this case)
readStream = new AdsStream(sizeof(int));
binReader = new AdsBinaryReader(readStream);
//Allocate memory [4 bytes] for write parameter (summands A and B in this case)
writeStream = new AdsStream(2 * sizeof(int));
binWriter = new AdsBinaryWriter(writeStream);
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
try
{
//Connect to local PLC - Port 851
tcClient.Connect(851);
//Get the handle of the PLC method "Addition" of POU MAIN.fbMath
hMethod = tcClient.CreateVariableHandle("MAIN.fbMath#Addition");
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
private void btnMethodCall_Click(object sender, EventArgs e)
{
try
{
//Write value A to stream
binWriter.Write(Convert.ToInt32(tbValueA.Text));
//Set stream position for next value
writeStream.Position = sizeof(int);
//Write value B to stream
binWriter.Write(Convert.ToInt32(tbValueB.Text));
//Call PLC method via handle
tcClient.ReadWrite((long)AdsReservedIndexGroups.SymbolValueByHandle, hMethod, readStream, writeStream);
//Read sum
tbSumAB.Text = Convert.ToString(binReader.ReadInt32());
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
// Reset stream position
readStream.Position = 0;
writeStream.Position = 0;
}
}
private void Form1_Closing(object sender, FormClosingEventArgs e)
{
try
{
tcClient.DeleteVariableHandle(hMethod);
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
finally
{
tcClient.Dispose();
}
}
}
} |
Hello, are there any news on this topic? :) |
This is not currently being actively worked on. It's on my TODO list at some point. In the meantime there will be a way of calling RPC methods by calling the CreateVariableHandle and ReadWrite functions yourself. This is just what the planned changes in would do anyway. You can follow the comment chain in above if you wish to implement this is your own program. If you do find the time and do this in your own application, please feel free to implement this feature into pyads, it will be appreciated! |
example of current way of calling methods in #356 |
i have implemented it in that way:
|
Hello, does anyone know if using the C DLL it is possible to do RPC method call of Methods from PLC FB's, like you can in the .NETimplementation?
I have had a look around the C files and can't see anything obvious, I'm not sure if it is possible to get the symbol of the method and just do a read/write to the corect memory areas.
Could be worth looking into if it hasn't already.
The text was updated successfully, but these errors were encountered: