Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions guide/docs/about/dependencies.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,9 @@ slug: /dependencies
import useBaseUrl from '@docusaurus/useBaseUrl';
import sitedata from '../../sitedata.json'

Rust's package manager (`cargo`) makes it easy to work with external dependencies. This is wonderful for development, but means that Rust applications
and libraries tend to have many dependencies.
Rust's package manager (`cargo`) makes it easy to work with external dependencies. This is great for development, but means Rust applications and libraries tend to have many dependencies.

Our library only depends directly on a handful of third-party libraries; however, those libraries pull in dozens of their own dependencies. Here's how we manage
our direct and indirect dependencies.
Our library depends directly on a handful of third-party libraries, but those pull in dozens of their own. Here's how we manage dependencies.

## Dependency Allowlisting

Expand Down
5 changes: 2 additions & 3 deletions guide/docs/about/dnp3.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ A DNP3 outstation is a field device that provides measurement data and controls
* Capacitor banks
* Voltage-regulators

If you use DNP3 over TCP/IP, the outstation typically acts as a TCP server. This lets it accept connections from one or more masters acting as a TCP client.
Over TCP/IP, the outstation typically acts as a server, accepting connections from one or more masters acting as TCP clients.

:::note
Unlike typical client/server architecture where multiple clients can access the same server, DNP3 statefully buffers event data for a specific master.
Expand All @@ -33,8 +33,7 @@ If you plan to connect multiple masters to the same TCP endpoint, you must preco

### Virtual RTUs

You can also use a DNP3 outstation to transfer measurement and control data from a utility SCADA system to a historian or automation process. This is also known as a virtual remote terminal unit (RTU) since you implement it as a software
processor within the SCADA server without separate physical hardware.
A DNP3 outstation can transfer measurement and control data from a SCADA system to a historian or automation process. This is called a virtual RTU—a software processor within the SCADA server with no separate physical hardware.

```mermaid
graph LR
Expand Down
3 changes: 1 addition & 2 deletions guide/docs/about/guide.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,7 @@ Language-specific API documentation is available via the links below:

## IEEE-1815

While this guide covers many DNP3 concepts, it is not a replacement for the DNP3 standard. If you plan to develop a product that uses DNP3, a copy of the
standard is indispensable. Purchase your copy from the [DNP3 Users Group](https://dnp.org) or [IEEE](https://standards.ieee.org/standard/1815-2012.html).
This guide covers many DNP3 concepts but is not a replacement for the standard. If you're developing a DNP3 product, the standard is indispensable. Purchase it from the [DNP3 Users Group](https://dnp.org) or [IEEE](https://standards.ieee.org/standard/1815-2012.html).

<div style={{textAlign: 'center'}}>
<a href="https://dnp.org"><img alt="DNP3 logo" src={useBaseUrl('img/dnp_logo.jpg')} /></a>
Expand Down
4 changes: 2 additions & 2 deletions guide/docs/about/interoperability.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ DNP3 defines four subset levels of interoperability:
* `Level 2`: This adds several function codes and objects in order to support a simple RTU or data concentrator.
* `Level 3`: This adds additional function codes and objects, most notably enable/disable of unsolicited reporting, in order to support complex RTUs/concentrators.
* `Level 4`: This adds rarely-used features, such as floating-point analog variations, double-bit binary inputs, and device attributes.
* Please note that features like file transfer, datasets, and secure authentication do not belong to any subset level.
Features like file transfer, datasets, and secure authentication do not belong to any subset level.


### Current Support: Level 3

Our library is currently `Level 3` compliant for both master and outstation. We will make it `Level 4` compliant in a future release. Please note that we already support a number of `Level 4` features, along with features that do not belong to a subset level including:
Our library is currently `Level 3` compliant for both master and outstation. `Level 4` compliance is planned for a future release. We already support a number of `Level 4` features, along with features outside subset levels:

| Feature | Objects | Level |
|---------------------------|---------------------------------------------------------|:----------:|
Expand Down
10 changes: 4 additions & 6 deletions guide/docs/api/logging.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ slug: /api/logging
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

The library provides highly-contextual logging using the [tracing](https://crates.io/crates/tracing) crate. If you're using Rust, refer to the
The library uses the [tracing](https://crates.io/crates/tracing) crate for contextual logging. Rust users should refer to the
tracing documentation for details.

In comparison, the bindings use a rigid logging interface with a single callback method to record a message. Configurable options include:
Expand Down Expand Up @@ -87,7 +87,7 @@ use.

## Example Output

The logs provide a wealth of contextual metadata so you can:
Logs include contextual metadata so you can:

* Determine which communication session produced the message
* Understand what state the software was in when the event occurred
Expand All @@ -103,16 +103,14 @@ INFO DNP3-Master-TCP{endpoint="127.0.0.1:20000"}:Task{type=Function(DisableUnsol

## Protocol Decoding

Protocol decoding is configurable on a per-communication channel basis, such as all traffic on a TCP socket or a serial port. You can specify the
`DecodeLevel` when you create a master or outstation or adjust it at runtime. This struct controls the level of decoding (including none) that takes place for each layer of the
protocol stack, including:
Configure protocol decoding per communication channel (TCP socket, serial port, etc.) by setting `DecodeLevel` when creating a master or outstation, or adjust it at runtime. This controls decoding for each layer of the protocol stack:

* Application-layer headers, object headers, and object values
* Transport-layer header and payload
* Link-layer header and payload
* Physical-layer length and data bytes

Refer to the language-specific API documentation for the meaning of each enumeration value. The decoding can even show the value of individual fields within objects:
See the language-specific API documentation for enumeration values. Decoding can show individual field values within objects:

```
APP TX - ctrl: [fir: true fin: true con: false uns: false seq: 1] func: Write ... (len = 6)
Expand Down
11 changes: 5 additions & 6 deletions guide/docs/api/master/association_config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ slug: /api/master/association/config
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

