-Dave
The StackManager can start up both slaves and masters. The DemoSlave isn't a bad place to start, but the interfaces are slightly different for an outstation/master.
Instead of calling AddTCPServer(..), add a serial port using AddSerial(..). That's where you'll configure baud, rate, etc. There's no direct control for 485, as there is no standard way of doing this. I assume your hardware is fixed on 485 or you have another way of configuring this.
Now that you have a named port, you call AddMaster(..). The parameter MasterStackConfig controls how the master will behave. Check out the documentation for this in the code or on our Hudson server:
https://dev.greenenergycorp.com:8888/hudson/job/DNP3_Docs/doxygen/?
If you call Start() function instead of Run(), the stack will run in a background thread so that you can go about setting up your UI, etc and retain control of your parent thread. Via the configuration you can set it up to periodically poll for your counters. Does your device support class polling? If so, that's probably the best way to go on a 1/2 duplex link.
The TestSet also shows how to configure a master, but there's a lot more going on there then the demo Slave. It would probably be beneficial to have an demo master as well.
regards,
Adam
The master will stay 100% quiescent with respect to the physical layer until an app layer respond times out. You shouldn't have any trouble using it with half duplex. We've run half duplex serial links with it in the past.
-Adam
-----Original Message-----
From: open...@googlegroups.com on behalf of ben...@benegon.com
Sent: Sun 7/11/2010 1:47 PM
To: open...@googlegroups.com; Sam Hendley
Subject: Re: [open-dnp3] Re: Setting up Half Duplex Operation
My experience with a commercial stack was that its half duplex support
was lacking in that the stack's built in link integrity polling would
transmit while I was receiving data. Since the stack handled the
transmit queue, the only way to handle this was to disable link
integrity polling
In your stack, how do I make sure that transmits don't occur until
after receives are complete?
Is there a "proper" way to do this with the AsyncMaster or do I have
to add a function to AsyncMaster to do it?
-Dave
1) The master doesn't currently support custom scans. We'd love for you to do this and contribute it back to the project.
2) I don't know of a way to write counters in DNP3. Does your device map an analog output to a counter value?
3) The master currently doesn't setting analog deadbands. Ditto from 1).
Both 1) and 3) would be fairly straightforward to implement.
-Adam
-----Original Message-----
From: open...@googlegroups.com on behalf of ben...@benegon.com
Sent: Mon 7/12/2010 9:11 AM
To: open...@googlegroups.com
Subject: RE: [open-dnp3] Setting up Half Duplex Operation
The class poll interval is not cutting it for me. I need to compose a
specific READ to get counter values, and I will also need to WRITE
some counters and set analog deadbands.
Is there a "proper" way to do this with the AsyncMaster or do I have
to add a function to AsyncMaster to do it?
-Dave
> Hi Dave,
>
> 1) The master doesn't currently support custom scans. We'd love for
> you to do this and contribute it back to the project.
OK. I don't really know your architecture but it seems like I would
-Have the user compose a custom APDU
-Hand that APDU and task handler to the AsyncMaster
-AsyncMaster hands those of to a SendAPDU() of its current state
-AMS_Idle is the only AMS_Base descendant to have a working SendAPDU
>
> 2) I don't know of a way to write counters in DNP3. Does your device
> map an analog output to a counter value?
This is specific to a certain product. Welcome to the real world of DNP.
>
> 3) The master currently doesn't setting analog deadbands. Ditto from 1).
>
I'll just use a custom APDU for that now.
1) the architecture encapsulates the APDU, attempting to minimize the number of externally exposed classes, especially complicated ones that introduce dependencies. The preferred/cleanest way to do this would be to extend the scans available to master in MasterConfig to be more generic to meet your application's needs. I.E. making the scans available take specific group/var and ranges.
You could add a more generic function to pass in an APDU + verification function but I would rather see the configurable scans as it most reusable to everyone. It's Apache 2.0, however, so do as you please!
2) Yes, DNP3 has lots of non-standard extensions, we'll consider non-standard additions to the mainline on a case-by-case basis. Out of curiosity, then, your slave then accept APDU's with Function == WRITE and object headers with counters types Group 20, Var X? What vendor/model? What masters that you have worked with support writing counters?
thanks,
Adam
-----Original Message-----
From: open...@googlegroups.com on behalf of ben...@benegon.com
Sent: Mon 7/12/2010 9:43 AM
To: open...@googlegroups.com
Subject: RE: [open-dnp3] Setting up Half Duplex Operation
Quoting Adam Crain <adam....@greenenergycorp.com>:
> Hi Dave,
>
> 1) The master doesn't currently support custom scans. We'd love for
> you to do this and contribute it back to the project.
OK. I don't really know your architecture but it seems like I would
-Have the user compose a custom APDU
-Hand that APDU and task handler to the AsyncMaster
-AsyncMaster hands those of to a SendAPDU() of its current state
-AMS_Idle is the only AMS_Base descendant to have a working SendAPDU
>
> 2) I don't know of a way to write counters in DNP3. Does your device
> map an analog output to a counter value?
This is specific to a certain product. Welcome to the real world of DNP.
>
> 3) The master currently doesn't setting analog deadbands. Ditto from 1).
>
I'll just use a custom APDU for that now.
>
-Do I still need an AsyncStackManager to do this?
-Is there some test code that does this?
Thanks,
Dave
Dave,
I'll try to clarify why it's implemented this way. We have a modbus codebase as well, and those interfaces/abstractions in APL (Async Protocol Library) were meant to serve as a superset of what you needed to represent the interfaces for index-based protocols like DNP3, modbus, telegyr, ICCP, etc.
In general, you may find our docs on our CI serer helpful:
https://dev.greenenergycorp.com:8888/hudson/job/DNP3_Docs/doxygen/?
The ICommandAcceptor is the only *dynamic* means of communication, but there's a whole config structure that could be modified to tell the master how to behave. This was written this way so that re-usability would be favored over custom tasks. That said, it's clearly getting in your way at the moment.
You could write your own master, and tie in directly to the application layer, but you'd be doing just as much work if not more work than modifying the current master's task handling and telling it what to do via new configuration information. You could add descriptors for how to do counter writes, deadbands setpoints, and custom polls to this file:
http://github.com/greenenergycorp/dnp3/blob/master/DNP3/MasterConfig.h
And then react to those configurations in AsyncMaster.
If you really wanted to write another master, you can start by looking at the interactions between these classes:
http://github.com/greenenergycorp/dnp3/blob/master/DNP3/AsyncStack.h
http://github.com/greenenergycorp/dnp3/blob/master/DNP3/AsyncLinkLayerRouter.h
http://github.com/greenenergycorp/dnp3/blob/master/APL/PhysicalLayerManager.h
If you can get your brain wrapper around how these three classes work together, you could write your own master and send APDU's directly. However, it will still have to be based on an async model where the event flow is driven by calls to boost::io_service::run(). This takes a bit of getting used to... but it's the way that we can get our frontend to talk to hundreds of endpoints without lots of nasty context switching.
If you want to understand how the master/outstation interacts with the application layer, have a look at the interfaces defined in:
http://github.com/greenenergycorp/dnp3/blob/master/DNP3/AsyncAppInterfaces.h
and the tests defined in:
http://github.com/greenenergycorp/dnp3/blob/master/DNP3Test/TestAsyncAppLayer.cpp
-Adam
-----Original Message-----
From: ben...@benegon.com [mailto:ben...@benegon.com]
Sent: Mon 7/12/2010 3:18 PM
To: open...@googlegroups.com; Adam Crain
Subject: RE: [open-dnp3] Setting up Half Duplex Operation
Adam,
I took another look at this and I think I am on the wrong track.
Even with the modifications to the Master, there is still a generic
ICommandAcceptor interface. However, what I am doing is very specific
to a single application. The Master abstraction is really getting in
the way because the only I have to communicate with it is through the
ICommandAcceptor. I really do not want to bubble a few specific
commands through all these layers of code. I also don't understand why
I need to talk to an interface in APL to do DNP stuff.
I like the APDU for composing commands and would just like to send
them to the destination slave address. I like the asynchronous part
but would be willing to write the code synchronously as well.
-Do I still need an AsyncStackManager to do this?
-Is there some test code that does this?
Thanks,
Dave
> The ICommandAcceptor is the only *dynamic* means of communication,
> but there's a whole config structure that could be modified to tell
> the master how to behave. This was written this way so that
> re-usability would be favored over custom tasks. That said, it's
> clearly getting in your way at the moment.
I have to say I ended up not using your library. Having used DNP
from a high level with another toolkit, it was easier for me to
understand the link, transport, and application protocol and hack
something out for my purposes. The data marshalling back and forth is
about 200-300 lines of code. The frustrating thing is I know you do
this already but it was not easy to use ONLY that part of the code.
I think your library could be a great starting point for a reference
implementation or maybe a big box SCADA system. However, I think for
developer use it needs improvement for the following areas:
-Embedded systems: There are many programmers with years of embedded
experience who are used to C and assembler. In many cases they are
being asked to write software that runs on top of an OS. They will run
screaming from boost.asio, ruby, java, and the jungle of CamelCased
design patterns that dominate your code. The only reason I didn't do
the same was because I'm not far out of a good computer science
school. If you don't provide a simple, synchronous C-like C++
interface you will be shutting out many senior engineers from this
product.
-Smaller data concentrators: Mostly similar to embedded systems. Don't
really need to manage thousands of connections; at most 5-6 dozen.
-Test Harness tools: Most test harness tools will let you do things
like Write Counters straight out of the box. That's because the give
you very fine grained control over composing DNP requests. NEVER force
the user to hack specific functions into generic interfaces; generic
interfaces promote reusability, but reusability should be optional,
not required.
I would like to see functions for stateful composition of packets and
marshalling data; leave it up to the programmer to send that data over
a fd. That way I can use your library to make product specific custom
tools.
Perhaps you modularize your top layers as well so I don't need to
use your IO framework to use them. I could just feed the data packets
to those layers and they could call me back.
Thanks,
-Dave
I have to say I ended up not using your library. Having used DNP from a high level with another toolkit, it was easier for me to understand the link, transport, and application protocol and hack something out for my purposes.The ICommandAcceptor is the only *dynamic* means of communication, but there's a whole config structure that could be modified to tell the master how to behave. This was written this way so that re-usability would be favored over custom tasks. That said, it's clearly getting in your way at the moment.
The data marshalling back and forth is about 200-300 lines of code. The frustrating thing is I know you do this already but it was not easy to use ONLY that part of the code.
I think your library could be a great starting point for a reference implementation or maybe a big box SCADA system. However, I think for developer use it needs improvement for the following areas:
-Embedded systems: There are many programmers with years of embedded experience who are used to C and assembler. In many cases they are being asked to write software that runs on top of an OS. They will run screaming from boost.asio, ruby, java, and the jungle of CamelCased design patterns that dominate your code. The only reason I didn't do the same was because I'm not far out of a good computer science school. If you don't provide a simple, synchronous C-like C++ interface you will be shutting out many senior engineers from this product.
-Smaller data concentrators: Mostly similar to embedded systems. Don't really need to manage thousands of connections; at most 5-6 dozen.
-Test Harness tools: Most test harness tools will let you do things like Write Counters straight out of the box. That's because the give you very fine grained control over composing DNP requests. NEVER force the user to hack specific functions into generic interfaces; generic interfaces promote reusability, but reusability should be optional, not required.
I would like to see functions for stateful composition of packets and marshalling data; leave it up to the programmer to send that data over a fd. That way I can use your library to make product specific custom tools.
Perhaps you modularize your top layers as well so I don't need to use your IO framework to use them. I could just feed the data packets to those layers and they could call me back.