Closed Mebus closed 2 years ago
Hmm strange. Can you check if a) localhost properly resolves (or connect to "127.0.0.1" instead) and b) the ADS server listens on that interface (and not just an external one)?
Since it's on localhost, I assume it's not a Beckhoff PLC where you need to have an ADS route in place?
This:
telnet localhost 48898
connects to something. It's a Beckhoff IPC. What kind of route do I need to add?
Mebus
I mean a normal ADS route on the PLC side.
Still would be interesting to know what happens if you use "127.0.0.1" as the address instead of "localhost".
When I use "127.0.0.1" I get:
ADS port: 48898
Verify ADS state:
Error: Ads("read state", "Port disabled - system service not started", 18)
But the PLC is running.
(Added som println!s to know where it fails.)
Mebus
Have you tried rust-rs directly on a Beckhoff PLC connecting via "127.0.0.1"?
Mebus
Ok, this is already progress. I remembered that there are some issues with resolving "localhost" on Windows...
Now you are connected and routing is fine (otherwise you wouldn't get any response).
The question is now which services are running, and which you are connecting to. Are you still using AmsAddr::new([127, 0, 0, 1, 1, 1].into(), 851) ? You might have to replace that with the actual NetId of the IPC.
And I have to admit I never ran ads-rs directly on an IPC connecting to 127.0.0.1
Even if I use the local AMS NetID that is not 127.0.0.1.1.1, I get the same error.
Can you probably try this on your machine, to see if the problem also exists there?
Mebus
Are you interested in further debugging this problem?
Mebus
Yes, sorry, I just had a few days off.
So to summarize, you always get Error: Ads("read state", "Port disabled - system service not started", 18)
when connecting to port 851?
Can you try to connect to port 10000 and see if that one responds ok?
So to summarize, you always get
Error: Ads("read state", "Port disabled - system service not started", 18)
when connecting to port 851?
Yes.
And Port 10000 is not open on 127.0.0.1
.
Mebus
I found a similar problem in a NodeJS implementation here:
https://github.com/roccomuso/node-ads/issues/8
I also changed the local AMSNetID when connecting, but this did not help either. Do you have an idea?
Mebus
And Port 10000 is not open on 127.0.0.1.
Just to be sure, I mean the ADS port, not the TCP port. The ADS port is always 48898.
What kind of IPC is that, and which version of TwinCat is it running?
Can you show me the exact code you used successfully with the Python client?
I found a similar problem in a NodeJS implementation here: I also changed the local AMSNetID when connecting, but this did not help either. Do you have an idea?
I don't think this is a problem, since the connection itself works (you're getting a reply from TwinCat, even though it's an error).
BTW, you can also use the adstool
example binary to do some quick checks. Can you try:
cargo run --example adstool 127.0.0.1 info
cargo run --example adstool 127.0.0.1 state
cargo run --example adstool 127.0.0.1 target-desc
cargo run --example adstool 127.0.0.1/:800 state
cargo run --example adstool 127.0.0.1/:801 state
cargo run --example adstool 127.0.0.1/:851 state
BTW, you can also use the
adstool
example binary to do some quick checks. Can you try:cargo run --example adstool 127.0.0.1 info cargo run --example adstool 127.0.0.1 state cargo run --example adstool 127.0.0.1 target-desc cargo run --example adstool 127.0.0.1/:800 state cargo run --example adstool 127.0.0.1/:801 state cargo run --example adstool 127.0.0.1/:851 state
PS C:\Users\Mebus\Desktop\adstest\ads-rs> cargo run --example adstool 127.0.0.1 info
Finished dev [unoptimized + debuginfo] target(s) in 0.14s
Running `target\debug\examples\adstool.exe 127.0.0.1 info`
NetID: 10.176.222.52.1.1
Hostname: MebusDevPC
TwinCAT version: 3.1.4024
OS version: Windows NT 10.0.19042
Fingerprint: bf6d2a95e626580f4151209f318b95ccaa1c464950a38e242db5857e2e2b0fdb
PS C:\Users\Mebus\Desktop\adstest\ads-rs> cargo run --example adstool 127.0.0.1 state
Finished dev [unoptimized + debuginfo] target(s) in 0.14s
Running `target\debug\examples\adstool.exe 127.0.0.1 state`
Error: get device info: Port disabled - system service not started (0x12)
error: process didn't exit successfully: `target\debug\examples\adstool.exe 127.0.0.1 state` (exit code: 1)
PS C:\Users\Mebus\Desktop\adstest\ads-rs> cargo run --example adstool 127.0.0.1/:851 state
Finished dev [unoptimized + debuginfo] target(s) in 0.14s
Running `target\debug\examples\adstool.exe 127.0.0.1/:851 state`
Error: get device info: Port disabled - system service not started (0x12)
error: process didn't exit successfully: `target\debug\examples\adstool.exe 127.0.0.1/:851 state` (exit code: 1)
PS C:\Users\Mebus\Desktop\adstest\ads-rs>
Mebus
Is the TwinCat in config mode or in run mode?
Can you show me the exact code you used successfully with the Python client?
Not the exact code, but the important parts of it:
import pyads
ads_route = "127.0.0.1.1.1"
ads_port = 851
plc = pyads.Connection(ads_route, ads_port)
plc.open()
reactor_vessel_pressure = plc.read_by_name(
"GVL_Reactor.fVesselPressure", pyads.PLCTYPE_REAL
)
print(reactor_vessel_pressure)
plc.close()
(This works on the machine.)
Mebus
Is the TwinCat in config mode or in run mode?
The gear tray icon is green.
Mebus
Ok, let's assume for a moment that the get_state
method just doesn't work. Can you try this:
let client = ads::Client::new(("127.0.0.1", ads::PORT), ads::Timeouts::none(), None)?;
let device = client.device(ads::AmsAddr::new([127, 0, 0, 1, 1, 1].into(), 851));
let handle = ads::Handle::new(device, "GVL_Reactor.fVesselPressure")?;
let mut data = [0; 4];
handle.read(&mut data)?;
println!("value is {}", f32::from_le_bytes(data));
Ok, let's assume for a moment that the
get_state
method just doesn't work. Can you try this:let client = ads::Client::new(("127.0.0.1", ads::PORT), ads::Timeouts::none(), None)?; let device = client.device(ads::AmsAddr::new([127, 0, 0, 1, 1, 1].into(), 851)); let handle = ads::Handle::new(device, "GVL_Reactor.fVesselPressure")?; let mut data = [0; 4]; handle.read(&mut data)?; println!("value is {}", f32::from_le_bytes(data));
I modified it to this:
let client = ads::Client::new(("127.0.0.1", ads::PORT), ads::Timeouts::none(), None).unwrap();
let device = client.device(ads::AmsAddr::new([127, 0, 0, 1, 1, 1].into(), 851));
let handle = ads::Handle::new(device, "GVL_Reactor.fVesselPressure").unwrap();
let mut data = [0; 4];
handle.read(&mut data).unwrap();
println!("value is {}", f32::from_le_bytes(data));
And I got this:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Ads("write and read data", "Port disabled - system service not started", 18)', src\main.rs:40:74
stack backtrace:
0: 0x7ff67fde4e5f - <unknown>
1: 0x7ff67fdf859a - <unknown>
2: 0x7ff67fde1469 - <unknown>
3: 0x7ff67fde6fbb - <unknown>
4: 0x7ff67fde6bae - <unknown>
5: 0x7ff67fde75b1 - <unknown>
6: 0x7ff67fde746d - <unknown>
7: 0x7ff67fde5767 - <unknown>
8: 0x7ff67fde7149 - <unknown>
9: 0x7ff67fdff835 - <unknown>
10: 0x7ff67fdff943 - <unknown>
11: 0x7ff67fd81845 - <unknown>
12: 0x7ff67fd83126 - <unknown>
13: 0x7ff67fd82f6c - <unknown>
14: 0x7ff67fd8df9b - <unknown>
15: 0x7ff67fd8134b - <unknown>
16: 0x7ff67fd811a1 - <unknown>
17: 0x7ff67fddd83e - <unknown>
18: 0x7ff67fd8116f - <unknown>
19: 0x7ff67fd832a6 - <unknown>
20: 0x7ff67fdfdeb8 - <unknown>
21: 0x7ffa42547034 - BaseThreadInitThunk
22: 0x7ffa42b82651 - RtlUserThreadStart
Might that be because of my modification?
Mebus
Ok, same thing here. At this point I don't really know how to diagnose further. I saw that pyads seems to use the TwinCAT ADS router on Windows, so there might be some difference in behavior there. I can try to reproduce this but need to set up a test system.
Might that be because of my modification?
No, the TwinCat error is the same, you're just getting a panic due to the unwrap() which is expected.
Ok, it would be great if you could resolve this :-)
Mebus
I reproduced your problem on a Windows VM. When checking with Wireshark how pyads is communicating with the PLC, I didn't see any TCP traffic, so it must be a completely different internal way of talking to TwinCAT. This is happening in the ADS DLL, so no good way to find out the details.
The way that I found works is to use the external (non-127.0.0.1) IP of the machine, and the correct NetID. In that case, however, you also have to add an ADS route pointing back to yourself, otherwise you'll see "Error receiving reply (route set?): unexpected end of file".
The source code of the Beckhoff DLL should be available here:
https://github.com/Beckhoff/ADS
Can you look into it to see how it does it?
Also I think it's not so easy to dump traffic of the Windows loopback interface.
Mebus
The source code of the Beckhoff DLL should be available here:
That's only an implementation for non-native systems, from the Readme: "This library is intended to provide easy use as ADS client applications running on non-windows systems". The source of the DLL shipped with TwinCAT is not available, AFAIK.
Also I think it's not so easy to dump traffic of the Windows loopback interface.
Well, at least I could see the traffic I generated using the Rust version on loopback without problems.
Does that one work for you?
OK, success! Looking at the other node package (ads-client) brought the enlightenment.
Please try out master
. The connect
method now takes a Source
as the third argument, set it to Source::Request
. Then you should be good to go (at least it worked for me with the latest TwinCAT 3.1.4024.29).
Hi birkenfled!
Great. Now it looks better 😃
PS C:\Users\Mebus\Desktop\adstest\ads-rs> cargo run --example adstool 127.0.0.1 state
Finished dev [unoptimized + debuginfo] target(s) in 0.15s
Running `target\debug\examples\adstool.exe 127.0.0.1 state`
Device: TwinCAT System 3.1.4024
Current state: Run
PS C:\Users\Mebus\Desktop\adstest\ads-rs>
Unfortunately I cannot read the reactor vessel pressure yet:
let dest_address = "127.0.0.1";
let source = if matches!(dest_address, "127.0.0.1" | "localhost") {
ads::Source::Request
} else {
ads::Source::Auto
};
let client = ads::Client::new(("127.0.0.1", ads::PORT), ads::Timeouts::none(), source).unwrap();
let device = client.device(ads::AmsAddr::new([127, 0, 0, 1, 1, 1].into(), 851));
let handle = ads::Handle::new(device, "GVL_Reactor.fVesselPressure").unwrap();
let mut data = [0; 4];
handle.read(&mut data).unwrap();
println!("The VesselPressure is: {} kPa", f32::from_le_bytes(data));
This gives:
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Reply("write and read data", "unexpected source address", 0)', src\main.rs:48:74
stack backtrace:
0: 0x7ff790bb614f - <unknown>
1: 0x7ff790bc988a - <unknown>
2: 0x7ff790bb26f9 - <unknown>
...
Have you implemented the new source address thing everywhere, where it is neccessary?
My dependencies look like this at the moment:
[dependencies]
#ads = "0.3.1"
ads = {git = "https://github.com/birkenfeld/ads-rs"}
That should work to make it use the current master branch, right?
Mebus
Thanks for testing. This is because of the target NetID 127.0.0.1.1.1 - I didn't test with that. Now this NetID is mappend to the local NetID we get from the router.
Please retry (you need to call cargo update
to get the newest master revision).
I've now also added a nicer API to read values. You can replace this:
let mut data = [0; 4];
handle.read(&mut data).unwrap();
println!("The VesselPressure is: {} kPa", f32::from_le_bytes(data));
by
println!("The VesselPressure is: {} kPa", handle.read_value::<f32>().unwrap());
Hi,
thanks! I did some more testing. That looks better now. But can you please increase the version number of your package so that I can use it in a normal way in the Cargo.toml file?
Mebus
Yes, I was just waiting for your confirmation. Will release 0.4 now.
Hi,
I am trying to connect to the local plc like this:
But I get this:
The Python ADS client connects without any problems on this machine. What can I do to fix this?
Mebus