The `AssociationConfig` struct provides the configuration information you need to communicate with a particular outstation on the communication channel, including:
`AssociationConfig` configures communication with a particular outstation:

* Timeout for responses on this association
* Startup handshaking
* If and how to perform time synchronization
* Per-association task queue size

Note that the outstation address is provided as a separate argument when adding an association to a channel.
The outstation address is provided as a separate argument when adding an association to a channel.

<Tabs
groupId="language"
Expand Down Expand Up @@ -78,12 +78,11 @@ sequenceDiagram
Outstation->>Master: Response;
```

If your outstation doesn't support unsolicited reporting, you can turn the DISABLE/ENABLE unsolicited requests off by setting
`AssociationConfig.DisableUnsolClasses` and `AssociationConfig.EnableUnsolClasses` to `EventClasses.None()`. The master will then skip unsolicited configuration during initialization, only performing the integrity poll.
If your outstation doesn't support unsolicited reporting, set `AssociationConfig.DisableUnsolClasses` and `AssociationConfig.EnableUnsolClasses` to `EventClasses.None()`. The master will skip unsolicited configuration and only perform the integrity poll.

## Scheduling

The following algorithm is used to schedule requests within an association:
Requests within an association are scheduled as follows:

1. User requests such as control operations get top priority.
2. The association then considers automatic and initialization tasks in this order:
Expand All @@ -92,7 +91,7 @@ The following algorithm is used to schedule requests within an association:
3. Perform an integrity scan if configured to do so during initialization.
4. Perform automatic time synchronization if enabled, and the master observes the 'NEED_TIME IIN' bit in a response.
5. Enable unsolicited reporting if configured to do so during initialization.
3. Finally, the system will then execute periodic polls.
3. Periodic polls execute last.

:::note
The standard does not specify how requests should be scheduled for multiple associations on a channel. Our implementation uses a per-association task queue. The channel scheduler round-robins through the associations to ensure fair access.
Expand Down
5 changes: 2 additions & 3 deletions guide/docs/api/master/association_create.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ slug: /api/master/association/create
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

You can create associations on a `MasterChannel` by specifying configuration and callback interfaces.
Create associations on a `MasterChannel` by specifying configuration and callback interfaces.

<Tabs
groupId="language"
Expand Down Expand Up @@ -64,8 +64,7 @@ The Rust API and the binding APIs handle associations in two different ways:
</TabItem>
</Tabs>

The `AssociationId` struct that is returned when adding an association is just a token. While it's required to perform operations on a particular outstation on the channel,
you don't need to keep a reference to it unless you need it to perform operations later. Allowing the `AssociationId` to be garbage collected won't remove the association from the channel.
The returned `AssociationId` is just a token. It's required for operations on a particular outstation, but you don't need to keep a reference unless you need it later. Garbage collecting the `AssociationId` won't remove the association from the channel.

## Removing

Expand Down
5 changes: 2 additions & 3 deletions guide/docs/api/master/association_handler.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,9 @@ slug: /api/master/association_handler
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

The `AssociationHandler` interface handles all the per-association callbacks that are unrelated to measurement data. It contains a single method (`get_current_time`)
to retrieve a UTC timestamp used to synchronize the time on the outstation.
`AssociationHandler` handles per-association callbacks unrelated to measurement data. It contains a single method (`get_current_time`) to retrieve a UTC timestamp for time synchronization.

Typically, you'd return the system time in `get_current_time` which is kept synchronized via NTP. However, you can use a different clock if desired. For example, you might want a data concentrator to receive time from an upstream DNP3 master while maintaining an offset from an internal clock. The examples below demonstrate how to implement an `AssociationHandler` that retrieves the system time.
Typically, return the system time (synchronized via NTP) in `get_current_time`. You can use a different clock if desired—for example, a data concentrator receiving time from an upstream DNP3 master. The examples below retrieve the system time.

<Tabs
groupId="language"
Expand Down
3 changes: 1 addition & 2 deletions guide/docs/api/master/association_polls.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ slug: /api/master/association/polls
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

You should typically add periodic polls before calling `MasterChannel.enable()`. However, you can also add or remove periodic polls at any time. You can specify the
association to poll, the type of request, and the polling interval.
Add periodic polls before calling `MasterChannel.enable()`, though you can add or remove them at any time. Specify the association, request type, and polling interval.

<Tabs
groupId="language"
Expand Down
2 changes: 1 addition & 1 deletion guide/docs/api/master/attributes.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,7 @@ values={[

## Writing Attributes

Attributes can be written one at a time or in batches by constructing a request header send it the outstation. The Rust
Attributes can be written one at a time or in batches by constructing a request header and sending it to the outstation. The Rust
API uses a single method to add an attribute to the header, whereas the bindings use a separate method for each type of
attribute.

Expand Down
2 changes: 1 addition & 1 deletion guide/docs/api/master/channel_config.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ The `MasterChannelConfig` struct contains the following generic settings that ar
* Transmit and receive buffer sizes

:::note
The timeout for responses is configured for each association individually. This is useful if the outstation is a gateway services with varying latency.
The timeout for responses is configured for each association individually. This is useful if the outstation is a gateway service with varying latency.
:::

The constructor takes the master address and has reasonable defaults for all other settings. The default response timeout is 5 seconds; you may need to increase it for high-latency communication links. You should only need to adjust the default buffer size of 2,048 bytes if an outstation has a non-standard configuration.
Expand Down
2 changes: 1 addition & 1 deletion guide/docs/api/master/controls.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ slug: /api/master/association/controls
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

You can construct arbitrary sequences of binary and analog output headers using a builder class. You can then send these commands to a particular outstation using the association id.
Construct sequences of binary and analog output headers using a builder class, then send them to a particular outstation using the association id.


<Tabs
Expand Down
8 changes: 4 additions & 4 deletions guide/docs/api/master/file_transfer.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ values={[
<TabItem value="C">

```c
This is possible, but not part of the C example!
// Not demonstrated in this example.
```

</TabItem>
Expand Down Expand Up @@ -111,7 +111,7 @@ values={[
<TabItem value="C">

```c
This is possible, but not part of the C example!
// Not demonstrated in this example.
```

</TabItem>
Expand Down Expand Up @@ -160,7 +160,7 @@ a background file transfer, accumulating the file data over possibly multiple bl
of `FileInfo` instances.

:::warning
The default limit for the size of directory file is 2048 bytes. This is a reasonable and safe limit, however, if its too
The default limit for the size of directory file is 2048 bytes. This is a reasonable and safe limit, however, if it's too
small in your application you can raise this limit using the provided parameter in `DirReadConfig`.
:::

Expand All @@ -184,7 +184,7 @@ values={[
<TabItem value="C">

```c
This is possible, but not part of the C example!
// Not demonstrated in this example.
```

</TabItem>
Expand Down
7 changes: 2 additions & 5 deletions guide/docs/api/master/read_handler.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ slug: /api/master/read_handler
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

The `ReadHandler` interface is used to receive values from the outstation as it is received by the master. This callback interface is specified
for each association you create and is invoked for both unsolicited responses and responses to READ requests.
The `ReadHandler` interface receives measurement values from the outstation. Specify it for each association; it's invoked for both unsolicited responses and READ responses.

When a response is parsed and determined to carry measurement data, `ReadHandler` callbacks are executed in the following order:

Expand All @@ -35,9 +34,7 @@ Since responses may consist of multiple fragments, you can inspect the `Response
in a response series.
:::

