[co7io] Industrial integrations with Beckhoff ADS/Siemens S7

Hi, thank you for your quick reply. I changed the extension of the file to something else and back to .kar. Now I could install the package. Maybe also I was not waiting long enough.
I con do some testing now. Looking forward. Thank you. BR

Hi, I can not connect to the PLC. I would like to create an Beckhoff ADS Network Bridge.

What I have: host, targetAmsId and targetAmsPort of the Beckhoff PLC as target.

What I don´t have: sourceAmsId, sourceAmsPort?
I don´t get it. What do I have to put in there? Normally there is no bidirektional authentification so I usually don´t need to know the information of the source?

I put in some values and the error message is like this:

[handler.BeckhoffNetworkBridgeHandler] - Could not obtain connection

org.apache.plc4x.java.api.exceptions.PlcConnectionException: Connection url ads:tcp://192.168.178.58/192.168.178.58.1.1:801/1.2:801 doesn't match 'ads://{{host|ip}|serial:definition}/{targetAmsNetId}:{targetAmsPort}/{sourceAmsNetId}:{sourceAmsPort}' RAW:^ads:(tcp://(?<host>[\w.]+)(:(?<port>\d*))?|serial://(?<serialDefinition>((?!/\d).)*))/(?<targetAmsNetId>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(?<targetAmsPort>\d+)(/(?<sourceAmsNetId>\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}):(?<sourceAmsPort>\d+))?(\?.*)?

Thank you. BR

Error you noticed comes from invalid connection string. This connection URL is generated from parameters given in configuration.

By default sourceAmsId is client machine IP address suffixed with .1.1. If computer on which you run openHAB is visible in network as 192.168.200.20 then source ams can be set to 192.168.200.20.1.1, I would leave port same as you have on target machine eventually set it to 48898 if it doesn’t work.

By re-checking regular expression I noticed that source ams parameters are optional from plc4x. I will make them optional as well. Please try suggested values while I will cook new build. :slight_smile:

Thank you. Thats nice. Now I have a connection. :grinning:
Next thing where I struggle is the channel configuration. I try to set a bool variable. Field configuration looks like this:


But now I receive errors like this:

An error occurred while calling method ‘ThingHandler.handleCommand()’ on ‘org.connectorio.binding.plc4x.beckhoff.internal.handler.BeckhoffPlcHandler@1aee3eb’: No enum constant org.apache.plc4x.java.ads.model.AdsDataType.0x0

Btw: Refresh interval is in [ms]?

1 Like

Field might be 0x00004020:0x0:BOOL. You need data type and you can skip number of elements if you read single element/not an array. If you fetch 4 elements from an array (which is unsupported ATM) then you use 0x00004020:0x0:BOOL[4], however I will need to double check how plc4x actually handles that.

Yes, refresh interval is in ms.

When I am changing the value of the item in openHab there are exceptions in the log. On the side of PLC there is no change. Do you have an idea?
log.txt (3.4 KB)

It is communication error, possibly the network connection is not working as expected due to wrong ams id which breaks routing of answer back to caller. Lets see if newer version will work better.

Cause I can’t edit first post, attaching link here.

  • 20200103 - 2.5.0-SNAPSHOT - Beckhoff’s sourceAmsId/port parameters are now marked as optional. Added TCP port option for ADS network connections.

Hi @splatch and @Tuny, im in with testing to.

First of all, thanks to @splatch for the great effort so far.

I managed to get the ADS binding to work with the 20200103 Snapshot.

I have done it with a .things file that looks like this:

Bridge co7io-plc4x-ads:network:1dc63c66 [host="192.168.2.35", port=48898, targetAmsId="5.28.212.102.1.1", targetAmsPort=801, sourceAmsId="192.168.2.9.1.1", sourceAmsPort=801, refreshInterval=1000] {
  Thing co7io-plc4x-ads:ads:1bb93999 [refreshInterval=1000] {
  Channels:
     Type switch : plc4XBoolTest1 "plc4XBoolTest1" [field="gTestPLC4XBOOL:BOOL", refreshInterval=1000]
  }
}

My things look like this now:

This are my global test variables on the TwinCat side:

image

Unfortunately i’m getting this error now, when the binding tries to read the boolean:

2020-01-04 11:26:33.242 [me.event.ThingUpdatedEvent] - Thing 'co7io-plc4x-ads:ads:1bb93999' has been updated.

==> /logs/openhab.log <==

