Skip to content

Commit

Permalink
Merge pull request #3084 from kefeimo/dnp3-driver-pr
Browse files Browse the repository at this point in the history
Dnp3 driver pr
  • Loading branch information
craig8 authored Aug 17, 2023
2 parents e1f52ca + 793ca15 commit 811bacf
Show file tree
Hide file tree
Showing 20 changed files with 2,559 additions and 52 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@
from datetime import datetime, timedelta
import logging

from . import BaseInterface, BaseRegister, BasicRevert
from services.core.PlatformDriverAgent.platform_driver.interfaces import BaseInterface, BaseRegister, BasicRevert

_log = logging.getLogger(__name__)
type_mapping = {"string": str,
Expand Down
89 changes: 89 additions & 0 deletions deprecated/OldDnp3/OldDnp3Driver/dnp3-driver.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
.. _DNP3-Driver:

===========
DNP3 Driver
===========

VOLTTRON's DNP3 driver enables the use of `DNP3 <https://en.wikipedia.org/wiki/DNP3>`_ (Distributed Network Protocol)
communications, reading and writing points via a DNP3 Outstation.

In order to use a DNP3 driver to read and write point data, VOLTTRON's DNP3 Agent must also
be configured and running. All communication between the VOLTTRON Outstation and a
DNP3 Master happens through the DNP3 Agent.

For information about the DNP3 Agent, please see the :ref:`DNP3 Platform Specification <DNP3-Agent>`.


Requirements
============

The DNP3 driver requires the PyDNP3 package. This package can be installed in an activated environment with:

.. code-block:: bash
pip install pydnp3
Driver Configuration
====================

There is one argument for the "driver_config" section of the DNP3 driver configuration file:

- **dnp3_agent_id** - ID of VOLTTRON's DNP3Agent.

Here is a sample DNP3 driver configuration file:

.. code-block:: json
{
"driver_config": {
"dnp3_agent_id": "dnp3agent"
},
"campus": "campus",
"building": "building",
"unit": "dnp3",
"driver_type": "dnp3",
"registry_config": "config://dnp3.csv",
"interval": 15,
"timezone": "US/Pacific",
"heart_beat_point": "Heartbeat"
}
A sample DNP3 driver configuration file can be found in the VOLTTRON repository
in ``services/core/PlatformDriverAgent/example_configurations/test_dnp3.config``.


DNP3 Registry Configuration File
================================

The driver's registry configuration file, a `CSV <https://en.wikipedia.org/wiki/Comma-separated_values>`_ file,
specifies which DNP3 points the driver will read and/or write. Each row configures a single DNP3 point.

The following columns are required for each row:

- **Volttron Point Name** - The name used by the VOLTTRON platform and agents to refer to the point.
- **Group** - The point's DNP3 group number.
- **Index** - The point's index number within its DNP3 data type (which is derived from its DNP3 group number).
- **Scaling** - A factor by which to multiply point values.
- **Units** - Point value units.
- **Writable** - TRUE or FALSE, indicating whether the point can be written by the driver (FALSE = read-only).

Consult the **DNP3 data dictionary** for a point's Group and Index values. Point
definitions in the data dictionary are by agreement between the DNP3 Outstation and Master.
The VOLTTRON DNP3Agent loads the data dictionary of point definitions from the JSON file
at "point_definitions_path" in the DNP3Agent's config file.

A sample data dictionary is available in ``services/core/DNP3Agent/dnp3/mesa_points.config``.

Point definitions in the DNP3 driver's registry should look something like this:

.. csv-table:: DNP3
:header: Volttron Point Name,Group,Index,Scaling,Units,Writable

DCHD.WTgt,41,65,1.0,NA,FALSE
DCHD.WTgt-In,30,90,1.0,NA,TRUE
DCHD.WinTms,41,66,1.0,NA,FALSE
DCHD.RmpTms,41,67,1.0,NA,FALSE

A sample DNP3 driver registry configuration file is available
in ``services/core/PlatformDriverAgent/example_configurations/dnp3.csv``.
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
Volttron Point Name,Group,Index,Scaling,Units,Writable
DCHD.WTgt,41,65,1.0,NA,FALSE
DCHD.WTgt-In,30,90,1.0,NA,TRUE
DCHD.WinTms,41,66,1.0,NA,FALSE
DCHD.RmpTms,41,67,1.0,NA,FALSE
DCHD.RevtTms,41,68,1.0,NA,FALSE
DCHD.RmpUpRte,41,69,1.0,NA,FALSE
DCHD.RmpDnRte,41,70,1.0,NA,FALSE
DCHD.ChaRmpUpRte,41,71,1.0,NA,FALSE
DCHD.ChaRmpDnRte,41,72,1.0,NA,FALSE
DCHD.ModPrty,41,9,1.0,NA,FALSE
DCHD.VArAct,41,10,1.0,NA,FALSE
DCHD.ModEna,12,5,1.0,NA,FALSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
{
"driver_config": {
"dnp3_agent_id": "dnp3agent"
},
"campus": "campus",
"building": "building",
"unit": "dnp3",
"driver_type": "dnp3",
"registry_config": "config://dnp3.csv",
"interval": 15,
"timezone": "US/Pacific",
"heart_beat_point": "Heartbeat"
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,42 @@ DNP3 Driver
VOLTTRON's DNP3 driver enables the use of `DNP3 <https://en.wikipedia.org/wiki/DNP3>`_ (Distributed Network Protocol)
communications, reading and writing points via a DNP3 Outstation.

In order to use a DNP3 driver to read and write point data, VOLTTRON's DNP3 Agent must also
be configured and running. All communication between the VOLTTRON Outstation and a
DNP3 Master happens through the DNP3 Agent.

For information about the DNP3 Agent, please see the :ref:`DNP3 Platform Specification <DNP3-Agent>`.

In order to use a DNP3 driver to read and write point data, a server component (i.e., Outstation) must also
be configured and running.

Requirements
============

The DNP3 driver requires the PyDNP3 package. This package can be installed in an activated environment with:
The DNP3 driver requires the `dnp3-python <https://github.com/VOLTTRON/dnp3-python>`_ package, a wrapper on Pydnp3 package.
This package can be installed in an activated environment with:

.. code-block:: bash
pip install pydnp3
pip install dnp3-python
Driver Configuration
====================

There is one argument for the "driver_config" section of the DNP3 driver configuration file:

- **dnp3_agent_id** - ID of VOLTTRON's DNP3Agent.

Here is a sample DNP3 driver configuration file:

.. code-block:: json
{
"driver_config": {
"dnp3_agent_id": "dnp3agent"
},
"campus": "campus",
"building": "building",
"unit": "dnp3",
"driver_type": "dnp3",
"registry_config": "config://dnp3.csv",
"interval": 15,
"timezone": "US/Pacific",
"heart_beat_point": "Heartbeat"
"driver_config": {"master_ip": "0.0.0.0", "outstation_ip": "127.0.0.1",
"master_id": 2, "outstation_id": 1,
"port": 20000},
"registry_config":"config://udd-Dnp3.csv",
"driver_type": "udd_dnp3",
"interval": 5,
"timezone": "UTC",
"campus": "campus-vm",
"building": "building-vm",
"unit": "Dnp3",
"publish_depth_first_all": true,
"heart_beat_point": "random_bool"
}
A sample DNP3 driver configuration file can be found in the VOLTTRON repository
Expand All @@ -63,6 +59,7 @@ The following columns are required for each row:

- **Volttron Point Name** - The name used by the VOLTTRON platform and agents to refer to the point.
- **Group** - The point's DNP3 group number.
- **Variation** - THe permit negotiated exchange of data formatted, i.e., data type.
- **Index** - The point's index number within its DNP3 data type (which is derived from its DNP3 group number).
- **Scaling** - A factor by which to multiply point values.
- **Units** - Point value units.
Expand All @@ -78,12 +75,16 @@ A sample data dictionary is available in ``services/core/DNP3Agent/dnp3/mesa_poi
Point definitions in the DNP3 driver's registry should look something like this:

.. csv-table:: DNP3
:header: Volttron Point Name,Group,Index,Scaling,Units,Writable
:header: Point Name,Volttron Point Name,Group,Variation,Index,Scaling,Units,Writable,Notes

AnalogInput_index0,AnalogInput_index0,30,6,0,1,NA,FALSE,Double Analogue input without status
BinaryInput_index0,BinaryInput_index0,1,2,0,1,NA,FALSE,Single bit binary input with status
AnalogOutput_index0,AnalogOutput_index0,40,4,0,1,NA,TRUE,Double-precision floating point with flags
BinaryOutput_index0,BinaryOutput_index0,10,2,0,1,NA,TRUE,Binary Output with flags

DCHD.WTgt,41,65,1.0,NA,FALSE
DCHD.WTgt-In,30,90,1.0,NA,TRUE
DCHD.WinTms,41,66,1.0,NA,FALSE
DCHD.RmpTms,41,67,1.0,NA,FALSE

A sample DNP3 driver registry configuration file is available
in ``services/core/PlatformDriverAgent/example_configurations/dnp3.csv``.

For more information about Group Variation definition, please refer to `dnp3.Variation
<https://docs.stepfunc.io/dnp3/0.9.0/dotnet/namespacednp3.html#a467a3b6f7d543e90374b39c8088cadfbaff335165a793b52dafbd928a8864f607>`_.
30 changes: 17 additions & 13 deletions examples/configurations/drivers/dnp3.csv
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
Volttron Point Name,Group,Index,Scaling,Units,Writable
DCHD.WTgt,41,65,1.0,NA,FALSE
DCHD.WTgt-In,30,90,1.0,NA,TRUE
DCHD.WinTms,41,66,1.0,NA,FALSE
DCHD.RmpTms,41,67,1.0,NA,FALSE
DCHD.RevtTms,41,68,1.0,NA,FALSE
DCHD.RmpUpRte,41,69,1.0,NA,FALSE
DCHD.RmpDnRte,41,70,1.0,NA,FALSE
DCHD.ChaRmpUpRte,41,71,1.0,NA,FALSE
DCHD.ChaRmpDnRte,41,72,1.0,NA,FALSE
DCHD.ModPrty,41,9,1.0,NA,FALSE
DCHD.VArAct,41,10,1.0,NA,FALSE
DCHD.ModEna,12,5,1.0,NA,FALSE
Point Name,Volttron Point Name,Group,Variation,Index,Scaling,Units,Writable,Notes
AnalogInput_index0,AnalogInput_index0,30,6,0,1,NA,FALSE,Double Analogue input without status
AnalogInput_index1,AnalogInput_index1,30,6,1,1,NA,FALSE,Double Analogue input without status
AnalogInput_index2,AnalogInput_index2,30,6,2,1,NA,FALSE,Double Analogue input without status
AnalogInput_index3,AnalogInput_index3,30,6,3,1,NA,FALSE,Double Analogue input without status
BinaryInput_index0,BinaryInput_index0,1,2,0,1,NA,FALSE,Single bit binary input with status
BinaryInput_index1,BinaryInput_index1,1,2,1,1,NA,FALSE,Single bit binary input with status
BinaryInput_index2,BinaryInput_index2,1,2,2,1,NA,FALSE,Single bit binary input with status
BinaryInput_index3,BinaryInput_index3,1,2,3,1,NA,FALSE,Single bit binary input with status
AnalogOutput_index0,AnalogOutput_index0,40,4,0,1,NA,TRUE,Double-precision floating point with flags
AnalogOutput_index1,AnalogOutput_index1,40,4,1,1,NA,TRUE,Double-precision floating point with flags
AnalogOutput_index2,AnalogOutput_index2,40,4,2,1,NA,TRUE,Double-precision floating point with flags
AnalogOutput_index3,AnalogOutput_index3,40,4,3,1,NA,TRUE,Double-precision floating point with flags
BinaryOutput_index0,BinaryOutput_index0,10,2,0,1,NA,TRUE,Binary Output with flags
BinaryOutput_index1,BinaryOutput_index1,10,2,1,1,NA,TRUE,Binary Output with flags
BinaryOutput_index2,BinaryOutput_index2,10,2,2,1,NA,TRUE,Binary Output with flags
BinaryOutput_index3,BinaryOutput_index3,10,2,3,1,NA,TRUE,Binary Output with flags
25 changes: 13 additions & 12 deletions examples/configurations/drivers/test_dnp3.config
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
{
"driver_config": {
"dnp3_agent_id": "dnp3agent"
},
"campus": "campus",
"building": "building",
"unit": "dnp3",
"driver_type": "dnp3",
"registry_config": "config://dnp3.csv",
"interval": 15,
"timezone": "US/Pacific",
"heart_beat_point": "Heartbeat"
}
"driver_config": {"master_ip": "0.0.0.0", "outstation_ip": "127.0.0.1",
"master_id": 2, "outstation_id": 1,
"port": 20000},
"registry_config":"config://udd-Dnp3.csv",
"driver_type": "udd_dnp3",
"interval": 5,
"timezone": "UTC",
"campus": "campus-vm",
"building": "building-vm",
"unit": "Dnp3",
"publish_depth_first_all": true,
"heart_beat_point": "random_bool"
}
41 changes: 41 additions & 0 deletions scripts/dnp3/get_point_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
"""
A demo to test dnp3-driver get_point method using rpc call.
Pre-requisite:
- install platform-driver
- configure dnp3-driver
- a dnp3 outstation/server is up and running
- platform-driver is up and running
"""

import random
from volttron.platform.vip.agent.utils import build_agent
from time import sleep
import datetime


def main():
a = build_agent()
while True:
sleep(5)
print("============")
try:
rpc_method = "get_point"
device_name = "campus-vm/building-vm/Dnp3"

reg_pt_name = "AnalogInput_index0"
rs = a.vip.rpc.call("platform.driver", rpc_method,
device_name,
reg_pt_name).get(timeout=10)
print(datetime.datetime.now(), "point_name: ", reg_pt_name, "value: ", rs)
reg_pt_name = "AnalogInput_index1"
rs = a.vip.rpc.call("platform.driver", rpc_method,
device_name,
reg_pt_name).get(timeout=10)
print(datetime.datetime.now(), "point_name: ", reg_pt_name, "value: ", rs)
except Exception as e:
print(e)


if __name__ == "__main__":
main()
52 changes: 52 additions & 0 deletions scripts/dnp3/set_point_demo.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
"""
A demo to test dnp3-driver set_point method using rpc call.
Pre-requisite:
- install platform-driver
- configure dnp3-driver
- a dnp3 outstation/server is up and running
- platform-driver is up and running
"""

import random
from volttron.platform.vip.agent.utils import build_agent
from time import sleep
import datetime


def main():
a = build_agent()
while True:
sleep(5)
print("============")
try:
rpc_method = "set_point"
device_name = "campus-vm/building-vm/Dnp3"

for i in range(3):
reg_pt_name = "AnalogOutput_index" + str(i)
val_to_set = random.random()
rs = a.vip.rpc.call("platform.driver", rpc_method,
device_name,
reg_pt_name,
val_to_set).get(timeout=10)
print(datetime.datetime.now(), "point_name: ", reg_pt_name, "response: ", rs)

# verify
sleep(1)

for i in range(3):
rpc_method = "get_point"
reg_pt_name = "AnalogOutput_index" + str(i)
# val_to_set = random.random()
rs = a.vip.rpc.call("platform.driver", rpc_method,
device_name,
reg_pt_name
).get(timeout=10)
print(datetime.datetime.now(), "point_name: ", reg_pt_name, "response: ", rs)
except Exception as e:
print(e)


if __name__ == "__main__":
main()
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
from .dnp3 import *
Loading

0 comments on commit 811bacf

Please sign in to comment.