It is possible to send a read request with a specific `ReadHandler` by using the `MasterChannel::read_with_handler()` method.
All the response data associated with the request will be forwarded to the `ReadHandler` specified as an argument instead of
going to the handler specified at the creation of the association.
Use `MasterChannel::read_with_handler()` to send a read request with a specific `ReadHandler`. Response data goes to the specified handler instead of the association's default handler.

## Device Attributes

Expand Down
8 changes: 3 additions & 5 deletions guide/docs/api/master/tcp_client.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ slug: /api/master/tcp_client
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

A `MasterChannel` presents the same interface once you create it, regardless of the underlying transport. You can create a TCP client channel using the runtime,
configuration data, and a callback to observe the status of the connection.
A `MasterChannel` presents the same interface regardless of transport. Create a TCP client channel using the runtime, configuration data, and a connection status callback.

<Tabs
groupId="language"
Expand Down Expand Up @@ -65,7 +64,7 @@ The function is called within the context of the Tokio runtime, and is therefore

## Enabling

A `MasterChannel` won't start communicating until you call the `enable` method. This gives you the opportunity to configure all the associations on the channel, as discussed in the next section. You can also `disable` the channel to put it in an inactive state.
A `MasterChannel` won't communicate until you call `enable`. This lets you configure all associations first. Call `disable` to put the channel in an inactive state.