2020-01-04 11:26:33.224 [INFO ] [el.core.internal.ModelRepositoryImpl] - Validation issues found in configuration model 'plc4XTest.things', using it anyway:

Provide a thing type ID and a thing ID in this format:

 <thingTypeId> <thingId>

2020-01-04 11:26:33.227 [INFO ] [el.core.internal.ModelRepositoryImpl] - Refreshing model 'plc4XTest.things'

2020-01-04 11:26:36.243 [WARN ] [mmon.WrappedScheduledExecutorService] - Scheduled runnable ended with an exception: 

org.apache.plc4x.java.api.exceptions.PlcRuntimeException: java.util.concurrent.TimeoutException

	at org.apache.plc4x.java.ads.connection.AdsAbstractPlcConnection.getFromFuture(AdsAbstractPlcConnection.java:236) ~[?:?]

	at org.apache.plc4x.java.ads.connection.AdsAbstractPlcConnection.lambda$mapFields$3(AdsAbstractPlcConnection.java:180) ~[?:?]

	at java.util.concurrent.ConcurrentHashMap.computeIfAbsent(ConcurrentHashMap.java:1660) ~[?:1.8.0_232]

	at org.apache.plc4x.java.ads.connection.AdsAbstractPlcConnection.mapFields(AdsAbstractPlcConnection.java:163) ~[?:?]

	at java.util.stream.ForEachOps$ForEachOp$OfRef.accept(ForEachOps.java:183) ~[?:1.8.0_232]

	at java.util.stream.ReferencePipeline$3$1.accept(ReferencePipeline.java:193) ~[?:1.8.0_232]

	at java.util.stream.ReferencePipeline$2$1.accept(ReferencePipeline.java:175) ~[?:1.8.0_232]

	at java.util.LinkedList$LLSpliterator.forEachRemaining(LinkedList.java:1235) ~[?:1.8.0_232]

	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482) ~[?:1.8.0_232]

	at java.util.stream.ForEachOps$ForEachTask.compute(ForEachOps.java:290) ~[?:1.8.0_232]

	at java.util.concurrent.CountedCompleter.exec(CountedCompleter.java:731) ~[?:1.8.0_232]

	at java.util.concurrent.ForkJoinTask.doExec(ForkJoinTask.java:289) ~[?:1.8.0_232]

	at java.util.concurrent.ForkJoinTask.doInvoke(ForkJoinTask.java:401) ~[?:1.8.0_232]

	at java.util.concurrent.ForkJoinTask.invoke(ForkJoinTask.java:734) ~[?:1.8.0_232]

	at java.util.stream.ForEachOps$ForEachOp.evaluateParallel(ForEachOps.java:159) ~[?:1.8.0_232]

	at java.util.stream.ForEachOps$ForEachOp$OfRef.evaluateParallel(ForEachOps.java:173) ~[?:1.8.0_232]

	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:233) ~[?:1.8.0_232]

	at java.util.stream.ReferencePipeline.forEach(ReferencePipeline.java:485) ~[?:1.8.0_232]

	at org.apache.plc4x.java.ads.connection.AdsAbstractPlcConnection.mapFields(AdsAbstractPlcConnection.java:157) ~[?:?]

	at org.apache.plc4x.java.ads.connection.AdsAbstractPlcConnection.read(AdsAbstractPlcConnection.java:103) ~[?:?]

	at org.apache.plc4x.java.base.messages.DefaultPlcReadRequest.execute(DefaultPlcReadRequest.java:44) ~[?:?]

	at org.connectorio.binding.plc4x.shared.handler.task.ReadTask.run(ReadTask.java:47) ~[?:?]

	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) ~[?:1.8.0_232]

	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) ~[?:1.8.0_232]

	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) ~[?:1.8.0_232]

	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) ~[?:1.8.0_232]

	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_232]

	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_232]

	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_232]

Caused by: java.util.concurrent.TimeoutException

	at java.util.concurrent.CompletableFuture.timedGet(CompletableFuture.java:1784) ~[?:1.8.0_232]

	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1928) ~[?:1.8.0_232]

	at org.apache.plc4x.java.ads.connection.AdsAbstractPlcConnection.getFromFuture(AdsAbstractPlcConnection.java:230) ~[?:?]

	... 28 more

==> /logs/events.log <==

I think this is pretty much the same error as @Tuny reported allready here:

Any ideas how to fix this?

One concerne i’m thinking about in this case is:

When i connect to my PLC with Beckhoff tools, i must provide a username and a passwort to get connection to the ADS routing. How does PLC4X handle this? Shouldn’t we be able to provide credentials here to?

Might this probably chause the error i’m seeing now?

1 Like

I made a second attempt, using index decimal notation to declare the field value.

This time the .things file looks like this:

Bridge co7io-plc4x-ads:network:1dc63c66 [host="192.168.2.35", port=48898, targetAmsId="5.28.212.102.1.1", targetAmsPort=801, sourceAmsId="192.168.2.9.1.1", sourceAmsPort=801, refreshInterval=1000] {
  Thing co7io-plc4x-ads:ads:1bb93999 [refreshInterval=1000] {
  Channels:
     Type switch : plc4XBoolTest1 "plc4XBoolTest1" [field="16448/1035447:BOOL", refreshInterval=5000]
  }
}

With that approach i’m getting another error:

2020-01-04 13:58:25.822 [WARN ] [g.plc4x.shared.handler.task.ReadTask] - Could not fetch data from PLC

java.util.concurrent.ExecutionException: java.nio.channels.ClosedChannelException

	at java.util.concurrent.CompletableFuture.reportGet(CompletableFuture.java:357) ~[?:1.8.0_232]

	at java.util.concurrent.CompletableFuture.get(CompletableFuture.java:1908) ~[?:1.8.0_232]

	at org.connectorio.binding.plc4x.shared.handler.task.ReadTask.run(ReadTask.java:52) [bundleFile:?]

	at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:511) [?:1.8.0_232]

	at java.util.concurrent.FutureTask.runAndReset(FutureTask.java:308) [?:1.8.0_232]

	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.access$301(ScheduledThreadPoolExecutor.java:180) [?:1.8.0_232]

	at java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask.run(ScheduledThreadPoolExecutor.java:294) [?:1.8.0_232]

	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149) [?:1.8.0_232]

	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624) [?:1.8.0_232]

	at java.lang.Thread.run(Thread.java:748) [?:1.8.0_232]

Caused by: java.nio.channels.ClosedChannelException

	at io.netty.channel.AbstractChannel$AbstractUnsafe.newClosedChannelException(AbstractChannel.java:955) ~[?:?]

	at io.netty.channel.AbstractChannel$AbstractUnsafe.write(AbstractChannel.java:863) ~[?:?]

	at io.netty.channel.DefaultChannelPipeline$HeadContext.write(DefaultChannelPipeline.java:1378) ~[?:?]

	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:716) ~[?:?]

	at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:708) ~[?:?]

	at io.netty.channel.AbstractChannelHandlerContext.access$1700(AbstractChannelHandlerContext.java:56) ~[?:?]

	at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.write(AbstractChannelHandlerContext.java:1102) ~[?:?]

	at io.netty.channel.AbstractChannelHandlerContext$WriteAndFlushTask.write(AbstractChannelHandlerContext.java:1149) ~[?:?]

	at io.netty.channel.AbstractChannelHandlerContext$AbstractWriteTask.run(AbstractChannelHandlerContext.java:1073) ~[?:?]

	at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:163) ~[?:?]

	at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:416) ~[?:?]

	at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:515) ~[?:?]

	at io.netty.util.concurrent.SingleThreadEventExecutor$5.run(SingleThreadEventExecutor.java:918) ~[?:?]

	at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74) ~[?:?]

	at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30) ~[?:?]

	... 1 more

==> /logs/events.log <==

Hey @seimenb, @Tuny I still couldn’t get device for direct tests thus I can not (yet) confirm if it is a bug. I hope to get VPN access to Apache IoT Lab in next days to do testing myself.
You can try to skip source ams parameters, if it doesn’t help you can also try to follow PLC4X instructions on setting up AMS routing:
https://plc4x.apache.org/developers/vpn.html#_toc_beckhoff_c6920-0030

Cheers,
Łukasz

I also installed it and i am currently working on it … some observations:

I tend to say that In ADS the “Target Port” is the Port for your Runtime on your SPS and you can see that in the TwinCat System Manager. SPS Configuration, for me 801 (on my Cx9xxx) for the first runtime on that SPS (811 would be second, 821,831,… just in case you have multiple runtimes)

Also i belive from this IOBroker thread https://forum.iobroker.net/topic/14285/adapter-beckhoff-ads/85 and my own local TWINCat Software i need to add a route for the openhab IP and Target System using the TwinCat System Manager. (Currently i am trying to fix that)