## LinkErrorMode

Expand All @@ -74,8 +73,7 @@ close the connection. However, you can treat a TCP channel like a serial port by

## EndpointList

An `EndpointList` is a list of remote endpoints that the master will try to connect to. It must contain at least one entry, with the option to include additional backup
addresses. The channel will round-robin through this list until it establishes a connection. The list may contain endpoints consisting of a `<host>:<port>` tuple where "host" is one of the following:
An `EndpointList` contains remote endpoints the master will try to connect to. It must have at least one entry; additional entries serve as backups. The channel round-robins through the list until connected. Each endpoint is a `<host>:<port>` tuple where "host" is:

* IPv4 address
* IPv6 address
Expand Down
5 changes: 2 additions & 3 deletions guide/docs/api/master/terminology.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,11 @@ slug: /api/master/terminology
import Tabs from '@theme/Tabs';
import TabItem from '@theme/TabItem';

Master stations typically communicate with multiple outstations over multiple communication channels. We'll describe in the following sections how you can create different channel types, each of which can be used to talk to multiple outstations on the channel.
Master stations communicate with multiple outstations over multiple communication channels. The following sections describe how to create different channel types, each supporting multiple outstations.

## MasterChannel

You can create a `MasterChannel` using generic configuration combined with transport-specific options. Once created, all channel instances have the same API,
regardless of the underlying transport.
Create a `MasterChannel` using generic configuration combined with transport-specific options. All channel instances have the same API regardless of the underlying transport.

## Association

Expand Down
Loading