Source Port is kind off optional but mandatory field. Id did a quick check in the JAVA examples of Beckhoff https://infosys.beckhoff.de/english.php?content=../content/1033/tcsample_java/html/tcsample_java_intro.htm&id=
and i did not saw any of them using a Source Port to connect … so i tend to say it is only required if you have multiple ADS Device ID talking to a single destination. Like Multiple SPS on one AMS ID talking to another Target AMS id on another system.

I did a few packet captures and the only i see is when i add the Device that openhab connects (TCP SYN…) TCP gets established, does not transports anything (no DATA) and once fully established (just TCP layer) the SPS sends a FIN to disconnect the TCP immediate. Maybe i still miss the correct route.

Will continue testing this.

I’ve tried to avoid usage of port numbers beside amsId however current regular expression for parsing connection string requires it.
Today I’ve got my VPN access so I will play with it over weekend to see if I will go any further.

Hello Folks,

I also started testing this ADS Binding with my CX5120 and TwinCat 3.1.4027 (newest TC3 version)

I do get the same error as @Tuny and @seimenb.

I’m sure that the error happens, when the Binding trys to connect to the plc and I’m also pretty sure that this happens because the ADS Route is not established at this time. When I start the Bridge it says that it is online in the PaperUI, but on the target system no new route is added.

I think the route does not get established because the binding does not provide a username and a password for the route.

When you set up an ads route on the normal Beckhoff way, you will have to set it up with this window:

image

By adding the route I need to enter the login credentials for the PLC:

image

Only then, I’m able to add the route from openHAB to the PLC.
I tried to enter the credentials in my Bridige, but it didn’t solve the problem. I guess these parameters are not set up in this add-on:

Bridge co7io-plc4x-ads:network:1dc63c66 [host="192.168.0.9", port=48898, targetAmsId="5.40.218.192.1.1", targetAmsPort=801, sourceAmsId="5.40.218.192.1.1", sourceAmsPort=801, refreshInterval=1000, username="Administrator", password="XXXXXX"] {

}

@splatch: Are you able to check my theory or send me a github link from the binding, so I can check it by myself?

Thanks, I would really like to get this binding running.

Marcel

Hey @MarcelPayne,
Thanks for the info and test drive. Can you tell me if static route can be added upfront and left in persistent manner or lack of user/pw blocks entirely whole thing?
Binding attempts to open a connection to PLC and it does not support anything related to routing yet. In fact ams parameters set on connection are the only one thing exposed by underlying client library (plc4x) so far.
To me what you shown on above screens “add remote route” which requires additional password seems to be preflight call for opening the connection. I was trying to check Beckhoff documentation if there is any operation which requires username and password and found none beside routing.

Because we are currently limited by connection string ads://{{host|ip}|serial:definition}/{targetAmsNetId}:{targetAmsPort}/{sourceAmsNetId}:{sourceAmsPort} supported by plc4x (see AdsPlcDriver here) there is no way to get anything more than that.
We need to implement additionally routing part of ADS protocol in order to move forward. I checked with plc4x folks and they are interested to get that as part of the project up but first someone needs to donate code implementing that functionality. We still can experiment on our own with making binding aware of ads routing and its details.

Cheers,
Łukasz

For these who were interested in soruces, they are now available here: http://github.com/connectorio/connectorio-addons

I’ve been working on BACnet binding recently thus I didn’t move much forward with ADS yet.

Best,
Łukasz

Hello together,

I’m new in Openhab and try to connect my Beckhoff CP6606 (TwinCat 3) with Openhab.

I search tutorials in google and find this site.

I download the snapshot and install the Version 2.5.0 into my Openhab.

But now I’m not sure how to continue…

is there anywhere a tutorial for me?

Greetings

Thomas

After installation of binding you should be able to add new ADS connection via Inbox > Add (plus button) or Configuration > Things > Add (plus button). There is no support for discovery and because of routing Beckhoff binding generally speaking doesn’t work unless you setup routing properly (Ams source/target id).

Thank you for your fast answer.

I did it, but is it right, that I can only add three types of channel?
On/Off Switch - Open/Closed Contact - Numeric value

Are there no more possibilitys?

Greetings

Thomas

You are right. Currently there are just three kinds of channels supported, but adding additional ones is not a problem. What data types from PLC do you currently miss?

Maybe all of them? :slight_smile: