From aeccc6cec690020daa9fbc87469d6920bf52a9a9 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 28 Aug 2023 13:21:18 -0700 Subject: [PATCH 01/36] Updated RabbitMQ version to 3.9.29 and Erlang to version 25 --- README.md | 50 +++--- ci-integration/run-tests.sh | 2 +- ci-integration/virtualization/Dockerfile | 4 +- .../multi-platform-multi-bus.rst | 12 +- docs/source/introduction/platform-install.rst | 50 +++--- .../rabbitmq/rabbitmq-ssl-auth.rst | 6 +- .../rabbitmq/rabbitmq-volttron.rst | 4 +- .../rabbitmq/rabbitmq_config.yml | 4 +- scripts/rabbit_dependencies.sh | 157 ------------------ volttron/platform/instance_setup.py | 15 -- volttron/platform/web/platform_web_service.py | 2 +- volttron/utils/rmq_config_params.py | 4 +- volttron/utils/rmq_setup.py | 4 +- volttrontesting/fixtures/rmq_test_setup.py | 2 +- volttrontesting/platform/web/test_certs.py | 4 +- 15 files changed, 68 insertions(+), 252 deletions(-) delete mode 100755 scripts/rabbit_dependencies.sh diff --git a/README.md b/README.md index 7f888a3744..18ed6519c8 100644 --- a/README.md +++ b/README.md @@ -113,37 +113,31 @@ You can deactivate the environment at any time by running `deactivate`. #### Steps for RabbitMQ -##### 1. Install Erlang version 24 packages +##### 1. Install Erlang version 25 packages -For RabbitMQ based VOLTTRON, some RabbitMQ specific software packages must be installed. - -###### On Debian based systems and CentOS 6/7 - -If you are running an Debian or CentOS system, you can install the RabbitMQ dependencies by running the rabbit - dependencies script, passing in the OS name and appropriate distribution as parameters. The following are supported: - -- `debian focal` (for Ubuntu 20.04) - -- `debian bionic` (for Ubuntu 18.04) - -- `debian stretch` (for Debian Stretch) +###### Install Erlang pre-requisites +```shell +sudo apt-get update +sudo apt-get install -y gnupg apt-transport-https libsctp1 +``` -- `debian buster` (for Debian Buster) +###### Purge previous versions of Erlang +```shell +sudo apt-get purge -yf erlang-base +``` -- `raspbian buster` (for Raspbian/Raspberry Pi OS buster) +###### Install Erlang -Example command: +Download and install ErlangOTP from [Erlang Solutions](https://www.erlang-solutions.com/downloads/). +RMQ uses components - ssl, public_key, asn1, and crypto. These are by default included in the OTP +RabbitMQ 3.9.29 is compatible with Erlang versions 24.3.4.2 to 25.2. VOLTTRON was tested with Erlang version 25.2-1 -```sh -./scripts/rabbit_dependencies.sh debian xenial +Example: +```shell +wget https://binaries2.erlang-solutions.com/ubuntu/pool/contrib/e/esl-erlang/esl-erlang_25.2-1~ubuntu~jammy_amd64.deb +sudo dpkg -i esl-erlang_25.2-1~ubuntu~jammy_amd64.deb ``` -###### Alternatively - -You can download and install Erlang from [Erlang Solutions](https://www.erlang-solutions.com/resources/download.html). -Please include OTP/components - ssl, public_key, asn1, and crypto. -Also lock your version of Erlang using the [yum-plugin-versionlock](https://access.redhat.com/solutions/98873) - ##### 2. Configure hostname Make sure that your hostname is correctly configured in /etc/hosts (See [this StackOverflow Post](https://stackoverflow.com/questions/24797947/os-x-and-rabbitmq-error-epmd-error-for-host-xxx-address-cannot-connect-to-ho)). @@ -175,7 +169,7 @@ it needs to be set to the RabbitMQ installation directory (default path is `/rabbitmq_server/rabbitmq_server-`) ```sh -echo 'export RABBITMQ_HOME=$HOME/rabbitmq_server/rabbitmq_server-3.9.7'|sudo tee --append ~/.bashrc +echo 'export RABBITMQ_HOME=$HOME/rabbitmq_server/rabbitmq_server-3.9.29'|sudo tee --append ~/.bashrc source ~/.bashrc $RABBITMQ_HOME/sbin/rabbitmqctl status @@ -232,7 +226,7 @@ Your VOLTTRON_HOME currently set to: /home/vdev/new_vhome2 Is this the volttron you are attempting to setup? [Y]: Creating rmq config yml -RabbitMQ server home: [/home/vdev/rabbitmq_server/rabbitmq_server-3.9.7]: +RabbitMQ server home: [/home/vdev/rabbitmq_server/rabbitmq_server-3.9.29]: Fully qualified domain name of the system: [cs_cbox.pnl.gov]: Enable SSL Authentication: [Y]: @@ -252,7 +246,7 @@ AMQPS (SSL) port RabbitMQ address: [5671]: https port for the RabbitMQ management plugin: [15671]: INFO:rmq_setup.pyc:Starting rabbitmq server Warning: PID file not written; -detached was passed. -INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.7 +INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.29 INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost @@ -266,7 +260,7 @@ INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost INFO:rmq_setup.pyc:**Stopped rmq server Warning: PID file not written; -detached was passed. -INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.7 +INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.29 INFO:rmq_setup.pyc: ####################### diff --git a/ci-integration/run-tests.sh b/ci-integration/run-tests.sh index 9266b0b883..26b83297e9 100755 --- a/ci-integration/run-tests.sh +++ b/ci-integration/run-tests.sh @@ -46,7 +46,7 @@ echo "bootstrapping RABBITMQ" python bootstrap.py --rabbitmq --market echo "rabbitmq status" -"$HOME/rabbitmq_server/rabbitmq_server-3.9.7/sbin/rabbitmqctl" status +"$HOME/rabbitmq_server/rabbitmq_server-3.9.29/sbin/rabbitmqctl" status echo "TestDirs" for dir in $testdirs; do diff --git a/ci-integration/virtualization/Dockerfile b/ci-integration/virtualization/Dockerfile index 58346d044b..18af962aac 100644 --- a/ci-integration/virtualization/Dockerfile +++ b/ci-integration/virtualization/Dockerfile @@ -31,8 +31,8 @@ RUN chmod +x /startup/entrypoint.sh && \ USER $VOLTTRON_USER RUN mkdir $RMQ_ROOT RUN set -eux \ - && wget -P $VOLTTRON_USER_HOME https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.7/rabbitmq-server-generic-unix-3.9.7.tar.xz \ - && tar -xf $VOLTTRON_USER_HOME/rabbitmq-server-generic-unix-3.9.7.tar.xz --directory $RMQ_ROOT \ + && wget -P $VOLTTRON_USER_HOME https://github.com/rabbitmq/rabbitmq-server/releases/download/v3.9.29/rabbitmq-server-generic-unix-3.9.29.tar.xz \ + && tar -xf $VOLTTRON_USER_HOME/rabbitmq-server-generic-unix-3.9.29.tar.xz --directory $RMQ_ROOT \ && $RMQ_HOME/sbin/rabbitmq-plugins enable rabbitmq_management rabbitmq_federation rabbitmq_federation_management rabbitmq_shovel rabbitmq_shovel_management rabbitmq_auth_mechanism_ssl rabbitmq_trust_store RUN python3 -m pip install gevent-pika --user ############################################ diff --git a/docs/source/deploying-volttron/multi-platform/multi-platform-multi-bus.rst b/docs/source/deploying-volttron/multi-platform/multi-platform-multi-bus.rst index e58f9ed497..e01563c1c6 100644 --- a/docs/source/deploying-volttron/multi-platform/multi-platform-multi-bus.rst +++ b/docs/source/deploying-volttron/multi-platform/multi-platform-multi-bus.rst @@ -83,7 +83,7 @@ Platform agent, SQL historian agent and a Listener agent. The following shows an Is this the volttron you are attempting to setup? [Y]: What type of message bus (rmq/zmq)? [zmq]: rmq Name of this volttron instance: [volttron1]: central - RabbitMQ server home: [/home/user/rabbitmq_server/rabbitmq_server-3.9.7]: + RabbitMQ server home: [/home/user/rabbitmq_server/rabbitmq_server-3.9.29]: Fully qualified domain name of the system: [central]: Would you like to create a new self signed root CAcertificate for this instance: [Y]: @@ -95,7 +95,7 @@ Platform agent, SQL historian agent and a Listener agent. The following shows an Organization Unit: volttron Do you want to use default values for RabbitMQ home, ports, and virtual host: [Y]: 2020-04-13 13:29:36,347 rmq_setup.py INFO: Starting RabbitMQ server - 2020-04-13 13:29:46,528 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.7 is running at + 2020-04-13 13:29:46,528 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.29 is running at 2020-04-13 13:29:46,554 volttron.utils.rmq_mgmt DEBUG: Creating new VIRTUAL HOST: volttron 2020-04-13 13:29:46,582 volttron.utils.rmq_mgmt DEBUG: Create READ, WRITE and CONFIGURE permissions for the user: central-admin Create new exchange: volttron, {'durable': True, 'type': 'topic', 'arguments': {'alternate-exchange': 'undeliverable'}} @@ -108,7 +108,7 @@ Platform agent, SQL historian agent and a Listener agent. The following shows an 2020-04-13 13:29:46,601 rmq_setup.py INFO: Creating root ca with the following info: {'C': 'US', 'ST': 'WA', 'L': 'Richland', 'O': 'PNNL', 'OU': 'VOLTTRON', 'CN': 'central-root-ca'} Created CA cert 2020-04-13 13:29:49,668 rmq_setup.py INFO: **Stopped rmq server - 2020-04-13 13:30:00,556 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.7 is running at + 2020-04-13 13:30:00,556 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.29 is running at 2020-04-13 13:30:00,557 rmq_setup.py INFO: ####################### @@ -443,7 +443,7 @@ name is set to "collector2". Is this the volttron you are attempting to setup? [Y]: What type of message bus (rmq/zmq)? [zmq]: rmq Name of this volttron instance: [volttron1]: collector2 - RabbitMQ server home: [/home/user/rabbitmq_server/rabbitmq_server-3.9.7]: + RabbitMQ server home: [/home/user/rabbitmq_server/rabbitmq_server-3.9.29]: Fully qualified domain name of the system: [node-rmq]: Would you like to create a new self signed root CA certificate for this instance: [Y]: @@ -455,7 +455,7 @@ name is set to "collector2". Organization Unit: volttron Do you want to use default values for RabbitMQ home, ports, and virtual host: [Y]: 2020-04-13 13:29:36,347 rmq_setup.py INFO: Starting RabbitMQ server - 2020-04-13 13:29:46,528 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.7 is running at + 2020-04-13 13:29:46,528 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.29 is running at 2020-04-13 13:29:46,554 volttron.utils.rmq_mgmt DEBUG: Creating new VIRTUAL HOST: volttron 2020-04-13 13:29:46,582 volttron.utils.rmq_mgmt DEBUG: Create READ, WRITE and CONFIGURE permissions for the user: collector2-admin Create new exchange: volttron, {'durable': True, 'type': 'topic', 'arguments': {'alternate-exchange': 'undeliverable'}} @@ -468,7 +468,7 @@ name is set to "collector2". 2020-04-13 13:29:46,601 rmq_setup.py INFO: Creating root ca with the following info: {'C': 'US', 'ST': 'WA', 'L': 'Richland', 'O': 'PNNL', 'OU': 'VOLTTRON', 'CN': 'collector2-root-ca'} Created CA cert 2020-04-13 13:29:49,668 rmq_setup.py INFO: **Stopped rmq server - 2020-04-13 13:30:00,556 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.7 is running at + 2020-04-13 13:30:00,556 rmq_setup.py INFO: Rmq server at /home/user/rabbitmq_server/rabbitmq_server-3.9.29 is running at 2020-04-13 13:30:00,557 rmq_setup.py INFO: ####################### diff --git a/docs/source/introduction/platform-install.rst b/docs/source/introduction/platform-install.rst index c17e1f0d74..f772cc4433 100644 --- a/docs/source/introduction/platform-install.rst +++ b/docs/source/introduction/platform-install.rst @@ -194,37 +194,31 @@ Step 2 - Install Erlang packages For RabbitMQ based VOLTTRON, some of the RabbitMQ specific software packages have to be installed. +Install Erlang pre-requisites ++++++++++++++++++++++++++++++ +.. code-block:: bash + sudo apt-get update + sudo apt-get install -y gnupg apt-transport-https libsctp1 -On Debian based systems and CentOS 8 -"""""""""""""""""""""""""""""""""""" - -If you are running a Debian or CentOS 8 system, you can install the RabbitMQ dependencies by running the -"rabbit_dependencies.sh" script, passing in the OS name and appropriate distribution as parameters. The -following are supported: - -* `debian bionic` (for Ubuntu 18.04) - -* `debian focal` (for Ubuntu 20.04) - - -Example command: +Purge previous versions of Erlang ++++++++++++++++++++++++++++++++++ .. code-block:: bash - ./scripts/rabbit_dependencies.sh debian xenial + sudo apt-get purge -yf erlang-base +Install Erlang +++++++++++++++ -Alternatively -""""""""""""" +Download and install ErlangOTP from [Erlang Solutions](https://www.erlang-solutions.com/downloads/). +RMQ uses components - ssl, public_key, asn1, and crypto. These are by default included in the OTP +RabbitMQ 3.9.29 is compatible with Erlang versions 24.3.4.2 to 25.2. VOLTTRON was tested with Erlang version 25.2-1 -You can download and install Erlang from `Erlang Solutions `_. -Please include OTP/components - ssl, public_key, asn1, and crypto. -Also lock your version of Erlang using the `yum-plugin-versionlock `_. +Example: +.. code-block:: bash -.. note:: - Currently VOLTTRON only officially supports specific versions of Erlang for each operating system: - * 1:24.1.7-1 for Debian - * 24.2-1.el8 for CentOS 8 + wget https://binaries2.erlang-solutions.com/ubuntu/pool/contrib/e/esl-erlang/esl-erlang_25.2-1~ubuntu~jammy_amd64.deb + sudo dpkg -i esl-erlang_25.2-1~ubuntu~jammy_amd64.deb Step 3 - Configure hostname @@ -272,11 +266,11 @@ Thus, you can use $RABBITMQ_HOME to see if the RabbitMQ server is installed by c .. note:: The `RABBITMQ_HOME` environment variable can be set in ~/.bashrc. If doing so, it needs to be set to the RabbitMQ - installation directory (default path is `/rabbitmq_server/rabbitmq_server-3.9.7`) + installation directory (default path is `/rabbitmq_server/rabbitmq_server-3.9.29`) .. code-block:: bash - echo 'export RABBITMQ_HOME=$HOME/rabbitmq_server/rabbitmq_server-3.9.7'|sudo tee --append ~/.bashrc + echo 'export RABBITMQ_HOME=$HOME/rabbitmq_server/rabbitmq_server-3.9.29'|sudo tee --append ~/.bashrc source ~/.bashrc $RABBITMQ_HOME/sbin/rabbitmqctl status @@ -334,7 +328,7 @@ prompts for necessary details. Is this the volttron you are attempting to setup? [Y]: Creating rmq config yml - RabbitMQ server home: [/home/vdev/rabbitmq_server/rabbitmq_server-3.9.7]: + RabbitMQ server home: [/home/vdev/rabbitmq_server/rabbitmq_server-3.9.29]: Fully qualified domain name of the system: [cs_cbox.pnl.gov]: Enable SSL Authentication: [Y]: @@ -354,7 +348,7 @@ prompts for necessary details. https port for the RabbitMQ management plugin: [15671]: INFO:rmq_setup.pyc:Starting rabbitmq server Warning: PID file not written; -detached was passed. - INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.7 + INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.29 INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost @@ -368,7 +362,7 @@ prompts for necessary details. INFO:requests.packages.urllib3.connectionpool:Starting new HTTP connection (1): localhost INFO:rmq_setup.pyc:**Stopped rmq server Warning: PID file not written; -detached was passed. - INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.7 + INFO:rmq_setup.pyc:**Started rmq server at /home/vdev/rabbitmq_server/rabbitmq_server-3.9.29 INFO:rmq_setup.pyc: ####################### diff --git a/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-ssl-auth.rst b/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-ssl-auth.rst index 5549b6beaf..37fc7efdc3 100644 --- a/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-ssl-auth.rst +++ b/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-ssl-auth.rst @@ -14,7 +14,7 @@ configurations can be seen by running the following command: .. code-block:: bash - cat ~/rabbitmq_server/rabbitmq_server-3.9.7/etc/rabbitmq/rabbitmq.conf + cat ~/rabbitmq_server/rabbitmq_server-3.9.29/etc/rabbitmq/rabbitmq.conf The configurations required to enable SSL: @@ -78,8 +78,8 @@ To configure RabbitMQ-VOLTTRON to use SSL based authentication, we need to add S # defaults to true ssl: 'true' - # defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.7 - rmq-home: "~/rabbitmq_server/rabbitmq_server-3.9.7" + # defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.29 + rmq-home: "~/rabbitmq_server/rabbitmq_server-3.9.29" The parameters of interest for SSL based configuration are diff --git a/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-volttron.rst b/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-volttron.rst index 249b382cd7..5d29152ee1 100644 --- a/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-volttron.rst +++ b/docs/source/platform-features/message-bus/rabbitmq/rabbitmq-volttron.rst @@ -56,8 +56,8 @@ Path: `$VOLTTRON_HOME/rabbitmq_config.yml` # defaults to true ssl: 'true' - # defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.7 - rmq-home: "~/rabbitmq_server/rabbitmq_server-3.9.7" + # defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.29 + rmq-home: "~/rabbitmq_server/rabbitmq_server-3.9.29" Each VOLTTRON instance resides within a RabbitMQ virtual host. The name of the virtual host needs to be unique per VOLTTRON instance if there are multiple virtual instances within a single host/machine. The hostname needs to be able diff --git a/examples/configurations/rabbitmq/rabbitmq_config.yml b/examples/configurations/rabbitmq/rabbitmq_config.yml index e6bf802fdc..e34a3a97bc 100644 --- a/examples/configurations/rabbitmq/rabbitmq_config.yml +++ b/examples/configurations/rabbitmq/rabbitmq_config.yml @@ -48,8 +48,8 @@ ssl: true #use-existing-certs: True -# defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.7 -rmq-home: ~/rabbitmq_server/rabbitmq_server-3.9.7 +# defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.29 +rmq-home: ~/rabbitmq_server/rabbitmq_server-3.9.29 # RabbitMQ reconnect retry delay (in seconds) reconnect-delay: 30 diff --git a/scripts/rabbit_dependencies.sh b/scripts/rabbit_dependencies.sh deleted file mode 100755 index c14508639c..0000000000 --- a/scripts/rabbit_dependencies.sh +++ /dev/null @@ -1,157 +0,0 @@ -#!/usr/bin/env bash -set -e -ubuntu_list=(bionic focal) -list=(buster ) -list=("${ubuntu_list[@]}" "${debian_list[@]}") -declare -A ubuntu_versions -ubuntu_versions=( ["ubuntu-18.04"]="bionic" ["ubuntu-20.04"]="focal") - -function exit_on_error { - rc=$? - if [[ $rc != 0 ]] - then - printf "\n## Script could not complete successfully because of above error## \n" - exit $rc - fi - -} - -function print_usage { - echo " -Command Usage: -/rabbit_dependencies.sh or centos version> -Valid Debian distributions: ${list[@]} ${!ubuntu_versions[@]} -Valid centos versions: 8 -" - exit 0 - -} - - -function install_on_centos { - - if [[ "$DIST" != "8" ]]; then - printf "Invalid centos version. Centos 8 is the only compatible versions\n" - print_usage - fi - - repo="## In /etc/yum.repos.d/erlang.repo -[erlang-solutions] -name=CentOS $releasever - $basearch - Erlang Solutions -baseurl=https://packages.erlang-solutions.com/rpm/centos/\$releasever/\$basearch -gpgcheck=1 -gpgkey=https://packages.erlang-solutions.com/rpm/erlang_solutions.asc -enabled=1 -" - if [[ -f "/etc/yum.repos.d/erlang.repo" ]]; then - echo "\n/etc/yum.repos.d/erlang.repo exists. renaming current file to rlang.repo.old\n" - mv /etc/yum.repos.d/erlang.repo /etc/yum.repos.d/erlang.repo.old - exit_on_error - fi - echo "$repo" | ${prefix} tee -a /etc/yum.repos.d/erlang.repo - rpm --import https://packages.erlang-solutions.com/rpm/erlang_solutions.asc - ${prefix} yum install -y erlang-$erlang_package_version - exit_on_error -} - -function install_on_debian { - FOUND=0 - OS="" - for item in "${ubuntu_list[@]}"; do - if [[ "$DIST" == "$item" ]]; then - FOUND=1 - OS="ubuntu" - break - fi - done - - if [[ "$FOUND" != "1" ]]; then - for item in "${debian_list[@]}"; do - if [[ "$DIST" == "$item" ]]; then - FOUND=1 - OS="debian" - break - fi - done - fi - - if [[ "$FOUND" != "1" ]]; then - # check if ubuntu-version was passed if so map it to name - for ubuntu_version in "${!ubuntu_versions[@]}"; do - if [[ "$DIST" == "$ubuntu_version" ]]; then - FOUND=1 - DIST="${ubuntu_versions[$ubuntu_version]}" - OS="ubuntu" - break - fi - done - fi - - if [[ "$FOUND" != "1" ]]; then - echo "Invalid distribution found" - print_usage - fi - - echo "Installing ERLANG" - ${prefix} apt-get update - ${prefix} apt-get install -y gnupg apt-transport-https -y - ${prefix} apt-get purge -yf erlang-base - # Adds erlang repository entry - wget https://packages.erlang-solutions.com/erlang-solutions_2.0_all.deb - sudo dpkg -i erlang-solutions_2.0_all.deb - rm erlang-solutions_2.0_all.deb - if [[ -f "/etc/apt/sources.list.d/erlang.list" ]]; then - echo "\n/etc/apt/sources.list.d/erlang.list exists. renaming current file to erlang.list.old\n" - ${prefix} mv /etc/apt/sources.list.d/erlang.list /etc/apt/sources.list.d/erlang.list.old - exit_on_error - fi - version=${erlang_package_version} - to_install="\ - erlang-base=$version\ - erlang-asn1=$version \ - erlang-crypto=$version \ - erlang-eldap=$version \ - erlang-ftp=$version \ - erlang-inets=$version \ - erlang-mnesia=$version \ - erlang-os-mon=$version \ - erlang-parsetools=$version \ - erlang-public-key=$version \ - erlang-runtime-tools=$version \ - erlang-snmp=$version \ - erlang-ssl=$version \ - erlang-syntax-tools=$version \ - erlang-tools=$version \ - erlang-xmerl=$version \ - erlang-tftp=$version \ - " - - ${prefix} apt-get update - ${prefix} apt-get install -y --allow-downgrades ${to_install} -} - -os_name="$1" -DIST="$2" -user=`whoami` -if [[ ${user} == 'root' ]]; then - prefix="" -else - prefix="sudo" -fi -is_arm="FALSE" - -${prefix} pwd > /dev/null - -if [[ "$os_name" == "debian" ]]; then - erlang_package_version="1:24.1.7-1" - is_arm="FALSE" - install_on_debian -elif [[ "$os_name" == "centos" ]]; then - erlang_package_version="24.2-1.el8" - install_on_centos -else - printf "For operating system/distributions not supported by this script, please refer to https://www.rabbitmq.com/which-erlang.html#erlang-repositories\n" - print_usage -fi - -echo "Finished installing dependencies for rabbitmq" diff --git a/volttron/platform/instance_setup.py b/volttron/platform/instance_setup.py index d4212253ee..d8e91a3de1 100644 --- a/volttron/platform/instance_setup.py +++ b/volttron/platform/instance_setup.py @@ -375,15 +375,6 @@ def set_dependencies(requirement): subprocess.check_call(cmds) return - -def set_dependencies_rmq(): - install_rabbit(default_rmq_dir) - prompt = 'What OS are you running?' - user_os = prompt_response(prompt, default='debian') - prompt = 'Which distribution are you running?' - user_dist = prompt_response(prompt, default='bionic') - _cmd(["./scripts/rabbit_dependencies.sh", user_os, user_dist]) - def _create_web_certs(): global config_opts """ @@ -453,12 +444,6 @@ def do_message_bus(): print("Message type is not valid. Valid entries are zmq or rmq.") if bus_type == 'rmq': - if not is_rabbitmq_available(): - print("RabbitMQ has not been set up!") - print("Setting up now...") - set_dependencies_rmq() - print("Done!") - try: check_rmq_setup() except AssertionError: diff --git a/volttron/platform/web/platform_web_service.py b/volttron/platform/web/platform_web_service.py index 50fe254ed9..b2da02e3a4 100644 --- a/volttron/platform/web/platform_web_service.py +++ b/volttron/platform/web/platform_web_service.py @@ -806,7 +806,7 @@ def startupagent(self, sender, **kwargs): # Register VUI endpoints: self._vui_endpoints = VUIEndpoints(self) - _log.debug(f'VUI: adding routes - {self._vui_endpoints.get_routes()}') + #_log.debug(f'VUI: adding routes - {self._vui_endpoints.get_routes()}') self.registeredroutes.extend(self._vui_endpoints.get_routes()) # Allow authentication endpoint from any https connection diff --git a/volttron/utils/rmq_config_params.py b/volttron/utils/rmq_config_params.py index 2e8c247e64..c68b14538d 100644 --- a/volttron/utils/rmq_config_params.py +++ b/volttron/utils/rmq_config_params.py @@ -88,7 +88,7 @@ def __init__(self): with open(os.path.expanduser("~/.volttron_rmq_home")) as f: self.rabbitmq_server = f.read().strip() else: - self.rabbitmq_server = os.path.expanduser("~/rabbitmq_server/rabbitmq_server-3.9.7/") + self.rabbitmq_server = os.path.expanduser("~/rabbitmq_server/rabbitmq_server-3.9.29/") assert os.path.isdir(self.rabbitmq_server), "Missing rabbitmq server directory{}".format(self.rabbitmq_server) from volttron.platform.auth import certs @@ -118,7 +118,7 @@ def _set_default_config(self): self.config_opts.setdefault('reconnect-delay', 30) self.config_opts.setdefault('user', self.instance_name + '-admin') rmq_home = os.path.join(os.path.expanduser("~"), - "rabbitmq_server/rabbitmq_server-3.9.7") + "rabbitmq_server/rabbitmq_server-3.9.29") self.config_opts.setdefault('rabbitmq-service', False) self.config_opts.setdefault("rmq-home", rmq_home) diff --git a/volttron/utils/rmq_setup.py b/volttron/utils/rmq_setup.py index 712971428f..dfb75f5ce0 100644 --- a/volttron/utils/rmq_setup.py +++ b/volttron/utils/rmq_setup.py @@ -90,13 +90,13 @@ def _start_rabbitmq_without_ssl(rmq_config, conf_file, env=None): rmq_home = rmq_config.rmq_home if not rmq_home: rmq_home = os.path.join(os.path.expanduser("~"), - "rabbitmq_server/rabbitmq_server-3.9.7") + "rabbitmq_server/rabbitmq_server-3.9.29") if os.path.exists(rmq_home): os.environ['RABBITMQ_HOME'] = rmq_home else: _log.error("\nMissing key 'rmq_home' in RabbitMQ config and RabbitMQ is " "not installed in default path: \n" - "~/rabbitmq_server/rabbitmq_server-3.9.7 \n" + "~/rabbitmq_server/rabbitmq_server-3.9.29 \n" "Please set the correct RabbitMQ installation path in " "rabbitmq_config.yml") exit(1) diff --git a/volttrontesting/fixtures/rmq_test_setup.py b/volttrontesting/fixtures/rmq_test_setup.py index 464179dfb8..a69a6373b1 100644 --- a/volttrontesting/fixtures/rmq_test_setup.py +++ b/volttrontesting/fixtures/rmq_test_setup.py @@ -34,7 +34,7 @@ def __init__(self): # This is overwritten in the class below during # the create_rmq_volttron_setup function, but is # left here for completeness of the configuration. - 'rmq-home': '~/rabbitmq_server-3.9.7', + 'rmq-home': '~/rabbitmq_server-3.9.29', 'reconnect-delay': 5 } diff --git a/volttrontesting/platform/web/test_certs.py b/volttrontesting/platform/web/test_certs.py index 08e79788a5..f56d91ccf1 100644 --- a/volttrontesting/platform/web/test_certs.py +++ b/volttrontesting/platform/web/test_certs.py @@ -60,8 +60,8 @@ # defaults to true ssl: 'true' -# defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.7 -rmq-home: "~/rabbitmq_server/rabbitmq_server-3.9.7" +# defaults to ~/rabbitmq_server/rabbbitmq_server-3.9.29 +rmq-home: "~/rabbitmq_server/rabbitmq_server-3.9.29" """ From a917d21c1ddd6a1359ad8ac2aca6e9de6e866a24 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 28 Aug 2023 14:47:04 -0700 Subject: [PATCH 02/36] Updated RabbitMQ version to 3.9.29 and Erlang to version 25 --- bootstrap.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bootstrap.py b/bootstrap.py index 285a8c52ca..a20364c355 100644 --- a/bootstrap.py +++ b/bootstrap.py @@ -86,7 +86,7 @@ _WINDOWS = sys.platform.startswith('win') default_rmq_dir = os.path.join(os.path.expanduser("~"), "rabbitmq_server") -rmq_version = "3.9.7" +rmq_version = "3.9.29" rabbitmq_server = f"rabbitmq_server-{rmq_version}" From 07319407a6e3eb9233702772a93105cec4e19db8 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Wed, 30 Aug 2023 15:16:39 -0700 Subject: [PATCH 03/36] Fix for issue #3114. update dependency information --- services/core/DNP3Agent/README.md | 4 ++-- services/core/DNP3Agent/requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/core/DNP3Agent/README.md b/services/core/DNP3Agent/README.md index 3cf6162e19..2b092015af 100644 --- a/services/core/DNP3Agent/README.md +++ b/services/core/DNP3Agent/README.md @@ -7,9 +7,9 @@ DNP3 and MESA specifications, located in VOLTTRON readthedocs under http://volttron.readthedocs.io/en/develop/specifications/dnp3_agent.html and http://volttron.readthedocs.io/en/develop/specifications/mesa_agent.html. -These agents depend on the pydnp3 library, which must be installed in the VOLTTRON virtual environment: +These agents depend on the dnp3-python==0.2.3b3 library, which must be installed in the VOLTTRON virtual environment: - (volttron) $ pip install pydnp3 + (volttron) $ pip install dnp3-python==0.2.3b3 Installing MesaAgent -------------------- diff --git a/services/core/DNP3Agent/requirements.txt b/services/core/DNP3Agent/requirements.txt index 9647f44d1e..2a3adaaaae 100644 --- a/services/core/DNP3Agent/requirements.txt +++ b/services/core/DNP3Agent/requirements.txt @@ -1 +1 @@ -pydnp3==0.1.0 +dnp3-python==0.2.3b3 From fbc86ee0efee47ce26a20c7c17f050335e0ed800 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Wed, 30 Aug 2023 15:22:22 -0700 Subject: [PATCH 04/36] Revert "Fix for issue #3114. update dependency information" This reverts commit 07319407a6e3eb9233702772a93105cec4e19db8. --- services/core/DNP3Agent/README.md | 4 ++-- services/core/DNP3Agent/requirements.txt | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/services/core/DNP3Agent/README.md b/services/core/DNP3Agent/README.md index 2b092015af..3cf6162e19 100644 --- a/services/core/DNP3Agent/README.md +++ b/services/core/DNP3Agent/README.md @@ -7,9 +7,9 @@ DNP3 and MESA specifications, located in VOLTTRON readthedocs under http://volttron.readthedocs.io/en/develop/specifications/dnp3_agent.html and http://volttron.readthedocs.io/en/develop/specifications/mesa_agent.html. -These agents depend on the dnp3-python==0.2.3b3 library, which must be installed in the VOLTTRON virtual environment: +These agents depend on the pydnp3 library, which must be installed in the VOLTTRON virtual environment: - (volttron) $ pip install dnp3-python==0.2.3b3 + (volttron) $ pip install pydnp3 Installing MesaAgent -------------------- diff --git a/services/core/DNP3Agent/requirements.txt b/services/core/DNP3Agent/requirements.txt index 2a3adaaaae..9647f44d1e 100644 --- a/services/core/DNP3Agent/requirements.txt +++ b/services/core/DNP3Agent/requirements.txt @@ -1 +1 @@ -dnp3-python==0.2.3b3 +pydnp3==0.1.0 From 3e5c8361a6c40d84b693eefd74920d3a5bebe655 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 31 Aug 2023 17:09:53 -0700 Subject: [PATCH 05/36] Updates for Erlang and Rabbitmq version update. Erlang updated to version 25. Rabbitmq updated to 3.9.29 Multiple test case update to increase default timeout --- README.md | 14 ++++++ services/core/DNP3OutstationAgent/README.md | 2 +- services/core/DNP3OutstationAgent/conftest.py | 6 +++ .../core/DNP3OutstationAgent/requirements.txt | 1 + .../core/DataMover/tests/test_datamover.py | 20 --------- .../tests/test_forwarder_reconnections.py | 9 ++-- .../tests/test_multi_messagebus_forwarder.py | 2 + volttron/utils/rmq_setup.py | 2 +- .../fixtures/volttron_platform_fixtures.py | 45 ++++++++++++------- .../test_multiplatform_pubsub.py | 1 + volttrontesting/multiplatform/test_shovel.py | 2 + .../platform/control_tests/test_control.py | 21 +++++---- .../control_tests/test_vctl_commands.py | 2 +- .../platform/security/test_aip_security.py | 7 +-- volttrontesting/platform/test_core_agent.py | 4 +- .../platform/test_instance_setup.py | 2 + volttrontesting/utils/platformwrapper.py | 13 +++++- 17 files changed, 95 insertions(+), 58 deletions(-) create mode 100644 services/core/DNP3OutstationAgent/conftest.py create mode 100644 services/core/DNP3OutstationAgent/requirements.txt diff --git a/README.md b/README.md index 18ed6519c8..5da7b8d078 100644 --- a/README.md +++ b/README.md @@ -133,11 +133,21 @@ RMQ uses components - ssl, public_key, asn1, and crypto. These are by default in RabbitMQ 3.9.29 is compatible with Erlang versions 24.3.4.2 to 25.2. VOLTTRON was tested with Erlang version 25.2-1 Example: + +On Ubuntu 22.04: + ```shell wget https://binaries2.erlang-solutions.com/ubuntu/pool/contrib/e/esl-erlang/esl-erlang_25.2-1~ubuntu~jammy_amd64.deb sudo dpkg -i esl-erlang_25.2-1~ubuntu~jammy_amd64.deb ``` +On Ubuntu 20.04: +```shell +wget https://binaries2.erlang-solutions.com/ubuntu/pool/contrib/e/esl-erlang/esl-erlang_25.2-1~ubuntu~focal_amd64.deb +sudo dpkg -i esl-erlang_25.2-1~ubuntu~focal_amd64.deb +``` + + ##### 2. Configure hostname Make sure that your hostname is correctly configured in /etc/hosts (See [this StackOverflow Post](https://stackoverflow.com/questions/24797947/os-x-and-rabbitmq-error-epmd-error-for-host-xxx-address-cannot-connect-to-ho)). @@ -149,9 +159,13 @@ connect to empd (port 4369) on ." Note: RabbitMQ startup error would s and not in RabbitMQ logs (/var/log/rabbitmq/rabbitmq@hostname.log) ##### 3. Bootstrap +Remove older version of rabbitmq_server directory. Defaults to /rabbitmq_server/rabbitmq_server-3.9.7 + +Run the rabbitmq boostrap command within an activated VOLTTRON environment ```sh cd volttron +source env/bin/activate python3 bootstrap.py --rabbitmq [optional install directory. defaults to /rabbitmq_server] ``` diff --git a/services/core/DNP3OutstationAgent/README.md b/services/core/DNP3OutstationAgent/README.md index 5938674930..b25354d874 100644 --- a/services/core/DNP3OutstationAgent/README.md +++ b/services/core/DNP3OutstationAgent/README.md @@ -40,7 +40,7 @@ layer, and transport layer. Also, DNP3 can be transmitted over a serial bus conn 1. (If not satisfied yet,) install [dnp3-python](https://pypi.org/project/dnp3-python/) dependency. ```shell - (volttron) $ pip install dnp3-python==0.3.0b1 + (volttron) $ pip install dnp3-python==0.2.3b3 ``` 1. Install and start the DNP3 Outstation Agent. diff --git a/services/core/DNP3OutstationAgent/conftest.py b/services/core/DNP3OutstationAgent/conftest.py new file mode 100644 index 0000000000..8559470457 --- /dev/null +++ b/services/core/DNP3OutstationAgent/conftest.py @@ -0,0 +1,6 @@ +import sys + +from volttrontesting.fixtures.volttron_platform_fixtures import * + +# Add system path of the agent's directory +sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) \ No newline at end of file diff --git a/services/core/DNP3OutstationAgent/requirements.txt b/services/core/DNP3OutstationAgent/requirements.txt new file mode 100644 index 0000000000..2a3adaaaae --- /dev/null +++ b/services/core/DNP3OutstationAgent/requirements.txt @@ -0,0 +1 @@ +dnp3-python==0.2.3b3 diff --git a/services/core/DataMover/tests/test_datamover.py b/services/core/DataMover/tests/test_datamover.py index 730c31bdf5..d25945a44b 100644 --- a/services/core/DataMover/tests/test_datamover.py +++ b/services/core/DataMover/tests/test_datamover.py @@ -567,23 +567,3 @@ def test_old_config(volttron_instances, forwarder): print("data_mover agent id: ", uuid) - -@pytest.mark.historian -@pytest.mark.forwarder -def test_default_config(volttron_instances): - """ - Test the default configuration file included with the agent - """ - publish_agent = volttron_instance1.build_agent(identity="test_agent") - gevent.sleep(1) - - config_path = os.path.join(get_services_core("DataMover"), "config") - with open(config_path, "r") as config_file: - config_json = json.load(config_file) - assert isinstance(config_json, dict) - volttron_instance1.install_agent( - agent_dir=get_services_core("DataMover"), - config_file=config_json, - start=True, - vip_identity="health_test") - assert publish_agent.vip.rpc.call("health_test", "health.get_status").get(timeout=10).get('status') == STATUS_GOOD diff --git a/services/core/ForwardHistorian/tests/test_forwarder_reconnections.py b/services/core/ForwardHistorian/tests/test_forwarder_reconnections.py index 04f05357a0..cdc4013bb9 100644 --- a/services/core/ForwardHistorian/tests/test_forwarder_reconnections.py +++ b/services/core/ForwardHistorian/tests/test_forwarder_reconnections.py @@ -112,8 +112,6 @@ def _device_capture(peer, sender, bus, topic, headers, message): pub_listener.core.stop() - - def test_target_shutdown(setup_instances): inst_forward, inst_target = setup_instances @@ -160,21 +158,22 @@ def _device_capture(peer, sender, bus, topic, headers, message): inst_target.restart_platform() assert inst_target.is_running() - + gevent.sleep(3) pub_listener = inst_target.build_agent() pub_listener.vip.pubsub.subscribe(peer="pubsub", prefix="devices", callback=_device_capture) - gevent.sleep(0.1) + gevent.sleep(3) all_topic = 'devices/campus/building/all' headers, message = publish_device_messages(inst_forward, all_topic=all_topic) + gevent.sleep(3) validate_published_device_data(headers, message, pubsub_retrieved[0][1], pubsub_retrieved[0][2]) def test_can_pause_publishing(setup_instances): - pass \ No newline at end of file + pass diff --git a/services/core/ForwardHistorian/tests/test_multi_messagebus_forwarder.py b/services/core/ForwardHistorian/tests/test_multi_messagebus_forwarder.py index 1f8eb55d96..b95e7476ac 100644 --- a/services/core/ForwardHistorian/tests/test_multi_messagebus_forwarder.py +++ b/services/core/ForwardHistorian/tests/test_multi_messagebus_forwarder.py @@ -136,6 +136,7 @@ def test_multi_messagebus_forwarder(multi_messagebus_forwarder): assert subscriber_agent.analysis_callback.call_count == 5 +@pytest.mark.timeout(600) @pytest.mark.forwarder def test_multi_messagebus_custom_topic_forwarder(multi_messagebus_forwarder): """ @@ -169,6 +170,7 @@ def test_multi_messagebus_custom_topic_forwarder(multi_messagebus_forwarder): assert subscriber_agent.callback.call_count == 5 +@pytest.mark.timeout(600) @pytest.mark.forwarder def test_multi_messagebus_forwarder_reconnection(multi_messagebus_forwarder): """ diff --git a/volttron/utils/rmq_setup.py b/volttron/utils/rmq_setup.py index dfb75f5ce0..f018a9a522 100644 --- a/volttron/utils/rmq_setup.py +++ b/volttron/utils/rmq_setup.py @@ -1543,7 +1543,7 @@ def start_rabbit(rmq_home, env=None): execute_command(status_cmd, env=env) if not start: # if we have attempted started already - gevent.sleep(1) # give a second just to be sure + gevent.sleep(2) # give couple of seconds just to be sure started = True _log.info("Rmq server at {} is running at ".format(rmq_home)) except RuntimeError as e: diff --git a/volttrontesting/fixtures/volttron_platform_fixtures.py b/volttrontesting/fixtures/volttron_platform_fixtures.py index 33fe919435..3fc606e850 100644 --- a/volttrontesting/fixtures/volttron_platform_fixtures.py +++ b/volttrontesting/fixtures/volttron_platform_fixtures.py @@ -62,14 +62,20 @@ def cleanup_wrapper(wrapper): # if wrapper.is_running(): # wrapper.remove_all_agents() # Shutdown handles case where the platform hasn't started. + wrapper_pid = wrapper.p_process.pid wrapper.shutdown_platform() if wrapper.p_process is not None: - if psutil.pid_exists(wrapper.p_process.pid): - proc = psutil.Process(wrapper.p_process.pid) + if psutil.pid_exists(wrapper_pid): + proc = psutil.Process(wrapper_pid) proc.terminate() if not wrapper.debug_mode: assert not Path(wrapper.volttron_home).parent.exists(), \ f"{str(Path(wrapper.volttron_home).parent)} wasn't cleaned!" + if not wrapper.debug_mode: + assert not Path(wrapper.volttron_home).exists() + # Final way to kill off the platform wrapper for the tests. + if psutil.pid_exists(wrapper_pid): + psutil.Process(wrapper_pid).kill() def cleanup_wrappers(platforms): @@ -126,12 +132,14 @@ def volttron_instance(request, **kwargs): @return: volttron platform instance """ address = kwargs.pop("vip_address", get_rand_vip()) + if request.param['messagebus'] == 'rmq': + kwargs['timeout'] = 120 + wrapper = build_wrapper(address, messagebus=request.param.get('messagebus', 'zmq'), ssl_auth=request.param.get('ssl_auth', False), auth_enabled=request.param.get('auth_enabled', True), **kwargs) - wrapper_pid = wrapper.p_process.pid try: yield wrapper @@ -139,11 +147,6 @@ def volttron_instance(request, **kwargs): print(ex.args) finally: cleanup_wrapper(wrapper) - if not wrapper.debug_mode: - assert not Path(wrapper.volttron_home).exists() - # Final way to kill off the platform wrapper for the tests. - if psutil.pid_exists(wrapper_pid): - psutil.Process(wrapper_pid).kill() # Use this fixture to get more than 1 volttron instance for test. @@ -184,6 +187,7 @@ def get_n_volttron_instances(n, should_start=True, **kwargs): wrapper = build_wrapper(address, should_start=should_start, messagebus=request.param.get('messagebus', 'zmq'), ssl_auth=request.param.get('ssl_auth', False), + auth_enabled=request.param.get('auth_enabled', True), **kwargs) instances.append(wrapper) if should_start: @@ -216,20 +220,31 @@ def cleanup(): # Use this fixture when you want a single instance of volttron platform for zmq message bus # test -@pytest.fixture(scope="module") -def volttron_instance_zmq(): +@pytest.fixture(scope="module", + params=[ + dict(messagebus='zmq'), + dict(messagebus='zmq', auth_enabled=False) + ]) +def volttron_instance_zmq(request, **kwargs): """Fixture that returns a single instance of volttron platform for testing @param request: pytest request object @return: volttron platform instance """ - address = get_rand_vip() - - wrapper = build_wrapper(address) + address = kwargs.pop("vip_address", get_rand_vip()) - yield wrapper + wrapper = build_wrapper(address, + messagebus=request.param.get('messagebus', 'zmq'), + ssl_auth=request.param.get('ssl_auth', False), + auth_enabled=request.param.get('auth_enabled', True), + **kwargs) - cleanup_wrapper(wrapper) + try: + yield wrapper + except Exception as ex: + print(ex.args) + finally: + cleanup_wrapper(wrapper) # Use this fixture when you want a single instance of volttron platform for rmq message bus diff --git a/volttrontesting/multiplatform/test_multiplatform_pubsub.py b/volttrontesting/multiplatform/test_multiplatform_pubsub.py index f6145983e0..88c35d9d4a 100644 --- a/volttrontesting/multiplatform/test_multiplatform_pubsub.py +++ b/volttrontesting/multiplatform/test_multiplatform_pubsub.py @@ -247,6 +247,7 @@ def test_multiplatform_pubsub(request, multi_platform_connection): assert message == [{'point': 'value'}] +@pytest.mark.timeout(600) @pytest.mark.multiplatform def test_multiplatform_2_publishers(request, five_platform_connection): subscription_results2 = {} diff --git a/volttrontesting/multiplatform/test_shovel.py b/volttrontesting/multiplatform/test_shovel.py index 76afbefe58..67d487409f 100644 --- a/volttrontesting/multiplatform/test_shovel.py +++ b/volttrontesting/multiplatform/test_shovel.py @@ -259,6 +259,7 @@ def two_way_shovel_connection(request, **kwargs): sink.shutdown_platform() +@pytest.mark.timeout(800) @pytest.mark.shovel def test_shovel_pubsub(shovel_pubsub_rmq_instances): source, sink = shovel_pubsub_rmq_instances @@ -286,6 +287,7 @@ def callback2(peer, sender, bus, topic, headers, message): assert message == [{'point': 'value'}] +@pytest.mark.timeout(600) @pytest.mark.shovel def test_shovel_rpc(two_way_shovel_connection): instance_1, instance_2 = two_way_shovel_connection diff --git a/volttrontesting/platform/control_tests/test_control.py b/volttrontesting/platform/control_tests/test_control.py index 987c33a0ac..b12d896576 100644 --- a/volttrontesting/platform/control_tests/test_control.py +++ b/volttrontesting/platform/control_tests/test_control.py @@ -9,7 +9,7 @@ from volttron.platform.jsonrpc import RemoteError import sys - +@pytest.mark.timeout(600) @pytest.mark.control def test_agent_versions(volttron_instance): auuid = volttron_instance.install_agent( @@ -130,15 +130,16 @@ def test_prioritize_agent_invalid_input(volttron_instance, uuid, priority, expec assert expected in e.value.message +@pytest.mark.timeout(600) @pytest.mark.control -def test_recover_from_crash(get_volttron_instances): +def test_recover_from_crash(volttron_instance): """ Test if control agent periodically monitors and restarts any crashed agents :param volttron_instance: :return: """ - - volttron_instance = get_volttron_instances(1, True, agent_monitor_frequency=10) + volttron_instance.stop_platform() + volttron_instance.startup_platform(volttron_instance.vip_address, agent_monitor_frequency=20) tmpdir = tempfile.mkdtemp() os.chdir(tmpdir) @@ -158,9 +159,9 @@ def __init__(self, config_path, **kwargs): super(CrashTestAgent, self).__init__(**kwargs) @Core.receiver('onstart') - def crash_after_five_seconds(self, sender, **kwargs): + def crash_after_test_seconds(self, sender, **kwargs): print("crash test agent on start") - gevent.sleep(5) + gevent.sleep(15) print("crash test agent quitting") sys.exit(5) @@ -204,8 +205,10 @@ def main(argv=sys.argv): wheel = os.path.join(tmpdir, "dist", "crashtest-0.1-py3-none-any.whl") assert os.path.exists(wheel) - agent_uuid = volttron_instance.install_agent(agent_wheel=wheel, start=True) + agent_uuid = volttron_instance.install_agent(agent_wheel=wheel) assert agent_uuid + gevent.sleep(1) + volttron_instance.start_agent(agent_uuid) query_agent = volttron_instance.dynamic_agent status = query_agent.vip.rpc.call("control", "agent_status", agent_uuid).get( timeout=2 @@ -216,9 +219,9 @@ def main(argv=sys.argv): wait_time = 0 # wait till it has not crashed and once crashed # wait till we detect a restart or 20 seconds. - # have to do this since the test agent is hardcoded to crash 5 + # have to do this since the test agent is hardcoded to crash 15 # seconds after start - while not crashed or (not restarted and wait_time < 30): + while not crashed or (not restarted and wait_time < 50): status = query_agent.vip.rpc.call("control", "agent_status", agent_uuid).get( timeout=2 ) diff --git a/volttrontesting/platform/control_tests/test_vctl_commands.py b/volttrontesting/platform/control_tests/test_vctl_commands.py index f8f6c55701..4ac7f164f8 100644 --- a/volttrontesting/platform/control_tests/test_vctl_commands.py +++ b/volttrontesting/platform/control_tests/test_vctl_commands.py @@ -30,6 +30,7 @@ def test_needs_connection(): except AssertionError: assert not stderr.decode("utf-8") +@pytest.mark.timeout(600) @pytest.mark.control def test_needs_connection_with_connection(volttron_instance: PlatformWrapper): # Verify peerlist command works when instance is running @@ -592,4 +593,3 @@ def test_vctl_start_stop_restart_should_not_fail_on_when_no_agents_are_installed with with_os_environ(volttron_instance.env): execute_command(["vctl", subcommand, valid_option], volttron_instance.env) assert not jsonapi.loads(execute_command(["vctl", "--json", "status"], volttron_instance.env)) - \ No newline at end of file diff --git a/volttrontesting/platform/security/test_aip_security.py b/volttrontesting/platform/security/test_aip_security.py index 06d69c657c..eeb068a019 100644 --- a/volttrontesting/platform/security/test_aip_security.py +++ b/volttrontesting/platform/security/test_aip_security.py @@ -1,7 +1,7 @@ import pwd import gevent import pytest - +import os from mock import MagicMock from volttron.platform import is_rabbitmq_available @@ -19,8 +19,9 @@ "setup script before running test case") # Run as root or sudo scripts/secure_user_permissions.sh for both the below instance names before running these tests -INSTANCE_NAME1 = "volttron1" -INSTANCE_NAME2 = "volttron2" +# also make sure your test environment has acl installed (sudo apt-get install acl) +INSTANCE_NAME1 = "svolttron1" +INSTANCE_NAME2 = "svolttron2" def get_agent_user_from_dir(agent_uuid, home): diff --git a/volttrontesting/platform/test_core_agent.py b/volttrontesting/platform/test_core_agent.py index 45e265b308..548d814142 100644 --- a/volttrontesting/platform/test_core_agent.py +++ b/volttrontesting/platform/test_core_agent.py @@ -174,7 +174,9 @@ def setup_channel(self, channel_name): channel.close(linger=0) del channel - +# marking the first test with extra time out as starting RMQ instance for the first time takes longer and +# pytest.timeout applies not just for the test run alone but include fixture and clean up time +@pytest.mark.timeout(600) @pytest.mark.agent def test_channel_send_data(volttron_instance: PlatformWrapper): diff --git a/volttrontesting/platform/test_instance_setup.py b/volttrontesting/platform/test_instance_setup.py index 959864a576..3f31b7ea5e 100644 --- a/volttrontesting/platform/test_instance_setup.py +++ b/volttrontesting/platform/test_instance_setup.py @@ -126,6 +126,7 @@ def test_zmq_case_no_agents(monkeypatch): assert not is_volttron_running(vhome) +@pytest.mark.timeout(400) def test_zmq_case_with_agents(monkeypatch): with create_vcfg_vhome() as vhome: monkeypatch.setenv("VOLTTRON_HOME", vhome) @@ -261,6 +262,7 @@ def test_zmq_case_web_no_agents(monkeypatch): assert not is_volttron_running(vhome) +@pytest.mark.timeout(400) def test_zmq_case_web_with_agents(monkeypatch): with create_vcfg_vhome() as vhome: monkeypatch.setenv("VOLTTRON_HOME", vhome) diff --git a/volttrontesting/utils/platformwrapper.py b/volttrontesting/utils/platformwrapper.py index 8f90472396..4c9688f763 100644 --- a/volttrontesting/utils/platformwrapper.py +++ b/volttrontesting/utils/platformwrapper.py @@ -170,7 +170,8 @@ def start_wrapper_platform(wrapper, with_http=False, with_tcp=True, wrapper.startup_platform(vip_address=vc_tcp, bind_web_address=bind_address, volttron_central_address=volttron_central_address, - volttron_central_serverkey=volttron_central_serverkey) + volttron_central_serverkey=volttron_central_serverkey, + timeout=100) if with_http: discovery = "{}/discovery/".format(vc_http) response = grequests.get(discovery).send().response @@ -530,6 +531,9 @@ def build_agent(self, address=None, should_spawn=True, identity=None, event.wait(timeout=4) has_control = False times = 0 + if self.messagebus == 'rmq': + # agent seem to need a extra second for agent to establish connection + gevent.sleep(1) while not has_control and times < 10: times += 1 try: @@ -1233,7 +1237,12 @@ def __wait_for_control_connection_to_exit__(self, timeout: int = 10): disconnected = False timer_start = time.time() while not disconnected: - peers = self.dynamic_agent.vip.peerlist().get(timeout=20) + try: + peers = self.dynamic_agent.vip.peerlist().get(timeout=10) + except gevent.Timeout: + self.logit("peerlist call timed out. Exiting loop. " + "Not waiting for control connection to exit.") + break disconnected = CONTROL_CONNECTION not in peers if disconnected: break From e3f4088d31098153a942c9b30cb3ce4b520af8e3 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 31 Aug 2023 17:48:15 -0700 Subject: [PATCH 06/36] Updates for Erlang and Rabbitmq version update. Erlang updated to version 25. Rabbitmq updated to 3.9.29 Multiple test case update to increase default timeout --- docs/source/introduction/platform-install.rst | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/docs/source/introduction/platform-install.rst b/docs/source/introduction/platform-install.rst index f772cc4433..3f806339b6 100644 --- a/docs/source/introduction/platform-install.rst +++ b/docs/source/introduction/platform-install.rst @@ -214,13 +214,20 @@ Download and install ErlangOTP from [Erlang Solutions](https://www.erlang-soluti RMQ uses components - ssl, public_key, asn1, and crypto. These are by default included in the OTP RabbitMQ 3.9.29 is compatible with Erlang versions 24.3.4.2 to 25.2. VOLTTRON was tested with Erlang version 25.2-1 -Example: +Example: Ubuntu 22.04 .. code-block:: bash wget https://binaries2.erlang-solutions.com/ubuntu/pool/contrib/e/esl-erlang/esl-erlang_25.2-1~ubuntu~jammy_amd64.deb sudo dpkg -i esl-erlang_25.2-1~ubuntu~jammy_amd64.deb +Example: Ubuntu 20.04 +.. code-block:: bash + + wget https://binaries2.erlang-solutions.com/ubuntu/pool/contrib/e/esl-erlang/esl-erlang_25.2-1~ubuntu~focal_amd64.deb + sudo dpkg -i esl-erlang_25.2-1~ubuntu~focal_amd64.deb + + Step 3 - Configure hostname ^^^^^^^^^^^^^^^^^^^^^^^^^^^ @@ -240,10 +247,13 @@ to connect to empd (port 4369) on ." Step 4 - Bootstrap the environment ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +Remove older version of rabbitmq_server directory. Defaults to /rabbitmq_server/rabbitmq_server-3.9.7 +Run the rabbitmq bootstrap step from within an VOLTTRON activated environment. .. code-block:: bash cd volttron + source env/bin/activate python3 bootstrap.py --rabbitmq [optional install directory. defaults to /rabbitmq_server] This will build the platform and create a virtual Python environment and dependencies for RabbitMQ. It also installs From c53965a49302565bdbdad483ecf86033e76ef6f7 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Sat, 2 Sep 2023 18:32:39 -0700 Subject: [PATCH 07/36] added missing imports --- volttron/platform/agent/base_weather.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/volttron/platform/agent/base_weather.py b/volttron/platform/agent/base_weather.py index 6cb0aa0d13..2efabb905b 100644 --- a/volttron/platform/agent/base_weather.py +++ b/volttron/platform/agent/base_weather.py @@ -41,13 +41,14 @@ import csv import sqlite3 import datetime +import os from functools import wraps from abc import abstractmethod from gevent import get_hub from volttron.platform.agent.utils import fix_sqlite3_datetime, \ get_aware_utc_now, format_timestamp, process_timestamp, \ parse_timestamp_string -from volttron.platform.vip.agent import Agent +from volttron.platform.vip.agent import Agent, RPC, Core from volttron.platform.async_ import AsyncCall from volttron.platform.messaging import headers from volttron.platform.messaging.health import (STATUS_BAD, From b77d31af392ad357b7bd1178ddde6dd49e0cb709 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Sat, 2 Sep 2023 18:33:22 -0700 Subject: [PATCH 08/36] Changed pytest xfail cases to skip instead of fail --- services/core/VolttronCentral/tests/test_vc_autoregister.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/services/core/VolttronCentral/tests/test_vc_autoregister.py b/services/core/VolttronCentral/tests/test_vc_autoregister.py index b7e7109089..cf0bb838ca 100644 --- a/services/core/VolttronCentral/tests/test_vc_autoregister.py +++ b/services/core/VolttronCentral/tests/test_vc_autoregister.py @@ -52,10 +52,10 @@ def test_able_to_register_unregister(multi_messagebus_vc_vcp): vcp_instance, vc_instance, vcp_uuid = multi_messagebus_vc_vcp if vcp_instance.param['sink'] == 'rmq_web' and vcp_instance.param['source'] != 'rmq': pytest.mark.xfail("Combination of rmq<-zmq is not valid") - pytest.fail("Combination of rmq<-zmq is not valid") + pytest.skip("Combination of rmq<-zmq is not valid") elif vcp_instance.param['sink'] == 'zmq_web' and vcp_instance.param['source'] != 'zmq': pytest.mark.xfail("Combination of zmq<-rmq does not work") - pytest.fail("Combination of rmq<-zmq is not valid") + pytest.skip("Combination of zmq<-rmq is not valid") apitester = APITester(vc_instance) From 785bbbe0cc390d891738b2259f9c9aae575c8545 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 7 Sep 2023 14:57:45 -0700 Subject: [PATCH 09/36] changed reference to deprecated method. using requests instead of grequests as we wait for result --- .../core/WeatherDotGov/weatherdotgov/agent.py | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/services/core/WeatherDotGov/weatherdotgov/agent.py b/services/core/WeatherDotGov/weatherdotgov/agent.py index d309b88bbd..b1c96e599c 100644 --- a/services/core/WeatherDotGov/weatherdotgov/agent.py +++ b/services/core/WeatherDotGov/weatherdotgov/agent.py @@ -43,7 +43,7 @@ import sys import grequests import datetime -import pkg_resources +from importlib.resources import files as get_resource_files from volttron.platform.agent.base_weather import BaseWeatherAgent from volttron.platform.agent import utils from volttron.utils.docs import doc_inherit @@ -52,7 +52,6 @@ # requests should be imported after grequests # as grequests monkey patches ssl and requests imports ssl -# TODO do we need the requests at all.. TODO test with RMQ import requests __version__ = "2.0.0" @@ -121,7 +120,7 @@ def get_point_name_defs_file(self): """ # returning resource file instead of stream, as csv.DictReader require file path or file like object opened in # text mode. - return pkg_resources.get_resource_filename(__name__, "data/name_mapping.csv") + return str(get_resource_files("weatherdotgov").joinpath("data/name_mapping.csv")) def get_location_string(self, location): """ @@ -300,8 +299,10 @@ def query_current_weather(self, location): raise ValueError('Invalid location. Expected format is:' '{"station":"station_id_value"}') gresponse = self.make_web_request(url) + _log.debug(f"get current- url is {url}") try: response = jsonapi.loads(gresponse.content) + _log.debug(f"Response: {response}") properties = response["properties"] observation_time = properties["timestamp"] return observation_time, properties @@ -382,13 +383,11 @@ def get_forecast_url(self, location): return url def make_web_request(self, url): - grequest = [grequests.get(url, verify=requests.certs.where(), - headers=self.headers, timeout=3)] - gresponse = grequests.map(grequest)[0] - if gresponse is None: + response = requests.get(url, headers=self.headers, verify=requests.certs.where()) + if response is None: raise RuntimeError("get request did not return any " "response") - return gresponse + return response def extract_forecast_data(self, url, gresponse): try: From cc03320404dfdfaaa90384cb706e22e6c7db7a53 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 7 Sep 2023 14:58:01 -0700 Subject: [PATCH 10/36] removed debug log --- volttron/platform/web/platform_web_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/volttron/platform/web/platform_web_service.py b/volttron/platform/web/platform_web_service.py index b2da02e3a4..a0b2db1155 100644 --- a/volttron/platform/web/platform_web_service.py +++ b/volttron/platform/web/platform_web_service.py @@ -491,7 +491,7 @@ def app_routing(self, env, start_response): retvalue = v(env, start_response, data) except TypeError: response = v(env, data) - _log.debug(f'VUI: Response at app_routing is: {response.response}') + #_log.debug(f'VUI: Response at app_routing is: {response.response}') return response(env, start_response) # retvalue = self.process_response(start_response, v(env, data)) From 08affbac17f2671ca17f2c3f374082cea7f046c1 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 7 Sep 2023 14:58:18 -0700 Subject: [PATCH 11/36] updated psycopg2 version --- requirements.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.py b/requirements.py index c3735d9ab0..999c049cbe 100644 --- a/requirements.py +++ b/requirements.py @@ -69,7 +69,7 @@ 'pymongo==4.2.0', 'crate==0.27.1', 'influxdb==5.3.1', - 'psycopg2-binary==2.8.6'], + 'psycopg2-binary==2.9.7'], 'documentation': ['mock==4.0.3', 'docutils<0.18', 'sphinx-rtd-theme==1.0.0', @@ -84,7 +84,7 @@ 'mongo': ['pymongo==4.2.0'], 'mysql': ['mysql-connector-python==8.0.30'], 'pandas': ['numpy==1.23.1', 'pandas==1.4.3'], - 'postgres': ['psycopg2-binary==2.8.6'], + 'postgres': ['psycopg2-binary==2.9.7'], # This is installed in bootstrap.py itself so we don't # include here, though we include the version number here # From 6ee5f1ecb9af86c1f3ece666682cce4c264d3922 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 11 Sep 2023 12:35:39 -0700 Subject: [PATCH 12/36] Fix for issue #3117 --- scripts/secure_user_permissions.sh | 15 ++++++++++++++- .../platform/security/test_aip_security.py | 8 ++++++-- 2 files changed, 20 insertions(+), 3 deletions(-) diff --git a/scripts/secure_user_permissions.sh b/scripts/secure_user_permissions.sh index faa7816e0d..ac614c57cd 100755 --- a/scripts/secure_user_permissions.sh +++ b/scripts/secure_user_permissions.sh @@ -265,6 +265,19 @@ while true; do fi done +# Get full path to python executable +while true; do + echo -n "Enter full path to python used for volttron:" + read python_path + valid=0 + version=`$python_path -V` + if [ $? -eq 0 ]; then + break + else + echo "Invalid python_path" + fi +done + echo "$volttron_user ALL= NOPASSWD: /usr/sbin/groupadd volttron_$name" | sudo EDITOR='tee -a' visudo -f /etc/sudoers.d/volttron_$name echo "$volttron_user ALL= NOPASSWD: /usr/sbin/usermod -a -G volttron_$name $USER" | sudo EDITOR='tee -a' visudo -f /etc/sudoers.d/volttron_$name echo "$volttron_user ALL= NOPASSWD: /usr/sbin/useradd volttron_[1-9]* -r -G volttron_$name" | sudo EDITOR='tee -a' visudo -f /etc/sudoers.d/volttron_$name @@ -273,6 +286,6 @@ echo "$volttron_user ALL= NOPASSWD: $source_dir/scripts/stop_agent_running_in_is # TODO want delete only users with pattern of particular group echo "$volttron_user ALL= NOPASSWD: /usr/sbin/userdel volttron_[1-9]*" | sudo EDITOR='tee -a' visudo -f /etc/sudoers.d/volttron_$name # allow user to run all non-sudo commands for all volttron agent users -echo "$volttron_user ALL=(%volttron_$name) NOPASSWD: ALL" | sudo EDITOR='tee -a' visudo -f /etc/sudoers.d/volttron_$name +echo "$volttron_user ALL=(%volttron_$name) NOPASSWD:SETENV: $python_path" | sudo EDITOR='tee -a' visudo -f /etc/sudoers.d/volttron_$name echo "Permissions set for $volttron_user" echo "Volttron agent isolation mode setup is complete" diff --git a/volttrontesting/platform/security/test_aip_security.py b/volttrontesting/platform/security/test_aip_security.py index eeb068a019..baa1981cf1 100644 --- a/volttrontesting/platform/security/test_aip_security.py +++ b/volttrontesting/platform/security/test_aip_security.py @@ -18,8 +18,12 @@ reason="Can't run on travis as this test needs root to run " "setup script before running test case") -# Run as root or sudo scripts/secure_user_permissions.sh for both the below instance names before running these tests -# also make sure your test environment has acl installed (sudo apt-get install acl) +# IMPORTANT steps for running this test +# 1. Make sure your test environment has acl installed (sudo apt-get install acl) +# 2. Make sure the python executable is accessible by any user. This would mean read and execute access to all +# directories in the path. For example if python is in /user/home/env/bin/python, then do chmod r+x to /user, +# and /user/home, and /user/home/env/, and /user/home/env/bin and /user/home/env/bin/python. +# 3. Run as root or sudo scripts/secure_user_permissions.sh for both the below instance names before running these INSTANCE_NAME1 = "svolttron1" INSTANCE_NAME2 = "svolttron2" From 479309cd834af70458a21ed2883c1417eb2faf82 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 11 Sep 2023 13:29:32 -0700 Subject: [PATCH 13/36] Fixed expected output --- volttrontesting/platform/test_instance_setup.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/volttrontesting/platform/test_instance_setup.py b/volttrontesting/platform/test_instance_setup.py index 3f31b7ea5e..ef3b83f2b4 100644 --- a/volttrontesting/platform/test_instance_setup.py +++ b/volttrontesting/platform/test_instance_setup.py @@ -936,8 +936,9 @@ def test_web_with_agents_volttron_running(monkeypatch, volttron_instance_web): if volttron_instance_web.ssl_auth is True: assert config.get('volttron', 'web-ssl-cert') == os.path.join(vhome, "certificates", "certs", "server0.crt") assert config.get('volttron', 'web-ssl-key') == os.path.join(vhome, "certificates", "private", "server0.pem") - assert _is_agent_installed("listener") - assert _is_agent_installed("platform_driver") - assert _is_agent_installed("platform_historian") - assert _is_agent_installed("vcp") + # if instance is running + assert not _is_agent_installed("listener") + # assert _is_agent_installed("platform_driver") + # assert _is_agent_installed("platform_historian") + # assert _is_agent_installed("vcp") assert is_volttron_running(vhome) From ced3a0eb929dd2dac9f37ab823a7b08f9c870a2e Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 11 Sep 2023 13:39:52 -0700 Subject: [PATCH 14/36] removed debug stmts --- services/core/WeatherDotGov/weatherdotgov/agent.py | 2 -- 1 file changed, 2 deletions(-) diff --git a/services/core/WeatherDotGov/weatherdotgov/agent.py b/services/core/WeatherDotGov/weatherdotgov/agent.py index b1c96e599c..5c26e17014 100644 --- a/services/core/WeatherDotGov/weatherdotgov/agent.py +++ b/services/core/WeatherDotGov/weatherdotgov/agent.py @@ -299,10 +299,8 @@ def query_current_weather(self, location): raise ValueError('Invalid location. Expected format is:' '{"station":"station_id_value"}') gresponse = self.make_web_request(url) - _log.debug(f"get current- url is {url}") try: response = jsonapi.loads(gresponse.content) - _log.debug(f"Response: {response}") properties = response["properties"] observation_time = properties["timestamp"] return observation_time, properties From 827f4cfc7ce13ead163331b14febaec247bf20c3 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 11 Sep 2023 13:40:04 -0700 Subject: [PATCH 15/36] added entry for dnp3 --- requirements.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/requirements.py b/requirements.py index 999c049cbe..77ad9b8efa 100644 --- a/requirements.py +++ b/requirements.py @@ -106,4 +106,5 @@ 'passlib==1.7.4', 'argon2-cffi==21.3.0', 'Werkzeug==2.2.1', - 'treelib==1.6.1']} + 'treelib==1.6.1'], + 'dnp3': ['dnp3-python==0.2.3b3']} From e19a57bdbf4cd8d2b01415d9acb28d35e5dda503 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 11 Sep 2023 13:48:31 -0700 Subject: [PATCH 16/36] minor test case fix --- volttrontesting/platform/test_platform_web.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/volttrontesting/platform/test_platform_web.py b/volttrontesting/platform/test_platform_web.py index 1bf18481bf..9fbcbd9d19 100644 --- a/volttrontesting/platform/test_platform_web.py +++ b/volttrontesting/platform/test_platform_web.py @@ -229,8 +229,8 @@ def test_test_web_agent(volttron_instance_web): @pytest.mark.web -def test_register_path_route(web_instance): - vi = web_instance +def test_register_path_route(volttron_instance_web): + vi = volttron_instance_web with with_os_environ(vi.env): assert vi.is_running() From 606aa8849afb7e97e730083cbf5e6a3fd4cd63bd Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 11 Sep 2023 13:48:52 -0700 Subject: [PATCH 17/36] updated based on gitlab changes --- .gitlab-ci.yml | 150 ++++++++++++++++++++++++++++++++++--------------- 1 file changed, 104 insertions(+), 46 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index 892e7e9d18..d0b7229eba 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -1,46 +1,104 @@ -# This file is a template, and might need editing before it works on your project. -# You can copy and paste this template into a new `.gitlab-ci.yml` file. -# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword. -# -# To contribute improvements to CI/CD templates, please follow the Development guide at: -# https://docs.gitlab.com/ee/development/cicd/templates.html -# This specific template is located at: -# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Bash.gitlab-ci.yml - -# See https://docs.gitlab.com/ee/ci/yaml/index.html for all available options - -# you can delete this line if you're not using Docker -# image: busybox:latest - -22.04 job: - tags: - - ubuntu2204 - - before_script: - - python3 bootstrap.py --all - - after_script: - - rm -rf dist - - rm -rf /tmp/tmp* - - rm -rf env - - script: - - env/bin/activate - - pytest volttrontesting - -20.04 job: - tags: - - ubuntu2004 - - before_script: - - python3 bootstrap.py --all - - after_script: - - rm -rf dist - - rm -rf /tmp/tmp* - - rm -rf env - - script: - - env/bin/activate - - pytest volttrontesting - +# This file is a template, and might need editing before it works on your project. +# You can copy and paste this template into a new `.gitlab-ci.yml` file. +# You should not add this template to an existing `.gitlab-ci.yml` file by using the `include:` keyword. +# +# To contribute improvements to CI/CD templates, please follow the Development guide at: +# https://docs.gitlab.com/ee/development/cicd/templates.html +# This specific template is located at: +# https://gitlab.com/gitlab-org/gitlab/-/blob/master/lib/gitlab/ci/templates/Bash.gitlab-ci.yml + +# See https://docs.gitlab.com/ee/ci/yaml/index.html for all available options + +# you can delete this line if you're not using Docker +# image: busybox:latest + +stages: + - build + - test + +.parallel-tests: + parallel: + matrix: + - TEST: + - services/core/ActuatorAgent/tests + - services/core/DataMover/tests/ + - services/core/DNP3OutstationAgent/tests + - services/core/ForwardHistorian/tests + +# build 22.04: +# stage: build +# tags: +# - ubuntu2204 + +# before_script: +# #- killall -9 volttron beam.smp python +# - rm -rf dist ~/.volttron ~/.volttron_instances +# - rm -rf /tmp/tmp* +# - rm -rf ~/rabbitmq_server + +# script: +# - python3 bootstrap.py --all +# - source env/bin/activate +# - python3 bootstrap.py --rabbitmq +# - echo "BUILD_DIR_22_04=`pwd`" >> build.env +# - echo "$BUILD_DIR_22_04" +# - echo `pwd` + +# artifacts: +# reports: +# dotenv: build.env + +build 20.04: + stage: build + tags: + - ubuntu2004 + + before_script: + #- killall -9 volttron beam.smp python + - rm -rf dist ~/.volttron ~/.volttron_instances + - rm -rf /tmp/tmp* + - rm -rf ~/rabbitmq_server + + script: + - python3 bootstrap.py --all + - source env/bin/activate + - python3 bootstrap.py --rabbitmq + - echo "BUILD_DIR_20_04=`pwd`" >> build.env + - echo "$BUILD_DIR_20_04" + - echo `pwd` + + artifacts: + reports: + dotenv: build.env + + +# test 22.04: +# stage: test +# needs: [build 22.04] +# variables: +# GIT_CHECKOUT: "false" +# tags: +# - ubuntu2204 +# extends: .parallel-tests +# script: +# - cd $BUILD_DIR_22_04 +# - echo `pwd` +# - source env/bin/activate +# - pytest $TEST + + +test 20.04: + stage: test + needs: [build 20.04] + variables: + GIT_CHECKOUT: "false" + tags: + - ubuntu2004 + extends: .parallel-tests + script: + - cd $BUILD_DIR_20_04 + - echo `pwd` + - source env/bin/activate + - pytest $TEST + + From 9d486e82393d75111d6180da0d42aa0524bd8ab0 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 14 Sep 2023 13:22:26 -0700 Subject: [PATCH 18/36] removed old dnp3 agent --- services/core/DNP3Agent/README.md | 86 - services/core/DNP3Agent/config | 11 - services/core/DNP3Agent/conftest.py | 19 - services/core/DNP3Agent/dnp3/__init__.py | 74 - services/core/DNP3Agent/dnp3/agent.py | 99 - .../core/DNP3Agent/dnp3/base_dnp3_agent.py | 517 - services/core/DNP3Agent/dnp3/mesa/__init__.py | 0 services/core/DNP3Agent/dnp3/mesa/agent.py | 353 - .../core/DNP3Agent/dnp3/mesa/conversion.py | 4 - .../core/DNP3Agent/dnp3/mesa/functions.py | 570 - .../DNP3Agent/dnp3/mesa/mesa_functions.yaml | 2595 ---- .../core/DNP3Agent/dnp3/mesa_points.config | 10270 --------------- services/core/DNP3Agent/dnp3/outstation.py | 420 - services/core/DNP3Agent/dnp3/points.py | 614 - services/core/DNP3Agent/dnp3_master.py | 517 - services/core/DNP3Agent/function_test.py | 150 - services/core/DNP3Agent/install_dnp3_agent.sh | 19 - services/core/DNP3Agent/install_mesa_agent.sh | 25 - services/core/DNP3Agent/mesa_master.py | 142 - services/core/DNP3Agent/mesaagent.config | 15 - services/core/DNP3Agent/requirements.txt | 1 - services/core/DNP3Agent/setup.py | 68 - .../DNP3Agent/tests/MesaTestAgent/setup.py | 63 - .../tests/MesaTestAgent/testagent.config | 23 - .../tests/MesaTestAgent/testagent/__init__.py | 0 .../tests/MesaTestAgent/testagent/agent.py | 217 - services/core/DNP3Agent/tests/README.md | 43 - .../tests/data/connect_and_disconnect.json | 7 - .../data/enable_watt_var_power_mode.json | 13 - .../tests/data/enable_watt_var_schedule.json | 13 - .../DNP3Agent/tests/data/mesa_functions.yaml | 2581 ---- .../DNP3Agent/tests/data/mesa_points.config | 10276 ---------------- .../DNP3Agent/tests/data/mesaagent.config | 15 - .../DNP3Agent/tests/data/watt_var_curve.json | 26 - .../tests/data/watt_var_schedule.json | 30 - .../core/DNP3Agent/tests/mesa_master_cmd.py | 155 - .../core/DNP3Agent/tests/mesa_master_test.py | 131 - .../core/DNP3Agent/tests/test_dnp3_agent.py | 273 - .../core/DNP3Agent/tests/test_functions.py | 369 - .../core/DNP3Agent/tests/test_mesa_agent.py | 546 - services/core/DNP3Agent/tests/test_points.py | 177 - .../tests/unit_test_point_definitions.py | 212 - 42 files changed, 31739 deletions(-) delete mode 100644 services/core/DNP3Agent/README.md delete mode 100644 services/core/DNP3Agent/config delete mode 100644 services/core/DNP3Agent/conftest.py delete mode 100644 services/core/DNP3Agent/dnp3/__init__.py delete mode 100644 services/core/DNP3Agent/dnp3/agent.py delete mode 100644 services/core/DNP3Agent/dnp3/base_dnp3_agent.py delete mode 100644 services/core/DNP3Agent/dnp3/mesa/__init__.py delete mode 100644 services/core/DNP3Agent/dnp3/mesa/agent.py delete mode 100644 services/core/DNP3Agent/dnp3/mesa/conversion.py delete mode 100644 services/core/DNP3Agent/dnp3/mesa/functions.py delete mode 100644 services/core/DNP3Agent/dnp3/mesa/mesa_functions.yaml delete mode 100644 services/core/DNP3Agent/dnp3/mesa_points.config delete mode 100644 services/core/DNP3Agent/dnp3/outstation.py delete mode 100644 services/core/DNP3Agent/dnp3/points.py delete mode 100644 services/core/DNP3Agent/dnp3_master.py delete mode 100644 services/core/DNP3Agent/function_test.py delete mode 100644 services/core/DNP3Agent/install_dnp3_agent.sh delete mode 100644 services/core/DNP3Agent/install_mesa_agent.sh delete mode 100644 services/core/DNP3Agent/mesa_master.py delete mode 100644 services/core/DNP3Agent/mesaagent.config delete mode 100644 services/core/DNP3Agent/requirements.txt delete mode 100644 services/core/DNP3Agent/setup.py delete mode 100644 services/core/DNP3Agent/tests/MesaTestAgent/setup.py delete mode 100644 services/core/DNP3Agent/tests/MesaTestAgent/testagent.config delete mode 100644 services/core/DNP3Agent/tests/MesaTestAgent/testagent/__init__.py delete mode 100644 services/core/DNP3Agent/tests/MesaTestAgent/testagent/agent.py delete mode 100644 services/core/DNP3Agent/tests/README.md delete mode 100644 services/core/DNP3Agent/tests/data/connect_and_disconnect.json delete mode 100644 services/core/DNP3Agent/tests/data/enable_watt_var_power_mode.json delete mode 100644 services/core/DNP3Agent/tests/data/enable_watt_var_schedule.json delete mode 100644 services/core/DNP3Agent/tests/data/mesa_functions.yaml delete mode 100644 services/core/DNP3Agent/tests/data/mesa_points.config delete mode 100644 services/core/DNP3Agent/tests/data/mesaagent.config delete mode 100644 services/core/DNP3Agent/tests/data/watt_var_curve.json delete mode 100644 services/core/DNP3Agent/tests/data/watt_var_schedule.json delete mode 100644 services/core/DNP3Agent/tests/mesa_master_cmd.py delete mode 100644 services/core/DNP3Agent/tests/mesa_master_test.py delete mode 100644 services/core/DNP3Agent/tests/test_dnp3_agent.py delete mode 100644 services/core/DNP3Agent/tests/test_functions.py delete mode 100644 services/core/DNP3Agent/tests/test_mesa_agent.py delete mode 100644 services/core/DNP3Agent/tests/test_points.py delete mode 100644 services/core/DNP3Agent/tests/unit_test_point_definitions.py diff --git a/services/core/DNP3Agent/README.md b/services/core/DNP3Agent/README.md deleted file mode 100644 index 3cf6162e19..0000000000 --- a/services/core/DNP3Agent/README.md +++ /dev/null @@ -1,86 +0,0 @@ -DNP3Agent and MesaAgent, either of which can be built from this directory, -are VOLTTRON agents that handle DNP3 communications. -They implement a DNP3 outstation, communicating with a DNP3 master. - -For further information about these agents and DNP3 communications, please see the VOLTTRON -DNP3 and MESA specifications, located in VOLTTRON readthedocs -under http://volttron.readthedocs.io/en/develop/specifications/dnp3_agent.html -and http://volttron.readthedocs.io/en/develop/specifications/mesa_agent.html. - -These agents depend on the pydnp3 library, which must be installed in the VOLTTRON virtual environment: - - (volttron) $ pip install pydnp3 - -Installing MesaAgent --------------------- - -MesaAgent implements MESA-ESS, an enhanced version of the DNP3 protocol. - -MesaAgent can be installed by running the **install_mesa_agent.sh** -command-line script as follows: - - (volttron) $ export VOLTTRON_ROOT= - (volttron) $ source $VOLTTRON_ROOT/services/core/DNP3Agent/install_mesa_agent.sh - -The **install_mesa_agent.sh** script installs the agent: - - (volttron) $ export DNP3_ROOT=$VOLTTRON_ROOT/services/core/DNP3Agent - (volttron) $ export AGENT_MODULE=dnp3.mesa.agent - (volttron) $ cd $VOLTTRON_ROOT - (volttron) $ python scripts/install-agent.py -s $DNP3_ROOT -i mesaagent -c $DNP3_ROOT/mesaagent.config -t mesaagent -f - -(Note that $AGENT_MODULE directs the installer to use agent -source code residing in the "dnp3/mesa" subdirectory.) - -Then the script stores DNP3 point and MESA function definitions in the agent's config store: - - (volttron) $ cd $DNP3_ROOT - (volttron) $ python dnp3/mesa/conversion.py < dnp3/mesa/mesa_functions.yaml > dnp3/mesa/mesa_functions.config - (volttron) $ cd $VOLTTRON_ROOT - (volttron) $ vctl config store mesaagent mesa_points.config $DNP3_ROOT/dnp3/mesa_points.config - (volttron) $ vctl config store mesaagent mesa_functions.config $DNP3_ROOT/dnp3/mesa/mesa_functions.config - -Regression tests can be run from a command-line shell as follows: - - (volttron) $ pytest services/core/DNP3Agent/tests/test_mesa_agent.py - -Installing DNP3Agent --------------------- - -DNP3Agent implements the basic DNP3 protocol. - -DNP3Agent can be installed by running the **install_dnp3_agent.sh** -command-line script as follows: - - (volttron) $ export VOLTTRON_ROOT= - (volttron) $ source $VOLTTRON_ROOT/services/core/DNP3Agent/install_dnp3_agent.sh - -The **install_dnp3_agent.sh** script installs the agent: - - (volttron) $ export DNP3_ROOT=$VOLTTRON_ROOT/services/core/DNP3Agent - (volttron) $ export AGENT_MODULE=dnp3.agent - (volttron) $ cd $VOLTTRON_ROOT - (volttron) $ python scripts/install-agent.py -s $DNP3_ROOT -i dnp3agent -c $DNP3_ROOT/config -t dnp3agent -f - -(Note that $AGENT_MODULE directs the installer to use agent -source code residing in the "dnp3" directory.) - -Then the script stores DNP3 point (but not MESA function) definitions in the agent's config store: - - (volttron) $ vctl config store dnp3agent mesa_points.config $DNP3_ROOT/dnp3/mesa_points.config - -Regression tests can be run from a command-line shell as follows: - - (volttron) $ cd $VOLTTRON_ROOT - (volttron) $ pytest services/core/DNP3Agent/tests/test_dnp3_agent.py - -Maintaining mesa_points.config and mesa_functions.yaml ------------------------------------------------------- - -mesa_points.config is installed in $DNP3_ROOT/dnp3/mesa_points.config - -mesa_functions.yaml is installed in $DNP3_ROOT/dnp3/mesa/mesa_functions.yaml - -To update Mesa points and functions config files, please follow instructions for -[mesa_points.config](https://docs.google.com/document/d/1WgiGkNCtILLvNKSm0ZsNo0HrqY0akIQIiGQNZP1PBP0/edit#heading=h.5224t5rtcb0g) -and [mesa_functions.yaml](https://docs.google.com/document/d/1WgiGkNCtILLvNKSm0ZsNo0HrqY0akIQIiGQNZP1PBP0/edit#heading=h.qhuvbxq207n2) diff --git a/services/core/DNP3Agent/config b/services/core/DNP3Agent/config deleted file mode 100644 index fe60378e83..0000000000 --- a/services/core/DNP3Agent/config +++ /dev/null @@ -1,11 +0,0 @@ -{ - "points": "config://mesa_points.config", - "point_topic": "dnp3/point", - "outstation_status_topic": "dnp3/outstation_status", - "outstation_config": { - "database_sizes": 10000, - "log_levels": ["NORMAL"] - }, - "local_ip": "0.0.0.0", - "port": 20000 -} \ No newline at end of file diff --git a/services/core/DNP3Agent/conftest.py b/services/core/DNP3Agent/conftest.py deleted file mode 100644 index 74134a5b76..0000000000 --- a/services/core/DNP3Agent/conftest.py +++ /dev/null @@ -1,19 +0,0 @@ -import sys - -from volttrontesting.fixtures.volttron_platform_fixtures import * - -collect_ignore = ["function_test.py", "tests/mesa_platform_test.py"] - -try: - import pydnp3 -except ImportError: - # pydnp3 library has not been installed -- all pytest modules would fail - collect_ignore.extend(["tests/test_dnp3_agent.py", - "tests/test_mesa_agent.py", - "tests/test_mesa_data.py"]) - -# Add system path of the agent's directory -sys.path.insert(0, os.path.abspath(os.path.dirname(__file__))) - -# Add system path of the agent's dnp3 subdirectory -sys.path.insert(0, os.path.abspath(os.path.dirname(__file__) + '/dnp3')) diff --git a/services/core/DNP3Agent/dnp3/__init__.py b/services/core/DNP3Agent/dnp3/__init__.py deleted file mode 100644 index d0525d5da5..0000000000 --- a/services/core/DNP3Agent/dnp3/__init__.py +++ /dev/null @@ -1,74 +0,0 @@ -from pydnp3 import opendnp3 - -DEFAULT_POINT_TOPIC = 'dnp3/point' -DEFAULT_OUTSTATION_STATUS_TOPIC = 'mesa/outstation_status' -DEFAULT_LOCAL_IP = "0.0.0.0" -DEFAULT_PORT = 20000 - -# StepDefinition.fcode values: -DIRECT_OPERATE = 'direct_operate' # This is actually DIRECT OPERATE / RESPONSE -SELECT = 'select' # This is actually SELECT / RESPONSE -OPERATE = 'operate' # This is actually OPERATE / RESPONSE -READ = 'read' -RESPONSE = 'response' - -# PointDefinition.action values: -PUBLISH = 'publish' -PUBLISH_AND_RESPOND = 'publish_and_respond' - -# Some PointDefinition.type values -POINT_TYPE_ARRAY = 'array' -POINT_TYPE_SELECTOR_BLOCK = 'selector_block' -POINT_TYPE_ENUMERATED = 'enumerated' -POINT_TYPES = [POINT_TYPE_ARRAY, POINT_TYPE_SELECTOR_BLOCK, POINT_TYPE_ENUMERATED] - -# Some PointDefinition.point_type values: -DATA_TYPE_ANALOG_INPUT = 'AI' -DATA_TYPE_ANALOG_OUTPUT = 'AO' -DATA_TYPE_BINARY_INPUT = 'BI' -DATA_TYPE_BINARY_OUTPUT = 'BO' - -# PointDefinition.group -DEFAULT_GROUP_BY_DATA_TYPE = { - DATA_TYPE_BINARY_INPUT: 1, - DATA_TYPE_BINARY_OUTPUT: 10, - DATA_TYPE_ANALOG_INPUT: 30, - DATA_TYPE_ANALOG_OUTPUT: 40 -} - -# variation = 1: 32 bit, variation = 2: 16 bit -DEFAULT_VARIATION = { - DATA_TYPE_BINARY_INPUT: {'evariation': opendnp3.EventBinaryVariation.Group2Var1, - 'svariation': opendnp3.StaticBinaryVariation.Group1Var2}, - DATA_TYPE_BINARY_OUTPUT: {'evariation': opendnp3.EventBinaryOutputStatusVariation.Group11Var1, - 'svariation': opendnp3.StaticBinaryOutputStatusVariation.Group10Var2}, - DATA_TYPE_ANALOG_INPUT: {'evariation': opendnp3.EventAnalogVariation.Group32Var1, - 'svariation': opendnp3.StaticAnalogVariation.Group30Var1}, - DATA_TYPE_ANALOG_OUTPUT: {'evariation': opendnp3.EventAnalogOutputStatusVariation.Group42Var1, - 'svariation': opendnp3.StaticAnalogOutputStatusVariation.Group40Var1} -} - -# PointDefinition.event_class -DEFAULT_EVENT_CLASS = 2 - -EVENT_CLASSES = { - 0: opendnp3.PointClass.Class0, - 1: opendnp3.PointClass.Class1, - 2: opendnp3.PointClass.Class2, - 3: opendnp3.PointClass.Class3 -} - -DATA_TYPES_BY_GROUP = { - # Single-Bit Binary: See DNP3 spec, Section A.2-A.5 and Table 11-17 - 1: DATA_TYPE_BINARY_INPUT, # Binary Input (static): Reporting the present value of a single-bit binary object - 2: DATA_TYPE_BINARY_INPUT, # Binary Input Event: Reporting single-bit binary input events and flag bit changes - # Binary Output: See DNP3 spec, Section A.6-A.9 and Table 11-12 - 10: DATA_TYPE_BINARY_OUTPUT, # Binary Output (static): Reporting the present output status - 11: DATA_TYPE_BINARY_OUTPUT, # Binary Output Event: Reporting changes to the output status or flag bits - # Analog Input: See DNP3 spec, Section A.14-A.18 and Table 11-9 - 30: DATA_TYPE_ANALOG_INPUT, # Analog Input (static): Reporting the present value - 32: DATA_TYPE_ANALOG_INPUT, # Analog Input Event: Reporting analog input events or changes to the flag bits - # Analog Output: See DNP3 spec, Section A.19-A.22 and Table 11-10 - 40: DATA_TYPE_ANALOG_OUTPUT, # Analog Output Status (static): Reporting present value of analog outputs - 42: DATA_TYPE_ANALOG_OUTPUT # Analog Output Event: Reporting changes to the analog output or flag bits -} diff --git a/services/core/DNP3Agent/dnp3/agent.py b/services/core/DNP3Agent/dnp3/agent.py deleted file mode 100644 index 8ecbc7cd24..0000000000 --- a/services/core/DNP3Agent/dnp3/agent.py +++ /dev/null @@ -1,99 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, SLAC / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# This material was prepared as an account of work sponsored by an agency of -# the United States Government. Neither the United States Government nor the -# United States Department of Energy, nor SLAC, nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by the United States Government or any agency thereof, or -# SLAC, or Kisensum. The views and opinions of authors expressed -# herein do not necessarily state or reflect those of the -# United States Government or any agency thereof. -# }}} - -import logging -import sys - -from volttron.platform.agent import utils -from dnp3.base_dnp3_agent import BaseDNP3Agent - -utils.setup_logging() -_log = logging.getLogger(__name__) - -__version__ = '1.1' - - -class DNP3Agent(BaseDNP3Agent): - """ - DNP3Agent is a VOLTTRON agent that handles DNP3 outstation communications. - - DNP3Agent models a DNP3 outstation, communicating with a DNP3 master. - - For further information about this agent and DNP3 communications, please see the VOLTTRON - DNP3 specification, located in VOLTTRON readthedocs - under http://volttron.readthedocs.io/en/develop/specifications/dnp3_agent.html. - - This agent can be installed from a command-line shell as follows: - $ export VOLTTRON_ROOT= - $ cd $VOLTTRON_ROOT - $ source services/core/DNP3Agent/install_dnp3_agent.sh - """ - - def _process_point_value(self, point_value): - """DNP3Agent publishes each point value to the message bus as the value is received from the master.""" - point_val = super(DNP3Agent, self)._process_point_value(point_value) - if point_val: - self.publish_point_value(point_value) - - -def dnp3_agent(config_path, **kwargs): - """ - Parse the DNP3 Agent configuration. Return an agent instance created from that config. - - :param config_path: (str) Path to a configuration file. - :returns: (DNP3Agent) The DNP3 agent - """ - try: - config = utils.load_config(config_path) - except Exception: - config = {} - return DNP3Agent(points=config.get('points', None), - point_topic=config.get('point_topic', 'dnp3/point'), - local_ip=config.get('local_ip', '0.0.0.0'), - port=config.get('port', 20000), - outstation_config=config.get('outstation_config', {}), - **kwargs) - - -def main(): - """Main method called to start the agent.""" - utils.vip_main(dnp3_agent, identity='dnp3agent', version=__version__) - - -if __name__ == '__main__': - # Entry point for script - try: - sys.exit(main()) - except KeyboardInterrupt: - pass diff --git a/services/core/DNP3Agent/dnp3/base_dnp3_agent.py b/services/core/DNP3Agent/dnp3/base_dnp3_agent.py deleted file mode 100644 index 6a26645635..0000000000 --- a/services/core/DNP3Agent/dnp3/base_dnp3_agent.py +++ /dev/null @@ -1,517 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, SLAC / 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# This material was prepared in part as an account of work sponsored by an agency of -# the United States Government. Neither the United States Government nor the -# United States Department of Energy, nor SLAC, nor 8minutenergy, nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by the United States Government or any agency thereof, or -# SLAC, 8minutenergy, or Kisensum. The views and opinions of authors expressed -# herein do not necessarily state or reflect those of the -# United States Government or any agency thereof. -# }}} - -import logging -import numbers -import os - -from pydnp3 import opendnp3 - -from volttron.platform.vip.agent import RPC -from volttron.platform.agent import utils -from volttron.platform.messaging import headers -from volttron.platform.vip.agent import Agent - -from dnp3.outstation import DNP3Outstation -from dnp3 import DEFAULT_POINT_TOPIC, DEFAULT_OUTSTATION_STATUS_TOPIC -from dnp3 import DEFAULT_LOCAL_IP, DEFAULT_PORT -from dnp3 import DATA_TYPE_ANALOG_INPUT, DATA_TYPE_BINARY_INPUT -from dnp3 import PUBLISH_AND_RESPOND -from dnp3.points import PointDefinitions, PointArray -from dnp3.points import DNP3Exception - -utils.setup_logging() -_log = logging.getLogger(__name__) - - -class BaseDNP3Agent(Agent): - """ - DNP3Agent is a VOLTTRON agent that handles DNP3 outstation communications. - - DNP3Agent models a DNP3 outstation, communicating with a DNP3 master. - - For further information about this agent and DNP3 communications, please see the VOLTTRON - DNP3 specification, located in VOLTTRON readthedocs - under http://volttron.readthedocs.io/en/develop/specifications/dnp3_agent.html. - - This agent can be installed from a command-line shell as follows: - export VOLTTRON_ROOT= - export DNP3_ROOT=$VOLTTRON_ROOT/services/core/DNP3Agent - cd $VOLTTRON_ROOT - python scripts/install-agent.py -s $DNP3_ROOT -i dnp3agent -c $DNP3_ROOT/config -t dnp3agent -f - """ - - def __init__(self, points=None, point_topic='', local_ip=None, port=None, - outstation_config=None, local_point_definitions_path=None, **kwargs): - """Initialize the DNP3 agent.""" - super(BaseDNP3Agent, self).__init__(**kwargs) - self.points = points - self.point_topic = point_topic - self.local_ip = local_ip - self.port = port - self.outstation_config = outstation_config - self.default_config = { - 'points': points, - 'point_topic': point_topic, - 'local_ip': local_ip, - 'port': port, - 'outstation_config': outstation_config, - } - self.application = None - self.volttron_points = None - - self.point_definitions = None - self._current_point_values = {} - self._current_array = None - self._local_point_definitions_path = local_point_definitions_path - - self.vip.config.set_default('config', self.default_config) - self.vip.config.subscribe(self._configure, actions=['NEW', 'UPDATE'], pattern='config') - - def _configure(self, config_name, action, contents): - """Initialize/Update the agent configuration.""" - self._configure_parameters(contents) - - def load_point_definitions(self): - """ - Load and cache a dictionary of PointDefinitions from a json list. - - Index the dictionary by point_type and point index. - """ - _log.debug('Loading DNP3 point definitions.') - try: - self.point_definitions = PointDefinitions() - self.point_definitions.load_points(self.points) - except (AttributeError, TypeError) as err: - if self._local_point_definitions_path: - _log.warning("Attempting to load point definitions from local path.") - self.point_definitions = PointDefinitions(point_definitions_path=self._local_point_definitions_path) - else: - raise DNP3Exception("Failed to load point definitions from config store: {}".format(err)) - - def start_outstation(self): - """Start the DNP3Outstation instance, kicking off communication with the DNP3 Master.""" - _log.info('Starting DNP3Outstation') - self.publish_outstation_status('starting') - self.application = DNP3Outstation(self.local_ip, self.port, self.outstation_config) - self.application.start() - self.publish_outstation_status('running') - - def stop_outstation(self): - """Shutdown the DNP3Outstation application.""" - _log.info('Stopping DNP3Outstation') - self.publish_outstation_status('stopping') - self.application.shutdown() - self.publish_outstation_status('stopped') - self.application = None - - def _configure_parameters(self, contents): - """ - Initialize/Update the DNP3 agent configuration. - - DNP3Agent configuration parameters (the MesaAgent subclass has some more): - - points: (string) A JSON structure of point definitions to be loaded. - point_topic: (string) Message bus topic to use when publishing DNP3 point values. - Default: mesa/point. - outstation_status_topic: (string) Message bus topic to use when publishing outstation status. - Default: mesa/outstation_status. - local_ip: (string) Outstation's host address (DNS resolved). - Default: 0.0.0.0. - port: (integer) Outstation's port number - the port that the remote endpoint (Master) is listening on. - Default: 20000. - outstation_config: (dictionary) Outstation configuration parameters. All are optional. - Parameters include: - database_sizes: (integer) Size of each DNP3 database buffer. - Default: 10000. - event_buffers: (integer) Size of the database event buffers. - Default: 10. - allow_unsolicited: (boolean) Whether to allow unsolicited requests. - Default: True. - link_local_addr: (integer) Link layer local address. - Default: 10. - link_remote_addr: (integer) Link layer remote address. - Default: 1. - log_levels: List of bit field names (OR'd together) that filter what gets logged by DNP3. - Default: [NORMAL]. - Possible values: ALL, ALL_APP_COMMS, ALL_COMMS, NORMAL, NOTHING. - threads_to_allocate: (integer) Threads to allocate in the manager's thread pool. - Default: 1. - """ - config = self.default_config.copy() - config.update(contents) - self.points = config.get('points', []) - self.point_topic = config.get('point_topic', DEFAULT_POINT_TOPIC) - self.outstation_status_topic = config.get('outstation_status_topic', DEFAULT_OUTSTATION_STATUS_TOPIC) - self.local_ip = config.get('local_ip', DEFAULT_LOCAL_IP) - self.port = int(config.get('port', DEFAULT_PORT)) - self.outstation_config = config.get('outstation_config', {}) - _log.debug('DNP3Agent configuration parameters:') - _log.debug('\tpoints type={}'.format(type(self.points))) - _log.debug('\tpoint_topic={}'.format(self.point_topic)) - _log.debug('\toutstation_status_topic={}'.format(self.outstation_status_topic)) - _log.debug('\tlocal_ip={}'.format(self.local_ip)) - _log.debug('\tport={}'.format(self.port)) - _log.debug('\toutstation_config={}'.format(self.outstation_config)) - self.load_point_definitions() - DNP3Outstation.set_agent(self) - - # Stop outstation if DNP3 config has been changed - if self.application and ( - self.application.local_ip, self.application.port, self.application.outstation_config) != ( - self.local_ip, self.port, self.outstation_config): - self.stop_outstation() - - # Start outstation if the DNP3 application has not started - if not self.application: - self.start_outstation() - - return config - - @RPC.export - def reset(self): - """Reset the agent's internal state, emptying point value caches. Used during iterative testing.""" - _log.info('Resetting agent state.') - self._current_point_values = {} - self._current_array = {} - - def get_current_point_value(self, data_type, index): - """Return the most-recently-received PointValue for a given PointDefinition.""" - if data_type not in self._current_point_values or index not in self._current_point_values[data_type]: - return None - else: - return self._current_point_values[data_type][index] - - def _set_point(self, point_name, value): - """ - (Internal) Set the value of a given input point (no debug trace). - - @param point_name: The VOLTTRON point name of a DNP3 PointDefinition. - @param value: The value to set. The value's data type must match the one in the DNP3 PointDefinition. - """ - point_properties = self.volttron_points.get(point_name, {}) - data_type = point_properties.get('data_type', None) - index = point_properties.get('index', None) - try: - if data_type == DATA_TYPE_ANALOG_INPUT: - wrapped_value = opendnp3.Analog(value) - elif data_type == DATA_TYPE_BINARY_INPUT: - wrapped_value = opendnp3.Binary(value) - else: - raise Exception('Unexpected data type for DNP3 point named {0}'.format(point_name)) - DNP3Outstation.apply_update(wrapped_value, index) - except Exception as e: - raise DNP3Exception(e) - - def process_point_value(self, command_type, command, index, op_type): - """ - A point value was received from the Master. Process its payload. - - @param command_type: Either 'Select' or 'Operate'. - @param command: A ControlRelayOutputBlock or else a wrapped data value (AnalogOutputInt16, etc.). - @param index: DNP3 index of the payload's data definition. - @param op_type: An OperateType, or None if command_type == 'Select'. - @return: A CommandStatus value. - """ - try: - point_value = self.point_definitions.point_value_for_command(command_type, command, index, op_type) - if point_value is None: - return opendnp3.CommandStatus.DOWNSTREAM_FAIL - except Exception as ex: - _log.error('No DNP3 PointDefinition for command with index {}'.format(index)) - return opendnp3.CommandStatus.DOWNSTREAM_FAIL - - try: - self._process_point_value(point_value) - except Exception as ex: - _log.error('Error processing DNP3 command: {}'.format(ex)) - # Delete a cached point value (typically occurs only if an error is being handled). - try: - self._current_point_values.get(point_value.point_def.data_type, {}).pop(int(point_value.index), None) - except Exception as err: - _log.error('Error discarding cached value {}'.format(point_value)) - return opendnp3.CommandStatus.DOWNSTREAM_FAIL - - return opendnp3.CommandStatus.SUCCESS - - def _process_point_value(self, point_value): - _log.info('Received DNP3 {}'.format(point_value)) - if point_value.command_type == 'Select': - # Perform any needed validation now, then wait for the subsequent Operate command. - return None - else: - # Update a dictionary that holds the most-recently-received value of each point. - self._current_point_values.setdefault(point_value.point_def.data_type, {})[ - int(point_value.index)] = point_value - return point_value - - def get_point_named(self, point_name): - return self.point_definitions.get_point_named(point_name) - - def update_array_for_point(self, point_value): - """A received point belongs to a PointArray. Update it.""" - if point_value.point_def.is_array_head_point: - self._current_array = PointArray(point_value.point_def) - elif self._current_array is None: - raise DNP3Exception('Array point received, but there is no current Array.') - elif not self._current_array.contains_index(point_value.index): - raise DNP3Exception('Received Array point outside of current Array.') - self._current_array.add_point_value(point_value) - - def update_input_point(self, point_def, value): - """ - Update an input point. This may send its PointValue to the Master. - - :param point_def: A PointDefinition. - :param value: A value to send (unwrapped simple data type, or else a list/array). - """ - if type(value) == list: - # It's an array. Break it down into its constituent points, and apply each one separately. - col_count = len(point_def.array_points) - cols_by_name = {pt['name']: col for col, pt in enumerate(point_def.array_points)} - for row_number, point_dict in enumerate(value): - for pt_name, pt_val in point_dict.items(): - pt_index = point_def.index + col_count * row_number + cols_by_name[pt_name] - array_point_def = self.point_definitions.get_point_named(point_def.name, index=pt_index) - self._apply_point_update(array_point_def, pt_index, pt_val) - else: - self._apply_point_update(point_def, point_def.index, value) - - @staticmethod - def _apply_point_update(point_def, point_index, value): - """ - Set an input point in the outstation database. This may send its PointValue to the Master. - - :param point_def: A PointDefinition. - :param point_index: A numeric index for the point. - :param value: A value to send (unwrapped, simple data type). - """ - data_type = point_def.data_type - if data_type == DATA_TYPE_ANALOG_INPUT: - wrapped_val = opendnp3.Analog(float(value)) - if isinstance(value, bool) or not isinstance(value, numbers.Number): - # Invalid data type - raise DNP3Exception('Received {} value for {}.'.format(type(value), point_def)) - elif data_type == DATA_TYPE_BINARY_INPUT: - wrapped_val = opendnp3.Binary(value) - if not isinstance(value, bool): - # Invalid data type - raise DNP3Exception('Received {} value for {}.'.format(type(value), point_def)) - else: - # The agent supports only DNP3's Analog and Binary point types at this time. - raise DNP3Exception('Unsupported point type {}'.format(data_type)) - if wrapped_val is not None: - DNP3Outstation.apply_update(wrapped_val, point_index) - _log.debug('Sent DNP3 point {}, value={}'.format(point_def, wrapped_val.value)) - - def publish_point_value(self, point_value): - """Publish a PointValue as it is received from the DNP3 Master.""" - _log.info('Publishing DNP3 {}'.format(point_value)) - msg = { - point_value.name: (point_value.unwrapped_value() if point_value else None) - } - - if point_value.point_def.action == PUBLISH_AND_RESPOND: - msg.update({ - 'response': point_value.point_def.response - }) - - self.publish_data(self.point_topic, msg) - - def publish_outstation_status(self, outstation_status): - """Publish outstation status.""" - _log.info('Publishing outstation status: {}'.format(outstation_status)) - self.publish_data(self.outstation_status_topic, outstation_status) - - def publish_data(self, topic, msg): - """Publish a payload to the message bus.""" - try: - self.vip.pubsub.publish(peer='pubsub', - topic=topic, - headers={headers.TIMESTAMP: utils.format_timestamp(utils.get_aware_utc_now())}, - message=msg) - except Exception as err: - if os.environ.get('UNITTEST', False): - _log.debug('Disregarding publish_data exception during unit test') - else: - raise DNP3Exception('Error publishing topic {}, message {}: {}'.format(topic, msg, err)) - - def dnp3_point_name(self, point_name): - """ - Return a point's DNP3 point name, mapped from its VOLTTRON point name if necessary. - - If VOLTTRON point names were configured (by the DNP device driver), map them to DNP3 point names. - """ - dnp3_point_name = self.volttron_points.get(point_name, '') if self.volttron_points else point_name - if not dnp3_point_name: - raise DNP3Exception('No configured point for {}'.format(point_name)) - return dnp3_point_name - - @RPC.export - def get_point(self, point_name): - """ - Look up the most-recently-received value for a given output point. - - @param point_name: The point name of a DNP3 PointDefinition. - @return: The (unwrapped) value of a received point. - """ - _log.info('Getting point value for {}'.format(point_name)) - try: - point_name = self.dnp3_point_name(point_name) - point_def = self.point_definitions.get_point_named(point_name) - point_value = self.get_current_point_value(point_def.data_type, point_def.index) - return point_value.unwrapped_value() if point_value else None - except Exception as e: - raise DNP3Exception(e) - - @RPC.export - def get_point_by_index(self, data_type, index): - """ - Look up the most-recently-received value for a given point. - - @param data_type: The data_type of a DNP3 point. - @param index: The index of a DNP3 point. - @return: The (unwrapped) value of a received point. - """ - _log.info('Getting point value for data_type {} and index {}'.format(data_type, index)) - try: - point_value = self.get_current_point_value(data_type, index) - return point_value.unwrapped_value() if point_value else None - except Exception as e: - raise DNP3Exception(e) - - @RPC.export - def get_points(self, point_list): - """ - Look up the most-recently-received value of each configured output point. - - @param point_list: A list of point names. - @return: A dictionary of point values, indexed by their point names. - """ - _log.info('Getting values for the following points: {}'.format(point_list)) - try: - return {name: self.get_point(name) for name in point_list} - except Exception as e: - raise DNP3Exception(e) - - @RPC.export - def get_configured_points(self): - """ - Look up the most-recently-received value of each configured point. - - @return: A dictionary of point values, indexed by their point names. - """ - if self.volttron_points is None: - raise DNP3Exception('DNP3 points have not been configured') - - _log.info('Getting all DNP3 configured point values') - try: - return {name: self.get_point(name) for name in self.volttron_points} - except Exception as e: - raise DNP3Exception(e) - - @RPC.export - def set_point(self, point_name, value): - """ - Set the value of a given input point. - - @param point_name: The point name of a DNP3 PointDefinition. - @param value: The value to set. The value's data type must match the one in the DNP3 PointDefinition. - """ - _log.info('Setting DNP3 {} point value = {}'.format(point_name, value)) - try: - self.update_input_point(self.get_point_named(self.dnp3_point_name(point_name)), value) - - except Exception as e: - raise DNP3Exception(e) - - @RPC.export - def set_points(self, point_dict): - """ - Set point values for a dictionary of points. - - @param point_dict: A dictionary of {point_name: value} for a list of DNP3 points to set. - """ - _log.info('Setting DNP3 point values: {}'.format(point_dict)) - try: - for point_name, value in point_dict.items(): - self.update_input_point(self.get_point_named(self.dnp3_point_name(point_name)), value) - except Exception as e: - raise DNP3Exception(e) - - @RPC.export - def config_points(self, point_map): - """ - For each of the agent's points, map its VOLTTRON point name to its DNP3 group and index. - - @param point_map: A dictionary that maps a point's VOLTTRON point name to its DNP3 group and index. - """ - _log.info('Configuring DNP3 points: {}'.format(point_map)) - self.volttron_points = point_map - - @RPC.export - def get_point_definitions(self, point_name_list): - """ - For each DNP3 point name in point_name_list, return a dictionary with each of the point definitions. - - The returned dictionary looks like this: - - { - "point_name1": { - "property1": "property1_value", - "property2": "property2_value", - ... - }, - "point_name2": { - "property1": "property1_value", - "property2": "property2_value", - ... - } - } - - If a definition cannot be found for a point name, it is omitted from the returned dictionary. - - :param point_name_list: A list of point names. - :return: A dictionary of point definitions. - """ - _log.info('Fetching a list of DNP3 point definitions for {}'.format(point_name_list)) - try: - response = {} - for name in point_name_list: - point_def = self.point_definitions.get_point_named(self.dnp3_point_name(name)) - if point_def is not None: - response[name] = point_def.as_json() - return response - except Exception as e: - raise DNP3Exception(e) diff --git a/services/core/DNP3Agent/dnp3/mesa/__init__.py b/services/core/DNP3Agent/dnp3/mesa/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/core/DNP3Agent/dnp3/mesa/agent.py b/services/core/DNP3Agent/dnp3/mesa/agent.py deleted file mode 100644 index 4a0200a982..0000000000 --- a/services/core/DNP3Agent/dnp3/mesa/agent.py +++ /dev/null @@ -1,353 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} -import logging -import sys - -from volttron.platform.agent import utils -from volttron.platform.vip.agent import RPC - -from dnp3.base_dnp3_agent import BaseDNP3Agent - -from dnp3.points import DNP3Exception -from dnp3 import DEFAULT_LOCAL_IP, DEFAULT_PORT -from dnp3 import DEFAULT_POINT_TOPIC, DEFAULT_OUTSTATION_STATUS_TOPIC -from dnp3 import PUBLISH, PUBLISH_AND_RESPOND - -from dnp3.mesa.functions import DEFAULT_FUNCTION_TOPIC, ACTION_PUBLISH_AND_RESPOND -from dnp3.mesa.functions import FunctionDefinitions, Function, FunctionException - -__version__ = '1.1' - -utils.setup_logging() -_log = logging.getLogger(__name__) - - -class MesaAgent(BaseDNP3Agent): - """ - MesaAgent is a VOLTTRON agent that handles MESA-ESS DNP3 outstation communications. - - MesaAgent models a DNP3 outstation, communicating with a DNP3 master. - - For further information about this agent, MESA-ESS, and DNP3 communications, please - see the VOLTTRON MESA-ESS agent specification, which can be found in VOLTTRON readthedocs - at http://volttron.readthedocs.io/en/develop/specifications/mesa_agent.html. - - This agent can be installed from a command-line shell as follows: - $ export VOLTTRON_ROOT= - $ cd $VOLTTRON_ROOT - $ source services/core/DNP3Agent/install_mesa_agent.sh - That file specifies a default agent configuration, which can be overridden as needed. - """ - - def __init__(self, functions=None, function_topic='', outstation_status_topic='', - all_functions_supported_by_default=False, - local_function_definitions_path=None, function_validation=False, **kwargs): - """Initialize the MESA agent.""" - super(MesaAgent, self).__init__(**kwargs) - self.functions = functions - self.function_topic = function_topic - self.outstation_status_topic = outstation_status_topic - self.all_functions_supported_by_default = all_functions_supported_by_default - self.function_validation = function_validation - - # Update default config - self.default_config.update({ - 'functions': functions, - 'function_topic': function_topic, - 'outstation_status_topic': outstation_status_topic, - 'all_functions_supported_by_default': all_functions_supported_by_default, - 'function_validation': function_validation - }) - - # Update default config in config store. - self.vip.config.set_default('config', self.default_config) - - self.function_definitions = None - self._local_function_definitions_path = local_function_definitions_path - - self._current_functions = dict() # {function_id: Function} - self._current_block = dict() # {name: name, index: index} - self._selector_block = dict() # {selector_block_point_name: {selector_index: [Step]}} - self._edit_selectors = list() # [{name: name, index: index}] - - def _configure_parameters(self, contents): - """ - Initialize/Update the MesaAgent configuration. - - See also the superclass version of this method, which does most of the initialization. - MesaAgent configuration parameters: - - functions: (string) A JSON structure of function definitions to be loaded. - function_topic: (string) Message bus topic to use when publishing MESA-ESS functions. - Default: mesa/function. - all_functions_supported_by_default: (boolean) When deciding whether to reject points for unsupported - functions, ignore the values of their 'supported' points: simply treat all functions as - supported. - Default: False. - """ - config = super(MesaAgent, self)._configure_parameters(contents) - self.functions = config.get('functions', {}) - self.function_topic = config.get('function_topic', DEFAULT_FUNCTION_TOPIC) - self.all_functions_supported_by_default = config.get('all_functions_supported_by_default', False) - self.function_validation = config.get('function_validation', False) - _log.debug('MesaAgent configuration parameters:') - _log.debug('\tfunctions type={}'.format(type(self.functions))) - _log.debug('\tfunction_topic={}'.format(self.function_topic)) - _log.debug('\tall_functions_supported_by_default={}'.format(bool(self.all_functions_supported_by_default))) - _log.debug('\tfuntion_validation={}'.format(bool(self.function_validation))) - self.load_function_definitions() - self.supported_functions = [] - # Un-comment the next line to do more detailed validation and print definition statistics. - # validate_definitions(self.point_definitions, self.function_definitions) - - def load_function_definitions(self): - """Populate the FunctionDefinitions repository from JSON in the config store.""" - _log.debug('Loading MESA function definitions') - try: - self.function_definitions = FunctionDefinitions(self.point_definitions) - self.function_definitions.load_functions(self.functions['functions']) - except (AttributeError, TypeError) as err: - if self._local_function_definitions_path: - _log.warning("Attempting to load Function Definitions from local path.") - self.function_definitions = FunctionDefinitions( - self.point_definitions, - function_definitions_path=self._local_function_definitions_path) - else: - raise DNP3Exception("Failed to load Function Definitions from config store: {}".format(err)) - - @RPC.export - def reset(self): - """Reset the agent's internal state, emptying point value caches. Used during iterative testing.""" - super(MesaAgent, self).reset() - self._current_functions = dict() - self._current_block = dict() - self._selector_block = dict() - self._edit_selectors = list() - - @RPC.export - def get_selector_block(self, block_name, index): - try: - return {step.definition.name: step.as_json() for step in self._selector_block[block_name][index]} - except KeyError: - _log.debug('Have not received data for Selector Block {} at Edit Selector {}'.format(block_name, index)) - return None - - def _process_point_value(self, point_value): - """ - A PointValue was received from the Master. Process its payload. - - :param point_value: A PointValue. - """ - try: - point_val = super(MesaAgent, self)._process_point_value(point_value) - - if point_val: - if point_val.point_def.is_selector_block: - self._current_block = { - 'name': point_val.point_def.name, - 'index': float(point_val.value) - } - _log.debug('Starting to receive Selector Block {name} at Edit Selector {index}'.format( - **self._current_block - )) - - # Publish mesa/point if the point action is PUBLISH or PUBLISH_AND_RESPOND - if point_val.point_def.action in (PUBLISH, PUBLISH_AND_RESPOND): - self.publish_point_value(point_value) - - self.update_function_for_point_value(point_val) - - if self._current_functions: - for current_func_id, current_func in self._current_functions.items(): - # if step action is ACTION_ECHO or ACTION_ECHO_AND_PUBLISH - if current_func.has_input_point(): - self.update_input_point( - self.get_point_named(current_func.input_point_name()), - point_val.unwrapped_value() - ) - - # if step is the last curve or schedule step - if self._current_block and point_val.point_def == current_func.definition.last_step.point_def: - current_block_name = self._current_block['name'] - self._selector_block.setdefault(current_block_name, dict()) - self._selector_block[current_block_name][self._current_block['index']] = current_func.steps - - _log.debug('Saved Selector Block {} at Edit Selector {}: {}'.format( - self._current_block['name'], - self._current_block['index'], - self.get_selector_block(self._current_block['name'], self._current_block['index']) - )) - - self._current_block = dict() - - # if step reference to a curve or schedule function - func_ref = current_func.last_step.definition.func_ref - if func_ref: - block_name = self.function_definitions[func_ref].first_step.name - block_index = float(point_val.value) - if not self._selector_block.get(block_name, dict()).get(block_index, None): - error_msg = 'Have not received data for Selector Block {} at Edit Selector {}' - raise DNP3Exception(error_msg.format(block_name, block_index)) - current_edit_selector = { - 'name': block_name, - 'index': block_index - } - if current_edit_selector not in self._edit_selectors: - self._edit_selectors.append(current_edit_selector) - - # if step action is ACTION_PUBLISH, ACTION_ECHO_AND_PUBLISH, or ACTION_PUBLISH_AND_RESPOND - if current_func.publish_now(): - self.publish_function_step(current_func.last_step) - - # if current function is completed - if current_func.complete: - self._current_functions.pop(current_func_id) - self._edit_selectors = list() - - except (DNP3Exception, FunctionException) as err: - self._current_functions = dict() - self._edit_selectors = list() - if type(err) == DNP3Exception: - raise DNP3Exception('Error processing point value: {}'.format(err)) - - def update_function_for_point_value(self, point_value): - """Add point_value to the current Function if appropriate.""" - error_msg = None - current_functions = self.current_function_for(point_value.point_def) - if not current_functions: - return None - for function_id, current_function in current_functions.items(): - try: - if point_value.point_def.is_array_point: - self.update_array_for_point(point_value) - current_function.add_point_value(point_value, - current_array=self._current_array, - function_validation=self.function_validation) - except (DNP3Exception, FunctionException) as err: - current_functions.pop(function_id) - if type(err) == DNP3Exception: - error_msg = err - if error_msg and not current_functions: - raise DNP3Exception('Error updating function: {}'.format(error_msg)) - - def current_function_for(self, new_point_def): - """A point was received. Return the current Function, updating it if necessary.""" - new_point_function_def = self.function_definitions.get_fdef_for_pdef(new_point_def) - if new_point_function_def is None: - return None - if self._current_functions: - current_funcs = dict() - for func_def in new_point_function_def: - val = self._current_functions.pop(func_def.function_id, None) - if val: - current_funcs.update({func_def.function_id: val}) - self._current_functions = current_funcs - else: - for func_def in new_point_function_def: - if not self.all_functions_supported_by_default and not func_def.supported: - raise DNP3Exception('Received a point for unsupported {}'.format(func_def)) - self._current_functions[func_def.function_id] = Function(func_def) - return self._current_functions - - def update_input_point(self, point_def, value): - """ - Update an input point. This may send its PointValue to the Master. - - :param point_def: A PointDefinition. - :param value: A value to send (unwrapped simple data type, or else a list/array). - """ - super(MesaAgent, self).update_input_point(point_def, value) - if type(value) != list: - # Side-effect: If it's a Support point for a Function, update the Function's "supported" property. - func = self.function_definitions.support_point_names().get(point_def.name, None) - if func is not None and func.supported != value: - _log.debug('Updating supported property to {} in {}'.format(value, func)) - func.supported = value - - def publish_function_step(self, step_to_send): - """A Function Step was received from the DNP3 Master. Publish the Function.""" - function_to_send = step_to_send.function - - points = {step.definition.name: step.as_json() for step in function_to_send.steps} - for edit_selector in self._edit_selectors: - block_name = edit_selector['name'] - index = edit_selector['index'] - try: - points[block_name][index] = self.get_selector_block(block_name, index) - except (KeyError, TypeError): - points[block_name] = { - index: self.get_selector_block(block_name, index) - } - - msg = { - "function_id": function_to_send.definition.function_id, - "function_name": function_to_send.definition.name, - "points": points - } - if step_to_send.definition.action == ACTION_PUBLISH_AND_RESPOND: - msg["expected_response"] = step_to_send.definition.response - _log.info('Publishing MESA {} message {}'.format(function_to_send, msg)) - self.publish_data(self.function_topic, msg) - - -def mesa_agent(config_path, **kwargs): - """ - Parse the MesaAgent configuration. Return an agent instance created from that config. - - :param config_path: (str) Path to a configuration file. - :returns: (MesaAgent) The MESA agent - """ - try: - config = utils.load_config(config_path) - except Exception: - config = {} - return MesaAgent(points=config.get('points', []), - functions=config.get('functions', []), - point_topic=config.get('point_topic', DEFAULT_POINT_TOPIC), - function_topic=config.get('function_topic', DEFAULT_FUNCTION_TOPIC), - outstation_status_topic=config.get('outstation_status_topic', DEFAULT_OUTSTATION_STATUS_TOPIC), - local_ip=config.get('local_ip', DEFAULT_LOCAL_IP), - port=config.get('port', DEFAULT_PORT), - outstation_config=config.get('outstation_config', {}), - all_functions_supported_by_default=config.get('all_functions_supported_by_default', False), - function_validation=config.get('function_validation', False), - **kwargs) - - -def main(): - """Main method called to start the agent.""" - utils.vip_main(mesa_agent, identity='mesaagent', version=__version__) - - -if __name__ == '__main__': - # Entry point for script - try: - sys.exit(main()) - except KeyboardInterrupt: - pass diff --git a/services/core/DNP3Agent/dnp3/mesa/conversion.py b/services/core/DNP3Agent/dnp3/mesa/conversion.py deleted file mode 100644 index ea2592cab2..0000000000 --- a/services/core/DNP3Agent/dnp3/mesa/conversion.py +++ /dev/null @@ -1,4 +0,0 @@ -import sys, yaml, json - -y=yaml.safe_load(sys.stdin.read()) -print(json.dumps(y)) diff --git a/services/core/DNP3Agent/dnp3/mesa/functions.py b/services/core/DNP3Agent/dnp3/mesa/functions.py deleted file mode 100644 index aabc934752..0000000000 --- a/services/core/DNP3Agent/dnp3/mesa/functions.py +++ /dev/null @@ -1,570 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} -import argparse -import logging -import os -import collections.abc -import yaml - -from dnp3.points import PointDefinitions, PointDefinition, DNP3Exception - -DEFAULT_FUNCTION_TOPIC = 'mesa/function' - -# Values of StepDefinition.optional -OPTIONAL = 'O' -MANDATORY = 'M' -INITIALIZE = 'I' -ALL_OPTIONALITY = [OPTIONAL, MANDATORY, INITIALIZE] - -# Values of the elements of StepDefinition.fcodes: -DIRECT_OPERATE = 'direct_operate' # This is actually DIRECT OPERATE / RESPONSE -SELECT = 'select' # This is actually SELECT / RESPONSE -OPERATE = 'operate' # This is actually OPERATE / RESPONSE -READ = 'read' -RESPONSE = 'response' - -# Values of StepDefinition.action: -ACTION_ECHO = 'echo' -ACTION_PUBLISH = 'publish' -ACTION_ECHO_AND_PUBLISH = 'echo_and_publish' -ACTION_PUBLISH_AND_RESPOND = 'publish_and_respond' -ACTION_NONE = 'none' - -_log = logging.getLogger(__name__) - - -class FunctionDefinitions(collections.abc.Mapping): - """In-memory repository of FunctionDefinitions.""" - - def __init__(self, point_definitions, function_definitions_path=None): - """Data holder for all MESA-ESS functions.""" - self._point_definitions = point_definitions - self._functions = dict() # {function_id: FunctionDefinition} - self._pdef_function_map = dict() # {PointDefinition: [FunctionDefinition]} - if function_definitions_path: - file_path = os.path.expandvars(os.path.expanduser(function_definitions_path)) - self.load_functions_from_yaml_file(file_path) - - def __getitem__(self, function_id): - """Return the function associated with this function_id. Must be unique.""" - return self._functions[function_id] - - def __iter__(self): - return iter(self._functions) - - def __len__(self): - """Return the total number of functions from FunctionDefinitions.""" - return len(self._functions) - - @property - def all_function_ids(self): - """Return all function_id from FunctionDefinitions.""" - return self._functions.keys() - - @property - def function_def_lst(self): - """Return a list of all FunctionDefinition in the FunctionDefinitions.""" - return self._functions.values() - - def support_point_names(self): - """Return a dictionary of FunctionDefinitions keyed by their (non-null) support_point_names.""" - return {f.support_point_name: f - for f_id, f in self._functions.items() - if f.support_point_name is not None} - - def function_for_id(self, function_id): - """Return a specific function definition from (cached) dictionary of FunctionDefinitions.""" - return self._functions.get(function_id, None) - - def load_functions_from_yaml_file(self, function_definitions_path): - """Load and cache a YAML file of FunctionDefinitions. Index them by function name.""" - _log.debug('Loading MESA-ESS FunctionDefinitions from {}.'.format(function_definitions_path)) - if function_definitions_path: - fdef_path = os.path.expandvars(os.path.expanduser(function_definitions_path)) - self._functions = {} - try: - with open(fdef_path, 'r') as f: - self.load_functions(yaml.safe_load(f)['functions']) - except Exception as err: - raise ValueError('Problem parsing {}. Error={}'.format(fdef_path, err)) - _log.debug('Loaded {} FunctionDefinitions'.format(len(self._functions.keys()))) - - def get_fdef_for_pdef(self, pdef): - """ - Return a list of FunctionDefinition that contains the PointDefinition or None otherwise. - - :param pdef: PointDefinition - """ - return self._pdef_function_map.get(pdef, None) - - def load_functions(self, function_definitions_json): - """ - Load and cache a JSON dictionary of FunctionDefinitions. Index them by function ID. - Check if function_id is unique and func_ref in steps are valid. - """ - self._functions = {} - try: - for function_def in function_definitions_json: - new_function = FunctionDefinition(self._point_definitions, function_def) - function_id = new_function.function_id - if self._functions.get(function_id, None): - raise ValueError('There are multiple functions for function id {}'.format(function_id)) - self._functions[function_id] = new_function - for pdef in new_function.all_point_defs(): - try: - self._pdef_function_map[pdef].append(new_function) - except KeyError: - self._pdef_function_map[pdef] = [new_function] - except Exception as err: - raise ValueError('Problem parsing FunctionDefinitions. Error={}'.format(err)) - - for fdef in self.function_def_lst: - for step in fdef.steps: - func_ref = step.func_ref - if func_ref and func_ref not in self.all_function_ids: - raise ValueError('Invalid Function Reference {} for Step {} in Function {}'. format( - func_ref, - step.step_number, - fdef.function_id - )) - - _log.debug('Loaded {} FunctionDefinitions'.format(len(self))) - - -class FunctionDefinition: - """A MESA-ESS FunctionDefinition (aka mode, command).""" - - def __init__(self, point_definitions, function_def_dict): - """ - Data holder for the definition of a MESA-ESS function. Including parsing data validation. - self._point_steps_map: dictionary mapping PointDefinition including all Array points to StepDefinition - self.steps: a list of all StepDefinition (not including array points) in the function - """ - self.function_id = function_def_dict.get('id', None) # Must be unique - self.name = function_def_dict.get('name', None) - self.mode_types = function_def_dict.get('mode_types', {}) - self.ref = function_def_dict.get('ref', None) - self.support_point_name = function_def_dict.get('support_point', None) - self._point_steps_map = {} - - # function_id and steps validation - if not self.function_id: - raise ValueError('Missing function ID') - json_steps = function_def_dict.get('steps', None) - if not json_steps: - raise ValueError('Missing steps for function {}'.format(self.function_id)) - - step_numbers = list() - try: - self.steps = [StepDefinition(point_definitions, self.function_id, step_def) for step_def in json_steps] - is_selector_block = self.is_selector_block - for step in self.steps: - step_number = step.step_number - - # Check if there are duplicated step number - if step_number in step_numbers: - raise ValueError('Duplicated step number {} for function {}'.format(step_number, self.function_id)) - step_numbers.append(step_number) - - # If function is selector block (curve or schedule), all steps must be mandatory or initialize - if is_selector_block and step.optional not in [INITIALIZE, MANDATORY]: - raise ValueError( - 'Function {} - Step {}: optionality must be either INITIALIZE or MANDATORY'.format( - self.function_id, step_number)) - - # Update self._point_steps_map - for pd in step.all_point_defs(): - self._point_steps_map[pd] = step - except AttributeError as err: - raise AttributeError('Error creating FunctionDefinition {}, err={}'.format(self.name, err)) - - # Check is there is missing steps - if set([i for i in range(1, len(self.steps) + 1)]) != set(step_numbers): - raise ValueError('There are missing steps for function {}'.format(self.function_id)) - - def __str__(self): - return 'Function {}'.format(self.name) - - def __contains__(self, point_def): - return point_def in self.all_point_defs() - - def __getitem__(self, point_def): - return self._point_steps_map[point_def] - - @property - def supported(self): - """ - Set supported to False if the Function has a defined support_point_name -- the Control Agent must set it. - To override this (support all functions), set config all_functions_supported_by_default = "True". - """ - return not self.support_point_name - - @property - def first_step(self): - """First step of the function. Mainly used for Selector Block.""" - for step in self.steps: - if step.step_number == 1: - return step - return None - - @property - def last_step(self): - """Last step of the function. Mainly used for Selector Block.""" - for step in self.steps: - if step.step_number == len(self.steps): - return step - return None - - @property - def is_selector_block(self): - return self.first_step.point_def and self.first_step.point_def.is_selector_block - - def instance(self): - """Return an instance of this FunctionDefinition.""" - return Function(self) - - def describe_function(self): - """Return a string describing a function: its name and all of its StepDefinitions.""" - return 'Function {}: {}'.format(self.name, [s.__str__() for s in self.steps]) - - def all_point_defs(self): - """Return all point definition including array points.""" - return self._point_steps_map.keys() - - def all_points(self): - """Return all point definition not including array points and None points.""" - return [step_def.point_def for step_def in self.steps if step_def] - - def is_mode(self): - """Return True if there is mode enable point in the function, False otherwise.""" - for point in self.all_points(): - if point and point.category == 'mode_enable': - return True - return False - - def get_mode_enable(self): - """Return a list of all mode enable points in the function.""" - return [point for point in self.all_points() if point and point.category == 'mode_enable'] - - -class StepDefinition: - """Step definition in a MESA-ESS FunctionDefinition.""" - - def __init__(self, point_definitions, function_id, step_def=None): - """ - Data holder for the definition of a step in a MESA-ESS FunctionDefinition. - - :param function_def: The FunctionDefinition to which the StepDefinition belongs. - :param step_def: A dictionary of data from which to create the StepDefinition. - """ - self.function_id = function_id - self.name = step_def.get('point_name', None) - self.point_def = point_definitions[self.name] - self.step_number = step_def.get('step_number', None) - self.optional = step_def.get('optional', OPTIONAL) - self.fcodes = step_def.get('fcodes', []) - self.action = step_def.get('action', None) - self.func_ref = step_def.get('func_ref', None) - self.description = step_def.get('description', None) - self.validate() - - try: - self.response = point_definitions[step_def.get('response', None)] - except Exception as err: - raise AttributeError('Response point in function {} step {} does not match point definition. Error={}'.format( - self.function_id, - self.step_number, - err - )) - - def __str__(self): - return '{} Step {}: {}'.format(self.function_id, self.step_number, self.name) - - def all_point_defs(self): - """Return a list of all PointDefinition including all Array points""" - all_defs = [self.point_def] - if self.point_def and self.point_def.is_array_head_point: - all_defs.extend(self.point_def.array_point_definitions) - return all_defs - - def validate(self): - if self.step_number is None: - raise AttributeError('Missing step number in function {}'.format(self.function_id)) - if not self.name: - raise AttributeError('Missing name in function {} step {}'.format(self.function_id, self.step_number)) - if self.optional not in ALL_OPTIONALITY: - raise AttributeError('Invalid optional value in function {} step {}: {}'.format(self.function_id, - self.step_number, - self.optional)) - if type(self.fcodes) != list: - raise AttributeError('Invalid fcodes in function {} step {}, type={}'.format(self.function_id, - self.step_number, - type(self.fcodes))) - for fc in self.fcodes: - if fc not in [DIRECT_OPERATE, SELECT, OPERATE, READ, RESPONSE]: - raise AttributeError('Invalid fcode in function {} step {}, fcode={}'.format(self.function_id, - self.step_number, - fc)) - if fc == READ and self.optional != OPTIONAL: - raise AttributeError('Invalid optionality in function {} step {}: must be OPTIONAL'.format( - self.function_id, - self.step_number - )) - - -class Step: - """A MESA-ESS Step that has been received by an outstation.""" - - def __init__(self, definition, func, value): - """ - Data holder for a received Step. - - :param definition: A StepDefinition. - :param value: A PointValue. - """ - self.definition = definition - self.function = func - self.value = value - - def __str__(self): - return '{}: {}'.format(self.definition, self.value) - - def as_json(self): - return self.value.as_json() if self.definition.point_def.is_array_head_point else self.value.unwrapped_value() - - def echoes_input(self): - return self.definition.action in [ACTION_ECHO, ACTION_ECHO_AND_PUBLISH] - - def publish(self): - return self.definition.action in [ACTION_PUBLISH, - ACTION_ECHO_AND_PUBLISH, - ACTION_PUBLISH_AND_RESPOND] - - -class FunctionException(Exception): - """ - Raise exceptions that are used for _process_point_value in Mesa agent. - Set the current function to None if the exception is raised. - """ - pass - - -class Function: - """A MESA-ESS Function that has been received by an outstation.""" - - def __init__(self, definition): - """ - Data holder for a Function received by an outstation. - - :param definition: A FunctionDefinition. - """ - self.definition = definition - self.steps = [] - - def __str__(self): - return 'Function {}'.format(self.definition.name) - - def __contains__(self, point_def): - if not isinstance(point_def, PointDefinition): - raise ValueError("Membership test only works for PointDefinition instance, not {}".format(point_def)) - return point_def in self.definition - - @property - def last_step(self): - """ - Return last received step of the function. - """ - return self.steps[-1] if self.steps else None - - @property - def complete(self): - """ - Return True if function is completed, False otherwise. - """ - if self.next_remaining_mandatory_step_number: - return False - return True - - @property - def next_remaining_mandatory_step_number(self): - """ - Return next remaining mandatory step number of the function if there is one existed, None otherwise. - """ - last_received_step_number = 0 if not self.last_step else self.last_step.definition.step_number - for step_def in self.definition.steps: - step_number = step_def.step_number - if step_number > last_received_step_number and step_def.optional in [MANDATORY, INITIALIZE]: - return step_number - return None - - def add_step(self, step_def, value, function_validation=False): - """ - Add a step to function if no mandatory step missing and return the step, raise exception otherwise. - - :param step_def: step definition to add to function - :param value: value of the point in step_def - :param function_validation: defaults to False. - When there is mandatory step missing, raise DNP3Exception if function_validation is True, - raise FunctionException otherwise. - FunctionException is used for _process_point_value in Mesa agent, if the FunctionException is raised, - reset current function to None and process the next point as the first step of a new function. - """ - # Check for missing mandatory steps up to the current step - if self.next_remaining_mandatory_step_number \ - and step_def.step_number > self.next_remaining_mandatory_step_number: - exception_message = '{} is missing Mandatory step number {}'.format( - self, - self.next_remaining_mandatory_step_number - ) - if function_validation: - raise DNP3Exception(exception_message) - raise FunctionException(exception_message) - # add current step to self.steps - step_value = Step(step_def, self, value) - self.steps.append(step_value) - return step_value - - def add_point_value(self, point_value, current_array=None, function_validation=False): - """ - Add a received PointValue as a Step in the current Function. Return the Step. - - :param point_value: point value - :param current_array: current array - :param function_validation: defaults to False. If function_validation is True, - raise DNP3Exception when getting an error while adding a new step to the current function. - If function_validation is False, reset current function to None if missing mandatory step, - set the adding step as the first step of the current function if step is not in order, - or replace the last step by the adding step if step is duplicated. - """ - step_def = self.definition[point_value.point_def] - step_number = step_def.step_number - if not self.last_step: - self.add_step(step_def, point_value, function_validation) - else: - last_received_step_number = self.last_step.definition.step_number - if step_number != last_received_step_number: - if step_number < last_received_step_number: - if self.next_remaining_mandatory_step_number: - if function_validation: - raise DNP3Exception('Step {} received after {}'.format(step_number, - last_received_step_number)) - # Since the old function was complete, treat this as the first step of a new function. - self.steps = [] - self.add_step(step_def, point_value, function_validation) - else: - if not point_value.point_def.is_array_point: - if function_validation: - raise DNP3Exception('Duplicate step number {} received'.format(step_number)) - self.steps.pop() - self.add_step(step_def, point_value, function_validation) - else: - # An array point was received for an existing step. Update the step's value. - self.last_step.value = current_array - - return self.last_step - - def has_input_point(self): - """Function has an input pont to be echoed following last step.""" - return self.last_step.echoes_input() if self.last_step else False - - def input_point_name(self): - """The name of the input point - - @todo This really should be a point_def - """ - return self.last_step.definition.response if self.last_step else '' - - def publish_now(self): - """The function has points to published following last step.""" - return self.last_step.publish() if self.last_step else False - - -def load_and_validate_definitions(): - """ - Standalone method, intended to be invoked from the command line. - - Load PointDefinition and FunctionDefinition files as specified in command line args, - and validate their contents. - """ - # Grab JSON and YAML definition file paths from the command line. - parser = argparse.ArgumentParser() - parser.add_argument('point_defs', help='path of the point definitions file (json)') - parser.add_argument('function_defs', help='path of the function definitions file (yaml)') - args = parser.parse_args() - - point_definitions = PointDefinitions(point_definitions_path=args.point_defs) - function_definitions = FunctionDefinitions(point_definitions, function_definitions_path=args.function_defs) - validate_definitions(point_definitions, function_definitions) - - -def validate_definitions(point_definitions, function_definitions): - """Validate PointDefinitions, Arrays, SelectorBlocks and FunctionDefinitions.""" - - print('\nValidating Point definitions...') - all_points = point_definitions.all_points() - print('\t{} point definitions'.format(len(all_points))) - - print('\nValidating Array definitions...') - array_head_points = [pt for pt in all_points if pt.is_array_head_point] - array_bounds = {pt: [pt.index, pt.array_last_index] for pt in array_head_points} - for pt in array_head_points: - # Print each array's definition. Also, check for overlapping array bounds. - print('\t{} ({}): indexes=({},{}), elements={}'.format(pt.name, - pt.data_type, - pt.index, - pt.array_last_index, - len(pt.array_points))) - for other_pt, other_bounds in array_bounds.iteritems(): - if pt.name != other_pt.name: - if other_bounds[0] <= pt.index <= other_bounds[1]: - print('\tERROR: Overlapping array definition in {} and {}'.format(pt, other_pt)) - if other_bounds[0] <= pt.array_last_index <= other_bounds[1]: - print('\tERROR: Overlapping array definition in {} and {}'.format(pt, other_pt)) - print('\t{} array definitions'.format(len(array_head_points))) - - print('\nValidating Selector Block definitions...') - selector_block_points = [pt for pt in all_points if pt.is_selector_block] - selector_block_bounds = {pt: [pt.selector_block_start, pt.selector_block_end] for pt in selector_block_points} - for pt in selector_block_points: - # Print each selector block's definition. Also, check for overlapping selector block bounds. - print('\t{} ({}): indexes=({},{})'.format(pt.name, - pt.data_type, - pt.selector_block_start, - pt.selector_block_end)) - for other_pt, other_bounds in selector_block_bounds.iteritems(): - if pt.name != other_pt.name: - if other_bounds[0] <= pt.selector_block_start <= other_bounds[1]: - print('\tERROR: Overlapping selector blocks in {} and {}'.format(pt, other_pt)) - if other_bounds[0] <= pt.selector_block_end <= other_bounds[1]: - print('\tERROR: Overlapping selector blocks in {} and {}'.format(pt, other_pt)) - # Check that each save_on_write point references a selector_block_point - print('\t{} selector block definitions'.format(len(selector_block_points))) - print('\nValidating Function definitions...') - functions = function_definitions.all_function_ids - print('\t{} function definitions'.format(len(functions))) diff --git a/services/core/DNP3Agent/dnp3/mesa/mesa_functions.yaml b/services/core/DNP3Agent/dnp3/mesa/mesa_functions.yaml deleted file mode 100644 index 500f52d3eb..0000000000 --- a/services/core/DNP3Agent/dnp3/mesa/mesa_functions.yaml +++ /dev/null @@ -1,2595 +0,0 @@ -functions: -- id: connect_and_disconnect - name: Connect and Disconnect - ref: AN2018 Spec section 2.4.4 Table 29 - steps: - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DCTE.WinTms.AO16 - response: DCTE.WinTms.AI60 - step_number: 1 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DCTE.RvrtTms.AO17 - response: DCTE.RvrtTms.AI61 - step_number: 2 - - description: Retrieve status of switch - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.off.BI23 - step_number: 3 - - action: publish - description: Issue switch control command and receive response - fcodes: - - select - - operate - optional: M - point_name: CSWI.Pos.BO5 - response: DSTO.DEROpSt.off.BI23 - step_number: 4 - - description: Detect if switch is moving - fcodes: - - read - - response - optional: O - point_name: n/a - response: CSWI.Pos.BI24 - step_number: 5 -- id: cease_to_energize_and_return_to_service - name: Cease to Energize and Return to Service - ref: AN2018 Spec section 2.4.5 Table 30 - steps: - - description: Set Cease to Energize Time Window - fcodes: - - direct_operate - optional: I - point_name: DCTE.WinTms.AO13 - response: DCTE.WinTms.AI57 - step_number: 1 - - description: Set Cease to Energize Ramp DownTime - fcodes: - - direct_operate - optional: I - point_name: DCTE.RmpTms.AO14 - response: DCTE.RmpTms.AI58 - step_number: 2 - - description: Set Cease to Energize Timeout Period - fcodes: - - direct_operate - optional: I - point_name: DCTE.RvrtTms.AO15 - response: DCTE.RvrtTms.AI59 - step_number: 3 - - description: Cause DER to Cease to Energize - fcodes: - - select - - operate - optional: M - point_name: DCTE.CeaEngzReq.BO2 - response: DSTO.DEROpSt.connectedandidle.BI14 - step_number: 4 - - description: Give DER Permission to Stop - fcodes: - - select - - operate - optional: M - point_name: DSTO.PrmDscon.BO4 - response: DSTO.PrmDscon.BI17 - step_number: 5 - - description: Confirm DER is Stopping - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.stopping.BI13 - step_number: 6 - - description: Confirm DER has Ceased to Energize - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.ceasedtoenergize.BI15 - step_number: 7 - - description: Set High Voltage Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.VHiLim.AO6 - response: DCTE.VHiLim.AI50 - step_number: 8 - - description: Set Low Voltage Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.VLoLim.AO7 - response: DCTE.VLoLim.AI51 - step_number: 9 - - description: Set High Frequency Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.HzHiLim.AO8 - response: DCTE.HzHiLim.AI52 - step_number: 10 - - description: Set Low Frequency Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.HzLoLim.AO9 - response: DCTE.HzLoLim.AI53 - step_number: 11 - - description: Set Delay Time - fcodes: - - direct_operate - optional: I - point_name: DCTE.RtnDlyTmms.AO10 - response: DCTE.RtnDlTmms.AI54 - step_number: 12 - - description: Set Return to Service Time Window - fcodes: - - direct_operate - optional: I - point_name: DCTE.WinTms.AO11 - response: DCTE.WinTms.AI55 - step_number: 13 - - description: Set Return to Service Ramp Up Time - fcodes: - - direct_operate - optional: I - point_name: DCTE.RtnRmpTmms.AO12 - response: DCTE.RtnRmpTmms.AI56 - step_number: 14 - - description: Cause DER to Return to Service - fcodes: - - select - - operate - optional: M - point_name: DCTE.RtnSrvReq.BO1 - response: DSTO.DEROpSt.startingandsynchronizing.BI12 - step_number: 15 - - action: publish - description: Give DER Permission to Start - fcodes: - - select - - operate - optional: M - point_name: DSTO.PrmConn.BO3 - response: DSTO.PrmConn.BI16 - step_number: 16 - - description: Confirm DER is Started - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.connectedandidle.BI14 - step_number: 17 -- id: enable_low_high_voltage_ride-through_mode - mode_types: - curve: - - 9 - - 10 - - 11 - - 12 - schedule: - - 1 - - 2 - - 3 - - 4 - name: Enable Low/High Voltage Ride-Through Mode - ref: AN2018 Spec section 2.5.1 Table 33 - steps: - - description: Set the Reference Voltage if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 1 - - description: Set the Reference Voltage Offset if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 2 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHVT.EcpRef.AO22 - response: DHVT.EcpRef.AI71 - step_number: 3 - - description: 'DGSMn.ModTyp.AO245 = <9> HVRT Must Trip: If the curve is a must - trip curve, identify the index of the curve which specifies trip points when - the voltage is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOV.BlkRef.AO23 - response: PTOV.BlkRef.AI73 - step_number: 4 - - description: 'DGSMn.ModTyp.AO245 = <11> LVRT Must Trip: If the curve is a must - trip curve, identify the index of the curve which specifies trip points when - the voltage is low' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUV.BlkRef.AO24 - response: PTUV.BlkRef.AI74 - step_number: 5 - - description: 'DGSMn.ModTyp.AO245 = <10> HVRT Momentary Cessation: If the curve - is a must trip curve, identify the index of the curve which specifies where - generation/discharging must stop when the voltage is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOV.BlkRef.AO25 - response: PTOV.BlkRef.AI75 - step_number: 6 - - description: 'DGSMn.ModTyp.AO245 = <12> LVRT Momentary Cessation: If the curve - is a must trip curve, identify the index of the curve which specifies where - generation/discharging must stop when the voltage is low' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUV.BlkRef.AO26 - response: PTUV.BlkRef.AI76 - step_number: 7 - - action: publish - description: Enable the Low/High Voltage Ride-Through Mode - fcodes: - - select - - operate - optional: M - point_name: DHVT.ModEna.BO12 - response: DHVT.ModEna.BI64 - step_number: 8 -- id: enable_low_high_frequency_ride-through_mode - mode_types: - curve: - - 13 - - 14 - - 15 - - 16 - schedule: - - 5 - - 6 - - 7 - - 8 - name: Enable Low/High Frequency Ride-Through Mode - ref: AN2018 Spec section 2.5.2 Table 35 - steps: - - description: Set the Nominal Grid Frequency if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.EcpNomHz.AO2 - response: DECP.EcpNomHz.AI31 - step_number: 1 - - description: Identify the meter used to measure the frequency. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHFT.EcpRef.AO27 - response: DHFT.EcpRef.AI77 - step_number: 2 - - description: 'DGSMn.ModTyp.AO245 = <13> HFRT Must Trip: Identify the index of - the frequency ride through curve which specifies trip ponts when the frequency - is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOF.BlkRef.AO28 - response: PTOF.BlkRef.AI79 - step_number: 3 - - description: 'DGSMn.ModTyp.AO245 = <15> LFRT Must Trip: Identify the index of - the frequency ride through curve which specifies trip ponts when the voltage - is low' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUF.BlkRef.AO29 - response: PTUF.BlkRef.AI80 - step_number: 4 - - description: 'DGSMn.ModTyp.AO245 = <14> HFRT Mandatory Operation: Identify the - index of the frequency ride through curve which specifies where generation/discharging - must stop when the frequency is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOF.BlkRef.AO30 - response: PTOF.BlkRef.AI81 - step_number: 5 - - description: 'DGSMn.ModTyp.AO245 = <16> LFRT Mandatory Operation: Identify the - index of the frequency ride through curve which specifies where generation/discharging - must stop when the frequency is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUF.BlkRef.AO31 - response: PTUF.BlkRef.AI82 - step_number: 6 - - action: publish - description: Enable the Low/High Frequency Ride-Through Mode - fcodes: - - select - - operate - optional: M - point_name: DHFT.ModEna.BO13 - response: DHFT.ModEna.BI65 - step_number: 7 -- id: enable_frequency-watt_mode - name: Enable Frequency-Watt Mode - ref: AN2018 Spec section 2.5.3 Table 36 - mode_types: - schedule: - - 11 - steps: - - description: If not already established, set the Nominal Grid Frequency - fcodes: - - direct_operate - optional: I - point_name: DECP.EcpNomHz.AO2 - response: DECP.EcpNomHz.AI31 - step_number: 1 - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW2.ModPrio.AO57 - response: DHFW2.ModPrio.AI115 - step_number: 2 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DHFW.WinTms.AO58 - response: DHFW.WinTms.AI116 - step_number: 3 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DHFW.RmpTms.AO59 - response: DHFW.RmpTms.AI117 - step_number: 4 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DHFW.RvrtTms.AO60 - response: DHFW.RvrtTms.AI118 - step_number: 5 - - description: Identify the meter used to measure the frequency. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHFW.EcpRef.AO61 - response: DHFW2.EcpRef.AI119 - step_number: 6 - - description: Set the High Starting Frequency - fcodes: - - direct_operate - optional: I - point_name: DHFW.HzStr.AO62 - response: DHFW2.HzStr.AI121 - step_number: 7 - - description: Set the High Stopping Frequency - fcodes: - - direct_operate - optional: I - point_name: DHFW.HzStop.AO63 - response: DHFW2.HzStop.AI122 - step_number: 8 - - description: Set the High Discharging Gradient - fcodes: - - direct_operate - optional: I - point_name: DHFW.WGra.AO64 - response: DHFW.WGra.AI123 - step_number: 9 - - description: Set the High Charging Gradient - fcodes: - - direct_operate - optional: I - point_name: DHFW.WChaGra.AO65 - response: DHFW.WChaGra.AI124 - step_number: 10 - - description: Set the Low Starting Frequency - fcodes: - - direct_operate - optional: I - point_name: DLFW.HzStr.AO66 - response: DLFW2.HzStr.AI125 - step_number: 11 - - description: Set the Low Stopping Frequency - fcodes: - - direct_operate - optional: I - point_name: DLFW.HzStop.AO67 - response: DLFW2.HzStop.AI126 - step_number: 12 - - description: Set the Low Discharging Gradient - fcodes: - - direct_operate - optional: I - point_name: DLFW.WGra.AO68 - response: DLFW.WGra.AI127 - step_number: 13 - - description: Set the Low Charging Gradient - fcodes: - - direct_operate - optional: I - point_name: DLFW.WChaGra.AO69 - response: DLFW.WChaGra.AI128 - step_number: 14 - - description: Set the Start Delay - fcodes: - - direct_operate - optional: I - point_name: DHFW2.ActStrDlTmms.AO70 - response: DHFW2.ActStrDlTmms.AI129 - step_number: 15 - - description: Set the Stop Delay - fcodes: - - direct_operate - optional: I - point_name: DHFW2.ActStopDlTmms.AO71 - response: DHFW2.ActStopDlTmms.AI130 - step_number: 16 - - description: Set the Ramp Up Time Constant - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoop.AO72 - response: DLFW.OpnLoopMax.AI131 - step_number: 17 - - description: Set the Ramp Down Time Constant - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoop.AO73 - response: DHFW.OpnLoopMax.AI132 - step_number: 18 - - description: Set the Discharging Up Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.DschRpuRte.AO74 - response: DHFW.RpuRte.AI133 - step_number: 19 - - description: Set the Discharging Down Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.DschRpdRte.AO75 - response: DHFW.RpdRteMax.AI134 - step_number: 20 - - description: Set the Charging Up Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.ChaRpuRte.AO76 - response: DHFW.RpuChaRte.AI135 - step_number: 21 - - description: Set the Charging Down Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.ChaRpdRte.AO77 - response: DHFW.RpdChaRteMax.AI136 - step_number: 22 - - description: Set the Hight Return Gradient - fcodes: - - direct_operate - optional: I - point_name: DHFW.RtnRmpRte.AO78 - response: DHFW2.RtnRmpRte.AI137 - step_number: 23 - - description: Set the Low Return Gradient - fcodes: - - direct_operate - optional: I - point_name: DLFW.RtnRmpRte.AO79 - response: DLFW2.RtnRmpRte.AI138 - step_number: 24 - - description: Set the minium State of Charge to be used by this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMin.AO80 - response: DAGC.SocUseMinPct.AI140 - step_number: 25 - - description: Set the maximum State of Charge to be used by this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMax.AO81 - response: DAGC.SocUseMaxPct.AI141 - step_number: 26 - - description: Enable or Disable Hysteresis - fcodes: - - direct_operate - optional: I - point_name: DHFW.HysEna.BO34 - response: DHFW.HysEna.BI86 - step_number: 27 - - description: Enable or Disable Snapshot of Power - fcodes: - - direct_operate - optional: I - point_name: DHFW.SnptEna.BO35 - response: DHFW.SnptEna.BI87 - step_number: 28 - - action: publish - description: Enable Frequency-Watt Mode - fcodes: - - select - - operate - optional: M - point_name: DHFW.ModEna.BO16 - response: DHFW.ModEna.BI68 - step_number: 29 -- id: enable_dynamic_reactive_current_support_mode - name: Enable Dynamic Reactive Current Support Mode - ref: AN2018 Spec section 2.5.4 Table 37 - mode_types: - schedule: - - 9 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DRGS.ModPrio.AO32 - response: DRGS.ModPrio.AI83 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DRGS.WinTms.AO33 - response: DRGS.WinTms.AI84 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DRGS.RmpTms.AO34 - response: DRGS.RmpTms.AI85 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DRGS.RvrtTms.AO35 - response: DRGS.RvrtTms.AI86 - step_number: 4 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DRGS.EcpRef.AO36 - response: DRGS.EcpRef.AI87 - step_number: 5 - - description: Set the Gradient Mode to select the curve shape - fcodes: - - direct_operate - optional: M - point_name: DRGS.ArGraMod.AO37 - response: DRGS.ArGraMod.AI91 - step_number: 6 - - description: Set the Deadband Minimum Voltage - fcodes: - - direct_operate - optional: M - point_name: DRGS.DbVMin.AO38 - response: DRGS.DbVMin.AI92 - step_number: 7 - - description: Set the Deadband Maximum Voltage - fcodes: - - direct_operate - optional: M - point_name: DRGS.DbVMax.AO39 - response: DRGS.DbVMax.AI93 - step_number: 8 - - description: Set the Reactive Current Support Gradient for Sags - fcodes: - - direct_operate - optional: M - point_name: DRGS.ArGraSag.AO40 - response: DRGS.ArGraSag.AI94 - step_number: 9 - - description: Set the Reactive Current Support Gradient for Swells - fcodes: - - direct_operate - optional: M - point_name: DRGS.ArGraSwl.AO41 - response: DRGS.ArGraSwl.AI95 - step_number: 10 - - description: Set the Filter Time for the Moving Average Voltage in seconds - fcodes: - - direct_operate - optional: M - point_name: DRGS.FilTms.AO42 - response: DRGS.FilTms.AI96 - step_number: 11 - - description: Enable Event-Based Reactive Current Support if required. It shall - default to Disabled. - fcodes: - - direct_operate - optional: I - point_name: DRGS.ArGraMod.BO33 - response: DRGS.ModEna.BI85 - step_number: 12 - - description: Set the Hold Time in milliseconds if Event-Based Reactive Current - Support is required. - fcodes: - - direct_operate - optional: I - point_name: DRGS.HoldTmms.AO46 - response: DRGS.HoldTmms.AI100 - step_number: 13 - - description: Set the Block Zone Voltage if required. Otherwise it shall default - to zero. - fcodes: - - direct_operate - optional: I - point_name: DRGS.BlkZnV.AO43 - response: DRGS.BlkZnV.AI97 - step_number: 14 - - description: Set the Hysteresis Block Zone Voltage if required. Otherwise it - shall default to zero. - fcodes: - - direct_operate - optional: I - point_name: DRGS.HysBlkZnV.AO44 - response: DRGS.HysBlkZnV.AI98 - step_number: 15 - - description: Set the Block Zone Time in milliseconds if required. Otherwise it - shall default to zero. - fcodes: - - direct_operate - optional: I - point_name: DRGS.BlkZnTmms.AO45 - response: DRGS.BlkZnTmms.AI99 - step_number: 16 - - action: publish - description: Enable Dynamic Reactive Current Mode - fcodes: - - select - - operate - optional: M - point_name: DRGS.ModEna.BO14 - response: DRGS.ModEna.BI66 - step_number: 17 -- id: enable_volt-watt_mode - name: Enable Volt-Watt Mode - ref: AN2018 Spec section 2.5.5 Table 38 - steps: - - description: If not already established, set the Reference Voltage - fcodes: - - direct_operate - optional: I - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 1 - - description: If not already established, set the Reference Voltage Offset - fcodes: - - direct_operate - optional: I - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 2 - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVWD.ModPrio.AO48 - response: DVWD.ModPrio.AI102 - step_number: 3 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DVWD.WinTms.AO49 - response: DVWD.WinTms.AI103 - step_number: 4 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DVWD.RmpTms.AO50 - response: DVWD.RmpTms.AI104 - step_number: 5 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVWD.RvrtTms.AO51 - response: DVWD.RvrtTms.AI105 - step_number: 6 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DVWD2.EcpRef.AO52 - response: DVWD2.EcpRef.AI106 - step_number: 7 - - description: Set the Dynamic Volt-Watt Gradient - fcodes: - - direct_operate - optional: I - point_name: DVWD.DynVWGra.AO53 - response: DVWD.DynVWGra.AI110 - step_number: 8 - - description: Set the Dynamic Volt-Watt Filter Time - fcodes: - - direct_operate - optional: I - point_name: DVWD.VWFilTms.AO54 - response: DVWD.VWFilTms.AI111 - step_number: 9 - - description: Set the Dynamic Volt-Watt Lower Deadband - fcodes: - - direct_operate - optional: I - point_name: DVWD.DbVWLo.AO55 - response: DVWD.DbVWLo.AI112 - step_number: 10 - - description: Set the Dynamic Volt-Watt Upper Deadband - fcodes: - - direct_operate - optional: I - point_name: DVWD.DbVWHi.AO56 - response: DVWD.DbVWHi.AI113 - step_number: 11 - - action: publish - description: Enable Dynamic Volt-Watt mode - fcodes: - - select - - operate - optional: M - point_name: DVWD.ModEna.BO15 - response: DVWD.ModEna.BI67 - step_number: 12 -- id: enable_active_power_limit_mode - name: Enable Active Power Limit Mode - ref: AN2018 Spec section 2.6.1 Table 39 - mode_types: - schedule: - - 12 - - 13 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWMX.ModPrio.AO82 - response: DWMX.ModPrio.AI142 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DWMX.WinTms.AO83 - response: DWMX.WinTms.AI143 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DWMX.RmpTms.AO84 - response: DWMX.RmpTms.AI144 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWMX.RvrtTms.AO85 - response: DWMX.RvrtTms.AI145 - step_number: 4 - - description: Identify the meter used to measure the active power. By default - this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DWMX.EcpRef.AO86 - response: DWMX.EcpRef.AI146 - step_number: 5 - - description: Retrieve Maximum Active Generation Power Capability - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.WMax.AI32 - step_number: 6 - - description: Retrieve Maximum Active Charging Power Capability - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.ChaWMax.AI33 - step_number: 7 - - description: Set maximum output in percent of nominal Watts (Charging) - fcodes: - - direct_operate - optional: M - point_name: DWMX.WLimPct.AO87 - response: DWMX.WLimPct.AI148 - step_number: 8 - - description: Set maximum output in percent of nominal Watts (Generating) - fcodes: - - direct_operate - optional: M - point_name: DWMN.WLimPct.AO88 - response: DWMN.WLimPct.AI149 - step_number: 9 - - action: publish - description: Enable Active Power Limit mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DWLM.ModEna.BO17 - response: DWLM.ModEna.BI69 - step_number: 10 -- id: enable_charge_discharge_storage_mode - name: Enable Charge/Discharge Storage Mode - ref: AN2018 Spec section 2.6.2 Table 41 - mode_types: - schedule: - - 14 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWGC.ModPrio.AO89 - response: DWGC.ModPrio.AI150 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DWGC.WinTms.AO90 - response: DWGC.WinTms.AI151 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DWGC.RmpTms.AO91 - response: DWGC.RmpTms.AI152 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWGC.RvrtTms.AO92 - response: DWGC.RvrtTms.AI153 - step_number: 4 - - description: Select whether to use Ramp Rates or Time Constants - fcodes: - - direct_operate - optional: I - point_name: DWGC.UseRmpRte.BO38 - response: DWGC.UseRmpRte.BI90 - step_number: 5 - - description: 'If DWGC.UseRmpRte = 0: Set Charge/Discharge Time Constant Ramp Up - Time' - fcodes: - - direct_operate - optional: O - point_name: DWGC.OpnLoop.AO94 - response: DWGC.OpnLoopMax.AI155 - step_number: 6 - - description: 'If DWGC.UseRmpRte = 0: Set Charge/Discharge Time Constant Ramp Down - Time' - fcodes: - - direct_operate - optional: O - point_name: DWGC.OpnLoop.AO95 - response: DWGC.OpnLoopMax.AI156 - step_number: 7 - - description: 'If DWGC.UseRmpRte = 1: Set Discharge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.DschRpuRte.AO96 - response: DWGC.RpuRte.AI157 - step_number: 8 - - description: 'If DWGC.UseRmpRte = 1: Set Discharge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.DschRpdRte.AO97 - response: DWGC.RpdRteMax.AI158 - step_number: 9 - - description: 'If DWGC.UseRmpRte = 1: Set Charge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.ChaRpuRte.AO98 - response: DWGC.RpuChaRte.AI159 - step_number: 10 - - description: 'If DWGC.UseRmpRte = 1: Set Charge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.ChaRpdRte.AO99 - response: DWGC.RpdChaRteMax.AI160 - step_number: 11 - - description: Set Minimum Reserve for Storage (percent of Battery Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DWGC.SocUseMinPct.AO100 - response: DWGC.SocUseMinPct.AI161 - step_number: 12 - - description: Set Maximum Reserve for Storage (percent of Battery Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DWGC.SocUseMaxPct.AO101 - response: DWGC.SocUseMaxPct.AI162 - step_number: 13 - - description: Set discharge/charge Active Power Target. Positive is discharging, - negative is charging. - fcodes: - - direct_operate - optional: M - point_name: DWGC.GnWPctSpt.AO93 - response: DWGC.GnWPctSpt.AI154 - step_number: 14 - - action: publish - description: Enable charge/discharge mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DWGC.ModEna.BO18 - response: DWGC.ModEna.BI70 - step_number: 15 -- id: enable_coordinated_charge_discharge_management_mode - name: Enable Coordinated Charge/Discharge Management Mode - ref: AN2018 Spec section 2.6.3 Table 42 - mode_types: - schedule: - - 15 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DTCD.ModPrio.AO102 - response: DTCD.ModPrio.AI163 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DTCD.WinTms.AO103 - response: DTCD.WinTms.AI164 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DTCD.RmpTms.AO104 - response: DTCD.RmpTms.AI165 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DTCD.RvrtTms.AO105 - response: DTCD.RvrtTms.AI166 - step_number: 4 - - description: Set the Target State of Charge, as a percentage of Usable Capacity - fcodes: - - direct_operate - optional: M - point_name: DTCD.SocUseTgtPct.AO106 - response: DTCD.SocUseTgtPct.AI167 - step_number: 5 - - description: Set the Target Date Charge Needed - fcodes: - - direct_operate - optional: M - point_name: DTCD.DateTgt.AO107 - response: DTCD.DateTgt.AI168 - step_number: 6 - - description: Set the Target Time Charge Needed (milliseconds since midnight) - fcodes: - - direct_operate - optional: M - point_name: DTCD.DateTgtTms.AO108 - response: DTCD.DateTgtTms.AI169 - step_number: 7 - - action: publish - description: Enable coordinated charge/discharge mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DWGC.ModEna.BO18 - response: DTCD.ModEna.BI71 - step_number: 8 -- id: enable_active_power_response_mode_1 - name: Enable Active Power Response Mode 1 - ref: AN2018 Spec section 2.6.4 Table 43 - mode_types: - schedule: - - 16 - steps: - - description: 'Set the priority of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.ModPrio.AO115 - response: DPKP.ModPrio.AI176 - step_number: 1 - - description: 'Set enabling time window of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.WinTms.AO116 - response: DPKP.WinTms.AI177 - step_number: 2 - - description: 'Set enabling ramp time of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RmpTms.AO117 - response: DPKP.RmpTms.AI178 - step_number: 3 - - description: 'Set reversion timeout period of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RvrtTms.AO118 - response: DPKP.RvrtTms.AI179 - step_number: 4 - - description: 'Identify the meter used to measure the Reference Power Input of - mode #1. By default this is the System Meter (ID = 0)' - fcodes: - - direct_operate - optional: I - point_name: DPKP.EcpRef.AO119 - response: DPKP.EcpRef.AI180 - step_number: 5 - - description: 'Set the power threshold for activating mode #1' - fcodes: - - direct_operate - optional: M - point_name: DPKP.PkPwrWLim.AO120 - response: DPKP.PkPwrWLim.AI182 - step_number: 6 - - description: 'Set the ratio used to calculate the output power from the measured - power of mode #1' - fcodes: - - direct_operate - optional: M - point_name: DPKP.PkPwrFolPct.AO121 - response: DPKP.PkPwrFolPct.AI183 - step_number: 7 - - description: 'Set the maximum ramp up rate of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RpuRte.AO122 - response: DPKP.RpuRte.AI184 - step_number: 8 - - description: 'Set the maximum ramp down rate of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RpdRte.AO123 - response: DPKP.RpdRte.AI185 - step_number: 9 - - action: publish - description: 'Enable the active response mode #1' - fcodes: - - select - - operate - optional: M - point_name: DPKP.ModEna.BO20 - response: DPKP.ModEna.BI72 - step_number: 10 -- id: enable_active_power_response_mode_2 - name: Enable Active Power Response Mode 2 - ref: AN2018 Spec section 2.6.4 Table 43 - mode_types: - schedule: - - 17 - steps: - - description: 'Set the priority of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.ModPrio.AO124 - response: DGFL.ModPrio.AI187 - step_number: 1 - - description: 'Set enabling time window of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.WinTms.AO125 - response: DGFL.WinTms.AI188 - step_number: 2 - - description: 'Set enabling ramp time of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RmpTms.AO126 - response: DGFL.RmpTms.AI189 - step_number: 3 - - description: 'Set reversion timeout period of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RvrtTms.AO127 - response: DGFL.RvrtTms.AI190 - step_number: 4 - - description: 'Identify the meter used to measure the Reference Power Input of - mode #2. By default this is the System Meter (ID = 0)' - fcodes: - - direct_operate - optional: I - point_name: DGFL.EcpRef.AO128 - response: DGFL.EcpRef.AI191 - step_number: 5 - - description: 'Set the power threshold for activating mode #2' - fcodes: - - direct_operate - optional: M - point_name: DGFL.PkPwrWLim.AO129 - response: DGFL.PkPwrWLim.AI193 - step_number: 6 - - description: 'Set the ratio used to calculate the output power from the measured - power of mode #2' - fcodes: - - direct_operate - optional: M - point_name: DGFL.PkPwrFolPct.AO130 - response: DGFL.PkPwrFolPct.AI194 - step_number: 7 - - description: 'Set the maximum ramp up rate of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RpuRte.AO131 - response: DGFL.RpuRte.AI195 - step_number: 8 - - description: 'Set the maximum ramp down rate of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RpdRte.AO132 - response: DGFL.RpdRte.AI196 - step_number: 9 - - action: publish - description: 'Enable the active response mode #2' - fcodes: - - select - - operate - optional: M - point_name: DGFL.ModEna.BO21 - response: DGFL.ModEna.BI73 - step_number: 10 -- id: enable_active_power_response_mode_3 - name: Enable Active Power Response Mode 3 - ref: AN2018 Spec section 2.6.4 Table 43 - mode_types: - schedule: - - 18 - steps: - - description: 'Set the priority of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.ModPrio.AO133 - response: DLFL.ModPrio.AI198 - step_number: 1 - - description: 'Set enabling time window of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.WinTms.AO134 - response: DLFL.WinTms.AI199 - step_number: 2 - - description: 'Set enabling ramp time of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RmpTms.AO135 - response: DLFL.RmpTms.AI200 - step_number: 3 - - description: 'Set reversion timeout period of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RvrtTms.AO136 - response: DLFL.RvrtTms.AI201 - step_number: 4 - - description: 'Identify the meter used to measure the Reference Power Input of - mode #3. By default this is the System Meter (ID = 0)' - fcodes: - - direct_operate - optional: I - point_name: DLFL.EcpRef.AO137 - response: DLFL.EcpRef.AI202 - step_number: 5 - - description: 'Set the power threshold for activating mode #3' - fcodes: - - direct_operate - optional: M - point_name: DLFL.PkPwrWLim.AO138 - response: DLFL.PkPwrWLim.AI204 - step_number: 6 - - description: 'Set the ratio used to calculate the output power from the measured - power of mode #3' - fcodes: - - direct_operate - optional: M - point_name: DLFL.PkPwrFolPct.AO139 - response: DLFL.PkPwrFolPct.AI205 - step_number: 7 - - description: 'Set the maximum ramp up rate of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RpuRte.AO140 - response: DLFL.RpuRte.AI206 - step_number: 8 - - description: 'Set the maximum ramp down rate of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RpdRte.AO141 - response: DLFL.RpdRte.AI207 - step_number: 9 - - action: publish - description: 'Enable the active response mode #3' - fcodes: - - select - - operate - optional: M - point_name: DLFL.ModEna.BO22 - response: DLFL.ModEna.BI74 - step_number: 10 -- id: perform_automatic_generation_control_mode - name: Perform Automatic Generation Control Mode - ref: AN2018 Spec section 2.6.5 Table 45 - mode_types: - schedule: - - 19 - steps: - - description: Set priority of the mode - fcodes: - - direct_operate - optional: I - point_name: DAGC.ModPrio.AO142 - response: DAGC.ModPrio.AI209 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DAGC.WinTms.AO143 - response: DAGC.WinTms.AI210 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DAGC.RmpTms.AO144 - response: DAGC.RmpTms.AI211 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DAGC.RvrtTms.AO145 - response: DAGC.RvrtTms.AI212 - step_number: 4 - - description: Select whether to use Ramp Rates or Time Constants - fcodes: - - direct_operate - optional: I - point_name: DAGC.UseRmpRte.BO39 - response: DAGC.UseRmpRte.BI91 - step_number: 5 - - description: 'If DAGC.UseRmpRte = 0: Set AGC Ramp Time Constant Up Time' - fcodes: - - direct_operate - optional: O - point_name: DAGC.OpnLoop.AO147 - response: DAGC.RmpUpTms.AI214 - step_number: 6 - - description: 'If DAGC.UseRmpRte = 0: Set AGC Ramp Time Constant Down Time' - fcodes: - - direct_operate - optional: O - point_name: DAGC.OpnLoop.AO148 - response: DAGC.RmpDnTms.AI215 - step_number: 7 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Discharge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.DschRpuRte.AO149 - response: DAGC.RpuRte.AI216 - step_number: 8 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Discharge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.DschRpdRte.AO150 - response: DAGC.RpdRte.AI217 - step_number: 9 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Charge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.ChaRpuRte.AO151 - response: DAGC.RpuChaRte.AI218 - step_number: 10 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Charge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.ChaRpdRte.AO152 - response: DAGC.RpdChaRte.AI219 - step_number: 11 - - description: Set Minimum Usable State of Charge (percent of Usable Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DAGC.SocUseMinPct.AO153 - response: DAGC.SocUseMinPct.AI220 - step_number: 12 - - description: Set Maximum Usable State of Charge (percent of Usable Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DAGC.SocUseMaxPct.AO154 - response: DAGC.SocUseMaxPct.AI221 - step_number: 13 - - description: Set the Active Power Target (in Watts) Positive is discharging, negative - is charging. - fcodes: - - direct_operate - optional: M - point_name: DAGC.GnWSpt.AO146 - response: DAGC.GnWSpt.AI213 - step_number: 14 - - description: Enable AGC mode and receive response. - fcodes: - - select - - operate - optional: M - point_name: DAGC.ModEna.BO23 - response: DAGC.ModEna.BI75 - step_number: 15 - - action: publish - description: Once the mode is enabled, periodically update the Active Power Target. - fcodes: - - direct_operate - optional: M - point_name: DAGC.GnWSpt.AO146 - response: DAGC.GnWSpt.AI213 - step_number: 16 - - description: Read the predicted State of Charge - fcodes: - - read - optional: O - point_name: n/a - response: DAGC.SocExpc.AI224 - step_number: 17 -- id: enable_active_power_smoothing - name: Enable Active Power Smoothing - ref: AN2018 Spec section 2.6.6 Table 46 - mode_types: - schedule: - - 20 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWSM.ModPrio.AO155 - response: DWSM.ModPrio.AI227 - step_number: 1 - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DWSM.WinTms.AO156 - response: DWSM.WinTms.AI228 - step_number: 2 - - description: Set ramp time - fcodes: - - direct_operate - optional: I - point_name: DWSM.RmpTms.AO157 - response: DWSM.RmpTms.AI229 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWSM.RvrtTms.AO158 - response: DWSM.RvrtTms.AI230 - step_number: 4 - - description: Identify the meter used to measure the Reference Power Input. By - default this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DWSM.EcpRef.AO159 - response: DWSM.EcpRef.AI231 - step_number: 5 - - description: Set the Active Power Smoothing Gradient - fcodes: - - direct_operate - optional: I - point_name: DWSM.WSmthGra.AO160 - response: DWSM.WSmthGra.AI233 - step_number: 6 - - description: Set the Active Power Smoothing Lower Limit - fcodes: - - direct_operate - optional: I - point_name: DWSM.WSmthLoLim.AO161 - response: DWSM.WSmthLoLim.AI234 - step_number: 7 - - description: Set the Active Power Smoothing Upper Limit - fcodes: - - direct_operate - optional: I - point_name: DWSM.WSmthHiLim.AO162 - response: DWSM.WSmthHiLim.AI235 - step_number: 8 - - description: Set the Active Power Smoothing Filter Time - fcodes: - - direct_operate - optional: I - point_name: DWSM.FilTms.AO163 - response: DWSM.FilTms.AI236 - step_number: 9 - - description: Set the Discharge Ramp Up Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.DschRpuRte.AO164 - response: DWSM.RpuRte.AI237 - step_number: 10 - - description: Set the Discharge Ramp Down Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.DschRpdRte.AO165 - response: DWSM.RpdRte.AI238 - step_number: 11 - - description: Set the Charge Ramp Up Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.ChaRpuRte.AO166 - response: DWSM.RpuChaRte.AI239 - step_number: 12 - - description: Set the Charge Ramp Down Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.ChaRpdRte.AO167 - response: DWSM.RpdChaRte.AI240 - step_number: 13 - - action: publish - description: Enable Active Power Smoothing Mode - fcodes: - - select - - operate - optional: M - point_name: DWSM.ModEna.BO24 - response: DWSM.ModEna.BI76 - step_number: 14 -- id: enable_volt-watt_curve - mode_types: - curve: - - 5 - schedule: - - 21 - name: Enable Volt-Watt Curve - ref: AN2018 Spec section 2.6.7 Table 47 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVWC.ModPrio.AO168 - response: DVWC.ModPrio.AI242 - step_number: 1 - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DVWC.WinTms.AO169 - response: DVWC.WinTms.AI243 - step_number: 2 - - description: Set ramp time - fcodes: - - direct_operate - optional: I - point_name: DVWC.RmpTms.AO170 - response: DVWC.RmpTms.AI244 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVWC.RvrtTms.AO171 - response: DVWC.RvrtTms.AI245 - step_number: 4 - - description: Identify the meter used to measure the Voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DVWC.EcpRef.AO172 - response: DVWC.EcpRef.AI246 - step_number: 5 - - description: Set the reference voltage if it has not already been set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 6 - - description: Set the reference voltage offset if it has not already been set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 7 - - description: Identify the index of the curve being used - fcodes: - - direct_operate - func_ref: curve - optional: M - point_name: DVWC.VWCrv.AO173 - response: DVWC.VWCrv.AI248 - step_number: 8 - - action: publish - description: Enable the Volt-Watt Mode - fcodes: - - select - - operate - optional: M - point_name: DVWC.ModEna.BO25 - response: DVWC.ModEna.BI77 - step_number: 9 - - description: Read the maximum active power the outstation will attempt to generate - or absorb based on the voltage and the curve in use. - fcodes: - - read - optional: O - point_name: n/a - response: DVWC.ReqWLim.AI249 - step_number: 10 - - description: Read the actual active power produced or absorbed - fcodes: - - read - optional: O - point_name: n/a - response: MMXU.TotW.AI537 - step_number: 11 -- id: enable_frequency-watt_curve_mode - mode_types: - curve: - - 3 - schedule: - - 22 - - 23 - - 24 - name: Enable Frequency-Watt Curve Mode - ref: AN2018 Spec section 2.6.8 Table 48 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW.ModPrio.AO181 - response: DHFW.ModPrio.AI257 - step_number: 1 - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DHFW.WinTms.AO182 - response: DHFW.WinTms.AI258 - step_number: 2 - - description: Set ramp time - fcodes: - - direct_operate - optional: I - point_name: DHFW.RvrtTms.AO184 - response: DHFW.RmpTms.AI259 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DHFW.RmpTms.AO183 - response: DHFW.RvrtTms.AI260 - step_number: 4 - - description: Identify the meter used to measure the Frequency. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHFW.EcpRef.AO185 - response: DHFW.EcpRef.AI261 - step_number: 5 - - description: Set the Nominal Grid Frequency if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.EcpNomHz.AO2 - response: DECP.EcpNomHz.AI31 - step_number: 6 - - description: Set the starting delays - fcodes: - - direct_operate - optional: I - point_name: DHFW.ActStrDlTmms.AO189 - response: DHFW.ActStrDlTmms.AI266 - step_number: 7 - - description: Set the stopping delays - fcodes: - - direct_operate - optional: I - point_name: DHFW.ActStopDlTmms.AO190 - response: DHFW.ActStopDlTmms.AI267 - step_number: 8 - - description: Set the frequency-watt curve ramp up time constant for the output - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoopMax.AO191 - response: DHFW.OpnLoopMax.AI268 - step_number: 9 - - description: Set the frequency-watt curve ramp down time constant for the output - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoopMax.AO192 - response: DHFW.OpnLoopMax.AI269 - step_number: 10 - - description: Set the frequency-watt curve discharge ramp up rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpuRte.AO193 - response: DHFW.RpuRte.AI270 - step_number: 11 - - description: Set the frequency-watt curve discharge ramp down rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpdRte.AO194 - response: DHFW.RpdRte.AI271 - step_number: 12 - - description: Set the frequency-watt curve charge ramp up rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpuChaRte.AO195 - response: DHFW.RpuChaRte.AI272 - step_number: 13 - - description: Set the frequency-watt curve charge ramp down rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpdChaRte.AO196 - response: DHFW.RpdChaRte.AI273 - step_number: 14 - - description: Identify the index of the main curve being used - fcodes: - - direct_operate - func_ref: curve - optional: I - point_name: DHFW.HzWCrv.AO186 - response: DHFW.HzWCrv.AI263 - step_number: 15 - - description: Identify the index of the high frequency hyteresis curve being used - fcodes: - - direct_operate - func_ref: curve - optional: I - point_name: DHFW.HysCrv.AO187 - response: DHFW.HysCrv.AI264 - step_number: 16 - - description: Identify the index of the low frequency hyteresis curve being used - fcodes: - - direct_operate - func_ref: curve - optional: I - point_name: DLFW.HysCrv.AO188 - response: DLFW.HysCrv.AI265 - step_number: 17 - - description: Set the minimum state of charge in which this mode shall operate - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMinPct.AO197 - response: DHFW.SocUseMinPct.AI275 - step_number: 18 - - description: Set the maximum state of charge in which this mode shall operate - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMaxPct.AO198 - response: DHFW.SocUseMaxPct.AI276 - step_number: 19 - - description: Choose whether to use hysteresis - fcodes: - - direct_operate - optional: I - point_name: DLFW.HysEna.BO36 - response: DLFW.HysEna.BI88 - step_number: 20 - - description: Choose whether to snapshot power - fcodes: - - direct_operate - optional: I - point_name: DLFW.SnptEna.BO37 - response: DLFW.SnptEna.BI89 - step_number: 21 - - action: publish - description: Enable the Frequency-Watt Curve Mode - fcodes: - - select - - operate - optional: M - point_name: DHFW.ModEna.BO26 - response: DHFW.ModEna.BI78 - step_number: 22 -- id: set_constant_var_output - name: Set Constant Var Output - ref: AN2018 Spec section 2.7.1 Table 50 - mode_types: - schedule: - - 25 - steps: - - description: Set the priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVAR.ModPrio.AO199 - response: DVAR.ModPrio.AI277 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DVAR.WinTms.AO200 - response: DVAR.WinTms.AI278 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DVAR.RmpTms.AO201 - response: DVAR.RmpTms.AI279 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVAR.RvrtTms.AO202 - response: DVAR.RvrtTms.AI280 - step_number: 4 - - description: Set the ramp up Time Constants - fcodes: - - direct_operate - optional: I - point_name: DVAR.OpnLoopMax.AO204 - response: DVAR.OpnLoopMax.AI282 - step_number: 5 - - description: Set the ramp down Time Constants - fcodes: - - direct_operate - optional: I - point_name: DVAR.OpnLoopMax.AO205 - response: DVAR.OpnLoopMax.AI283 - step_number: 6 - - description: Choose whether the time constants represent 3-Tau limits or Open - Loop Response Times - fcodes: - - direct_operate - optional: I - point_name: DSTO.OpnLoopTau.BO9 - response: DSTO.OpnLoopTau.BI28 - step_number: 7 - - description: If Open Loop Response Times are selected, choose the percentage of - final output represented by the time constant (e.g. 90% or 95%) - fcodes: - - direct_operate - optional: I - point_name: DSTO.OpnLoopPct.AO3 - response: DGEN.OpnLoopPct.AI40 - step_number: 8 - - description: Select the meaning of the Constant VArs Reactive Power Target - fcodes: - - direct_operate - optional: I - point_name: DSTO.VArRef.AO5 - response: DGEN.VArSetRef.AI42 - step_number: 9 - - description: 'If DSTO.VArRef = 1: Read percent of maximum active generation power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.WMax.AI32 - step_number: 10 - - description: 'If DSTO.VArRef = 1: Read percent of maximum active charging power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.ChaWMax.AI33 - step_number: 11 - - description: 'If DSTO.VArRef = 2: Read percent of maximum reactive injection power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.IvarMax.AI34 - step_number: 12 - - description: 'If DSTO.VArRef = 2: Read percent of maximum reactive absorption - power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.AvarMax.AI35 - step_number: 13 - - description: 'If DSTO.VArRef = 3: Read percent of system reactive injection power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.AvarAvl.AI45 - step_number: 14 - - description: 'If DSTO.VArRef = 3: Read percent of system reactive absorption power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.IvarAvl.AI46 - step_number: 15 - - description: Set the Constant VArs Reactive Power Target in percent - fcodes: - - direct_operate - optional: M - point_name: DVAR.VArTgtPct.AO203 - response: DVAR.VArTgtPct.AI281 - step_number: 16 - - action: publish - description: Enable Constant VArs mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DVAR.ModEna.BO27 - response: DVAR.ModEna.BI79 - step_number: 17 -- id: set_a_fixed_power_factor - name: Set a Fixed Power Factor - ref: AN2018 Spec section 2.7.2 Table 52 - mode_types: - schedule: - - 26 - steps: - - description: Set the priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DFPF.ModPrio.AO206 - response: DFPF.ModPrio.AI284 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DFPF.WinTms.AO207 - response: DFPF.WinTms.AI285 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DFPF.RmpTms.AO208 - response: DFPF.RmpTms.AI286 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DFPF.RvrtTms.AO209 - response: DFPF.RvrtTms.AI287 - step_number: 4 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when discharging / generating - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFGnExtSet.BO10 - response: DFPF.PFGnExtSet.BI29 - step_number: 5 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when charging - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFLodExtSet.BO11 - response: DFPF.PFLodExtSet.BI30 - step_number: 6 - - description: Set Fixed Power Factor Setpoint to use when generating / discharging - fcodes: - - direct_operate - optional: M - point_name: DFPF.PFGnTgt.AO210 - response: DFPF.PFGnTgt.AI288 - step_number: 7 - - description: Set Fixed Power Factor Setpoint to use when charging - fcodes: - - direct_operate - optional: M - point_name: DFPF.PFLodTgt.AO211 - response: DFPF.PFLodTgt.AI289 - step_number: 8 - - action: publish - description: Enable fixed power factor mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DFPF.ModEna.BO28 - response: DFPF.BI47 - step_number: 9 -- id: change_and_select_volt-var_control_mode - mode_types: - curve: - - 2 - schedule: - - 27 - name: Change and Select Volt-Var Control Mode - ref: AN2018 Spec section 2.7.3 Table 54 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVVR.ModPrio.AO212 - response: DVVR.ModPrio.AI290 - step_number: 1 - - description: Set the enabling time window - fcodes: - - direct_operate - optional: I - point_name: DVVR.WinTms.AO213 - response: DVVR.WinTms.AI291 - step_number: 2 - - description: Set the enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DVVR.RmpTms.AO214 - response: DVVR.RmpTms.AI292 - step_number: 3 - - description: Set the enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVVR.RvrtTms.AO215 - response: DVVR.RvrtTms.AI293 - step_number: 4 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DVVR.EcpRef.AO216 - response: DVVR.EcpRef.AI294 - step_number: 5 - - description: If using a fixed Voltage reference, set the reference voltage if - it has not already been set - fcodes: - - direct_operate - optional: O - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 6 - - description: If using a fixed Voltage reference, set the reference voltage offset - if it has not already been set - fcodes: - - direct_operate - optional: O - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 7 - - description: If autonomously adjusting the Voltage reference, set the time constant - for the lowpass filter - fcodes: - - direct_operate - optional: O - point_name: DVVR.VRefTmms.AO220 - response: DVVR.VRefTmms.AI300 - step_number: 8 - - description: If autonomously adjusting the Voltage reference, enable autonomous - adjustment - fcodes: - - direct_operate - optional: O - point_name: DVVR.VRefAdjEna.BO41 - response: DVVR.VRefAdjEna.BI93 - step_number: 9 - - description: Set the ramp up time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DVVR.OpnLoopMax.AO218 - response: DVVR.OpnLoopMax.AI298 - step_number: 10 - - description: Set the ramp down time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DVVR.OpnLoopMax.AO219 - response: DVVR.OpnLoopMax.AI299 - step_number: 11 - - description: Identify the index of the curve being used - fcodes: - - direct_operate - func_ref: curve - optional: M - point_name: DVVR.VVArCrv.AO217 - response: DVVR.VVArCrv.AI297 - step_number: 12 - - action: publish - description: Enable the Volt-VAr Control Mode - fcodes: - - select - - operate - optional: M - point_name: DVVC.ModEna.BO29 - response: DVVC.BI48 - step_number: 13 - - description: Read the adjusted reference voltage, if it is not fixed - fcodes: - - read - optional: O - point_name: n/a - response: DVVR.VRefSet.AI296 - step_number: 14 - - description: Read the measured Voltage - fcodes: - - read - optional: O - point_name: n/a - response: MMXN.Vol.AI295 - step_number: 15 - - description: Read the attempted VArs - fcodes: - - read - optional: O - point_name: n/a - response: DVVR.ReqVAr.AI301 - step_number: 16 - - description: Read the actual VArs (if using system meter) - fcodes: - - read - optional: O - point_name: n/a - response: MMXU.TotVAr.AI541 - step_number: 17 -- id: enable_watt-var_power_mode - mode_types: - curve: - - 4 - schedule: - - 28 - name: Enable Watt-Var Power Mode - ref: AN2018 Spec section 2.7.4 Table 55 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWVR.ModPrio.AO221 - response: DWVR.ModPrio.AI302 - step_number: 1 - - description: Set the enabling time window - fcodes: - - direct_operate - optional: I - point_name: DWVR.WinTms.AO222 - response: DWVR.WinTms.AI303 - step_number: 2 - - description: Set the enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DWVR.RmpTms.AO223 - response: DWVR.RmpTms.AI304 - step_number: 3 - - description: Set the enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWVR.RvrtTms.AO224 - response: DWVR.RvrtTms.AI305 - step_number: 4 - - description: Identify the meter used to measure the active power. By default - this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DWVR.EcpRef.AO225 - response: DWVR.EcpRef.AI306 - step_number: 5 - - description: Read the maximum generation power used as the reference for percent - Watts - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.WMax.AI32 - step_number: 6 - - description: Read the maximum charging power used as the reference for percent - Watts - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.ChaWMax.AI33 - step_number: 7 - - description: Set the ramp up time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DWVR.OpnLoopMax.AO227 - response: DWVR.OpnLoopMax.AI309 - step_number: 8 - - description: Set the ramp down time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DWVR.OpnLoopMax.AO228 - response: DWVR.OpnLoopMax.AI310 - step_number: 9 - - description: Identify the index of the curve being used - fcodes: - - direct_operate - func_ref: curve - optional: M - point_name: DWVR.WVArCrv.AO226 - response: DWVR.WVArCrv.AI308 - step_number: 10 - - action: publish - description: Enable the Watt-VAr Power Mode - fcodes: - - select - - operate - optional: M - point_name: DWVR.ModEna.BO30 - response: DWVR.BI49 - step_number: 11 -- id: enable_power_factor_correction_mode - name: Enable Power Factor Correction Mode - ref: AN2018 Spec section 2.7.5 Table 56 - mode_types: - schedule: - - 29 - steps: - - description: Set the priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DPFC.ModPrio.AO229 - response: DPFC.ModPrio.AI312 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DPFC.WinTms.AO230 - response: DPFC.WinTms.AI313 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DPFC.RmpRte.AO231 - response: DPFC.RmpTms.AI314 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DPFC.RvrtTms.AO232 - response: DPFC.RvrtTms.AI315 - step_number: 4 - - description: Identify the meter used to measure the active power. By default - this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DPFC.EcpRef.AO233 - response: DPFC.EcpRef.AI316 - step_number: 5 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when discharging - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFGnExtSet.BO10 - response: DFPF.PFGnExtSet.BI29 - step_number: 6 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when charging - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFLodExtSet.BO11 - response: DFPF.PFLodExtSet.BI30 - step_number: 7 - - description: Set the Average PF Target - fcodes: - - direct_operate - optional: M - point_name: DPFC.PFTrg.AO234 - response: MMXU.TotPF.AI317 - step_number: 8 - - description: Set the Lower PF Limit - fcodes: - - direct_operate - optional: M - point_name: DPFC.PFCorRef.rangeC.AO235 - response: DPFC.PFTrg.AI318 - step_number: 9 - - description: Set the Upper PF Limit - fcodes: - - direct_operate - optional: M - point_name: DPFC.PFCorRef.rangeC.AO236 - response: DPFC.PFCorRef.rangeC.AI319 - step_number: 10 - - action: publish - description: Enable Power Factor Correction Mode - fcodes: - - select - - operate - optional: M - point_name: DPFC.ModEna.BO31 - response: DPFC.ModEna.BI83 - step_number: 11 -- id: signal_a_price_change - name: Signal a Price Change - ref: AN2018 Spec section 2.8 Table 57 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DPRG.ModPrio.AO237 - response: DPRG.ModPrio.AI321 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DPRG.WinTms.AO238 - response: DPRG.WinTms.AI322 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DPRG.RmpTms.AO239 - response: DPRG.RmpTms.AI323 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DPRG.RvrtTms.AO240 - response: DPRG.RvrtTms.AI324 - step_number: 4 - - description: Set pricing mode time constant for ramping up - fcodes: - - direct_operate - optional: I - point_name: DPRG.OpnLoopMax.AO242 - response: DPRG.OpnLoopMax.AI326 - step_number: 5 - - description: Set pricing mode time constant for ramping down - fcodes: - - direct_operate - optional: I - point_name: DPRG.OpnLoopMax.AO243 - response: DPRG.OpnLoopMax.AI327 - step_number: 6 - - description: Set pricing signal and receive response - fcodes: - - select - - operate - optional: M - point_name: DPRG.PrcRef.AO241 - response: DPRG.PrcRef.AI325 - step_number: 7 - - action: publish - description: Enable pricing signal mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DPRG.ModEna.BO32 - response: DPRG.ModEna.BI84 - step_number: 8 -- id: enable_schedules - name: Enable Schedules - ref: AN2018 Spec section 2.9 Table 59 - steps: - - description: Enable the Schedule by changing its state to ready - fcodes: - - select - - operate - optional: M - point_name: FSCHxx.Mod.BO42 - response: FSCH.SchdSt.3.BI108 - step_number: 1 - - description: Select shedule index - fcodes: - - direct_operate - func_ref: schedule - optional: M - point_name: FSCC.Schd.AO461 - response: FSCC.Schd.AI570 - step_number: 2 - - description: Check that outstation validates the selected schedule - fcodes: - - read - optional: O - point_name: n/a - response: FSCH.SchdSt.2.BI109 - step_number: 3 - - description: Set selected schedule repeat weekly Sunday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO43 - response: FSCHxx.SchdReuse.BI110 - step_number: 4 - - description: Set selected schedule repeat weekly Monday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO44 - response: FSCHxx.SchdReuse.BI111 - step_number: 5 - - description: Set selected schedule repeat weekly Tuesday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO45 - response: FSCHxx.SchdReuse.BI112 - step_number: 6 - - description: Set selected schedule repeat weekly Wednesday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO46 - response: FSCHxx.SchdReuse.BI113 - step_number: 7 - - description: Set selected schedule repeat weekly Thursday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO47 - response: FSCHxx.SchdReuse.BI114 - step_number: 8 - - description: Set selected schedule repeat weekly Friday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO48 - response: FSCHxx.SchdReuse.BI115 - step_number: 9 - - action: publish - description: Set selected schedule repeat weekly Saturday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO49 - response: FSCHxx.SchdReuse.BI116 - step_number: 10 - - description: Be notified when the schedule is running - fcodes: - - read - optional: O - point_name: n/a - response: FSCH1.SchdSt.AI579 - step_number: 11 -- id: curve - name: Curve - ref: AN2018 Spec Curve Definition - steps: - - description: Select which curve to edit - fcodes: - - direct_operate - optional: M - point_name: DGSMn.InCrv.AO244 - response: DGSMn.InCrv.AI328 - step_number: 1 - - description: Specify the Curve Mode Type - fcodes: - - direct_operate - optional: M - point_name: DGSMn.ModTyp.AO245 - response: DGSMn.ModTyp.AI329 - step_number: 2 - - description: Specify that the Independent (X-Value) units for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.IndpUnits.AO247 - response: FMARn.IndpUnits.AI331 - step_number: 3 - - description: Specify the Dependent (Y-Value) units for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.DepRef.AO248 - response: FMARn.DepRef.AI332 - step_number: 4 - - description: Set X-Value and Y-Values pairs for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.PairArr.CrvPts.AO249 - response: FMARn.PairArr.CrvPts.AI333 - step_number: 5 - - action: publish - description: Set number of points used for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.PairArr.NumPts.AO246 - response: FMARn.PairArr.NumPts.AI330 - step_number: 6 -- id: schedule - name: Schedule - ref: AN2018 Spec Schedule Definition - steps: - - description: Select which schedule to edit. This is the index of the schedule, - not its identity. The indexes shall be the monotonically increasing integers - 12, 13, 14 .etc. while the curve identities may be any unique number. - fcodes: - - direct_operate - optional: M - point_name: FSCC.Schd.AO461 - response: FSCC.Schd.AI570 - step_number: 1 - - description: Set the identity of the schedule to a unique number - fcodes: - - direct_operate - optional: M - point_name: FSCC.Schd.AO462 - response: FSCC.Schd.AI571 - step_number: 2 - - description: Set the priority for the schedule - fcodes: - - direct_operate - optional: M - point_name: FSCH1.SchdPrio.AO463 - response: FSCH.SchdPrio.AI572 - step_number: 3 - - description: Set the meaning of the Y-values of the schedule, i.e. the schedule - type. Refer to Table 58. - fcodes: - - direct_operate - optional: M - point_name: FSCH.SchdVal.valEq.AO464 - response: AI573 - step_number: 4 - - description: Set the date for the schedule to start - fcodes: - - direct_operate - optional: M - point_name: FSCH.StrTm.AO465 - response: FSCH.StrTm.AI574 - step_number: 5 - - description: Set the time for the schedule to start - fcodes: - - direct_operate - optional: M - point_name: FSCH.StrTm.AO466 - response: FSCH.StrTm.AI575 - step_number: 6 - - description: Set the repetition interval - fcodes: - - direct_operate - optional: M - point_name: FSCH.NxtStrTm.AO467 - response: FSCH.NxtStrTm.AI576 - step_number: 7 - - description: Set the units of the repetition interval - fcodes: - - direct_operate - optional: M - point_name: FSCH.SchdReuse.AO468 - response: FSCH.SchdReuse.AI577 - step_number: 8 - - description: Set the Time Offset (X-Values) and Schedule Value (Y-Values) for - each schedule point - fcodes: - - direct_operate - optional: M - point_name: FSCHn.SchdEntr.AO470 - response: FSCHn.SchdEntr.AI581 - step_number: 9 - - action: publish - description: Set the number of points used for the schedule. - fcodes: - - direct_operate - optional: M - point_name: FSCH.NumEntr.AO469 - response: FSCH.NumEntr.AI580 - step_number: 10 \ No newline at end of file diff --git a/services/core/DNP3Agent/dnp3/mesa_points.config b/services/core/DNP3Agent/dnp3/mesa_points.config deleted file mode 100644 index a5561e411d..0000000000 --- a/services/core/DNP3Agent/dnp3/mesa_points.config +++ /dev/null @@ -1,10270 +0,0 @@ -[ - { - "index": 0, - "description": "Reference Voltage", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VRef", - "name": "DECP.VRef.AO0" - }, - { - "index": 1, - "description": "Reference Voltage Offset", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "data_object": "VRefOfs", - "name": "DECP.VRefOfs.AO1" - }, - { - "index": 2, - "description": "Nominal Grid Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DECP", - "units": "Hz", - "minimum": 0, - "data_object": "EcpNomHz", - "name": "DECP.EcpNomHz.AO2" - }, - { - "index": 3, - "description": "Open Loop Response Time Percentage. Percent of target to reach within the open loop response time. Default is 90%.", - "data_type": "AO", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DSTO", - "units": "Percent", - "minimum": 0, - "data_object": "OpnLoopPct", - "name": "DSTO.OpnLoopPct.AO3" - }, - { - "index": 4, - "description": "Power Factor Sign convention", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "MMXU", - "units": "None", - "minimum": 1, - "data_object": "PFSign", - "allowed_values": { - "1": "IEC active power", - "2": "IEEE lead/lag" - }, - "type": "enumerated", - "name": "MMXU.PFSign.AO4" - }, - { - "index": 5, - "description": "Reference for Reactive Power Setpoints. Selects which setpoint is active. Default is <3>.", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 3, - "ln_class": "DSTO", - "units": "None (list)", - "minimum": 0, - "data_object": "VArRef", - "allowed_values": { - "0": "Not applicable / Unknown", - "1": "Percent of Maximum Active Power (WMax)", - "2": "Percent of Maximum Reactive Power (VArMax)", - "3": "Percent of Available Reactive Power (VArAval)" - }, - "type": "enumerated", - "name": "DSTO.VArRef.AO5" - }, - { - "index": 6, - "description": "DER Start (Return to Service) Voltage High Limit. Percent of Reference Voltage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 20000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VHiLim", - "name": "DCTE.VHiLim.AO6" - }, - { - "index": 7, - "description": "DER Start (Return to Service) Voltage Low Limit. Percent of Reference Voltage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 10000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VLoLim", - "name": "DCTE.VLoLim.AO7" - }, - { - "index": 8, - "description": "DER Start (Return to Service) Frequency High Limit", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzHiLim", - "name": "DCTE.HzHiLim.AO8" - }, - { - "index": 9, - "description": "DER Start (Return to Service) Frequency Low Limit", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzLoLim", - "name": "DCTE.HzLoLim.AO9" - }, - { - "index": 10, - "description": "DER Start (Return to Service) Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnDlyTmms", - "name": "DCTE.RtnDlyTmms.AO10" - }, - { - "index": 11, - "description": "DER Start (Return to Service) Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AO11" - }, - { - "index": 12, - "description": "DER Start (Return to Service) Ramp Up Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnRmpTmms", - "name": "DCTE.RtnRmpTmms.AO12" - }, - { - "index": 13, - "description": "DER Stop (Cease to Energize) Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AO13" - }, - { - "index": 14, - "description": "DER Stop (Cease to Energize) Ramp Down Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DCTE.RmpTms.AO14" - }, - { - "index": 15, - "description": "DER Stop (Cease to Energize) Reversion Timeout Period. Time to revert from the stopped state and return to service.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AO15" - }, - { - "index": 16, - "description": "Connect/Disconnect Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AO16" - }, - { - "index": 17, - "description": "Connect/Disconnect Reversion Timeout Period. Timeout (reversion time is for the Disconnect only).", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AO17" - }, - { - "index": 18, - "description": "Requested Settings Group", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO Enable Sensed Grid Config Detection)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP1.EcpIsldSt.AO18" - }, - { - "index": 19, - "description": "Settings Group Being Edited", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DRCC", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "name": "DRCC1.EcpIsldSt.AO19" - }, - { - "index": 20, - "description": "Freeze Counter Interval. Interval between freeze counter operations after the initial occurrence. A zero value means the free counter operation is not repeated.", - "data_type": "AO", - "minimum": 0, - "name": "AO20" - }, - { - "index": 21, - "description": "Freeze Counter Interval Units. Units of the interval between freeze counter operations.", - "data_type": "AO", - "maximum": 9, - "minimum": 0, - "units": "None (list)", - "allowed_values": { - "0": "The outstation does not repeat the action, regardless of the Interval count.", - "1": "Milliseconds - In this case the interval is always counted relative to the Start Time and is constant regardless of the clock time set at the Outstation.", - "2": "Seconds - At the same millisecond within the second that is specified in the Start Time.", - "3": "Minutes - At the same second and millisecond within the minute that is specified in the Start Time.", - "4": "Hours - At the same minute,second and B7millisecond within the hour that is specified in the Start Time.", - "5": "Days - At the same time of day that is specified in the Start Time.", - "6": "Weeks - On the same day of the week at the same time of day that is specified in the Start Time", - "7": "Months - On the same day of each month at the same time of day that is specified in the Start Time. If the Start Time falls on the 29th or greater day of the month, the outstation shall not perform the action in months that do not have such a day.", - "8": "Months on Same Day of Week from Start of Month - At the same time of the day on the same day of the week after the beginning of the month as the day specified in the Start Time. For instance, if the Start Time specifies the second Tuesday of February and the Interval Count is 2, the next action shall occur on the second Tuesday of April. In the same example, if the Interval Count is set to 12, this is the same as specifying, Every year on the second Tuesday in February. If the specified day does not occur in a given month when an action was scheduled to occur, the outstation shall not perform the action that month but shall perform it at the next valid scheduled time.", - "9": "Months on Same Day of Week from End of Month - The outstation shall interpret this setting as in <8>, but the day of the week shall be measured from the end of the month, e.g., the second-last Tuesday in February." - }, - "type": "enumerated", - "name": "AO21" - }, - { - "index": 22, - "description": "Low/High Voltage Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHVT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHVT.EcpRef.AO22" - }, - { - "index": 23, - "description": "Low/High Voltage Ride-Through High Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AO23" - }, - { - "index": 24, - "description": "Low/High Voltage Ride-Through Low Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AO24" - }, - { - "index": 25, - "description": "Low/High Voltage Ride-Through High Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AO25" - }, - { - "index": 26, - "description": "Low/High Voltage Ride-Through Low Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AO26" - }, - { - "index": 27, - "description": "Low/High Frequency Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHFT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFT.EcpRef.AO27" - }, - { - "index": 28, - "description": "Low/High Frequency Ride-Through High Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AO28" - }, - { - "index": 29, - "description": "Low/High Frequency Ride-Through Low Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AO29" - }, - { - "index": 30, - "description": "Low/High Frequency Ride-Through High Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AO30" - }, - { - "index": 31, - "description": "Low/High Frequency Ride-Through Low Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AO31" - }, - { - "index": 32, - "description": "Dynamic Reactive Current Support Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "ModPrio", - "name": "DRGS.ModPrio.AO32" - }, - { - "index": 33, - "description": "Dynamic Reactive Current Support Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DRGS.WinTms.AO33" - }, - { - "index": 34, - "description": "Dynamic Reactive Current Support Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DRGS.RmpTms.AO34" - }, - { - "index": 35, - "description": "Dynamic Reactive Current Support Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DRGS.RvrtTms.AO35" - }, - { - "index": 36, - "description": "Dynamic Reactive Current Support Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "EcpRef", - "name": "DRGS.EcpRef.AO36" - }, - { - "index": 37, - "description": "Dynamic Reactive Current Support - Gradient Mode.", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "DRGS", - "units": "None (list)", - "minimum": 0, - "data_object": "ArGraMod", - "allowed_values": { - "0": "Undefined", - "1": "Gradients reach 0 at the moving average Voltage", - "2": "Gradients reach 0 at the Voltage deadbands" - }, - "type": "enumerated", - "name": "DRGS.ArGraMod.AO37" - }, - { - "index": 38, - "description": "Dynamic Reactive Current Support Deadband Minimum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays above this value for the length of the Hold Time.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DRGS", - "units": "Percent", - "minimum": -10000, - "data_object": "DbVMin", - "name": "DRGS.DbVMin.AO38" - }, - { - "index": 39, - "description": "Dynamic Reactive Current Support Deadband Maximum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays below this value for the length of the Hold Time.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 10000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "DbVMax", - "name": "DRGS.DbVMax.AO39" - }, - { - "index": 40, - "description": "Dynamic Reactive Current Support Gradient for Sags. Percentage of the rated current (DRAT.ARtg) to apply capacitively per percentage of the negative deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSag", - "name": "DRGS.ArGraSag.AO40" - }, - { - "index": 41, - "description": "Dynamic Reactive Current Support Gradient for Swells. Percentage of the rated current (DRAT.ARtg) to apply inductively per percentage of the positive deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSwl", - "name": "DRGS.ArGraSwl.AO41" - }, - { - "index": 42, - "description": "Dynamic Reactive Current Support Filter Time for Moving Average Voltage (RDGS.VAv). Used to determine amount of dynamic reactive current support.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DRGS.FilTms.AO42" - }, - { - "index": 43, - "description": "Dynamic Reactive Current Support Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef) below which no reactive current support shall be applied.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "BlkZnV", - "name": "DRGS.BlkZnV.AO43" - }, - { - "index": 44, - "description": "Dynamic Reactive Current Support Hysteresis Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef). After being blocked, reactive current support shall not resume until the voltage has been above BlkZnV + HysBlkZnV.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "HysBlkZnV", - "name": "DRGS.HysBlkZnV.AO44" - }, - { - "index": 45, - "description": "Dynamic Reactive Current Support Block Zone Time. Time in milliseconds from the beginning of any \"sag\" event,before which dynamic reactive current support will always continue,regardless of how low voltage may sag.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "BlkZnTmms", - "name": "DRGS.BlkZnTmms.AO45" - }, - { - "index": 46, - "description": "Dynamic Reactive Current Support Start Hold Time. When the voltage exceeds the deadband limits for this length of time (measured in milliseconds),the \"sag\" or \"swell\" event begins and the DER may begin altering active power output.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "HoldTmms", - "name": "DRGS.HoldTmms.AO46" - }, - { - "index": 47, - "description": "Dynamic Reactive Current Support End Hold Time. When the voltage returns to within the deadband limits for this length of time (measured in milliseconds),the \"sag\" or \"swell\" event is considered to be over. Reactive current support ends,frozen values are unfrozen,and a new event can begin.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "HoldTmms", - "name": "DRGS.HoldTmms.AO47" - }, - { - "index": 48, - "description": "Dynamic Volt-Watt Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWD.ModPrio.AO48" - }, - { - "index": 49, - "description": "Dynamic Volt-Watt Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWD.WinTms.AO49" - }, - { - "index": 50, - "description": "Dynamic Volt-Watt Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWD.RmpTms.AO50" - }, - { - "index": 51, - "description": "Dynamic Volt-Watt Reversion Timeout period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWD.RvrtTms.AO51" - }, - { - "index": 52, - "description": "Dynamic Volt-Watt Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWD2.EcpRef.AO52" - }, - { - "index": 53, - "description": "Dynamic Volt-Watt Gradient. Signed unit-less quantity that establishes the ratio of additional Watts supplied (expressed in terms of % DRCT.WMax) to the present difference from the moving average voltage (expressed as % DRCT.VRef).", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DVWD", - "units": "Percent watts per percent voltage difference", - "data_object": "DynVWGra", - "name": "DVWD.DynVWGra.AO53" - }, - { - "index": 54, - "description": "Dynamic Volt-Watt Filter Time. The time in seconds used to calculate the moving average voltage for dynamic Volt-Watt support.", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "VWFilTms", - "name": "DVWD.VWFilTms.AO54" - }, - { - "index": 55, - "description": "Dynamic Volt-Watt Lower Deadband. Percentage of the nominal voltage (DRCT.Vref) measured below the moving average voltage. If the present voltage is above this value, no additional Watts shall be supplied.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVWD", - "units": "Percent", - "minimum": 0, - "data_object": "DbVWLo", - "name": "DVWD.DbVWLo.AO55" - }, - { - "index": 56, - "description": "Dynamic Volt-Watt Upper Deadband. Percentage of the nominal voltage (DRCT.Vref) measured above the moving average voltage. If the present voltage is below this value,no additional Watts shall be supplied.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVWD", - "units": "Percent", - "minimum": 0, - "data_object": "DbVWHi", - "name": "DVWD.DbVWHi.AO56" - }, - { - "index": 57, - "description": "Frequency-Watt Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW2.ModPrio.AO57" - }, - { - "index": 58, - "description": "Frequency-Watt Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AO58" - }, - { - "index": 59, - "description": "Frequency-Watt Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AO59" - }, - { - "index": 60, - "description": "Frequency-Watt Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AO60" - }, - { - "index": 61, - "description": "Frequency-Watt Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW.EcpRef.AO61" - }, - { - "index": 62, - "description": "Frequency-Watt High Starting Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStr", - "name": "DHFW.HzStr.AO62" - }, - { - "index": 63, - "description": "Frequency-Watt High Stopping Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStop", - "name": "DHFW.HzStop.AO63" - }, - { - "index": 64, - "description": "Frequency-Watt High Discharging/Generating Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DHFW.WGra.AO64" - }, - { - "index": 65, - "description": "Frequency-Watt High Charging Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DHFW.WChaGra.AO65" - }, - { - "index": 66, - "description": "Frequency-Watt Low Starting Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStr", - "name": "DLFW.HzStr.AO66" - }, - { - "index": 67, - "description": "Frequency-Watt Low Stopping Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStop", - "name": "DLFW.HzStop.AO67" - }, - { - "index": 68, - "description": "Frequency-Watt Low Discharging/Generating Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DLFW.WGra.AO68" - }, - { - "index": 69, - "description": "Frequency-Watt Low Charging Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DLFW.WChaGra.AO69" - }, - { - "index": 70, - "description": "Frequency-Watt Start Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW2.ActStrDlTmms.AO70" - }, - { - "index": 71, - "description": "Frequency-Watt Stop Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW2.ActStopDlTmms.AO71" - }, - { - "index": 72, - "description": "Frequency-Watt Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DHFW.OpnLoop.AO72" - }, - { - "index": 73, - "description": "Frequency-Watt Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DHFW.OpnLoop.AO73" - }, - { - "index": 74, - "description": "Frequency-Watt Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DHFW.DschRpuRte.AO74" - }, - { - "index": 75, - "description": "Frequency-Watt Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DHFW.DschRpdRte.AO75" - }, - { - "index": 76, - "description": "Frequency-Watt Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DHFW.ChaRpuRte.AO76" - }, - { - "index": 77, - "description": "Frequency-Watt Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DHFW.ChaRpdRte.AO77" - }, - { - "index": 78, - "description": "Frequency-Watt Hi Return Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "RtnRmpRte", - "name": "DHFW.RtnRmpRte.AO78" - }, - { - "index": 79, - "description": "Frequency-Watt Low Return Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "RtnRmpRte", - "name": "DLFW.RtnRmpRte.AO79" - }, - { - "index": 80, - "description": "Frequency-Watt Minimum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMin", - "name": "DHFW.SocUseMin.AO80" - }, - { - "index": 81, - "description": "Frequency-Watt Maximum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMax", - "name": "DHFW.SocUseMax.AO81" - }, - { - "index": 82, - "description": "Active Power Limit Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWMX.ModPrio.AO82" - }, - { - "index": 83, - "description": "Active Power Limit Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWMX.WinTms.AO83" - }, - { - "index": 84, - "description": "Active Power Limit Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWMX.RmpTms.AO84" - }, - { - "index": 85, - "description": "Active Power Limit Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWMX.RvrtTms.AO85" - }, - { - "index": 86, - "description": "Active Power Limit Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWMX.EcpRef.AO86" - }, - { - "index": 87, - "description": "Active Power Limit Charge Setpoint. Maximum allowed Watts as a percentage of Maximum Active Power capability.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMX", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMX.WLimPct.AO87" - }, - { - "index": 88, - "description": "Active Power Limit Discharge Setpoint. Maximum allowed Watts as a percentage of Maximum Active Power capability.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMN", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMN.WLimPct.AO88" - }, - { - "index": 89, - "description": "Charge/Discharge Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWGC.ModPrio.AO89" - }, - { - "index": 90, - "description": "Charge/Discharge Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWGC.WinTms.AO90" - }, - { - "index": 91, - "description": "Charge/Discharge Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWGC.RmpTms.AO91" - }, - { - "index": 92, - "description": "Charge/Discharge Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWGC.RvrtTms.AO92" - }, - { - "index": 93, - "description": "Charge/Discharge Active Power Target. Percentage of maxmum active power.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "GnWPctSpt", - "name": "DWGC.GnWPctSpt.AO93" - }, - { - "index": 94, - "description": "Charge/Discharge Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DWGC.OpnLoop.AO94" - }, - { - "index": 95, - "description": "Charge/Discharge Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DWGC.OpnLoop.AO95" - }, - { - "index": 96, - "description": "Charge/Discharge Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DWGC.DschRpuRte.AO96" - }, - { - "index": 97, - "description": "Charge/Discharge Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DWGC.DschRpdRte.AO97" - }, - { - "index": 98, - "description": "Charge/Discharge Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DWGC.ChaRpuRte.AO98" - }, - { - "index": 99, - "description": "Charge/Discharge Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DWGC.ChaRpdRte.AO99" - }, - { - "index": 100, - "description": "Charge/Discharge Minimum Reserve for Storage. The minimum level to which the storage system may be discharged,expressed as a percentage of the total usable storage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMinPct", - "name": "DWGC.SocUseMinPct.AO100" - }, - { - "index": 101, - "description": "Charge/Discharge Maximum Reserve for Storage. The maximum level to which the storage system may be discharged,expressed as a percentage of the total usable storage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMaxPct", - "name": "DWGC.SocUseMaxPct.AO101" - }, - { - "index": 102, - "description": "Coordinated Charge/Discharge Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DTCD.ModPrio.AO102" - }, - { - "index": 103, - "description": "Coordinated Charge/Discharge Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DTCD.WinTms.AO103" - }, - { - "index": 104, - "description": "Coordinated Charge/Discharge Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DTCD.RmpTms.AO104" - }, - { - "index": 105, - "description": "Coordinated Charge/Discharge Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DTCD.RvrtTms.AO105" - }, - { - "index": 106, - "description": "Coordinated Charge/Discharge Target State of Charge. Charge that the system is expected to achieve,as a percentage of the usable capacity.", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DTCD", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseTgtPct", - "name": "DTCD.SocUseTgtPct.AO106" - }, - { - "index": 107, - "description": "Coordinated Charge/Discharge Target Date. Date by which the storage system must reach the target SOC. Expressed as number of days since January 1, 1970, UTC.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AO107" - }, - { - "index": 108, - "description": "Coordinated Charge/Discharge Target Time. Time by which storage system must reach the target SOC. Expressed as number of milliseconds since the start of Target Date.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "DateTgtTms", - "name": "DTCD.DateTgtTms.AO108" - }, - { - "index": 109, - "description": "Coordinated Charge/Discharge Energy Request", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Watt-hours", - "minimum": 0, - "data_object": "SocWReq", - "name": "DTCD.SocWReq.AO109" - }, - { - "index": 110, - "description": "Coordinated Charge/Discharge Minimum Charging Duration", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurTms", - "name": "DTCD.ChaDurTms.AO110" - }, - { - "index": 111, - "description": "Coordinated Charge/Discharge Date of Reference", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AO111" - }, - { - "index": 112, - "description": "Coordinated Charge/Discharge Time of Reference", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "SocDateTms", - "name": "DTCD.SocDateTms.AO112" - }, - { - "index": 113, - "description": "Coordinated Charge/Discharge Duration at Maximum Charge Rate", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurMax", - "name": "DTCD.ChaDurMax.AO113" - }, - { - "index": 114, - "description": "Coordinated Charge/Discharge Duration at Maximum Discharge Rate", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "DschDurMax", - "name": "DTCD.DschDurMax.AO114" - }, - { - "index": 115, - "description": "Active Power Response Mode #1 Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPKP.ModPrio.AO115" - }, - { - "index": 116, - "description": "Active Power Response Mode #1 Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPKP.WinTms.AO116" - }, - { - "index": 117, - "description": "Active Power Response Mode #1 Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPKP.RmpTms.AO117" - }, - { - "index": 118, - "description": "Active Power Response Mode #1 Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPKP.RvrtTms.AO118" - }, - { - "index": 119, - "description": "Active Power Response Mode #1 Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPKP.EcpRef.AO119" - }, - { - "index": 120, - "description": "Active Power Response Mode #1 Power Threshold", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPKP", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DPKP.PkPwrWLim.AO120" - }, - { - "index": 121, - "description": "Active Power Response Mode #1 Ratio", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DPKP", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DPKP.PkPwrFolPct.AO121" - }, - { - "index": 122, - "description": "Active Power Response Mode #1 Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DPKP.RpuRte.AO122" - }, - { - "index": 123, - "description": "Active Power Response Mode #1 Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DPKP.RpdRte.AO123" - }, - { - "index": 124, - "description": "Active Power Response Mode #2 Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DGFL.ModPrio.AO124" - }, - { - "index": 125, - "description": "Active Power Response Mode #2 Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DGFL.WinTms.AO125" - }, - { - "index": 126, - "description": "Active Power Response Mode #2 Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DGFL.RmpTms.AO126" - }, - { - "index": 127, - "description": "Active Power Response Mode #2 Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DGFL.RvrtTms.AO127" - }, - { - "index": 128, - "description": "Active Power Response Mode #2 Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DGFL.EcpRef.AO128" - }, - { - "index": 129, - "description": "Active Power Response Mode #2 Power Threshold", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DGFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DGFL.PkPwrWLim.AO129" - }, - { - "index": 130, - "description": "Active Power Response Mode #2 Ratio", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DGFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DGFL.PkPwrFolPct.AO130" - }, - { - "index": 131, - "description": "Active Power Response Mode #2 Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DGFL.RpuRte.AO131" - }, - { - "index": 132, - "description": "Active Power Response Mode #2 Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DGFL.RpdRte.AO132" - }, - { - "index": 133, - "description": "Active Power Response Mode #3 Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DLFL.ModPrio.AO133" - }, - { - "index": 134, - "description": "Active Power Response Mode #3 Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DLFL.WinTms.AO134" - }, - { - "index": 135, - "description": "Active Power Response Mode #3 Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DLFL.RmpTms.AO135" - }, - { - "index": 136, - "description": "Active Power Response Mode #3 Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DLFL.RvrtTms.AO136" - }, - { - "index": 137, - "description": "Active Power Response Mode #3 Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DLFL.EcpRef.AO137" - }, - { - "index": 138, - "description": "Active Power Response Mode #3 Power Threshold", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DLFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DLFL.PkPwrWLim.AO138" - }, - { - "index": 139, - "description": "Active Power Response Mode #3 Ratio", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DLFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DLFL.PkPwrFolPct.AO139" - }, - { - "index": 140, - "description": "Active Power Response Mode #3 Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DLFL.RpuRte.AO140" - }, - { - "index": 141, - "description": "Active Power Response Mode #3 Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DLFL.RpdRte.AO141" - }, - { - "index": 142, - "description": "AGC Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DAGC.ModPrio.AO142" - }, - { - "index": 143, - "description": "AGC Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DAGC.WinTms.AO143" - }, - { - "index": 144, - "description": "AGC Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DAGC.RmpTms.AO144" - }, - { - "index": 145, - "description": "AGC Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DAGC.RvrtTms.AO145" - }, - { - "index": 146, - "description": "AGC Active Power Target", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "GnWSpt", - "name": "DAGC.GnWSpt.AO146" - }, - { - "index": 147, - "description": "AGC Ramp Time Constant Up Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DAGC.OpnLoop.AO147" - }, - { - "index": 148, - "description": "AGC Ramp Time Constant Down Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DAGC.OpnLoop.AO148" - }, - { - "index": 149, - "description": "AGC Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DAGC.DschRpuRte.AO149" - }, - { - "index": 150, - "description": "AGC Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DAGC.DschRpdRte.AO150" - }, - { - "index": 151, - "description": "AGC Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DAGC.ChaRpuRte.AO151" - }, - { - "index": 152, - "description": "AGC Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DAGC.ChaRpdRte.AO152" - }, - { - "index": 153, - "description": "AGC Minimum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DAGC.SocUseMinPct.AO153" - }, - { - "index": 154, - "description": "AGC Maximum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DAGC.SocUseMaxPct.AO154" - }, - { - "index": 155, - "description": "Active Power Smoothing Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWSM.ModPrio.AO155" - }, - { - "index": 156, - "description": "Active Power Smoothing Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWSM.WinTms.AO156" - }, - { - "index": 157, - "description": "Active Power Smoothing Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWSM.RmpTms.AO157" - }, - { - "index": 158, - "description": "Active Power Smoothing Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWSM.RvrtTms.AO158" - }, - { - "index": 159, - "description": "Active Power Smoothing Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWSM.EcpRef.AO159" - }, - { - "index": 160, - "description": "Active Power Smoothing Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DWSM", - "units": "Watts per delta-watt", - "data_object": "WSmthGra", - "name": "DWSM.WSmthGra.AO160" - }, - { - "index": 161, - "description": "Active Power Smoothing Lower Limit. Difference in Watts from the moving average of the reference power (MMXN1.Watt) above which no smoothing shall be applied.", - "data_type": "AO", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DWSM", - "units": "Watts", - "data_object": "WSmthLoLim", - "name": "DWSM.WSmthLoLim.AO161" - }, - { - "index": 162, - "description": "Active Power Smoothing Upper Limit. Difference in Watts from the moving average of the reference power (MMXN.Watt) below which no smoothing shall be applied.", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DWSM", - "units": "Watts", - "minimum": 0, - "data_object": "WSmthHiLim", - "name": "DWSM.WSmthHiLim.AO162" - }, - { - "index": 163, - "description": "Active Power Smoothing Filter Time (Seconds). Time in seconds used to calculate the moving average of the reference load or generation (MMXN1.Watt) being smoothed.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DWSM.FilTms.AO163" - }, - { - "index": 164, - "description": "Active Power Smoothing Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DWSM.DschRpuRte.AO164" - }, - { - "index": 165, - "description": "Active Power Smoothing Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DWSM.DschRpdRte.AO165" - }, - { - "index": 166, - "description": "Active Power Smoothing Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DWSM.ChaRpuRte.AO166" - }, - { - "index": 167, - "description": "Active Power Smoothing Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DWSM.ChaRpdRte.AO167" - }, - { - "index": 168, - "description": "Volt-Watt Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWC.ModPrio.AO168" - }, - { - "index": 169, - "description": "Volt-Watt Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWC.WinTms.AO169" - }, - { - "index": 170, - "description": "Volt-Watt Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWC.RmpTms.AO170" - }, - { - "index": 171, - "description": "Volt-Watt Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWC.RvrtTms.AO171" - }, - { - "index": 172, - "description": "Volt-Watt Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWC.EcpRef.AO172" - }, - { - "index": 173, - "description": "Volt-Watt Curve Index", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "VWCrv", - "name": "DVWC.VWCrv.AO173" - }, - { - "index": 174, - "description": "Volt-Watt Filter Time (Seconds)", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DVWC.FilTms.AO174" - }, - { - "index": 175, - "description": "Volt-Watt Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DVWC.OpnLoop.AO175" - }, - { - "index": 176, - "description": "Volt-Watt Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DVWC.OpnLoop.AO176" - }, - { - "index": 177, - "description": "Volt-Watt Discharging Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DVWC.DschRpuRte.AO177" - }, - { - "index": 178, - "description": "Volt-Watt Discharging Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DVWC.DschRpdRte.AO178" - }, - { - "index": 179, - "description": "Volt-Watt Charging Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DVWC.ChaRpuRte.AO179" - }, - { - "index": 180, - "description": "Volt-Watt Charging Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DVWC.ChaRpdRte.AO180" - }, - { - "index": 181, - "description": "Frequency-Watt Curve Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW.ModPrio.AO181" - }, - { - "index": 182, - "description": "Frequency-Watt Curve Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AO182" - }, - { - "index": 183, - "description": "Frequency-Watt Curve Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AO183" - }, - { - "index": 184, - "description": "Frequency-Watt Curve Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AO184" - }, - { - "index": 185, - "description": "Frequency-Watt Curve Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW.EcpRef.AO185" - }, - { - "index": 186, - "description": "Frequency-Watt Curve - Curve Index", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HzWCrv", - "name": "DHFW.HzWCrv.AO186" - }, - { - "index": 187, - "description": "Frequency-Watt Curve - High Frequency Hysteresis Curve Index", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DHFW.HysCrv.AO187" - }, - { - "index": 188, - "description": "Frequency-Watt Curve - Low Frequency Hysteresis Curve Index", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DLFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DLFW.HysCrv.AO188" - }, - { - "index": 189, - "description": "Frequency-Watt Curve Start Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW.ActStrDlTmms.AO189" - }, - { - "index": 190, - "description": "Frequency-Watt Curve Stop Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW.ActStopDlTmms.AO190" - }, - { - "index": 191, - "description": "Frequency-Watt Curve Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AO191" - }, - { - "index": 192, - "description": "Frequency-Watt Curve Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AO192" - }, - { - "index": 193, - "description": "Frequency-Watt Curve Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DHFW.RpuRte.AO193" - }, - { - "index": 194, - "description": "Frequency-Watt Curve Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DHFW.RpdRte.AO194" - }, - { - "index": 195, - "description": "Frequency-Watt Curve Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DHFW.RpuChaRte.AO195" - }, - { - "index": 196, - "description": "Frequency-Watt Curve Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DHFW.RpdChaRte.AO196" - }, - { - "index": 197, - "description": "Frequency-Watt Curve Minimum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DHFW.SocUseMinPct.AO197" - }, - { - "index": 198, - "description": "Frequency-Watt Curve Maximum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DHFW.SocUseMaxPct.AO198" - }, - { - "index": 199, - "description": "Constant VArs Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVAR.ModPrio.AO199" - }, - { - "index": 200, - "description": "Constant VArs Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVAR.WinTms.AO200" - }, - { - "index": 201, - "description": "Constant VArs Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVAR.RmpTms.AO201" - }, - { - "index": 202, - "description": "Constant VArs Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVAR.RvrtTms.AO202" - }, - { - "index": 203, - "description": "Constant VArs Reactive Power Target. Percentage of maxmum reactive power.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVAR", - "units": "Percent", - "minimum": -1000, - "data_object": "VArTgtPct", - "name": "DVAR.VArTgtPct.AO203" - }, - { - "index": 204, - "description": "Constant VArs Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AO204" - }, - { - "index": 205, - "description": "Constant VArs Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AO205" - }, - { - "index": 206, - "description": "Fixed Power Factor Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "minimum": 0, - "data_object": "ModPrio", - "name": "DFPF.ModPrio.AO206" - }, - { - "index": 207, - "description": "Fixed Power Factor Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DFPF.WinTms.AO207" - }, - { - "index": 208, - "description": "Fixed Power Factor Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DFPF.RmpTms.AO208" - }, - { - "index": 209, - "description": "Fixed Power Factor Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DFPF.RvrtTms.AO209" - }, - { - "index": 210, - "description": "Fixed Power Factor Setpoint - Generation/Discharging", - "data_type": "AO", - "common_data_class": "APC", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFGnTgt", - "name": "DFPF.PFGnTgt.AO210" - }, - { - "index": 211, - "description": "Fixed Power Factor Setpoint - Charging", - "data_type": "AO", - "common_data_class": "APC", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFLodTgt", - "name": "DFPF.PFLodTgt.AO211" - }, - { - "index": 212, - "description": "Volt-VAr Control Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVVR.ModPrio.AO212" - }, - { - "index": 213, - "description": "Volt-VAr Control Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVVR.WinTms.AO213" - }, - { - "index": 214, - "description": "Volt-VAr Control Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVVR.RmpTms.AO214" - }, - { - "index": 215, - "description": "Volt-VAr Control Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVVR.RvrtTms.AO215" - }, - { - "index": 216, - "description": "Volt-VAr Control Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVVR.EcpRef.AO216" - }, - { - "index": 217, - "description": "Volt-VAr Curve Index", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "VVArCrv", - "name": "DVVR.VVArCrv.AO217" - }, - { - "index": 218, - "description": "Volt-VAr Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AO218" - }, - { - "index": 219, - "description": "Volt-VAr Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AO219" - }, - { - "index": 220, - "description": "Volt-VAr Autonomous Voltage Reference Adjustment Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "VRefTmms", - "name": "DVVR.VRefTmms.AO220" - }, - { - "index": 221, - "description": "Watt-VAr Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWVR.ModPrio.AO221" - }, - { - "index": 222, - "description": "Watt-VAr Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWVR.WinTms.AO222" - }, - { - "index": 223, - "description": "Watt-VAr Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWVR.RmpTms.AO223" - }, - { - "index": 224, - "description": "Watt-VAr Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWVR.RvrtTms.AO224" - }, - { - "index": 225, - "description": "Watt-VAr Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWVR.EcpRef.AO225" - }, - { - "index": 226, - "description": "Watt-VAr Curve Index", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "WVArCrv", - "name": "DWVR.WVArCrv.AO226" - }, - { - "index": 227, - "description": "Watt-VAr Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AO227" - }, - { - "index": 228, - "description": "Watt-VAr Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AO228" - }, - { - "index": 229, - "description": "Power Factor Correction Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPFC.ModPrio.AO229" - }, - { - "index": 230, - "description": "Power Factor Correction Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPFC.WinTms.AO230" - }, - { - "index": 231, - "description": "Power Factor Correction Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpRte", - "name": "DPFC.RmpRte.AO231" - }, - { - "index": 232, - "description": "Power Factor Correction Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPFC.RvrtTms.AO232" - }, - { - "index": 233, - "description": "Power Factor Correction Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPFC.EcpRef.AO233" - }, - { - "index": 234, - "description": "Power Factor Correction Average PF Target", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFTrg", - "name": "DPFC.PFTrg.AO234" - }, - { - "index": 235, - "description": "Power Factor Correction Lower PF Limit", - "data_type": "AO", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AO235" - }, - { - "index": 236, - "description": "Power Factor Correction Upper PF Limit", - "data_type": "AO", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AO236" - }, - { - "index": 237, - "description": "Pricing Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "None", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPRG.ModPrio.AO237" - }, - { - "index": 238, - "description": "Pricing Mode Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPRG.WinTms.AO238" - }, - { - "index": 239, - "description": "Pricing Mode Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPRG.RmpTms.AO239" - }, - { - "index": 240, - "description": "Pricing Mode Reversion Timeout period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPRG.RvrtTms.AO240" - }, - { - "index": 241, - "description": "Pricing Mode Setpoint. Hundredths of local currency per Kilowatt-Hr.", - "data_type": "AO", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "ln_class": "DPRG", - "units": "100ths of local currency", - "data_object": "PrcRef", - "name": "DPRG.PrcRef.AO241" - }, - { - "index": 242, - "description": "Pricing Mode Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AO242" - }, - { - "index": 243, - "description": "Pricing Mode Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AO243" - }, - { - "index": 244, - "description": "Curve Edit Selector. Writing to this point selects which of the curves can currently be viewed and changed.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DGSM", - "minimum": 1, - "data_object": "InCrv", - "name": "DGSMn.InCrv.AO244", - "type": "selector_block", - "selector_block_start": 244, - "selector_block_end": 448 - }, - { - "index": 245, - "description": "Curve Mode Type", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 20, - "ln_class": "DGSM", - "units": "None (list)", - "minimum": 0, - "data_object": "ModTyp", - "allowed_values": { - "0": "Curve disabled", - "1": "Not applicable / Unknown", - "2": "Volt-Var modes VV11-VV12", - "3": "Frequency-Watt mode FW22", - "4": "Watt-VAr mode WP42", - "5": "Voltage-Watt modes VW51-VW52", - "6": "Remain Connected", - "7": "Temperature mode", - "8": "Pricing signal mode", - "9": "HVRT Must Trip", - "10": "HVRT Momentary Cessation", - "11": "LVRT Must Trip", - "12": "LVRT Momentary Cessation", - "13": "HFRT Must Trip", - "14": "HFRT Momentary Cessation", - "15": "LFRT Must Trip", - "16": "LFRT Mandatory Operation" - }, - "type": "enumerated", - "name": "DGSMn.ModTyp.AO245" - }, - { - "index": 246, - "description": "Curve Number of Points", - "data_type": "AO", - "common_data_class": "CSG", - "maximum": 100, - "ln_class": "FMAR", - "minimum": 0, - "data_object": "PairArr.NumPts", - "name": "FMARn.PairArr.NumPts.AO246" - }, - { - "index": 247, - "description": "Independent (X-Value) Units for Curve", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "minimum": 0, - "data_object": "IndpUnits", - "allowed_values": { - "0": "Curve disabled", - "1": "Not applicable / Unknown", - "4": "Time", - "23": "Celsius Temperature", - "29": "Voltage", - "33": "Frequency", - "38": "Watts", - "100": "Price in hundredths of local currency", - "129": "Percent Voltage", - "133": "Percent Frequency", - "138": "Percent Watts", - "233": "Frequency Deviation" - }, - "type": "enumerated", - "name": "FMARn.IndpUnits.AO247" - }, - { - "index": 248, - "description": "Dependent (Y-Value) Units for Curve", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "minimum": 0, - "data_object": "DepRef", - "allowed_values": { - "0": "Curve disabled", - "1": "Not applicable / unknown", - "2": "VArs as percent of max VArs (VARMax)", - "3": "VArs as percent of max available VArs (VArAval)", - "4": "Vars as percent of max Watts (Wmax) not used", - "5": "Watts as percent of max Watts (Wmax)", - "6": "Watts as percent of frozen active power (DeptSnptRef)", - "7": "Power Factor in EEI notation", - "8": "Volts as a percent of the nominal voltage (VRef)", - "9": "Frequency as a percent of the nominal grid frequency (ECPNomHz)" - }, - "type": "enumerated", - "name": "FMARn.DepRef.AO248" - }, - { - "index": 249, - "description": "Curve X-Value and Y-Value pairs for curve points 1 - 100", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "FMAR", - "units": "Varies", - "data_object": "PairArr.CrvPts", - "name": "FMARn.PairArr.CrvPts.AO249", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FMARn.PairArr.CrvPts.AO249.xVal" - }, - { - "name": "FMARn.PairArr.CrvPts.AO249.yVal" - } - ] - }, - { - "index": 449, - "description": "System Meter Active Power - High Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.hLim", - "name": "MMXU.TotW.rangeC.hLim.AO449" - }, - { - "index": 450, - "description": "System Meter Active Power - Low Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.lLim", - "name": "MMXU.TotW.rangeC.lLim.AO450" - }, - { - "index": 451, - "description": "System Meter Reactive Power - High Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.hLim", - "name": "MMXU.TotVAr.rangeC.hLim.AO451" - }, - { - "index": 452, - "description": "System Meter at Reactive Power - Low Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.lLim", - "name": "MMXU.TotVAr.rangeC.lLim.AO452" - }, - { - "index": 453, - "description": "System Meter at Power Factor - High Threshold", - "data_type": "AO", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.hLim", - "name": "MMXU.TotPF.rangeC.hLim.AO453" - }, - { - "index": 454, - "description": "System Meter at Power Factor - Low Threshold", - "data_type": "AO", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.lLim", - "name": "MMXU.TotPF.rangeC.lLim.AO454" - }, - { - "index": 455, - "description": "System Meter Phase A Volts - High Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.hLim", - "name": "MMXU.PhV.phsA.rangeC.hLim.AO455" - }, - { - "index": 456, - "description": "System Meter Phase A Volts - Low Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.lLim", - "name": "MMXU.PhV.phsA.rangeC.lLim.AO456" - }, - { - "index": 457, - "description": "System Meter Phase B Volts High Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.hLim", - "name": "MMXU.PhV.phsB.rangeC.hLim.AO457" - }, - { - "index": 458, - "description": "System Meter Phase B Volts - Low Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.lLim", - "name": "MMXU.PhV.phsB.rangeC.lLim.AO458" - }, - { - "index": 459, - "description": "System Meter Phase C Volts - High Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.hLim", - "name": "MMXU.PhV.phsC.rangeC.hLim.AO459" - }, - { - "index": 460, - "description": "System Meter Phase C Volts - Low Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.lLim", - "name": "MMXU.PhV.phsC.rangeC.lLim.AO460" - }, - { - "index": 461, - "description": "Schedule to Edit Selector. Selects which of the schedules can be currently viewed and changed.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "name": "FSCC.Schd.AO461", - "type": "selector_block", - "selector_block_start": 461, - "selector_block_end": 669 - - }, - { - "index": 462, - "description": "Selected Schedule Identity", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "name": "FSCC.Schd.AO462" - }, - { - "index": 463, - "description": "Selected Schedule Priority. Priority of the schedule relative to other running schedules. Lower values have higher priority over higher values.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 0, - "data_object": "SchdPrio", - "name": "FSCH1.SchdPrio.AO463" - }, - { - "index": 464, - "description": "Selected Schedule Type", - "data_type": "AO", - "common_data_class": "SCR", - "maximum": 30, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdVal.valEq", - "allowed_values": { - "1": "Low/High Voltage Ride-Through - Hi Must Trip", - "2": "Low/High Voltage Ride-Through - Low Must Trip", - "3": "Low/High Voltage Ride-Through - Hi Momentary", - "4": "Low/High Voltage Ride-Through - Lo Momentary", - "5": "Low/High Frequency Ride-Through - Hi Must Trip", - "6": "Low/High Frequency Ride-Through - Lo Must Trip", - "7": "Low/High Frequency Ride-Through - Hi Momentary", - "8": "Low/High Frequency Ride-Through - Low Momentary", - "9": "Dynamic Reactive Current Support - On/Off", - "10": "Dynamic Volt-Watt - On/Off", - "11": "Frequency-Watt - On/Off", - "12": "Active Power Limit - Charging", - "13": "Active Power Limit - Generating", - "14": "Charge/Discharge - Percent of Maximum", - "15": "Coordinated Charge/Discharge - SOC Target", - "16": "Active Power Response #1 - On/Off", - "17": "Active Power Response #2 - On/Off", - "18": "Active Power Response #3 - On/Off", - "19": "AGC - Watts", - "20": "Active Power Smoothing - On/Off", - "21": "Volt-Watt - Curve Index", - "22": "Frequency-Watt Curve - Curve Index", - "23": "Frequency-Watt Curve - High Hysteresis", - "24": "Frequency-Watt Curve - Low Hysteresis", - "25": "Constant VArs - Percent of Maximum", - "26": "Fixed Power Factor - Power Factor", - "27": "Volt-VAr - Curve Index", - "28": "Watt-VAr - Curve Index", - "29": "Power Factor Correction - On/Off", - "30": "Reserved - For pricing mode" - }, - "type": "enumerated", - "name": "FSCH.SchdVal.valEq.AO464" - }, - { - "index": 465, - "description": "Selected Schedule Start Date. Number of days since January 1, 1970, UTC.", - "data_type": "AO", - "common_data_class": "TSG", - "ln_class": "FSCH", - "units": "Days", - "minimum": 0, - "data_object": "StrTm", - "name": "FSCH.StrTm.AO465" - }, - { - "index": 466, - "description": "Selected Schedule Start Time. Milliseconds since the start of Schedule Start Date.", - "data_type": "AO", - "common_data_class": "TSG", - "maximum": 86400000, - "ln_class": "FSCH", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "StrTm", - "name": "FSCH.StrTm.AO466" - }, - { - "index": 467, - "description": "Selected Schedule Repeat Interval. Interval between actions after the initial occurrence. A zero value means the schedule is not repeated.", - "data_type": "AO", - "common_data_class": "TCS", - "ln_class": "FSCH", - "minimum": 0, - "data_object": "NxtStrTm", - "name": "FSCH.NxtStrTm.AO467" - }, - { - "index": 468, - "description": "Selected Schedule Repeat Interval Units", - "data_type": "AO", - "common_data_class": "SPG", - "maximum": 8, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdReuse", - "allowed_values": { - "0": "No Repeat", - "1": "Seconds", - "2": "Minutes", - "3": "Hours", - "4": "Days", - "5": "Weeks", - "6": "Months", - "7": "Months on Same Day of Week", - "8": "Months on Same Day of Week from End" - }, - "type": "enumerated", - "name": "FSCH.SchdReuse.AO468" - }, - { - "index": 469, - "description": "Selected Schedule Number of Points", - "data_type": "AO", - "common_data_class": "ING", - "maximum": 100, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "NumEntr", - "name": "FSCH.NumEntr.AO469" - }, - { - "index": 470, - "description": "Select schedule time offset and value pairs for points 1 - 100", - "data_type": "AO", - "minimum": 0, - "name": "FSCHn.SchdEntr.AO470", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FSCHn.SchdEntr.AO470.time", - "description": "Number of seconds from the start of the schedule when this point becomes active", - "units": "Seconds" - }, - { - "name": "FSCHn.SchdEntr.AO470.val", - "ln_class": "FSCH", - "data_object": "SchdEntr" - } - ] - }, - { - "index": 0, - "description": "DER Profile Version Number. Always the number 1.00 for this specification.", - "data_type": "AI", - "scaling_multiplier": 0.01, - "maximum": 100, - "minimum": 100, - "event_class": 3, - "name": "AI0" - }, - { - "index": 1, - "description": "DER Profile Implementation Level. 1, 2 or 3 to indicate support for Level 1, Level 2 or Level 3 respectively.", - "data_type": "AI", - "maximum": 3, - "minimum": 1, - "event_class": 3, - "name": "AI1" - }, - { - "index": 2, - "description": "Nameplate Minimum Voltage Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DGEN", - "units": "Volts", - "minimum": 0, - "data_object": "VMinRtg", - "event_class": 3, - "name": "DGEN.VMinRtg.AI2" - }, - { - "index": 3, - "description": "Nameplate Maximum Voltage Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DGEN", - "units": "Volts", - "minimum": 0, - "data_object": "VMaxRtg", - "event_class": 3, - "name": "DGEN.VMaxRtg.AI3" - }, - { - "index": 4, - "description": "Nameplate Active Generation Power Rating at Unity Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WMaxRtg", - "event_class": 3, - "name": "DGEN.WMaxRtg.AI4" - }, - { - "index": 5, - "description": "Nameplate Active Charging Power Rating at Unity Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWMaxRtg", - "event_class": 3, - "name": "DSTO.ChaWMaxRtg.AI5" - }, - { - "index": 6, - "description": "Nameplate Active Generation Power Rating at Specified Over-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WOvPFRtg", - "event_class": 3, - "name": "DGEN.WOvPFRtg.AI6" - }, - { - "index": 7, - "description": "Nameplate Active Charging Power Rating at Specified Over-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWOvPFRtg", - "event_class": 3, - "name": "DSTO.ChaWOvPFRtg.AI7" - }, - { - "index": 8, - "description": "Specified Over-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DGEN", - "units": "None", - "minimum": -100, - "data_object": "OvPFRtg", - "event_class": 3, - "name": "DGEN.OvPFRtg.AI8" - }, - { - "index": 9, - "description": "Nameplate Active Generation Power Rating at Specified Under-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WUnPFRtg", - "event_class": 3, - "name": "DGEN.WUnPFRtg.AI9" - }, - { - "index": 10, - "description": "Nameplate Active Charging Power Rating at Specified Under-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWUnPFRtg", - "event_class": 3, - "name": "DSTO.ChaWUnPFRtg.AI10" - }, - { - "index": 11, - "description": "Specified Under-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DGEN", - "units": "None", - "minimum": -100, - "data_object": "UnPFRtg", - "event_class": 3, - "name": "DGEN.UnPFRtg.AI11" - }, - { - "index": 12, - "description": "Nameplate Reactive Supply (Injection) Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VARs", - "minimum": 0, - "data_object": "IvarMaxRtg", - "event_class": 3, - "name": "DGEN.IvarMaxRtg.AI12" - }, - { - "index": 13, - "description": "Nameplate Reactive Absorption Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DGEN", - "units": "VARs", - "data_object": "AvarMaxRtg", - "event_class": 3, - "name": "DGEN.AvarMaxRtg.AI13" - }, - { - "index": 14, - "description": "Nameplate Apparent Generation Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VAs", - "minimum": 0, - "data_object": "VAMaxRtg", - "event_class": 3, - "name": "DGEN.VAMaxRtg.AI14" - }, - { - "index": 15, - "description": "Nameplate Apparent Charging Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "VAs", - "data_object": "ChaVAMaxRtg", - "event_class": 3, - "name": "DSTO.ChaVAMaxRtg.AI15" - }, - { - "index": 16, - "description": "Nameplate Storage Actual Energy Capacity. Nameplate (original) actual total energy capacity of the storage system expressed in Storage Capacity Units.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DSTO", - "units": "Amp-hrs or Watt-hrs", - "minimum": 0, - "data_object": "WhRtg", - "event_class": 3, - "name": "DSTO.WhRtg.AI16" - }, - { - "index": 17, - "description": "Storage Effective Actual Energy Capacity. Present actual total energy capacity of the storage system expressed in Storage Capacity Units.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DSTO", - "units": "Amp-hrs or Watt-hrs", - "minimum": 0, - "data_object": "EffWh", - "event_class": 3, - "name": "DSTO.EffWh.AI17" - }, - { - "index": 18, - "description": "Storage Usable Energy Capacity. Usable energy capacity of the storage system expressed in Storage Capacity Units.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DSTO", - "units": "Amp-hrs or Watt-hrs", - "minimum": 0, - "data_object": "UseWh", - "event_class": 3, - "name": "DSTO.UseWh.AI18" - }, - { - "index": 19, - "description": "Nameplate AC Current Maximum Generation Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DGEN", - "units": "Amps", - "minimum": 0, - "data_object": "AMaxRtg", - "event_class": 3, - "name": "DGEN.AMaxRtg.AI19" - }, - { - "index": 20, - "description": "Nameplate AC Current Maximum Charging Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DSTO", - "units": "Amps", - "data_object": "ChaAMaxRtg", - "event_class": 3, - "name": "DSTO.ChaAMaxRtg.AI20" - }, - { - "index": 21, - "description": "Remaining Reactive Susceptance", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Siemens", - "data_object": "SuscRtg", - "event_class": 3, - "name": "DGEN.SuscRtg.AI21" - }, - { - "index": 22, - "description": "IEEE 1547 Normal Operating Performance Category.", - "data_type": "AI", - "maximum": 2, - "minimum": 0, - "units": "None (list)", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "Category A", - "2": "Category B" - }, - "type": "enumerated", - "name": "AI22" - }, - { - "index": 23, - "description": "IEEE 1547 Abnormal Operating Performance Category.", - "data_type": "AI", - "maximum": 3, - "minimum": 0, - "units": "None (list)", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "Category I", - "2": "Category II", - "3": "Category III" - }, - "type": "enumerated", - "name": "AI23" - }, - { - "index": 24, - "description": "Number of System Schedules", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI24" - }, - { - "index": 25, - "description": "Number of Meters", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI25" - }, - { - "index": 26, - "description": "Number of Inverters", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI26" - }, - { - "index": 27, - "description": "Number of Batteries", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI27" - }, - { - "index": 28, - "description": "Number of DER units connected to controller", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DSTO", - "units": "None", - "minimum": 0, - "data_object": "InclDER", - "event_class": 3, - "name": "DSTO.InclDER.AI28" - }, - { - "index": 29, - "description": "Reference Voltage", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VRef", - "name": "DECP.VRef.AI29" - }, - { - "index": 30, - "description": "Reference Voltage Offset", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "data_object": "VRefOfs", - "name": "DECP.VRefOfs.AI30" - }, - { - "index": 31, - "description": "Nominal Grid Frequency", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DECP", - "units": "Hz", - "minimum": 0, - "data_object": "EcpNomHz", - "name": "DECP.EcpNomHz.AI31" - }, - { - "index": 32, - "description": "Maximum Active Generation Power", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WMax", - "name": "DGEN.WMax.AI32" - }, - { - "index": 33, - "description": "Maximum Active Charging Power", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWMax", - "name": "DSTO.ChaWMax.AI33" - }, - { - "index": 34, - "description": "Maximum Reactive Injection Power", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VARs", - "minimum": 0, - "data_object": "IvarMax", - "name": "DGEN.IvarMax.AI34" - }, - { - "index": 35, - "description": "Maximum Reactive Absorption Power", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DGEN", - "units": "VARs", - "data_object": "AvarMax", - "name": "DGEN.AvarMax.AI35" - }, - { - "index": 36, - "description": "Maximum Apparent Generation Power", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VA", - "minimum": 0, - "data_object": "VAMax", - "name": "DGEN.VAMax.AI36" - }, - { - "index": 37, - "description": "Maximum Apparent Charging Power", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "VA", - "data_object": "ChaVAMax", - "name": "DSTO.ChaVAMax.AI37" - }, - { - "index": 38, - "description": "Minimum Voltage", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VMin", - "name": "DECP.VMin.AI38" - }, - { - "index": 39, - "description": "Maximum Voltage", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VMax", - "name": "DECP.VMax.AI39" - }, - { - "index": 40, - "description": "Open Loop Response Time Percentage. Percent of target to reach within the open loop response time. Default is 90%.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DGEN", - "units": "Percent", - "minimum": 0, - "data_object": "OpnLoopPct", - "name": "DGEN.OpnLoopPct.AI40" - }, - { - "index": 41, - "description": "Power Factor Sign Convention.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "MMXU", - "units": "None", - "minimum": 1, - "data_object": "PFSign", - "allowed_values": { - "1": "IEC active power", - "2": "IEEE lead/lag" - }, - "type": "enumerated", - "name": "MMXU.PFSign.AI41" - }, - { - "index": 42, - "description": "Reference for Reactive Power Setpoints. Selects which setpoint is active. Default is <3>.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 3, - "ln_class": "DGEN", - "units": "None (list)", - "minimum": 0, - "data_object": "VArSetRef", - "allowed_values": { - "0": "Not applicable / Unknown", - "1": "Percent of Maximum Active Power (WMax)", - "2": "Percent of Maximum Reactive Power (VArMax)", - "3": "Percent of Available Reactive Power (VArAvl)" - }, - "type": "enumerated", - "name": "DGEN.VArSetRef.AI42" - }, - { - "index": 43, - "description": "System Available Active Generation Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW", - "name": "MMXU.TotW.AI43" - }, - { - "index": 44, - "description": "System Available Active Charging Power", - "data_type": "AI", - "common_data_class": "MV", - "maximum": 0, - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotChaW", - "name": "MMXU.TotChaW.AI44" - }, - { - "index": 45, - "description": "System Available Reactive Injection Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DGEN", - "units": "VARs", - "minimum": 0, - "data_object": "AvarAvl", - "name": "DGEN.AvarAvl.AI45" - }, - { - "index": 46, - "description": "System Available Reactive Absorption Power", - "data_type": "AI", - "common_data_class": "MV", - "maximum": 0, - "ln_class": "DGEN", - "units": "VARs", - "data_object": "IvarAvl", - "name": "DGEN.IvarAvl.AI46" - }, - { - "index": 47, - "description": "System Available Actual State of Charge - Present energy in the DER as a percentage of Storage Effective Actual Capacity", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DSTO", - "units": "Percent", - "minimum": 0, - "data_object": "SocPct", - "name": "DSTO.SocPct.AI47" - }, - { - "index": 48, - "description": "System Usable State of Charge - Present usable energy in the DER as a percentage of Nameplate Storage Usable Capacity", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DSTO", - "units": "Percent", - "minimum": 0, - "data_object": "UseSocPct", - "name": "DSTO.UseSocPct.AI48" - }, - { - "index": 49, - "description": "System Start-up Status", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 99, - "ln_class": "DGEN", - "units": "None (list)", - "minimum": -1, - "data_object": "DEROpSt", - "name": "DGEN.DEROpSt.AI49" - }, - { - "index": 50, - "description": "DER Start (Return to Service) Voltage High Limit. Percent of Reference Voltage.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 20000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VHiLim", - "name": "DCTE.VHiLim.AI50" - }, - { - "index": 51, - "description": "DER Start (Return to Service) Voltage Low Limit. Percent of Reference Voltage.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 10000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VLoLim", - "name": "DCTE.VLoLim.AI51" - }, - { - "index": 52, - "description": "DER Start (Return to Service) Frequency High Limit", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzHiLim", - "name": "DCTE.HzHiLim.AI52" - }, - { - "index": 53, - "description": "DER Start (Return to Service) Frequency Low Limit", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzLoLim", - "name": "DCTE.HzLoLim.AI53" - }, - { - "index": 54, - "description": "DER Start (Return to Service) Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnDlTmms", - "name": "DCTE.RtnDlTmms.AI54" - }, - { - "index": 55, - "description": "DER Start (Return to Service) Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AI55" - }, - { - "index": 56, - "description": "DER Start (Return to Service) Ramp Up Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnRmpTmms", - "name": "DCTE.RtnRmpTmms.AI56" - }, - { - "index": 57, - "description": "DER Stop (Cease to Energize) Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AI57" - }, - { - "index": 58, - "description": "DER Stop (Cease to Energize) Ramp Down Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DCTE.RmpTms.AI58" - }, - { - "index": 59, - "description": "DER Stop (Cease to Energize) Reversion Timeout Period. Time to revert from the stopped state and return to service.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AI59" - }, - { - "index": 60, - "description": "Connect/Disconnect Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AI60" - }, - { - "index": 61, - "description": "Connect/Disconnect Reversion Timeout Period. Timeout (reversion time is for the Disconnect only).", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AI61" - }, - { - "index": 62, - "description": "Maximum Generation Ramp Up Rate. The maximum generation ramp up rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRteMax", - "name": "DCTE.RpuRteMax.AI62" - }, - { - "index": 63, - "description": "Maximum Generation Ramp Down Rate. The maximum generation ramp down rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRteMax", - "name": "DCTE.RpdRteMax.AI63" - }, - { - "index": 64, - "description": "Maximum Charging Ramp Up Rate. The maximum charging ramp up rate expressed as a percentage of the Maximum Charging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRteMax", - "name": "DCTE.RpuChaRteMax.AI64" - }, - { - "index": 65, - "description": "Maximum Charging Ramp Down Rate. The maximum charging ramp down rate expressed as a percentage of the Maximum Charnging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRteMax", - "name": "DCTE.RpdChaRteMax.AI65" - }, - { - "index": 66, - "description": "Requested Settings Group.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO Enable Sensed Grid Config Detection)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP.EcpIsldSt.AI66" - }, - { - "index": 67, - "description": "Settings Group Being Edited.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO Enable Sensed Grid Config Detection)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP.EcpIsldSt.AI67" - }, - { - "index": 68, - "description": "Active Settings Group. Note this may differ from the Requested Settings Group or Settings Group Being Edited analog outputs depending on whether communications has been lost and how the Enable Sensed Grid Config Detection binary output is set.", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO42)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP.EcpIsldSt.AI68" - }, - { - "index": 69, - "description": "Freeze Counter Interval. interval between freeze counter operations after the initial occurrence. A zero value means the free counter operation is not repeated.", - "data_type": "AI", - "minimum": 0, - "name": "AI69" - }, - { - "index": 70, - "description": "Freeze Counter Interval Units. Units of the interval between freeze counter operations.", - "data_type": "AI", - "maximum": 9, - "minimum": 0, - "units": "None (list)", - "allowed_values": { - "0": "The outstation does not repeat the action,regardless of the Interval count.", - "1": "Milliseconds - In this case the interval is always counted relative to the Start Time and is constant regardless of the clock time set at the Outstation.", - "2": "Seconds - At the same millisecond within the second that is specified in the Start Time.", - "3": "Minutes - At the same second and millisecond within the minute that is specified in the Start Time.", - "4": "Hours - At the same minute,second and B7millisecond within the hour that is specified in the Start Time.", - "5": "Days - At the same time of day that is specified in the Start Time.", - "6": "Weeks - On the same day of the week at the same time of day that is specified in the Start Time", - "7": "Months - On the same day of each month at the same time of day that is specified in the Start Time. If the Start Time falls on the 29th or greater day of the month,the outstation shall not perform the action in months that do not have such a day", - "8": "Months on Same Day of Week from Start of Month - At the same timeof day on the same day of the week after the beginning of the month as the day specified in the Start Time. For instance,if the Start Time specifies the second Tuesday of February and the Interval Count is 2,the next action shall occur on the second Tuesday of April. In the same example,if the Interval Count is set to 12,this is the same as specifying,Every year on the second Tuesday in February. If the specified day does not occur in a given month when an action was scheduled to occur,the outstation shall not perform the action that month but shall perform it at the next valid scheduled time.", - "9": "Months on Same Day of Week from End of Month - The outstation shall interpret this setting as in <8>,but the day of the week shall be measured from the end of the month,e.g.,the second-last Tuesday in February." - }, - "type": "enumerated", - "name": "AI70" - }, - { - "index": 71, - "description": "Low/High Voltage Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHVT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHVT.EcpRef.AI71" - }, - { - "index": 72, - "description": "Low/High Voltage Ride-Through Voltage Reference Input. Active voltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN.Vol.AI72" - }, - { - "index": 73, - "description": "Low/High Voltage Ride-Through High Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AI73" - }, - { - "index": 74, - "description": "Low/High Voltage Ride-Through Low Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AI74" - }, - { - "index": 75, - "description": "Low/High Voltage Ride-Through High Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AI75" - }, - { - "index": 76, - "description": "Low/High Voltage Ride-Through Low Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AI76" - }, - { - "index": 77, - "description": "Low/High Frequency Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHFT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFT.EcpRef.AI77" - }, - { - "index": 78, - "description": "Low/High Frequency Ride-Through Frequency Reference Input. Active frequency measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "Hz", - "name": "MMXU.Hz.AI78" - }, - { - "index": 79, - "description": "Low/High Frequency Ride-Through High Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AI79" - }, - { - "index": 80, - "description": "Low/High Frequency Ride-Through Low Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AI80" - }, - { - "index": 81, - "description": "Low/High Frequency Ride-Through High Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AI81" - }, - { - "index": 82, - "description": "Low/High Frequency Ride-Through Low Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AI82" - }, - { - "index": 83, - "description": "Dynamic Reactive Current Support Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "ModPrio", - "name": "DRGS.ModPrio.AI83" - }, - { - "index": 84, - "description": "Dynamic Reactive Current Support Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DRGS.WinTms.AI84" - }, - { - "index": 85, - "description": "Dynamic Reactive Current Support Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DRGS.RmpTms.AI85" - }, - { - "index": 86, - "description": "Dynamic Reactive Current Support Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DRGS.RvrtTms.AI86" - }, - { - "index": 87, - "description": "Dynamic Reactive Current Support Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "EcpRef", - "name": "DRGS.EcpRef.AI87" - }, - { - "index": 88, - "description": "Dynamic Reactive Current Support Voltage Reference Input. Votltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN2.Vol.AI88" - }, - { - "index": 89, - "description": "Dynamic Reactive Current Support Moving Average Voltage", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DRGS", - "units": "Volts", - "minimum": 0, - "data_object": "VAv", - "name": "DRGS.VAv.AI89" - }, - { - "index": 90, - "description": "Dynamic Reactive Current Support Present Delta Voltage. Difference in Volts between the present measured Voltage and the Moving Average Voltage (RDGS.Vav) as a percentage of the reference voltage (VRef).", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 10000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": -10000, - "data_object": "DelV", - "name": "DRGS.DelV.AI90" - }, - { - "index": 91, - "description": "Dynamic Reactive Current Support - Gradient Mode.", - "data_type": "AI", - "common_data_class": "SPG", - "maximum": 2, - "ln_class": "DRGS", - "units": "None (list)", - "minimum": 0, - "data_object": "ArGraMod", - "allowed_values": { - "0": "Undefined", - "1": "Gradients reach 0 at the moving average Voltage", - "2": "Gradients reach 0 at the Voltage deadbands" - }, - "type": "enumerated", - "name": "DRGS.ArGraMod.AI91" - }, - { - "index": 92, - "description": "Dynamic Reactive Current Support Deadband Minimum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays above this value for the length of the Hold Time.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DRGS", - "units": "Percent", - "minimum": -10000, - "data_object": "DbVMin", - "name": "DRGS.DbVMin.AI92" - }, - { - "index": 93, - "description": "Dynamic Reactive Current Support Deadband Maximum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays below this value for the length of the Hold Time.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 10000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "DbVMax", - "name": "DRGS.DbVMax.AI93" - }, - { - "index": 94, - "description": "Dynamic Reactive Current Support Gradient for Sags. Percentage of the rated current (DRAT.ARtg) to apply capacitively per percentage of the negative deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSag", - "name": "DRGS.ArGraSag.AI94" - }, - { - "index": 95, - "description": "Dynamic Reactive Current Support Gradient for Swells. Percentage of the rated current (DRAT.ARtg) to apply inductively per percentage of the positive deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSwl", - "name": "DRGS.ArGraSwl.AI95" - }, - { - "index": 96, - "description": "Dynamic Reactive Current Support Filter Time for Moving Average Voltage (RDGS.VAv). Used to determine amount of dynamic reactive current support.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DRGS.FilTms.AI96" - }, - { - "index": 97, - "description": "Dynamic Reactive Current Support Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef) below which no reactive current support shall be applied.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "BlkZnV", - "name": "DRGS.BlkZnV.AI97" - }, - { - "index": 98, - "description": "Dynamic Reactive Current Support Hysteresis Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef). After being blocked,reactive current support shall not resume until the voltage has been above BlkZnV + HysBlkZnV.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "HysBlkZnV", - "name": "DRGS.HysBlkZnV.AI98" - }, - { - "index": 99, - "description": "Dynamic Reactive Current Support Block Zone Time. Time in milliseconds from the beginning of any \"sag\" event, before which dynamic reactive current support will always continue, regardless of how low voltage may sag.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "BlkZnTmms", - "name": "DRGS.BlkZnTmms.AI99" - }, - { - "index": 100, - "description": "Dynamic Reactive Current Support Hold Time. When the voltage returns to within the deadband limits (RDGS.dbVMin annd RDGS.dbVMax) for this length of time (measured in milliseconds), the \"sag\" or \"swell\" event is considered to be over. Reactive current support ends, frozen values are unfrozen, and a new event can begin.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "HoldTmms", - "name": "DRGS.HoldTmms.AI100" - }, - { - "index": 101, - "description": "Dynamic Reactive Current Attempted Output. Current output that the mode is attempting to achieve based on the Voltage input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DRGS", - "units": "Amps", - "minimum": 0, - "data_object": "ReqA", - "name": "DRGS.ReqA.AI101" - }, - { - "index": 102, - "description": "Dynamic Volt-Watt Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWD.ModPrio.AI102" - }, - { - "index": 103, - "description": "Dynamic Volt-Watt Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWD.WinTms.AI103" - }, - { - "index": 104, - "description": "Dynamic Volt-Watt Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWD.RmpTms.AI104" - }, - { - "index": 105, - "description": "Dynamic Volt-Watt Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWD.RvrtTms.AI105" - }, - { - "index": 106, - "description": "Dynamic Volt-Watt Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWD2.EcpRef.AI106" - }, - { - "index": 107, - "description": "Dynamic Volt-Watt Voltage Reference Input. Votltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN2.Vol.AI107" - }, - { - "index": 108, - "description": "Dynamic Volt-Watt Moving Average Voltage", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DVWD", - "units": "Volts", - "minimum": 0, - "data_object": "VAv", - "name": "DVWD2.VAv.AI108" - }, - { - "index": 109, - "description": "Dynamic Volt-Watt Present Delta Voltage", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DVWD", - "units": "Volts", - "minimum": 0, - "data_object": "DelV", - "name": "DVWD2.DelV.AI109" - }, - { - "index": 110, - "description": "Dynamic Volt-Watt Gradient. Signed quantity that establishes the ratio of additional Watts supplied (expressed in terms of % DRCT.WMax) to the present difference from the moving average voltage (expressed as % DRCT.VRef).", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DVWD", - "units": "Percent watts per percent voltage difference", - "data_object": "DynVWGra", - "name": "DVWD.DynVWGra.AI110" - }, - { - "index": 111, - "description": "Dynamic Volt-Watt Filter Time. The time in seconds used to calculate the moving average voltage for dynamic Volt-Watt support.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "VWFilTms", - "name": "DVWD.VWFilTms.AI111" - }, - { - "index": 112, - "description": "Dynamic Volt-Watt Lower Deadband. Percentage of the nominal voltage (DRCT.Vref) measured below the moving average voltage. If the present voltage is above this value,no additional Watts shall be supplied.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DVWD", - "units": "Percent", - "minimum": -1000, - "data_object": "DbVWLo", - "name": "DVWD.DbVWLo.AI112" - }, - { - "index": 113, - "description": "Dynamic Volt-Watt Upper Deadband. Percentage of the nominal voltage (DRCT.Vref) measured above the moving average voltage. If the present voltage is below this value, no additional Watts shall be supplied.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVWD", - "units": "Percent", - "minimum": 0, - "data_object": "DbVWHi", - "name": "DVWD.DbVWHi.AI113" - }, - { - "index": 114, - "description": "Dynamic Volt-Watt Attempted Output. Watt output that the mode is attempting to achieve based on the Voltage input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DVWD", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DVWD.ReqWSet.AI114" - }, - { - "index": 115, - "description": "Frequency-Watt Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW2.ModPrio.AI115" - }, - { - "index": 116, - "description": "Frequency-Watt Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AI116" - }, - { - "index": 117, - "description": "Frequency-Watt Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AI117" - }, - { - "index": 118, - "description": "Frequency-Watt Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AI118" - }, - { - "index": 119, - "description": "Frequency-Watt Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW2.EcpRef.AI119" - }, - { - "index": 120, - "description": "Frequency-Watt Frequency Reference Input. Frequency measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "MMXU", - "units": "Hz", - "minimum": 0, - "data_object": "Hz", - "name": "MMXU2.Hz.AI120" - }, - { - "index": 121, - "description": "Frequency-Watt High Starting Frequency. Delta frequency between start frequency and nominal grid frequency for high frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStr", - "name": "DHFW2.HzStr.AI121" - }, - { - "index": 122, - "description": "Frequency-Watt High Stopping Frequency. Delta frequency between stop frequency and nominal grid frequency for high frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStop", - "name": "DHFW2.HzStop.AI122" - }, - { - "index": 123, - "description": "Frequency-Watt High Discharging/Generating Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DHFW.WGra.AI123" - }, - { - "index": 124, - "description": "Frequency-Watt High Charging Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DHFW.WChaGra.AI124" - }, - { - "index": 125, - "description": "Frequency-Watt Low Starting Frequency. Delta frequency between start frequency and nominal grid frequency for low frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStr", - "name": "DLFW2.HzStr.AI125" - }, - { - "index": 126, - "description": "Frequency-Watt Low Stopping Frequency. Delta frequency between stop frequency and nominal grid frequency for low frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStop", - "name": "DLFW2.HzStop.AI126" - }, - { - "index": 127, - "description": "Frequency-Watt Low Discharging/Generating Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DLFW.WGra.AI127" - }, - { - "index": 128, - "description": "Frequency-Watt Low Charging Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DLFW.WChaGra.AI128" - }, - { - "index": 129, - "description": "Frequency-Watt Start Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW2.ActStrDlTmms.AI129" - }, - { - "index": 130, - "description": "Frequency-Watt Stop Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW2.ActStopDlTmms.AI130" - }, - { - "index": 131, - "description": "Frequency-Watt Ramp Up Time Constant. Time constant or open loop response time for moving from the current active power target to a higher active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DLFW.OpnLoopMax.AI131" - }, - { - "index": 132, - "description": "Frequency-Watt Ramp Down Time Constant. Time constant or open loop response time for moving from the current active power target to a lower active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AI132" - }, - { - "index": 133, - "description": "Frequency-Watt Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DHFW.RpuRte.AI133" - }, - { - "index": 134, - "description": "Frequency-Watt Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRteMax", - "name": "DHFW.RpdRteMax.AI134" - }, - { - "index": 135, - "description": "Frequency-Watt Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DHFW.RpuChaRte.AI135" - }, - { - "index": 136, - "description": "Frequency-Watt Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRteMax", - "name": "DHFW.RpdChaRteMax.AI136" - }, - { - "index": 137, - "description": "Frequency-Watt High Return Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "minimum": 0, - "data_object": "RtnRmpRte", - "name": "DHFW2.RtnRmpRte.AI137" - }, - { - "index": 138, - "description": "Frequency-Watt Low Return Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "minimum": 0, - "data_object": "RtnRmpRte", - "name": "DLFW2.RtnRmpRte.AI138" - }, - { - "index": 139, - "description": "Frequency-Watt Attempted Output. Watt output that the mode is attempting to achieve based on the Frequency input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DHFW", - "units": "Watts", - "data_object": "ReqWLim", - "name": "DHFW.ReqWLim.AI139" - }, - { - "index": 140, - "description": "Frequency-Watt Minimum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DAGC.SocUseMinPct.AI140" - }, - { - "index": 141, - "description": "Frequency-Watt Maximum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DAGC.SocUseMaxPct.AI141" - }, - { - "index": 142, - "description": "Active Power Limit Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWMX.ModPrio.AI142" - }, - { - "index": 143, - "description": "Active Power Limit Enabling Time Window. Time window (in seconds) within which to randomly execute a command. If the time window is zero, the command will be executed immediately.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWMX.WinTms.AI143" - }, - { - "index": 144, - "description": "Active Power Limit Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWMX.RmpTms.AI144" - }, - { - "index": 145, - "description": "Active Power Limit Reversion Timeout Period. Reversion Timeout Period (in seconds), after which the device will revert to its default status, such as closing the switch to reconnect to the grid or allowing maximum watts output, in case communications are lost or mitigating messages are not received.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWMX.RvrtTms.AI145" - }, - { - "index": 146, - "description": "Active Power Limit Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWMX.EcpRef.AI146" - }, - { - "index": 147, - "description": "Active Power Limit Reference Input. Active Power measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI147" - }, - { - "index": 148, - "description": "Active Power Limit Charge Setpoint", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMX", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMX.WLimPct.AI148" - }, - { - "index": 149, - "description": "Active Power Limit Generation Setpoint", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMN", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMN.WLimPct.AI149" - }, - { - "index": 150, - "description": "Charge/Discharge Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWGC.ModPrio.AI150" - }, - { - "index": 151, - "description": "Charge/Discharge Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWGC.WinTms.AI151" - }, - { - "index": 152, - "description": "Charge/Discharge Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWGC.RmpTms.AI152" - }, - { - "index": 153, - "description": "Charge/Discharge Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWGC.RvrtTms.AI153" - }, - { - "index": 154, - "description": "Charge/Discharge Active Power Target. Percentage of maximum active power.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "GnWPctSpt", - "name": "DWGC.GnWPctSpt.AI154" - }, - { - "index": 155, - "description": "Charge/Discharge Ramp Up Time Constant. Ramp time, in seconds, for moving from the current active power target to a higher active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWGC.OpnLoopMax.AI155" - }, - { - "index": 156, - "description": "Charge/Discharge Ramp Down Time Constant. Ramp time, in seconds, for moving from the current active power target to a lower active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWGC.OpnLoopMax.AI156" - }, - { - "index": 157, - "description": "Charge/Discharge Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DWGC.RpuRte.AI157" - }, - { - "index": 158, - "description": "Charge/Discharge Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRteMax", - "name": "DWGC.RpdRteMax.AI158" - }, - { - "index": 159, - "description": "Charge/Discharge Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DWGC.RpuChaRte.AI159" - }, - { - "index": 160, - "description": "Charge/Discharge Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRteMax", - "name": "DWGC.RpdChaRteMax.AI160" - }, - { - "index": 161, - "description": "Charge/Discharge Minimum Reserve for Storage. The reserve level below which the storage system may be only be discharged in emergency situations, expressed as a percentage of the usable capacity.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMinPct", - "name": "DWGC.SocUseMinPct.AI161" - }, - { - "index": 162, - "description": "Charge/Discharge Maximum Reserve for Storage. The reserve level above which the storage system may be only be charged in emergency situations, expressed as a percentage of the usable capacity.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMaxPct", - "name": "DWGC.SocUseMaxPct.AI162" - }, - { - "index": 163, - "description": "Coordinated Charge/Discharge Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DTCD.ModPrio.AI163" - }, - { - "index": 164, - "description": "Coordinated Charge/Discharge Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DTCD.WinTms.AI164" - }, - { - "index": 165, - "description": "Coordinated Charge/Discharge Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DTCD.RmpTms.AI165" - }, - { - "index": 166, - "description": "Coordinated Charge/Discharge Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DTCD.RvrtTms.AI166" - }, - { - "index": 167, - "description": "Coordinated Charge/Discharge Target State of Charge. Charge that the system is expected to achieve, as a percentage of the usable capacity.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DTCD", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseTgtPct", - "name": "DTCD.SocUseTgtPct.AI167" - }, - { - "index": 168, - "description": "Coordinated Charge/Discharge Target Date. Date by which the storage system must reach the target SOC. Days since January 1, 1970, UTC.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AI168" - }, - { - "index": 169, - "description": "Coordinated Charge/Discharge Target Time. Time by when the storage system must reach the target SOC. Expressed as the number of seconds since the start of Target Date.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milliseconds", - "minimum": 0, - "data_object": "DateTgtTms", - "name": "DTCD.DateTgtTms.AI169" - }, - { - "index": 170, - "description": "Coordinated Charge/Discharge Energy Request. Amount of energy that must be transferred from the grid to the charger to move the SOC from the value at the specific time of reference to the target SOC.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Watt-hours", - "minimum": 0, - "data_object": "SocWReq", - "name": "DTCD.SocWReq.AI170" - }, - { - "index": 171, - "description": "Coordinated Charge/Discharge Minimum Charging Duration. Minimum duration to move from the SOC at the time of reference to the target SOC.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurTms", - "name": "DTCD.ChaDurTms.AI171" - }, - { - "index": 172, - "description": "Coordinated Charge/Discharge Date of Reference. Date that the SOC is measured or computed by the storage system and is the basis for the Energy Request, Minimum Charging Duration, and other parameters.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AI172" - }, - { - "index": 173, - "description": "Coordinated Charge/Discharge Time of Reference. Time that the SOC is measured or computed by the storage system and is the basis for the Energy Request, Minimum Charging Duration, and other parameters.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milliseconds", - "minimum": 0, - "data_object": "SocDateTms", - "name": "DTCD.SocDateTms.AI173" - }, - { - "index": 174, - "description": "Coordinated Charge/Discharge Duration at Maximum Charge Rate. Duration that energy can be stored at the Maximum Charge Rate.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurMax", - "name": "DTCD.ChaDurMax.AI174" - }, - { - "index": 175, - "description": "Coordinated Charge/Discharge Duration Maximum Discharge Rate. Duration that energy can be delivered at the Maximum Discharge Rate.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "DschDurMax", - "name": "DTCD.DschDurMax.AI175" - }, - { - "index": 176, - "description": "Active Power Response Mode #1 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPKP.ModPrio.AI176" - }, - { - "index": 177, - "description": "Active Power Response Mode #1 Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPKP.WinTms.AI177" - }, - { - "index": 178, - "description": "Active Power Response Mode #1 Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPKP.RmpTms.AI178" - }, - { - "index": 179, - "description": "Active Power Response Mode #1 Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPKP.RvrtTms.AI179" - }, - { - "index": 180, - "description": "Active Power Response Mode #1 Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPKP.EcpRef.AI180" - }, - { - "index": 181, - "description": "Active Power Response Mode #1 Reference Power Measured", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI181" - }, - { - "index": 182, - "description": "Active Power Response Mode #1 Power Threshold", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPKP", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DPKP.PkPwrWLim.AI182" - }, - { - "index": 183, - "description": "Active Power Response Mode #1 Ratio", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DPKP", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DPKP.PkPwrFolPct.AI183" - }, - { - "index": 184, - "description": "Active Power Response Mode #1 Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DPKP.RpuRte.AI184" - }, - { - "index": 185, - "description": "Active Power Response Mode #1 Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DPKP.RpdRte.AI185" - }, - { - "index": 186, - "description": "Active Power Response Mode #1 Attempted Output. Watt output that the mode is attempting to achieve based on the Watts input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DPKP", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DPKP.ReqWSet.AI186" - }, - { - "index": 187, - "description": "Active Power Response Mode #2 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DGFL.ModPrio.AI187" - }, - { - "index": 188, - "description": "Active Power Response Mode #2 Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DGFL.WinTms.AI188" - }, - { - "index": 189, - "description": "Active Power Response Mode #2 Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DGFL.RmpTms.AI189" - }, - { - "index": 190, - "description": "Active Power Response Mode #2 Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DGFL.RvrtTms.AI190" - }, - { - "index": 191, - "description": "Active Power Response Mode #2 Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DGFL.EcpRef.AI191" - }, - { - "index": 192, - "description": "Active Power Response Mode #2 Reference Power Measured", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI192" - }, - { - "index": 193, - "description": "Active Power Response Mode #2 Power Threshold", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DGFL.PkPwrWLim.AI193" - }, - { - "index": 194, - "description": "Active Power Response Mode #2 Ratio", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DGFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DGFL.PkPwrFolPct.AI194" - }, - { - "index": 195, - "description": "Active Power Response Mode #2 Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DGFL.RpuRte.AI195" - }, - { - "index": 196, - "description": "Active Power Response Mode #2 Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DGFL.RpdRte.AI196" - }, - { - "index": 197, - "description": "Active Power Response Mode #2 Attempted Output. Watt output that the mode is attempting to achieve based on the Watts input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DGFL", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DGFL.ReqWSet.AI197" - }, - { - "index": 198, - "description": "Active Power Response Mode #3 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DLFL.ModPrio.AI198" - }, - { - "index": 199, - "description": "Active Power Response Mode #3 Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DLFL.WinTms.AI199" - }, - { - "index": 200, - "description": "Active Power Response Mode #3 Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DLFL.RmpTms.AI200" - }, - { - "index": 201, - "description": "Active Power Response Mode #3 Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DLFL.RvrtTms.AI201" - }, - { - "index": 202, - "description": "Active Power Response Mode #3 Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DLFL.EcpRef.AI202" - }, - { - "index": 203, - "description": "Active Power Response Mode #3 Reference Power Measured", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI203" - }, - { - "index": 204, - "description": "Active Power Response Mode #3 Power Threshold", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DLFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DLFL.PkPwrWLim.AI204" - }, - { - "index": 205, - "description": "Active Power Response Mode #3 Ratio", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DLFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DLFL.PkPwrFolPct.AI205" - }, - { - "index": 206, - "description": "Active Power Response Mode #3 Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DLFL.RpuRte.AI206" - }, - { - "index": 207, - "description": "Active Power Response Mode #3 Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DLFL.RpdRte.AI207" - }, - { - "index": 208, - "description": "Active Power Response Mode #3 Attempted Output. Watt output that the mode is attempting to achieve based on the Watts input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DLFL", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DLFL.ReqWSet.AI208" - }, - { - "index": 209, - "description": "AGC Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DAGC.ModPrio.AI209" - }, - { - "index": 210, - "description": "AGC Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DAGC.WinTms.AI210" - }, - { - "index": 211, - "description": "AGC Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DAGC.RmpTms.AI211" - }, - { - "index": 212, - "description": "AGC Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DAGC.RvrtTms.AI212" - }, - { - "index": 213, - "description": "AGC Active Power Target", - "data_type": "AI", - "common_data_class": "APC", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "GnWSpt", - "name": "DAGC.GnWSpt.AI213" - }, - { - "index": 214, - "description": "AGC Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpUpTms", - "name": "DAGC.RmpUpTms.AI214" - }, - { - "index": 215, - "description": "AGC Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpDnTms", - "name": "DAGC.RmpDnTms.AI215" - }, - { - "index": 216, - "description": "AGC Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DAGC.RpuRte.AI216" - }, - { - "index": 217, - "description": "AGC Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DAGC.RpdRte.AI217" - }, - { - "index": 218, - "description": "AGC Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DAGC.RpuChaRte.AI218" - }, - { - "index": 219, - "description": "AGC Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DAGC.RpdChaRte.AI219" - }, - { - "index": 220, - "description": "AGC Minimum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DAGC.SocUseMinPct.AI220" - }, - { - "index": 221, - "description": "AGC Maximum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DAGC.SocUseMaxPct.AI221" - }, - { - "index": 222, - "description": "AGC Maximum Watts Available", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "WMaxAvl", - "name": "DAGC.WMaxAvl.AI222" - }, - { - "index": 223, - "description": "AGC Minimum Watts Available", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "WMinAvl", - "name": "DAGC.WMinAvl.AI223" - }, - { - "index": 224, - "description": "AGC Expected State of Charge", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocExpc", - "name": "DAGC.SocExpc.AI224" - }, - { - "index": 225, - "description": "AGC Expected State of Energy", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SoeExpc", - "name": "DAGC.SoeExpc.AI225" - }, - { - "index": 226, - "description": "AGC Expected State of Charge Time Interval", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "SocExpcTms", - "name": "DAGC.SocExpcTms.AI226" - }, - { - "index": 227, - "description": "Active Power Smoothing Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWSM.ModPrio.AI227" - }, - { - "index": 228, - "description": "Active Power Smoothing Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWSM.WinTms.AI228" - }, - { - "index": 229, - "description": "Active Power Smoothing Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWSM.RmpTms.AI229" - }, - { - "index": 230, - "description": "Active Power Smoothing Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWSM.RvrtTms.AI230" - }, - { - "index": 231, - "description": "Active Power Smoothing Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWSM.EcpRef.AI231" - }, - { - "index": 232, - "description": "Active Power Smoothing Reference Power Input. Active Power measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "minimum": 0, - "data_object": "TotW", - "name": "MMXU.TotW.AI232" - }, - { - "index": 233, - "description": "Active Power Smoothing Gradient. Signed quantity that establishes the ratio of additional smoothing Watts provided to the present delta-watts of the reference load or generation. Delta Watts is the difference between the moving average and the present value of the reference power. Positive values of this gradient are for following load (increased reference load results in a dynamic increase in DER output), and negative values are for following generation (increased reference generation results in a dynamic decrease in DER output).", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DWSM", - "units": "Watts per Delta-watt", - "data_object": "WSmthGra", - "name": "DWSM.WSmthGra.AI233" - }, - { - "index": 234, - "description": "Active Power Smoothing Lower Limit. Difference in Watts from the moving average of the reference power above which no smoothing shall be applied.", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DWSM", - "units": "Watts", - "data_object": "WSmthLoLim", - "name": "DWSM.WSmthLoLim.AI234" - }, - { - "index": 235, - "description": "Active Power Smoothing Upper Limit. Difference in Watts from the moving average of the reference power below which no smoothing shall be applied.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DWSM", - "units": "Watts", - "minimum": 0, - "data_object": "WSmthHiLim", - "name": "DWSM.WSmthHiLim.AI235" - }, - { - "index": 236, - "description": "Active Power Smoothing Filter Time (Seconds). Time in seconds used to calculate the moving average of the reference load or generation being smoothed.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DWSM.FilTms.AI236" - }, - { - "index": 237, - "description": "Active Power Smoothing Discharge Ramp Up Rate. The maximum generation ramp up rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DWSM.RpuRte.AI237" - }, - { - "index": 238, - "description": "Active Power Smoothing Discharge Ramp Down Rate. The maximum generation ramp down rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DWSM.RpdRte.AI238" - }, - { - "index": 239, - "description": "Active Power Smoothing Charge Ramp Up Rate. The maximum charging ramp up rate expressed as a percentage of the Maximum Charging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DWSM.RpuChaRte.AI239" - }, - { - "index": 240, - "description": "Active Power Smoothing Charge Ramp Down Rate. The maximum charging ramp down rate expressed as a percentage of the Maximum Charnging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DWSM.RpdChaRte.AI240" - }, - { - "index": 241, - "description": "Active Power Smoothing Attempted Output. Watt output that the mode is attempting to achieve based on the Watt input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DWSM", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DWSM.ReqWSet.AI241" - }, - { - "index": 242, - "description": "Volt-Watt Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWC.ModPrio.AI242" - }, - { - "index": 243, - "description": "Volt-Watt Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWC.WinTms.AI243" - }, - { - "index": 244, - "description": "Volt-Watt Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWC.RmpTms.AI244" - }, - { - "index": 245, - "description": "Volt-Watt Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWC.RvrtTms.AI245" - }, - { - "index": 246, - "description": "Volt-Watt Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWC.EcpRef.AI246" - }, - { - "index": 247, - "description": "Volt-Watt Reference Voltage Input. Voltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN.Vol.AI247" - }, - { - "index": 248, - "description": "Volt-Watt Curve Index. Index of the Volt-Watt curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "VWCrv", - "name": "DVWC.VWCrv.AI248" - }, - { - "index": 249, - "description": "Volt-Watt Attempted Output. Maximum active power the outstation will attempt to generate or absorb based on the Voltage input and selected curve.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DVWC", - "units": "Watts", - "data_object": "ReqWLim", - "name": "DVWC.ReqWLim.AI249" - }, - { - "index": 250, - "description": "Volt-Watt Filter Time (Seconds)", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DVWC.FilTms.AI250" - }, - { - "index": 251, - "description": "Volt-Watt Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVWC.OpnLoopMax.AI251" - }, - { - "index": 252, - "description": "Volt-Watt Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVWC.OpnLoopMax.AI252" - }, - { - "index": 253, - "description": "Volt-Watt Discharging Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DVWC.RpuRte.AI253" - }, - { - "index": 254, - "description": "Volt-Watt Discharging Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DVWC.RpdRte.AI254" - }, - { - "index": 255, - "description": "Volt-Watt Charging Ramp Up Rate. Maximum charging ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DVWC.RpuChaRte.AI255" - }, - { - "index": 256, - "description": "Volt-Watt Charging Ramp Down Rate. Maximum charging ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DVWC.RpdChaRte.AI256" - }, - { - "index": 257, - "description": "Frequency-Watt Curve Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW.ModPrio.AI257" - }, - { - "index": 258, - "description": "Frequency-Watt Curve Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AI258" - }, - { - "index": 259, - "description": "Frequency-Watt Curve Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AI259" - }, - { - "index": 260, - "description": "Frequency-Watt Curve Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AI260" - }, - { - "index": 261, - "description": "Frequency-Watt Curve Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW.EcpRef.AI261" - }, - { - "index": 262, - "description": "Frequency-Watt Curve Frequency Reference Input. Frequency measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "MMXU", - "units": "Hz", - "minimum": 0, - "data_object": "Hz", - "name": "MMXU.Hz.AI262" - }, - { - "index": 263, - "description": "Frequency-Watt Curve - Curve Index. Index of the Frequency-Watt curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HzWCrv", - "name": "DHFW.HzWCrv.AI263" - }, - { - "index": 264, - "description": "Frequency-Watt Curve - High Frequency Hysteresis Curve Index", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DHFW.HysCrv.AI264" - }, - { - "index": 265, - "description": "Frequency-Watt Curve - Low Frequency Hysteresis Curve Index", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DLFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DLFW.HysCrv.AI265" - }, - { - "index": 266, - "description": "Frequency-Watt Curve Start Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW.ActStrDlTmms.AI266" - }, - { - "index": 267, - "description": "Frequency-Watt Curve Stop Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW.ActStopDlTmms.AI267" - }, - { - "index": 268, - "description": "Frequency-Watt Curve Ramp Up Time Constant. Time constant or open loop response time for moving from the current active power target to a higher active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AI268" - }, - { - "index": 269, - "description": "Frequency-Watt Curve Ramp Down Time Constant. Time constant or open loop response time for moving from the current active power target to a lower active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AI269" - }, - { - "index": 270, - "description": "Frequency-Watt Curve Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DHFW.RpuRte.AI270" - }, - { - "index": 271, - "description": "Frequency-Watt Curve Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DHFW.RpdRte.AI271" - }, - { - "index": 272, - "description": "Frequency-Watt Curve Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DHFW.RpuChaRte.AI272" - }, - { - "index": 273, - "description": "Frequency-Watt Curve Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DHFW.RpdChaRte.AI273" - }, - { - "index": 274, - "description": "Frequency-Watt Attempted Output. Watt output that the mode is attempting to achieve based on the Frequency input and selected curve. If Snapshot of Power is not enabled,this is the maximum active power the outstation will attempt to generate or absorb.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DHFW", - "units": "Watts", - "data_object": "ReqWLim", - "name": "DHFW.ReqWLim.AI274" - }, - { - "index": 275, - "description": "Frequency-Watt Curve Minimum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DHFW.SocUseMinPct.AI275" - }, - { - "index": 276, - "description": "Frequency-Watt Curve Maximum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DHFW.SocUseMaxPct.AI276" - }, - { - "index": 277, - "description": "Constant VArs Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVAR.ModPrio.AI277" - }, - { - "index": 278, - "description": "Constant VArs Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVAR.WinTms.AI278" - }, - { - "index": 279, - "description": "Constant VArs Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVAR.RmpTms.AI279" - }, - { - "index": 280, - "description": "Constant VArs Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVAR.RvrtTms.AI280" - }, - { - "index": 281, - "description": "Constant VArs Reactive Power Target. Percentage of maximum reactive power.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVAR", - "units": "Percent", - "minimum": -1000, - "data_object": "VArTgtPct", - "name": "DVAR.VArTgtPct.AI281" - }, - { - "index": 282, - "description": "Constant VArs Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AI282" - }, - { - "index": 283, - "description": "Constant VArs Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AI283" - }, - { - "index": 284, - "description": "Fixed Power Factor Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "minimum": 0, - "data_object": "ModPrio", - "name": "DFPF.ModPrio.AI284" - }, - { - "index": 285, - "description": "Fixed Power Factor Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DFPF.WinTms.AI285" - }, - { - "index": 286, - "description": "Fixed Power Factor Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DFPF.RmpTms.AI286" - }, - { - "index": 287, - "description": "Fixed Power Factor Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DFPF.RvrtTms.AI287" - }, - { - "index": 288, - "description": "Fixed Power Factor Setpoint - Generation/Discharging", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFGnTgt", - "name": "DFPF.PFGnTgt.AI288" - }, - { - "index": 289, - "description": "Fixed Power Factor Setpoint - Charging", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFLodTgt", - "name": "DFPF.PFLodTgt.AI289" - }, - { - "index": 290, - "description": "Volt-Var Control Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVVR.ModPrio.AI290" - }, - { - "index": 291, - "description": "Volt-VAr Control Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVVR.WinTms.AI291" - }, - { - "index": 292, - "description": "Volt-VAr Control Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVVR.RmpTms.AI292" - }, - { - "index": 293, - "description": "Volt-VAr Control Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVVR.RvrtTms.AI293" - }, - { - "index": 294, - "description": "Volt-VAr Control Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVVR.EcpRef.AI294" - }, - { - "index": 295, - "description": "Volt-VAr Control Voltage Input. Voltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN.Vol.AI295" - }, - { - "index": 296, - "description": "Volt-VAr Control Adjusted Voltage Reference. The Voltage used as reference for Volt-VAr control. If Autonomous Voltage Reference Adjustment is disabled,this is the same fixed value as the Reference Voltage.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DVVR", - "units": "Volts", - "minimum": 0, - "data_object": "VRefSet", - "name": "DVVR.VRefSet.AI296" - }, - { - "index": 297, - "description": "Volt-VAr Curve Index. Index of the Volt-VAr curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "VVArCrv", - "name": "DVVR.VVArCrv.AI297" - }, - { - "index": 298, - "description": "Volt-VAr Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AI298" - }, - { - "index": 299, - "description": "Volt-VAr Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AI299" - }, - { - "index": 300, - "description": "Volt-VAr Autonomous Voltage Reference Adjustment Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "VRefTmms", - "name": "DVVR.VRefTmms.AI300" - }, - { - "index": 301, - "description": "Volt-VAr Attempted Output. VAr output that the mode is attempting to achieve based on the Voltage input and selected curve.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DVVR", - "units": "VARs", - "data_object": "ReqVAr", - "name": "DVVR.ReqVAr.AI301" - }, - { - "index": 302, - "description": "Watt-VAr Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWVR.ModPrio.AI302" - }, - { - "index": 303, - "description": "Watt-VAr Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWVR.WinTms.AI303" - }, - { - "index": 304, - "description": "Watt-VAr Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWVR.RmpTms.AI304" - }, - { - "index": 305, - "description": "Watt-VAr Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWVR.RvrtTms.AI305" - }, - { - "index": 306, - "description": "Watt-VAr Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWVR.EcpRef.AI306" - }, - { - "index": 307, - "description": "Watt-VAr Reference Power Input. Power measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW", - "name": "MMXU.TotW.AI307" - }, - { - "index": 308, - "description": "Watt-VAr Curve Index. Index of the Watt-VAr curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "WVArCrv", - "name": "DWVR.WVArCrv.AI308" - }, - { - "index": 309, - "description": "Watt-VAr Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AI309" - }, - { - "index": 310, - "description": "Watt-VAr Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AI310" - }, - { - "index": 311, - "description": "Watt-VAr Attempted Output. VAr output that the mode is attempting to achieve based on the Watt input and selected curve.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DWVR", - "units": "VARs", - "data_object": "ReqVAr", - "name": "DWVR.ReqVAr.AI311" - }, - { - "index": 312, - "description": "Power Factor Correction Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPFC.ModPrio.AI312" - }, - { - "index": 313, - "description": "Power Factor Correction Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPFC.WinTms.AI313" - }, - { - "index": 314, - "description": "Power Factor Correction Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPFC.RmpTms.AI314" - }, - { - "index": 315, - "description": "Power Factor Correction Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPFC.RvrtTms.AI315" - }, - { - "index": 316, - "description": "Power Factor Correction Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPFC.EcpRef.AI316" - }, - { - "index": 317, - "description": "Power Factor Correction Reference Power Factor Input. Power factor measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF", - "name": "MMXU.TotPF.AI317" - }, - { - "index": 318, - "description": "Power Factor Correction Average PF Target", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFTrg", - "name": "DPFC.PFTrg.AI318" - }, - { - "index": 319, - "description": "Power Factor Correction Lower PF Limit", - "data_type": "AI", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AI319" - }, - { - "index": 320, - "description": "Power Factor Correction Upper PF Limit", - "data_type": "AI", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AI320" - }, - { - "index": 321, - "description": "Pricing Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPRG.ModPrio.AI321" - }, - { - "index": 322, - "description": "Pricing Mode Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPRG.WinTms.AI322" - }, - { - "index": 323, - "description": "Pricing Mode Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPRG.RmpTms.AI323" - }, - { - "index": 324, - "description": "Pricing Mode Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPRG.RvrtTms.AI324" - }, - { - "index": 325, - "description": "Pricing Mode Setpoint: Hundredths of local currency per Kilowatt-Hr.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "ln_class": "DPRG", - "units": "100ths of local currency", - "data_object": "PrcRef", - "name": "DPRG.PrcRef.AI325" - }, - { - "index": 326, - "description": "Pricing Mode Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AI326" - }, - { - "index": 327, - "description": "Pricing Mode Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AI327" - }, - { - "index": 328, - "description": "Curve Edit Selector Index of the curve which is currently being viewed and/or changed", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DGSM", - "minimum": 1, - "data_object": "InCrv", - "name": "DGSMn.InCrv.AI328", - "type": "selector_block", - "selector_block_start": 328, - "selector_block_end": 532 - - }, - { - "index": 329, - "description": "Curve Mode Type", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 20, - "ln_class": "DGSM", - "units": "None (list)", - "minimum": 0, - "data_object": "ModTyp", - "allowed_values": { - "0": "Curve is not defined", - "1": "None, dimensionless", - "2": "Volt-Var modes VV11-VV12", - "3": "Frequency-Watt mode FW22", - "4": "Watt-VAr mode WP42", - "5": "Voltage-Watt modes VW51-VW52", - "6": "Remain Connected", - "7": "Temperature mode", - "8": "Pricing signal mode", - "9": "HVRT Must Trip", - "10": "HVRT Momentary Cessation", - "11": "LVRT Must Trip", - "12": "LVRT Momentary Cessation", - "13": "HFRT Must Trip", - "14": "HFRT Momentary Cessation", - "15": "LFRT Must Trip", - "16": "LFRT Momentary Cessation" - }, - "type": "enumerated", - "name": "DGSMn.ModTyp.AI329" - }, - { - "index": 330, - "description": "Curve Number of Points", - "data_type": "AI", - "common_data_class": "CSG", - "maximum": 100, - "ln_class": "FMAR", - "minimum": 0, - "data_object": "PairArr.NumPts", - "name": "FMARn.PairArr.NumPts.AI330" - }, - { - "index": 331, - "description": "Independent (X-Value) Units for Curve", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "allowed_values": { - "0": "Curve is not defined", - "1": "Not applicable / Unknown", - "4": "Time", - "23": "Celsius Temperature", - "29": "Voltage", - "33": "Frequency", - "38": "Watts", - "100": "Price in hundredths of local currency", - "129": "Percent Voltage", - "133": "Percent Frequency", - "138": "Percent Watts", - "233": "Frequency Deviation" - }, - "type": "enumerated", - "minimum": 0, - "data_object": "IndpUnits", - "name": "FMARn.IndpUnits.AI331" - }, - { - "index": 332, - "description": "Dependent (Y-Value) Units for Curve", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "minimum": 0, - "data_object": "DepRef", - "allowed_values": { - "0": "Curve is not defined", - "1": "Not applicable / unknown", - "2": "VArs as percent of max VArs (VARMax)", - "3": "VArs as percent of max available VArs (VArAval)", - "4": "Vars as percent of max Watts (Wmax) - not used", - "5": "Watts as percent of max Watts (Wmax)", - "6": "Watts as percent of frozen active power (DeptSnptRef)", - "7": "Power Factor in EEI notation", - "8": "Volts as a percent of the nominal voltage (VRef)", - "9": "Frequency as a percentage of the Nominal Grid Frequency (ECPNomHz)" - }, - "type": "enumerated", - "name": "FMARn.DepRef.AI332" - }, - { - "index": 333, - "description": "Curve X-Value and Y-Value pairs for curve points 1 - 100", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "FMAR", - "units": "Varies", - "data_object": "PairArr.CrvPts", - "name": "FMARn.PairArr.CrvPts.AI333", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FMARn.PairArr.CrvPts.AI333.xVal" - }, - { - "name": "FMARn.PairArr.CrvPts.AI333.yVal" - } - ] - }, - { - "index": 533, - "description": "System Meter Type of Connection Point", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 99, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpConnType", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "DER to local EPS", - "2": "Internal to DER", - "3": "local EPS with load to area EPS (PCC with load)", - "4": "local EPS w/o load to area EPS (PCC without load)", - "5": "Load to local EPS", - "6": "External to DER beyond the PCC", - "7": "External to DER within the local EPS", - "8": "Auxiliary DER Load", - "9": "Group of DERs to the area EPS", - "99": "Other" - }, - "type": "enumerated", - "name": "DECP.EcpConnType.AI533" - }, - { - "index": 534, - "description": "System Meter Type of Circuit Phases", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 8, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "PhsConnTyp", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "Single phase", - "2": "Split phase", - "3": "2-phase", - "4": "3-phase delta", - "5": "3-phase wye", - "6": "3-phase wye grounded", - "7": "3-phase / 3-wire (inverter type)", - "8": "3-phase / 4-wire (inverter type)" - }, - "type": "enumerated", - "name": "DECP.PhsConnTyp.AI534" - }, - { - "index": 535, - "description": "System Meter Apparent Power Calculation Method. Calculation method for total apparent power calculation.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "MMXU", - "units": "None (list)", - "minimum": 0, - "data_object": "ClcTotVA", - "allowed_values": { - "0": "unknown", - "1": "vector", - "2": "arithmetic" - }, - "type": "enumerated", - "name": "MMXU.ClcTotVA.AI535" - }, - { - "index": 536, - "description": "System Meter Frequency", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "MMXU", - "units": "Hz", - "minimum": 0, - "data_object": "Hz", - "event_class": 3, - "name": "MMXU.Hz.AI536" - }, - { - "index": 537, - "description": "System Meter Active Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "event_class": 3, - "name": "MMXU.TotW.AI537" - }, - { - "index": 538, - "description": "System Meter Active Power A", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "W.phsA.mag", - "event_class": 1, - "name": "MMXU.W.phsA.mag.AI538" - }, - { - "index": 539, - "description": "System Meter Active Power B", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "W.phsB.mag", - "event_class": 1, - "name": "MMXU.W.phsB.mag.AI539" - }, - { - "index": 540, - "description": "System Meter Active Power C", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "W.phsC.mag", - "event_class": 1, - "name": "MMXU.W.phsC.mag.AI540" - }, - { - "index": 541, - "description": "System Meter Reactive Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "data_object": "TotVAr", - "event_class": 3, - "name": "MMXU.TotVAr.AI541" - }, - { - "index": 542, - "description": "System Meter Reactive Power A", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "VAr", - "data_object": "VAr.phsA.mag", - "event_class": 1, - "name": "MMXU.VAr.phsA.mag.AI542" - }, - { - "index": 543, - "description": "System Meter Reactive Power B", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "VAr", - "data_object": "VAr.phsB.mag", - "event_class": 1, - "name": "MMXU.VAr.phsB.mag.AI543" - }, - { - "index": 544, - "description": "System Meter Reactive Power C", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "VAr", - "data_object": "VAr.phsC.mag", - "event_class": 1, - "name": "MMXU.VAr.phsC.mag.AI544" - }, - { - "index": 545, - "description": "System Meter Power Factor", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF", - "event_class": 3, - "name": "MMXU.TotPF.AI545" - }, - { - "index": 546, - "description": "System Meter Apparent Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VA", - "data_object": "TotVA", - "event_class": 3, - "name": "MMXU.TotVA.AI546" - }, - { - "index": 547, - "description": "System Meter Phase A Volts", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.mag", - "event_class": 3, - "name": "MMXU.PhV.phsA.mag.AI547" - }, - { - "index": 548, - "description": "System Meter Phase A Angle", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "maximum": 3600, - "ln_class": "MMXU", - "units": "Degrees", - "minimum": 0, - "data_object": "PhV.phsA.ang", - "event_class": 3, - "name": "MMXU.PhV.phsA.ang.AI548" - }, - { - "index": 549, - "description": "System Meter Phase B Volts", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.mag", - "event_class": 3, - "name": "MMXU.PhV.phsB.mag.AI549" - }, - { - "index": 550, - "description": "System Meter Phase B Angle", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "maximum": 3600, - "ln_class": "MMXU", - "units": "Degrees", - "minimum": 0, - "data_object": "PhV.phsB.ang", - "event_class": 3, - "name": "MMXU.PhV.phsB.ang.AI550" - }, - { - "index": 551, - "description": "System Meter Phase C Volts", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.mag", - "event_class": 3, - "name": "MMXU.PhV.phsC.mag.AI551" - }, - { - "index": 552, - "description": "System Meter Phase C Angle", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "maximum": 3600, - "ln_class": "MMXU", - "units": "Degrees", - "minimum": 0, - "data_object": "PhV.phsC.ang", - "event_class": 3, - "name": "MMXU.PhV.phsC.ang.AI552" - }, - { - "index": 553, - "description": "System Meter Average Line to Line Voltage", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "AvPPVPhs", - "event_class": 1, - "name": "MMXU.AvPPVPhs.AI553" - }, - { - "index": 554, - "description": "System Meter Current A", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Amps", - "data_object": "A.phsA.mag", - "event_class": 1, - "name": "MMXU.A.phsA.mag.AI554" - }, - { - "index": 555, - "description": "System Meter Current B", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Amps", - "data_object": "A.phsB.mag", - "event_class": 1, - "name": "MMXU.A.phsB.mag.AI555" - }, - { - "index": 556, - "description": "System Meter Current C", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Amps", - "data_object": "A.phsC.mag", - "event_class": 1, - "name": "MMXU.A.phsC.mag.AI556" - }, - { - "index": 557, - "description": "System Meter Active Power - High Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.hLim", - "event_class": 3, - "name": "MMXU.TotW.rangeC.hLim.AI557" - }, - { - "index": 558, - "description": "System Meter Active Power - Low Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.lLim", - "event_class": 3, - "name": "MMXU.TotW.rangeC.lLim.AI558" - }, - { - "index": 559, - "description": "System Meter Reactive Power - High Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.hLim", - "event_class": 3, - "name": "MMXU.TotVAr.rangeC.hLim.AI559" - }, - { - "index": 560, - "description": "System Meter Reactive Power - Low Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.lLim", - "event_class": 3, - "name": "MMXU.TotVAr.rangeC.lLim.AI560" - }, - { - "index": 561, - "description": "System Meter Power Factor - High Threshold", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.hLim", - "event_class": 3, - "name": "MMXU.TotPF.rangeC.hLim.AI561" - }, - { - "index": 562, - "description": "System Meter Power Factor - Low Threshold", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.lLim", - "event_class": 3, - "name": "MMXU.TotPF.rangeC.lLim.AI562" - }, - { - "index": 563, - "description": "System Meter Phase A Volts - High Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.hLim", - "event_class": 3, - "name": "MMXU.PhV.phsA.rangeC.hLim.AI563" - }, - { - "index": 564, - "description": "System Meter Phase A Volts - Low Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.lLim", - "event_class": 3, - "name": "MMXU.PhV.phsA.rangeC.lLim.AI564" - }, - { - "index": 565, - "description": "System Meter Phase B Volts - High Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.hLim", - "event_class": 3, - "name": "MMXU.PhV.phsB.rangeC.hLim.AI565" - }, - { - "index": 566, - "description": "System Meter Phase B Volts - Low Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.lLim", - "event_class": 3, - "name": "MMXU.PhV.phsB.rangeC.lLim.AI566" - }, - { - "index": 567, - "description": "System Meter Phase C Volts - High Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.hLim", - "event_class": 3, - "name": "MMXU.PhV.phsC.rangeC.hLim.AI567" - }, - { - "index": 568, - "description": "System Meter Phase C Volts - Low Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.lLim", - "event_class": 3, - "name": "MMXU.PhV.phsC.rangeC.lLim.AI568" - }, - { - "index": 569, - "description": "Running Schedule Index. Index of the highest priority schedule that is currently running or 0 if no schedule is currently running.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "ActSchdRef", - "name": "FSCC1.ActSchdRef.AI569" - }, - { - "index": 570, - "description": "Schedule to Edit Selector", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "event_class": 3, - "name": "FSCC.Schd.AI570", - "type": "selector_block", - "selector_block_start": 570, - "selector_block_end": 780 - - }, - { - "index": 571, - "description": "Selected Schedule Identity", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "event_class": 3, - "name": "FSCC.Schd.AI571" - }, - { - "index": 572, - "description": "Selected Schedule Priority. Priority of the schedule relative to other running schedules. Lower values have higher priority over higher values.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 1, - "data_object": "SchdPrio", - "event_class": 3, - "name": "FSCH.SchdPrio.AI572" - }, - { - "index": 573, - "description": "Selected Schedule Type.", - "data_type": "AI", - "maximum": 21, - "minimum": 0, - "units": "None (list)", - "event_class": 3, - "allowed_values": { - "1": "Low/High Voltage Ride-Through Hi Must Trip", - "2": "Low/High Voltage Ride-Through Low Must Trip", - "3": "Low/High Voltage Ride-Through Hi Momentary", - "4": "Low/High Voltage Ride-Through Lo Momentary", - "5": "Low/High Frequency Ride-Through Hi Must Trip", - "6": "Low/High Frequency Ride-Through Lo Must Trip", - "7": "Low/High Frequency Ride-Through Hi Momentary", - "8": "Low/High Frequency Ride-Through Low Momentary", - "9": "Dynamic Reactive Current Support - On/Off", - "10": "Dynamic Volt-Watt - On/Off", - "11": "Frequency-Watt - On/Off", - "12": "Active Power Limit - Charging", - "13": "Active Power Limit - Generating", - "14": "Charge/Discharge - Percent of Maximum", - "15": "Coordinated Charge/Discharge - SOC Target", - "16": "Active Power Response #1 - On/Off", - "17": "Active Power Response #2 - On/Off", - "18": "Active Power Response #3 - On/Off", - "19": "AGC Watts", - "20": "Active Power Smoothing - On/Off", - "21": "Volt-Watt Curve Index", - "22": "Frequency-Watt Curve Curve Index", - "23": "Frequency-Watt Curve High Hysteresis", - "24": "Frequency-Watt Curve Low Hysteresis", - "25": "Constant VArs - Percent of Maximum", - "26": "Fixed Power Factor - Power Factor", - "27": "Volt-VAr Curve Index", - "28": "Watt-VAr Curve Index", - "29": "Power Factor Correction - On/Off", - "30": "Reserved - For pricing mode" - }, - "type": "enumerated", - "name": "AI573" - }, - { - "index": 574, - "description": "Selected Schedule Start Date. Number of days since January 1, 1970, UTC.", - "data_type": "AI", - "common_data_class": "TSG", - "ln_class": "FSCH", - "units": "Days", - "minimum": 0, - "data_object": "StrTm", - "event_class": 3, - "name": "FSCH.StrTm.AI574" - }, - { - "index": 575, - "description": "Selected Schedule Start Time. Milliseconds since the start of Schedule Start Date.", - "data_type": "AI", - "common_data_class": "TSG", - "maximum": 86400000, - "ln_class": "FSCH", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "StrTm", - "event_class": 3, - "name": "FSCH.StrTm.AI575" - }, - { - "index": 576, - "description": "Selected Schedule Repeat Interval. Interval between actions after the initial occurrence. A zero value means the schedule is not repeated.", - "data_type": "AI", - "common_data_class": "TCS", - "ln_class": "FSCH", - "units": "Varies", - "minimum": 0, - "data_object": "NxtStrTm", - "event_class": 3, - "name": "FSCH.NxtStrTm.AI576" - }, - { - "index": 577, - "description": "Selected Schedule Repeat Interval Units", - "data_type": "AI", - "common_data_class": "SPG", - "maximum": 8, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "SchdReuse", - "event_class": 3, - "allowed_values": { - "0": "No Repeat", - "1": "sec", - "2": "Minutes", - "3": "Hours", - "4": "Days", - "5": "Weeks", - "6": "Months", - "7": "Months on Same Day of Week", - "8": "Months on Same Day of Week from End" - }, - "type": "enumerated", - "name": "FSCH.SchdReuse.AI577" - }, - { - "index": 578, - "description": "Selected Schedule Validation Status", - "data_type": "AI", - "common_data_class": "ENSScheduleState", - "maximum": 4, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "SchdSt", - "event_class": 3, - "name": "FSCH1.SchdSt.AI578" - }, - { - "index": 579, - "description": "Selected Schedule Status", - "data_type": "AI", - "common_data_class": "ENSScheduleState", - "maximum": 4, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdSt", - "allowed_values": { - "0": "unknown", - "1": "Not available", - "2": "Inactive", - "3": "Ready-to-Run", - "4": "Running" - }, - "type": "enumerated", - "name": "FSCH1.SchdSt.AI579" - }, - { - "index": 580, - "description": "Selected Schedule Number of Points", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 0, - "data_object": "NumEntr", - "event_class": 3, - "name": "FSCH.NumEntr.AI580" - }, - { - "index": 581, - "description": "Select schedule time offset and value pairs for points 1 - 100", - "data_type": "AI", - "minimum": 0, - "name": "FSCHn.SchdEntr.AI581", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FSCHn.SchdEntr.AI581.time", - "units": "Seconds" - }, - { - "name": "FSCHn.SchdEntr.AI581.val", - "ln_class": "FSCH", - "data_object": "SchdEntr" - } - ] - }, - { - "index": 781, - "description": "Schedule 1 Status", - "data_type": "AI", - "common_data_class": "ENSScheduleState", - "maximum": 4, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdSt", - "allowed_values": { - "0": "unknown", - "1": "Not available", - "2": "Inactive", - "3": "Ready-to-Run", - "4": "Running" - }, - "type": "enumerated", - "name": "FSCH1.SchdSt.AI781" - }, - { - "index": 782, - "description": "Schedule 1 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 1, - "data_object": "SchdPrio", - "name": "FSCH.SchdPrio.AI782" - }, - { - "index": 783, - "description": "Schedule 1 Active Time Value. This is the index of the time value entry the schedule is currently running. First entry is 1. Zero if the schedule is not running.", - "data_type": "AI", - "common_data_class": "INS", - "maximum": 10, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "ActStrTm", - "name": "FSCH1.ActStrTm.AI783" - }, - { - "category": "alarm", - "index": 0, - "description": "System Communication Error", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "LCCH", - "data_object": "ChLiv", - "allowed_values": { - "0": "Normal", - "1": "Alarm: Communications error exists in the ESS" - }, - "event_class": 1, - "name": "LCCH.ChLiv.BI0" - }, - { - "category": "alarm", - "index": 1, - "description": "System Has Priority 1 Alarms", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "CALH", - "data_object": "GrAlm", - "allowed_values": { - "0": "No P1 Alarms Active", - "1": "Alarm: One or More P1 Alarms Active" - }, - "event_class": 1, - "name": "CALH.GrAlm.BI1" - }, - { - "category": "alarm", - "index": 2, - "description": "System Has Priority 2 Alarms", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "CALH", - "data_object": "GrWrn", - "allowed_values": { - "0": "No P2 Alarms Active", - "1": "Alarm: One or More P2 Alarms Active" - }, - "event_class": 1, - "name": "CALH.GrWrn.BI2" - }, - { - "category": "alarm", - "index": 3, - "description": "System Has Priority 3 Alarms", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "CALH", - "data_object": "GrInd", - "allowed_values": { - "0": "No P3 Alarms Active", - "1": "Alarm: One or More P3 Alarms Active" - }, - "event_class": 1, - "name": "CALH.GrInd.BI3" - }, - { - "category": "alarm", - "index": 4, - "description": "Storage State of Charge at Maximum. Maximum Usable State of Charge Reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SocHiWrn", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SocHiWrn.BI4" - }, - { - "category": "alarm", - "index": 5, - "description": "Storage State of Charge is Too High. Maximum Reserve Percentage (of usable capacity) reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SocHiAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SocHiAlm.BI5" - }, - { - "category": "alarm", - "index": 6, - "description": "Storage State of Charge is Too Low. Minimum Reserve Percentage (of usable capacity) reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SocLoAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SocLoAlm.BI6" - }, - { - "category": "alarm", - "index": 7, - "description": "Storage State of Charge is Depleted. Minimum Usable State of Charge Reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SohLoAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SohLoAlm.BI7" - }, - { - "category": "alarm", - "index": 8, - "description": "Storage Internal Temperature is Too High", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DBAT", - "data_object": "IntnTmpHiAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DBAT.IntnTmpHiAlm.BI8" - }, - { - "category": "alarm", - "index": 9, - "description": "Storage External (Ambient) Temperature is Too High", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DBAT", - "data_object": "ExtTmpHiAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DBAT.ExtTmpHiAlm.BI9" - }, - { - "index": 10, - "description": "System Is In Local State. System has been locked by a local operator which prevents other operators from executing commands. Note: Local State is also sometimes referred to as Maintenance State. Local State overrides Lockout State.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and in maintenance", - "allowed_values": { - "0": "System not in local state", - "1": "System in local state" - }, - "name": "DSTO.DEROpSt.disconnectedandinmaintenance.BI10" - }, - { - "index": 11, - "description": "System Is In Lockout State. System has been locked by an operator such that other operators may not execute commands. Lockout State is also sometimes referred to as Blocked State.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and blocked", - "allowed_values": { - "0": "System not locked out", - "1": "System locked out" - }, - "name": "DSTO.DEROpSt.disconnectedandblocked.BI11" - }, - { - "index": 12, - "description": "System Is Starting Up. Set to 1 when a BO \"System Initiate Start-up Sequence\" command has been received.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.starting and synchronizing", - "allowed_values": { - "0": "Not Starting Up", - "1": "Start command has been received." - }, - "name": "DSTO.DEROpSt.startingandsynchronizing.BI12" - }, - { - "index": 13, - "description": "System Is Stopping. Set to 1 when an B0 \"System Execute Stop\" command has been received.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.stopping", - "allowed_values": { - "0": "Not Stopping", - "1": "Emergency stop command has been received." - }, - "name": "DSTO.DEROpSt.stopping.BI13" - }, - { - "index": 14, - "description": "System is Started (Return to Service). If any of the DER Units are started,then true. DER Units in the maintenance operational state are excluded.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and idle", - "allowed_values": { - "0": "Null", - "1": "Started" - }, - "name": "DSTO.DEROpSt.connectedandidle.BI14" - }, - { - "index": 15, - "description": "System is Stopped (Cease to Energize). If all of the DER Units are stopped, then true. DER Units in the maintenance operational state are excluded.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.ceased to energize", - "allowed_values": { - "0": "Null", - "1": "Stopped" - }, - "name": "DSTO.DEROpSt.ceasedtoenergize.BI15" - }, - { - "index": 16, - "description": "System Permission to Start Status", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmConn", - "allowed_values": { - "0": "Start Permission Not Granted", - "1": "Start Permission Granted" - }, - "name": "DSTO.PrmConn.BI16" - }, - { - "index": 17, - "description": "System Permission to Stop Status", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmDscon", - "allowed_values": { - "0": "Stop Permission Not Granted", - "1": "Stop Permission Granted" - }, - "name": "DSTO.PrmDscon.BI17" - }, - { - "index": 18, - "description": "DER is Connected and Idle", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and idle", - "allowed_values": { - "0": "Null", - "1": "Idle-Connected" - }, - "name": "DSTO.DEROpSt.connectedandidle.BI18" - }, - { - "index": 19, - "description": "DER is Connected and Generating", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and generating", - "allowed_values": { - "0": "Null", - "1": "On-Connected" - }, - "name": "DSTO.DEROpSt.connectedandgenerating.BI19" - }, - { - "index": 20, - "description": "DER is Connected and Charging", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and consuming", - "allowed_values": { - "0": "Null", - "1": "On-Charging-Connected" - }, - "name": "DSTO.DEROpSt.connectedandconsuming.BI20" - }, - { - "index": 21, - "description": "DER is Off but Available to Start", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and available", - "allowed_values": { - "0": "Null", - "1": "Off-Available" - }, - "name": "DSTO.DEROpSt.disconnectedandavailable.BI21" - }, - { - "index": 22, - "description": "DER is Off and Not Available to Start", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and stand-by", - "allowed_values": { - "0": "Null", - "1": "Off-Not-Available" - }, - "name": "DSTO.DEROpSt.disconnectedandstand-by.BI22" - }, - { - "index": 23, - "description": "DER Connect/Disconnect Switch Closed Status", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.off", - "allowed_values": { - "0": "Open", - "1": "Closed" - }, - "name": "DSTO.DEROpSt.off.BI23" - }, - { - "index": 24, - "description": "DER Connect/Disconnect Switch Movement Status", - "data_type": "BI", - "common_data_class": "DPC", - "ln_class": "CSWI", - "data_object": "Pos", - "allowed_values": { - "0": "Not Moving", - "1": "Moving" - }, - "name": "CSWI.Pos.BI24" - }, - { - "index": 25, - "description": "Islanded Mode. Determines how the DER behaves when in an Islanded configuration.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "IsldCtlFol", - "allowed_values": { - "0": "Isochronous Mode. DER attempts to control voltage and frequency independent of configured curves and settings up to the limits of the machine's capabilities in order to achieve the AO Reference Voltage and AO nominal frequency.", - "1": "Droop Mode. DER acts as a follower using Volt/VAR and Freq/Watt curves." - }, - "event_class": 3, - "name": "DSTO.IsldCtlFol.BI25" - }, - { - "index": 26, - "description": "Sensed Grid Config Detection Enabled. If Enabled, the DER may independently change its Active Settings Group based on locally observed grid conditions.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DECP", - "data_object": "ECPIsldAuto", - "allowed_values": { - "0": "No Autonomous Detection.", - "1": "Autonomous Detection. Inverter's Active Settings Group may differ from the Requested Settings Group" - }, - "event_class": 3, - "name": "DECP.ECPIsldAuto.BI26" - }, - { - "index": 27, - "description": "Storage Capacity Units. Determines whether energy storage values are expressed in units of Amp-hrs or Watt-hrs.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "AGra", - "allowed_values": { - "0": "Amp-hrs (default)", - "1": "Watt-hrs" - }, - "event_class": 3, - "name": "DSTO.AGra.BI27" - }, - { - "index": 28, - "description": "Time Constant Mode. Indicates whether Time Constant Ramp parameters are interpreted as Open Loop Response times or 3Tau values.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "OpnLoopTau", - "allowed_values": { - "0": "Open Loop Response Time", - "1": "3Tau Value" - }, - "event_class": 3, - "name": "DSTO.OpnLoopTau.BI28" - }, - { - "index": 29, - "description": "Power Factor Excitation When Discharging/Generating", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFGnExtSet", - "allowed_values": { - "0": "Injecting VARs - Q1", - "1": "Absorbing VARs - Q4" - }, - "name": "DFPF.PFGnExtSet.BI29" - }, - { - "index": 30, - "description": "Power Factor Excitation When Charging", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFLodExtSet", - "allowed_values": { - "0": "Injecting VARs - Q2", - "1": "Absorbing VARs - Q3" - }, - "name": "DFPF.PFLodExtSet.BI30" - }, - { - "index": 31, - "description": "Supports Low/High Voltage Ride-Through Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DHVT", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DHVT.BI31" - }, - { - "index": 32, - "description": "Supports Low/High Frequency Ride-Through Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DHFT", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DHFT.BI32" - }, - { - "index": 33, - "description": "Supports Dynamic Reactive Current Support Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DRGS", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DRGS.BI33" - }, - { - "index": 34, - "description": "Supports Dynamic Volt-Watt Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVWD", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVWD.BI34" - }, - { - "index": 35, - "description": "Supports Frequency-Watt Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DHFW", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DHFW.BI35" - }, - { - "index": 36, - "description": "Supports Active Power Limit Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWLM", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWLM.BI36" - }, - { - "index": 37, - "description": "Supports Charge/Discharge Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWGC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWGC.BI37" - }, - { - "index": 38, - "description": "Supports Coordinated Charge/Discharge Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DTCD", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DTCD.BI38" - }, - { - "index": 39, - "description": "Supports Active Power Response Mode #1", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DLFL", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DLFL.BI39" - }, - { - "index": 40, - "description": "Supports Active Power Response Mode #2", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DGFL", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DGFL.BI40" - }, - { - "index": 41, - "description": "Supports Active Power Response Mode #3", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DGFL", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DGFL.BI41" - }, - { - "index": 42, - "description": "Supports Automatic Generation Control Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DAGC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DAGC.BI42" - }, - { - "index": 43, - "description": "Supports Active Power Smoothing Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWSM", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWSM.BI43" - }, - { - "index": 44, - "description": "Supports Volt-Watt Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVWC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVWC.BI44" - }, - { - "index": 45, - "description": "Supports Frequency-Watt Curve Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DFWC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DFWC.BI45" - }, - { - "index": 46, - "description": "Supports Constant VArs Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVAR", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVAR.BI46" - }, - { - "index": 47, - "description": "Supports Fixed Power Factor Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DFPF", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DFPF.BI47" - }, - { - "index": 48, - "description": "Supports Volt-VAr Control Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVVC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVVC.BI48" - }, - { - "index": 49, - "description": "Supports Watt-VAr Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWVR", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWVR.BI49" - }, - { - "index": 50, - "description": "Supports Power Factor Correction Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DPFC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DPFC.BI50" - }, - { - "index": 51, - "description": "Supports Pricing Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DPRG", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DPRG.BI51" - }, - { - "index": 52, - "description": "Overvoltage Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTOV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTOV.Blk.BI52" - }, - { - "index": 53, - "description": "Overvoltage Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTOV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTOV.Str.general.BI53" - }, - { - "index": 54, - "description": "Overvoltage Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTOV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTOV.Op.general.BI54" - }, - { - "index": 55, - "description": "Undervoltage Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTUV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTUV.Blk.BI55" - }, - { - "index": 56, - "description": "Undervoltage Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTUV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTUV.Str.general.BI56" - }, - { - "index": 57, - "description": "Undervoltage Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTUV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTUV.Op.general.BI57" - }, - { - "index": 58, - "description": "Over Frequency Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTOV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTOV.Blk.BI58" - }, - { - "index": 59, - "description": "Over Frequency Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTOV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTOV.Str.general.BI59" - }, - { - "index": 60, - "description": "Over Frequency Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTOV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTOV.Op.general.BI60" - }, - { - "index": 61, - "description": "Under Frequency Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTUV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTUV.Blk.BI61" - }, - { - "index": 62, - "description": "Under Frequency Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTUV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTUV.Str.general.BI62" - }, - { - "index": 63, - "description": "Under Frequency Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTUV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTUV.Op.general.BI63" - }, - { - "category": "mode_enable", - "index": 64, - "description": "Operating Mode - Low/High Voltage Ride-Through", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHVT", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHVT.ModEna.BI64" - }, - { - "category": "mode_enable", - "index": 65, - "description": "Operating Mode - Low/High Frequency Ride-Through", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHFT", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFT.ModEna.BI65" - }, - { - "category": "mode_enable", - "index": 66, - "description": "Operating Mode - Dynamic Reactive Current Support Enabled", - "data_type": "BI", - "common_data_class": "ENC", - "ln_class": "DRGS", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DRGS.ModEna.BI66" - }, - { - "category": "mode_enable", - "index": 67, - "description": "Operating Mode - Dynamic Volt-Watt Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVWD", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVWD.ModEna.BI67" - }, - { - "category": "mode_enable", - "index": 68, - "description": "Operating Mode - Frequency-Watt Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFW.ModEna.BI68" - }, - { - "category": "mode_enable", - "index": 69, - "description": "Operating Mode - Active Power Limit Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWLM", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWLM.ModEna.BI69" - }, - { - "category": "mode_enable", - "index": 70, - "description": "Operating Mode - Charge/Discharge Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWGC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWGC.ModEna.BI70" - }, - { - "category": "mode_enable", - "index": 71, - "description": "Operating Mode - Coordinated Charge/Discharge Management Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DTCD", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DTCD.ModEna.BI71" - }, - { - "category": "mode_enable", - "index": 72, - "description": "Operating Mode - Active Power Response Mode #1 Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DPKP", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DPKP.ModEna.BI72" - }, - { - "category": "mode_enable", - "index": 73, - "description": "Operating Mode - Active Power Response Mode #2 Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DGFL", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DGFL.ModEna.BI73" - }, - { - "category": "mode_enable", - "index": 74, - "description": "Operating Mode - Active Power Response Mode #3 Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DLFL", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DLFL.ModEna.BI74" - }, - { - "category": "mode_enable", - "index": 75, - "description": "Operating Mode - Automatic Generation Control Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DAGC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DAGC.ModEna.BI75" - }, - { - "category": "mode_enable", - "index": 76, - "description": "Operating Mode - Active Power Smoothing Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWSM", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWSM.ModEna.BI76" - }, - { - "category": "mode_enable", - "index": 77, - "description": "Operating Mode - Volt-Watt Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVWC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVWC.ModEna.BI77" - }, - { - "category": "mode_enable", - "index": 78, - "description": "Operating Mode - Frequency-Watt Curve Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFW.ModEna.BI78" - }, - { - "category": "mode_enable", - "index": 79, - "description": "Operating Mode - Constant VArs Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVAR", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVAR.ModEna.BI79" - }, - { - "category": "mode_enable", - "index": 80, - "description": "Operating Mode - Fixed Power Factor Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DFPF", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DFPF.ModEna.BI80" - }, - { - "category": "mode_enable", - "index": 81, - "description": "Operating Mode - Volt-VAR Control Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVVR", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVVR.ModEna.BI81" - }, - { - "category": "mode_enable", - "index": 82, - "description": "Operating Mode - Watt-VAr Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWVR", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWVR.ModEna.BI82" - }, - { - "category": "mode_enable", - "index": 83, - "description": "Operating Mode - Power Factor Correction Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DPFC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DPFC.ModEna.BI83" - }, - { - "category": "mode_enable", - "index": 84, - "description": "Operating Mode - Pricing Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DPRG", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DPRG.ModEna.BI84" - }, - { - "category": "mode_enable", - "index": 85, - "description": "Operating Mode - Event-Based Reactive Current Support Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DRGS", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DRGS.ModEna.BI85" - }, - { - "index": 86, - "description": "Frequency-Watt Mode - Use Hysteresis", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFW.HysEna.BI86" - }, - { - "index": 87, - "description": "Frequency-Watt Mode - Snapshot of Power", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DHFW.SnptEna.BI87" - }, - { - "index": 88, - "description": "Frequency-Watt Curve Mode - Use Hysteresis", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DLFW.HysEna.BI88" - }, - { - "index": 89, - "description": "Frequency-Watt Curve Mode - Snapshot of Power", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DLFW.SnptEna.BI89" - }, - { - "index": 90, - "description": "Charge/Discharge Mode - Use Ramp Rates. Indicates whether or not Charge/Discharge should use specified ramp rates or ramp times.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DWGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constants", - "1": "Use Ramp Rates" - }, - "name": "DWGC.UseRmpRte.BI90" - }, - { - "index": 91, - "description": "AGC Mode - Use Ramp Rates. Indicates whether or not charge/discharge should use specified ramp rates or ramp times.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DAGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constants", - "1": "Use Ramp Rates" - }, - "name": "DAGC.UseRmpRte.BI91" - }, - { - "index": 92, - "description": "Volt-Watt - Use Ramp Rates and Time Constants", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DVWC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constants", - "1": "Use Ramp Rates AND Time Constants" - }, - "name": "DVWC.UseRmpRte.BI92" - }, - { - "index": 93, - "description": "Volt-VAr Enable Autonomous Voltage Reference Adjustment", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DVVR", - "data_object": "VRefAdjEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVVR.VRefAdjEna.BI93" - }, - { - "category": "alarm", - "index": 94, - "description": "System Meter Active Power is Too High", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotW.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotW.range.BI94" - }, - { - "category": "alarm", - "index": 95, - "description": "System Meter Active Power is Too Low", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotW.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotW.range.BI95" - }, - { - "category": "alarm", - "index": 96, - "description": "System Meter Reactive Power is Too High", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotVAr.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotVAr.range.BI96" - }, - { - "category": "alarm", - "index": 97, - "description": "System Meter Reactive Power is Too Low", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotVAr.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotVAr.range.BI97" - }, - { - "category": "alarm", - "index": 98, - "description": "System Meter Power Factor is Too High", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotPF.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotPF.range.BI98" - }, - { - "category": "alarm", - "index": 99, - "description": "System Meter Power Factor is Too Low", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotPF.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotPF.range.BI99" - }, - { - "category": "alarm", - "index": 100, - "description": "System Meter Phase A Voltage is Too High", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsA.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsA.range.BI100" - }, - { - "category": "alarm", - "index": 101, - "description": "System Meter Phase A Voltage is Too Low", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsA.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsA.range.BI101" - }, - { - "category": "alarm", - "index": 102, - "description": "System Meter Phase B Voltage is Too High", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsB.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsB.range.BI102" - }, - { - "category": "alarm", - "index": 103, - "description": "System Meter Phase B Voltage is Too Low", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsB.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsB.range.BI103" - }, - { - "category": "alarm", - "index": 104, - "description": "System Meter Phase C Voltage is Too High", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsC.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsC.range.BI104" - }, - { - "category": "alarm", - "index": 105, - "description": "System Meter Phase C Voltage is Too Low", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsC.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsC.range.BI105" - }, - { - "category": "alarm", - "index": 106, - "description": "System Meter Communication Error", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "LCCH", - "data_object": "ChLiv", - "allowed_values": { - "0": "Normal: No Active Communications Error", - "1": "Alarm: Active Communications Error" - }, - "event_class": 1, - "name": "LCCH.ChLiv.BI106" - }, - { - "index": 107, - "description": "Selected Curve is Referenced by a Mode", - "data_type": "BI", - "allowed_values": { - "0": "Curve is not Referenced", - "1": "Curve is Referenced" - }, - "event_class": 1, - "name": "BI107" - }, - { - "index": 108, - "description": "Selected Schedule Is Ready", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "FSCH", - "data_object": "SchdSt.3", - "allowed_values": { - "0": "Not Ready", - "1": "Ready" - }, - "name": "FSCH.SchdSt.3.BI108" - }, - { - "index": 109, - "description": "Selected Schedule is Validated", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "FSCH", - "data_object": "SchdSt.2", - "allowed_values": { - "0": "Not validated", - "1": "Validated" - }, - "name": "FSCH.SchdSt.2.BI109" - }, - { - "index": 110, - "description": "Selected Schedule Repeat Weekly Sunday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI110" - }, - { - "index": 111, - "description": "Selected Schedule Repeat Weekly Monday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI111" - }, - { - "index": 112, - "description": "Selected Schedule Repeat Weekly Tuesday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI112" - }, - { - "index": 113, - "description": "Selected Schedule Repeat Weekly Wednesday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI113" - }, - { - "index": 114, - "description": "Selected Schedule Repeat Weekly Thursday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI114" - }, - { - "index": 115, - "description": "Selected Schedule Repeat Weekly Friday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI115" - }, - { - "index": 116, - "description": "Selected Schedule Repeat Weekly Saturday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI116" - }, - { - "index": 0, - "description": "System Set Lockout State", - "data_type": "BO", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and blocked", - "allowed_values": { - "0": "Not Locked Out", - "1": "Lock Out" - }, - "name": "DSTO.DEROpSt.disconnectedandblocked.BO0" - }, - { - "index": 1, - "description": "System Initiate Start-up Sequence (Return to Service). Setting this to 1 does the following: - Sets BI \"System Is Starting Up\" to 1 indicating that the system is starting up. Additional start-up status can be found in AI \"System Start-up Status\". - Instructs all batteries to connect. - Once each battery has reported that it has connect successfully, instructs corresponding DER Unit to start. System can be shut down by executing B0 \"Emergency Stop\" command. This operation is the same as California Rule 21 \"Soft Start\".", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DCTE", - "data_object": "RtnSrvReq", - "allowed_values": { - "0": "No Change", - "1": "Initiate Start-up" - }, - "name": "DCTE.RtnSrvReq.BO1" - }, - { - "index": 2, - "description": "System Execute Stop (Cease to Energize). Setting this to 1 does the following: - Sets BI \"System Is Emergency Stopping\" to 1 indicating that an emergency stop is in progress. - Ensures that any executing operating modes are shut down (disabled). - Ensures that any executing schedules are shut down (disabled). - Instructs all inverters to shut down. - Instructs all batteries to disconnect. System can be started again by executing BO \"Initiate Start-up Sequence\" command.", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DCTE", - "data_object": "CeaEngzReq", - "allowed_values": { - "0": "No Change", - "1": "Stop (Emergency)" - }, - "name": "DCTE.CeaEngzReq.BO2" - }, - { - "index": 3, - "description": "System Permission to Start", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmConn", - "allowed_values": { - "0": "DCTE", - "1": "Start Permission Granted" - }, - "name": "DSTO.PrmConn.BO3" - }, - { - "index": 4, - "description": "System Permission to Stop", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmDscon", - "allowed_values": { - "0": "DCTE", - "1": "Stop Permission Granted" - }, - "name": "DSTO.PrmDscon.BO4" - }, - { - "index": 5, - "description": "DER Connect/Disconnect Switch", - "data_type": "BO", - "common_data_class": "DPC", - "ln_class": "CSWI", - "data_object": "Pos", - "allowed_values": { - "0": "Open Switch", - "1": "Close Switch" - }, - "name": "CSWI.Pos.BO5" - }, - { - "index": 6, - "description": "Islanded Mode. Determines how the DER behaves when in an Islanded configuration.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DGEN", - "data_object": "IsldCtlFol", - "allowed_values": { - "0": "Isochronous Mode. DER attempts to control voltage and frequency independent of configured curves and settings up to the limits of the machine's capabilities in order to achieve AO reference voltage and AO nominal frequency.", - "1": "Droop Mode. DER acts as a follower using Volt/VAR and Freq/Watt curves." - }, - "name": "DGEN.IsldCtlFol.BO6" - }, - { - "index": 7, - "description": "Enable Sensed Grid Config Detection. If Enabled, the DER may independently change its Active Settings Group based on locally observed grid conditions.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DECP", - "data_object": "ECPIsldAuto", - "allowed_values": { - "0": "No Autonomous Detection.", - "1": "Autonomous Detection. Inverter's Active Settings Group may differ from the Requested Settings Group" - }, - "name": "DECP.ECPIsldAuto.BO7" - }, - { - "index": 8, - "description": "Storage Capacity Units. Determines whether the energy storage values are expressed in Amp-hrs or Watt-hrs.", - "data_type": "BO", - "common_data_class": "ASG", - "ln_class": "DSTO", - "data_object": "AGra", - "allowed_values": { - "0": "Amp-hrs (default)", - "1": "Watt-hrs" - }, - "name": "DSTO.AGra.BO8" - }, - { - "index": 9, - "description": "Time Constant Mode. Indicates whether Time Constant Ramp parameters are interpreted as Open Loop Response times or 3Tau values.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "OpnLoopTau", - "allowed_values": { - "0": "Open Loop Response Time", - "1": "3Tau Value" - }, - "name": "DSTO.OpnLoopTau.BO9" - }, - { - "index": 10, - "description": "Power Factor Excitation When Discharging/Generating", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFGnExtSet", - "allowed_values": { - "0": "Producing VARs - Q1", - "1": "Absorbing VARs - Q4" - }, - "name": "DFPF.PFGnExtSet.BO10" - }, - { - "index": 11, - "description": "Power Factor Excitation When Charging", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFLodExtSet", - "allowed_values": { - "0": "Producing VARs - Q2", - "1": "Absorbing VARs - Q3" - }, - "name": "DFPF.PFLodExtSet.BO11" - }, - { - "category": "mode_enable", - "index": 12, - "description": "Enable Low/High Voltage Ride-Through Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHVT", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHVT.ModEna.BI64", - "name": "DHVT.ModEna.BO12" - }, - { - "category": "mode_enable", - "index": 13, - "description": "Enable Low/High Frequency Ride-Through Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHFT", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHFT.ModEna.BI65", - "name": "DHFT.ModEna.BO13" - }, - { - "category": "mode_enable", - "index": 14, - "description": "Enable Dynamic Reactive Current Support Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DRGS", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DRGS.ModEna.BI66", - "name": "DRGS.ModEna.BO14" - }, - { - "category": "mode_enable", - "index": 15, - "description": "Enable Dynamic Volt-Watt Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVWD", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVWD.ModEna.BI67", - "name": "DVWD.ModEna.BO15" - }, - { - "category": "mode_enable", - "index": 16, - "description": "Enable Frequency-Watt Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHFW.ModEna.BI68", - "name": "DHFW.ModEna.BO16" - }, - { - "category": "mode_enable", - "index": 17, - "description": "Enable Active Power Limit Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWLM", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DWLM.ModEna.BI69", - "name": "DWLM.ModEna.BO17" - }, - { - "category": "mode_enable", - "index": 18, - "description": "Enable Charge/Discharge Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWGC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DTCD.ModEna.BI71", - "name": "DWGC.ModEna.BO18" - }, - { - "category": "mode_enable", - "index": 19, - "description": "Enable Coordinated Charge/Discharge Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DTCD", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DTCD.ModEna.BO19" - }, - { - "category": "mode_enable", - "index": 20, - "description": "Enable Active Power Response Mode #1", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DPKP", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DPKP.ModEna.BI72", - "name": "DPKP.ModEna.BO20" - }, - { - "category": "mode_enable", - "index": 21, - "description": "Enable Active Power Response Mode #2", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DGFL", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DGFL.ModEna.BI73", - "name": "DGFL.ModEna.BO21" - }, - { - "category": "mode_enable", - "index": 22, - "description": "Enable Active Power Response Mode #3", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DLFL", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DLFL.ModEna.BI74", - "name": "DLFL.ModEna.BO22" - }, - { - "category": "mode_enable", - "index": 23, - "description": "Enable Automatic Generation Control Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DAGC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DAGC.ModEna.BI75", - "name": "DAGC.ModEna.BO23" - }, - { - "category": "mode_enable", - "index": 24, - "description": "Enable Active Power Smoothing Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWSM", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DWSM.ModEna.BI76", - "name": "DWSM.ModEna.BO24" - }, - { - "category": "mode_enable", - "index": 25, - "description": "Enable Volt-Watt Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVWC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVWC.ModEna.BI77", - "name": "DVWC.ModEna.BO25" - }, - { - "category": "mode_enable", - "index": 26, - "description": "Enable Frequency-Watt Curve Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHFW.ModEna.BI78", - "name": "DHFW.ModEna.BO26" - }, - { - "category": "mode_enable", - "index": 27, - "description": "Enable Constant VArs Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVAR", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVAR.ModEna.BI79", - "name": "DVAR.ModEna.BO27" - }, - { - "category": "mode_enable", - "index": 28, - "description": "Enable Fixed Power Factor Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DFPF", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DFPF.BI47", - "name": "DFPF.ModEna.BO28" - }, - { - "category": "mode_enable", - "index": 29, - "description": "Enable Volt-VAR Control Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVVC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVVC.BI48", - "name": "DVVC.ModEna.BO29" - }, - { - "category": "mode_enable", - "index": 30, - "description": "Enable Watt-VAr Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWVR", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DWVR.BI49", - "name": "DWVR.ModEna.BO30" - }, - { - "category": "mode_enable", - "index": 31, - "description": "Enable Power Factor Correction Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DPFC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DPFC.ModEna.BI83", - "name": "DPFC.ModEna.BO31" - }, - { - "category": "mode_enable", - "index": 32, - "description": "Enable Pricing Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DPRG", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DPRG.ModEna.BI84", - "name": "DPRG.ModEna.BO32" - }, - { - "index": 33, - "description": "Enable Event-Based Reactive Current Support Mode, in which the moving average voltage and the base reactive current are frozen until after the voltage has returned to within the deadband for a specified hold time. Dynamic Reactive Current Support mode must be Enable for this setting to apply.", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DRGS", - "data_object": "ArGraMod", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DRGS.ArGraMod.BO33" - }, - { - "index": 34, - "description": "Frequency-Watt Mode - Use Hysteresis", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DHFW.HysEna.BO34" - }, - { - "index": 35, - "description": "Frequency-Watt Mode - Snapshot of Power", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DHFW.SnptEna.BO35" - }, - { - "index": 36, - "description": "Frequency-Watt Curve Mode - Use Hysteresis", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DLFW.HysEna.BO36" - }, - { - "index": 37, - "description": "Frequency-Watt Curve Mode - Snapshot of Power", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DLFW.SnptEna.BO37" - }, - { - "index": 38, - "description": "Charge/Discharge Mode - Use Ramp Rates. Indicates whether or not Charge/Discharge should use specified ramp rates or time constants.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DWGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constatnts", - "1": "Use Ramp Rates" - }, - "name": "DWGC.UseRmpRte.BO38" - }, - { - "index": 39, - "description": "AGC Mode - Use Ramp Rates. Indicates whether or not AGC mode should use specified ramp rates or time constants.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DAGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constatnts", - "1": "Use Ramp Rates" - }, - "name": "DAGC.UseRmpRte.BO39" - }, - { - "index": 40, - "description": "Volt-Watt - Use Ramp Rates and Time Constants. Indicates whether Volt-Watt mode should use only Time Constants,or both Time Constants and Ramp Rates", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DVWC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constatnts", - "1": "Use Ramp Rates AND Time Constants" - }, - "name": "DVWC.UseRmpRte.BO40" - }, - { - "index": 41, - "description": "Volt-VAr Enable Autonomous Voltage Reference Adjustment", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DVVR", - "data_object": "VRefAdjEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DVVR.VRefAdjEna.BO41" - }, - { - "index": 42, - "description": "Set Selected Scheduled Ready", - "data_type": "BO", - "common_data_class": "ENC", - "ln_class": "FSCH", - "data_object": "Mod", - "allowed_values": { - "0": "Not Ready", - "1": "Ready" - }, - "name": "FSCHxx.Mod.BO42" - }, - { - "index": 43, - "description": "Set Selected Schedule Repeat Weekly Sunday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO43" - }, - { - "index": 44, - "description": "Set Selected Schedule Repeat Weekly Monday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO44" - }, - { - "index": 45, - "description": "Set Selected Schedule Repeat Weekly Tuesday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO45" - }, - { - "index": 46, - "description": "Set Selected Schedule Repeat Weekly Wednesday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO46" - }, - { - "index": 47, - "description": "Set Selected Schedule Repeat Weekly Thursday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO47" - }, - { - "index": 48, - "description": "Set Selected Schedule Repeat Weekly Friday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO48" - }, - { - "index": 49, - "description": "Set Selected Schedule Repeat Weekly Saturday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO49" - } -] \ No newline at end of file diff --git a/services/core/DNP3Agent/dnp3/outstation.py b/services/core/DNP3Agent/dnp3/outstation.py deleted file mode 100644 index 142eec388d..0000000000 --- a/services/core/DNP3Agent/dnp3/outstation.py +++ /dev/null @@ -1,420 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, SLAC / 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# This material was prepared in part as an account of work sponsored by an agency of -# the United States Government. Neither the United States Government nor the -# United States Department of Energy, nor SLAC, nor 8minutenergy, nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by the United States Government or any agency thereof, or -# SLAC, 8minutenergy, or Kisensum. The views and opinions of authors expressed -# herein do not necessarily state or reflect those of the -# United States Government or any agency thereof. -# }}} - -import os -import logging - -from pydnp3 import opendnp3, openpal, asiopal, asiodnp3 - -# from volttron.platform.agent import utils - -# utils.setup_logging() -_log = logging.getLogger(__name__) - - -class DNP3Outstation(opendnp3.IOutstationApplication): - """ - Model the Application Layer of a DNP3 outstation. - - This class models the interface for all outstation callback info except for control requests. - - DNP3 spec section 5.1.6.2: - The Application Layer provides the following services for the DNP3 User Layer in an outstation: - - Notifies the DNP3 User Layer when action requests, such as control output, - analog output, freeze and file operations, arrive from a master. - - Requests data and information from the outstation that is wanted by a master - and formats the responses returned to a master. - - Assures that event data is successfully conveyed to a master (using - Application Layer confirmation). - - Sends notifications to the master when the outstation restarts, has queued events, - and requires time synchronization. - - DNP spec section 5.1.6.3: - The Application Layer requires specific services from the layers beneath it. - - Partitioning of fragments into smaller portions for transport reliability. - - Knowledge of which device(s) were the source of received messages. - - Transmission of messages to specific devices or to all devices. - - Message integrity (i.e., error-free reception and transmission of messages). - - Knowledge of the time when messages arrive. - - Either precise times of transmission or the ability to set time values - into outgoing messages. - """ - - outstation = None - outstation_config = {} - agent = None - - def __init__(self, local_ip, port, outstation_config): - """ - Initialize the outstation's Application Layer. - - @param local_ip: Host name (DNS resolved) or IP address of remote endpoint. Default: 0.0.0.0. - @param port: Port remote endpoint is listening on. Default: 20000. - @param outstation_config: A dictionary of configuration parameters. All are optional. Parameters include: - database_sizes: (integer) Size of the Outstation's point database, by point type. Default: 10000. - event_buffers: (integer) Size of the database event buffers. Default: 10. - allow_unsolicited: (boolean) Whether to allow unsolicited requests. Default: True. - link_local_addr: (integer) Link layer local address. Default: 10. - link_remote_addr: (integer) Link layer remote address. Default: 1. - log_levels: List of bit field names (OR'd together) that filter what gets logged by DNP3. Default: [NORMAL]. - Possible values: ALL, ALL_APP_COMMS, ALL_COMMS, NORMAL, NOTHING - threads_to_allocate: (integer) Threads to allocate in the manager's thread pool. Default: 1. - """ - super(DNP3Outstation, self).__init__() - self.local_ip = local_ip - self.port = port - self.set_outstation_config(outstation_config) - # The following variables are initialized after start() is called. - self.stack_config = None - self.log_handler = None - self.manager = None - self.retry_parameters = None - self.listener = None - self.channel = None - self.command_handler = None - - def start(self): - _log.debug('Configuring the DNP3 stack.') - self.stack_config = asiodnp3.OutstationStackConfig(opendnp3.DatabaseSizes.AllTypes(self.outstation_config.get('database_sizes', 10000))) - self.stack_config.outstation.eventBufferConfig = opendnp3.EventBufferConfig.AllTypes(self.outstation_config.get('event_buffers', 10)) - self.stack_config.outstation.params.allowUnsolicited = self.outstation_config.get('allow_unsolicited', True) - self.stack_config.link.LocalAddr = self.outstation_config.get('link_local_addr', 10) - self.stack_config.link.RemoteAddr = self.outstation_config.get('link_remote_addr', 1) - self.stack_config.link.KeepAliveTimeout = openpal.TimeDuration().Max() - - # Configure the outstation database of points based on the contents of the data dictionary. - _log.debug('Configuring the DNP3 Outstation database.') - db_config = self.stack_config.dbConfig - for point in self.get_agent().point_definitions.all_points(): - if point.data_type == 'Analog Input': - cfg = db_config.analog[int(point.index)] - elif point.data_type == 'Binary Input': - cfg = db_config.binary[int(point.index)] - else: - # This database's point configuration is limited to Binary and Analog data types. - cfg = None - if cfg: - # cfg.vIndex = virtual index of the point - cfg.clazz = point.eclass - # cfg.svariation and cfg.evariation are static const: cannot modify - - _log.debug('Creating a DNP3Manager.') - threads_to_allocate = self.outstation_config.get('threads_to_allocate', 1) - # self.log_handler = asiodnp3.ConsoleLogger().Create() # (or use this during regression testing) - # self.log_handler = MyLogger().Create() - self.log_handler = MyLogger() - self.manager = asiodnp3.DNP3Manager(threads_to_allocate, self.log_handler) - - _log.debug('Creating the DNP3 channel, a TCP server.') - self.retry_parameters = asiopal.ChannelRetry().Default() - # self.listener = asiodnp3.PrintingChannelListener().Create() # (or use this during regression testing) - self.listener = AppChannelListener() - self.channel = self.manager.AddTCPServer("server", - self.dnp3_log_level(), - self.retry_parameters, - self.local_ip, - self.port, - self.listener) - - _log.debug('Adding the DNP3 Outstation to the channel.') - # self.command_handler = opendnp3.SuccessCommandHandler().Create() # (or use this during regression testing) - self.command_handler = OutstationCommandHandler() - self.outstation = self.channel.AddOutstation("outstation", self.command_handler, self, self.stack_config) - - # Set the singleton instance that communicates with the Master. - self.set_outstation(self.outstation) - - _log.info('Enabling the DNP3 Outstation. Traffic can now start to flow.') - self.outstation.Enable() - - def reload_parameters(self, local_ip, port, outstation_config): - _log.debug('In reload_parameters') - self.local_ip = local_ip - self.port = port - self.outstation_config = outstation_config - - @classmethod - def get_agent(cls): - """Return the singleton DNP3Agent or MesaAgent instance.""" - agt = cls.agent - if agt is None: - raise ValueError('Outstation has no configured agent') - return agt - - @classmethod - def set_agent(cls, agent): - """Set the singleton DNP3Agent or MesaAgent instance.""" - cls.agent = agent - - @classmethod - def get_outstation(cls): - """Get the singleton instance of IOutstation.""" - outst = cls.outstation - if outst is None: - raise AttributeError('IOutstation is not yet enabled') - return outst - - @classmethod - def set_outstation(cls, outstn): - """ - Set the singleton instance of IOutstation, as returned from the channel's AddOutstation call. - - Making IOutstation available as a singleton allows other classes - to send commands to it -- see apply_update(). - """ - cls.outstation = outstn - - @classmethod - def get_outstation_config(cls): - """Get the outstation_config, a dictionary of configuration parameters.""" - return cls.outstation_config - - @classmethod - def set_outstation_config(cls, outstn_cfg): - """ - Set the outstation_config. - - It's managed as a class variable so that it can be examined by the class method apply_update(). - - :param outstn_cfg: A dictionary of configuration parameters. - """ - cls.outstation_config = outstn_cfg - - def dnp3_log_level(self): - """ - Return a bit-encoded integer that indicates the level of DNP3 logging. - - If a list of level names is specified in the Outstation config, - use a union of those names to construct the integer. Otherwise return the default log level. - """ - log_level_list = self.outstation_config.get('log_levels', ['NORMAL']) - # log_level_list should be a list of strings. If it's not (e.g., if it's a simple string), fail. - if not isinstance(log_level_list, list): - raise TypeError('log_levels should be configured as a list of strings, not as {}'.format(log_level_list)) - log_level_list = [s.upper() for s in log_level_list] - - name_to_bitmasks = { - 'ALL': opendnp3.levels.ALL, - 'ALL_APP_COMMS': opendnp3.levels.ALL_APP_COMMS, - 'ALL_COMMS': opendnp3.levels.ALL_COMMS, - 'NORMAL': opendnp3.levels.NORMAL, - 'NOTHING': opendnp3.levels.NOTHING - } - log_level = 0 - for name in log_level_list: - log_level = log_level | name_to_bitmasks.get(name, 0) - - _log.debug('Setting DNP3 log level={} ({})'.format(log_level, log_level_list)) - return log_level - - # Overridden method - def ColdRestartSupport(self): - """Return a RestartMode enumerated type value indicating whether cold restart is supported.""" - _log.debug('In DNP3 ColdRestartSupport') - return opendnp3.RestartMode.UNSUPPORTED - - # Overridden method - def GetApplicationIIN(self): - """Return the application-controlled IIN field.""" - application_iin = opendnp3.ApplicationIIN() - application_iin.configCorrupt = False - application_iin.deviceTrouble = False - application_iin.localControl = False - application_iin.needTime = False - iin_field = application_iin.ToIIN() - # Experiment with setting iin_field to an error value, e.g. configCorrupt to indicate that - # a point couldn't be found in the Outstation's database. - # Other interesting IIN values might be PARAM_ERROR, ALREADY_EXECUTING, FUNC_NOT_SUPPORTED. - if iin_field.LSB != 0 or iin_field.MSB != 0: - status_string = 'IINField LSB={}, MSB={}'.format(iin_field.LSB, iin_field.MSB) - DNP3Outstation.get_agent().publish_outstation_status(status_string) - return application_iin - - # Overridden method - def SupportsAssignClass(self): - _log.debug('In DNP3 SupportsAssignClass') - return False - - # Overridden method - def SupportsWriteAbsoluteTime(self): - _log.debug('In DNP3 SupportsWriteAbsoluteTime') - return False - - # Overridden method - def SupportsWriteTimeAndInterval(self): - _log.debug('In DNP3 SupportsWriteTimeAndInterval') - return False - - # Overridden method - def WarmRestartSupport(self): - """Return a RestartMode enumerated value indicating whether a warm restart is supported.""" - _log.debug('In DNP3 WarmRestartSupport') - return opendnp3.RestartMode.UNSUPPORTED - - @classmethod - def apply_update(cls, value, index): - """ - Record an opendnp3 data value (Analog, Binary, etc.) in the outstation's database. - - The data value gets sent to the Master as a side-effect. - - :param value: An instance of Analog, Binary, or another opendnp3 data value. - :param index: (integer) Index of the data definition in the opendnp3 database. - """ - _log.debug('Recording DNP3 {} measurement, index={}, value={}'.format(type(value).__name__, index, value.value)) - max_index = cls.get_outstation_config().get('database_sizes', 10000) - if index > max_index: - raise ValueError('Attempt to set a value for index {} which exceeds database size {}'.format(index, - max_index)) - builder = asiodnp3.UpdateBuilder() - builder.Update(value, index) - update = builder.Build() - try: - cls.get_outstation().Apply(update) - except AttributeError as err: - if not os.environ.get('UNITTEST', False): - raise err - - def shutdown(self): - """ - Execute an orderly shutdown of the Outstation. - - The debug messages may be helpful if errors occur during shutdown. - """ - _log.debug('Exiting DNP3 Outstation module...') - self.manager.Shutdown() - _log.debug('Garbage collecting DNP3 Outstation...') - self.set_outstation(None) - _log.debug('Garbage collecting DNP3 stack config...') - self.stack_config = None - _log.debug('Garbage collecting DNP3 channel...') - self.channel = None - _log.debug('Garbage collecting DNP3Manager...') - self.manager = None - - -class OutstationCommandHandler(opendnp3.ICommandHandler): - """ - ICommandHandler implements the Outstation's handling of Select and Operate, - which relay commands and data from the Master to the Outstation. - """ - - def Start(self): - # This debug line is too chatty... - # _log.debug('In DNP3 OutstationCommandHandler.Start') - pass - - def End(self): - # This debug line is too chatty... - # _log.debug('In DNP3 OutstationCommandHandler.End') - pass - - def Select(self, command, index): - """ - The Master sent a Select command to the Outstation. Handle it. - - :param command: ControlRelayOutputBlock, - AnalogOutputInt16, AnalogOutputInt32, AnalogOutputFloat32, or AnalogOutputDouble64. - :param index: int - :return: CommandStatus - """ - return DNP3Outstation.get_agent().process_point_value('Select', command, index, None) - - def Operate(self, command, index, op_type): - """ - The Master sent an Operate command to the Outstation. Handle it. - - :param command: ControlRelayOutputBlock, - AnalogOutputInt16, AnalogOutputInt32, AnalogOutputFloat32, or AnalogOutputDouble64. - :param index: int - :param op_type: OperateType - :return: CommandStatus - """ - return DNP3Outstation.get_agent().process_point_value('Operate', command, index, op_type) - - -class AppChannelListener(asiodnp3.IChannelListener): - """ - IChannelListener has been overridden to implement application-specific channel behavior. - """ - - def __init__(self): - super(AppChannelListener, self).__init__() - - def OnStateChange(self, state): - """ - There has been an outstation state change. Publish the new state to the message bus. - - :param state: A ChannelState. - """ - DNP3Outstation.get_agent().publish_outstation_status(str(state)) - - -# class MyLogger(asiodnp3.ConsoleLogger): -class MyLogger(openpal.ILogHandler): - """ - ILogHandler has been overridden to implement application-specific logging behavior. - """ - - def __init__(self): - super(MyLogger, self).__init__() - self.tcp_client = None - - def Log(self, entry): - """Write a DNP3 log entry to the logger (debug level).""" - location = entry.location.rsplit('/')[-1] if entry.location else '' - filters = entry.filters.GetBitfield() - message = entry.message - - if "Accepted connection from" in message: - self.tcp_client = message.split(": ")[1] - - _log.debug('DNP3Log {0}\t(filters={1}) {2}'.format(location, filters, message)) - # This is here as an example of how to send a specific log entry to the message bus as outstation status. - # if 'Accepted connection' in message or 'Listening on' in message: - # DNP3Outstation.get_agent().publish_outstation_status(str(message)) - - -def main(): - """The Outstation has been started from the command line. Execute ad-hoc tests if desired.""" - dnp3_outstation = DNP3Outstation('0.0.0.0', 20000, {}) - dnp3_outstation.start() - _log.debug('DNP3 initialization complete. In command loop.') - # Ad-hoc tests can be performed at this point if desired. - dnp3_outstation.shutdown() - _log.debug('DNP3 Outstation exiting.') - exit() - -if __name__ == '__main__': - main() diff --git a/services/core/DNP3Agent/dnp3/points.py b/services/core/DNP3Agent/dnp3/points.py deleted file mode 100644 index 99c9313832..0000000000 --- a/services/core/DNP3Agent/dnp3/points.py +++ /dev/null @@ -1,614 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, SLAC / 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# This material was prepared in part as an account of work sponsored by an agency of -# the United States Government. Neither the United States Government nor the -# United States Department of Energy, nor SLAC, nor 8minutenergy, nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by the United States Government or any agency thereof, or -# SLAC, 8minutenergy, or Kisensum. The views and opinions of authors expressed -# herein do not necessarily state or reflect those of the -# United States Government or any agency thereof. -# }}} - -from datetime import datetime -import logging -import os -import pytz -import re - -from volttron.platform import jsonapi -from pydnp3 import opendnp3 -from dnp3 import POINT_TYPES, POINT_TYPE_SELECTOR_BLOCK, POINT_TYPE_ENUMERATED, POINT_TYPE_ARRAY -from dnp3 import DATA_TYPE_ANALOG_INPUT, DATA_TYPE_ANALOG_OUTPUT, DATA_TYPE_BINARY_INPUT, DATA_TYPE_BINARY_OUTPUT -from dnp3 import EVENT_CLASSES, DATA_TYPES_BY_GROUP -from dnp3 import DEFAULT_GROUP_BY_DATA_TYPE, DEFAULT_EVENT_CLASS -from dnp3 import PUBLISH_AND_RESPOND - -_log = logging.getLogger(__name__) - - -class DNP3Exception(Exception): - """Raise exceptions that are specific to the DNP3 agent. No special exception behavior is needed at this time.""" - pass - - -class PointDefinitions: - """In-memory repository of PointDefinitions.""" - - def __init__(self, point_definitions_path=None): - self._points = {} # {data_type: {point_index: PointDefinition}} - self._point_name_dict = {} # {point_name: [PointDefinition]} - if point_definitions_path: - file_path = os.path.expandvars(os.path.expanduser(point_definitions_path)) - self.load_points_from_json_file(file_path) - - def __getitem__(self, name): - """Return the PointDefinition associated with this name. Must be unique.""" - if name in [None, 'n/a']: - return None - return self.get_point_named(name) - - def load_points_from_json_file(self, point_definitions_path): - """Load and cache a dictionary of PointDefinitions, indexed by point_type and point index.""" - if point_definitions_path: - try: - file_path = os.path.expandvars(os.path.expanduser(point_definitions_path)) - _log.debug('Loading DNP3 point definitions from {}.'.format(file_path)) - with open(file_path, 'r') as f: - # Filter comments out of the file's contents before loading it as jsonapi. - self.load_points(jsonapi.loads(self.strip_comments(f.read()))) - except Exception as err: - raise ValueError('Problem parsing {}. Error={}'.format(point_definitions_path, err)) - else: - _log.debug('No point_definitions_path specified, loading no points') - - def strip_comments(self, raw_string): - """ - Return a string with comments stripped. - - Both JavaScript-style comments (//... and /*...*/) and hash (#...) comments are removed. - Thanks to VOLTTRON volttron/platform/agent/utils.py/strip_comments() for this logic. - """ - def _repl(match): - return match.group(1) or '' - - _comment_re = re.compile(r'((["\'])(?:\\?.)*?\2)|(/\*.*?\*/)|((?:#|//).*?(?=\n|$))', re.MULTILINE | re.DOTALL) - return _comment_re.sub(_repl, raw_string) - - def load_points(self, point_definitions_json): - """Load and cache a dictionary of PointDefinitions, indexed by point_type and point index.""" - try: - self._points = {} # If they're already loaded, force a reload. - for element in point_definitions_json: - # Load a PointDefinition (or subclass) from JSON, and add it to the dictionary of points. - # If the point defines an array, load additional definitions for each interior point in the array. - try: - if element.get('type', None) != POINT_TYPE_ARRAY: - point_def = PointDefinition(element) - self.update_point(point_def) - else: - point_def = ArrayHeadPointDefinition(element) - self.update_point(point_def) - # Load a separate ArrayPointDefinition for each interior point in the array. - for pt in point_def.create_array_point_definitions(element): - self.update_point(pt) - except ValueError as err: - raise DNP3Exception('Validation error for point with json: {}: {}'.format(element, err)) - except Exception as err: - raise ValueError('Problem parsing PointDefinitions. Error={}'.format(err)) - _log.debug('Loaded {} PointDefinitions'.format(len(self.all_points()))) - - def update_point(self, point_def): - """Add a PointDefinition to self._points and self._point_name_dict.""" - data_type, name, index = point_def.data_type, point_def.name, point_def.index - data_type_dict = self._points.setdefault(data_type, {}) - name_lst = self._point_name_dict.setdefault(name, []) - if index in data_type_dict: - raise ValueError('Duplicate index {} for data type {}'.format(index, data_type)) - if name_lst and point_def.type != 'array': - raise ValueError('Duplicated point name {}'.format(name)) - data_type_dict[index] = point_def - name_lst.append(point_def) - - def for_group_and_index(self, group, index): - """Return a PointDefinition for given group and index""" - data_type = DATA_TYPES_BY_GROUP.get(group, None) - if not data_type: - _log.error('No DNP3 point type found for group {}'.format(group)) - return self._points.get(data_type, {}).get(index, None) - - def point_value_for_command(self, command_type, command, index, op_type): - """ - A DNP3 Select or Operate was received from the master. Create and return a PointValue for its data. - - :param command_type: Either 'Select' or 'Operate'. - :param command: A ControlRelayOutputBlock or else a wrapped data value (AnalogOutputInt16, etc.). - :param index: DNP3 index of the payload's data definition. - :param op_type: An OperateType, or None if command_type == 'Select'. - :return: An instance of PointValue - """ - function_code = command.functionCode if type(command) == opendnp3.ControlRelayOutputBlock else None - data_type = DATA_TYPE_BINARY_OUTPUT if function_code else DATA_TYPE_ANALOG_OUTPUT - point_def = self.for_data_type_and_index(data_type, index) - if not point_def: - raise DNP3Exception('No DNP3 PointDefinition found for point type {} and index {}'.format(data_type, index)) - point_value = PointValue(command_type, - function_code, - command.value if not function_code else None, - point_def, - index, - op_type) - _log.debug('Received DNP3 {}'.format(point_value)) - return point_value - - def for_data_type_and_index(self, data_type, index): - """ - Return a PointDefinition for given data type and index. - - @param data_type: A data type (string). - @param index: Unique integer index of the PointDefinition to be looked up. - """ - return self._points.get(data_type, {}).get(index, None) - - def point_named(self, name, index=None): - """ - Return the PointDefinition with the indicated name and (optionally) index, or None if no match. - - :param name: (string) The point's name. - :param index: (integer) An optional index value. If supplied, search for an array point at this DNP3 index. - """ - point_def_list = self._point_name_dict.get(name, None) - if point_def_list is None: - return None # No points with that name - - if index is not None: - # Return the PointDefinition with a matching index. - for pt in point_def_list: - if pt.index == index: - return pt - return None - - # In multi-element lists, give preference to the ArrayHeadPointDefinition. - for pt in point_def_list: - if pt.is_array_head_point: - return pt - return point_def_list[0] - - def get_point_named(self, name, index=None): - """ - Return the PointDefinition with the indicated name and (optionally) index. - Raise an exception if none found. - - :param name: (string) The point's name. - :param index: (integer) An optional index value. If supplied, search for an array point at this DNP3 index. - :return A PointDefinition. - """ - point_def = self.point_named(name, index=index) - if point_def is None: - if index is not None: - raise DNP3Exception('No point named {} with index {}'.format(name, index)) - else: - raise DNP3Exception('No point named {}'.format(name)) - return point_def - - def all_points(self): - """Return a flat list of all PointDefinitions.""" - point_list = [] - for inner_dict in self._points.values(): - point_list.extend(inner_dict.values()) - return point_list - - -class BasePointDefinition: - """Abstract superclass for PointDefinition data holders.""" - - def __init__(self, element_def): - """Initialize an instance of the PointDefinition from a dictionary of point attributes.""" - self.name = str(element_def.get('name', '')) - self.data_type = element_def.get('data_type', None) - self.index = element_def.get('index', None) - self.type = element_def.get('type', None) - self.description = element_def.get('description', '') - self.scaling_multiplier = element_def.get('scaling_multiplier', 1) # Only used for Analog data_type - self.units = element_def.get('units', '') - self.event_class = element_def.get('event_class', DEFAULT_EVENT_CLASS) - self.selector_block_start = element_def.get('selector_block_start', None) - self.selector_block_end = element_def.get('selector_block_end', None) - self.action = element_def.get('action', None) - self.response = element_def.get('response', None) - self.category = element_def.get('category', None) - self.ln_class = element_def.get('ln_class', None) - self.data_object = element_def.get('data_object', None) - self.common_data_class = element_def.get('common_data_class', None) - self.minimum = element_def.get('minimum', -2147483648) # Only used for Analog data_type - self.maximum = element_def.get('maximum', 2147483647) # Only used for Analog data_type - self.scaling_offset = element_def.get('scaling_offset', 0) # Only used for Analog data_type - self.allowed_values = self.convert_allowed_values(element_def.get('allowed_values', None)) - - @property - def is_enumerated(self): - return self.type == POINT_TYPE_ENUMERATED - - @property - def is_array_point(self): - return False - - @property - def is_array_head_point(self): - return False - - @property - def is_array(self): - return self.is_array_point or self.is_array_head_point - - def convert_allowed_values(self, allowed_values): - if allowed_values: - return {int(str_val): description for str_val, description in allowed_values.items()} - return None - - def validate_point(self): - """A PointDefinition has been created. Perform a variety of validations on it.""" - if not self.name: - raise ValueError('Missing point name') - if self.index is None: - raise ValueError('Missing index for point {}'.format(self.name)) - if not self.data_type: - raise ValueError('Missing data type for point {}'.format(self.name)) - if self.data_type not in DEFAULT_GROUP_BY_DATA_TYPE: - raise ValueError('Invalid data type {} for point {}'.format(self.data_type, self.name)) - if not self.eclass: - raise ValueError('Invalid event class {} for point {}'.format(self.event_class, self.name)) - if self.type and self.type not in POINT_TYPES: - raise ValueError('Invalid type {} for point {}'.format(self.type, self.name)) - if self.action == PUBLISH_AND_RESPOND and not self.response: - raise ValueError('Missing response point name for point {}'.format(self.name)) - if self.is_enumerated and not self.allowed_values: - raise ValueError('Missing allowed values mapping for point {}'.format(self.name)) - if self.is_selector_block: - if self.selector_block_start is None: - raise ValueError('Missing selector_block_start for block named {}'.format(self.name)) - if self.selector_block_end is None: - raise ValueError('Missing selector_block_end for block named {}'.format(self.name)) - if self.selector_block_start > self.selector_block_end: - raise ValueError('Selector block end index < start index for block named {}'.format(self.name)) - elif self.selector_block_start is not None: - raise ValueError('selector_block_start defined for non-selector-block point {}'.format(self.name)) - elif self.selector_block_end is not None: - raise ValueError('selector_block_end defined for non-selector-block point {}'.format(self.name)) - - def as_json(self): - """Return a json description of the PointDefinition.""" - point_json = { - "name": self.name, - "data_type": self.data_type, - "index": self.index, - "group": self.group, - "event_class": self.event_class - } - if self.type: - point_json["type"] = self.type - if self.description: - point_json["description"] = self.description - if self.units: - point_json["units"] = self.units - if self.selector_block_start is not None: - point_json["selector_block_start"] = self.selector_block_start - if self.selector_block_end is not None: - point_json["selector_block_end"] = self.selector_block_end - if self.allowed_values: - point_json["allowed_values"] = self.allowed_values - if self.action: - point_json["action"] = self.action - if self.response: - point_json["response"] = self.response - if self.category: - point_json["category"] = self.category - if self.ln_class: - point_json["ln_class"] = self.ln_class - if self.data_object: - point_json["data_object"] = self.data_object - if self.common_data_class: - point_json["common_data_class"] = self.common_data_class - if self.data_type in [DATA_TYPE_ANALOG_INPUT, DATA_TYPE_ANALOG_OUTPUT]: - point_json.update({ - "scaling_multiplier": self.scaling_multiplier, - "scaling_offset": self.scaling_offset, - "minimum": self.minimum, - "maximum": self.maximum - }) - - return point_json - - def __str__(self): - """Return a string description of the PointDefinition.""" - try: - return '{0} {1} (event_class={2}, index={3}, type={4})'.format( - self.__class__.__name__, - self.name, - self.event_class, - self.index, - self.data_type - ) - except UnicodeEncodeError as err: - _log.error('Unable to convert point definition to string, err = {}'.format(err)) - return '' - - @property - def group(self): - return DEFAULT_GROUP_BY_DATA_TYPE.get(self.data_type, None) - - @property - def is_input(self): - """Return True if the PointDefinition is a Binary or Analog input point (i.e., sent by the Outstation).""" - return self.data_type in [DATA_TYPE_ANALOG_INPUT, DATA_TYPE_BINARY_INPUT] - - @property - def is_output(self): - """Return True if the PointDefinition is a Binary or Analog output point (i.e., sent by the Master).""" - return self.data_type in [DATA_TYPE_ANALOG_OUTPUT, DATA_TYPE_BINARY_OUTPUT] - - @property - def is_selector_block(self): - return self.type == POINT_TYPE_SELECTOR_BLOCK - - @property - def eclass(self): - """Return the PointDefinition's event class, or the default (2) if no event class was defined for the point.""" - return EVENT_CLASSES.get(self.event_class, None) - - -class PointDefinition(BasePointDefinition): - """Data holder for an OpenDNP3 data element.""" - - def __init__(self, element_def): - """Initialize an instance of the PointDefinition from a dictionary of point attributes.""" - super(PointDefinition, self).__init__(element_def) - self.validate_point() - - def validate_point(self): - """A PointDefinition has been created. Perform a variety of validations on it.""" - super(PointDefinition, self).validate_point() - if self.type and self.type not in ['selector_block', 'enumerated']: - raise ValueError('Invalid type for {}: {}'.format(self.name, self.type)) - - -class ArrayHeadPointDefinition(BasePointDefinition): - """Data holder for an OpenDNP3 data element that is the head point in an array.""" - - def __init__(self, json_element): - """ - Initialize an ArrayPointDefinition instance. - An ArrayPointDefinition defines an interior point (not the head point) in an array. - - :param json_element: A JSON dictionary of point attributes. - """ - super(ArrayHeadPointDefinition, self).__init__(json_element) - self.array_points = json_element.get('array_points', None) - self.array_times_repeated = json_element.get('array_times_repeated', None) - self.array_point_definitions = [] # Holds all ArrayPointDefinitions belonging to this array. - self.validate_point() - - def validate_point(self): - """An ArrayHeadPointDefinition has been created. Perform a variety of validations on it.""" - super(ArrayHeadPointDefinition, self).validate_point() - if self.type != 'array': - raise ValueError('Invalid type {} for array named {}'.format(self.type, self.name)) - if self.array_points is None: - raise ValueError('Missing array_points for array named {}'.format(self.name)) - if self.array_times_repeated is None: - raise ValueError('Missing array_times_repeated for array named {}'.format(self.name)) - - @property - def is_array_point(self): - return True - - @property - def is_array_head_point(self): - return True - - def as_json(self): - """Return a json description of the ArrayHeadPointDefinition.""" - point_json = super(ArrayHeadPointDefinition, self).as_json() - # array_points has been excluded because it's not a simple data type. Is it needed in the json? - # if self.array_points is not None: - # point_json["array_points"] = self.array_points - if self.array_times_repeated is not None: - point_json["array_times_repeated"] = self.array_times_repeated - return point_json - - @property - def array_last_index(self): - """Calculate and return the array's last index value.""" - if self.is_array_head_point: - return self.index + self.array_times_repeated * len(self.array_points) - 1 - else: - return None - - def create_array_point_definitions(self, element): - """Create a separate ArrayPointDefinition for each interior point in the array.""" - for row_number in range(self.array_times_repeated): - for column_number, pt in enumerate(self.array_points): - # The ArrayHeadPointDefinition is already defined -- don't create a redundant definition. - if row_number > 0 or column_number > 0: - array_pt_def = ArrayPointDefinition(element, self, row_number, column_number, pt['name']) - self.array_point_definitions.append(array_pt_def) - return self.array_point_definitions - - -class ArrayPointDefinition(BasePointDefinition): - """Data holder for an OpenDNP3 data element that is interior to an array.""" - - def __init__(self, json_element, base_point_def, row, column, array_element_name): - """ - Initialize an ArrayPointDefinition instance. - An ArrayPointDefinition defines an interior point (not the head point) in an array. - - :param json_element: A JSON dictionary of point attributes. - :param base_point_def: The PointDefinition of the head point in the array. - :param row: The point's row number in the array. - :param column: The point's column number in the array. - :param array_element_name: The point's column name in the array. - """ - super(ArrayPointDefinition, self).__init__(json_element) - self.base_point_def = base_point_def - self.row = row - self.column = column - self.index = self.base_point_def.index + row * len(self.base_point_def.array_points) + column - self.array_element_name = array_element_name - self.validate_point() - - def validate_point(self): - """An ArrayPointDefinition has been created. Perform a variety of validations on it.""" - super(ArrayPointDefinition, self).validate_point() - if self.type != 'array': - raise ValueError('Invalid type {} for array named {}'.format(self.type, self.name)) - if self.base_point_def is None: - raise ValueError('Missing base point definition for array point named {}'.format(self.name)) - if self.row is None: - raise ValueError('Missing row number for array point named {}'.format(self.name)) - if self.column is None: - raise ValueError('Missing column number for array point named {}'.format(self.name)) - if self.index is None: - raise ValueError('Missing index value for array point named {}'.format(self.name)) - if self.array_element_name is None: - raise ValueError('Missing array element name for array point named {}'.format(self.name)) - - @property - def is_array_point(self): - return True - - @property - def is_array_head_point(self): - return False - - def as_json(self): - """Return a json description of the ArrayPointDefinition.""" - point_json = super(ArrayPointDefinition, self).as_json() - if self.row is not None: - point_json["row"] = self.row - if self.row is not None: - point_json["column"] = self.column - if self.row is not None: - point_json["array_element_name"] = self.array_element_name - return point_json - - -class PointValue: - """Data holder for a point value (DNP3 measurement or command) received by an outstation.""" - - def __init__(self, command_type, function_code, value, point_def, index, op_type): - """Initialize an instance of the PointValue.""" - # Don't rely on VOLTTRON utils in this code, which may run outside of VOLTTRON - # self.when_received = utils.get_aware_utc_now() - self.when_received = pytz.UTC.localize(datetime.utcnow()) - self.command_type = command_type - self.function_code = function_code - self.value = value - self.point_def = point_def - self.index = index # MESA Array point indexes can differ from the indexes of their PointDefinitions. - self.op_type = op_type - - def __str__(self): - """Return a string description of the PointValue.""" - str_desc = 'Point value {0} ({1}, {2}.{3}, {4})' - return str_desc.format(self.value or self.function_code, - self.name, - self.point_def.event_class, - self.index, - self.command_type) - - @property - def name(self): - """Return the name of the PointDefinition.""" - return self.point_def.name - - def unwrapped_value(self): - """Unwrap the point's value, returning the sample data type (e.g. an integer, binary, etc. instance).""" - if self.value is None: - # For binary commands, send True if function_code is LATCH_ON, False otherwise - return self.function_code == opendnp3.ControlCode.LATCH_ON - else: - return self.value - - -class PointArray: - """Data holder for a MESA-ESS Array.""" - - def __init__(self, point_def): - """ - The "points" variable is a dictionary of dictionaries: - 0: { - 0: PointValue, - 1: PointValue - }, - 1: { - 0: PointValue, - 1: PointValue - } - (etc.) - It's stored as dictionaries indexed by index numbers, not as lists, - because there's no guarantee that array elements will arrive in order. - - :param point_def: The PointDefinition of the array's head point. - """ - _log.debug('New Array {} starting at {} with bounds ({}, {})'.format(point_def.name, - point_def.index, - point_def.index, - point_def.array_last_index)) - self.point_def = point_def - self.points = {} - - def __str__(self): - return 'Array, points = {}'.format(self.points) - - def as_json(self): - """ - Return a JSON representation of the PointArray: - - [ - {name1: val1a, name2: val2a, ...}, - {name1: val1b, name2: val2b, ...}, - ... - ] - """ - names = [d['name'] for d in self.point_def.array_points] - json_array = [] - for pt_dict_key in sorted(self.points): - pt_dict = self.points[pt_dict_key] - json_array.append({name: (pt_dict[i].value if i in pt_dict else None) for i, name in enumerate(names)}) - return json_array - - def contains_index(self, index): - """Answer whether this Array contains the point index.""" - return self.point_def.index <= index <= self.point_def.array_last_index - - def add_point_value(self, point_value): - """Add point_value to the Array's "points" dictionary.""" - point_def = point_value.point_def - row = 0 if point_def.is_array_head_point else point_def.row - col = 0 if point_def.is_array_head_point else point_def.column - if row not in self.points: - self.points[row] = {} - self.points[row][col] = point_value diff --git a/services/core/DNP3Agent/dnp3_master.py b/services/core/DNP3Agent/dnp3_master.py deleted file mode 100644 index 166026959f..0000000000 --- a/services/core/DNP3Agent/dnp3_master.py +++ /dev/null @@ -1,517 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - -import logging - -from pydnp3 import opendnp3, openpal, asiopal, asiodnp3 - -_log = logging.getLogger(__name__) - - -class DNP3Master: - """ - Interface for all master application callback info except for measurement values. - """ - - def __init__(self, - log_levels=opendnp3.levels.NORMAL | opendnp3.levels.ALL_APP_COMMS, - host_ip="127.0.0.1", # presumably outstation - local_ip="0.0.0.0", - port=20000, - log_handler=asiodnp3.ConsoleLogger().Create(), - channel_listener=asiodnp3.PrintingChannelListener().Create(), - soe_handler=asiodnp3.PrintingSOEHandler().Create(), - platform_application=asiodnp3.DefaultMasterApplication().Create(), - stack_config=None): - - self.log_levels = log_levels - self.host_ip = host_ip - self.local_ip = local_ip - self.port = port - self.log_handler = log_handler - self.channel_listener = channel_listener - self.soe_handler = soe_handler - self.platform_application = platform_application - - self.stackConfig = stack_config - if not self.stackConfig: - # The master config object for a master. - self.stackConfig = asiodnp3.MasterStackConfig() - self.stackConfig.master.responseTimeout = openpal.TimeDuration().Seconds(2) - self.stackConfig.link.RemoteAddr = 10 - - self.manager = None - self.channel = None - self.master = None - - def connect(self): - """Connect to an outstation, add an master to the channel, and start the communications.""" - - # Root DNP3 object used to create channels and sessions - if not self.manager: - self.manager = asiodnp3.DNP3Manager(1, self.log_handler) - - # Connect via a TCPClient socket to a outstation - self.channel = self.manager.AddTCPClient("tcpclient", - self.log_levels, - asiopal.ChannelRetry(), - self.host_ip, - self.local_ip, - self.port, - self.channel_listener) - - # Create a new master on a previously declared port, with a name, log level, command acceptor, and config info. - # This returns a thread-safe interface used for sending commands. - self.master = self.channel.AddMaster("master", - self.soe_handler, - self.platform_application, - self.stackConfig) - - # Enable the master. This will start communications. - self.master.Enable() - - def reconnect(self, host_ip, port): - """Reconnect master to a different host and port and start the communications.""" - if self.master: - self.master.Disable() - - if self.channel: - self.channel.Shutdown() - - self.host_ip = host_ip - self.port = port - self.connect() - - def send_read_command(self, group, variation, index): - """ - Request to read a point data from outstation - - :param group: group of the point data - :param variation: variation of the point data - :param index: index of the point data - :param data_type: 'analog' or 'binary' - """ - self.master.PerformFunction('READ', - opendnp3.FunctionCode.READ, - [opendnp3.Header().Range16(group, variation, index, index + 1)]) - - def send_unsolicited_response_command(self, group, variation, index): - """ - Unsolicited response that was not prompted by an explicit request - - :param group: group of the point data - :param variation: variation of the point data - :param index: index of the point data - :param data_type: 'analog' or 'binary' - """ - self.master.PerformFunction('UNSOLICITED_RESPONSE', - opendnp3.FunctionCode.UNSOLICITED_RESPONSE, - [opendnp3.Header().Range16(group, variation, index, index + 1)]) - - def send_direct_operate_command(self, command, index, callback=asiodnp3.PrintingCommandCallback.Get(), - config=opendnp3.TaskConfig().Default()): - """ - Direct operate a single command - - :param command: command to operate - :param index: index of the command - :param callback: callback that will be invoked upon completion or failure - :param config: optional configuration that controls normal callbacks and allows the user to be specified for SA - """ - self.master.DirectOperate(command, index, callback, config) - - def send_direct_operate_command_set(self, command_set, callback=asiodnp3.PrintingCommandCallback.Get(), - config=opendnp3.TaskConfig().Default()): - """ - Direct operate a set of commands - - :param command_set: set of command headers - :param callback: callback that will be invoked upon completion or failure - :param config: optional configuration that controls normal callbacks and allows the user to be specified for SA - """ - self.master.DirectOperate(command_set, callback, config) - - def send_select_and_operate_command(self, command, index, callback=asiodnp3.PrintingCommandCallback.Get(), - config=opendnp3.TaskConfig().Default()): - """ - Select and operate a single command - - :param command: command to operate - :param index: index of the command - :param callback: callback that will be invoked upon completion or failure - :param config: optional configuration that controls normal callbacks and allows the user to be specified for SA - """ - self.master.SelectAndOperate(command, index, callback, config) - - def send_select_and_operate_command_set(self, command_set, callback=asiodnp3.PrintingCommandCallback.Get(), - config=opendnp3.TaskConfig().Default()): - """ - Select and operate a set of commands - - :param command_set: set of command headers - :param callback: callback that will be invoked upon completion or failure - :param config: optional configuration that controls normal callbacks and allows the user to be specified for SA - """ - self.master.SelectAndOperate(command_set, callback, config) - - def shutdown(self): - """ - Shutdown manager and terminate the threadpool - """ - del self.master - del self.channel - if self.manager: - self.manager.Shutdown() - - -class VisitorIndexedBinary(opendnp3.IVisitorIndexedBinary): - """ - Override IVisitorIndexedBinary in this manner to implement visiting elements of IndexedBinary collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedBinary, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedBinary - """ - self.index_and_value.append((indexed_instance.index, indexed_instance.value.value)) - - -class VisitorIndexedDoubleBitBinary(opendnp3.IVisitorIndexedDoubleBitBinary): - """ - Override IVisitorIndexedDoubleBitBinary in this manner to implement visiting elements of IndexedDoubleBitBinary - collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedDoubleBitBinary, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedDoubleBitBinary - """ - self.index_and_value.append((indexed_instance.index, indexed_instance.value.value)) - - -class VisitorIndexedCounter(opendnp3.IVisitorIndexedCounter): - """ - Override IVisitorIndexedCounter in this manner to implement visiting elements of IndexedCounter collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedCounter, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedCounter - """ - self.index_and_value.append((indexed_instance.index, indexed_instance.value.value)) - - -class VisitorIndexedFrozenCounter(opendnp3.IVisitorIndexedFrozenCounter): - """ - Override IVisitorIndexedFrozenCounter in this manner to implement visiting elements of IndexedFrozenCounter - collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedFrozenCounter, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedFrozenCounter - """ - self.index_and_value.append((indexed_instance.index, indexed_instance.value.value)) - - -class VisitorIndexedAnalog(opendnp3.IVisitorIndexedAnalog): - """ - Override IVisitorIndexedAnalog in this manner to implement visiting elements of IndexedAnalog collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedAnalog, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedAnalog - """ - self.index_and_value.append((indexed_instance.index, indexed_instance.value.value)) - - -class VisitorIndexedBinaryOutputStatus(opendnp3.IVisitorIndexedBinaryOutputStatus): - """ - Override IVisitorIndexedBinaryOutputStatus in this manner to implement visiting elements of - IndexedBinaryOutputStatus collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedBinaryOutputStatus, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedBinaryOutputStatus - """ - self.index_and_value.append((indexed_instance.index, indexed_instance.value.value)) - - -class VisitorIndexedAnalogOutputStatus(opendnp3.IVisitorIndexedAnalogOutputStatus): - """ - Override IVisitorIndexedAnalogOutputStatus in this manner to implement visiting elements of - IndexedAnalogOutputStatus collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedAnalogOutputStatus, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedAnalogOutputStatus - """ - self.index_and_value.append((indexed_instance.index, indexed_instance.value.value)) - - -class VisitorIndexedTimeAndInterval(opendnp3.IVisitorIndexedTimeAndInterval): - """ - Override IVisitorIndexedTimeAndInterval in this manner to implement visiting elements of - IndexedTimeAndInterval collection. - - This is used in SOEHandler callback. - """ - - def __init__(self): - super(VisitorIndexedTimeAndInterval, self).__init__() - self.index_and_value = [] - - def OnValue(self, indexed_instance): - """ - Process current value visiting. - - :param indexed_instance: current value visiting, an instance of IndexedTimeAndInterval - """ - # The TimeAndInterval class is a special case, because it doesn't have a "value" per se. - ti_instance = indexed_instance.value - ti_dnptime = ti_instance.time - ti_interval = ti_instance.interval - self.index_and_value.append((indexed_instance.index, (ti_dnptime.value, ti_interval))) - - -class LogHandler(openpal.ILogHandler): - """ - Override ILogHandler in this manner to implement application-specific logging behavior. - """ - - def __init__(self): - super(LogHandler, self).__init__() - - def Log(self, entry): - flag = opendnp3.LogFlagToString(entry.filters.GetBitfield()) - filters = entry.filters.GetBitfield() - location = entry.location.rsplit('/')[-1] if entry.location else '' - message = entry.message - _log.debug('LOG\t\t{:<10}\tfilters={:<5}\tlocation={:<25}\tentry={}'.format(flag, filters, location, message)) - - -class ChannelListener(asiodnp3.IChannelListener): - """ - Override IChannelListener in this manner to implement application-specific channel behavior. - """ - - def __init__(self): - super(ChannelListener, self).__init__() - - def OnStateChange(self, state): - _log.debug('In AppChannelListener.OnStateChange: state={}'.format(opendnp3.ChannelStateToString(state))) - - -class SOEHandler(opendnp3.ISOEHandler): - """ - Override ISOEHandler in this manner to implement application-specific sequence-of-events behavior. - - This is an interface for SequenceOfEvents (SOE) callbacks from the Master stack to the application layer. - """ - - def __init__(self): - super(SOEHandler, self).__init__() - self.result = { - "Binary": {}, - "DoubleBitBinary": {}, - "Counter": {}, - "FrozenCounter": {}, - "Analog": {}, - "BinaryOutputStatus": {}, - "AnalogOutputStatus": {}, - "TimeAndInterval": {} - } - - def Process(self, info, values): - """ - Process measurement data. - - :param info: HeaderInfo - :param values: A collection of values received from the Outstation (various data types are possible). - """ - visitor_class_types = { - opendnp3.ICollectionIndexedBinary: VisitorIndexedBinary, - opendnp3.ICollectionIndexedDoubleBitBinary: VisitorIndexedDoubleBitBinary, - opendnp3.ICollectionIndexedCounter: VisitorIndexedCounter, - opendnp3.ICollectionIndexedFrozenCounter: VisitorIndexedFrozenCounter, - opendnp3.ICollectionIndexedAnalog: VisitorIndexedAnalog, - opendnp3.ICollectionIndexedBinaryOutputStatus: VisitorIndexedBinaryOutputStatus, - opendnp3.ICollectionIndexedAnalogOutputStatus: VisitorIndexedAnalogOutputStatus, - opendnp3.ICollectionIndexedTimeAndInterval: VisitorIndexedTimeAndInterval - } - - visitor_class = visitor_class_types[type(values)] - visitor = visitor_class() - - # Visit all the elements of a collection - values.Foreach(visitor) - - for index, value in visitor.index_and_value: - self.result[type(values).__name__.split("ICollectionIndexed")[1]][index] = value - - def Start(self): - pass - - def End(self): - pass - - -class MasterApplication(opendnp3.IMasterApplication): - def __init__(self): - super(MasterApplication, self).__init__() - - # Overridden method - def AssignClassDuringStartup(self): - _log.debug('In MasterApplication.AssignClassDuringStartup') - return False - - # Overridden method - def OnClose(self): - _log.debug('In MasterApplication.OnClose') - - # Overridden method - def OnOpen(self): - _log.debug('In MasterApplication.OnOpen') - - # Overridden method - def OnReceiveIIN(self, iin): - _log.debug('In MasterApplication.OnReceiveIIN') - - # Overridden method - def OnTaskComplete(self, info): - _log.debug('In MasterApplication.OnTaskComplete') - - # Overridden method - def OnTaskStart(self, type, id): - _log.debug('In MasterApplication.OnTaskStart') - - -def collection_callback(result=None): - """ - :type result: opendnp3.CommandPointResult - """ - print("Header: {0} | Index: {1} | State: {2} | Status: {3}".format( - result.headerIndex, - result.index, - opendnp3.CommandPointStateToString(result.state), - opendnp3.CommandStatusToString(result.status) - )) - - -def command_callback(result=None): - """ - :type result: opendnp3.ICommandTaskResult - """ - print("Received command result with summary: {}".format(opendnp3.TaskCompletionToString(result.summary))) - result.ForeachItem(collection_callback) - - -def restart_callback(result=opendnp3.RestartOperationResult()): - if result: - if result.summary == opendnp3.TaskCompletion.SUCCESS: - status_message = "Success, Time: {0}".format(result.restartTime.GetMilliseconds()) - else: - status_message = "Failure: {0}".format(opendnp3.TaskCompletionToString(result.summary)) - else: - status_message = "Failure: No result returned" - - _log.debug(status_message) - - -def main(): - dnp3_master = DNP3Master(log_handler=LogHandler(), - channel_listener=ChannelListener(), - soe_handler=SOEHandler(), - platform_application=MasterApplication()) - dnp3_master.connect() - # Ad-hoc tests can be inserted here if desired. - dnp3_master.shutdown() - - -if __name__ == '__main__': - main() diff --git a/services/core/DNP3Agent/function_test.py b/services/core/DNP3Agent/function_test.py deleted file mode 100644 index 150c41a89f..0000000000 --- a/services/core/DNP3Agent/function_test.py +++ /dev/null @@ -1,150 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - - -import os - -from dnp3.mesa.functions import FunctionDefinitions -from dnp3.points import PointDefinitions -from dnp3 import DATA_TYPES_BY_GROUP -from dnp3 import DATA_TYPE_ANALOG_OUTPUT, DATA_TYPE_BINARY_OUTPUT - -from volttron.platform import jsonapi -POINT_DEF_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'tests', 'data', 'mesa_points.config')) -FUNCTION_DEF_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'tests', 'data', 'mesa_functions.yaml')) - -DATA_TYPE_TO_PYTHON_TYPE = { - DATA_TYPE_BINARY_OUTPUT: {bool}, - DATA_TYPE_ANALOG_OUTPUT: {int, float}, -} - - -class FunctionTestException(Exception): - pass - - -class FunctionTest: - - def __init__(self, func_test_path='', func_test_json=None, func_def_path='', point_def_path=''): - self.func_def_path = func_def_path or FUNCTION_DEF_PATH - self.point_definitions = PointDefinitions(point_definitions_path=point_def_path or POINT_DEF_PATH) - self.ftest = func_test_json or jsonapi.load(open(func_test_path)) - self.function_id = self.ftest.get('function_id', self.ftest.get('id', None)) - self.function_name = self.ftest.get('function_name', self.ftest.get('name', None)) - self.name = self.ftest.get('name', None) - self.points = {k: v for k, v in self.ftest.items() if k not in ["name", "function_id", "function_name", "id"]} - - def get_function_def(self): - """ - Gets the function definition for the function test. Returns None if no definition is found. - """ - fdefs = FunctionDefinitions(point_definitions=self.point_definitions, - function_definitions_path=self.func_def_path) - return fdefs.function_for_id(self.function_id) - - @staticmethod - def get_mandatory_steps(func_def): - """ - Returns list of mandatory steps for the given function definition. - - :param func_def: function definition - """ - return [step.name for step in func_def.steps if step.optional in ['M', 'I']] - - def has_mandatory_steps(self, fdef=None): - """ - Returns True if the instance has all required steps, and raises an exception if not. - - :param fdef: function definition - """ - fdef = fdef or self.get_function_def() - if not fdef: - raise FunctionTestException("Function definition not found: {}".format(self.function_id)) - - missing_steps = list(set(self.get_mandatory_steps(fdef)) - set(self.ftest.keys())) - if missing_steps: - raise FunctionTestException("Function Test missing mandatory steps: {}".format(missing_steps)) - - return True - - def points_resolve(self, func_def): - """ - Returns true if all the points in the instance resolve to point names in the function definition, - and raises an exception if not. - - :param func_def: function definition of the given instance - """ - # It would have been more informative to identify the mismatched step/point name, - # but that would break a pytest assertion that matches on this specific exception description. - if not all(step_name in [step.point_def.name for step in func_def.steps if step.point_def] for step_name in - self.points.keys()): - raise FunctionTestException("Not all points resolve") - return True - - def correct_point_types(self): - """ - Check valid point value. - """ - for point_name, point_value in self.points.items(): - point_def = self.point_definitions.point_named(point_name) - point_values = sum([list(v.values()) for v in point_value], []) if point_def.is_array else [point_value] - for value in point_values: - if type(value) not in DATA_TYPE_TO_PYTHON_TYPE[DATA_TYPES_BY_GROUP[point_def.group]]: - # It would have been more informative to display the value and/or type in the error message, - # but that would break a pytest assertion that matches on this specific exception description. - raise FunctionTestException("Invalid point value: {}".format(point_name)) - return True - - def is_valid(self): - """ - Returns True if the function test passes two validation steps: - 1. it has all the mandatory steps - 2. its point names resolve to point names in the function definition - 3. its point value is valid - If the function test is invalid, an exception is raised. - """ - f_def = self.get_function_def() - - try: - self.has_mandatory_steps(f_def) - self.points_resolve(f_def) - self.correct_point_types() - return True - except Exception as err: - raise FunctionTestException("Validation Error: {}".format(str(err))) - - -def main(): - function_test = FunctionTest(func_test_path=os.path.abspath(os.path.join(os.path.dirname(__file__), - 'tests', 'data', 'watt_var_curve.json'))) - function_test.is_valid() - - -if __name__ == '__main__': - main() \ No newline at end of file diff --git a/services/core/DNP3Agent/install_dnp3_agent.sh b/services/core/DNP3Agent/install_dnp3_agent.sh deleted file mode 100644 index 420ae1dd4d..0000000000 --- a/services/core/DNP3Agent/install_dnp3_agent.sh +++ /dev/null @@ -1,19 +0,0 @@ -# This script assumes that $VOLTTRON_ROOT is the directory where VOLTTRON source code is loaded from github. - -export DNP3_ROOT=$VOLTTRON_ROOT/services/core/DNP3Agent - -# Install the agent that resides in the dnp3 subdirectory -export AGENT_MODULE=dnp3.agent - -cd $VOLTTRON_ROOT - -python scripts/install-agent.py -s $DNP3_ROOT -i dnp3agent -c $DNP3_ROOT/config -t dnp3agent -f - -# Put the agent's point definitions in the config store. -cd $VOLTTRON_ROOT -vctl config store dnp3agent mesa_points.config $DNP3_ROOT/dnp3/mesa_points.config - -echo -echo Stored point configurations in config store... -vctl config list dnp3agent -echo diff --git a/services/core/DNP3Agent/install_mesa_agent.sh b/services/core/DNP3Agent/install_mesa_agent.sh deleted file mode 100644 index b84ed53189..0000000000 --- a/services/core/DNP3Agent/install_mesa_agent.sh +++ /dev/null @@ -1,25 +0,0 @@ -#/bin/sh -# This script assumes that $VOLTTRON_ROOT is the directory where VOLTTRON source code is loaded from github. - -export DNP3_ROOT=$VOLTTRON_ROOT/services/core/DNP3Agent - -# Install the agent that resides in the dnp3.mesa subdirectory -export AGENT_MODULE=dnp3.mesa.agent - -cd $VOLTTRON_ROOT - -python scripts/install-agent.py -s $DNP3_ROOT -i mesaagent -c $DNP3_ROOT/mesaagent.config -t mesaagent -f - -# Convert function YAML to JSON -cd $DNP3_ROOT -python dnp3/mesa/conversion.py < dnp3/mesa/mesa_functions.yaml > dnp3/mesa/mesa_functions.config - -# Put the agent's point definitions and function definitions in the config store. -cd $VOLTTRON_ROOT -vctl config store mesaagent mesa_points.config $DNP3_ROOT/dnp3/mesa_points.config -vctl config store mesaagent mesa_functions.config $DNP3_ROOT/dnp3/mesa/mesa_functions.config - -echo -echo Stored point and function configurations in config store... -vctl config list mesaagent -echo diff --git a/services/core/DNP3Agent/mesa_master.py b/services/core/DNP3Agent/mesa_master.py deleted file mode 100644 index 803caa01a7..0000000000 --- a/services/core/DNP3Agent/mesa_master.py +++ /dev/null @@ -1,142 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - -import os -import time - -from pydnp3 import opendnp3 - -from dnp3 import DIRECT_OPERATE, SELECT, OPERATE, DATA_TYPE_BINARY_OUTPUT -from dnp3.points import PointDefinitions -from dnp3_master import DNP3Master -from function_test import FunctionTest - -POINT_DEF_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'tests', 'data', 'mesa_points.config')) - -OUTPUT_TYPES = { - float: opendnp3.AnalogOutputFloat32, - int: opendnp3.AnalogOutputInt32, - bool: opendnp3.ControlRelayOutputBlock -} - - -class MesaMasterException(Exception): - pass - - -class MesaMaster(DNP3Master): - - def __init__(self, **kwargs): - DNP3Master.__init__(self, **kwargs) - - self.SEND_FUNCTIONS = { - DIRECT_OPERATE: self.send_direct_operate_command, - SELECT: self.send_select_and_operate_command, - OPERATE: self.send_select_and_operate_command, - } - - def send_command(self, send_func, pdef, point_value, index=None): - """ - Send a command to outstation. Check for valid value to send. - - :param send_func: send_direct_operate_command or send_select_and_operate_command - :param pdef: point definition - :param point_value: value of the point that will be sent to outstation - :param index: index of the point from point definition - """ - value_type = type(point_value) - - if pdef.data_type == DATA_TYPE_BINARY_OUTPUT: - point_value = opendnp3.ControlCode.LATCH_ON if point_value else opendnp3.ControlCode.LATCH_OFF - - try: - send_func(OUTPUT_TYPES[value_type](point_value), index or pdef.index) - time.sleep(0.2) - except KeyError: - raise MesaMasterException("Unrecognized output type: {}".format(value_type)) - - def send_array(self, json_array, pdef): - """ - Send point array to outstation. - - :param json_array: json array of points and values that will be sent to outstation - :param pdef: point definition - """ - for offset, value in enumerate( - record[field['name']] - for record in json_array for field in pdef.array_points): - if value not in ['', None]: - self.send_command(self.send_direct_operate_command, pdef, value, index=pdef.index+offset) - - def send_function_test(self, point_def_path='', func_def_path='', func_test_path='', func_test_json=None): - """ - Send a function test after validating the function test (as JSON). - - :param point_def_path: path to point definition config - :param func_def_path: path to function definition config - :param func_test_path: path to function test json - :param func_test_json: function test json - """ - ftest = FunctionTest(func_test_path, func_test_json, point_def_path=point_def_path, func_def_path=func_def_path) - - ftest.is_valid() - - pdefs = PointDefinitions(point_definitions_path=point_def_path or POINT_DEF_PATH) - - func_def = ftest.get_function_def() - for func_step_def in func_def.steps: - try: - point_value = ftest.points[func_step_def.name] - except KeyError: - continue - - pdef = pdefs.point_named(func_step_def.name) # No need to test for valid point name, as that was done above - if not pdef: - raise MesaMasterException("Point definition not found: {}".format(func_step_def.name)) - - if type(point_value) == list: - self.send_array(point_value, pdef) - else: - try: - send_func = self.SEND_FUNCTIONS[func_step_def.fcodes[0] if func_step_def.fcodes else DIRECT_OPERATE] - except (KeyError, IndexError): - raise MesaMasterException("Unrecognized sent command function") - - self.send_command(send_func, pdef, point_value) - - -def main(): - mesa_master = MesaMaster() - mesa_master.connect() - # Ad-hoc tests can be inserted here if desired. - mesa_master.shutdown() - - -if __name__ == '__main__': - main() diff --git a/services/core/DNP3Agent/mesaagent.config b/services/core/DNP3Agent/mesaagent.config deleted file mode 100644 index ce39874edd..0000000000 --- a/services/core/DNP3Agent/mesaagent.config +++ /dev/null @@ -1,15 +0,0 @@ -{ - "points": "config://mesa_points.config", - "functions": "config://mesa_functions.config", - "point_topic": "mesa/point", - "function_topic": "mesa/function", - "outstation_status_topic": "mesa/outstation_status", - "outstation_config": { - "database_sizes": 10000, - "log_levels": ["NORMAL"] - }, - "local_ip": "0.0.0.0", - "port": 20000, - "all_functions_supported_by_default": true, - "function_validation": false -} diff --git a/services/core/DNP3Agent/requirements.txt b/services/core/DNP3Agent/requirements.txt deleted file mode 100644 index 9647f44d1e..0000000000 --- a/services/core/DNP3Agent/requirements.txt +++ /dev/null @@ -1 +0,0 @@ -pydnp3==0.1.0 diff --git a/services/core/DNP3Agent/setup.py b/services/core/DNP3Agent/setup.py deleted file mode 100644 index f581207dc4..0000000000 --- a/services/core/DNP3Agent/setup.py +++ /dev/null @@ -1,68 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, SLAC / 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# This material was prepared in part as an account of work sponsored by an agency of -# the United States Government. Neither the United States Government nor the -# United States Department of Energy, nor SLAC, nor 8minutenergy, nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by the United States Government or any agency thereof, or -# SLAC, 8minutenergy, or Kisensum. The views and opinions of authors expressed -# herein do not necessarily state or reflect those of the -# United States Government or any agency thereof. -# }}} - -from os import path, environ -from setuptools import setup, find_packages - -MAIN_MODULE = 'agent' - -# Find the agent package that contains the main module -packages = find_packages('.') -agent_package = '' -for package in find_packages(): - # Because there could be other packages such as tests - if path.isfile(package + '/' + MAIN_MODULE + '.py') is True: - agent_package = package -if not agent_package: - raise RuntimeError('None of the packages under {dir} contain the file ' - '{main_module}'.format(main_module=MAIN_MODULE + '.py', - dir=path.abspath('.'))) - -# Find the version number from the main module -agent_module = environ.get('AGENT_MODULE', agent_package + '.' + MAIN_MODULE) -_temp = __import__(agent_module, globals(), locals(), ['__version__'], 0) -__version__ = _temp.__version__ - -# Setup -setup( - name=agent_module.replace('.', ''), - version=__version__, - install_requires=['volttron'], - packages=packages, - entry_points={ - 'setuptools.installation': [ - 'eggsecutable = ' + agent_module + ':main', - ] - } -) diff --git a/services/core/DNP3Agent/tests/MesaTestAgent/setup.py b/services/core/DNP3Agent/tests/MesaTestAgent/setup.py deleted file mode 100644 index 9c01575e32..0000000000 --- a/services/core/DNP3Agent/tests/MesaTestAgent/setup.py +++ /dev/null @@ -1,63 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - -from os import path -from setuptools import setup, find_packages - -MAIN_MODULE = 'agent' - -# Find the agent package that contains the main module -packages = find_packages('.') -agent_package = '' -for package in find_packages(): - # Because there could be other packages such as tests - if path.isfile(package + '/' + MAIN_MODULE + '.py') is True: - agent_package = package -if not agent_package: - raise RuntimeError('None of the packages under {dir} contain the file ' - '{main_module}'.format(main_module=MAIN_MODULE + '.py', - dir=path.abspath('.'))) - -# Find the version number from the main module -agent_module = agent_package + '.' + MAIN_MODULE -_temp = __import__(agent_module, globals(), locals(), ['__version__'], 0) -__version__ = _temp.__version__ - -# Setup -setup( - name=agent_package + 'agent', - version=__version__, - install_requires=['volttron'], - packages=packages, - entry_points={ - 'setuptools.installation': [ - 'eggsecutable = ' + agent_module + ':main', - ] - } -) diff --git a/services/core/DNP3Agent/tests/MesaTestAgent/testagent.config b/services/core/DNP3Agent/tests/MesaTestAgent/testagent.config deleted file mode 100644 index 1f73dc61fa..0000000000 --- a/services/core/DNP3Agent/tests/MesaTestAgent/testagent.config +++ /dev/null @@ -1,23 +0,0 @@ -{ - "mesaagent_id": "mesaagent", - # The point configuration can be defined here by the test agent, or the test agent - # can rely on the DNP3 driver's config (e.g. dnp3.csv). If a point configuration is - # defined here, and the test agent is started after the PlatformDriverAgent, the test - # agent's point config will override the DNP3 driver config. - # "point_config": { - # "DCHD.WTgt": {"group": 41, "index": 65}, - # "DCHD.WinTms": {"group": 41, "index": 66}, - # "DCHD.RmpTms": {"group": 41, "index": 67}, - # "DCHD.RevtTms": {"group": 41, "index": 68}, - # "DCHD.RmpUpRte": {"group": 41, "index": 69}, - # "DCHD.RmpDnRte": {"group": 41, "index": 70}, - # "DCHD.ChaRmpUpRte": {"group": 41, "index": 71}, - # "DCHD.ChaRmpDnRte": {"group": 41, "index": 72}, - # "DCHD.ModPrty": {"group": 41, "index": 9}, - # "DCHD.VArAct": {"group": 41, "index": 10}, - # "DCHD.ModEna": {"group": 12, "index": 5} - # }, - "point_topic": "mesa/point", - "function_topic": "mesa/function", - "outstation_status_topic": "mesa/outstation_status" -} diff --git a/services/core/DNP3Agent/tests/MesaTestAgent/testagent/__init__.py b/services/core/DNP3Agent/tests/MesaTestAgent/testagent/__init__.py deleted file mode 100644 index e69de29bb2..0000000000 diff --git a/services/core/DNP3Agent/tests/MesaTestAgent/testagent/agent.py b/services/core/DNP3Agent/tests/MesaTestAgent/testagent/agent.py deleted file mode 100644 index 80ae3731ec..0000000000 --- a/services/core/DNP3Agent/tests/MesaTestAgent/testagent/agent.py +++ /dev/null @@ -1,217 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - - - -import logging -import sys - -from volttron.platform.agent import utils -from volttron.platform.vip.agent import Agent, Core, RPC -from volttron.platform.scheduling import periodic - -utils.setup_logging() -_log = logging.getLogger(__name__) - -__version__ = '1.0' - -RPC_INTERVAL_SECS = 10 - -TEST_GET_POINT_NAME1 = 'DCHD.ModEna' -TEST_GET_POINT_NAME2 = 'DCHD.VArAct.out' -TEST_GET_SELECTOR_BLOCK_POINT_NAME = 'Curve Edit Selector' -TEST_SET_POINT_NAME = 'DCHD.WTgt.1' -TEST_SET_SUPPORT_POINT_NAME = 'DCHA.Beh' -# Test has been disabled: these points are not part of the current production data definitions. -# TEST_DEVICE_ARRAY = { -# "Inverter power readings": [ -# { -# "Inverter active power output - Present Active Power output level": 302, -# "Inverter reactive output - Present reactive power output level": 100 -# } -# ] -# } -TEST_INPUT_CURVE = { - "FMAR.in.PairArray.CsvPts": [ - {"FMAR.in.PairArray.CsvPts.xVal": 30, "FMAR.in.PairArray.CsvPts.yVal": 130}, - {"FMAR.in.PairArray.CsvPts.xVal": 31, "FMAR.in.PairArray.CsvPts.yVal": 131}, - {"FMAR.in.PairArray.CsvPts.xVal": 32, "FMAR.in.PairArray.CsvPts.yVal": 132} - ] -} - - -def mesa_test_agent(config_path, **kwargs): - """ - Parse the TestAgent configuration file and return an instance of - the agent that has been created using that configuration. - - See initialize_config() method documentation for a description of each configurable parameter. - - This agent can be installed from a command-line shell as follows: - export VOLTTRON_ROOT= - export MESA_TEST=$VOLTTRON_ROOT/services/core/MesaAgent/tests/TestAgent - cd $VOLTTRON_ROOT - python scripts/install-agent.py -s $$MESA_TEST -i mesatest -c $MESA_TEST/testagent.config -t mesatest -f - - :param config_path: (str) Path to a configuration file. - :returns: TestAgent instance - """ - try: - config = utils.load_config(config_path) - except (Exception, err): - _log.error("Error loading MesaTestAgent configuration: {}".format(err)) - config = {} - mesaagent_id = config.get('mesaagent_id', 'mesaagent') - point_topic = config.get('point_topic', 'mesa/point') - function_topic = config.get('function_topic', 'mesa/function') - outstation_status_topic = config.get('outstation_status_topic', 'mesa/outstation_status') - point_config = config.get('point_config', None) - return MesaTestAgent(mesaagent_id, point_topic, function_topic, outstation_status_topic, point_config, **kwargs) - - -class MesaTestAgent(Agent): - """ - This is a sample test agent that demonstrates and tests MesaAgent. - It exercises MesaAgent's exposed RPC calls and consumes VOLTTRON messages published by MesaAgent. - """ - - def __init__(self, mesaagent_id, point_topic, function_topic, outstation_status_topic, point_config, **kwargs): - super(MesaTestAgent, self).__init__(**kwargs) - self.mesaagent_id = None - self.point_topic = None - self.function_topic = None - self.outstation_status_topic = None - self.point_config = None - self.default_config = {'mesaagent_id': mesaagent_id, - 'point_topic': point_topic, - 'function_topic': function_topic, - 'outstation_status_topic': outstation_status_topic, - 'point_config': point_config} - self.vip.config.set_default("config", self.default_config) - self.vip.config.subscribe(self._configure, actions=["NEW", "UPDATE"], pattern="config") - self.initialize_config(self.default_config) - - def _configure(self, config_name, action, contents): - """The agent's config may have changed. Re-initialize it.""" - config = self.default_config.copy() - config.update(contents) - self.initialize_config(config) - - def initialize_config(self, config): - self.mesaagent_id = config['mesaagent_id'] - self.point_topic = config['point_topic'] - self.function_topic = config['function_topic'] - self.outstation_status_topic = config['outstation_status_topic'] - self.point_config = config['point_config'] - _log.debug('MesaTestAgent configuration parameters:') - _log.debug('\tmesaagent_id={}'.format(self.mesaagent_id)) - _log.debug('\tpoint_topic={}'.format(self.point_topic)) - _log.debug('\tfunction_topic={}'.format(self.function_topic)) - _log.debug('\toutstation_status_topic={}'.format(self.outstation_status_topic)) - _log.debug('\tpoint_config={}'.format(self.point_config)) - - @Core.receiver('onstart') - def onstart_method(self, sender): - """The test agent has started. Perform initialization and spawn the main process loop.""" - _log.debug('Starting MesaTestAgent') - if self.point_config: - # This test agent can configure the points itself, or (by default) it can rely on the DNP3 driver to do it. - _log.debug('Sending DNP3 point map: {}'.format(self.point_config)) - self.send_rpc('config_points', self.point_config) - # Subscribe to the MesaAgent's point, function, and outstation_status publications. - self.vip.pubsub.subscribe(peer='pubsub', prefix=self.point_topic, callback=self.receive_point_value) - self.vip.pubsub.subscribe(peer='pubsub', prefix=self.function_topic, callback=self.receive_function) - self.vip.pubsub.subscribe(peer='pubsub', prefix=self.outstation_status_topic, callback=self.receive_status) - self.core.schedule(periodic(RPC_INTERVAL_SECS), self.issue_rpcs) - - @staticmethod - def receive_point_value(peer, sender, bus, topic, headers, point_value): - """(Subscription callback) Receive a point value.""" - _log.debug('MesaTestAgent received point_value={}'.format(point_value)) - - def receive_function(self, peer, sender, bus, topic, headers, point_value): - """(Subscription callback) Receive a function.""" - _log.debug('MesaTestAgent received function={}'.format(point_value)) - if 'expected_response' in point_value: - # The function step expects a response. Send one. - self.set_point(point_value['expected_response'], 1) - - @staticmethod - def receive_status(peer, sender, bus, topic, headers, point_value): - """(Subscription callback) Receive outstation status.""" - _log.debug('MesaTestAgent received outstation status={}'.format(point_value)) - - def issue_rpcs(self): - """Periodically issue RPCs to the DNP3 agent.""" - self.get_point(TEST_GET_POINT_NAME1) - self.get_point(TEST_GET_POINT_NAME2) - self.get_selector_block(TEST_GET_SELECTOR_BLOCK_POINT_NAME, 3) - self.set_point(TEST_SET_POINT_NAME, 10) - self.set_point(TEST_SET_SUPPORT_POINT_NAME, True) - # self.set_points(TEST_DEVICE_ARRAY) - self.set_points(TEST_INPUT_CURVE) - - def get_point(self, point_name): - """Get a single metric from the MesaAgent via an RPC call.""" - point_value = self.send_rpc('get_point', point_name) - _log.debug('MesaTestAgent get_point received {}={}'.format(point_name, point_value)) - - def get_selector_block(self, point_name, edit_selector): - """Get a selector block from the MesaAgent via an RPC call.""" - selector_block = self.send_rpc('get_selector_block', point_name, edit_selector) - _log.debug('MesaTestAgent get_selector_block {} selector {} received {}'.format(point_name, - edit_selector, - selector_block)) - - def set_point(self, point_name, value): - """Send a single point value to the MesaAgent via an RPC call.""" - _log.debug('MesaTestAgent set_point sent {}={}'.format(point_name, value)) - self.send_rpc('set_point', point_name, value) - - def set_points(self, json_payload): - """Send a single point value to the MesaAgent via an RPC call.""" - _log.debug('MesaTestAgent sending points: {}'.format(json_payload)) - self.send_rpc('set_points', json_payload) - - def send_rpc(self, rpc_name, *args, **kwargs): - """Send an RPC request to the MesaAgent, and return its response (if any).""" - response = self.vip.rpc.call(self.mesaagent_id, rpc_name, *args, **kwargs) - return response.get(30) - - -def main(): - """Start the agent.""" - utils.vip_main(mesa_test_agent, identity='mesa_test_agent', version=__version__) - - -if __name__ == '__main__': - try: - sys.exit(main()) - except KeyboardInterrupt: - pass diff --git a/services/core/DNP3Agent/tests/README.md b/services/core/DNP3Agent/tests/README.md deleted file mode 100644 index 8238796c8f..0000000000 --- a/services/core/DNP3Agent/tests/README.md +++ /dev/null @@ -1,43 +0,0 @@ -The tests/ subdirectory of DNP3Agent contains several types of tests: - -# MesaAgent Regression Tests - -**test_mesa_agent.py** contains MesaAgent pytest regression tests as follows: - -1. Load point and function definitions. -2. Start a MesaAgent process. -3. Test routing of DNP3 output: - - Send point values from a simulated Master. - - Verify that MesaAgent has published them correctly on the VOLTTRON message bus. -4. Test routing of DNP3 input: - - Use RPC calls to set point values. - - Verify that the simulated Master has received them correctly. - -# DNP3Agent Regression Tests - -**test_dnp3_agent.py** contains DNP3Agent pytest regression tests as follows: - -1. Load point definitions. -2. Start a DNP3Agent process. -3. Test routing of DNP3 output, similar to the MesaAgent tests above. -4. Test routing of DNP3 input, similar to the MesaAgent tests above. - -# Data Regression Tests - -**test_mesa_data.py** contains pytest regression tests of MesaAgent data. - -The test strategy in test_mesa_data.py is similar to the other pytest strategies, -but rather than working with a small, controlled set of data, this module's tests -use "production" point and function definitions. - -# Ad-Hoc Unit Test Support - -**unit_test_point_definitions.py** contains a mix of standalone non-pytest -methods that test and validate various types of data and behavior. - -**MesaTestAgent** is a VOLTTRON agent that interacts with MesaAgent, sending -RPC calls and subscribing to MesaAgent publication of data. - -**mesa_platform_cmd.py** is a standalone command-line utility (built on the Python -Cmd library) that sends point and function values from the master to -the (MesaAgent) DNP3 outstation. diff --git a/services/core/DNP3Agent/tests/data/connect_and_disconnect.json b/services/core/DNP3Agent/tests/data/connect_and_disconnect.json deleted file mode 100644 index 26ba349c17..0000000000 --- a/services/core/DNP3Agent/tests/data/connect_and_disconnect.json +++ /dev/null @@ -1,7 +0,0 @@ -{ - "function_id": "connect_and_disconnect", - "function_name": "Connect and Disconnect", - "DCTE.WinTms.AO16": 10, - "DCTE.RvrtTms.AO17": 12, - "CSWI.Pos.BO5": true -} \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/data/enable_watt_var_power_mode.json b/services/core/DNP3Agent/tests/data/enable_watt_var_power_mode.json deleted file mode 100644 index 756b598ebe..0000000000 --- a/services/core/DNP3Agent/tests/data/enable_watt_var_power_mode.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "function_id": "enable_watt-var_power_mode", - "function_name": "Enable Watt-Var Power Mode", - "DWVR.ModPrio.AO221": 1, - "DWVR.WinTms.AO222": 2, - "DWVR.RmpTms.AO223": 3, - "DWVR.RvrtTms.AO224": 4, - "DWVR.EcpRef.AO225": 5, - "DWVR.OpnLoopMax.AO227": 10, - "DWVR.OpnLoopMax.AO228": 1, - "DWVR.WVArCrv.AO226": 2, - "DWVR.ModEna.BO30": true -} \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/data/enable_watt_var_schedule.json b/services/core/DNP3Agent/tests/data/enable_watt_var_schedule.json deleted file mode 100644 index a30f249fa4..0000000000 --- a/services/core/DNP3Agent/tests/data/enable_watt_var_schedule.json +++ /dev/null @@ -1,13 +0,0 @@ -{ - "function_id": "enable_schedules", - "function_name": "Enable Watt-Var Schedule", - "FSCHxx.Mod.BO42": true, - "FSCC.Schd.AO461": 2, - "FSCHxx.SchdReuse.BO43": true, - "FSCHxx.SchdReuse.BO44": false, - "FSCHxx.SchdReuse.BO45": false, - "FSCHxx.SchdReuse.BO46": false, - "FSCHxx.SchdReuse.BO47": false, - "FSCHxx.SchdReuse.BO48": false, - "FSCHxx.SchdReuse.BO49": false -} \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/data/mesa_functions.yaml b/services/core/DNP3Agent/tests/data/mesa_functions.yaml deleted file mode 100644 index fdad5de95b..0000000000 --- a/services/core/DNP3Agent/tests/data/mesa_functions.yaml +++ /dev/null @@ -1,2581 +0,0 @@ -functions: -- id: connect_and_disconnect - name: Connect and Disconnect - ref: AN2018 Spec section 2.4.4 Table 29 - steps: - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DCTE.WinTms.AO16 - response: DCTE.WinTms.AI60 - step_number: 1 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DCTE.RvrtTms.AO17 - response: DCTE.RvrtTms.AI61 - step_number: 2 - - description: Retrieve status of switch - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.off.BI23 - step_number: 3 - - action: publish - description: Issue switch control command and receive response - fcodes: - - select - - operate - optional: M - point_name: CSWI.Pos.BO5 - response: DSTO.DEROpSt.off.BI23 - step_number: 4 - - description: Detect if switch is moving - fcodes: - - read - - response - optional: O - point_name: n/a - response: CSWI.Pos.BI24 - step_number: 5 -- id: cease_to_energize_and_return_to_service - name: Cease to Energize and Return to Service - ref: AN2018 Spec section 2.4.5 Table 30 - steps: - - description: Set Cease to Energize Time Window - fcodes: - - direct_operate - optional: I - point_name: DCTE.WinTms.AO13 - response: DCTE.WinTms.AI57 - step_number: 1 - - description: Set Cease to Energize Ramp DownTime - fcodes: - - direct_operate - optional: I - point_name: DCTE.RmpTms.AO14 - response: DCTE.RmpTms.AI58 - step_number: 2 - - description: Set Cease to Energize Timeout Period - fcodes: - - direct_operate - optional: I - point_name: DCTE.RvrtTms.AO15 - response: DCTE.RvrtTms.AI59 - step_number: 3 - - description: Cause DER to Cease to Energize - fcodes: - - select - - operate - optional: M - point_name: DCTE.CeaEngzReq.BO2 - response: DSTO.DEROpSt.connectedandidle.BI14 - step_number: 4 - - description: Give DER Permission to Stop - fcodes: - - select - - operate - optional: M - point_name: DSTO.PrmDscon.BO4 - response: DSTO.PrmDscon.BI17 - step_number: 5 - - description: Confirm DER is Stopping - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.stopping.BI13 - step_number: 6 - - description: Confirm DER has Ceased to Energize - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.ceasedtoenergize.BI15 - step_number: 7 - - description: Set High Voltage Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.VHiLim.AO6 - response: DCTE.VHiLim.AI50 - step_number: 8 - - description: Set Low Voltage Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.VLoLim.AO7 - response: DCTE.VLoLim.AI51 - step_number: 9 - - description: Set High Frequency Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.HzHiLim.AO8 - response: DCTE.HzHiLim.AI52 - step_number: 10 - - description: Set Low Frequency Limit - fcodes: - - direct_operate - optional: I - point_name: DCTE.HzLoLim.AO9 - response: DCTE.HzLoLim.AI53 - step_number: 11 - - description: Set Delay Time - fcodes: - - direct_operate - optional: I - point_name: DCTE.RtnDlyTmms.AO10 - response: DCTE.RtnDlTmms.AI54 - step_number: 12 - - description: Set Return to Service Time Window - fcodes: - - direct_operate - optional: I - point_name: DCTE.WinTms.AO11 - response: DCTE.WinTms.AI55 - step_number: 13 - - description: Set Return to Service Ramp Up Time - fcodes: - - direct_operate - optional: I - point_name: DCTE.RtnRmpTmms.AO12 - response: DCTE.RtnRmpTmms.AI56 - step_number: 14 - - description: Cause DER to Return to Service - fcodes: - - select - - operate - optional: M - point_name: DCTE.RtnSrvReq.BO1 - response: DSTO.DEROpSt.startingandsynchronizing.BI12 - step_number: 15 - - action: publish - description: Give DER Permission to Start - fcodes: - - select - - operate - optional: M - point_name: DSTO.PrmConn.BO3 - response: DSTO.PrmConn.BI16 - step_number: 16 - - description: Confirm DER is Started - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.DEROpSt.connectedandidle.BI14 - step_number: 17 -- id: enable_low_high_voltage_ride-through_mode - mode_types: - curve: - - 9 - - 10 - - 11 - - 12 - schedule: - - 1 - - 2 - - 3 - - 4 - name: Enable Low/High Voltage Ride-Through Mode - ref: AN2018 Spec section 2.5.1 Table 33 - steps: - - description: Set the Reference Voltage if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 1 - - description: Set the Reference Voltage Offset if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 2 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHVT.EcpRef.AO22 - response: DHVT.EcpRef.AI71 - step_number: 3 - - description: 'DGSMn.ModTyp.AO245 = <9> HVRT Must Trip: If the curve is a must - trip curve, identify the index of the curve which specifies trip points when - the voltage is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOV.BlkRef.AO23 - response: PTOV.BlkRef.AI73 - step_number: 4 - - description: 'DGSMn.ModTyp.AO245 = <11> LVRT Must Trip: If the curve is a must - trip curve, identify the index of the curve which specifies trip points when - the voltage is low' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUV.BlkRef.AO24 - response: PTUV.BlkRef.AI74 - step_number: 5 - - description: 'DGSMn.ModTyp.AO245 = <10> HVRT Momentary Cessation: If the curve - is a must trip curve, identify the index of the curve which specifies where - generation/discharging must stop when the voltage is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOV.BlkRef.AO25 - response: PTOV.BlkRef.AI75 - step_number: 6 - - description: 'DGSMn.ModTyp.AO245 = <12> LVRT Momentary Cessation: If the curve - is a must trip curve, identify the index of the curve which specifies where - generation/discharging must stop when the voltage is low' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUV.BlkRef.AO26 - response: PTUV.BlkRef.AI76 - step_number: 7 - - action: publish - description: Enable the Low/High Voltage Ride-Through Mode - fcodes: - - select - - operate - optional: M - point_name: DHVT.ModEna.BO12 - response: DHVT.ModEna.BI64 - step_number: 8 -- id: enable_low_high_frequency_ride-through_mode - mode_types: - curve: - - 13 - - 14 - - 15 - - 16 - schedule: - - 5 - - 6 - - 7 - - 8 - name: Enable Low/High Frequency Ride-Through Mode - ref: AN2018 Spec section 2.5.2 Table 35 - steps: - - description: Set the Nominal Grid Frequency if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.EcpNomHz.AO2 - response: DECP.EcpNomHz.AI31 - step_number: 1 - - description: Identify the meter used to measure the frequency. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHFT.EcpRef.AO27 - response: DHFT.EcpRef.AI77 - step_number: 2 - - description: 'DGSMn.ModTyp.AO245 = <13> HFRT Must Trip: Identify the index of - the frequency ride through curve which specifies trip ponts when the frequency - is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOF.BlkRef.AO28 - response: PTOF.BlkRef.AI79 - step_number: 3 - - description: 'DGSMn.ModTyp.AO245 = <15> LFRT Must Trip: Identify the index of - the frequency ride through curve which specifies trip ponts when the voltage - is low' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUF.BlkRef.AO29 - response: PTUF.BlkRef.AI80 - step_number: 4 - - description: 'DGSMn.ModTyp.AO245 = <14> HFRT Mandatory Operation: Identify the - index of the frequency ride through curve which specifies where generation/discharging - must stop when the frequency is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTOF.BlkRef.AO30 - response: PTOF.BlkRef.AI81 - step_number: 5 - - description: 'DGSMn.ModTyp.AO245 = <16> LFRT Mandatory Operation: Identify the - index of the frequency ride through curve which specifies where generation/discharging - must stop when the frequency is high' - fcodes: - - direct_operate - func_ref: curve - optional: O - point_name: PTUF.BlkRef.AO31 - response: PTUF.BlkRef.AI82 - step_number: 6 - - action: publish - description: Enable the Low/High Frequency Ride-Through Mode - fcodes: - - select - - operate - optional: M - point_name: DHFT.ModEna.BO13 - response: DHFT.ModEna.BI65 - step_number: 7 -- id: enable_frequency-watt_mode - name: Enable Frequency-Watt Mode - ref: AN2018 Spec section 2.5.3 Table 36 - mode_types: - schedule: - - 11 - steps: - - description: If not already established, set the Nominal Grid Frequency - fcodes: - - direct_operate - optional: I - point_name: DECP.EcpNomHz.AO2 - response: DECP.EcpNomHz.AI31 - step_number: 1 - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW2.ModPrio.AO57 - response: DHFW2.ModPrio.AI115 - step_number: 2 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DHFW.WinTms.AO58 - response: DHFW.WinTms.AI116 - step_number: 3 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DHFW.RmpTms.AO59 - response: DHFW.RmpTms.AI117 - step_number: 4 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DHFW.RvrtTms.AO60 - response: DHFW.RvrtTms.AI118 - step_number: 5 - - description: Identify the meter used to measure the frequency. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHFW.EcpRef.AO61 - response: DHFW2.EcpRef.AI119 - step_number: 6 - - description: Set the High Starting Frequency - fcodes: - - direct_operate - optional: I - point_name: DHFW.HzStr.AO62 - response: DHFW2.HzStr.AI121 - step_number: 7 - - description: Set the High Stopping Frequency - fcodes: - - direct_operate - optional: I - point_name: DHFW.HzStop.AO63 - response: DHFW2.HzStop.AI122 - step_number: 8 - - description: Set the High Discharging Gradient - fcodes: - - direct_operate - optional: I - point_name: DHFW.WGra.AO64 - response: DHFW.WGra.AI123 - step_number: 9 - - description: Set the High Charging Gradient - fcodes: - - direct_operate - optional: I - point_name: DHFW.WChaGra.AO65 - response: DHFW.WChaGra.AI124 - step_number: 10 - - description: Set the Low Starting Frequency - fcodes: - - direct_operate - optional: I - point_name: DLFW.HzStr.AO66 - response: DLFW2.HzStr.AI125 - step_number: 11 - - description: Set the Low Stopping Frequency - fcodes: - - direct_operate - optional: I - point_name: DLFW.HzStop.AO67 - response: DLFW2.HzStop.AI126 - step_number: 12 - - description: Set the Low Discharging Gradient - fcodes: - - direct_operate - optional: I - point_name: DLFW.WGra.AO68 - response: DLFW.WGra.AI127 - step_number: 13 - - description: Set the Low Charging Gradient - fcodes: - - direct_operate - optional: I - point_name: DLFW.WChaGra.AO69 - response: DLFW.WChaGra.AI128 - step_number: 14 - - description: Set the Start Delay - fcodes: - - direct_operate - optional: I - point_name: DHFW2.ActStrDlTmms.AO70 - response: DHFW2.ActStrDlTmms.AI129 - step_number: 15 - - description: Set the Stop Delay - fcodes: - - direct_operate - optional: I - point_name: DHFW2.ActStopDlTmms.AO71 - response: DHFW2.ActStopDlTmms.AI130 - step_number: 16 - - description: Set the Ramp Up Time Constant - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoop.AO72 - response: DLFW.OpnLoopMax.AI131 - step_number: 17 - - description: Set the Ramp Down Time Constant - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoop.AO73 - response: DHFW.OpnLoopMax.AI132 - step_number: 18 - - description: Set the Discharging Up Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.DschRpuRte.AO74 - response: DHFW.RpuRte.AI133 - step_number: 19 - - description: Set the Discharging Down Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.DschRpdRte.AO75 - response: DHFW.RpdRteMax.AI134 - step_number: 20 - - description: Set the Charging Up Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.ChaRpuRte.AO76 - response: DHFW.RpuChaRte.AI135 - step_number: 21 - - description: Set the Charging Down Ramp Rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.ChaRpdRte.AO77 - response: DHFW.RpdChaRteMax.AI136 - step_number: 22 - - description: Set the Hight Return Gradient - fcodes: - - direct_operate - optional: I - point_name: DHFW.RtnRmpRte.AO78 - response: DHFW2.RtnRmpRte.AI137 - step_number: 23 - - description: Set the Low Return Gradient - fcodes: - - direct_operate - optional: I - point_name: DLFW.RtnRmpRte.AO79 - response: DLFW2.RtnRmpRte.AI138 - step_number: 24 - - description: Set the minium State of Charge to be used by this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMin.AO80 - response: DAGC.SocUseMinPct.AI140 - step_number: 25 - - description: Set the maximum State of Charge to be used by this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMax.AO81 - response: DAGC.SocUseMaxPct.AI141 - step_number: 26 - - description: Enable or Disable Hysteresis - fcodes: - - direct_operate - optional: I - point_name: DHFW.HysEna.BO34 - response: DHFW.HysEna.BI86 - step_number: 27 - - description: Enable or Disable Snapshot of Power - fcodes: - - direct_operate - optional: I - point_name: DHFW.SnptEna.BO35 - response: DHFW.SnptEna.BI87 - step_number: 28 - - action: publish - description: Enable Frequency-Watt Mode - fcodes: - - select - - operate - optional: M - point_name: DHFW.ModEna.BO16 - response: DHFW.ModEna.BI68 - step_number: 29 -- id: enable_dynamic_reactive_current_support_mode - name: Enable Dynamic Reactive Current Support Mode - ref: AN2018 Spec section 2.5.4 Table 37 - mode_types: - schedule: - - 9 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DRGS.ModPrio.AO32 - response: DRGS.ModPrio.AI83 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DRGS.WinTms.AO33 - response: DRGS.WinTms.AI84 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DRGS.RmpTms.AO34 - response: DRGS.RmpTms.AI85 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DRGS.RvrtTms.AO35 - response: DRGS.RvrtTms.AI86 - step_number: 4 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DRGS.EcpRef.AO36 - response: DRGS.EcpRef.AI87 - step_number: 5 - - description: Set the Gradient Mode to select the curve shape - fcodes: - - direct_operate - optional: M - point_name: DRGS.ArGraMod.AO37 - response: DRGS.ArGraMod.AI91 - step_number: 6 - - description: Set the Deadband Minimum Voltage - fcodes: - - direct_operate - optional: M - point_name: DRGS.DbVMin.AO38 - response: DRGS.DbVMin.AI92 - step_number: 7 - - description: Set the Deadband Maximum Voltage - fcodes: - - direct_operate - optional: M - point_name: DRGS.DbVMax.AO39 - response: DRGS.DbVMax.AI93 - step_number: 8 - - description: Set the Reactive Current Support Gradient for Sags - fcodes: - - direct_operate - optional: M - point_name: DRGS.ArGraSag.AO40 - response: DRGS.ArGraSag.AI94 - step_number: 9 - - description: Set the Reactive Current Support Gradient for Swells - fcodes: - - direct_operate - optional: M - point_name: DRGS.ArGraSwl.AO41 - response: DRGS.ArGraSwl.AI95 - step_number: 10 - - description: Set the Filter Time for the Moving Average Voltage in seconds - fcodes: - - direct_operate - optional: M - point_name: DRGS.FilTms.AO42 - response: DRGS.FilTms.AI96 - step_number: 11 - - description: Enable Event-Based Reactive Current Support if required. It shall - default to Disabled. - fcodes: - - direct_operate - optional: I - point_name: DRGS.ArGraMod.BO33 - response: DRGS.ModEna.BI85 - step_number: 12 - - description: Set the Hold Time in milliseconds if Event-Based Reactive Current - Support is required. - fcodes: - - direct_operate - optional: I - point_name: DRGS.HoldTmms.AO46 - response: DRGS.HoldTmms.AI100 - step_number: 13 - - description: Set the Block Zone Voltage if required. Otherwise it shall default - to zero. - fcodes: - - direct_operate - optional: I - point_name: DRGS.BlkZnV.AO43 - response: DRGS.BlkZnV.AI97 - step_number: 14 - - description: Set the Hysteresis Block Zone Voltage if required. Otherwise it - shall default to zero. - fcodes: - - direct_operate - optional: I - point_name: DRGS.HysBlkZnV.AO44 - response: DRGS.HysBlkZnV.AI98 - step_number: 15 - - description: Set the Block Zone Time in milliseconds if required. Otherwise it - shall default to zero. - fcodes: - - direct_operate - optional: I - point_name: DRGS.BlkZnTmms.AO45 - response: DRGS.BlkZnTmms.AI99 - step_number: 16 - - action: publish - description: Enable Dynamic Reactive Current Mode - fcodes: - - select - - operate - optional: M - point_name: DRGS.ModEna.BO14 - response: DRGS.ModEna.BI66 - step_number: 17 -- id: enable_volt-watt_mode - name: Enable Volt-Watt Mode - ref: AN2018 Spec section 2.5.5 Table 38 - steps: - - description: If not already established, set the Reference Voltage - fcodes: - - direct_operate - optional: I - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 1 - - description: If not already established, set the Reference Voltage Offset - fcodes: - - direct_operate - optional: I - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 2 - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVWD.ModPrio.AO48 - response: DVWD.ModPrio.AI102 - step_number: 3 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DVWD.WinTms.AO49 - response: DVWD.WinTms.AI103 - step_number: 4 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DVWD.RmpTms.AO50 - response: DVWD.RmpTms.AI104 - step_number: 5 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVWD.RvrtTms.AO51 - response: DVWD.RvrtTms.AI105 - step_number: 6 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DVWD2.EcpRef.AO52 - response: DVWD2.EcpRef.AI106 - step_number: 7 - - description: Set the Dynamic Volt-Watt Gradient - fcodes: - - direct_operate - optional: I - point_name: DVWD.DynVWGra.AO53 - response: DVWD.DynVWGra.AI110 - step_number: 8 - - description: Set the Dynamic Volt-Watt Filter Time - fcodes: - - direct_operate - optional: I - point_name: DVWD.VWFilTms.AO54 - response: DVWD.VWFilTms.AI111 - step_number: 9 - - description: Set the Dynamic Volt-Watt Lower Deadband - fcodes: - - direct_operate - optional: I - point_name: DVWD.DbVWLo.AO55 - response: DVWD.DbVWLo.AI112 - step_number: 10 - - description: Set the Dynamic Volt-Watt Upper Deadband - fcodes: - - direct_operate - optional: I - point_name: DVWD.DbVWHi.AO56 - response: DVWD.DbVWHi.AI113 - step_number: 11 - - action: publish - description: Enable Dynamic Volt-Watt mode - fcodes: - - select - - operate - optional: M - point_name: DVWD.ModEna.BO15 - response: DVWD.ModEna.BI67 - step_number: 12 -- id: enable_active_power_limit_mode - name: Enable Active Power Limit Mode - ref: AN2018 Spec section 2.6.1 Table 39 - mode_types: - schedule: - - 12 - - 13 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWMX.ModPrio.AO82 - response: DWMX.ModPrio.AI142 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DWMX.WinTms.AO83 - response: DWMX.WinTms.AI143 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DWMX.RmpTms.AO84 - response: DWMX.RmpTms.AI144 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWMX.RvrtTms.AO85 - response: DWMX.RvrtTms.AI145 - step_number: 4 - - description: Identify the meter used to measure the active power. By default - this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DWMX.EcpRef.AO86 - response: DWMX.EcpRef.AI146 - step_number: 5 - - description: Retrieve Maximum Active Generation Power Capability - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.WMax.AI32 - step_number: 6 - - description: Retrieve Maximum Active Charging Power Capability - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.ChaWMax.AI33 - step_number: 7 - - description: Set maximum output in percent of nominal Watts (Charging) - fcodes: - - direct_operate - optional: M - point_name: DWMX.WLimPct.AO87 - response: DWMX.WLimPct.AI148 - step_number: 8 - - description: Set maximum output in percent of nominal Watts (Generating) - fcodes: - - direct_operate - optional: M - point_name: DWMN.WLimPct.AO88 - response: DWMN.WLimPct.AI149 - step_number: 9 - - action: publish - description: Enable Active Power Limit mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DWLM.ModEna.BO17 - response: DWLM.ModEna.BI69 - step_number: 10 -- id: enable_charge_discharge_storage_mode - name: Enable Charge/Discharge Storage Mode - ref: AN2018 Spec section 2.6.2 Table 41 - mode_types: - schedule: - - 14 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWGC.ModPrio.AO89 - response: DWGC.ModPrio.AI150 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DWGC.WinTms.AO90 - response: DWGC.WinTms.AI151 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DWGC.RmpTms.AO91 - response: DWGC.RmpTms.AI152 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWGC.RvrtTms.AO92 - response: DWGC.RvrtTms.AI153 - step_number: 4 - - description: Select whether to use Ramp Rates or Time Constants - fcodes: - - direct_operate - optional: I - point_name: DWGC.UseRmpRte.BO38 - response: DWGC.UseRmpRte.BI90 - step_number: 5 - - description: 'If DWGC.UseRmpRte = 0: Set Charge/Discharge Time Constant Ramp Up - Time' - fcodes: - - direct_operate - optional: O - point_name: DWGC.OpnLoop.AO94 - response: DWGC.OpnLoopMax.AI155 - step_number: 6 - - description: 'If DWGC.UseRmpRte = 0: Set Charge/Discharge Time Constant Ramp Down - Time' - fcodes: - - direct_operate - optional: O - point_name: DWGC.OpnLoop.AO95 - response: DWGC.OpnLoopMax.AI156 - step_number: 7 - - description: 'If DWGC.UseRmpRte = 1: Set Discharge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.DschRpuRte.AO96 - response: DWGC.RpuRte.AI157 - step_number: 8 - - description: 'If DWGC.UseRmpRte = 1: Set Discharge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.DschRpdRte.AO97 - response: DWGC.RpdRteMax.AI158 - step_number: 9 - - description: 'If DWGC.UseRmpRte = 1: Set Charge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.ChaRpuRte.AO98 - response: DWGC.RpuChaRte.AI159 - step_number: 10 - - description: 'If DWGC.UseRmpRte = 1: Set Charge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DWGC.ChaRpdRte.AO99 - response: DWGC.RpdChaRteMax.AI160 - step_number: 11 - - description: Set Minimum Reserve for Storage (percent of Battery Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DWGC.SocUseMinPct.AO100 - response: DWGC.SocUseMinPct.AI161 - step_number: 12 - - description: Set Maximum Reserve for Storage (percent of Battery Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DWGC.SocUseMaxPct.AO101 - response: DWGC.SocUseMaxPct.AI162 - step_number: 13 - - description: Set discharge/charge Active Power Target. Positive is discharging, - negative is charging. - fcodes: - - direct_operate - optional: M - point_name: DWGC.GnWPctSpt.AO93 - response: DWGC.GnWPctSpt.AI154 - step_number: 14 - - action: publish - description: Enable charge/discharge mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DWGC.ModEna.BO18 - response: DWGC.ModEna.BI70 - step_number: 15 -- id: enable_coordinated_charge_discharge_management_mode - name: Enable Coordinated Charge/Discharge Management Mode - ref: AN2018 Spec section 2.6.3 Table 42 - mode_types: - schedule: - - 15 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DTCD.ModPrio.AO102 - response: DTCD.ModPrio.AI163 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DTCD.WinTms.AO103 - response: DTCD.WinTms.AI164 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DTCD.RmpTms.AO104 - response: DTCD.RmpTms.AI165 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DTCD.RvrtTms.AO105 - response: DTCD.RvrtTms.AI166 - step_number: 4 - - description: Set the Target State of Charge, as a percentage of Usable Capacity - fcodes: - - direct_operate - optional: M - point_name: DTCD.SocUseTgtPct.AO106 - response: DTCD.SocUseTgtPct.AI167 - step_number: 5 - - description: Set the Target Date Charge Needed - fcodes: - - direct_operate - optional: M - point_name: DTCD.DateTgt.AO107 - response: DTCD.DateTgt.AI168 - step_number: 6 - - description: Set the Target Time Charge Needed (milliseconds since midnight) - fcodes: - - direct_operate - optional: M - point_name: DTCD.DateTgtTms.AO108 - response: DTCD.DateTgtTms.AI169 - step_number: 7 - - action: publish - description: Enable coordinated charge/discharge mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DWGC.ModEna.BO18 - response: DTCD.ModEna.BI71 - step_number: 8 -- id: enable_active_power_response_modes - name: Enable Active Power Response Modes - ref: AN2018 Spec section 2.6.4 Table 43 - mode_types: - schedule: - - 16 - - 17 - - 18 - steps: - - description: 'Set the priority of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.ModPrio.AO115 - response: DPKP.ModPrio.AI176 - step_number: 1 - - description: 'Set the priority of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.ModPrio.AO124 - response: DGFL.ModPrio.AI187 - step_number: 2 - - description: 'Set the priority of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.ModPrio.AO133 - response: DLFL.ModPrio.AI198 - step_number: 3 - - description: 'Set enabling time window of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.WinTms.AO116 - response: DPKP.WinTms.AI177 - step_number: 4 - - description: 'Set enabling time window of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.WinTms.AO125 - response: DGFL.WinTms.AI188 - step_number: 5 - - description: 'Set enabling time window of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.WinTms.AO134 - response: DLFL.WinTms.AI199 - step_number: 6 - - description: 'Set enabling ramp time of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RmpTms.AO117 - response: DPKP.RmpTms.AI178 - step_number: 7 - - description: 'Set enabling ramp time of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RmpTms.AO126 - response: DGFL.RmpTms.AI189 - step_number: 8 - - description: 'Set enabling ramp time of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RmpTms.AO135 - response: DLFL.RmpTms.AI200 - step_number: 9 - - description: 'Set reversion timeout period of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RvrtTms.AO118 - response: DPKP.RvrtTms.AI179 - step_number: 10 - - description: 'Set reversion timeout period of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RvrtTms.AO127 - response: DGFL.RvrtTms.AI190 - step_number: 11 - - description: 'Set reversion timeout period of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RvrtTms.AO136 - response: DLFL.RvrtTms.AI201 - step_number: 12 - - description: 'Identify the meter used to measure the Reference Power Input of - mode #1. By default this is the System Meter (ID = 0)' - fcodes: - - direct_operate - optional: I - point_name: DPKP.EcpRef.AO119 - response: DPKP.EcpRef.AI180 - step_number: 13 - - description: 'Identify the meter used to measure the Reference Power Input of - mode #2. By default this is the System Meter (ID = 0)' - fcodes: - - direct_operate - optional: I - point_name: DGFL.EcpRef.AO128 - response: DGFL.EcpRef.AI191 - step_number: 14 - - description: 'Identify the meter used to measure the Reference Power Input of - mode #3. By default this is the System Meter (ID = 0)' - fcodes: - - direct_operate - optional: I - point_name: DLFL.EcpRef.AO137 - response: DLFL.EcpRef.AI202 - step_number: 15 - - description: 'Set the power threshold for activating mode #1' - fcodes: - - direct_operate - optional: M - point_name: DPKP.PkPwrWLim.AO120 - response: DPKP.PkPwrWLim.AI182 - step_number: 16 - - description: 'Set the power threshold for activating mode #2' - fcodes: - - direct_operate - optional: M - point_name: DGFL.PkPwrWLim.AO129 - response: DGFL.PkPwrWLim.AI193 - step_number: 17 - - description: 'Set the power threshold for activating mode #3' - fcodes: - - direct_operate - optional: M - point_name: DLFL.PkPwrWLim.AO138 - response: DLFL.PkPwrWLim.AI204 - step_number: 18 - - description: 'Set the ratio used to calculate the output power from the measured - power of mode #1' - fcodes: - - direct_operate - optional: M - point_name: DPKP.PkPwrFolPct.AO121 - response: DPKP.PkPwrFolPct.AI183 - step_number: 19 - - description: 'Set the ratio used to calculate the output power from the measured - power of mode #2' - fcodes: - - direct_operate - optional: M - point_name: DGFL.PkPwrFolPct.AO130 - response: DGFL.PkPwrFolPct.AI194 - step_number: 20 - - description: 'Set the ratio used to calculate the output power from the measured - power of mode #3' - fcodes: - - direct_operate - optional: M - point_name: DLFL.PkPwrFolPct.AO139 - response: DLFL.PkPwrFolPct.AI205 - step_number: 21 - - description: 'Set the maximum ramp up rate of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RpuRte.AO122 - response: DPKP.RpuRte.AI184 - step_number: 22 - - description: 'Set the maximum ramp up rate of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RpuRte.AO131 - response: DGFL.RpuRte.AI195 - step_number: 23 - - description: 'Set the maximum ramp up rate of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RpuRte.AO140 - response: DLFL.RpuRte.AI206 - step_number: 24 - - description: 'Set the maximum ramp down rate of mode #1' - fcodes: - - direct_operate - optional: I - point_name: DPKP.RpdRte.AO123 - response: DPKP.RpdRte.AI185 - step_number: 25 - - description: 'Set the maximum ramp down rate of mode #2' - fcodes: - - direct_operate - optional: I - point_name: DGFL.RpdRte.AO132 - response: DGFL.RpdRte.AI196 - step_number: 26 - - description: 'Set the maximum ramp down rate of mode #3' - fcodes: - - direct_operate - optional: I - point_name: DLFL.RpdRte.AO141 - response: DLFL.RpdRte.AI207 - step_number: 27 - - description: 'Enable the active response mode #1' - fcodes: - - select - - operate - optional: M - point_name: DPKP.ModEna.BO20 - response: DPKP.ModEna.BI72 - step_number: 28 - - description: 'Enable the active response mode #2' - fcodes: - - select - - operate - optional: M - point_name: DGFL.ModEna.BO21 - response: DGFL.ModEna.BI73 - step_number: 29 - - action: publish - description: 'Enable the active response mode #3' - fcodes: - - select - - operate - optional: M - point_name: DLFL.ModEna.BO22 - response: DLFL.ModEna.BI74 - step_number: 30 -- id: perform_automatic_generation_control_mode - name: Perform Automatic Generation Control Mode - ref: AN2018 Spec section 2.6.5 Table 45 - mode_types: - schedule: - - 19 - steps: - - description: Set priority of the mode - fcodes: - - direct_operate - optional: I - point_name: DAGC.ModPrio.AO142 - response: DAGC.ModPrio.AI209 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DAGC.WinTms.AO143 - response: DAGC.WinTms.AI210 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DAGC.RmpTms.AO144 - response: DAGC.RmpTms.AI211 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DAGC.RvrtTms.AO145 - response: DAGC.RvrtTms.AI212 - step_number: 4 - - description: Select whether to use Ramp Rates or Time Constants - fcodes: - - direct_operate - optional: I - point_name: DAGC.UseRmpRte.BO39 - response: DAGC.UseRmpRte.BI91 - step_number: 5 - - description: 'If DAGC.UseRmpRte = 0: Set AGC Ramp Time Constant Up Time' - fcodes: - - direct_operate - optional: O - point_name: DAGC.OpnLoop.AO147 - response: DAGC.RmpUpTms.AI214 - step_number: 6 - - description: 'If DAGC.UseRmpRte = 0: Set AGC Ramp Time Constant Down Time' - fcodes: - - direct_operate - optional: O - point_name: DAGC.OpnLoop.AO148 - response: DAGC.RmpDnTms.AI215 - step_number: 7 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Discharge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.DschRpuRte.AO149 - response: DAGC.RpuRte.AI216 - step_number: 8 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Discharge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.DschRpdRte.AO150 - response: DAGC.RpdRte.AI217 - step_number: 9 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Charge Ramp Up Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.ChaRpuRte.AO151 - response: DAGC.RpuChaRte.AI218 - step_number: 10 - - description: 'If DAGC.UseRmpRte = 1: Set AGC Charge Ramp Down Rate' - fcodes: - - direct_operate - optional: O - point_name: DAGC.ChaRpdRte.AO152 - response: DAGC.RpdChaRte.AI219 - step_number: 11 - - description: Set Minimum Usable State of Charge (percent of Usable Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DAGC.SocUseMinPct.AO153 - response: DAGC.SocUseMinPct.AI220 - step_number: 12 - - description: Set Maximum Usable State of Charge (percent of Usable Capacity Rating) - fcodes: - - direct_operate - optional: I - point_name: DAGC.SocUseMaxPct.AO154 - response: DAGC.SocUseMaxPct.AI221 - step_number: 13 - - description: Set the Active Power Target (in Watts) Positive is discharging, negative - is charging. - fcodes: - - direct_operate - optional: M - point_name: DAGC.GnWSpt.AO146 - response: DAGC.GnWSpt.AI213 - step_number: 14 - - description: Enable AGC mode and receive response. - fcodes: - - select - - operate - optional: M - point_name: DAGC.ModEna.BO23 - response: DAGC.ModEna.BI75 - step_number: 15 - - action: publish - description: Once the mode is enabled, periodically update the Active Power Target. - fcodes: - - direct_operate - optional: M - point_name: DAGC.GnWSpt.AO146 - response: DAGC.GnWSpt.AI213 - step_number: 16 - - description: Read the predicted State of Charge - fcodes: - - read - optional: O - point_name: n/a - response: DAGC.SocExpc.AI224 - step_number: 17 -- id: enable_active_power_smoothing - name: Enable Active Power Smoothing - ref: AN2018 Spec section 2.6.6 Table 46 - mode_types: - schedule: - - 20 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWSM.ModPrio.AO155 - response: DWSM.ModPrio.AI227 - step_number: 1 - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DWSM.WinTms.AO156 - response: DWSM.WinTms.AI228 - step_number: 2 - - description: Set ramp time - fcodes: - - direct_operate - optional: I - point_name: DWSM.RmpTms.AO157 - response: DWSM.RmpTms.AI229 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWSM.RvrtTms.AO158 - response: DWSM.RvrtTms.AI230 - step_number: 4 - - description: Identify the meter used to measure the Reference Power Input. By - default this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DWSM.EcpRef.AO159 - response: DWSM.EcpRef.AI231 - step_number: 5 - - description: Set the Active Power Smoothing Gradient - fcodes: - - direct_operate - optional: I - point_name: DWSM.WSmthGra.AO160 - response: DWSM.WSmthGra.AI233 - step_number: 6 - - description: Set the Active Power Smoothing Lower Limit - fcodes: - - direct_operate - optional: I - point_name: DWSM.WSmthLoLim.AO161 - response: DWSM.WSmthLoLim.AI234 - step_number: 7 - - description: Set the Active Power Smoothing Upper Limit - fcodes: - - direct_operate - optional: I - point_name: DWSM.WSmthHiLim.AO162 - response: DWSM.WSmthHiLim.AI235 - step_number: 8 - - description: Set the Active Power Smoothing Filter Time - fcodes: - - direct_operate - optional: I - point_name: DWSM.FilTms.AO163 - response: DWSM.FilTms.AI236 - step_number: 9 - - description: Set the Discharge Ramp Up Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.DschRpuRte.AO164 - response: DWSM.RpuRte.AI237 - step_number: 10 - - description: Set the Discharge Ramp Down Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.DschRpdRte.AO165 - response: DWSM.RpdRte.AI238 - step_number: 11 - - description: Set the Charge Ramp Up Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.ChaRpuRte.AO166 - response: DWSM.RpuChaRte.AI239 - step_number: 12 - - description: Set the Charge Ramp Down Rate - fcodes: - - direct_operate - optional: I - point_name: DWSM.ChaRpdRte.AO167 - response: DWSM.RpdChaRte.AI240 - step_number: 13 - - action: publish - description: Enable Active Power Smoothing Mode - fcodes: - - select - - operate - optional: M - point_name: DWSM.ModEna.BO24 - response: DWSM.ModEna.BI76 - step_number: 14 -- id: enable_volt-watt_curve - mode_types: - curve: - - 5 - schedule: - - 21 - name: Enable Volt-Watt Curve - ref: AN2018 Spec section 2.6.7 Table 47 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVWC.ModPrio.AO168 - response: DVWC.ModPrio.AI242 - step_number: 1 - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DVWC.WinTms.AO169 - response: DVWC.WinTms.AI243 - step_number: 2 - - description: Set ramp time - fcodes: - - direct_operate - optional: I - point_name: DVWC.RmpTms.AO170 - response: DVWC.RmpTms.AI244 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVWC.RvrtTms.AO171 - response: DVWC.RvrtTms.AI245 - step_number: 4 - - description: Identify the meter used to measure the Voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DVWC.EcpRef.AO172 - response: DVWC.EcpRef.AI246 - step_number: 5 - - description: Set the reference voltage if it has not already been set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 6 - - description: Set the reference voltage offset if it has not already been set - fcodes: - - direct_operate - optional: I - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 7 - - description: Identify the index of the curve being used - fcodes: - - direct_operate - func_ref: curve - optional: M - point_name: DVWC.VWCrv.AO173 - response: DVWC.VWCrv.AI248 - step_number: 8 - - action: publish - description: Enable the Volt-Watt Mode - fcodes: - - select - - operate - optional: M - point_name: DVWC.ModEna.BO25 - response: DVWC.ModEna.BI77 - step_number: 9 - - description: Read the maximum active power the outstation will attempt to generate - or absorb based on the voltage and the curve in use. - fcodes: - - read - optional: O - point_name: n/a - response: DVWC.ReqWLim.AI249 - step_number: 10 - - description: Read the actual active power produced or absorbed - fcodes: - - read - optional: O - point_name: n/a - response: MMXU.TotW.AI537 - step_number: 11 -- id: enable_frequency-watt_curve_mode - mode_types: - curve: - - 3 - schedule: - - 22 - - 23 - - 24 - name: Enable Frequency-Watt Curve Mode - ref: AN2018 Spec section 2.6.8 Table 48 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DHFW.ModPrio.AO181 - response: DHFW.ModPrio.AI257 - step_number: 1 - - description: Set time window - fcodes: - - direct_operate - optional: I - point_name: DHFW.WinTms.AO182 - response: DHFW.WinTms.AI258 - step_number: 2 - - description: Set ramp time - fcodes: - - direct_operate - optional: I - point_name: DHFW.RvrtTms.AO184 - response: DHFW.RmpTms.AI259 - step_number: 3 - - description: Set reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DHFW.RmpTms.AO183 - response: DHFW.RvrtTms.AI260 - step_number: 4 - - description: Identify the meter used to measure the Frequency. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DHFW.EcpRef.AO185 - response: DHFW.EcpRef.AI261 - step_number: 5 - - description: Set the Nominal Grid Frequency if it is not already set - fcodes: - - direct_operate - optional: I - point_name: DECP.EcpNomHz.AO2 - response: DECP.EcpNomHz.AI31 - step_number: 6 - - description: Set the starting delays - fcodes: - - direct_operate - optional: I - point_name: DHFW.ActStrDlTmms.AO189 - response: DHFW.ActStrDlTmms.AI266 - step_number: 7 - - description: Set the stopping delays - fcodes: - - direct_operate - optional: I - point_name: DHFW.ActStopDlTmms.AO190 - response: DHFW.ActStopDlTmms.AI267 - step_number: 8 - - description: Set the frequency-watt curve ramp up time constant for the output - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoopMax.AO191 - response: DHFW.OpnLoopMax.AI268 - step_number: 9 - - description: Set the frequency-watt curve ramp down time constant for the output - fcodes: - - direct_operate - optional: I - point_name: DHFW.OpnLoopMax.AO192 - response: DHFW.OpnLoopMax.AI269 - step_number: 10 - - description: Set the frequency-watt curve discharge ramp up rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpuRte.AO193 - response: DHFW.RpuRte.AI270 - step_number: 11 - - description: Set the frequency-watt curve discharge ramp down rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpdRte.AO194 - response: DHFW.RpdRte.AI271 - step_number: 12 - - description: Set the frequency-watt curve charge ramp up rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpuChaRte.AO195 - response: DHFW.RpuChaRte.AI272 - step_number: 13 - - description: Set the frequency-watt curve charge ramp down rate - fcodes: - - direct_operate - optional: I - point_name: DHFW.RpdChaRte.AO196 - response: DHFW.RpdChaRte.AI273 - step_number: 14 - - description: Identify the index of the main curve being used - fcodes: - - direct_operate - func_ref: curve - optional: I - point_name: DHFW.HzWCrv.AO186 - response: DHFW.HzWCrv.AI263 - step_number: 15 - - description: Identify the index of the high frequency hyteresis curve being used - fcodes: - - direct_operate - func_ref: curve - optional: I - point_name: DHFW.HysCrv.AO187 - response: DHFW.HysCrv.AI264 - step_number: 16 - - description: Identify the index of the low frequency hyteresis curve being used - fcodes: - - direct_operate - func_ref: curve - optional: I - point_name: DLFW.HysCrv.AO188 - response: DLFW.HysCrv.AI265 - step_number: 17 - - description: Set the minimum state of charge in which this mode shall operate - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMinPct.AO197 - response: DHFW.SocUseMinPct.AI275 - step_number: 18 - - description: Set the maximum state of charge in which this mode shall operate - fcodes: - - direct_operate - optional: I - point_name: DHFW.SocUseMaxPct.AO198 - response: DHFW.SocUseMaxPct.AI276 - step_number: 19 - - description: Choose whether to use hysteresis - fcodes: - - direct_operate - optional: I - point_name: DLFW.HysEna.BO36 - response: DLFW.HysEna.BI88 - step_number: 20 - - description: Choose whether to snapshot power - fcodes: - - direct_operate - optional: I - point_name: DLFW.SnptEna.BO37 - response: DLFW.SnptEna.BI89 - step_number: 21 - - action: publish - description: Enable the Frequency-Watt Curve Mode - fcodes: - - select - - operate - optional: M - point_name: DHFW.ModEna.BO26 - response: DHFW.ModEna.BI78 - step_number: 22 -- id: set_constant_var_output - name: Set Constant Var Output - ref: AN2018 Spec section 2.7.1 Table 50 - mode_types: - schedule: - - 25 - steps: - - description: Set the priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVAR.ModPrio.AO199 - response: DVAR.ModPrio.AI277 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DVAR.WinTms.AO200 - response: DVAR.WinTms.AI278 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DVAR.RmpTms.AO201 - response: DVAR.RmpTms.AI279 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVAR.RvrtTms.AO202 - response: DVAR.RvrtTms.AI280 - step_number: 4 - - description: Set the ramp up Time Constants - fcodes: - - direct_operate - optional: I - point_name: DVAR.OpnLoopMax.AO204 - response: DVAR.OpnLoopMax.AI282 - step_number: 5 - - description: Set the ramp down Time Constants - fcodes: - - direct_operate - optional: I - point_name: DVAR.OpnLoopMax.AO205 - response: DVAR.OpnLoopMax.AI283 - step_number: 6 - - description: Choose whether the time constants represent 3-Tau limits or Open - Loop Response Times - fcodes: - - direct_operate - optional: I - point_name: DSTO.OpnLoopTau.BO9 - response: DSTO.OpnLoopTau.BI28 - step_number: 7 - - description: If Open Loop Response Times are selected, choose the percentage of - final output represented by the time constant (e.g. 90% or 95%) - fcodes: - - direct_operate - optional: I - point_name: DSTO.OpnLoopPct.AO3 - response: DGEN.OpnLoopPct.AI40 - step_number: 8 - - description: Select the meaning of the Constant VArs Reactive Power Target - fcodes: - - direct_operate - optional: I - point_name: DSTO.VArRef.AO5 - response: DGEN.VArSetRef.AI42 - step_number: 9 - - description: 'If DSTO.VArRef = 1: Read percent of maximum active generation power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.WMax.AI32 - step_number: 10 - - description: 'If DSTO.VArRef = 1: Read percent of maximum active charging power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.ChaWMax.AI33 - step_number: 11 - - description: 'If DSTO.VArRef = 2: Read percent of maximum reactive injection power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.IvarMax.AI34 - step_number: 12 - - description: 'If DSTO.VArRef = 2: Read percent of maximum reactive absorption - power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.AvarMax.AI35 - step_number: 13 - - description: 'If DSTO.VArRef = 3: Read percent of system reactive injection power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.AvarAvl.AI45 - step_number: 14 - - description: 'If DSTO.VArRef = 3: Read percent of system reactive absorption power' - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.IvarAvl.AI46 - step_number: 15 - - description: Set the Constant VArs Reactive Power Target in percent - fcodes: - - direct_operate - optional: M - point_name: DVAR.VArTgtPct.AO203 - response: DVAR.VArTgtPct.AI281 - step_number: 16 - - action: publish - description: Enable Constant VArs mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DVAR.ModEna.BO27 - response: DVAR.ModEna.BI79 - step_number: 17 -- id: set_a_fixed_power_factor - name: Set a Fixed Power Factor - ref: AN2018 Spec section 2.7.2 Table 52 - mode_types: - schedule: - - 26 - steps: - - description: Set the priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DFPF.ModPrio.AO206 - response: DFPF.ModPrio.AI284 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DFPF.WinTms.AO207 - response: DFPF.WinTms.AI285 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DFPF.RmpTms.AO208 - response: DFPF.RmpTms.AI286 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DFPF.RvrtTms.AO209 - response: DFPF.RvrtTms.AI287 - step_number: 4 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when discharging / generating - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFGnExtSet.BO10 - response: DFPF.PFGnExtSet.BI29 - step_number: 5 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when charging - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFLodExtSet.BO11 - response: DFPF.PFLodExtSet.BI30 - step_number: 6 - - description: Set Fixed Power Factor Setpoint to use when generating / discharging - fcodes: - - direct_operate - optional: M - point_name: DFPF.PFGnTgt.AO210 - response: DFPF.PFGnTgt.AI288 - step_number: 7 - - description: Set Fixed Power Factor Setpoint to use when charging - fcodes: - - direct_operate - optional: M - point_name: DFPF.PFLodTgt.AO211 - response: DFPF.PFLodTgt.AI289 - step_number: 8 - - action: publish - description: Enable fixed power factor mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DFPF.ModEna.BO28 - response: DFPF.BI47 - step_number: 9 -- id: change_and_select_volt-var_control_mode - mode_types: - curve: - - 2 - schedule: - - 27 - name: Change and Select Volt-Var Control Mode - ref: AN2018 Spec section 2.7.3 Table 54 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DVVR.ModPrio.AO212 - response: DVVR.ModPrio.AI290 - step_number: 1 - - description: Set the enabling time window - fcodes: - - direct_operate - optional: I - point_name: DVVR.WinTms.AO213 - response: DVVR.WinTms.AI291 - step_number: 2 - - description: Set the enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DVVR.RmpTms.AO214 - response: DVVR.RmpTms.AI292 - step_number: 3 - - description: Set the enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DVVR.RvrtTms.AO215 - response: DVVR.RvrtTms.AI293 - step_number: 4 - - description: Identify the meter used to measure the voltage. By default this - is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DVVR.EcpRef.AO216 - response: DVVR.EcpRef.AI294 - step_number: 5 - - description: If using a fixed Voltage reference, set the reference voltage if - it has not already been set - fcodes: - - direct_operate - optional: O - point_name: DECP.VRef.AO0 - response: DECP.VRef.AI29 - step_number: 6 - - description: If using a fixed Voltage reference, set the reference voltage offset - if it has not already been set - fcodes: - - direct_operate - optional: O - point_name: DECP.VRefOfs.AO1 - response: DECP.VRefOfs.AI30 - step_number: 7 - - description: If autonomously adjusting the Voltage reference, set the time constant - for the lowpass filter - fcodes: - - direct_operate - optional: O - point_name: DVVR.VRefTmms.AO220 - response: DVVR.VRefTmms.AI300 - step_number: 8 - - description: If autonomously adjusting the Voltage reference, enable autonomous - adjustment - fcodes: - - direct_operate - optional: O - point_name: DVVR.VRefAdjEna.BO41 - response: DVVR.VRefAdjEna.BI93 - step_number: 9 - - description: Set the ramp up time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DVVR.OpnLoopMax.AO218 - response: DVVR.OpnLoopMax.AI298 - step_number: 10 - - description: Set the ramp down time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DVVR.OpnLoopMax.AO219 - response: DVVR.OpnLoopMax.AI299 - step_number: 11 - - description: Identify the index of the curve being used - fcodes: - - direct_operate - func_ref: curve - optional: M - point_name: DVVR.VVArCrv.AO217 - response: DVVR.VVArCrv.AI297 - step_number: 12 - - action: publish - description: Enable the Volt-VAr Control Mode - fcodes: - - select - - operate - optional: M - point_name: DVVC.ModEna.BO29 - response: DVVC.BI48 - step_number: 13 - - description: Read the adjusted reference voltage, if it is not fixed - fcodes: - - read - optional: O - point_name: n/a - response: DVVR.VRefSet.AI296 - step_number: 14 - - description: Read the measured Voltage - fcodes: - - read - optional: O - point_name: n/a - response: MMXN.Vol.AI295 - step_number: 15 - - description: Read the attempted VArs - fcodes: - - read - optional: O - point_name: n/a - response: DVVR.ReqVAr.AI301 - step_number: 16 - - description: Read the actual VArs (if using system meter) - fcodes: - - read - optional: O - point_name: n/a - response: MMXU.TotVAr.AI541 - step_number: 17 -- id: enable_watt-var_power_mode - mode_types: - curve: - - 4 - schedule: - - 28 - name: Enable Watt-Var Power Mode - ref: AN2018 Spec section 2.7.4 Table 55 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DWVR.ModPrio.AO221 - response: DWVR.ModPrio.AI302 - step_number: 1 - - description: Set the enabling time window - fcodes: - - direct_operate - optional: I - point_name: DWVR.WinTms.AO222 - response: DWVR.WinTms.AI303 - step_number: 2 - - description: Set the enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DWVR.RmpTms.AO223 - response: DWVR.RmpTms.AI304 - step_number: 3 - - description: Set the enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DWVR.RvrtTms.AO224 - response: DWVR.RvrtTms.AI305 - step_number: 4 - - description: Identify the meter used to measure the active power. By default - this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DWVR.EcpRef.AO225 - response: DWVR.EcpRef.AI306 - step_number: 5 - - description: Read the maximum generation power used as the reference for percent - Watts - fcodes: - - read - - response - optional: O - point_name: n/a - response: DGEN.WMax.AI32 - step_number: 6 - - description: Read the maximum charging power used as the reference for percent - Watts - fcodes: - - read - - response - optional: O - point_name: n/a - response: DSTO.ChaWMax.AI33 - step_number: 7 - - description: Set the ramp up time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DWVR.OpnLoopMax.AO227 - response: DWVR.OpnLoopMax.AI309 - step_number: 8 - - description: Set the ramp down time constant for the output of the curve - fcodes: - - direct_operate - optional: I - point_name: DWVR.OpnLoopMax.AO228 - response: DWVR.OpnLoopMax.AI310 - step_number: 9 - - description: Identify the index of the curve being used - fcodes: - - direct_operate - func_ref: curve - optional: M - point_name: DWVR.WVArCrv.AO226 - response: DWVR.WVArCrv.AI308 - step_number: 10 - - action: publish - description: Enable the Watt-VAr Power Mode - fcodes: - - select - - operate - optional: M - point_name: DWVR.ModEna.BO30 - response: DWVR.BI49 - step_number: 11 -- id: enable_power_factor_correction_mode - name: Enable Power Factor Correction Mode - ref: AN2018 Spec section 2.7.5 Table 56 - mode_types: - schedule: - - 29 - steps: - - description: Set the priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DPFC.ModPrio.AO229 - response: DPFC.ModPrio.AI312 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DPFC.WinTms.AO230 - response: DPFC.WinTms.AI313 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DPFC.RmpRte.AO231 - response: DPFC.RmpTms.AI314 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DPFC.RvrtTms.AO232 - response: DPFC.RvrtTms.AI315 - step_number: 4 - - description: Identify the meter used to measure the active power. By default - this is the System Meter (ID = 0) - fcodes: - - direct_operate - optional: I - point_name: DPFC.EcpRef.AO233 - response: DPFC.EcpRef.AI316 - step_number: 5 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when discharging - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFGnExtSet.BO10 - response: DFPF.PFGnExtSet.BI29 - step_number: 6 - - description: Set the requirement for whether to inject or absorb VARs (PFExt) - when charging - fcodes: - - direct_operate - optional: I - point_name: DFPF.PFLodExtSet.BO11 - response: DFPF.PFLodExtSet.BI30 - step_number: 7 - - description: Set the Average PF Target - fcodes: - - direct_operate - optional: M - point_name: DPFC.PFTrg.AO234 - response: MMXU.TotPF.AI317 - step_number: 8 - - description: Set the Lower PF Limit - fcodes: - - direct_operate - optional: M - point_name: DPFC.PFCorRef.rangeC.AO235 - response: DPFC.PFTrg.AI318 - step_number: 9 - - description: Set the Upper PF Limit - fcodes: - - direct_operate - optional: M - point_name: DPFC.PFCorRef.rangeC.AO236 - response: DPFC.PFCorRef.rangeC.AI319 - step_number: 10 - - action: publish - description: Enable Power Factor Correction Mode - fcodes: - - select - - operate - optional: M - point_name: DPFC.ModEna.BO31 - response: DPFC.ModEna.BI83 - step_number: 11 -- id: signal_a_price_change - name: Signal a Price Change - ref: AN2018 Spec section 2.8 Table 57 - steps: - - description: Set priority of this mode - fcodes: - - direct_operate - optional: I - point_name: DPRG.ModPrio.AO237 - response: DPRG.ModPrio.AI321 - step_number: 1 - - description: Set enabling time window - fcodes: - - direct_operate - optional: I - point_name: DPRG.WinTms.AO238 - response: DPRG.WinTms.AI322 - step_number: 2 - - description: Set enabling ramp time - fcodes: - - direct_operate - optional: I - point_name: DPRG.RmpTms.AO239 - response: DPRG.RmpTms.AI323 - step_number: 3 - - description: Set enabling reversion timeout - fcodes: - - direct_operate - optional: I - point_name: DPRG.RvrtTms.AO240 - response: DPRG.RvrtTms.AI324 - step_number: 4 - - description: Set pricing mode time constant for ramping up - fcodes: - - direct_operate - optional: I - point_name: DPRG.OpnLoopMax.AO242 - response: DPRG.OpnLoopMax.AI326 - step_number: 5 - - description: Set pricing mode time constant for ramping down - fcodes: - - direct_operate - optional: I - point_name: DPRG.OpnLoopMax.AO243 - response: DPRG.OpnLoopMax.AI327 - step_number: 6 - - description: Set pricing signal and receive response - fcodes: - - select - - operate - optional: M - point_name: DPRG.PrcRef.AO241 - response: DPRG.PrcRef.AI325 - step_number: 7 - - action: publish - description: Enable pricing signal mode and receive response - fcodes: - - select - - operate - optional: M - point_name: DPRG.ModEna.BO32 - response: DPRG.ModEna.BI84 - step_number: 8 -- id: enable_schedules - name: Enable Schedules - ref: AN2018 Spec section 2.9 Table 59 - steps: - - description: Enable the Schedule by changing its state to ready - fcodes: - - select - - operate - optional: M - point_name: FSCHxx.Mod.BO42 - response: FSCH.SchdSt.3.BI108 - step_number: 1 - - description: Select shedule index - fcodes: - - direct_operate - func_ref: schedule - optional: M - point_name: FSCC.Schd.AO461 - response: FSCC.Schd.AI570 - step_number: 2 - - description: Check that outstation validates the selected schedule - fcodes: - - read - optional: O - point_name: n/a - response: FSCH.SchdSt.2.BI109 - step_number: 3 - - description: Set selected schedule repeat weekly Sunday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO43 - response: FSCHxx.SchdReuse.BI110 - step_number: 4 - - description: Set selected schedule repeat weekly Monday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO44 - response: FSCHxx.SchdReuse.BI111 - step_number: 5 - - description: Set selected schedule repeat weekly Tuesday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO45 - response: FSCHxx.SchdReuse.BI112 - step_number: 6 - - description: Set selected schedule repeat weekly Wednesday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO46 - response: FSCHxx.SchdReuse.BI113 - step_number: 7 - - description: Set selected schedule repeat weekly Thursday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO47 - response: FSCHxx.SchdReuse.BI114 - step_number: 8 - - description: Set selected schedule repeat weekly Friday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO48 - response: FSCHxx.SchdReuse.BI115 - step_number: 9 - - action: publish - description: Set selected schedule repeat weekly Saturday - fcodes: - - select - - operate - optional: I - point_name: FSCHxx.SchdReuse.BO49 - response: FSCHxx.SchdReuse.BI116 - step_number: 10 - - description: Be notified when the schedule is running - fcodes: - - read - optional: O - point_name: n/a - response: FSCH1.SchdSt.AI579 - step_number: 11 -- id: curve - name: Curve - ref: AN2018 Spec Curve Definition - steps: - - description: Select which curve to edit - fcodes: - - direct_operate - optional: M - point_name: DGSMn.InCrv.AO244 - response: DGSMn.InCrv.AI328 - step_number: 1 - - description: Specify the Curve Mode Type - fcodes: - - direct_operate - optional: M - point_name: DGSMn.ModTyp.AO245 - response: DGSMn.ModTyp.AI329 - step_number: 2 - - description: Specify that the Independent (X-Value) units for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.IndpUnits.AO247 - response: FMARn.IndpUnits.AI331 - step_number: 3 - - description: Specify the Dependent (Y-Value) units for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.DepRef.AO248 - response: FMARn.DepRef.AI332 - step_number: 4 - - description: Set X-Value and Y-Values pairs for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.PairArr.CrvPts.AO249 - response: FMARn.PairArr.CrvPts.AI333 - step_number: 5 - - action: publish - description: Set number of points used for the curve - fcodes: - - direct_operate - optional: M - point_name: FMARn.PairArr.NumPts.AO246 - response: FMARn.PairArr.NumPts.AI330 - step_number: 6 -- id: schedule - name: Schedule - ref: AN2018 Spec Schedule Definition - steps: - - description: Select which schedule to edit. This is the index of the schedule, - not its identity. The indexes shall be the monotonically increasing integers - 12, 13, 14 .etc. while the curve identities may be any unique number. - fcodes: - - direct_operate - optional: M - point_name: FSCC.Schd.AO461 - response: FSCC.Schd.AI570 - step_number: 1 - - description: Set the identity of the schedule to a unique number - fcodes: - - direct_operate - optional: M - point_name: FSCC.Schd.AO462 - response: FSCC.Schd.AI571 - step_number: 2 - - description: Set the priority for the schedule - fcodes: - - direct_operate - optional: M - point_name: FSCH1.SchdPrio.AO463 - response: FSCH.SchdPrio.AI572 - step_number: 3 - - description: Set the meaning of the Y-values of the schedule, i.e. the schedule - type. Refer to Table 58. - fcodes: - - direct_operate - optional: M - point_name: FSCH.SchdVal.valEq.AO464 - response: AI573 - step_number: 4 - - description: Set the date for the schedule to start - fcodes: - - direct_operate - optional: M - point_name: FSCH.StrTm.AO465 - response: FSCH.StrTm.AI574 - step_number: 5 - - description: Set the time for the schedule to start - fcodes: - - direct_operate - optional: M - point_name: FSCH.StrTm.AO466 - response: FSCH.StrTm.AI575 - step_number: 6 - - description: Set the repetition interval - fcodes: - - direct_operate - optional: M - point_name: FSCH.NxtStrTm.AO467 - response: FSCH.NxtStrTm.AI576 - step_number: 7 - - description: Set the units of the repetition interval - fcodes: - - direct_operate - optional: M - point_name: FSCH.SchdReuse.AO468 - response: FSCH.SchdReuse.AI577 - step_number: 8 - - description: Set the Time Offset (X-Values) and Schedule Value (Y-Values) for - each schedule point - fcodes: - - direct_operate - optional: M - point_name: FSCHn.SchdEntr.AO470 - response: FSCHn.SchdEntr.AI581 - step_number: 9 - - action: publish - description: Set the number of points used for the schedule. - fcodes: - - direct_operate - optional: M - point_name: FSCH.NumEntr.AO469 - response: FSCH.NumEntr.AI580 - step_number: 10 \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/data/mesa_points.config b/services/core/DNP3Agent/tests/data/mesa_points.config deleted file mode 100644 index 1ce6cdace7..0000000000 --- a/services/core/DNP3Agent/tests/data/mesa_points.config +++ /dev/null @@ -1,10276 +0,0 @@ -[ - { - "index": 0, - "description": "Reference Voltage", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VRef", - "name": "DECP.VRef.AO0" - }, - { - "index": 1, - "description": "Reference Voltage Offset", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "data_object": "VRefOfs", - "name": "DECP.VRefOfs.AO1" - }, - { - "index": 2, - "description": "Nominal Grid Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DECP", - "units": "Hz", - "minimum": 0, - "data_object": "EcpNomHz", - "name": "DECP.EcpNomHz.AO2" - }, - { - "index": 3, - "description": "Open Loop Response Time Percentage. Percent of target to reach within the open loop response time. Default is 90%.", - "data_type": "AO", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DSTO", - "units": "Percent", - "minimum": 0, - "data_object": "OpnLoopPct", - "name": "DSTO.OpnLoopPct.AO3" - }, - { - "index": 4, - "description": "Power Factor Sign convention", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "MMXU", - "units": "None", - "minimum": 1, - "data_object": "PFSign", - "allowed_values": { - "1": "IEC active power", - "2": "IEEE lead/lag" - }, - "type": "enumerated", - "name": "MMXU.PFSign.AO4" - }, - { - "index": 5, - "description": "Reference for Reactive Power Setpoints. Selects which setpoint is active. Default is <3>.", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 3, - "ln_class": "DSTO", - "units": "None (list)", - "minimum": 0, - "data_object": "VArRef", - "allowed_values": { - "0": "Not applicable / Unknown", - "1": "Percent of Maximum Active Power (WMax)", - "2": "Percent of Maximum Reactive Power (VArMax)", - "3": "Percent of Available Reactive Power (VArAval)" - }, - "type": "enumerated", - "name": "DSTO.VArRef.AO5" - }, - { - "index": 6, - "description": "DER Start (Return to Service) Voltage High Limit. Percent of Reference Voltage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 20000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VHiLim", - "name": "DCTE.VHiLim.AO6" - }, - { - "index": 7, - "description": "DER Start (Return to Service) Voltage Low Limit. Percent of Reference Voltage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 10000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VLoLim", - "name": "DCTE.VLoLim.AO7" - }, - { - "index": 8, - "description": "DER Start (Return to Service) Frequency High Limit", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzHiLim", - "name": "DCTE.HzHiLim.AO8" - }, - { - "index": 9, - "description": "DER Start (Return to Service) Frequency Low Limit", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzLoLim", - "name": "DCTE.HzLoLim.AO9" - }, - { - "index": 10, - "description": "DER Start (Return to Service) Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnDlyTmms", - "name": "DCTE.RtnDlyTmms.AO10" - }, - { - "index": 11, - "description": "DER Start (Return to Service) Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AO11" - }, - { - "index": 12, - "description": "DER Start (Return to Service) Ramp Up Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnRmpTmms", - "name": "DCTE.RtnRmpTmms.AO12" - }, - { - "index": 13, - "description": "DER Stop (Cease to Energize) Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AO13" - }, - { - "index": 14, - "description": "DER Stop (Cease to Energize) Ramp Down Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DCTE.RmpTms.AO14" - }, - { - "index": 15, - "description": "DER Stop (Cease to Energize) Reversion Timeout Period. Time to revert from the stopped state and return to service.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AO15" - }, - { - "index": 16, - "description": "Connect/Disconnect Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AO16" - }, - { - "index": 17, - "description": "Connect/Disconnect Reversion Timeout Period. Timeout (reversion time is for the Disconnect only).", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AO17" - }, - { - "index": 18, - "description": "Requested Settings Group", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO Enable Sensed Grid Config Detection)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP1.EcpIsldSt.AO18" - }, - { - "index": 19, - "description": "Settings Group Being Edited", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DRCC", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "name": "DRCC1.EcpIsldSt.AO19" - }, - { - "index": 20, - "description": "Freeze Counter Interval. Interval between freeze counter operations after the initial occurrence. A zero value means the free counter operation is not repeated.", - "data_type": "AO", - "minimum": 0, - "name": "AO20" - }, - { - "index": 21, - "description": "Freeze Counter Interval Units. Units of the interval between freeze counter operations.", - "data_type": "AO", - "maximum": 9, - "minimum": 0, - "units": "None (list)", - "allowed_values": { - "0": "The outstation does not repeat the action, regardless of the Interval count.", - "1": "Milliseconds - In this case the interval is always counted relative to the Start Time and is constant regardless of the clock time set at the Outstation.", - "2": "Seconds - At the same millisecond within the second that is specified in the Start Time.", - "3": "Minutes - At the same second and millisecond within the minute that is specified in the Start Time.", - "4": "Hours - At the same minute,second and B7millisecond within the hour that is specified in the Start Time.", - "5": "Days - At the same time of day that is specified in the Start Time.", - "6": "Weeks - On the same day of the week at the same time of day that is specified in the Start Time", - "7": "Months - On the same day of each month at the same time of day that is specified in the Start Time. If the Start Time falls on the 29th or greater day of the month, the outstation shall not perform the action in months that do not have such a day.", - "8": "Months on Same Day of Week from Start of Month - At the same time of the day on the same day of the week after the beginning of the month as the day specified in the Start Time. For instance, if the Start Time specifies the second Tuesday of February and the Interval Count is 2, the next action shall occur on the second Tuesday of April. In the same example, if the Interval Count is set to 12, this is the same as specifying, Every year on the second Tuesday in February. If the specified day does not occur in a given month when an action was scheduled to occur, the outstation shall not perform the action that month but shall perform it at the next valid scheduled time.", - "9": "Months on Same Day of Week from End of Month - The outstation shall interpret this setting as in <8>, but the day of the week shall be measured from the end of the month, e.g., the second-last Tuesday in February." - }, - "type": "enumerated", - "name": "AO21" - }, - { - "index": 22, - "description": "Low/High Voltage Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHVT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHVT.EcpRef.AO22" - }, - { - "index": 23, - "description": "Low/High Voltage Ride-Through High Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AO23" - }, - { - "index": 24, - "description": "Low/High Voltage Ride-Through Low Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AO24" - }, - { - "index": 25, - "description": "Low/High Voltage Ride-Through High Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AO25" - }, - { - "index": 26, - "description": "Low/High Voltage Ride-Through Low Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AO26" - }, - { - "index": 27, - "description": "Low/High Frequency Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHFT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFT.EcpRef.AO27" - }, - { - "index": 28, - "description": "Low/High Frequency Ride-Through High Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AO28" - }, - { - "index": 29, - "description": "Low/High Frequency Ride-Through Low Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AO29" - }, - { - "index": 30, - "description": "Low/High Frequency Ride-Through High Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is high.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AO30" - }, - { - "index": 31, - "description": "Low/High Frequency Ride-Through Low Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is low.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AO31" - }, - { - "index": 32, - "description": "Dynamic Reactive Current Support Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "ModPrio", - "name": "DRGS.ModPrio.AO32" - }, - { - "index": 33, - "description": "Dynamic Reactive Current Support Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DRGS.WinTms.AO33" - }, - { - "index": 34, - "description": "Dynamic Reactive Current Support Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DRGS.RmpTms.AO34" - }, - { - "index": 35, - "description": "Dynamic Reactive Current Support Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DRGS.RvrtTms.AO35" - }, - { - "index": 36, - "description": "Dynamic Reactive Current Support Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "EcpRef", - "name": "DRGS.EcpRef.AO36" - }, - { - "index": 37, - "description": "Dynamic Reactive Current Support - Gradient Mode.", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "DRGS", - "units": "None (list)", - "minimum": 0, - "data_object": "ArGraMod", - "allowed_values": { - "0": "Undefined", - "1": "Gradients reach 0 at the moving average Voltage", - "2": "Gradients reach 0 at the Voltage deadbands" - }, - "type": "enumerated", - "name": "DRGS.ArGraMod.AO37" - }, - { - "index": 38, - "description": "Dynamic Reactive Current Support Deadband Minimum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays above this value for the length of the Hold Time.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DRGS", - "units": "Percent", - "minimum": -10000, - "data_object": "DbVMin", - "name": "DRGS.DbVMin.AO38" - }, - { - "index": 39, - "description": "Dynamic Reactive Current Support Deadband Maximum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays below this value for the length of the Hold Time.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 10000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "DbVMax", - "name": "DRGS.DbVMax.AO39" - }, - { - "index": 40, - "description": "Dynamic Reactive Current Support Gradient for Sags. Percentage of the rated current (DRAT.ARtg) to apply capacitively per percentage of the negative deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSag", - "name": "DRGS.ArGraSag.AO40" - }, - { - "index": 41, - "description": "Dynamic Reactive Current Support Gradient for Swells. Percentage of the rated current (DRAT.ARtg) to apply inductively per percentage of the positive deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSwl", - "name": "DRGS.ArGraSwl.AO41" - }, - { - "index": 42, - "description": "Dynamic Reactive Current Support Filter Time for Moving Average Voltage (RDGS.VAv). Used to determine amount of dynamic reactive current support.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DRGS.FilTms.AO42" - }, - { - "index": 43, - "description": "Dynamic Reactive Current Support Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef) below which no reactive current support shall be applied.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "BlkZnV", - "name": "DRGS.BlkZnV.AO43" - }, - { - "index": 44, - "description": "Dynamic Reactive Current Support Hysteresis Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef). After being blocked, reactive current support shall not resume until the voltage has been above BlkZnV + HysBlkZnV.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "HysBlkZnV", - "name": "DRGS.HysBlkZnV.AO44" - }, - { - "index": 45, - "description": "Dynamic Reactive Current Support Block Zone Time. Time in milliseconds from the beginning of any \"sag\" event,before which dynamic reactive current support will always continue,regardless of how low voltage may sag.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "BlkZnTmms", - "name": "DRGS.BlkZnTmms.AO45" - }, - { - "index": 46, - "description": "Dynamic Reactive Current Support Start Hold Time. When the voltage exceeds the deadband limits for this length of time (measured in milliseconds),the \"sag\" or \"swell\" event begins and the DER may begin altering active power output.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "HoldTmms", - "name": "DRGS.HoldTmms.AO46" - }, - { - "index": 47, - "description": "Dynamic Reactive Current Support End Hold Time. When the voltage returns to within the deadband limits for this length of time (measured in milliseconds),the \"sag\" or \"swell\" event is considered to be over. Reactive current support ends,frozen values are unfrozen,and a new event can begin.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "HoldTmms", - "name": "DRGS.HoldTmms.AO47" - }, - { - "index": 48, - "description": "Dynamic Volt-Watt Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWD.ModPrio.AO48" - }, - { - "index": 49, - "description": "Dynamic Volt-Watt Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWD.WinTms.AO49" - }, - { - "index": 50, - "description": "Dynamic Volt-Watt Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWD.RmpTms.AO50" - }, - { - "index": 51, - "description": "Dynamic Volt-Watt Reversion Timeout period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWD.RvrtTms.AO51" - }, - { - "index": 52, - "description": "Dynamic Volt-Watt Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWD2.EcpRef.AO52" - }, - { - "index": 53, - "description": "Dynamic Volt-Watt Gradient. Signed unit-less quantity that establishes the ratio of additional Watts supplied (expressed in terms of % DRCT.WMax) to the present difference from the moving average voltage (expressed as % DRCT.VRef).", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DVWD", - "units": "Percent watts per percent voltage difference", - "data_object": "DynVWGra", - "name": "DVWD.DynVWGra.AO53" - }, - { - "index": 54, - "description": "Dynamic Volt-Watt Filter Time. The time in seconds used to calculate the moving average voltage for dynamic Volt-Watt support.", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "VWFilTms", - "name": "DVWD.VWFilTms.AO54" - }, - { - "index": 55, - "description": "Dynamic Volt-Watt Lower Deadband. Percentage of the nominal voltage (DRCT.Vref) measured below the moving average voltage. If the present voltage is above this value, no additional Watts shall be supplied.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVWD", - "units": "Percent", - "minimum": 0, - "data_object": "DbVWLo", - "name": "DVWD.DbVWLo.AO55" - }, - { - "index": 56, - "description": "Dynamic Volt-Watt Upper Deadband. Percentage of the nominal voltage (DRCT.Vref) measured above the moving average voltage. If the present voltage is below this value,no additional Watts shall be supplied.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVWD", - "units": "Percent", - "minimum": 0, - "data_object": "DbVWHi", - "name": "DVWD.DbVWHi.AO56" - }, - { - "index": 57, - "description": "Frequency-Watt Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW2.ModPrio.AO57" - }, - { - "index": 58, - "description": "Frequency-Watt Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AO58" - }, - { - "index": 59, - "description": "Frequency-Watt Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AO59" - }, - { - "index": 60, - "description": "Frequency-Watt Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AO60" - }, - { - "index": 61, - "description": "Frequency-Watt Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW.EcpRef.AO61" - }, - { - "index": 62, - "description": "Frequency-Watt High Starting Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStr", - "name": "DHFW.HzStr.AO62" - }, - { - "index": 63, - "description": "Frequency-Watt High Stopping Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStop", - "name": "DHFW.HzStop.AO63" - }, - { - "index": 64, - "description": "Frequency-Watt High Discharging/Generating Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DHFW.WGra.AO64" - }, - { - "index": 65, - "description": "Frequency-Watt High Charging Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DHFW.WChaGra.AO65" - }, - { - "index": 66, - "description": "Frequency-Watt Low Starting Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStr", - "name": "DLFW.HzStr.AO66" - }, - { - "index": 67, - "description": "Frequency-Watt Low Stopping Frequency", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStop", - "name": "DLFW.HzStop.AO67" - }, - { - "index": 68, - "description": "Frequency-Watt Low Discharging/Generating Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DLFW.WGra.AO68" - }, - { - "index": 69, - "description": "Frequency-Watt Low Charging Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DLFW.WChaGra.AO69" - }, - { - "index": 70, - "description": "Frequency-Watt Start Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW2.ActStrDlTmms.AO70" - }, - { - "index": 71, - "description": "Frequency-Watt Stop Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW2.ActStopDlTmms.AO71" - }, - { - "index": 72, - "description": "Frequency-Watt Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DHFW.OpnLoop.AO72" - }, - { - "index": 73, - "description": "Frequency-Watt Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DHFW.OpnLoop.AO73" - }, - { - "index": 74, - "description": "Frequency-Watt Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DHFW.DschRpuRte.AO74" - }, - { - "index": 75, - "description": "Frequency-Watt Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DHFW.DschRpdRte.AO75" - }, - { - "index": 76, - "description": "Frequency-Watt Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DHFW.ChaRpuRte.AO76" - }, - { - "index": 77, - "description": "Frequency-Watt Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DHFW.ChaRpdRte.AO77" - }, - { - "index": 78, - "description": "Frequency-Watt Hi Return Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "RtnRmpRte", - "name": "DHFW.RtnRmpRte.AO78" - }, - { - "index": 79, - "description": "Frequency-Watt Low Return Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "RtnRmpRte", - "name": "DLFW.RtnRmpRte.AO79" - }, - { - "index": 80, - "description": "Frequency-Watt Minimum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMin", - "name": "DHFW.SocUseMin.AO80" - }, - { - "index": 81, - "description": "Frequency-Watt Maximum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMax", - "name": "DHFW.SocUseMax.AO81" - }, - { - "index": 82, - "description": "Active Power Limit Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWMX.ModPrio.AO82" - }, - { - "index": 83, - "description": "Active Power Limit Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWMX.WinTms.AO83" - }, - { - "index": 84, - "description": "Active Power Limit Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWMX.RmpTms.AO84" - }, - { - "index": 85, - "description": "Active Power Limit Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWMX.RvrtTms.AO85" - }, - { - "index": 86, - "description": "Active Power Limit Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWMX.EcpRef.AO86" - }, - { - "index": 87, - "description": "Active Power Limit Charge Setpoint. Maximum allowed Watts as a percentage of Maximum Active Power capability.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMX", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMX.WLimPct.AO87" - }, - { - "index": 88, - "description": "Active Power Limit Discharge Setpoint. Maximum allowed Watts as a percentage of Maximum Active Power capability.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMN", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMN.WLimPct.AO88" - }, - { - "index": 89, - "description": "Charge/Discharge Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWGC.ModPrio.AO89" - }, - { - "index": 90, - "description": "Charge/Discharge Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWGC.WinTms.AO90" - }, - { - "index": 91, - "description": "Charge/Discharge Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWGC.RmpTms.AO91" - }, - { - "index": 92, - "description": "Charge/Discharge Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWGC.RvrtTms.AO92" - }, - { - "index": 93, - "description": "Charge/Discharge Active Power Target. Percentage of maxmum active power.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "GnWPctSpt", - "name": "DWGC.GnWPctSpt.AO93" - }, - { - "index": 94, - "description": "Charge/Discharge Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DWGC.OpnLoop.AO94" - }, - { - "index": 95, - "description": "Charge/Discharge Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DWGC.OpnLoop.AO95" - }, - { - "index": 96, - "description": "Charge/Discharge Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DWGC.DschRpuRte.AO96" - }, - { - "index": 97, - "description": "Charge/Discharge Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DWGC.DschRpdRte.AO97" - }, - { - "index": 98, - "description": "Charge/Discharge Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DWGC.ChaRpuRte.AO98" - }, - { - "index": 99, - "description": "Charge/Discharge Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DWGC.ChaRpdRte.AO99" - }, - { - "index": 100, - "description": "Charge/Discharge Minimum Reserve for Storage. The minimum level to which the storage system may be discharged,expressed as a percentage of the total usable storage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMinPct", - "name": "DWGC.SocUseMinPct.AO100" - }, - { - "index": 101, - "description": "Charge/Discharge Maximum Reserve for Storage. The maximum level to which the storage system may be discharged,expressed as a percentage of the total usable storage.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMaxPct", - "name": "DWGC.SocUseMaxPct.AO101" - }, - { - "index": 102, - "description": "Coordinated Charge/Discharge Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DTCD.ModPrio.AO102" - }, - { - "index": 103, - "description": "Coordinated Charge/Discharge Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DTCD.WinTms.AO103" - }, - { - "index": 104, - "description": "Coordinated Charge/Discharge Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DTCD.RmpTms.AO104" - }, - { - "index": 105, - "description": "Coordinated Charge/Discharge Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DTCD.RvrtTms.AO105" - }, - { - "index": 106, - "description": "Coordinated Charge/Discharge Target State of Charge. Charge that the system is expected to achieve,as a percentage of the usable capacity.", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DTCD", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseTgtPct", - "name": "DTCD.SocUseTgtPct.AO106" - }, - { - "index": 107, - "description": "Coordinated Charge/Discharge Target Date. Date by which the storage system must reach the target SOC. Expressed as number of days since January 1, 1970, UTC.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AO107" - }, - { - "index": 108, - "description": "Coordinated Charge/Discharge Target Time. Time by which storage system must reach the target SOC. Expressed as number of milliseconds since the start of Target Date.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "DateTgtTms", - "name": "DTCD.DateTgtTms.AO108" - }, - { - "index": 109, - "description": "Coordinated Charge/Discharge Energy Request", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Watt-hours", - "minimum": 0, - "data_object": "SocWReq", - "name": "DTCD.SocWReq.AO109" - }, - { - "index": 110, - "description": "Coordinated Charge/Discharge Minimum Charging Duration", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurTms", - "name": "DTCD.ChaDurTms.AO110" - }, - { - "index": 111, - "description": "Coordinated Charge/Discharge Date of Reference", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AO111" - }, - { - "index": 112, - "description": "Coordinated Charge/Discharge Time of Reference", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "SocDateTms", - "name": "DTCD.SocDateTms.AO112" - }, - { - "index": 113, - "description": "Coordinated Charge/Discharge Duration at Maximum Charge Rate", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurMax", - "name": "DTCD.ChaDurMax.AO113" - }, - { - "index": 114, - "description": "Coordinated Charge/Discharge Duration at Maximum Discharge Rate", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "DschDurMax", - "name": "DTCD.DschDurMax.AO114" - }, - { - "index": 115, - "description": "Active Power Response Mode #1 Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPKP.ModPrio.AO115" - }, - { - "index": 116, - "description": "Active Power Response Mode #1 Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPKP.WinTms.AO116" - }, - { - "index": 117, - "description": "Active Power Response Mode #1 Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPKP.RmpTms.AO117" - }, - { - "index": 118, - "description": "Active Power Response Mode #1 Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPKP.RvrtTms.AO118" - }, - { - "index": 119, - "description": "Active Power Response Mode #1 Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPKP.EcpRef.AO119" - }, - { - "index": 120, - "description": "Active Power Response Mode #1 Power Threshold", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPKP", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DPKP.PkPwrWLim.AO120" - }, - { - "index": 121, - "description": "Active Power Response Mode #1 Ratio", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DPKP", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DPKP.PkPwrFolPct.AO121" - }, - { - "index": 122, - "description": "Active Power Response Mode #1 Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DPKP.RpuRte.AO122" - }, - { - "index": 123, - "description": "Active Power Response Mode #1 Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DPKP.RpdRte.AO123" - }, - { - "index": 124, - "description": "Active Power Response Mode #2 Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DGFL.ModPrio.AO124" - }, - { - "index": 125, - "description": "Active Power Response Mode #2 Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DGFL.WinTms.AO125" - }, - { - "index": 126, - "description": "Active Power Response Mode #2 Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DGFL.RmpTms.AO126" - }, - { - "index": 127, - "description": "Active Power Response Mode #2 Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DGFL.RvrtTms.AO127" - }, - { - "index": 128, - "description": "Active Power Response Mode #2 Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DGFL.EcpRef.AO128" - }, - { - "index": 129, - "description": "Active Power Response Mode #2 Power Threshold", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DGFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DGFL.PkPwrWLim.AO129" - }, - { - "index": 130, - "description": "Active Power Response Mode #2 Ratio", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DGFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DGFL.PkPwrFolPct.AO130" - }, - { - "index": 131, - "description": "Active Power Response Mode #2 Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DGFL.RpuRte.AO131" - }, - { - "index": 132, - "description": "Active Power Response Mode #2 Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DGFL.RpdRte.AO132" - }, - { - "index": 133, - "description": "Active Power Response Mode #3 Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DLFL.ModPrio.AO133" - }, - { - "index": 134, - "description": "Active Power Response Mode #3 Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DLFL.WinTms.AO134" - }, - { - "index": 135, - "description": "Active Power Response Mode #3 Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DLFL.RmpTms.AO135" - }, - { - "index": 136, - "description": "Active Power Response Mode #3 Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DLFL.RvrtTms.AO136" - }, - { - "index": 137, - "description": "Active Power Response Mode #3 Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DLFL.EcpRef.AO137" - }, - { - "index": 138, - "description": "Active Power Response Mode #3 Power Threshold", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DLFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DLFL.PkPwrWLim.AO138" - }, - { - "index": 139, - "description": "Active Power Response Mode #3 Ratio", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DLFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DLFL.PkPwrFolPct.AO139" - }, - { - "index": 140, - "description": "Active Power Response Mode #3 Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DLFL.RpuRte.AO140" - }, - { - "index": 141, - "description": "Active Power Response Mode #3 Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DLFL.RpdRte.AO141" - }, - { - "index": 142, - "description": "AGC Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DAGC.ModPrio.AO142" - }, - { - "index": 143, - "description": "AGC Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DAGC.WinTms.AO143" - }, - { - "index": 144, - "description": "AGC Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DAGC.RmpTms.AO144" - }, - { - "index": 145, - "description": "AGC Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DAGC.RvrtTms.AO145" - }, - { - "index": 146, - "description": "AGC Active Power Target", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "GnWSpt", - "name": "DAGC.GnWSpt.AO146" - }, - { - "index": 147, - "description": "AGC Ramp Time Constant Up Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DAGC.OpnLoop.AO147" - }, - { - "index": 148, - "description": "AGC Ramp Time Constant Down Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DAGC.OpnLoop.AO148" - }, - { - "index": 149, - "description": "AGC Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DAGC.DschRpuRte.AO149" - }, - { - "index": 150, - "description": "AGC Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DAGC.DschRpdRte.AO150" - }, - { - "index": 151, - "description": "AGC Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DAGC.ChaRpuRte.AO151" - }, - { - "index": 152, - "description": "AGC Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DAGC.ChaRpdRte.AO152" - }, - { - "index": 153, - "description": "AGC Minimum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DAGC.SocUseMinPct.AO153" - }, - { - "index": 154, - "description": "AGC Maximum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DAGC.SocUseMaxPct.AO154" - }, - { - "index": 155, - "description": "Active Power Smoothing Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWSM.ModPrio.AO155" - }, - { - "index": 156, - "description": "Active Power Smoothing Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWSM.WinTms.AO156" - }, - { - "index": 157, - "description": "Active Power Smoothing Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWSM.RmpTms.AO157" - }, - { - "index": 158, - "description": "Active Power Smoothing Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWSM.RvrtTms.AO158" - }, - { - "index": 159, - "description": "Active Power Smoothing Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWSM.EcpRef.AO159" - }, - { - "index": 160, - "description": "Active Power Smoothing Gradient", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DWSM", - "units": "Watts per delta-watt", - "data_object": "WSmthGra", - "name": "DWSM.WSmthGra.AO160" - }, - { - "index": 161, - "description": "Active Power Smoothing Lower Limit. Difference in Watts from the moving average of the reference power (MMXN1.Watt) above which no smoothing shall be applied.", - "data_type": "AO", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DWSM", - "units": "Watts", - "data_object": "WSmthLoLim", - "name": "DWSM.WSmthLoLim.AO161" - }, - { - "index": 162, - "description": "Active Power Smoothing Upper Limit. Difference in Watts from the moving average of the reference power (MMXN.Watt) below which no smoothing shall be applied.", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DWSM", - "units": "Watts", - "minimum": 0, - "data_object": "WSmthHiLim", - "name": "DWSM.WSmthHiLim.AO162" - }, - { - "index": 163, - "description": "Active Power Smoothing Filter Time (Seconds). Time in seconds used to calculate the moving average of the reference load or generation (MMXN1.Watt) being smoothed.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DWSM.FilTms.AO163" - }, - { - "index": 164, - "description": "Active Power Smoothing Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DWSM.DschRpuRte.AO164" - }, - { - "index": 165, - "description": "Active Power Smoothing Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DWSM.DschRpdRte.AO165" - }, - { - "index": 166, - "description": "Active Power Smoothing Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DWSM.ChaRpuRte.AO166" - }, - { - "index": 167, - "description": "Active Power Smoothing Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DWSM.ChaRpdRte.AO167" - }, - { - "index": 168, - "description": "Volt-Watt Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWC.ModPrio.AO168" - }, - { - "index": 169, - "description": "Volt-Watt Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWC.WinTms.AO169" - }, - { - "index": 170, - "description": "Volt-Watt Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWC.RmpTms.AO170" - }, - { - "index": 171, - "description": "Volt-Watt Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWC.RvrtTms.AO171" - }, - { - "index": 172, - "description": "Volt-Watt Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWC.EcpRef.AO172" - }, - { - "index": 173, - "description": "Volt-Watt Curve Index", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "VWCrv", - "name": "DVWC.VWCrv.AO173" - }, - { - "index": 174, - "description": "Volt-Watt Filter Time (Seconds)", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DVWC.FilTms.AO174" - }, - { - "index": 175, - "description": "Volt-Watt Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DVWC.OpnLoop.AO175" - }, - { - "index": 176, - "description": "Volt-Watt Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoop", - "name": "DVWC.OpnLoop.AO176" - }, - { - "index": 177, - "description": "Volt-Watt Discharging Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpuRte", - "name": "DVWC.DschRpuRte.AO177" - }, - { - "index": 178, - "description": "Volt-Watt Discharging Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "DschRpdRte", - "name": "DVWC.DschRpdRte.AO178" - }, - { - "index": 179, - "description": "Volt-Watt Charging Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpuRte", - "name": "DVWC.ChaRpuRte.AO179" - }, - { - "index": 180, - "description": "Volt-Watt Charging Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "ChaRpdRte", - "name": "DVWC.ChaRpdRte.AO180" - }, - { - "index": 181, - "description": "Frequency-Watt Curve Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW.ModPrio.AO181" - }, - { - "index": 182, - "description": "Frequency-Watt Curve Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AO182" - }, - { - "index": 183, - "description": "Frequency-Watt Curve Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AO183" - }, - { - "index": 184, - "description": "Frequency-Watt Curve Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AO184" - }, - { - "index": 185, - "description": "Frequency-Watt Curve Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW.EcpRef.AO185" - }, - { - "index": 186, - "description": "Frequency-Watt Curve - Curve Index", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HzWCrv", - "name": "DHFW.HzWCrv.AO186" - }, - { - "index": 187, - "description": "Frequency-Watt Curve - High Frequency Hysteresis Curve Index", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DHFW.HysCrv.AO187" - }, - { - "index": 188, - "description": "Frequency-Watt Curve - Low Frequency Hysteresis Curve Index", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DLFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DLFW.HysCrv.AO188" - }, - { - "index": 189, - "description": "Frequency-Watt Curve Start Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW.ActStrDlTmms.AO189" - }, - { - "index": 190, - "description": "Frequency-Watt Curve Stop Delay", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW.ActStopDlTmms.AO190" - }, - { - "index": 191, - "description": "Frequency-Watt Curve Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AO191" - }, - { - "index": 192, - "description": "Frequency-Watt Curve Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AO192" - }, - { - "index": 193, - "description": "Frequency-Watt Curve Discharge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DHFW.RpuRte.AO193" - }, - { - "index": 194, - "description": "Frequency-Watt Curve Discharge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DHFW.RpdRte.AO194" - }, - { - "index": 195, - "description": "Frequency-Watt Curve Charge Ramp Up Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DHFW.RpuChaRte.AO195" - }, - { - "index": 196, - "description": "Frequency-Watt Curve Charge Ramp Down Rate", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DHFW.RpdChaRte.AO196" - }, - { - "index": 197, - "description": "Frequency-Watt Curve Minimum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DHFW.SocUseMinPct.AO197" - }, - { - "index": 198, - "description": "Frequency-Watt Curve Maximum Usable SOC", - "data_type": "AO", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DHFW.SocUseMaxPct.AO198" - }, - { - "index": 199, - "description": "Constant VArs Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVAR.ModPrio.AO199" - }, - { - "index": 200, - "description": "Constant VArs Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVAR.WinTms.AO200" - }, - { - "index": 201, - "description": "Constant VArs Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVAR.RmpTms.AO201" - }, - { - "index": 202, - "description": "Constant VArs Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVAR.RvrtTms.AO202" - }, - { - "index": 203, - "description": "Constant VArs Reactive Power Target. Percentage of maxmum reactive power.", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVAR", - "units": "Percent", - "minimum": -1000, - "data_object": "VArTgtPct", - "name": "DVAR.VArTgtPct.AO203" - }, - { - "index": 204, - "description": "Constant VArs Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AO204" - }, - { - "index": 205, - "description": "Constant VArs Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AO205" - }, - { - "index": 206, - "description": "Fixed Power Factor Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "minimum": 0, - "data_object": "ModPrio", - "name": "DFPF.ModPrio.AO206" - }, - { - "index": 207, - "description": "Fixed Power Factor Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DFPF.WinTms.AO207" - }, - { - "index": 208, - "description": "Fixed Power Factor Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DFPF.RmpTms.AO208" - }, - { - "index": 209, - "description": "Fixed Power Factor Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DFPF.RvrtTms.AO209" - }, - { - "index": 210, - "description": "Fixed Power Factor Setpoint - Generation/Discharging", - "data_type": "AO", - "common_data_class": "APC", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFGnTgt", - "name": "DFPF.PFGnTgt.AO210" - }, - { - "index": 211, - "description": "Fixed Power Factor Setpoint - Charging", - "data_type": "AO", - "common_data_class": "APC", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFLodTgt", - "name": "DFPF.PFLodTgt.AO211" - }, - { - "index": 212, - "description": "Volt-VAr Control Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVVR.ModPrio.AO212" - }, - { - "index": 213, - "description": "Volt-VAr Control Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVVR.WinTms.AO213" - }, - { - "index": 214, - "description": "Volt-VAr Control Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVVR.RmpTms.AO214" - }, - { - "index": 215, - "description": "Volt-VAr Control Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVVR.RvrtTms.AO215" - }, - { - "index": 216, - "description": "Volt-VAr Control Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVVR.EcpRef.AO216" - }, - { - "index": 217, - "description": "Volt-VAr Curve Index", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "VVArCrv", - "name": "DVVR.VVArCrv.AO217" - }, - { - "index": 218, - "description": "Volt-VAr Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AO218" - }, - { - "index": 219, - "description": "Volt-VAr Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AO219" - }, - { - "index": 220, - "description": "Volt-VAr Autonomous Voltage Reference Adjustment Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "VRefTmms", - "name": "DVVR.VRefTmms.AO220" - }, - { - "index": 221, - "description": "Watt-VAr Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWVR.ModPrio.AO221" - }, - { - "index": 222, - "description": "Watt-VAr Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWVR.WinTms.AO222" - }, - { - "index": 223, - "description": "Watt-VAr Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWVR.RmpTms.AO223" - }, - { - "index": 224, - "description": "Watt-VAr Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWVR.RvrtTms.AO224" - }, - { - "index": 225, - "description": "Watt-VAr Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWVR.EcpRef.AO225" - }, - { - "index": 226, - "description": "Watt-VAr Curve Index", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "WVArCrv", - "name": "DWVR.WVArCrv.AO226" - }, - { - "index": 227, - "description": "Watt-VAr Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AO227" - }, - { - "index": 228, - "description": "Watt-VAr Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AO228" - }, - { - "index": 229, - "description": "Power Factor Correction Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPFC.ModPrio.AO229" - }, - { - "index": 230, - "description": "Power Factor Correction Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPFC.WinTms.AO230" - }, - { - "index": 231, - "description": "Power Factor Correction Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpRte", - "name": "DPFC.RmpRte.AO231" - }, - { - "index": 232, - "description": "Power Factor Correction Reversion Timeout Period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPFC.RvrtTms.AO232" - }, - { - "index": 233, - "description": "Power Factor Correction Signal Meter ID", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPFC.EcpRef.AO233" - }, - { - "index": 234, - "description": "Power Factor Correction Average PF Target", - "data_type": "AO", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFTrg", - "name": "DPFC.PFTrg.AO234" - }, - { - "index": 235, - "description": "Power Factor Correction Lower PF Limit", - "data_type": "AO", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AO235" - }, - { - "index": 236, - "description": "Power Factor Correction Upper PF Limit", - "data_type": "AO", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AO236" - }, - { - "index": 237, - "description": "Pricing Mode Priority", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "None", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPRG.ModPrio.AO237" - }, - { - "index": 238, - "description": "Pricing Mode Enabling Time Window", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPRG.WinTms.AO238" - }, - { - "index": 239, - "description": "Pricing Mode Enabling Ramp Time", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPRG.RmpTms.AO239" - }, - { - "index": 240, - "description": "Pricing Mode Reversion Timeout period", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPRG.RvrtTms.AO240" - }, - { - "index": 241, - "description": "Pricing Mode Setpoint. Hundredths of local currency per Kilowatt-Hr.", - "data_type": "AO", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "ln_class": "DPRG", - "units": "100ths of local currency", - "data_object": "PrcRef", - "name": "DPRG.PrcRef.AO241" - }, - { - "index": 242, - "description": "Pricing Mode Ramp Up Time Constant", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AO242" - }, - { - "index": 243, - "description": "Pricing Mode Ramp Down Time Constant", - "data_type": "AO", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AO243" - }, - { - "index": 244, - "description": "Curve Edit Selector. Writing to this point selects which of the curves can currently be viewed and changed.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "DGSM", - "minimum": 1, - "data_object": "InCrv", - "name": "DGSMn.InCrv.AO244", - "type": "selector_block", - "selector_block_start": 244, - "selector_block_end": 448 - }, - { - "index": 245, - "description": "Curve Mode Type", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 20, - "ln_class": "DGSM", - "units": "None (list)", - "minimum": 0, - "data_object": "ModTyp", - "allowed_values": { - "0": "Curve disabled", - "1": "Not applicable / Unknown", - "2": "Volt-Var modes VV11-VV12", - "3": "Frequency-Watt mode FW22", - "4": "Watt-VAr mode WP42", - "5": "Voltage-Watt modes VW51-VW52", - "6": "Remain Connected", - "7": "Temperature mode", - "8": "Pricing signal mode", - "9": "HVRT Must Trip", - "10": "HVRT Momentary Cessation", - "11": "LVRT Must Trip", - "12": "LVRT Momentary Cessation", - "13": "HFRT Must Trip", - "14": "HFRT Momentary Cessation", - "15": "LFRT Must Trip", - "16": "LFRT Mandatory Operation" - }, - "type": "enumerated", - "name": "DGSMn.ModTyp.AO245" - }, - { - "index": 246, - "description": "Curve Number of Points", - "data_type": "AO", - "common_data_class": "CSG", - "maximum": 100, - "ln_class": "FMAR", - "minimum": 0, - "data_object": "PairArr.NumPts", - "name": "FMARn.PairArr.NumPts.AO246" - }, - { - "index": 247, - "description": "Independent (X-Value) Units for Curve", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "minimum": 0, - "data_object": "IndpUnits", - "allowed_values": { - "0": "Curve disabled", - "1": "Not applicable / Unknown", - "4": "Time", - "23": "Celsius Temperature", - "29": "Voltage", - "33": "Frequency", - "38": "Watts", - "100": "Price in hundredths of local currency", - "129": "Percent Voltage", - "133": "Percent Frequency", - "138": "Percent Watts", - "233": "Frequency Deviation" - }, - "type": "enumerated", - "name": "FMARn.IndpUnits.AO247" - }, - { - "index": 248, - "description": "Dependent (Y-Value) Units for Curve", - "data_type": "AO", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "minimum": 0, - "data_object": "DepRef", - "allowed_values": { - "0": "Curve disabled", - "1": "Not applicable / unknown", - "2": "VArs as percent of max VArs (VARMax)", - "3": "VArs as percent of max available VArs (VArAval)", - "4": "Vars as percent of max Watts (Wmax) not used", - "5": "Watts as percent of max Watts (Wmax)", - "6": "Watts as percent of frozen active power (DeptSnptRef)", - "7": "Power Factor in EEI notation", - "8": "Volts as a percent of the nominal voltage (VRef)", - "9": "Frequency as a percent of the nominal grid frequency (ECPNomHz)" - }, - "type": "enumerated", - "name": "FMARn.DepRef.AO248" - }, - { - "index": 249, - "description": "Curve X-Value and Y-Value pairs for curve points 1 - 100", - "data_type": "AO", - "common_data_class": "CSG", - "ln_class": "FMAR", - "units": "Varies", - "data_object": "PairArr.CrvPts", - "name": "FMARn.PairArr.CrvPts.AO249", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FMARn.PairArr.CrvPts.AO249.xVal" - }, - { - "name": "FMARn.PairArr.CrvPts.AO249.yVal" - } - ] - }, - { - "index": 449, - "description": "System Meter Active Power - High Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.hLim", - "name": "MMXU.TotW.rangeC.hLim.AO449" - }, - { - "index": 450, - "description": "System Meter Active Power - Low Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.lLim", - "name": "MMXU.TotW.rangeC.lLim.AO450" - }, - { - "index": 451, - "description": "System Meter Reactive Power - High Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.hLim", - "name": "MMXU.TotVAr.rangeC.hLim.AO451" - }, - { - "index": 452, - "description": "System Meter at Reactive Power - Low Threshold", - "data_type": "AO", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.lLim", - "name": "MMXU.TotVAr.rangeC.lLim.AO452" - }, - { - "index": 453, - "description": "System Meter at Power Factor - High Threshold", - "data_type": "AO", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.hLim", - "name": "MMXU.TotPF.rangeC.hLim.AO453" - }, - { - "index": 454, - "description": "System Meter at Power Factor - Low Threshold", - "data_type": "AO", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.lLim", - "name": "MMXU.TotPF.rangeC.lLim.AO454" - }, - { - "index": 455, - "description": "System Meter Phase A Volts - High Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.hLim", - "name": "MMXU.PhV.phsA.rangeC.hLim.AO455" - }, - { - "index": 456, - "description": "System Meter Phase A Volts - Low Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.lLim", - "name": "MMXU.PhV.phsA.rangeC.lLim.AO456" - }, - { - "index": 457, - "description": "System Meter Phase B Volts High Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.hLim", - "name": "MMXU.PhV.phsB.rangeC.hLim.AO457" - }, - { - "index": 458, - "description": "System Meter Phase B Volts - Low Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.lLim", - "name": "MMXU.PhV.phsB.rangeC.lLim.AO458" - }, - { - "index": 459, - "description": "System Meter Phase C Volts - High Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.hLim", - "name": "MMXU.PhV.phsC.rangeC.hLim.AO459" - }, - { - "index": 460, - "description": "System Meter Phase C Volts - Low Threshold", - "data_type": "AO", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.lLim", - "name": "MMXU.PhV.phsC.rangeC.lLim.AO460" - }, - { - "index": 461, - "description": "Schedule to Edit Selector. Selects which of the schedules can be currently viewed and changed.", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "name": "FSCC.Schd.AO461", - "type": "selector_block", - "selector_block_start": 461, - "selector_block_end": 669 - - }, - { - "index": 462, - "description": "Selected Schedule Identity", - "data_type": "AO", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "name": "FSCC.Schd.AO462" - }, - { - "index": 463, - "description": "Selected Schedule Priority. Priority of the schedule relative to other running schedules. Lower values have higher priority over higher values.", - "data_type": "AO", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 0, - "data_object": "SchdPrio", - "name": "FSCH1.SchdPrio.AO463" - }, - { - "index": 464, - "description": "Selected Schedule Type", - "data_type": "AO", - "common_data_class": "SCR", - "maximum": 30, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdVal.valEq", - "allowed_values": { - "1": "Low/High Voltage Ride-Through - Hi Must Trip", - "2": "Low/High Voltage Ride-Through - Low Must Trip", - "3": "Low/High Voltage Ride-Through - Hi Momentary", - "4": "Low/High Voltage Ride-Through - Lo Momentary", - "5": "Low/High Frequency Ride-Through - Hi Must Trip", - "6": "Low/High Frequency Ride-Through - Lo Must Trip", - "7": "Low/High Frequency Ride-Through - Hi Momentary", - "8": "Low/High Frequency Ride-Through - Low Momentary", - "9": "Dynamic Reactive Current Support - On/Off", - "10": "Dynamic Volt-Watt - On/Off", - "11": "Frequency-Watt - On/Off", - "12": "Active Power Limit - Charging", - "13": "Active Power Limit - Generating", - "14": "Charge/Discharge - Percent of Maximum", - "15": "Coordinated Charge/Discharge - SOC Target", - "16": "Active Power Response #1 - On/Off", - "17": "Active Power Response #2 - On/Off", - "18": "Active Power Response #3 - On/Off", - "19": "AGC - Watts", - "20": "Active Power Smoothing - On/Off", - "21": "Volt-Watt - Curve Index", - "22": "Frequency-Watt Curve - Curve Index", - "23": "Frequency-Watt Curve - High Hysteresis", - "24": "Frequency-Watt Curve - Low Hysteresis", - "25": "Constant VArs - Percent of Maximum", - "26": "Fixed Power Factor - Power Factor", - "27": "Volt-VAr - Curve Index", - "28": "Watt-VAr - Curve Index", - "29": "Power Factor Correction - On/Off", - "30": "Reserved - For pricing mode" - }, - "type": "enumerated", - "name": "FSCH.SchdVal.valEq.AO464" - }, - { - "index": 465, - "description": "Selected Schedule Start Date. Number of days since January 1, 1970, UTC.", - "data_type": "AO", - "common_data_class": "TSG", - "ln_class": "FSCH", - "units": "Days", - "minimum": 0, - "data_object": "StrTm", - "name": "FSCH.StrTm.AO465" - }, - { - "index": 466, - "description": "Selected Schedule Start Time. Milliseconds since the start of Schedule Start Date.", - "data_type": "AO", - "common_data_class": "TSG", - "maximum": 86400000, - "ln_class": "FSCH", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "StrTm", - "name": "FSCH.StrTm.AO466" - }, - { - "index": 467, - "description": "Selected Schedule Repeat Interval. Interval between actions after the initial occurrence. A zero value means the schedule is not repeated.", - "data_type": "AO", - "common_data_class": "TCS", - "ln_class": "FSCH", - "minimum": 0, - "data_object": "NxtStrTm", - "name": "FSCH.NxtStrTm.AO467" - }, - { - "index": 468, - "description": "Selected Schedule Repeat Interval Units", - "data_type": "AO", - "common_data_class": "SPG", - "maximum": 8, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdReuse", - "allowed_values": { - "0": "No Repeat", - "1": "Seconds", - "2": "Minutes", - "3": "Hours", - "4": "Days", - "5": "Weeks", - "6": "Months", - "7": "Months on Same Day of Week", - "8": "Months on Same Day of Week from End" - }, - "type": "enumerated", - "name": "FSCH.SchdReuse.AO468" - }, - { - "index": 469, - "description": "Selected Schedule Number of Points", - "data_type": "AO", - "common_data_class": "ING", - "maximum": 100, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "NumEntr", - "name": "FSCH.NumEntr.AO469" - }, - { - "index": 470, - "description": "Select schedule time offset and value pairs for points 1 - 100", - "data_type": "AO", - "minimum": 0, - "name": "FSCHn.SchdEntr.AO470", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FSCHn.SchdEntr.AO470.time", - "description": "Number of seconds from the start of the schedule when this point becomes active", - "units": "Seconds" - }, - { - "name": "FSCHn.SchdEntr.AO470.val", - "ln_class": "FSCH", - "data_object": "SchdEntr" - } - ] - }, - { - "index": 0, - "description": "DER Profile Version Number. Always the number 1.00 for this specification.", - "data_type": "AI", - "scaling_multiplier": 0.01, - "maximum": 100, - "minimum": 100, - "event_class": 3, - "name": "AI0" - }, - { - "index": 1, - "description": "DER Profile Implementation Level. 1, 2 or 3 to indicate support for Level 1, Level 2 or Level 3 respectively.", - "data_type": "AI", - "maximum": 3, - "minimum": 1, - "event_class": 3, - "name": "AI1" - }, - { - "index": 2, - "description": "Nameplate Minimum Voltage Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DGEN", - "units": "Volts", - "minimum": 0, - "data_object": "VMinRtg", - "event_class": 3, - "name": "DGEN.VMinRtg.AI2" - }, - { - "index": 3, - "description": "Nameplate Maximum Voltage Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DGEN", - "units": "Volts", - "minimum": 0, - "data_object": "VMaxRtg", - "event_class": 3, - "name": "DGEN.VMaxRtg.AI3" - }, - { - "index": 4, - "description": "Nameplate Active Generation Power Rating at Unity Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WMaxRtg", - "event_class": 3, - "name": "DGEN.WMaxRtg.AI4" - }, - { - "index": 5, - "description": "Nameplate Active Charging Power Rating at Unity Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWMaxRtg", - "event_class": 3, - "name": "DSTO.ChaWMaxRtg.AI5" - }, - { - "index": 6, - "description": "Nameplate Active Generation Power Rating at Specified Over-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WOvPFRtg", - "event_class": 3, - "name": "DGEN.WOvPFRtg.AI6" - }, - { - "index": 7, - "description": "Nameplate Active Charging Power Rating at Specified Over-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWOvPFRtg", - "event_class": 3, - "name": "DSTO.ChaWOvPFRtg.AI7" - }, - { - "index": 8, - "description": "Specified Over-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DGEN", - "units": "None", - "minimum": -100, - "data_object": "OvPFRtg", - "event_class": 3, - "name": "DGEN.OvPFRtg.AI8" - }, - { - "index": 9, - "description": "Nameplate Active Generation Power Rating at Specified Under-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WUnPFRtg", - "event_class": 3, - "name": "DGEN.WUnPFRtg.AI9" - }, - { - "index": 10, - "description": "Nameplate Active Charging Power Rating at Specified Under-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWUnPFRtg", - "event_class": 3, - "name": "DSTO.ChaWUnPFRtg.AI10" - }, - { - "index": 11, - "description": "Specified Under-Excited Power Factor", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DGEN", - "units": "None", - "minimum": -100, - "data_object": "UnPFRtg", - "event_class": 3, - "name": "DGEN.UnPFRtg.AI11" - }, - { - "index": 12, - "description": "Nameplate Reactive Supply (Injection) Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VARs", - "minimum": 0, - "data_object": "IvarMaxRtg", - "event_class": 3, - "name": "DGEN.IvarMaxRtg.AI12" - }, - { - "index": 13, - "description": "Nameplate Reactive Absorption Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DGEN", - "units": "VARs", - "data_object": "AvarMaxRtg", - "event_class": 3, - "name": "DGEN.AvarMaxRtg.AI13" - }, - { - "index": 14, - "description": "Nameplate Apparent Generation Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VAs", - "minimum": 0, - "data_object": "VAMaxRtg", - "event_class": 3, - "name": "DGEN.VAMaxRtg.AI14" - }, - { - "index": 15, - "description": "Nameplate Apparent Charging Power Rating", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "VAs", - "data_object": "ChaVAMaxRtg", - "event_class": 3, - "name": "DSTO.ChaVAMaxRtg.AI15" - }, - { - "index": 16, - "description": "Nameplate Storage Actual Energy Capacity. Nameplate (original) actual total energy capacity of the storage system expressed in Storage Capacity Units.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DSTO", - "units": "Amp-hrs or Watt-hrs", - "minimum": 0, - "data_object": "WhRtg", - "event_class": 3, - "name": "DSTO.WhRtg.AI16" - }, - { - "index": 17, - "description": "Storage Effective Actual Energy Capacity. Present actual total energy capacity of the storage system expressed in Storage Capacity Units.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DSTO", - "units": "Amp-hrs or Watt-hrs", - "minimum": 0, - "data_object": "EffWh", - "event_class": 3, - "name": "DSTO.EffWh.AI17" - }, - { - "index": 18, - "description": "Storage Usable Energy Capacity. Usable energy capacity of the storage system expressed in Storage Capacity Units.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DSTO", - "units": "Amp-hrs or Watt-hrs", - "minimum": 0, - "data_object": "UseWh", - "event_class": 3, - "name": "DSTO.UseWh.AI18" - }, - { - "index": 19, - "description": "Nameplate AC Current Maximum Generation Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DGEN", - "units": "Amps", - "minimum": 0, - "data_object": "AMaxRtg", - "event_class": 3, - "name": "DGEN.AMaxRtg.AI19" - }, - { - "index": 20, - "description": "Nameplate AC Current Maximum Charging Rating", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DSTO", - "units": "Amps", - "data_object": "ChaAMaxRtg", - "event_class": 3, - "name": "DSTO.ChaAMaxRtg.AI20" - }, - { - "index": 21, - "description": "Remaining Reactive Susceptance", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Siemens", - "data_object": "SuscRtg", - "event_class": 3, - "name": "DGEN.SuscRtg.AI21" - }, - { - "index": 22, - "description": "IEEE 1547 Normal Operating Performance Category.", - "data_type": "AI", - "maximum": 2, - "minimum": 0, - "units": "None (list)", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "Category A", - "2": "Category B" - }, - "type": "enumerated", - "name": "AI22" - }, - { - "index": 23, - "description": "IEEE 1547 Abnormal Operating Performance Category.", - "data_type": "AI", - "maximum": 3, - "minimum": 0, - "units": "None (list)", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "Category I", - "2": "Category II", - "3": "Category III" - }, - "type": "enumerated", - "name": "AI23" - }, - { - "index": 24, - "description": "Number of System Schedules", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI24" - }, - { - "index": 25, - "description": "Number of Meters", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI25" - }, - { - "index": 26, - "description": "Number of Inverters", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI26" - }, - { - "index": 27, - "description": "Number of Batteries", - "data_type": "AI", - "minimum": 0, - "units": "None", - "event_class": 3, - "name": "AI27" - }, - { - "index": 28, - "description": "Number of DER units connected to controller", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DSTO", - "units": "None", - "minimum": 0, - "data_object": "InclDER", - "event_class": 3, - "name": "DSTO.InclDER.AI28" - }, - { - "index": 29, - "description": "Reference Voltage", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VRef", - "name": "DECP.VRef.AI29" - }, - { - "index": 30, - "description": "Reference Voltage Offset", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "data_object": "VRefOfs", - "name": "DECP.VRefOfs.AI30" - }, - { - "index": 31, - "description": "Nominal Grid Frequency", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DECP", - "units": "Hz", - "minimum": 0, - "data_object": "EcpNomHz", - "name": "DECP.EcpNomHz.AI31" - }, - { - "index": 32, - "description": "Maximum Active Generation Power", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "Watts", - "minimum": 0, - "data_object": "WMax", - "name": "DGEN.WMax.AI32" - }, - { - "index": 33, - "description": "Maximum Active Charging Power", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "Watts", - "data_object": "ChaWMax", - "name": "DSTO.ChaWMax.AI33" - }, - { - "index": 34, - "description": "Maximum Reactive Injection Power", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VARs", - "minimum": 0, - "data_object": "IvarMax", - "name": "DGEN.IvarMax.AI34" - }, - { - "index": 35, - "description": "Maximum Reactive Absorption Power", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DGEN", - "units": "VARs", - "data_object": "AvarMax", - "name": "DGEN.AvarMax.AI35" - }, - { - "index": 36, - "description": "Maximum Apparent Generation Power", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGEN", - "units": "VA", - "minimum": 0, - "data_object": "VAMax", - "name": "DGEN.VAMax.AI36" - }, - { - "index": 37, - "description": "Maximum Apparent Charging Power", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DSTO", - "units": "VA", - "data_object": "ChaVAMax", - "name": "DSTO.ChaVAMax.AI37" - }, - { - "index": 38, - "description": "Minimum Voltage", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VMin", - "name": "DECP.VMin.AI38" - }, - { - "index": 39, - "description": "Maximum Voltage", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "ln_class": "DECP", - "units": "Volts", - "minimum": 0, - "data_object": "VMax", - "name": "DECP.VMax.AI39" - }, - { - "index": 40, - "description": "Open Loop Response Time Percentage. Percent of target to reach within the open loop response time. Default is 90%.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DGEN", - "units": "Percent", - "minimum": 0, - "data_object": "OpnLoopPct", - "name": "DGEN.OpnLoopPct.AI40" - }, - { - "index": 41, - "description": "Power Factor Sign Convention.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "MMXU", - "units": "None", - "minimum": 1, - "data_object": "PFSign", - "allowed_values": { - "1": "IEC active power", - "2": "IEEE lead/lag" - }, - "type": "enumerated", - "name": "MMXU.PFSign.AI41" - }, - { - "index": 42, - "description": "Reference for Reactive Power Setpoints. Selects which setpoint is active. Default is <3>.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 3, - "ln_class": "DGEN", - "units": "None (list)", - "minimum": 0, - "data_object": "VArSetRef", - "allowed_values": { - "0": "Not applicable / Unknown", - "1": "Percent of Maximum Active Power (WMax)", - "2": "Percent of Maximum Reactive Power (VArMax)", - "3": "Percent of Available Reactive Power (VArAvl)" - }, - "type": "enumerated", - "name": "DGEN.VArSetRef.AI42" - }, - { - "index": 43, - "description": "System Available Active Generation Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW", - "name": "MMXU.TotW.AI43" - }, - { - "index": 44, - "description": "System Available Active Charging Power", - "data_type": "AI", - "common_data_class": "MV", - "maximum": 0, - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotChaW", - "name": "MMXU.TotChaW.AI44" - }, - { - "index": 45, - "description": "System Available Reactive Injection Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DGEN", - "units": "VARs", - "minimum": 0, - "data_object": "AvarAvl", - "name": "DGEN.AvarAvl.AI45" - }, - { - "index": 46, - "description": "System Available Reactive Absorption Power", - "data_type": "AI", - "common_data_class": "MV", - "maximum": 0, - "ln_class": "DGEN", - "units": "VARs", - "data_object": "IvarAvl", - "name": "DGEN.IvarAvl.AI46" - }, - { - "index": 47, - "description": "System Available Actual State of Charge - Present energy in the DER as a percentage of Storage Effective Actual Capacity", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DSTO", - "units": "Percent", - "minimum": 0, - "data_object": "SocPct", - "name": "DSTO.SocPct.AI47" - }, - { - "index": 48, - "description": "System Usable State of Charge - Present usable energy in the DER as a percentage of Nameplate Storage Usable Capacity", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DSTO", - "units": "Percent", - "minimum": 0, - "data_object": "UseSocPct", - "name": "DSTO.UseSocPct.AI48" - }, - { - "index": 49, - "description": "System Start-up Status", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 99, - "ln_class": "DGEN", - "units": "None (list)", - "minimum": -1, - "data_object": "DEROpSt", - "name": "DGEN.DEROpSt.AI49" - }, - { - "index": 50, - "description": "DER Start (Return to Service) Voltage High Limit. Percent of Reference Voltage.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 20000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VHiLim", - "name": "DCTE.VHiLim.AI50" - }, - { - "index": 51, - "description": "DER Start (Return to Service) Voltage Low Limit. Percent of Reference Voltage.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 10000, - "ln_class": "DCTE", - "units": "Percent", - "minimum": 0, - "data_object": "VLoLim", - "name": "DCTE.VLoLim.AI51" - }, - { - "index": 52, - "description": "DER Start (Return to Service) Frequency High Limit", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzHiLim", - "name": "DCTE.HzHiLim.AI52" - }, - { - "index": 53, - "description": "DER Start (Return to Service) Frequency Low Limit", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DCTE", - "units": "Hz", - "minimum": 0, - "data_object": "HzLoLim", - "name": "DCTE.HzLoLim.AI53" - }, - { - "index": 54, - "description": "DER Start (Return to Service) Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnDlTmms", - "name": "DCTE.RtnDlTmms.AI54" - }, - { - "index": 55, - "description": "DER Start (Return to Service) Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AI55" - }, - { - "index": 56, - "description": "DER Start (Return to Service) Ramp Up Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RtnRmpTmms", - "name": "DCTE.RtnRmpTmms.AI56" - }, - { - "index": 57, - "description": "DER Stop (Cease to Energize) Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AI57" - }, - { - "index": 58, - "description": "DER Stop (Cease to Energize) Ramp Down Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DCTE.RmpTms.AI58" - }, - { - "index": 59, - "description": "DER Stop (Cease to Energize) Reversion Timeout Period. Time to revert from the stopped state and return to service.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AI59" - }, - { - "index": 60, - "description": "Connect/Disconnect Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DCTE.WinTms.AI60" - }, - { - "index": 61, - "description": "Connect/Disconnect Reversion Timeout Period. Timeout (reversion time is for the Disconnect only).", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DCTE", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DCTE.RvrtTms.AI61" - }, - { - "index": 62, - "description": "Maximum Generation Ramp Up Rate. The maximum generation ramp up rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRteMax", - "name": "DCTE.RpuRteMax.AI62" - }, - { - "index": 63, - "description": "Maximum Generation Ramp Down Rate. The maximum generation ramp down rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRteMax", - "name": "DCTE.RpdRteMax.AI63" - }, - { - "index": 64, - "description": "Maximum Charging Ramp Up Rate. The maximum charging ramp up rate expressed as a percentage of the Maximum Charging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRteMax", - "name": "DCTE.RpuChaRteMax.AI64" - }, - { - "index": 65, - "description": "Maximum Charging Ramp Down Rate. The maximum charging ramp down rate expressed as a percentage of the Maximum Charnging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DCTE", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRteMax", - "name": "DCTE.RpdChaRteMax.AI65" - }, - { - "index": 66, - "description": "Requested Settings Group.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO Enable Sensed Grid Config Detection)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP.EcpIsldSt.AI66" - }, - { - "index": 67, - "description": "Settings Group Being Edited.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO Enable Sensed Grid Config Detection)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP.EcpIsldSt.AI67" - }, - { - "index": 68, - "description": "Active Settings Group. Note this may differ from the Requested Settings Group or Settings Group Being Edited analog outputs depending on whether communications has been lost and how the Enable Sensed Grid Config Detection binary output is set.", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 255, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpIsldSt", - "allowed_values": { - "0": "Not Used", - "1": "Unspecified / Autonomously Determined (see BO42)", - "2": "Factory Configuration", - "3": "Default Configuration / Comms Lost", - "4": "Normal Grid-Connected Configuration", - "5": "Islanded Condition 1 (small, local island)", - "6": "Islanded Condition 2 (larger, area island)", - "7": "Islanded Condition 3 (largest, regional island)", - "8": "1st Alternate Grid-Connected Configuration", - "9": "2nd Alternate Grid-Connected Configuration", - "10": "3rd Alternate Grid-Connected Configuration" - }, - "type": "enumerated", - "name": "DECP.EcpIsldSt.AI68" - }, - { - "index": 69, - "description": "Freeze Counter Interval. interval between freeze counter operations after the initial occurrence. A zero value means the free counter operation is not repeated.", - "data_type": "AI", - "minimum": 0, - "name": "AI69" - }, - { - "index": 70, - "description": "Freeze Counter Interval Units. Units of the interval between freeze counter operations.", - "data_type": "AI", - "maximum": 9, - "minimum": 0, - "units": "None (list)", - "allowed_values": { - "0": "The outstation does not repeat the action,regardless of the Interval count.", - "1": "Milliseconds - In this case the interval is always counted relative to the Start Time and is constant regardless of the clock time set at the Outstation.", - "2": "Seconds - At the same millisecond within the second that is specified in the Start Time.", - "3": "Minutes - At the same second and millisecond within the minute that is specified in the Start Time.", - "4": "Hours - At the same minute,second and B7millisecond within the hour that is specified in the Start Time.", - "5": "Days - At the same time of day that is specified in the Start Time.", - "6": "Weeks - On the same day of the week at the same time of day that is specified in the Start Time", - "7": "Months - On the same day of each month at the same time of day that is specified in the Start Time. If the Start Time falls on the 29th or greater day of the month,the outstation shall not perform the action in months that do not have such a day", - "8": "Months on Same Day of Week from Start of Month - At the same timeof day on the same day of the week after the beginning of the month as the day specified in the Start Time. For instance,if the Start Time specifies the second Tuesday of February and the Interval Count is 2,the next action shall occur on the second Tuesday of April. In the same example,if the Interval Count is set to 12,this is the same as specifying,Every year on the second Tuesday in February. If the specified day does not occur in a given month when an action was scheduled to occur,the outstation shall not perform the action that month but shall perform it at the next valid scheduled time.", - "9": "Months on Same Day of Week from End of Month - The outstation shall interpret this setting as in <8>,but the day of the week shall be measured from the end of the month,e.g.,the second-last Tuesday in February." - }, - "type": "enumerated", - "name": "AI70" - }, - { - "index": 71, - "description": "Low/High Voltage Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHVT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHVT.EcpRef.AI71" - }, - { - "index": 72, - "description": "Low/High Voltage Ride-Through Voltage Reference Input. Active voltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN.Vol.AI72" - }, - { - "index": 73, - "description": "Low/High Voltage Ride-Through High Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AI73" - }, - { - "index": 74, - "description": "Low/High Voltage Ride-Through Low Must Trip Curve Index. Index of the Voltage Ride-through curve which specifies trip points when the voltage is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AI74" - }, - { - "index": 75, - "description": "Low/High Voltage Ride-Through High Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOV.BlkRef.AI75" - }, - { - "index": 76, - "description": "Low/High Voltage Ride-Through Low Momentary Cessation Curve Index. Index of the Voltage Ride-through curve which specifies where generation/discharging must stop when the voltage is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUV", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUV.BlkRef.AI76" - }, - { - "index": 77, - "description": "Low/High Frequency Ride-Through Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHFT", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFT.EcpRef.AI77" - }, - { - "index": 78, - "description": "Low/High Frequency Ride-Through Frequency Reference Input. Active frequency measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "Hz", - "name": "MMXU.Hz.AI78" - }, - { - "index": 79, - "description": "Low/High Frequency Ride-Through High Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AI79" - }, - { - "index": 80, - "description": "Low/High Frequency Ride-Through Low Must Trip Curve Index. Index of the Frequency Ride-through curve which specifies trip points when the frequency is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AI80" - }, - { - "index": 81, - "description": "Low/High Frequency Ride-Through High Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is high.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTOF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTOF.BlkRef.AI81" - }, - { - "index": 82, - "description": "Low/High Frequency Ride-Through Low Momentary Cessation Curve Index. Index of the Frequency Ride-through curve which specifies where generation/discharging must stop when the frequency is low.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "PTUF", - "minimum": 0, - "data_object": "BlkRef", - "name": "PTUF.BlkRef.AI82" - }, - { - "index": 83, - "description": "Dynamic Reactive Current Support Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "ModPrio", - "name": "DRGS.ModPrio.AI83" - }, - { - "index": 84, - "description": "Dynamic Reactive Current Support Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DRGS.WinTms.AI84" - }, - { - "index": 85, - "description": "Dynamic Reactive Current Support Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DRGS.RmpTms.AI85" - }, - { - "index": 86, - "description": "Dynamic Reactive Current Support Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DRGS.RvrtTms.AI86" - }, - { - "index": 87, - "description": "Dynamic Reactive Current Support Signal Meter ID. Referenced ECP. This is the meter from which current is being read to evaluate and provide support.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DRGS", - "minimum": 0, - "data_object": "EcpRef", - "name": "DRGS.EcpRef.AI87" - }, - { - "index": 88, - "description": "Dynamic Reactive Current Support Voltage Reference Input. Votltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN2.Vol.AI88" - }, - { - "index": 89, - "description": "Dynamic Reactive Current Support Moving Average Voltage", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DRGS", - "units": "Volts", - "minimum": 0, - "data_object": "VAv", - "name": "DRGS.VAv.AI89" - }, - { - "index": 90, - "description": "Dynamic Reactive Current Support Present Delta Voltage. Difference in Volts between the present measured Voltage and the Moving Average Voltage (RDGS.Vav) as a percentage of the reference voltage (VRef).", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 10000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": -10000, - "data_object": "DelV", - "name": "DRGS.DelV.AI90" - }, - { - "index": 91, - "description": "Dynamic Reactive Current Support - Gradient Mode.", - "data_type": "AI", - "common_data_class": "SPG", - "maximum": 2, - "ln_class": "DRGS", - "units": "None (list)", - "minimum": 0, - "data_object": "ArGraMod", - "allowed_values": { - "0": "Undefined", - "1": "Gradients reach 0 at the moving average Voltage", - "2": "Gradients reach 0 at the Voltage deadbands" - }, - "type": "enumerated", - "name": "DRGS.ArGraMod.AI91" - }, - { - "index": 92, - "description": "Dynamic Reactive Current Support Deadband Minimum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays above this value for the length of the Hold Time.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DRGS", - "units": "Percent", - "minimum": -10000, - "data_object": "DbVMin", - "name": "DRGS.DbVMin.AI92" - }, - { - "index": 93, - "description": "Dynamic Reactive Current Support Deadband Maximum Voltage. Percentage of the nominal voltage (DRCT.Vref), measured from the moving average voltage (RDGS.VAv). Support is no longer applied when the voltage stays below this value for the length of the Hold Time.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 10000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "DbVMax", - "name": "DRGS.DbVMax.AI93" - }, - { - "index": 94, - "description": "Dynamic Reactive Current Support Gradient for Sags. Percentage of the rated current (DRAT.ARtg) to apply capacitively per percentage of the negative deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSag", - "name": "DRGS.ArGraSag.AI94" - }, - { - "index": 95, - "description": "Dynamic Reactive Current Support Gradient for Swells. Percentage of the rated current (DRAT.ARtg) to apply inductively per percentage of the positive deviation from the moving average voltage (RDGS.Av). It is a ratio of percent and is therefore unitless.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DRGS", - "units": "Percent current per percent voltage deviation", - "data_object": "ArGraSwl", - "name": "DRGS.ArGraSwl.AI95" - }, - { - "index": 96, - "description": "Dynamic Reactive Current Support Filter Time for Moving Average Voltage (RDGS.VAv). Used to determine amount of dynamic reactive current support.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DRGS.FilTms.AI96" - }, - { - "index": 97, - "description": "Dynamic Reactive Current Support Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef) below which no reactive current support shall be applied.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "BlkZnV", - "name": "DRGS.BlkZnV.AI97" - }, - { - "index": 98, - "description": "Dynamic Reactive Current Support Hysteresis Block Zone Voltage. Percentage of the nominal voltage (DRCT.VRef). After being blocked,reactive current support shall not resume until the voltage has been above BlkZnV + HysBlkZnV.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DRGS", - "units": "Percent", - "minimum": 0, - "data_object": "HysBlkZnV", - "name": "DRGS.HysBlkZnV.AI98" - }, - { - "index": 99, - "description": "Dynamic Reactive Current Support Block Zone Time. Time in milliseconds from the beginning of any \"sag\" event, before which dynamic reactive current support will always continue, regardless of how low voltage may sag.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "BlkZnTmms", - "name": "DRGS.BlkZnTmms.AI99" - }, - { - "index": 100, - "description": "Dynamic Reactive Current Support Hold Time. When the voltage returns to within the deadband limits (RDGS.dbVMin annd RDGS.dbVMax) for this length of time (measured in milliseconds), the \"sag\" or \"swell\" event is considered to be over. Reactive current support ends, frozen values are unfrozen, and a new event can begin.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DRGS", - "units": "ms", - "minimum": 0, - "data_object": "HoldTmms", - "name": "DRGS.HoldTmms.AI100" - }, - { - "index": 101, - "description": "Dynamic Reactive Current Attempted Output. Current output that the mode is attempting to achieve based on the Voltage input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DRGS", - "units": "Amps", - "minimum": 0, - "data_object": "ReqA", - "name": "DRGS.ReqA.AI101" - }, - { - "index": 102, - "description": "Dynamic Volt-Watt Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWD.ModPrio.AI102" - }, - { - "index": 103, - "description": "Dynamic Volt-Watt Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWD.WinTms.AI103" - }, - { - "index": 104, - "description": "Dynamic Volt-Watt Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWD.RmpTms.AI104" - }, - { - "index": 105, - "description": "Dynamic Volt-Watt Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWD.RvrtTms.AI105" - }, - { - "index": 106, - "description": "Dynamic Volt-Watt Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DVWD", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWD2.EcpRef.AI106" - }, - { - "index": 107, - "description": "Dynamic Volt-Watt Voltage Reference Input. Votltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN2.Vol.AI107" - }, - { - "index": 108, - "description": "Dynamic Volt-Watt Moving Average Voltage", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DVWD", - "units": "Volts", - "minimum": 0, - "data_object": "VAv", - "name": "DVWD2.VAv.AI108" - }, - { - "index": 109, - "description": "Dynamic Volt-Watt Present Delta Voltage", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DVWD", - "units": "Volts", - "minimum": 0, - "data_object": "DelV", - "name": "DVWD2.DelV.AI109" - }, - { - "index": 110, - "description": "Dynamic Volt-Watt Gradient. Signed quantity that establishes the ratio of additional Watts supplied (expressed in terms of % DRCT.WMax) to the present difference from the moving average voltage (expressed as % DRCT.VRef).", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DVWD", - "units": "Percent watts per percent voltage difference", - "data_object": "DynVWGra", - "name": "DVWD.DynVWGra.AI110" - }, - { - "index": 111, - "description": "Dynamic Volt-Watt Filter Time. The time in seconds used to calculate the moving average voltage for dynamic Volt-Watt support.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DVWD", - "units": "Seconds", - "minimum": 0, - "data_object": "VWFilTms", - "name": "DVWD.VWFilTms.AI111" - }, - { - "index": 112, - "description": "Dynamic Volt-Watt Lower Deadband. Percentage of the nominal voltage (DRCT.Vref) measured below the moving average voltage. If the present voltage is above this value,no additional Watts shall be supplied.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 0, - "ln_class": "DVWD", - "units": "Percent", - "minimum": -1000, - "data_object": "DbVWLo", - "name": "DVWD.DbVWLo.AI112" - }, - { - "index": 113, - "description": "Dynamic Volt-Watt Upper Deadband. Percentage of the nominal voltage (DRCT.Vref) measured above the moving average voltage. If the present voltage is below this value, no additional Watts shall be supplied.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVWD", - "units": "Percent", - "minimum": 0, - "data_object": "DbVWHi", - "name": "DVWD.DbVWHi.AI113" - }, - { - "index": 114, - "description": "Dynamic Volt-Watt Attempted Output. Watt output that the mode is attempting to achieve based on the Voltage input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DVWD", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DVWD.ReqWSet.AI114" - }, - { - "index": 115, - "description": "Frequency-Watt Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW2.ModPrio.AI115" - }, - { - "index": 116, - "description": "Frequency-Watt Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AI116" - }, - { - "index": 117, - "description": "Frequency-Watt Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AI117" - }, - { - "index": 118, - "description": "Frequency-Watt Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AI118" - }, - { - "index": 119, - "description": "Frequency-Watt Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW2.EcpRef.AI119" - }, - { - "index": 120, - "description": "Frequency-Watt Frequency Reference Input. Frequency measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "MMXU", - "units": "Hz", - "minimum": 0, - "data_object": "Hz", - "name": "MMXU2.Hz.AI120" - }, - { - "index": 121, - "description": "Frequency-Watt High Starting Frequency. Delta frequency between start frequency and nominal grid frequency for high frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStr", - "name": "DHFW2.HzStr.AI121" - }, - { - "index": 122, - "description": "Frequency-Watt High Stopping Frequency. Delta frequency between stop frequency and nominal grid frequency for high frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "DHFW", - "units": "Hz", - "minimum": 0, - "data_object": "HzStop", - "name": "DHFW2.HzStop.AI122" - }, - { - "index": 123, - "description": "Frequency-Watt High Discharging/Generating Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DHFW.WGra.AI123" - }, - { - "index": 124, - "description": "Frequency-Watt High Charging Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DHFW.WChaGra.AI124" - }, - { - "index": 125, - "description": "Frequency-Watt Low Starting Frequency. Delta frequency between start frequency and nominal grid frequency for low frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStr", - "name": "DLFW2.HzStr.AI125" - }, - { - "index": 126, - "description": "Frequency-Watt Low Stopping Frequency. Delta frequency between stop frequency and nominal grid frequency for low frequency events.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "maximum": 0, - "ln_class": "DLFW", - "units": "Hz", - "minimum": -70000, - "data_object": "HzStop", - "name": "DLFW2.HzStop.AI126" - }, - { - "index": 127, - "description": "Frequency-Watt Low Discharging/Generating Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WGra", - "name": "DLFW.WGra.AI127" - }, - { - "index": 128, - "description": "Frequency-Watt Low Charging Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "data_object": "WChaGra", - "name": "DLFW.WChaGra.AI128" - }, - { - "index": 129, - "description": "Frequency-Watt Start Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW2.ActStrDlTmms.AI129" - }, - { - "index": 130, - "description": "Frequency-Watt Stop Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW2.ActStopDlTmms.AI130" - }, - { - "index": 131, - "description": "Frequency-Watt Ramp Up Time Constant. Time constant or open loop response time for moving from the current active power target to a higher active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DLFW.OpnLoopMax.AI131" - }, - { - "index": 132, - "description": "Frequency-Watt Ramp Down Time Constant. Time constant or open loop response time for moving from the current active power target to a lower active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AI132" - }, - { - "index": 133, - "description": "Frequency-Watt Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DHFW.RpuRte.AI133" - }, - { - "index": 134, - "description": "Frequency-Watt Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRteMax", - "name": "DHFW.RpdRteMax.AI134" - }, - { - "index": 135, - "description": "Frequency-Watt Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DHFW.RpuChaRte.AI135" - }, - { - "index": 136, - "description": "Frequency-Watt Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRteMax", - "name": "DHFW.RpdChaRteMax.AI136" - }, - { - "index": 137, - "description": "Frequency-Watt High Return Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent watts per percent frequency difference", - "minimum": 0, - "data_object": "RtnRmpRte", - "name": "DHFW2.RtnRmpRte.AI137" - }, - { - "index": 138, - "description": "Frequency-Watt Low Return Gradient", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DLFW", - "units": "Percent watts per percent frequency difference", - "minimum": 0, - "data_object": "RtnRmpRte", - "name": "DLFW2.RtnRmpRte.AI138" - }, - { - "index": 139, - "description": "Frequency-Watt Attempted Output. Watt output that the mode is attempting to achieve based on the Frequency input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DHFW", - "units": "Watts", - "data_object": "ReqWLim", - "name": "DHFW.ReqWLim.AI139" - }, - { - "index": 140, - "description": "Frequency-Watt Minimum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DAGC.SocUseMinPct.AI140" - }, - { - "index": 141, - "description": "Frequency-Watt Maximum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DAGC.SocUseMaxPct.AI141" - }, - { - "index": 142, - "description": "Active Power Limit Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWMX.ModPrio.AI142" - }, - { - "index": 143, - "description": "Active Power Limit Enabling Time Window. Time window (in seconds) within which to randomly execute a command. If the time window is zero, the command will be executed immediately.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWMX.WinTms.AI143" - }, - { - "index": 144, - "description": "Active Power Limit Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWMX.RmpTms.AI144" - }, - { - "index": 145, - "description": "Active Power Limit Reversion Timeout Period. Reversion Timeout Period (in seconds), after which the device will revert to its default status, such as closing the switch to reconnect to the grid or allowing maximum watts output, in case communications are lost or mitigating messages are not received.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWMX", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWMX.RvrtTms.AI145" - }, - { - "index": 146, - "description": "Active Power Limit Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DWMX", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWMX.EcpRef.AI146" - }, - { - "index": 147, - "description": "Active Power Limit Reference Input. Active Power measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI147" - }, - { - "index": 148, - "description": "Active Power Limit Charge Setpoint", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMX", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMX.WLimPct.AI148" - }, - { - "index": 149, - "description": "Active Power Limit Generation Setpoint", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWMN", - "units": "Percent", - "minimum": 0, - "data_object": "WLimPct", - "name": "DWMN.WLimPct.AI149" - }, - { - "index": 150, - "description": "Charge/Discharge Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWGC.ModPrio.AI150" - }, - { - "index": 151, - "description": "Charge/Discharge Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWGC.WinTms.AI151" - }, - { - "index": 152, - "description": "Charge/Discharge Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWGC.RmpTms.AI152" - }, - { - "index": 153, - "description": "Charge/Discharge Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWGC.RvrtTms.AI153" - }, - { - "index": 154, - "description": "Charge/Discharge Active Power Target. Percentage of maximum active power.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "GnWPctSpt", - "name": "DWGC.GnWPctSpt.AI154" - }, - { - "index": 155, - "description": "Charge/Discharge Ramp Up Time Constant. Ramp time, in seconds, for moving from the current active power target to a higher active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWGC.OpnLoopMax.AI155" - }, - { - "index": 156, - "description": "Charge/Discharge Ramp Down Time Constant. Ramp time, in seconds, for moving from the current active power target to a lower active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWGC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWGC.OpnLoopMax.AI156" - }, - { - "index": 157, - "description": "Charge/Discharge Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DWGC.RpuRte.AI157" - }, - { - "index": 158, - "description": "Charge/Discharge Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRteMax", - "name": "DWGC.RpdRteMax.AI158" - }, - { - "index": 159, - "description": "Charge/Discharge Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DWGC.RpuChaRte.AI159" - }, - { - "index": 160, - "description": "Charge/Discharge Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRteMax", - "name": "DWGC.RpdChaRteMax.AI160" - }, - { - "index": 161, - "description": "Charge/Discharge Minimum Reserve for Storage. The reserve level below which the storage system may be only be discharged in emergency situations, expressed as a percentage of the usable capacity.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMinPct", - "name": "DWGC.SocUseMinPct.AI161" - }, - { - "index": 162, - "description": "Charge/Discharge Maximum Reserve for Storage. The reserve level above which the storage system may be only be charged in emergency situations, expressed as a percentage of the usable capacity.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DWGC", - "units": "Percent", - "minimum": -1000, - "data_object": "SocUseMaxPct", - "name": "DWGC.SocUseMaxPct.AI162" - }, - { - "index": 163, - "description": "Coordinated Charge/Discharge Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "minimum": 0, - "data_object": "ModPrio", - "name": "DTCD.ModPrio.AI163" - }, - { - "index": 164, - "description": "Coordinated Charge/Discharge Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DTCD.WinTms.AI164" - }, - { - "index": 165, - "description": "Coordinated Charge/Discharge Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DTCD.RmpTms.AI165" - }, - { - "index": 166, - "description": "Coordinated Charge/Discharge Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DTCD.RvrtTms.AI166" - }, - { - "index": 167, - "description": "Coordinated Charge/Discharge Target State of Charge. Charge that the system is expected to achieve, as a percentage of the usable capacity.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DTCD", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseTgtPct", - "name": "DTCD.SocUseTgtPct.AI167" - }, - { - "index": 168, - "description": "Coordinated Charge/Discharge Target Date. Date by which the storage system must reach the target SOC. Days since January 1, 1970, UTC.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AI168" - }, - { - "index": 169, - "description": "Coordinated Charge/Discharge Target Time. Time by when the storage system must reach the target SOC. Expressed as the number of seconds since the start of Target Date.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milliseconds", - "minimum": 0, - "data_object": "DateTgtTms", - "name": "DTCD.DateTgtTms.AI169" - }, - { - "index": 170, - "description": "Coordinated Charge/Discharge Energy Request. Amount of energy that must be transferred from the grid to the charger to move the SOC from the value at the specific time of reference to the target SOC.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Watt-hours", - "minimum": 0, - "data_object": "SocWReq", - "name": "DTCD.SocWReq.AI170" - }, - { - "index": 171, - "description": "Coordinated Charge/Discharge Minimum Charging Duration. Minimum duration to move from the SOC at the time of reference to the target SOC.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurTms", - "name": "DTCD.ChaDurTms.AI171" - }, - { - "index": 172, - "description": "Coordinated Charge/Discharge Date of Reference. Date that the SOC is measured or computed by the storage system and is the basis for the Energy Request, Minimum Charging Duration, and other parameters.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Days", - "minimum": 0, - "data_object": "DateTgt", - "name": "DTCD.DateTgt.AI172" - }, - { - "index": 173, - "description": "Coordinated Charge/Discharge Time of Reference. Time that the SOC is measured or computed by the storage system and is the basis for the Energy Request, Minimum Charging Duration, and other parameters.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Milliseconds", - "minimum": 0, - "data_object": "SocDateTms", - "name": "DTCD.SocDateTms.AI173" - }, - { - "index": 174, - "description": "Coordinated Charge/Discharge Duration at Maximum Charge Rate. Duration that energy can be stored at the Maximum Charge Rate.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "ChaDurMax", - "name": "DTCD.ChaDurMax.AI174" - }, - { - "index": 175, - "description": "Coordinated Charge/Discharge Duration Maximum Discharge Rate. Duration that energy can be delivered at the Maximum Discharge Rate.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DTCD", - "units": "Seconds", - "minimum": 0, - "data_object": "DschDurMax", - "name": "DTCD.DschDurMax.AI175" - }, - { - "index": 176, - "description": "Active Power Response Mode #1 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPKP.ModPrio.AI176" - }, - { - "index": 177, - "description": "Active Power Response Mode #1 Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPKP.WinTms.AI177" - }, - { - "index": 178, - "description": "Active Power Response Mode #1 Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPKP.RmpTms.AI178" - }, - { - "index": 179, - "description": "Active Power Response Mode #1 Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPKP", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPKP.RvrtTms.AI179" - }, - { - "index": 180, - "description": "Active Power Response Mode #1 Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DPKP", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPKP.EcpRef.AI180" - }, - { - "index": 181, - "description": "Active Power Response Mode #1 Reference Power Measured", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI181" - }, - { - "index": 182, - "description": "Active Power Response Mode #1 Power Threshold", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPKP", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DPKP.PkPwrWLim.AI182" - }, - { - "index": 183, - "description": "Active Power Response Mode #1 Ratio", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DPKP", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DPKP.PkPwrFolPct.AI183" - }, - { - "index": 184, - "description": "Active Power Response Mode #1 Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DPKP.RpuRte.AI184" - }, - { - "index": 185, - "description": "Active Power Response Mode #1 Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DPKP", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DPKP.RpdRte.AI185" - }, - { - "index": 186, - "description": "Active Power Response Mode #1 Attempted Output. Watt output that the mode is attempting to achieve based on the Watts input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DPKP", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DPKP.ReqWSet.AI186" - }, - { - "index": 187, - "description": "Active Power Response Mode #2 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DGFL.ModPrio.AI187" - }, - { - "index": 188, - "description": "Active Power Response Mode #2 Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DGFL.WinTms.AI188" - }, - { - "index": 189, - "description": "Active Power Response Mode #2 Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DGFL.RmpTms.AI189" - }, - { - "index": 190, - "description": "Active Power Response Mode #2 Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DGFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DGFL.RvrtTms.AI190" - }, - { - "index": 191, - "description": "Active Power Response Mode #2 Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DGFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DGFL.EcpRef.AI191" - }, - { - "index": 192, - "description": "Active Power Response Mode #2 Reference Power Measured", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI192" - }, - { - "index": 193, - "description": "Active Power Response Mode #2 Power Threshold", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DGFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DGFL.PkPwrWLim.AI193" - }, - { - "index": 194, - "description": "Active Power Response Mode #2 Ratio", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DGFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DGFL.PkPwrFolPct.AI194" - }, - { - "index": 195, - "description": "Active Power Response Mode #2 Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DGFL.RpuRte.AI195" - }, - { - "index": 196, - "description": "Active Power Response Mode #2 Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DGFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DGFL.RpdRte.AI196" - }, - { - "index": 197, - "description": "Active Power Response Mode #2 Attempted Output. Watt output that the mode is attempting to achieve based on the Watts input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DGFL", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DGFL.ReqWSet.AI197" - }, - { - "index": 198, - "description": "Active Power Response Mode #3 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "ModPrio", - "name": "DLFL.ModPrio.AI198" - }, - { - "index": 199, - "description": "Active Power Response Mode #3 Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DLFL.WinTms.AI199" - }, - { - "index": 200, - "description": "Active Power Response Mode #3 Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DLFL.RmpTms.AI200" - }, - { - "index": 201, - "description": "Active Power Response Mode #3 Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DLFL", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DLFL.RvrtTms.AI201" - }, - { - "index": 202, - "description": "Active Power Response Mode #3 Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DLFL", - "minimum": 0, - "data_object": "EcpRef", - "name": "DLFL.EcpRef.AI202" - }, - { - "index": 203, - "description": "Active Power Response Mode #3 Reference Power Measured", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "name": "MMXU.TotW.AI203" - }, - { - "index": 204, - "description": "Active Power Response Mode #3 Power Threshold", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DLFL", - "units": "Watts", - "data_object": "PkPwrWLim", - "name": "DLFL.PkPwrWLim.AI204" - }, - { - "index": 205, - "description": "Active Power Response Mode #3 Ratio", - "data_type": "AI", - "common_data_class": "ING", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DLFL", - "units": "Percent", - "minimum": 0, - "data_object": "PkPwrFolPct", - "name": "DLFL.PkPwrFolPct.AI205" - }, - { - "index": 206, - "description": "Active Power Response Mode #3 Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DLFL.RpuRte.AI206" - }, - { - "index": 207, - "description": "Active Power Response Mode #3 Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DLFL", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DLFL.RpdRte.AI207" - }, - { - "index": 208, - "description": "Active Power Response Mode #3 Attempted Output. Watt output that the mode is attempting to achieve based on the Watts input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DLFL", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DLFL.ReqWSet.AI208" - }, - { - "index": 209, - "description": "AGC Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DAGC.ModPrio.AI209" - }, - { - "index": 210, - "description": "AGC Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DAGC.WinTms.AI210" - }, - { - "index": 211, - "description": "AGC Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DAGC.RmpTms.AI211" - }, - { - "index": 212, - "description": "AGC Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DAGC.RvrtTms.AI212" - }, - { - "index": 213, - "description": "AGC Active Power Target", - "data_type": "AI", - "common_data_class": "APC", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "GnWSpt", - "name": "DAGC.GnWSpt.AI213" - }, - { - "index": 214, - "description": "AGC Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpUpTms", - "name": "DAGC.RmpUpTms.AI214" - }, - { - "index": 215, - "description": "AGC Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpDnTms", - "name": "DAGC.RmpDnTms.AI215" - }, - { - "index": 216, - "description": "AGC Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DAGC.RpuRte.AI216" - }, - { - "index": 217, - "description": "AGC Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DAGC.RpdRte.AI217" - }, - { - "index": 218, - "description": "AGC Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DAGC.RpuChaRte.AI218" - }, - { - "index": 219, - "description": "AGC Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DAGC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DAGC.RpdChaRte.AI219" - }, - { - "index": 220, - "description": "AGC Minimum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DAGC.SocUseMinPct.AI220" - }, - { - "index": 221, - "description": "AGC Maximum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DAGC.SocUseMaxPct.AI221" - }, - { - "index": 222, - "description": "AGC Maximum Watts Available", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "WMaxAvl", - "name": "DAGC.WMaxAvl.AI222" - }, - { - "index": 223, - "description": "AGC Minimum Watts Available", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DAGC", - "units": "Watts", - "data_object": "WMinAvl", - "name": "DAGC.WMinAvl.AI223" - }, - { - "index": 224, - "description": "AGC Expected State of Charge", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SocExpc", - "name": "DAGC.SocExpc.AI224" - }, - { - "index": 225, - "description": "AGC Expected State of Energy", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DAGC", - "units": "Percent", - "minimum": 0, - "data_object": "SoeExpc", - "name": "DAGC.SoeExpc.AI225" - }, - { - "index": 226, - "description": "AGC Expected State of Charge Time Interval", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DAGC", - "units": "Seconds", - "minimum": 0, - "data_object": "SocExpcTms", - "name": "DAGC.SocExpcTms.AI226" - }, - { - "index": 227, - "description": "Active Power Smoothing Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWSM.ModPrio.AI227" - }, - { - "index": 228, - "description": "Active Power Smoothing Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWSM.WinTms.AI228" - }, - { - "index": 229, - "description": "Active Power Smoothing Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWSM.RmpTms.AI229" - }, - { - "index": 230, - "description": "Active Power Smoothing Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWSM.RvrtTms.AI230" - }, - { - "index": 231, - "description": "Active Power Smoothing Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DWSM", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWSM.EcpRef.AI231" - }, - { - "index": 232, - "description": "Active Power Smoothing Reference Power Input. Active Power measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "minimum": 0, - "data_object": "TotW", - "name": "MMXU.TotW.AI232" - }, - { - "index": 233, - "description": "Active Power Smoothing Gradient. Signed quantity that establishes the ratio of additional smoothing Watts provided to the present delta-watts of the reference load or generation. Delta Watts is the difference between the moving average and the present value of the reference power. Positive values of this gradient are for following load (increased reference load results in a dynamic increase in DER output), and negative values are for following generation (increased reference generation results in a dynamic decrease in DER output).", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.001, - "ln_class": "DWSM", - "units": "Watts per Delta-watt", - "data_object": "WSmthGra", - "name": "DWSM.WSmthGra.AI233" - }, - { - "index": 234, - "description": "Active Power Smoothing Lower Limit. Difference in Watts from the moving average of the reference power above which no smoothing shall be applied.", - "data_type": "AI", - "common_data_class": "ASG", - "maximum": 0, - "ln_class": "DWSM", - "units": "Watts", - "data_object": "WSmthLoLim", - "name": "DWSM.WSmthLoLim.AI234" - }, - { - "index": 235, - "description": "Active Power Smoothing Upper Limit. Difference in Watts from the moving average of the reference power below which no smoothing shall be applied.", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DWSM", - "units": "Watts", - "minimum": 0, - "data_object": "WSmthHiLim", - "name": "DWSM.WSmthHiLim.AI235" - }, - { - "index": 236, - "description": "Active Power Smoothing Filter Time (Seconds). Time in seconds used to calculate the moving average of the reference load or generation being smoothed.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWSM", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DWSM.FilTms.AI236" - }, - { - "index": 237, - "description": "Active Power Smoothing Discharge Ramp Up Rate. The maximum generation ramp up rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DWSM.RpuRte.AI237" - }, - { - "index": 238, - "description": "Active Power Smoothing Discharge Ramp Down Rate. The maximum generation ramp down rate expressed as a percentage of the Maximum Generation Rate (WMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DWSM.RpdRte.AI238" - }, - { - "index": 239, - "description": "Active Power Smoothing Charge Ramp Up Rate. The maximum charging ramp up rate expressed as a percentage of the Maximum Charging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DWSM.RpuChaRte.AI239" - }, - { - "index": 240, - "description": "Active Power Smoothing Charge Ramp Down Rate. The maximum charging ramp down rate expressed as a percentage of the Maximum Charnging Rate (WChaMax) per second.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DWSM", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DWSM.RpdChaRte.AI240" - }, - { - "index": 241, - "description": "Active Power Smoothing Attempted Output. Watt output that the mode is attempting to achieve based on the Watt input and other parameters.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DWSM", - "units": "Watts", - "data_object": "ReqWSet", - "name": "DWSM.ReqWSet.AI241" - }, - { - "index": 242, - "description": "Volt-Watt Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVWC.ModPrio.AI242" - }, - { - "index": 243, - "description": "Volt-Watt Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVWC.WinTms.AI243" - }, - { - "index": 244, - "description": "Volt-Watt Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVWC.RmpTms.AI244" - }, - { - "index": 245, - "description": "Volt-Watt Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVWC.RvrtTms.AI245" - }, - { - "index": 246, - "description": "Volt-Watt Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVWC.EcpRef.AI246" - }, - { - "index": 247, - "description": "Volt-Watt Reference Voltage Input. Voltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN.Vol.AI247" - }, - { - "index": 248, - "description": "Volt-Watt Curve Index. Index of the Volt-Watt curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DVWC", - "minimum": 0, - "data_object": "VWCrv", - "name": "DVWC.VWCrv.AI248" - }, - { - "index": 249, - "description": "Volt-Watt Attempted Output. Maximum active power the outstation will attempt to generate or absorb based on the Voltage input and selected curve.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DVWC", - "units": "Watts", - "data_object": "ReqWLim", - "name": "DVWC.ReqWLim.AI249" - }, - { - "index": 250, - "description": "Volt-Watt Filter Time (Seconds)", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "FilTms", - "name": "DVWC.FilTms.AI250" - }, - { - "index": 251, - "description": "Volt-Watt Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVWC.OpnLoopMax.AI251" - }, - { - "index": 252, - "description": "Volt-Watt Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVWC", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVWC.OpnLoopMax.AI252" - }, - { - "index": 253, - "description": "Volt-Watt Discharging Ramp Up Rate. Maximum ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DVWC.RpuRte.AI253" - }, - { - "index": 254, - "description": "Volt-Watt Discharging Ramp Down Rate. Maximum ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DVWC.RpdRte.AI254" - }, - { - "index": 255, - "description": "Volt-Watt Charging Ramp Up Rate. Maximum charging ramp up rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DVWC.RpuChaRte.AI255" - }, - { - "index": 256, - "description": "Volt-Watt Charging Ramp Down Rate. Maximum charging ramp down rate.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DVWC", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DVWC.RpdChaRte.AI256" - }, - { - "index": 257, - "description": "Frequency-Watt Curve Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "ModPrio", - "name": "DHFW.ModPrio.AI257" - }, - { - "index": 258, - "description": "Frequency-Watt Curve Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DHFW.WinTms.AI258" - }, - { - "index": 259, - "description": "Frequency-Watt Curve Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DHFW.RmpTms.AI259" - }, - { - "index": 260, - "description": "Frequency-Watt Curve Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DHFW.RvrtTms.AI260" - }, - { - "index": 261, - "description": "Frequency-Watt Curve Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "EcpRef", - "name": "DHFW.EcpRef.AI261" - }, - { - "index": 262, - "description": "Frequency-Watt Curve Frequency Reference Input. Frequency measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "MMXU", - "units": "Hz", - "minimum": 0, - "data_object": "Hz", - "name": "MMXU.Hz.AI262" - }, - { - "index": 263, - "description": "Frequency-Watt Curve - Curve Index. Index of the Frequency-Watt curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HzWCrv", - "name": "DHFW.HzWCrv.AI263" - }, - { - "index": 264, - "description": "Frequency-Watt Curve - High Frequency Hysteresis Curve Index", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DHFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DHFW.HysCrv.AI264" - }, - { - "index": 265, - "description": "Frequency-Watt Curve - Low Frequency Hysteresis Curve Index", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DLFW", - "minimum": 0, - "data_object": "HysCrv", - "name": "DLFW.HysCrv.AI265" - }, - { - "index": 266, - "description": "Frequency-Watt Curve Start Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStrDlTmms", - "name": "DHFW.ActStrDlTmms.AI266" - }, - { - "index": 267, - "description": "Frequency-Watt Curve Stop Delay", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "ActStopDlTmms", - "name": "DHFW.ActStopDlTmms.AI267" - }, - { - "index": 268, - "description": "Frequency-Watt Curve Ramp Up Time Constant. Time constant or open loop response time for moving from the current active power target to a higher active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AI268" - }, - { - "index": 269, - "description": "Frequency-Watt Curve Ramp Down Time Constant. Time constant or open loop response time for moving from the current active power target to a lower active power target.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DHFW", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DHFW.OpnLoopMax.AI269" - }, - { - "index": 270, - "description": "Frequency-Watt Curve Discharge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuRte", - "name": "DHFW.RpuRte.AI270" - }, - { - "index": 271, - "description": "Frequency-Watt Curve Discharge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdRte", - "name": "DHFW.RpdRte.AI271" - }, - { - "index": 272, - "description": "Frequency-Watt Curve Charge Ramp Up Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpuChaRte", - "name": "DHFW.RpuChaRte.AI272" - }, - { - "index": 273, - "description": "Frequency-Watt Curve Charge Ramp Down Rate", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 500000, - "ln_class": "DHFW", - "units": "Percent per Second", - "minimum": 0, - "data_object": "RpdChaRte", - "name": "DHFW.RpdChaRte.AI273" - }, - { - "index": 274, - "description": "Frequency-Watt Attempted Output. Watt output that the mode is attempting to achieve based on the Frequency input and selected curve. If Snapshot of Power is not enabled,this is the maximum active power the outstation will attempt to generate or absorb.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DHFW", - "units": "Watts", - "data_object": "ReqWLim", - "name": "DHFW.ReqWLim.AI274" - }, - { - "index": 275, - "description": "Frequency-Watt Curve Minimum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMinPct", - "name": "DHFW.SocUseMinPct.AI275" - }, - { - "index": 276, - "description": "Frequency-Watt Curve Maximum Usable SOC", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DHFW", - "units": "Percent", - "minimum": 0, - "data_object": "SocUseMaxPct", - "name": "DHFW.SocUseMaxPct.AI276" - }, - { - "index": 277, - "description": "Constant VArs Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVAR.ModPrio.AI277" - }, - { - "index": 278, - "description": "Constant VArs Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVAR.WinTms.AI278" - }, - { - "index": 279, - "description": "Constant VArs Enabling Ramp Time. Ramp time, in seconds, for moving from current operational mode settings to new operational mode settings.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVAR.RmpTms.AI279" - }, - { - "index": 280, - "description": "Constant VArs Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVAR.RvrtTms.AI280" - }, - { - "index": 281, - "description": "Constant VArs Reactive Power Target. Percentage of maximum reactive power.", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.1, - "maximum": 1000, - "ln_class": "DVAR", - "units": "Percent", - "minimum": -1000, - "data_object": "VArTgtPct", - "name": "DVAR.VArTgtPct.AI281" - }, - { - "index": 282, - "description": "Constant VArs Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AI282" - }, - { - "index": 283, - "description": "Constant VArs Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVAR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVAR.OpnLoopMax.AI283" - }, - { - "index": 284, - "description": "Fixed Power Factor Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "minimum": 0, - "data_object": "ModPrio", - "name": "DFPF.ModPrio.AI284" - }, - { - "index": 285, - "description": "Fixed Power Factor Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DFPF.WinTms.AI285" - }, - { - "index": 286, - "description": "Fixed Power Factor Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DFPF.RmpTms.AI286" - }, - { - "index": 287, - "description": "Fixed Power Factor Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DFPF", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DFPF.RvrtTms.AI287" - }, - { - "index": 288, - "description": "Fixed Power Factor Setpoint - Generation/Discharging", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFGnTgt", - "name": "DFPF.PFGnTgt.AI288" - }, - { - "index": 289, - "description": "Fixed Power Factor Setpoint - Charging", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DFPF", - "units": "None", - "minimum": 0, - "data_object": "PFLodTgt", - "name": "DFPF.PFLodTgt.AI289" - }, - { - "index": 290, - "description": "Volt-Var Control Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DVVR.ModPrio.AI290" - }, - { - "index": 291, - "description": "Volt-VAr Control Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DVVR.WinTms.AI291" - }, - { - "index": 292, - "description": "Volt-VAr Control Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DVVR.RmpTms.AI292" - }, - { - "index": 293, - "description": "Volt-VAr Control Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DVVR.RvrtTms.AI293" - }, - { - "index": 294, - "description": "Volt-VAr Control Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DVVR.EcpRef.AI294" - }, - { - "index": 295, - "description": "Volt-VAr Control Voltage Input. Voltage measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "MMXN", - "units": "Volts", - "minimum": 0, - "data_object": "Vol", - "name": "MMXN.Vol.AI295" - }, - { - "index": 296, - "description": "Volt-VAr Control Adjusted Voltage Reference. The Voltage used as reference for Volt-VAr control. If Autonomous Voltage Reference Adjustment is disabled,this is the same fixed value as the Reference Voltage.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.1, - "ln_class": "DVVR", - "units": "Volts", - "minimum": 0, - "data_object": "VRefSet", - "name": "DVVR.VRefSet.AI296" - }, - { - "index": 297, - "description": "Volt-VAr Curve Index. Index of the Volt-VAr curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DVVR", - "minimum": 0, - "data_object": "VVArCrv", - "name": "DVVR.VVArCrv.AI297" - }, - { - "index": 298, - "description": "Volt-VAr Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AI298" - }, - { - "index": 299, - "description": "Volt-VAr Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DVVR.OpnLoopMax.AI299" - }, - { - "index": 300, - "description": "Volt-VAr Autonomous Voltage Reference Adjustment Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DVVR", - "units": "Seconds", - "minimum": 0, - "data_object": "VRefTmms", - "name": "DVVR.VRefTmms.AI300" - }, - { - "index": 301, - "description": "Volt-VAr Attempted Output. VAr output that the mode is attempting to achieve based on the Voltage input and selected curve.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DVVR", - "units": "VARs", - "data_object": "ReqVAr", - "name": "DVVR.ReqVAr.AI301" - }, - { - "index": 302, - "description": "Watt-VAr Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "ModPrio", - "name": "DWVR.ModPrio.AI302" - }, - { - "index": 303, - "description": "Watt-VAr Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DWVR.WinTms.AI303" - }, - { - "index": 304, - "description": "Watt-VAr Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DWVR.RmpTms.AI304" - }, - { - "index": 305, - "description": "Watt-VAr Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DWVR.RvrtTms.AI305" - }, - { - "index": 306, - "description": "Watt-VAr Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "EcpRef", - "name": "DWVR.EcpRef.AI306" - }, - { - "index": 307, - "description": "Watt-VAr Reference Power Input. Power measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW", - "name": "MMXU.TotW.AI307" - }, - { - "index": 308, - "description": "Watt-VAr Curve Index. Index of the Watt-VAr curve that should be used by the mode.", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "DWVR", - "minimum": 0, - "data_object": "WVArCrv", - "name": "DWVR.WVArCrv.AI308" - }, - { - "index": 309, - "description": "Watt-VAr Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AI309" - }, - { - "index": 310, - "description": "Watt-VAr Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DWVR", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DWVR.OpnLoopMax.AI310" - }, - { - "index": 311, - "description": "Watt-VAr Attempted Output. VAr output that the mode is attempting to achieve based on the Watt input and selected curve.", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "DWVR", - "units": "VARs", - "data_object": "ReqVAr", - "name": "DWVR.ReqVAr.AI311" - }, - { - "index": 312, - "description": "Power Factor Correction Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPFC.ModPrio.AI312" - }, - { - "index": 313, - "description": "Power Factor Correction Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPFC.WinTms.AI313" - }, - { - "index": 314, - "description": "Power Factor Correction Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPFC.RmpTms.AI314" - }, - { - "index": 315, - "description": "Power Factor Correction Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPFC", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPFC.RvrtTms.AI315" - }, - { - "index": 316, - "description": "Power Factor Correction Signal Meter ID", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DPFC", - "minimum": 0, - "data_object": "EcpRef", - "name": "DPFC.EcpRef.AI316" - }, - { - "index": 317, - "description": "Power Factor Correction Reference Power Factor Input. Power factor measurement read from the meter and used as an input to the mode.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF", - "name": "MMXU.TotPF.AI317" - }, - { - "index": 318, - "description": "Power Factor Correction Average PF Target", - "data_type": "AI", - "common_data_class": "ASG", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFTrg", - "name": "DPFC.PFTrg.AI318" - }, - { - "index": 319, - "description": "Power Factor Correction Lower PF Limit", - "data_type": "AI", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AI319" - }, - { - "index": 320, - "description": "Power Factor Correction Upper PF Limit", - "data_type": "AI", - "common_data_class": "Int", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "DPFC", - "units": "None", - "minimum": -100, - "data_object": "PFCorRef.rangeC", - "name": "DPFC.PFCorRef.rangeC.AI320" - }, - { - "index": 321, - "description": "Pricing Mode Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "minimum": 0, - "data_object": "ModPrio", - "name": "DPRG.ModPrio.AI321" - }, - { - "index": 322, - "description": "Pricing Mode Enabling Time Window", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "WinTms", - "name": "DPRG.WinTms.AI322" - }, - { - "index": 323, - "description": "Pricing Mode Enabling Ramp Time", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RmpTms", - "name": "DPRG.RmpTms.AI323" - }, - { - "index": 324, - "description": "Pricing Mode Reversion Timeout Period", - "data_type": "AI", - "common_data_class": "ASG", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "RvrtTms", - "name": "DPRG.RvrtTms.AI324" - }, - { - "index": 325, - "description": "Pricing Mode Setpoint: Hundredths of local currency per Kilowatt-Hr.", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "ln_class": "DPRG", - "units": "100ths of local currency", - "data_object": "PrcRef", - "name": "DPRG.PrcRef.AI325" - }, - { - "index": 326, - "description": "Pricing Mode Ramp Up Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AI326" - }, - { - "index": 327, - "description": "Pricing Mode Ramp Down Time Constant", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "DPRG", - "units": "Seconds", - "minimum": 0, - "data_object": "OpnLoopMax", - "name": "DPRG.OpnLoopMax.AI327" - }, - { - "index": 328, - "description": "Curve Edit Selector Index of the curve which is currently being viewed and/or changed", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "DGSM", - "minimum": 1, - "data_object": "InCrv", - "name": "DGSMn.InCrv.AI328", - "type": "selector_block", - "selector_block_start": 328, - "selector_block_end": 532 - - }, - { - "index": 329, - "description": "Curve Mode Type", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 20, - "ln_class": "DGSM", - "units": "None (list)", - "minimum": 0, - "data_object": "ModTyp", - "allowed_values": { - "0": "Curve is not defined", - "1": "None, dimensionless", - "2": "Volt-Var modes VV11-VV12", - "3": "Frequency-Watt mode FW22", - "4": "Watt-VAr mode WP42", - "5": "Voltage-Watt modes VW51-VW52", - "6": "Remain Connected", - "7": "Temperature mode", - "8": "Pricing signal mode", - "9": "HVRT Must Trip", - "10": "HVRT Momentary Cessation", - "11": "LVRT Must Trip", - "12": "LVRT Momentary Cessation", - "13": "HFRT Must Trip", - "14": "HFRT Momentary Cessation", - "15": "LFRT Must Trip", - "16": "LFRT Momentary Cessation" - }, - "type": "enumerated", - "name": "DGSMn.ModTyp.AI329" - }, - { - "index": 330, - "description": "Curve Number of Points", - "data_type": "AI", - "common_data_class": "CSG", - "maximum": 100, - "ln_class": "FMAR", - "minimum": 0, - "data_object": "PairArr.NumPts", - "name": "FMARn.PairArr.NumPts.AI330" - }, - { - "index": 331, - "description": "Independent (X-Value) Units for Curve", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "allowed_values": { - "0": "Curve is not defined", - "1": "Not applicable / Unknown", - "4": "Time", - "23": "Celsius Temperature", - "29": "Voltage", - "33": "Frequency", - "38": "Watts", - "100": "Price in hundredths of local currency", - "129": "Percent Voltage", - "133": "Percent Frequency", - "138": "Percent Watts", - "233": "Frequency Deviation" - }, - "type": "enumerated", - "minimum": 0, - "data_object": "IndpUnits", - "name": "FMARn.IndpUnits.AI331" - }, - { - "index": 332, - "description": "Dependent (Y-Value) Units for Curve", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 255, - "ln_class": "FMAR", - "units": "None (list)", - "minimum": 0, - "data_object": "DepRef", - "allowed_values": { - "0": "Curve is not defined", - "1": "Not applicable / unknown", - "2": "VArs as percent of max VArs (VARMax)", - "3": "VArs as percent of max available VArs (VArAval)", - "4": "Vars as percent of max Watts (Wmax) - not used", - "5": "Watts as percent of max Watts (Wmax)", - "6": "Watts as percent of frozen active power (DeptSnptRef)", - "7": "Power Factor in EEI notation", - "8": "Volts as a percent of the nominal voltage (VRef)", - "9": "Frequency as a percentage of the Nominal Grid Frequency (ECPNomHz)" - }, - "type": "enumerated", - "name": "FMARn.DepRef.AI332" - }, - { - "index": 333, - "description": "Curve X-Value and Y-Value pairs for curve points 1 - 100", - "data_type": "AI", - "common_data_class": "CSG", - "ln_class": "FMAR", - "units": "Varies", - "data_object": "PairArr.CrvPts", - "name": "FMARn.PairArr.CrvPts.AI333", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FMARn.PairArr.CrvPts.AI333.xVal" - }, - { - "name": "FMARn.PairArr.CrvPts.AI333.yVal" - } - ] - }, - { - "index": 533, - "description": "System Meter Type of Connection Point", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 99, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "EcpConnType", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "DER to local EPS", - "2": "Internal to DER", - "3": "local EPS with load to area EPS (PCC with load)", - "4": "local EPS w/o load to area EPS (PCC without load)", - "5": "Load to local EPS", - "6": "External to DER beyond the PCC", - "7": "External to DER within the local EPS", - "8": "Auxiliary DER Load", - "9": "Group of DERs to the area EPS", - "99": "Other" - }, - "type": "enumerated", - "name": "DECP.EcpConnType.AI533" - }, - { - "index": 534, - "description": "System Meter Type of Circuit Phases", - "data_type": "AI", - "common_data_class": "ENS", - "maximum": 8, - "ln_class": "DECP", - "units": "None (list)", - "minimum": 0, - "data_object": "PhsConnTyp", - "event_class": 3, - "allowed_values": { - "0": "unknown", - "1": "Single phase", - "2": "Split phase", - "3": "2-phase", - "4": "3-phase delta", - "5": "3-phase wye", - "6": "3-phase wye grounded", - "7": "3-phase / 3-wire (inverter type)", - "8": "3-phase / 4-wire (inverter type)" - }, - "type": "enumerated", - "name": "DECP.PhsConnTyp.AI534" - }, - { - "index": 535, - "description": "System Meter Apparent Power Calculation Method. Calculation method for total apparent power calculation.", - "data_type": "AI", - "common_data_class": "ENG", - "maximum": 2, - "ln_class": "MMXU", - "units": "None (list)", - "minimum": 0, - "data_object": "ClcTotVA", - "allowed_values": { - "0": "unknown", - "1": "vector", - "2": "arithmetic" - }, - "type": "enumerated", - "name": "MMXU.ClcTotVA.AI535" - }, - { - "index": 536, - "description": "System Meter Frequency", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.001, - "maximum": 70000, - "ln_class": "MMXU", - "units": "Hz", - "minimum": 0, - "data_object": "Hz", - "event_class": 3, - "name": "MMXU.Hz.AI536" - }, - { - "index": 537, - "description": "System Meter Active Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "TotW", - "event_class": 3, - "name": "MMXU.TotW.AI537" - }, - { - "index": 538, - "description": "System Meter Active Power A", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "W.phsA.mag", - "event_class": 1, - "name": "MMXU.W.phsA.mag.AI538" - }, - { - "index": 539, - "description": "System Meter Active Power B", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "W.phsB.mag", - "event_class": 1, - "name": "MMXU.W.phsB.mag.AI539" - }, - { - "index": 540, - "description": "System Meter Active Power C", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "Watts", - "data_object": "W.phsC.mag", - "event_class": 1, - "name": "MMXU.W.phsC.mag.AI540" - }, - { - "index": 541, - "description": "System Meter Reactive Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "data_object": "TotVAr", - "event_class": 3, - "name": "MMXU.TotVAr.AI541" - }, - { - "index": 542, - "description": "System Meter Reactive Power A", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "VAr", - "data_object": "VAr.phsA.mag", - "event_class": 1, - "name": "MMXU.VAr.phsA.mag.AI542" - }, - { - "index": 543, - "description": "System Meter Reactive Power B", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "VAr", - "data_object": "VAr.phsB.mag", - "event_class": 1, - "name": "MMXU.VAr.phsB.mag.AI543" - }, - { - "index": 544, - "description": "System Meter Reactive Power C", - "data_type": "AI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "units": "VAr", - "data_object": "VAr.phsC.mag", - "event_class": 1, - "name": "MMXU.VAr.phsC.mag.AI544" - }, - { - "index": 545, - "description": "System Meter Power Factor", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF", - "event_class": 3, - "name": "MMXU.TotPF.AI545" - }, - { - "index": 546, - "description": "System Meter Apparent Power", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VA", - "data_object": "TotVA", - "event_class": 3, - "name": "MMXU.TotVA.AI546" - }, - { - "index": 547, - "description": "System Meter Phase A Volts", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.mag", - "event_class": 3, - "name": "MMXU.PhV.phsA.mag.AI547" - }, - { - "index": 548, - "description": "System Meter Phase A Angle", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "maximum": 3600, - "ln_class": "MMXU", - "units": "Degrees", - "minimum": 0, - "data_object": "PhV.phsA.ang", - "event_class": 3, - "name": "MMXU.PhV.phsA.ang.AI548" - }, - { - "index": 549, - "description": "System Meter Phase B Volts", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.mag", - "event_class": 3, - "name": "MMXU.PhV.phsB.mag.AI549" - }, - { - "index": 550, - "description": "System Meter Phase B Angle", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "maximum": 3600, - "ln_class": "MMXU", - "units": "Degrees", - "minimum": 0, - "data_object": "PhV.phsB.ang", - "event_class": 3, - "name": "MMXU.PhV.phsB.ang.AI550" - }, - { - "index": 551, - "description": "System Meter Phase C Volts", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.mag", - "event_class": 3, - "name": "MMXU.PhV.phsC.mag.AI551" - }, - { - "index": 552, - "description": "System Meter Phase C Angle", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "maximum": 3600, - "ln_class": "MMXU", - "units": "Degrees", - "minimum": 0, - "data_object": "PhV.phsC.ang", - "event_class": 3, - "name": "MMXU.PhV.phsC.ang.AI552" - }, - { - "index": 553, - "description": "System Meter Average Line to Line Voltage", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "AvPPVPhs", - "event_class": 1, - "name": "MMXU.AvPPVPhs.AI553" - }, - { - "index": 554, - "description": "System Meter Current A", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Amps", - "data_object": "A.phsA.mag", - "event_class": 1, - "name": "MMXU.A.phsA.mag.AI554" - }, - { - "index": 555, - "description": "System Meter Current B", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Amps", - "data_object": "A.phsB.mag", - "event_class": 1, - "name": "MMXU.A.phsB.mag.AI555" - }, - { - "index": 556, - "description": "System Meter Current C", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Amps", - "data_object": "A.phsC.mag", - "event_class": 1, - "name": "MMXU.A.phsC.mag.AI556" - }, - { - "index": 557, - "description": "System Meter Active Power - High Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.hLim", - "event_class": 3, - "name": "MMXU.TotW.rangeC.hLim.AI557" - }, - { - "index": 558, - "description": "System Meter Active Power - Low Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "Watts", - "minimum": 0, - "data_object": "TotW.rangeC.lLim", - "event_class": 3, - "name": "MMXU.TotW.rangeC.lLim.AI558" - }, - { - "index": 559, - "description": "System Meter Reactive Power - High Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.hLim", - "event_class": 3, - "name": "MMXU.TotVAr.rangeC.hLim.AI559" - }, - { - "index": 560, - "description": "System Meter Reactive Power - Low Threshold", - "data_type": "AI", - "common_data_class": "MV", - "ln_class": "MMXU", - "units": "VARs", - "minimum": 0, - "data_object": "TotVAr.rangeC.lLim", - "event_class": 3, - "name": "MMXU.TotVAr.rangeC.lLim.AI560" - }, - { - "index": 561, - "description": "System Meter Power Factor - High Threshold", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.hLim", - "event_class": 3, - "name": "MMXU.TotPF.rangeC.hLim.AI561" - }, - { - "index": 562, - "description": "System Meter Power Factor - Low Threshold", - "data_type": "AI", - "common_data_class": "MV", - "scaling_multiplier": 0.01, - "maximum": 100, - "ln_class": "MMXU", - "units": "None", - "minimum": -100, - "data_object": "TotPF.rangeC.lLim", - "event_class": 3, - "name": "MMXU.TotPF.rangeC.lLim.AI562" - }, - { - "index": 563, - "description": "System Meter Phase A Volts - High Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.hLim", - "event_class": 3, - "name": "MMXU.PhV.phsA.rangeC.hLim.AI563" - }, - { - "index": 564, - "description": "System Meter Phase A Volts - Low Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsA.rangeC.lLim", - "event_class": 3, - "name": "MMXU.PhV.phsA.rangeC.lLim.AI564" - }, - { - "index": 565, - "description": "System Meter Phase B Volts - High Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.hLim", - "event_class": 3, - "name": "MMXU.PhV.phsB.rangeC.hLim.AI565" - }, - { - "index": 566, - "description": "System Meter Phase B Volts - Low Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsB.rangeC.lLim", - "event_class": 3, - "name": "MMXU.PhV.phsB.rangeC.lLim.AI566" - }, - { - "index": 567, - "description": "System Meter Phase C Volts - High Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.hLim", - "event_class": 3, - "name": "MMXU.PhV.phsC.rangeC.hLim.AI567" - }, - { - "index": 568, - "description": "System Meter Phase C Volts - Low Threshold", - "data_type": "AI", - "common_data_class": "WYE", - "scaling_multiplier": 0.1, - "ln_class": "MMXU", - "units": "Volts", - "minimum": 0, - "data_object": "PhV.phsC.rangeC.lLim", - "event_class": 3, - "name": "MMXU.PhV.phsC.rangeC.lLim.AI568" - }, - { - "index": 569, - "description": "Running Schedule Index. Index of the highest priority schedule that is currently running or 0 if no schedule is currently running.", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "ActSchdRef", - "name": "FSCC1.ActSchdRef.AI569" - }, - { - "index": 570, - "description": "Schedule to Edit Selector", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "event_class": 3, - "name": "FSCC.Schd.AI570", - "type": "selector_block", - "selector_block_start": 570, - "selector_block_end": 780 - - }, - { - "index": 571, - "description": "Selected Schedule Identity", - "data_type": "AI", - "common_data_class": "ORG", - "ln_class": "FSCC", - "minimum": 0, - "data_object": "Schd", - "event_class": 3, - "name": "FSCC.Schd.AI571" - }, - { - "index": 572, - "description": "Selected Schedule Priority. Priority of the schedule relative to other running schedules. Lower values have higher priority over higher values.", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 1, - "data_object": "SchdPrio", - "event_class": 3, - "name": "FSCH.SchdPrio.AI572" - }, - { - "index": 573, - "description": "Selected Schedule Type.", - "data_type": "AI", - "maximum": 21, - "minimum": 0, - "units": "None (list)", - "event_class": 3, - "allowed_values": { - "1": "Low/High Voltage Ride-Through Hi Must Trip", - "2": "Low/High Voltage Ride-Through Low Must Trip", - "3": "Low/High Voltage Ride-Through Hi Momentary", - "4": "Low/High Voltage Ride-Through Lo Momentary", - "5": "Low/High Frequency Ride-Through Hi Must Trip", - "6": "Low/High Frequency Ride-Through Lo Must Trip", - "7": "Low/High Frequency Ride-Through Hi Momentary", - "8": "Low/High Frequency Ride-Through Low Momentary", - "9": "Dynamic Reactive Current Support - On/Off", - "10": "Dynamic Volt-Watt - On/Off", - "11": "Frequency-Watt - On/Off", - "12": "Active Power Limit - Charging", - "13": "Active Power Limit - Generating", - "14": "Charge/Discharge - Percent of Maximum", - "15": "Coordinated Charge/Discharge - SOC Target", - "16": "Active Power Response #1 - On/Off", - "17": "Active Power Response #2 - On/Off", - "18": "Active Power Response #3 - On/Off", - "19": "AGC Watts", - "20": "Active Power Smoothing - On/Off", - "21": "Volt-Watt Curve Index", - "22": "Frequency-Watt Curve Curve Index", - "23": "Frequency-Watt Curve High Hysteresis", - "24": "Frequency-Watt Curve Low Hysteresis", - "25": "Constant VArs - Percent of Maximum", - "26": "Fixed Power Factor - Power Factor", - "27": "Volt-VAr Curve Index", - "28": "Watt-VAr Curve Index", - "29": "Power Factor Correction - On/Off", - "30": "Reserved - For pricing mode" - }, - "type": "enumerated", - "name": "AI573" - }, - { - "index": 574, - "description": "Selected Schedule Start Date. Number of days since January 1, 1970, UTC.", - "data_type": "AI", - "common_data_class": "TSG", - "ln_class": "FSCH", - "units": "Days", - "minimum": 0, - "data_object": "StrTm", - "event_class": 3, - "name": "FSCH.StrTm.AI574" - }, - { - "index": 575, - "description": "Selected Schedule Start Time. Milliseconds since the start of Schedule Start Date.", - "data_type": "AI", - "common_data_class": "TSG", - "maximum": 86400000, - "ln_class": "FSCH", - "units": "Milli-seconds", - "minimum": 0, - "data_object": "StrTm", - "event_class": 3, - "name": "FSCH.StrTm.AI575" - }, - { - "index": 576, - "description": "Selected Schedule Repeat Interval. Interval between actions after the initial occurrence. A zero value means the schedule is not repeated.", - "data_type": "AI", - "common_data_class": "TCS", - "ln_class": "FSCH", - "units": "Varies", - "minimum": 0, - "data_object": "NxtStrTm", - "event_class": 3, - "name": "FSCH.NxtStrTm.AI576" - }, - { - "index": 577, - "description": "Selected Schedule Repeat Interval Units", - "data_type": "AI", - "common_data_class": "SPG", - "maximum": 8, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "SchdReuse", - "event_class": 3, - "allowed_values": { - "0": "No Repeat", - "1": "sec", - "2": "Minutes", - "3": "Hours", - "4": "Days", - "5": "Weeks", - "6": "Months", - "7": "Months on Same Day of Week", - "8": "Months on Same Day of Week from End" - }, - "type": "enumerated", - "name": "FSCH.SchdReuse.AI577" - }, - { - "index": 578, - "description": "Selected Schedule Validation Status", - "data_type": "AI", - "common_data_class": "ENSScheduleState", - "maximum": 4, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "SchdSt", - "event_class": 3, - "name": "FSCH1.SchdSt.AI578" - }, - { - "index": 579, - "description": "Selected Schedule Status", - "data_type": "AI", - "common_data_class": "ENSScheduleState", - "maximum": 4, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdSt", - "allowed_values": { - "0": "unknown", - "1": "Not available", - "2": "Inactive", - "3": "Ready-to-Run", - "4": "Running" - }, - "type": "enumerated", - "name": "FSCH1.SchdSt.AI579" - }, - { - "index": 580, - "description": "Selected Schedule Number of Points", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 0, - "data_object": "NumEntr", - "event_class": 3, - "name": "FSCH.NumEntr.AI580" - }, - { - "index": 581, - "description": "Select schedule time offset and value pairs for points 1 - 100", - "data_type": "AI", - "minimum": 0, - "name": "FSCHn.SchdEntr.AI581", - "type": "array", - "array_times_repeated": 100, - "array_points": [ - { - "name": "FSCHn.SchdEntr.AI581.time", - "units": "Seconds" - }, - { - "name": "FSCHn.SchdEntr.AI581.val", - "ln_class": "FSCH", - "data_object": "SchdEntr" - } - ] - }, - { - "index": 781, - "description": "Schedule 1 Status", - "data_type": "AI", - "common_data_class": "ENSScheduleState", - "maximum": 4, - "ln_class": "FSCH", - "units": "None (list)", - "minimum": 0, - "data_object": "SchdSt", - "allowed_values": { - "0": "unknown", - "1": "Not available", - "2": "Inactive", - "3": "Ready-to-Run", - "4": "Running" - }, - "type": "enumerated", - "name": "FSCH1.SchdSt.AI781" - }, - { - "index": 782, - "description": "Schedule 1 Priority", - "data_type": "AI", - "common_data_class": "ING", - "ln_class": "FSCH", - "minimum": 1, - "data_object": "SchdPrio", - "name": "FSCH.SchdPrio.AI782" - }, - { - "index": 783, - "description": "Schedule 1 Active Time Value. This is the index of the time value entry the schedule is currently running. First entry is 1. Zero if the schedule is not running.", - "data_type": "AI", - "common_data_class": "INS", - "maximum": 10, - "ln_class": "FSCH", - "minimum": 0, - "data_object": "ActStrTm", - "name": "FSCH1.ActStrTm.AI783" - }, - { - "category": "alarm", - "index": 0, - "description": "System Communication Error", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "LCCH", - "data_object": "ChLiv", - "allowed_values": { - "0": "Normal", - "1": "Alarm: Communications error exists in the ESS" - }, - "event_class": 1, - "name": "LCCH.ChLiv.BI0" - }, - { - "category": "alarm", - "index": 1, - "description": "System Has Priority 1 Alarms", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "CALH", - "data_object": "GrAlm", - "allowed_values": { - "0": "No P1 Alarms Active", - "1": "Alarm: One or More P1 Alarms Active" - }, - "event_class": 1, - "name": "CALH.GrAlm.BI1" - }, - { - "category": "alarm", - "index": 2, - "description": "System Has Priority 2 Alarms", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "CALH", - "data_object": "GrWrn", - "allowed_values": { - "0": "No P2 Alarms Active", - "1": "Alarm: One or More P2 Alarms Active" - }, - "event_class": 1, - "name": "CALH.GrWrn.BI2" - }, - { - "category": "alarm", - "index": 3, - "description": "System Has Priority 3 Alarms", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "CALH", - "data_object": "GrInd", - "allowed_values": { - "0": "No P3 Alarms Active", - "1": "Alarm: One or More P3 Alarms Active" - }, - "event_class": 1, - "name": "CALH.GrInd.BI3" - }, - { - "category": "alarm", - "index": 4, - "description": "Storage State of Charge at Maximum. Maximum Usable State of Charge Reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SocHiWrn", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SocHiWrn.BI4" - }, - { - "category": "alarm", - "index": 5, - "description": "Storage State of Charge is Too High. Maximum Reserve Percentage (of usable capacity) reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SocHiAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SocHiAlm.BI5" - }, - { - "category": "alarm", - "index": 6, - "description": "Storage State of Charge is Too Low. Minimum Reserve Percentage (of usable capacity) reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SocLoAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SocLoAlm.BI6" - }, - { - "category": "alarm", - "index": 7, - "description": "Storage State of Charge is Depleted. Minimum Usable State of Charge Reached.", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DSTO", - "data_object": "SohLoAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DSTO.SohLoAlm.BI7" - }, - { - "category": "alarm", - "index": 8, - "description": "Storage Internal Temperature is Too High", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DBAT", - "data_object": "IntnTmpHiAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DBAT.IntnTmpHiAlm.BI8" - }, - { - "category": "alarm", - "index": 9, - "description": "Storage External (Ambient) Temperature is Too High", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "DBAT", - "data_object": "ExtTmpHiAlm", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "DBAT.ExtTmpHiAlm.BI9" - }, - { - "index": 10, - "description": "System Is In Local State. System has been locked by a local operator which prevents other operators from executing commands. Note: Local State is also sometimes referred to as Maintenance State. Local State overrides Lockout State.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and in maintenance", - "allowed_values": { - "0": "System not in local state", - "1": "System in local state" - }, - "name": "DSTO.DEROpSt.disconnectedandinmaintenance.BI10" - }, - { - "index": 11, - "description": "System Is In Lockout State. System has been locked by an operator such that other operators may not execute commands. Lockout State is also sometimes referred to as Blocked State.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and blocked", - "allowed_values": { - "0": "System not locked out", - "1": "System locked out" - }, - "name": "DSTO.DEROpSt.disconnectedandblocked.BI11" - }, - { - "index": 12, - "description": "System Is Starting Up. Set to 1 when a BO \"System Initiate Start-up Sequence\" command has been received.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.starting and synchronizing", - "allowed_values": { - "0": "Not Starting Up", - "1": "Start command has been received." - }, - "name": "DSTO.DEROpSt.startingandsynchronizing.BI12" - }, - { - "index": 13, - "description": "System Is Stopping. Set to 1 when an B0 \"System Execute Stop\" command has been received.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.stopping", - "allowed_values": { - "0": "Not Stopping", - "1": "Emergency stop command has been received." - }, - "name": "DSTO.DEROpSt.stopping.BI13" - }, - { - "index": 14, - "description": "System is Started (Return to Service). If any of the DER Units are started,then true. DER Units in the maintenance operational state are excluded.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and idle", - "allowed_values": { - "0": "Null", - "1": "Started" - }, - "name": "DSTO.DEROpSt.connectedandidle.BI14" - }, - { - "index": 15, - "description": "System is Stopped (Cease to Energize). If all of the DER Units are stopped, then true. DER Units in the maintenance operational state are excluded.", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.ceased to energize", - "allowed_values": { - "0": "Null", - "1": "Stopped" - }, - "name": "DSTO.DEROpSt.ceasedtoenergize.BI15" - }, - { - "index": 16, - "description": "System Permission to Start Status", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmConn", - "allowed_values": { - "0": "Start Permission Not Granted", - "1": "Start Permission Granted" - }, - "name": "DSTO.PrmConn.BI16" - }, - { - "index": 17, - "description": "System Permission to Stop Status", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmDscon", - "allowed_values": { - "0": "Stop Permission Not Granted", - "1": "Stop Permission Granted" - }, - "name": "DSTO.PrmDscon.BI17" - }, - { - "index": 18, - "description": "DER is Connected and Idle", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and idle", - "allowed_values": { - "0": "Null", - "1": "Idle-Connected" - }, - "name": "DSTO.DEROpSt.connectedandidle.BI18" - }, - { - "index": 19, - "description": "DER is Connected and Generating", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and generating", - "allowed_values": { - "0": "Null", - "1": "On-Connected" - }, - "name": "DSTO.DEROpSt.connectedandgenerating.BI19" - }, - { - "index": 20, - "description": "DER is Connected and Charging", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.connected and consuming", - "allowed_values": { - "0": "Null", - "1": "On-Charging-Connected" - }, - "name": "DSTO.DEROpSt.connectedandconsuming.BI20" - }, - { - "index": 21, - "description": "DER is Off but Available to Start", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and available", - "allowed_values": { - "0": "Null", - "1": "Off-Available" - }, - "name": "DSTO.DEROpSt.disconnectedandavailable.BI21" - }, - { - "index": 22, - "description": "DER is Off and Not Available to Start", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and stand-by", - "allowed_values": { - "0": "Null", - "1": "Off-Not-Available" - }, - "name": "DSTO.DEROpSt.disconnectedandstand-by.BI22" - }, - { - "index": 23, - "description": "DER Connect/Disconnect Switch Closed Status", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.off", - "allowed_values": { - "0": "Open", - "1": "Closed" - }, - "name": "DSTO.DEROpSt.off.BI23" - }, - { - "index": 24, - "description": "DER Connect/Disconnect Switch Movement Status", - "data_type": "BI", - "common_data_class": "DPC", - "ln_class": "CSWI", - "data_object": "Pos", - "allowed_values": { - "0": "Not Moving", - "1": "Moving" - }, - "name": "CSWI.Pos.BI24" - }, - { - "index": 25, - "description": "Islanded Mode. Determines how the DER behaves when in an Islanded configuration.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "IsldCtlFol", - "allowed_values": { - "0": "Isochronous Mode. DER attempts to control voltage and frequency independent of configured curves and settings up to the limits of the machine's capabilities in order to achieve the AO Reference Voltage and AO nominal frequency.", - "1": "Droop Mode. DER acts as a follower using Volt/VAR and Freq/Watt curves." - }, - "event_class": 3, - "name": "DSTO.IsldCtlFol.BI25" - }, - { - "index": 26, - "description": "Sensed Grid Config Detection Enabled. If Enabled, the DER may independently change its Active Settings Group based on locally observed grid conditions.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DECP", - "data_object": "ECPIsldAuto", - "allowed_values": { - "0": "No Autonomous Detection.", - "1": "Autonomous Detection. Inverter's Active Settings Group may differ from the Requested Settings Group" - }, - "event_class": 3, - "name": "DECP.ECPIsldAuto.BI26" - }, - { - "index": 27, - "description": "Storage Capacity Units. Determines whether energy storage values are expressed in units of Amp-hrs or Watt-hrs.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "AGra", - "allowed_values": { - "0": "Amp-hrs (default)", - "1": "Watt-hrs" - }, - "event_class": 3, - "name": "DSTO.AGra.BI27" - }, - { - "index": 28, - "description": "Time Constant Mode. Indicates whether Time Constant Ramp parameters are interpreted as Open Loop Response times or 3Tau values.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "OpnLoopTau", - "allowed_values": { - "0": "Open Loop Response Time", - "1": "3Tau Value" - }, - "event_class": 3, - "name": "DSTO.OpnLoopTau.BI28" - }, - { - "index": 29, - "description": "Power Factor Excitation When Discharging/Generating", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFGnExtSet", - "allowed_values": { - "0": "Injecting VARs - Q1", - "1": "Absorbing VARs - Q4" - }, - "name": "DFPF.PFGnExtSet.BI29" - }, - { - "index": 30, - "description": "Power Factor Excitation When Charging", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFLodExtSet", - "allowed_values": { - "0": "Injecting VARs - Q2", - "1": "Absorbing VARs - Q3" - }, - "name": "DFPF.PFLodExtSet.BI30" - }, - { - "index": 31, - "description": "Supports Low/High Voltage Ride-Through Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DHVT", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DHVT.BI31" - }, - { - "index": 32, - "description": "Supports Low/High Frequency Ride-Through Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DHFT", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DHFT.BI32" - }, - { - "index": 33, - "description": "Supports Dynamic Reactive Current Support Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DRGS", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DRGS.BI33" - }, - { - "index": 34, - "description": "Supports Dynamic Volt-Watt Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVWD", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVWD.BI34" - }, - { - "index": 35, - "description": "Supports Frequency-Watt Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DHFW", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DHFW.BI35" - }, - { - "index": 36, - "description": "Supports Active Power Limit Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWLM", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWLM.BI36" - }, - { - "index": 37, - "description": "Supports Charge/Discharge Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWGC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWGC.BI37" - }, - { - "index": 38, - "description": "Supports Coordinated Charge/Discharge Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DTCD", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DTCD.BI38" - }, - { - "index": 39, - "description": "Supports Active Power Response Mode #1", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DLFL", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DLFL.BI39" - }, - { - "index": 40, - "description": "Supports Active Power Response Mode #2", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DGFL", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DGFL.BI40" - }, - { - "index": 41, - "description": "Supports Active Power Response Mode #3", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DGFL", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DGFL.BI41" - }, - { - "index": 42, - "description": "Supports Automatic Generation Control Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DAGC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DAGC.BI42" - }, - { - "index": 43, - "description": "Supports Active Power Smoothing Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWSM", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWSM.BI43" - }, - { - "index": 44, - "description": "Supports Volt-Watt Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVWC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVWC.BI44" - }, - { - "index": 45, - "description": "Supports Frequency-Watt Curve Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DFWC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DFWC.BI45" - }, - { - "index": 46, - "description": "Supports Constant VArs Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVAR", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVAR.BI46" - }, - { - "index": 47, - "description": "Supports Fixed Power Factor Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DFPF", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DFPF.BI47" - }, - { - "index": 48, - "description": "Supports Volt-VAr Control Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DVVC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DVVC.BI48" - }, - { - "index": 49, - "description": "Supports Watt-VAr Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DWVR", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DWVR.BI49" - }, - { - "index": 50, - "description": "Supports Power Factor Correction Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DPFC", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DPFC.BI50" - }, - { - "index": 51, - "description": "Supports Pricing Mode", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "DPRG", - "allowed_values": { - "0": "Not Supported", - "1": "Supported" - }, - "event_class": 0, - "name": "DPRG.BI51" - }, - { - "index": 52, - "description": "Overvoltage Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTOV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTOV.Blk.BI52" - }, - { - "index": 53, - "description": "Overvoltage Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTOV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTOV.Str.general.BI53" - }, - { - "index": 54, - "description": "Overvoltage Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTOV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTOV.Op.general.BI54" - }, - { - "index": 55, - "description": "Undervoltage Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTUV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTUV.Blk.BI55" - }, - { - "index": 56, - "description": "Undervoltage Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTUV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTUV.Str.general.BI56" - }, - { - "index": 57, - "description": "Undervoltage Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTUV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTUV.Op.general.BI57" - }, - { - "index": 58, - "description": "Over Frequency Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTOV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTOV.Blk.BI58" - }, - { - "index": 59, - "description": "Over Frequency Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTOV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTOV.Str.general.BI59" - }, - { - "index": 60, - "description": "Over Frequency Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTOV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTOV.Op.general.BI60" - }, - { - "index": 61, - "description": "Under Frequency Disconnect Protection Blocked", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "PTUV", - "data_object": "Blk", - "allowed_values": { - "0": "Not Blocked", - "1": "Blocked (Disabled)" - }, - "event_class": 1, - "name": "PTUV.Blk.BI61" - }, - { - "index": 62, - "description": "Under Frequency Disconnect Protection Started", - "data_type": "BI", - "common_data_class": "ACD", - "ln_class": "PTUV", - "data_object": "Str.general", - "allowed_values": { - "0": "Not Started", - "1": "Started (Evaluating)" - }, - "event_class": 1, - "name": "PTUV.Str.general.BI62" - }, - { - "index": 63, - "description": "Under Frequency Disconnect Protection Operated", - "data_type": "BI", - "common_data_class": "ACT", - "ln_class": "PTUV", - "data_object": "Op.general", - "allowed_values": { - "0": "Not Operated", - "1": "Operated (Disconnected)" - }, - "event_class": 1, - "name": "PTUV.Op.general.BI63" - }, - { - "category": "mode_enable", - "index": 64, - "description": "Operating Mode - Low/High Voltage Ride-Through", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHVT", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHVT.ModEna.BI64" - }, - { - "category": "mode_enable", - "index": 65, - "description": "Operating Mode - Low/High Frequency Ride-Through", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHFT", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFT.ModEna.BI65" - }, - { - "category": "mode_enable", - "index": 66, - "description": "Operating Mode - Dynamic Reactive Current Support Enabled", - "data_type": "BI", - "common_data_class": "ENC", - "ln_class": "DRGS", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DRGS.ModEna.BI66" - }, - { - "category": "mode_enable", - "index": 67, - "description": "Operating Mode - Dynamic Volt-Watt Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVWD", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVWD.ModEna.BI67" - }, - { - "category": "mode_enable", - "index": 68, - "description": "Operating Mode - Frequency-Watt Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFW.ModEna.BI68" - }, - { - "category": "mode_enable", - "index": 69, - "description": "Operating Mode - Active Power Limit Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWLM", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWLM.ModEna.BI69" - }, - { - "category": "mode_enable", - "index": 70, - "description": "Operating Mode - Charge/Discharge Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWGC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWGC.ModEna.BI70" - }, - { - "category": "mode_enable", - "index": 71, - "description": "Operating Mode - Coordinated Charge/Discharge Management Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DTCD", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DTCD.ModEna.BI71" - }, - { - "category": "mode_enable", - "index": 72, - "description": "Operating Mode - Active Power Response Mode #1 Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DPKP", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DPKP.ModEna.BI72" - }, - { - "category": "mode_enable", - "index": 73, - "description": "Operating Mode - Active Power Response Mode #2 Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DGFL", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DGFL.ModEna.BI73" - }, - { - "category": "mode_enable", - "index": 74, - "description": "Operating Mode - Active Power Response Mode #3 Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DLFL", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DLFL.ModEna.BI74" - }, - { - "category": "mode_enable", - "index": 75, - "description": "Operating Mode - Automatic Generation Control Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DAGC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DAGC.ModEna.BI75" - }, - { - "category": "mode_enable", - "index": 76, - "description": "Operating Mode - Active Power Smoothing Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWSM", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWSM.ModEna.BI76" - }, - { - "category": "mode_enable", - "index": 77, - "description": "Operating Mode - Volt-Watt Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVWC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVWC.ModEna.BI77" - }, - { - "category": "mode_enable", - "index": 78, - "description": "Operating Mode - Frequency-Watt Curve Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFW.ModEna.BI78" - }, - { - "category": "mode_enable", - "index": 79, - "description": "Operating Mode - Constant VArs Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVAR", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVAR.ModEna.BI79" - }, - { - "category": "mode_enable", - "index": 80, - "description": "Operating Mode - Fixed Power Factor Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DFPF", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DFPF.ModEna.BI80" - }, - { - "category": "mode_enable", - "index": 81, - "description": "Operating Mode - Volt-VAR Control Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DVVR", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVVR.ModEna.BI81" - }, - { - "category": "mode_enable", - "index": 82, - "description": "Operating Mode - Watt-VAr Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DWVR", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DWVR.ModEna.BI82" - }, - { - "category": "mode_enable", - "index": 83, - "description": "Operating Mode - Power Factor Correction Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DPFC", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DPFC.ModEna.BI83" - }, - { - "category": "mode_enable", - "index": 84, - "description": "Operating Mode - Pricing Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DPRG", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DPRG.ModEna.BI84" - }, - { - "category": "mode_enable", - "index": 85, - "description": "Operating Mode - Event-Based Reactive Current Support Enabled", - "data_type": "BI", - "common_data_class": "SPC", - "ln_class": "DRGS", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DRGS.ModEna.BI85" - }, - { - "index": 86, - "description": "Frequency-Watt Mode - Use Hysteresis", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DHFW.HysEna.BI86" - }, - { - "index": 87, - "description": "Frequency-Watt Mode - Snapshot of Power", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DHFW.SnptEna.BI87" - }, - { - "index": 88, - "description": "Frequency-Watt Curve Mode - Use Hysteresis", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DLFW.HysEna.BI88" - }, - { - "index": 89, - "description": "Frequency-Watt Curve Mode - Snapshot of Power", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DLFW.SnptEna.BI89" - }, - { - "index": 90, - "description": "Charge/Discharge Mode - Use Ramp Rates. Indicates whether or not Charge/Discharge should use specified ramp rates or ramp times.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DWGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constants", - "1": "Use Ramp Rates" - }, - "name": "DWGC.UseRmpRte.BI90" - }, - { - "index": 91, - "description": "AGC Mode - Use Ramp Rates. Indicates whether or not charge/discharge should use specified ramp rates or ramp times.", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DAGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constants", - "1": "Use Ramp Rates" - }, - "name": "DAGC.UseRmpRte.BI91" - }, - { - "index": 92, - "description": "Volt-Watt - Use Ramp Rates and Time Constants", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DVWC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constants", - "1": "Use Ramp Rates AND Time Constants" - }, - "name": "DVWC.UseRmpRte.BI92" - }, - { - "index": 93, - "description": "Volt-VAr Enable Autonomous Voltage Reference Adjustment", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "DVVR", - "data_object": "VRefAdjEna", - "allowed_values": { - "0": "Disabled", - "1": "Enabled" - }, - "name": "DVVR.VRefAdjEna.BI93" - }, - { - "category": "alarm", - "index": 94, - "description": "System Meter Active Power is Too High", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotW.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotW.range.BI94" - }, - { - "category": "alarm", - "index": 95, - "description": "System Meter Active Power is Too Low", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotW.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotW.range.BI95" - }, - { - "category": "alarm", - "index": 96, - "description": "System Meter Reactive Power is Too High", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotVAr.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotVAr.range.BI96" - }, - { - "category": "alarm", - "index": 97, - "description": "System Meter Reactive Power is Too Low", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotVAr.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotVAr.range.BI97" - }, - { - "category": "alarm", - "index": 98, - "description": "System Meter Power Factor is Too High", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotPF.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotPF.range.BI98" - }, - { - "category": "alarm", - "index": 99, - "description": "System Meter Power Factor is Too Low", - "data_type": "BI", - "common_data_class": "MV", - "ln_class": "MMXU", - "data_object": "TotPF.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.TotPF.range.BI99" - }, - { - "category": "alarm", - "index": 100, - "description": "System Meter Phase A Voltage is Too High", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsA.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsA.range.BI100" - }, - { - "category": "alarm", - "index": 101, - "description": "System Meter Phase A Voltage is Too Low", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsA.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsA.range.BI101" - }, - { - "category": "alarm", - "index": 102, - "description": "System Meter Phase B Voltage is Too High", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsB.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsB.range.BI102" - }, - { - "category": "alarm", - "index": 103, - "description": "System Meter Phase B Voltage is Too Low", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsB.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsB.range.BI103" - }, - { - "category": "alarm", - "index": 104, - "description": "System Meter Phase C Voltage is Too High", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsC.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsC.range.BI104" - }, - { - "category": "alarm", - "index": 105, - "description": "System Meter Phase C Voltage is Too Low", - "data_type": "BI", - "common_data_class": "WYE", - "ln_class": "MMXU", - "data_object": "PhV.phsC.range", - "allowed_values": { - "0": "Normal", - "1": "Alarm" - }, - "event_class": 1, - "name": "MMXU.PhV.phsC.range.BI105" - }, - { - "category": "alarm", - "index": 106, - "description": "System Meter Communication Error", - "data_type": "BI", - "common_data_class": "SPS", - "ln_class": "LCCH", - "data_object": "ChLiv", - "allowed_values": { - "0": "Normal: No Active Communications Error", - "1": "Alarm: Active Communications Error" - }, - "event_class": 1, - "name": "LCCH.ChLiv.BI106" - }, - { - "index": 107, - "description": "Selected Curve is Referenced by a Mode", - "data_type": "BI", - "allowed_values": { - "0": "Curve is not Referenced", - "1": "Curve is Referenced" - }, - "event_class": 1, - "name": "BI107" - }, - { - "index": 108, - "description": "Selected Schedule Is Ready", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "FSCH", - "data_object": "SchdSt.3", - "allowed_values": { - "0": "Not Ready", - "1": "Ready" - }, - "name": "FSCH.SchdSt.3.BI108" - }, - { - "index": 109, - "description": "Selected Schedule is Validated", - "data_type": "BI", - "common_data_class": "ENS", - "ln_class": "FSCH", - "data_object": "SchdSt.2", - "allowed_values": { - "0": "Not validated", - "1": "Validated" - }, - "name": "FSCH.SchdSt.2.BI109" - }, - { - "index": 110, - "description": "Selected Schedule Repeat Weekly Sunday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI110" - }, - { - "index": 111, - "description": "Selected Schedule Repeat Weekly Monday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI111" - }, - { - "index": 112, - "description": "Selected Schedule Repeat Weekly Tuesday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI112" - }, - { - "index": 113, - "description": "Selected Schedule Repeat Weekly Wednesday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI113" - }, - { - "index": 114, - "description": "Selected Schedule Repeat Weekly Thursday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI114" - }, - { - "index": 115, - "description": "Selected Schedule Repeat Weekly Friday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI115" - }, - { - "index": 116, - "description": "Selected Schedule Repeat Weekly Saturday", - "data_type": "BI", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BI116" - }, - { - "index": 0, - "description": "System Set Lockout State", - "data_type": "BO", - "common_data_class": "ENS", - "ln_class": "DSTO", - "data_object": "DEROpSt.disconnected and blocked", - "allowed_values": { - "0": "Not Locked Out", - "1": "Lock Out" - }, - "name": "DSTO.DEROpSt.disconnectedandblocked.BO0" - }, - { - "index": 1, - "description": "System Initiate Start-up Sequence (Return to Service). Setting this to 1 does the following: - Sets BI \"System Is Starting Up\" to 1 indicating that the system is starting up. Additional start-up status can be found in AI \"System Start-up Status\". - Instructs all batteries to connect. - Once each battery has reported that it has connect successfully, instructs corresponding DER Unit to start. System can be shut down by executing B0 \"Emergency Stop\" command. This operation is the same as California Rule 21 \"Soft Start\".", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DCTE", - "data_object": "RtnSrvReq", - "allowed_values": { - "0": "No Change", - "1": "Initiate Start-up" - }, - "name": "DCTE.RtnSrvReq.BO1" - }, - { - "index": 2, - "description": "System Execute Stop (Cease to Energize). Setting this to 1 does the following: - Sets BI \"System Is Emergency Stopping\" to 1 indicating that an emergency stop is in progress. - Ensures that any executing operating modes are shut down (disabled). - Ensures that any executing schedules are shut down (disabled). - Instructs all inverters to shut down. - Instructs all batteries to disconnect. System can be started again by executing BO \"Initiate Start-up Sequence\" command.", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DCTE", - "data_object": "CeaEngzReq", - "allowed_values": { - "0": "No Change", - "1": "Stop (Emergency)" - }, - "name": "DCTE.CeaEngzReq.BO2" - }, - { - "index": 3, - "description": "System Permission to Start", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmConn", - "allowed_values": { - "0": "DCTE", - "1": "Start Permission Granted" - }, - "name": "DSTO.PrmConn.BO3" - }, - { - "index": 4, - "description": "System Permission to Stop", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DSTO", - "data_object": "PrmDscon", - "allowed_values": { - "0": "DCTE", - "1": "Stop Permission Granted" - }, - "name": "DSTO.PrmDscon.BO4" - }, - { - "index": 5, - "description": "DER Connect/Disconnect Switch", - "data_type": "BO", - "common_data_class": "DPC", - "ln_class": "CSWI", - "data_object": "Pos", - "allowed_values": { - "0": "Open Switch", - "1": "Close Switch" - }, - "name": "CSWI.Pos.BO5" - }, - { - "index": 6, - "description": "Islanded Mode. Determines how the DER behaves when in an Islanded configuration.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DGEN", - "data_object": "IsldCtlFol", - "allowed_values": { - "0": "Isochronous Mode. DER attempts to control voltage and frequency independent of configured curves and settings up to the limits of the machine's capabilities in order to achieve AO reference voltage and AO nominal frequency.", - "1": "Droop Mode. DER acts as a follower using Volt/VAR and Freq/Watt curves." - }, - "name": "DGEN.IsldCtlFol.BO6" - }, - { - "index": 7, - "description": "Enable Sensed Grid Config Detection. If Enabled, the DER may independently change its Active Settings Group based on locally observed grid conditions.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DECP", - "data_object": "ECPIsldAuto", - "allowed_values": { - "0": "No Autonomous Detection.", - "1": "Autonomous Detection. Inverter's Active Settings Group may differ from the Requested Settings Group" - }, - "name": "DECP.ECPIsldAuto.BO7" - }, - { - "index": 8, - "description": "Storage Capacity Units. Determines whether the energy storage values are expressed in Amp-hrs or Watt-hrs.", - "data_type": "BO", - "common_data_class": "ASG", - "ln_class": "DSTO", - "data_object": "AGra", - "allowed_values": { - "0": "Amp-hrs (default)", - "1": "Watt-hrs" - }, - "name": "DSTO.AGra.BO8" - }, - { - "index": 9, - "description": "Time Constant Mode. Indicates whether Time Constant Ramp parameters are interpreted as Open Loop Response times or 3Tau values.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DSTO", - "data_object": "OpnLoopTau", - "allowed_values": { - "0": "Open Loop Response Time", - "1": "3Tau Value" - }, - "name": "DSTO.OpnLoopTau.BO9" - }, - { - "index": 10, - "description": "Power Factor Excitation When Discharging/Generating", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFGnExtSet", - "allowed_values": { - "0": "Producing VARs - Q1", - "1": "Absorbing VARs - Q4" - }, - "name": "DFPF.PFGnExtSet.BO10" - }, - { - "index": 11, - "description": "Power Factor Excitation When Charging", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DFPF", - "data_object": "PFLodExtSet", - "allowed_values": { - "0": "Producing VARs - Q2", - "1": "Absorbing VARs - Q3" - }, - "name": "DFPF.PFLodExtSet.BO11" - }, - { - "category": "mode_enable", - "index": 12, - "description": "Enable Low/High Voltage Ride-Through Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHVT", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHVT.ModEna.BI64", - "name": "DHVT.ModEna.BO12" - }, - { - "category": "mode_enable", - "index": 13, - "description": "Enable Low/High Frequency Ride-Through Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHFT", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHFT.ModEna.BI65", - "name": "DHFT.ModEna.BO13" - }, - { - "category": "mode_enable", - "index": 14, - "description": "Enable Dynamic Reactive Current Support Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DRGS", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DRGS.ModEna.BI66", - "name": "DRGS.ModEna.BO14" - }, - { - "category": "mode_enable", - "index": 15, - "description": "Enable Dynamic Volt-Watt Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVWD", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVWD.ModEna.BI67", - "name": "DVWD.ModEna.BO15" - }, - { - "category": "mode_enable", - "index": 16, - "description": "Enable Frequency-Watt Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHFW.ModEna.BI68", - "name": "DHFW.ModEna.BO16" - }, - { - "category": "mode_enable", - "index": 17, - "description": "Enable Active Power Limit Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWLM", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DWLM.ModEna.BI69", - "name": "DWLM.ModEna.BO17" - }, - { - "category": "mode_enable", - "index": 18, - "description": "Enable Charge/Discharge Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWGC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DTCD.ModEna.BI71", - "name": "DWGC.ModEna.BO18" - }, - { - "category": "mode_enable", - "index": 19, - "description": "Enable Coordinated Charge/Discharge Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DTCD", - "action": "publish", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DTCD.ModEna.BO19" - }, - { - "category": "mode_enable", - "index": 20, - "description": "Enable Active Power Response Mode #1", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DPKP", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DPKP.ModEna.BI72", - "name": "DPKP.ModEna.BO20" - }, - { - "category": "mode_enable", - "index": 21, - "description": "Enable Active Power Response Mode #2", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DGFL", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DGFL.ModEna.BI73", - "name": "DGFL.ModEna.BO21" - }, - { - "category": "mode_enable", - "index": 22, - "description": "Enable Active Power Response Mode #3", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DLFL", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DLFL.ModEna.BI74", - "name": "DLFL.ModEna.BO22" - }, - { - "category": "mode_enable", - "index": 23, - "description": "Enable Automatic Generation Control Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DAGC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DAGC.ModEna.BI75", - "name": "DAGC.ModEna.BO23" - }, - { - "category": "mode_enable", - "index": 24, - "description": "Enable Active Power Smoothing Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWSM", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DWSM.ModEna.BI76", - "name": "DWSM.ModEna.BO24" - }, - { - "category": "mode_enable", - "index": 25, - "description": "Enable Volt-Watt Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVWC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVWC.ModEna.BI77", - "name": "DVWC.ModEna.BO25" - }, - { - "category": "mode_enable", - "index": 26, - "description": "Enable Frequency-Watt Curve Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DHFW", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DHFW.ModEna.BI78", - "name": "DHFW.ModEna.BO26" - }, - { - "category": "mode_enable", - "index": 27, - "description": "Enable Constant VArs Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVAR", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVAR.ModEna.BI79", - "name": "DVAR.ModEna.BO27" - }, - { - "category": "mode_enable", - "index": 28, - "description": "Enable Fixed Power Factor Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DFPF", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DFPF.BI47", - "name": "DFPF.ModEna.BO28" - }, - { - "category": "mode_enable", - "index": 29, - "description": "Enable Volt-VAR Control Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DVVC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DVVC.BI48", - "name": "DVVC.ModEna.BO29" - }, - { - "category": "mode_enable", - "index": 30, - "description": "Enable Watt-VAr Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DWVR", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DWVR.BI49", - "name": "DWVR.ModEna.BO30" - }, - { - "category": "mode_enable", - "index": 31, - "description": "Enable Power Factor Correction Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DPFC", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DPFC.ModEna.BI83", - "name": "DPFC.ModEna.BO31" - }, - { - "category": "mode_enable", - "index": 32, - "description": "Enable Pricing Mode", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DPRG", - "action": "publish_and_respond", - "data_object": "ModEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "response": "DPRG.ModEna.BI84", - "name": "DPRG.ModEna.BO32" - }, - { - "index": 33, - "description": "Enable Event-Based Reactive Current Support Mode, in which the moving average voltage and the base reactive current are frozen until after the voltage has returned to within the deadband for a specified hold time. Dynamic Reactive Current Support mode must be Enable for this setting to apply.", - "data_type": "BO", - "common_data_class": "SPC", - "ln_class": "DRGS", - "data_object": "ArGraMod", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DRGS.ArGraMod.BO33" - }, - { - "index": 34, - "description": "Frequency-Watt Mode - Use Hysteresis", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DHFW.HysEna.BO34" - }, - { - "index": 35, - "description": "Frequency-Watt Mode - Snapshot of Power", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DHFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DHFW.SnptEna.BO35" - }, - { - "index": 36, - "description": "Frequency-Watt Curve Mode - Use Hysteresis", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "HysEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DLFW.HysEna.BO36" - }, - { - "index": 37, - "description": "Frequency-Watt Curve Mode - Snapshot of Power", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DLFW", - "data_object": "SnptEna", - "allowed_values": { - "0": "Not Active", - "1": "Active" - }, - "name": "DLFW.SnptEna.BO37" - }, - { - "index": 38, - "description": "Charge/Discharge Mode - Use Ramp Rates. Indicates whether or not Charge/Discharge should use specified ramp rates or time constants.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DWGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constatnts", - "1": "Use Ramp Rates" - }, - "name": "DWGC.UseRmpRte.BO38" - }, - { - "index": 39, - "description": "AGC Mode - Use Ramp Rates. Indicates whether or not AGC mode should use specified ramp rates or time constants.", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DAGC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constatnts", - "1": "Use Ramp Rates" - }, - "name": "DAGC.UseRmpRte.BO39" - }, - { - "index": 40, - "description": "Volt-Watt - Use Ramp Rates and Time Constants. Indicates whether Volt-Watt mode should use only Time Constants,or both Time Constants and Ramp Rates", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DVWC", - "data_object": "UseRmpRte", - "allowed_values": { - "0": "Use Time Constatnts", - "1": "Use Ramp Rates AND Time Constants" - }, - "name": "DVWC.UseRmpRte.BO40" - }, - { - "index": 41, - "description": "Volt-VAr Enable Autonomous Voltage Reference Adjustment", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "DVVR", - "data_object": "VRefAdjEna", - "allowed_values": { - "0": "Disable", - "1": "Enable" - }, - "name": "DVVR.VRefAdjEna.BO41" - }, - { - "index": 42, - "description": "Set Selected Scheduled Ready", - "data_type": "BO", - "common_data_class": "ENC", - "ln_class": "FSCH", - "data_object": "Mod", - "allowed_values": { - "0": "Not Ready", - "1": "Ready" - }, - "name": "FSCHxx.Mod.BO42" - }, - { - "index": 43, - "description": "Set Selected Schedule Repeat Weekly Sunday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO43" - }, - { - "index": 44, - "description": "Set Selected Schedule Repeat Weekly Monday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO44" - }, - { - "index": 45, - "description": "Set Selected Schedule Repeat Weekly Tuesday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO45" - }, - { - "index": 46, - "description": "Set Selected Schedule Repeat Weekly Wednesday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO46" - }, - { - "index": 47, - "description": "Set Selected Schedule Repeat Weekly Thursday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO47" - }, - { - "index": 48, - "description": "Set Selected Schedule Repeat Weekly Friday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO48" - }, - { - "index": 49, - "description": "Set Selected Schedule Repeat Weekly Saturday", - "data_type": "BO", - "common_data_class": "SPG", - "ln_class": "FSCH", - "data_object": "SchdReuse", - "allowed_values": { - "0": "Do Not Repeat", - "1": "Repeat" - }, - "name": "FSCHxx.SchdReuse.BO49" - }, - { - "index": 900, - "description": "Test Point for Database Size", - "data_type": "BI", - "name": "TestPoint.BI900" - } -] \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/data/mesaagent.config b/services/core/DNP3Agent/tests/data/mesaagent.config deleted file mode 100644 index ecfe2a73cb..0000000000 --- a/services/core/DNP3Agent/tests/data/mesaagent.config +++ /dev/null @@ -1,15 +0,0 @@ -{ - "points": "config://mesa_points.config", - "functions": "config://mesa_functions.config", - "point_topic": "mesa/point", - "function_topic": "mesa/function", - "outstation_status_topic": "mesa/outstation_status", - "outstation_config": { - "database_sizes": 2000, - "log_levels": ["NORMAL"] - }, - "local_ip": "0.0.0.0", - "port": 20000, - "all_functions_supported_by_default": true, - "function_validation": false -} diff --git a/services/core/DNP3Agent/tests/data/watt_var_curve.json b/services/core/DNP3Agent/tests/data/watt_var_curve.json deleted file mode 100644 index 5de59f07eb..0000000000 --- a/services/core/DNP3Agent/tests/data/watt_var_curve.json +++ /dev/null @@ -1,26 +0,0 @@ -{ - "function_id": "curve", - "function_name": "Watt-Var Curve", - "DGSMn.InCrv.AO244": 2, - "DGSMn.ModTyp.AO245": 4, - "FMARn.IndpUnits.AO247": 138, - "FMARn.DepRef.AO248": 2, - "FMARn.PairArr.CrvPts.AO249": [ - {"FMARn.PairArr.CrvPts.AO249.xVal": 1, - "FMARn.PairArr.CrvPts.AO249.yVal": 2 - }, - {"FMARn.PairArr.CrvPts.AO249.xVal": 3, - "FMARn.PairArr.CrvPts.AO249.yVal": 4 - }, - {"FMARn.PairArr.CrvPts.AO249.xVal": 5, - "FMARn.PairArr.CrvPts.AO249.yVal": 6 - }, - {"FMARn.PairArr.CrvPts.AO249.xVal": 7, - "FMARn.PairArr.CrvPts.AO249.yVal": 8 - }, - {"FMARn.PairArr.CrvPts.AO249.xVal": 9, - "FMARn.PairArr.CrvPts.AO249.yVal": 10 - } - ], - "FMARn.PairArr.NumPts.AO246": 5 -} \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/data/watt_var_schedule.json b/services/core/DNP3Agent/tests/data/watt_var_schedule.json deleted file mode 100644 index 6a7a509aab..0000000000 --- a/services/core/DNP3Agent/tests/data/watt_var_schedule.json +++ /dev/null @@ -1,30 +0,0 @@ -{ - "function_id": "schedule", - "function_name": "Watt-Var Schedule", - "FSCC.Schd.AO461": 2, - "FSCC.Schd.AO462": 1, - "FSCH1.SchdPrio.AO463": 1, - "FSCH.SchdVal.valEq.AO464": 28, - "FSCH.StrTm.AO465": 19, - "FSCH.StrTm.AO466": 5, - "FSCH.NxtStrTm.AO467": 0, - "FSCH.SchdReuse.AO468": 0, - "FSCHn.SchdEntr.AO470": [ - {"FSCHn.SchdEntr.AO470.time": 1, - "FSCHn.SchdEntr.AO470.val": 2 - }, - {"FSCHn.SchdEntr.AO470.time": 3, - "FSCHn.SchdEntr.AO470.val": 4 - }, - {"FSCHn.SchdEntr.AO470.time": 5, - "FSCHn.SchdEntr.AO470.val": 6 - }, - {"FSCHn.SchdEntr.AO470.time": 7, - "FSCHn.SchdEntr.AO470.val": 8 - }, - {"FSCHn.SchdEntr.AO470.time": 9, - "FSCHn.SchdEntr.AO470.val": 10 - } - ], - "FSCH.NumEntr.AO469": 5 -} \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/mesa_master_cmd.py b/services/core/DNP3Agent/tests/mesa_master_cmd.py deleted file mode 100644 index 62043a5d2a..0000000000 --- a/services/core/DNP3Agent/tests/mesa_master_cmd.py +++ /dev/null @@ -1,155 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - -import pytest -try: - import dnp3 -except ImportError: - pytest.skip("pydnp3 not found!", allow_module_level=True) - -import cmd -import logging -import sys - -from pydnp3 import opendnp3 - -from dnp3.points import PointDefinitions -from dnp3 import DIRECT_OPERATE -from mesa_master import MesaMaster -from function_test import FunctionTest - -LOG_LEVELS = opendnp3.levels.NORMAL -SERVER_IP = "127.0.0.1" -CLIENT_IP = "0.0.0.0" -PORT_NUMBER = 20000 -POINT_DEFINITIONS_PATH = 'tests/data/mesa_points.config' -FUNCTION_DEFINITIONS_PATH = 'tests/data/mesa_functions.yaml' - -CURVE_JSON = { - "name": "function_test_curve", - "function_id": "curve", - "function_name": "curve_function", - "Curve Edit Selector": 3, - "Curve Mode Type": 40, - "Curve Time Window": 5000, - "Curve Ramp Time": 24, - "Curve Revert Time": 51, - "Curve Maximum Number of Points": 671, - "Independent (X-Value) Units for Curve": 51, - "Dependent (Y-Value) Units for Curve": 625, - "Curve Time Constant": 612, - "Curve Decreasing Max Ramp Rate": 331, - "Curve Increasing Ramp Rate": 451, - "CurveStart-X": [ - {"Curve-X": 111, "Curve-Y": 2}, - {"Curve-X": 3, "Curve-Y": 4}, - {"Curve-X": 5, "Curve-Y": 6}, - {"Curve-X": 7, "Curve-Y": 8}, - {"Curve-X": 9, "Curve-Y": 10} - ], - "Curve Number of Points": 5 -} - -stdout_stream = logging.StreamHandler(sys.stdout) -stdout_stream.setFormatter(logging.Formatter('%(asctime)s\t%(name)s\t%(levelname)s\t%(message)s')) - -_log = logging.getLogger(__name__) -_log.addHandler(stdout_stream) -_log.setLevel(logging.DEBUG) - - -class MesaMasterCmd(cmd.Cmd): - """ - Run MesaMaster from the command line in support of certain types of ad-hoc outstation testing. - """ - - def __init__(self): - cmd.Cmd.__init__(self) - self.prompt = 'master> ' # Used by the Cmd framework, displayed when issuing a command-line prompt. - self._application = None - - @property - def application(self): - if self._application is None: - self._application = MesaMaster(local_ip=SERVER_IP, port=PORT_NUMBER) - self._application.connect() - return self._application - - def startup(self): - """Display the command-line interface's menu and issue a prompt.""" - self.do_menu('') - self.cmdloop('Please enter a command.') - exit() - - def do_menu(self, line): - """Display a menu of command-line options. Command syntax is: menu""" - print('\tfunction\tSend all data/commands for the MESA-ESS function.') - print('\tquit') - - def do_function(self, line): - """Send a function test after validating the function test (as JSON).""" - point_defs = PointDefinitions(point_definitions_path=POINT_DEFINITIONS_PATH) - ftest = FunctionTest(FUNCTION_DEFINITIONS_PATH, CURVE_JSON) - ftest.is_valid() - for func_step_def in ftest.get_function_def().steps: - try: - point_value = ftest.points[func_step_def.name] - except KeyError: - continue - pdef = point_defs.point_named(func_step_def.name) - if not pdef: - raise ValueError("Point definition not found: {}".format(pdef.name)) - - if type(point_value) == list: - self.application.send_array(point_value, pdef) - else: - try: - send_func = self.application.SEND_FUNCTIONS[func_step_def.fcodes[0] - if func_step_def.fcodes - else DIRECT_OPERATE] - except (KeyError, IndexError): - raise ValueError("Unrecognized sent command function") - - self.application.send_command(send_func, pdef, point_value) - - def do_quit(self, line): - """Quit the command line interface. Command syntax is: quit""" - self.application.shutdown() - exit() - - -def main(): - cmd_interface = MesaMasterCmd() - _log.debug('Initialization complete. In command loop.') - cmd_interface.startup() - _log.debug('Exiting.') - - -if __name__ == '__main__': - main() diff --git a/services/core/DNP3Agent/tests/mesa_master_test.py b/services/core/DNP3Agent/tests/mesa_master_test.py deleted file mode 100644 index b1d301c458..0000000000 --- a/services/core/DNP3Agent/tests/mesa_master_test.py +++ /dev/null @@ -1,131 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - -import pytest -try: - import dnp3 -except ImportError: - pytest.skip("pydnp3 not found!", allow_module_level=True) - -from volttron.platform import jsonapi -from collections import OrderedDict - -from dnp3 import DIRECT_OPERATE -from dnp3_master import SOEHandler -from mesa_master import MesaMaster -from dnp3.mesa.functions import FunctionDefinitions -from function_test import DATA_TYPE_TO_PYTHON_TYPE - - -class MesaMasterTestException(Exception): - pass - - -class MesaMasterTest(MesaMaster): - - def __init__(self, **kwargs): - MesaMaster.__init__(self, soe_handler=SOEHandler(), **kwargs) - - def shutdown(self): - """ - Override MesaMaster shutdown - """ - self.master.Disable() - del self.master - del self.channel - - def send_single_point(self, pdefs, point_name, point_value): - """ - Send a single non-function point to the outstation. Check for validation. - - Used by DNP3Agent (not MesaAgent). - - :param pdefs: point definitions - :param point_name: name of the point that will be sent - :param point_value: value of the point that will be sent - """ - pdef = pdefs.point_named(point_name) - if not pdef: - raise MesaMasterTestException("Point definition not found: {}".format(point_name)) - if not pdef.data_type: - raise MesaMasterTestException("Unrecognized data type: {}".format(pdef.data_type)) - if pdef.data_type in DATA_TYPE_TO_PYTHON_TYPE and \ - type(point_value) not in DATA_TYPE_TO_PYTHON_TYPE[pdef.data_type]: - raise MesaMasterTestException("Invalid point value: {}".format(pdef.name)) - self.send_command(self.send_direct_operate_command, pdef, point_value) - - def send_json(self, pdefs, func_def_path, send_json_path='', send_json=None): - """ - Send a json in order for testing purpose. - - :param pdefs: point definitions - :param func_def_path: path to function definition - :param send_json_path: path to json that will be sent to the outstation - :param send_json: json that will be sent to the outstation - :return: - """ - if send_json_path: - send_json = jsonapi.load(open(send_json_path), object_pairs_hook=OrderedDict) - - try: - function_id = send_json['function_id'] - except KeyError: - raise MesaMasterTestException('Missing function_id') - - fdefs = FunctionDefinitions(pdefs, function_definitions_path=func_def_path) - - try: - fdef = fdefs[function_id] - except KeyError: - raise MesaMasterTestException('Invalid function_id {}'.format(function_id)) - - step = 1 - for name, value in send_json.items(): - if name not in ['name', 'function_id', 'function_name']: - pdef = pdefs.point_named(name) - step_def = fdef[pdef] - if step != step_def.step_number: - raise MesaMasterTestException("Step not in order: {}".format(step)) - if type(value) == list: - self.send_array(value, pdef) - else: - send_func = self.SEND_FUNCTIONS.get(step_def.fcodes[0] if step_def.fcodes else DIRECT_OPERATE, None) - self.send_command(send_func, pdef, value) - step += 1 - - -def main(): - mesa_platform_test = MesaMasterTest() - mesa_platform_test.connect() - # Ad-hoc tests can be inserted here if desired. - mesa_platform_test.shutdown() - - -if __name__ == '__main__': - main() diff --git a/services/core/DNP3Agent/tests/test_dnp3_agent.py b/services/core/DNP3Agent/tests/test_dnp3_agent.py deleted file mode 100644 index 65214e5681..0000000000 --- a/services/core/DNP3Agent/tests/test_dnp3_agent.py +++ /dev/null @@ -1,273 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, SLAC / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# This material was prepared as an account of work sponsored by an agency of -# the United States Government. Neither the United States Government nor the -# United States Department of Energy, nor SLAC, nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by the United States Government or any agency thereof, or -# SLAC, or Kisensum. The views and opinions of authors expressed -# herein do not necessarily state or reflect those of the -# United States Government or any agency thereof. -# }}} - -import pytest -try: - import dnp3 -except ImportError: - pytest.skip("pydnp3 not found!", allow_module_level=True) - -import gevent -import os -import pytest - -from volttron.platform import get_services_core, jsonapi -from volttron.platform.agent.utils import strip_comments - -from dnp3.points import PointDefinitions -from mesa_master_test import MesaMasterTest - -from pydnp3 import asiodnp3, asiopal, opendnp3, openpal - -FILTERS = opendnp3.levels.NORMAL | opendnp3.levels.ALL_COMMS -HOST = "127.0.0.1" -LOCAL = "0.0.0.0" -PORT = 20000 - -DNP3_AGENT_ID = 'dnp3agent' -POINT_TOPIC = "dnp3/point" -TEST_GET_POINT_NAME = 'DCTE.WinTms.AO11' -TEST_SET_POINT_NAME = 'DCTE.WinTms.AI55' - -input_group_map = { - 1: "Binary", - 2: "Binary", - 30: "Analog", - 31: "Analog", - 32: "Analog", - 33: "Analog", - 34: "Analog" -} - -DNP3_AGENT_CONFIG = { - "points": "config://mesa_points.config", - "point_topic": POINT_TOPIC, - "outstation_config": { - "log_levels": ["NORMAL", "ALL_APP_COMMS"] - }, - "local_ip": "0.0.0.0", - "port": 20000 -} - -# Get point definitions from the files in the test directory. -POINT_DEFINITIONS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data', 'mesa_points.config')) - -pdefs = PointDefinitions(point_definitions_path=POINT_DEFINITIONS_PATH) - -AGENT_CONFIG = { - "points": "config://mesa_points.config", - "outstation_config": { - "database_sizes": 700, - "log_levels": ["NORMAL"] - }, - "local_ip": "0.0.0.0", - "port": 20000 -} - -messages = {} - - -def onmessage(peer, sender, bus, topic, headers, message): - """Callback: As DNP3Agent publishes mesa/point messages, store them in a multi-level global dictionary.""" - global messages - messages[topic] = {'headers': headers, 'message': message} - - -def dict_compare(source_dict, target_dict): - """Assert that the value for each key in source_dict matches the corresponding value in target_dict. - - Ignores keys in target_dict that are not in source_dict. - """ - for name, source_val in source_dict.items(): - target_val = target_dict.get(name, None) - assert source_val == target_val, "Source value of {}={}, target value={}".format(name, source_val, target_val) - - -def add_definitions_to_config_store(test_agent): - """Add PointDefinitions to the mesaagent's config store.""" - with open(POINT_DEFINITIONS_PATH, 'r') as f: - points_json = jsonapi.loads(strip_comments(f.read())) - test_agent.vip.rpc.call('config.store', 'set_config', DNP3_AGENT_ID, - 'mesa_points.config', points_json, config_type='raw') - - -@pytest.fixture(scope="module") -def agent(request, volttron_instance): - """Build the test agent for rpc call.""" - - test_agent = volttron_instance.build_agent(identity="test_agent") - capabilities = {'edit_config_store': {'identity': 'dnp3agent'}} - volttron_instance.add_capabilities(test_agent.core.publickey, capabilities) - add_definitions_to_config_store(test_agent) - - print('Installing DNP3Agent') - os.environ['AGENT_MODULE'] = 'dnp3.agent' - agent_id = volttron_instance.install_agent(agent_dir=get_services_core("DNP3Agent"), - config_file=AGENT_CONFIG, - vip_identity=DNP3_AGENT_ID, - start=True) - - # Subscribe to DNP3 point publication - test_agent.vip.pubsub.subscribe(peer='pubsub', prefix=POINT_TOPIC, callback=onmessage) - - def stop(): - """Stop test agent.""" - if volttron_instance.is_running(): - volttron_instance.stop_agent(agent_id) - volttron_instance.remove_agent(agent_id) - test_agent.core.stop() - - gevent.sleep(12) # wait for agents and devices to start - - request.addfinalizer(stop) - - return test_agent - - -@pytest.fixture(scope="module") -def run_master(request): - """Run Mesa master application.""" - master = MesaMasterTest(local_ip=AGENT_CONFIG['local_ip'], port=AGENT_CONFIG['port']) - master.connect() - - def stop(): - master.shutdown() - - request.addfinalizer(stop) - - return master - - -@pytest.fixture(scope="function") -def reset(agent): - """Reset agent and global variable messages before running every test.""" - global messages - messages = {} - agent.vip.rpc.call(DNP3_AGENT_ID, 'reset').get() - - -class TestDNP3Agent: - """Regression tests for (non-MESA) DNP3Agent.""" - - @staticmethod - def get_point(agent, point_name): - """Ask DNP3Agent for a point value for a DNP3 resource.""" - return agent.vip.rpc.call(DNP3_AGENT_ID, 'get_point', point_name).get(timeout=10) - - @staticmethod - def get_point_definitions(agent, point_names): - """Ask DNP3Agent for a list of point definitions.""" - return agent.vip.rpc.call(DNP3_AGENT_ID, 'get_point_definitions', point_names).get(timeout=10) - - @staticmethod - def get_point_by_index(agent, data_type, index): - """Ask DNP3Agent for a point value for a DNP3 resource.""" - return agent.vip.rpc.call(DNP3_AGENT_ID, 'get_point_by_index', data_type, index).get(timeout=10) - - @staticmethod - def set_point(agent, point_name, value): - """Use DNP3Agent to set a point value for a DNP3 resource.""" - response = agent.vip.rpc.call(DNP3_AGENT_ID, 'set_point', point_name, value).get(timeout=10) - gevent.sleep(5) # Give the Master time to receive an echoed point value back from the Outstation. - return response - - @staticmethod - def set_points(agent, point_dict): - """Use DNP3Agent to set point values for a DNP3 resource.""" - return agent.vip.rpc.call(DNP3_AGENT_ID, 'set_points', point_dict).get(timeout=10) - - @staticmethod - def send_single_point(master, point_name, point_value): - """ - Send a point name and value from the Master to DNP3Agent. - - Return a dictionary with an exception key and error, empty if successful. - """ - try: - master.send_single_point(pdefs, point_name, point_value) - return {} - except Exception as err: - exception = {'key': type(err).__name__, 'error': str(err)} - print("Exception sending point from master: {}".format(exception)) - return exception - - @staticmethod - def get_value_from_master(master, point_name): - """Get value of the point from master after being set by test agent.""" - try: - pdef = pdefs.point_named(point_name) - group = input_group_map[pdef.group] - index = pdef.index - return master.soe_handler.result[group][index] - except KeyError: - return None - - def get_point_definition(self, agent, point_name): - """Confirm that the agent has a point definition named point_name. Return the definition.""" - point_defs = self.get_point_definitions(agent, [point_name]) - point_def = point_defs.get(point_name, None) - assert point_def is not None, "Agent has no point definition for {}".format(TEST_GET_POINT_NAME) - return point_def - - @staticmethod - def subscribed_points(): - """Return point values published by DNP3Agent using the dnp3/point topic.""" - return messages[POINT_TOPIC].get('message', {}) - - # ********** - # ********** OUTPUT TESTS (send data from Master to Agent to ControlAgent) ************ - # ********** - - def test_get_point_definition(self, run_master, agent, reset): - """Ask the agent whether it has a point definition for a point name.""" - self.get_point_definition(agent, TEST_GET_POINT_NAME) - - def test_send_point(self, run_master, agent, reset): - """Send a point from the master and get its value from DNP3Agent.""" - exceptions = self.send_single_point(run_master, TEST_GET_POINT_NAME, 45) - assert exceptions == {} - received_point = self.get_point(agent, TEST_GET_POINT_NAME) - # Confirm that the agent's received point value matches the value that was sent. - assert received_point == 45, "Expected {} = {}, got {}".format(TEST_GET_POINT_NAME, 45, received_point) - dict_compare({TEST_GET_POINT_NAME: 45}, self.subscribed_points()) - - # ********** - # ********** INPUT TESTS (send data from ControlAgent to Agent to Master) ************ - # ********** - - def test_set_point(self, run_master, agent, reset): - """Test set an input point and confirm getting the same value for that point.""" - self.set_point(agent, TEST_SET_POINT_NAME, 45) - received_val = self.get_value_from_master(run_master, TEST_SET_POINT_NAME) - assert received_val == 45, "Expected {} = {}, got {}".format(TEST_SET_POINT_NAME, 45, received_val) diff --git a/services/core/DNP3Agent/tests/test_functions.py b/services/core/DNP3Agent/tests/test_functions.py deleted file mode 100644 index ce3cdfc92f..0000000000 --- a/services/core/DNP3Agent/tests/test_functions.py +++ /dev/null @@ -1,369 +0,0 @@ -import pytest -try: - import dnp3 -except ImportError: - pytest.skip("pydnp3 not found!", allow_module_level=True) - -import copy - -from dnp3.points import PointDefinitions -from dnp3.mesa.functions import FunctionDefinitions, FunctionDefinition, StepDefinition - -from test_mesa_agent import POINT_DEFINITIONS_PATH, FUNCTION_DEFINITIONS_PATH - - -POINT_DEFINITIONS = PointDefinitions(point_definitions_path=POINT_DEFINITIONS_PATH) - -enable_high_voltage_ride_through_mode = { - 'id': 'enable_high_voltage_ride_through_mode', - 'name': 'Enable High Volatge Ride-Through Mode', - 'ref': 'AN2018 Spec section 2.5.1 Table 33', - 'steps': [ - { - 'step_number': 1, - 'description': 'Set the Reference Voltage if it is not already set', - 'point_name': 'DECP.VRef.AO0', - 'optional': 'I', - 'fcode': ['direct_operate'], - 'response': 'DECP.VRef.AI29' - }, - { - 'step_number': 2, - 'description': 'Set the Reference Voltage Offset if it is not already set', - 'point_name': 'DECP.VRefOfs.AO1', - 'optional': 'I', - 'fcode': ['direct_operate'], - 'response': 'DECP.VRefOfs.AI30' - }, - { - 'step_number': 3, - 'description': 'Identify the meter used to measure the voltage. By default this is the System Meter', - 'point_name': 'DHVT.EcpRef.AO22', - 'optional': 'I', - 'fcode': ['direct_operate'], - 'response': 'DHVT.EcpRef.AI71' - }, - { - 'step_number': 4, - 'description': 'Identify the index of the curve which specifies trip points when the voltage is high', - 'point_name': 'PTOV.BlkRef.AO23', - 'optional': 'M', - 'fcode': ['direct_operate'], - 'response': 'PTOV.BlkRef.AI73', - 'func_ref': 'curve' - }, - { - 'step_number': 5, - 'description': 'Enable the Low/High Voltage Ride-Through Mode', - 'point_name': 'DHVT.ModEna.BO12', - 'optional': 'M', - 'fcode': ['select', 'operate'], - 'response': 'DHVT.ModEna.BI64' - } - ] -} - -curve_selector_block = { - 'id': 'curve', - 'name': 'Curve', - 'ref': 'AN2018 Spec Curve Definition', - 'steps': [ - { - 'step_number': 1, - 'description': 'Select which curve to edit', - 'point_name': 'DGSMn.InCrv.AO244', - 'optional': 'M', - 'fcode': ['direct_operate'], - 'response': 'DGSMn.InCrv.AI328' - }, - { - 'step_number': 2, - 'description': 'Specify the Curve Mode Type', - 'point_name': 'DGSMn.ModTyp.AO245', - 'optional': 'M', - 'fcode': ['direct_operate'], - 'response': 'DGSMn.ModTyp.AI329' - }, - { - 'step_number': 3, - 'description': 'Specify that the Independent (X-Value) units for the curve', - 'point_name': 'FMARn.IndpUnits.AO247', - 'optional': 'M', - 'fcode': ['direct_operate'], - 'response': 'FMARn.IndpUnits.AI331' - }, - { - 'step_number': 4, - 'description': 'Specify the Dependent (Y-Value) units for the curve', - 'point_name': 'FMARn.DepRef.AO248', - 'optional': 'M', - 'fcode': ['direct_operate'], - 'response': 'FMARn.DepRef.AI332', - 'action': 'publish' - }, - { - 'step_number': 5, - 'description': 'Set X-Value and Y-Values pairs for the curve', - 'point_name': 'FMARn.PairArr.CrvPts.AO249', - 'optional': 'M', - 'fcode': ['direct_operate'], - 'response': 'FMARn.PairArr.CrvPts.AI333' - }, - { - 'step_number': 6, - 'description': 'Set number of points used for the curve', - 'point_name': 'FMARn.PairArr.NumPts.AO246', - 'optional': 'M', - 'fcode': ['direct_operate'], - 'response': 'FMARn.PairArr.NumPts.AI330' - } - ] -} - - -class TestStepDefinition: - """Regression tests for Step Definition.""" - - @property - def function_id(self): - return 'enable_high_voltage_ride_through_mode' - - @property - def step_number(self): - return 1 - - @property - def step_json(self): - """Return function enable_high_voltage_ride_through_mode step 1""" - return copy.deepcopy(enable_high_voltage_ride_through_mode)['steps'][self.step_number-1] - - def validate_step_definition(self, step_json): - exception = {} - try: - step_def = StepDefinition(POINT_DEFINITIONS, self.function_id, step_json) - step_def.validate() - except Exception as err: - exception['key'] = type(err).__name__ - exception['error'] = str(err) - return exception - - def test_valid_step_definition(self): - exception = self.validate_step_definition(self.step_json) - assert exception == {} - - def test_missing_step_number(self): - """Test raising exception if step missing step_number""" - step_json = self.step_json - step_json.pop('step_number') - exception = self.validate_step_definition(step_json) - assert exception == { - 'key': 'AttributeError', - 'error': 'Missing step number in function {}'.format(self.function_id) - } - - def test_missing_point_name(self): - """Test raising exception if step missing point_name""" - step_json = self.step_json - step_json.pop('point_name') - exception = self.validate_step_definition(step_json) - assert exception == { - 'key': 'AttributeError', - 'error': 'Missing name in function {} step {}'.format(self.function_id, self.step_number) - } - - def test_invalid_optionality(self): - """Test raising exception if optional not O, M, or I""" - step_json = self.step_json - step_json.update({ - 'optional': 'C' - }) - exception = self.validate_step_definition(step_json) - assert exception == { - 'key': 'AttributeError', - 'error': 'Invalid optional value in function {} step {}: C'.format(self.function_id, self.step_number) - } - - def test_invalid_fcodes_type(self): - """Test raising exception if fcodes is not a list""" - step_json = self.step_json - step_json.update({ - 'fcodes': 'direct_operate' - }) - exception = self.validate_step_definition(step_json) - assert exception == { - 'key': 'AttributeError', - 'error': "Invalid fcodes in function {} step {}, type=".format(self.function_id, - self.step_number) - } - - def test_invalid_fcode_value(self): - """Test raising exception if a str value in fcodes list is invalid""" - step_json = self.step_json - step_json.update({ - 'fcodes': ['select_operate'] - }) - exception = self.validate_step_definition(step_json) - assert exception == { - 'key': 'AttributeError', - 'error': 'Invalid fcode in function {} step {}, fcode=select_operate'.format(self.function_id, - self.step_number) - } - - def test_invalid_optionality_for_read_fcode(self): - """Test raising exception if optionality is not OPTIONAL when fcode is read""" - step_json = self.step_json - step_json.update({ - 'fcodes': ['read', 'response'] - }) - exception = self.validate_step_definition(step_json) - assert exception == { - 'key': 'AttributeError', - 'error': 'Invalid optionality in function {} step {}: must be OPTIONAL'.format(self.function_id, - self.step_number) - } - - def test_invalid_response_point(self): - step_json = self.step_json - step_json.update({ - 'response': 'invalid_point' - }) - exception = self.validate_step_definition(step_json) - assert exception == { - 'key': 'AttributeError', - 'error': 'Response point in function {} step {} does not match point definition. ' - 'Error=No point named invalid_point'.format(self.function_id, self.step_number) - } - - -class TestFunctionDefinition: - """Regression tests for Function Definition.""" - - @property - def function_json(self): - """Return function enable_high_voltage_ride_through_mode""" - return copy.deepcopy(enable_high_voltage_ride_through_mode) - - @staticmethod - def validate_function_definition(function_json): - exception = {} - try: - FunctionDefinition(POINT_DEFINITIONS, function_json) - except Exception as err: - exception['key'] = type(err).__name__ - exception['error'] = str(err) - return exception - - def test_valid_function_definition(self): - exception = self.validate_function_definition(self.function_json) - assert exception == {} - - def test_missing_function_id(self): - """Test raising exception if function missing id""" - function_json = self.function_json - function_json.pop('id') - exception = self.validate_function_definition(function_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Missing function ID' - } - - def test_missing_function_steps(self): - """Test raising exception if function missing steps""" - function_json = self.function_json - function_json.pop('steps') - exception = self.validate_function_definition(function_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Missing steps for function {}'.format(self.function_json['id']) - } - - def test_duplicated_step_number(self): - """Test raising exception if there is duplicated step_number in function""" - function_json = self.function_json - function_json['steps'][2].update({ - 'step_number': 1 - }) - exception = self.validate_function_definition(function_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Duplicated step number 1 for function {}'.format(self.function_json['id']) - } - - def test_missing_a_step(self): - """Test raising exception if function missing a step""" - function_json = self.function_json - del function_json['steps'][1] - exception = self.validate_function_definition(function_json) - assert exception == { - 'key': 'ValueError', - 'error': 'There are missing steps for function {}'.format(self.function_json['id']) - } - - def test_selector_block_function(self): - """Test raising exception if one step in selector block function is optional""" - function_json = copy.deepcopy(curve_selector_block) - exception = self.validate_function_definition(function_json) - assert exception == {} - - # Change step 2 to optional - function_json['steps'][1]['optional'] = 'O' - exception = self.validate_function_definition(function_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Function curve - Step 2: optionality must be either INITIALIZE or MANDATORY' - } - - -class TestFunctionDefinitions: - """Regression tests for Function Definitions.""" - - @property - def functions_json(self): - return [ - copy.deepcopy(enable_high_voltage_ride_through_mode), - copy.deepcopy(curve_selector_block) - ] - - @staticmethod - def validate_functions_definition(functions_json): - exception = {} - try: - function_definitions = FunctionDefinitions(POINT_DEFINITIONS) - function_definitions.load_functions(functions_json) - except Exception as err: - exception['key'] = type(err).__name__ - exception['error'] = str(err) - return exception - - def test_load_functions_yaml(self): - try: - FunctionDefinitions(POINT_DEFINITIONS, FUNCTION_DEFINITIONS_PATH) - assert True - except ValueError: - assert False - - def test_valid_functions_definitions(self): - exception = self.validate_functions_definition(self.functions_json) - assert exception == {} - - def test_duplicated_function_id(self): - """Test raising exception if there are multiple function with same id""" - functions_json = self.functions_json - functions_json[1]['id'] = self.functions_json[0]['id'] - exception = self.validate_functions_definition(functions_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Problem parsing FunctionDefinitions. ' - 'Error=There are multiple functions for function id {}'.format(functions_json[1]['id']) - } - - def test_invalid_func_ref(self): - """Test raising exception if a step has an invalid func_ref""" - functions_json = self.functions_json - functions_json[0]['steps'][3]['func_ref'] = 'invalid_curve' - exception = self.validate_functions_definition(functions_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Invalid Function Reference invalid_curve for Step 4 ' - 'in Function enable_high_voltage_ride_through_mode' - } diff --git a/services/core/DNP3Agent/tests/test_mesa_agent.py b/services/core/DNP3Agent/tests/test_mesa_agent.py deleted file mode 100644 index c92604b3c2..0000000000 --- a/services/core/DNP3Agent/tests/test_mesa_agent.py +++ /dev/null @@ -1,546 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - -import pytest -try: - import dnp3 -except ImportError: - pytest.skip("pydnp3 not found!", allow_module_level=True) - -import gevent -import os -import pytest -import yaml - -from dnp3.points import PointDefinitions -from mesa_master_test import MesaMasterTest -from volttron.platform import get_services_core, jsonapi -from volttron.platform.agent.utils import strip_comments - -MESA_AGENT_ID = 'mesaagent' - -# Get point and function definitions from the files in the test directory. -POINT_DEFINITIONS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data', 'mesa_points.config')) -FUNCTION_DEFINITIONS_PATH = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data', 'mesa_functions.yaml')) - -pdefs = PointDefinitions(point_definitions_path=POINT_DEFINITIONS_PATH) - -input_group_map = { - 1: 'Binary', - 2: 'Binary', - 30: 'Analog', - 31: 'Analog', - 32: 'Analog', - 33: 'Analog', - 34: 'Analog' -} - -MESA_AGENT_CONFIG = { - 'points': 'config://mesa_points.config', - 'functions': 'config://mesa_functions.config', - 'point_topic': 'mesa/point', - 'function_topic': 'mesa/function', - 'outstation_status_topic': 'mesa/outstation_status', - 'outstation_config': { - 'database_sizes': 800, - 'log_levels': ['NORMAL'] - }, - 'local_ip': '0.0.0.0', - 'port': 20000, - 'all_functions_supported_by_default': True, - 'function_validation': False -} - -messages = {} - - -def onmessage(peer, sender, bus, topic, headers, message): - """Callback: As mesaagent publishes mesa/function messages, store them in a multi-level global dictionary.""" - global messages - messages[topic] = {'headers': headers, 'message': message} - - -def dict_compare(source_dict, target_dict): - """Assert that the value for each key in source_dict matches the corresponding value in target_dict. - - Ignores keys in target_dict that are not in source_dict. - """ - for name, source_val in source_dict.items(): - target_val = target_dict.get(name, None) - assert source_val == target_val, 'Source value of {}={}, target value={}'.format(name, source_val, target_val) - - -def add_definitions_to_config_store(test_agent): - """Add PointDefinitions and FunctionDefinitions to the mesaagent's config store.""" - with open(POINT_DEFINITIONS_PATH, 'r') as f: - points_json = jsonapi.loads(strip_comments(f.read())) - test_agent.vip.rpc.call('config.store', 'set_config', MESA_AGENT_ID, - 'mesa_points.config', points_json, config_type='raw') - with open(FUNCTION_DEFINITIONS_PATH, 'r') as f: - functions_json = yaml.safe_load(f.read()) - test_agent.vip.rpc.call('config.store', 'set_config', MESA_AGENT_ID, - 'mesa_functions.config', functions_json, config_type='raw') - - -@pytest.fixture(scope="module") -def agent(request, volttron_instance): - """Build the test agent for rpc call.""" - - test_agent = volttron_instance.build_agent(identity="test_agent") - capabilities = {'edit_config_store': {'identity': 'mesaagent'}} - volttron_instance.add_capabilities(test_agent.core.publickey, capabilities) - - add_definitions_to_config_store(test_agent) - - print('Installing Mesa Agent') - os.environ['AGENT_MODULE'] = 'dnp3.mesa.agent' - agent_id = volttron_instance.install_agent(agent_dir=get_services_core('DNP3Agent'), - config_file=MESA_AGENT_CONFIG, - vip_identity=MESA_AGENT_ID, - start=True) - - # Subscribe to MESA functions - test_agent.vip.pubsub.subscribe(peer='pubsub', - prefix='mesa/function', - callback=onmessage) - - test_agent.vip.pubsub.subscribe(peer='pubsub', - prefix='mesa/point', - callback=onmessage) - - def stop(): - """Stop test agent.""" - if volttron_instance.is_running(): - volttron_instance.stop_agent(agent_id) - volttron_instance.remove_agent(agent_id) - test_agent.core.stop() - - gevent.sleep(3) # wait for agents and devices to start - - request.addfinalizer(stop) - - return test_agent - - -@pytest.fixture(scope="module") -def run_master(request): - """Run Mesa master application.""" - master = MesaMasterTest(local_ip=MESA_AGENT_CONFIG['local_ip'], - port=MESA_AGENT_CONFIG['port']) - master.connect() - - def stop(): - master.shutdown() - - request.addfinalizer(stop) - - return master - - -@pytest.fixture(scope="function") -def reset(agent): - """Reset agent and global variable messages before running every test.""" - global messages - messages = {} - agent.vip.rpc.call(MESA_AGENT_ID, 'reset') - - -class TestMesaAgent: - """Regression tests for the Mesa Agent.""" - - @staticmethod - def get_point(agent, point_name): - """Ask DNP3Agent for a point value for a DNP3 resource.""" - return agent.vip.rpc.call(MESA_AGENT_ID, 'get_point', point_name).get(timeout=10) - - @staticmethod - def get_point_definitions(agent, point_names): - """Ask DNP3Agent for a list of point definitions.""" - return agent.vip.rpc.call(MESA_AGENT_ID, 'get_point_definitions', point_names).get(timeout=10) - - @staticmethod - def get_point_by_index(agent, data_type, index): - """Ask DNP3Agent for a point value for a DNP3 resource.""" - return agent.vip.rpc.call(MESA_AGENT_ID, 'get_point_by_index', data_type, index).get(timeout=10) - - @staticmethod - def set_point(agent, point_name, value): - """Use DNP3Agent to set a point value for a DNP3 resource.""" - response = agent.vip.rpc.call(MESA_AGENT_ID, 'set_point', point_name, value).get(timeout=10) - gevent.sleep(1) # Give the Master time to receive an echoed point value back from the Outstation. - return response - - @staticmethod - def set_points(agent, point_dict): - """Use DNP3Agent to set point values for a DNP3 resource.""" - return agent.vip.rpc.call(MESA_AGENT_ID, 'set_points', point_dict).get(timeout=10) - - @staticmethod - def get_selector_block(agent, point_name, edit_selector): - """Get a selector block from the MesaAgent via an RPC call.""" - return agent.vip.rpc.call(MESA_AGENT_ID, 'get_selector_block', point_name, edit_selector).get(timeout=10) - - @staticmethod - def convert_json_file_to_dict(json_file): - """Convert a json file to a dictionary.""" - send_json = os.path.abspath(os.path.join(os.path.dirname(__file__), 'data', json_file)) - return jsonapi.load(open(send_json)) - - @staticmethod - def send_points(master, send_json, send_in_step_order=True): - """Master loads points from json and send them to mesa agent. - Return empty dictionary if function sent successfully, the dictionary with key and error otherwise.""" - exceptions = {} - try: - if send_in_step_order: - master.send_function_test(func_test_json=send_json) - else: - master.send_json(pdefs, FUNCTION_DEFINITIONS_PATH, send_json=send_json) - except Exception as err: - print('{}: {}'.format(type(err).__name__, str(err))) - exceptions['key'] = type(err).__name__ - exceptions['error'] = str(err) - - return exceptions - - @staticmethod - def get_value_from_master(master, point_name): - """Get value of the point from master after being set by test agent.""" - try: - pdef = pdefs.point_named(point_name) - group = input_group_map[pdef.group] - index = pdef.index - return master.soe_handler.result[group][index] - except KeyError: - return None - - def send_function_and_confirm(self, master, agent, json_file, func_ref=None): - """Test get points to confirm if points is set correctly by master.""" - send_function = self.convert_json_file_to_dict(json_file) - exceptions = self.send_points(master, send_function) - - for point_name in send_function.keys(): - if point_name not in ['name', 'function_id', 'function_name']: - - pdef = pdefs.point_named(point_name) - - if pdef.is_array_head_point: - for offset, value in enumerate( - record[field['name']] - for record in send_function[point_name] for field in pdef.array_points - ): - get_point = self.get_point_by_index(agent, pdef.data_type, pdef.index+offset) - assert get_point == value, 'Expected {} = {}, got {}'.format(point_name, value, get_point) - else: - get_point = self.get_point(agent, point_name) - # Ask the agent whether it has a point definition for that point name. - point_defs = self.get_point_definitions(agent, [point_name]) - point_def = point_defs.get(point_name, None) - assert point_def is not None, 'Agent has no point definition for {}'.format(point_name) - # Confirm that the agent's point value matches the value in the json. - json_val = send_function[point_name] - assert get_point == json_val, 'Expected {} = {}, got {}'.format(point_name, - json_val, - get_point) - if func_ref: - send_function.update({ - func_ref['name']: { - str(func_ref['index']): self.get_selector_block(agent, func_ref['name'], func_ref['index']) - } - }) - dict_compare(messages['mesa/function']['message']['points'], send_function) - assert exceptions == {} - - # ********** - # ********** OUTPUT TESTS (send data from Master to Agent to ControlAgent) ************ - # ********** - - def test_send_single_point_publish(self, run_master, agent, reset): - """Test send a single point with publish action.""" - test_point_name = 'DTCD.ModEna.BO19' - run_master.send_single_point(pdefs, test_point_name, True) - assert self.get_point(agent, test_point_name) == True - assert messages['mesa/point']['message'] == {test_point_name: True} - - def test_send_single_point_publish_and_respond(self, run_master, agent, reset): - """Test send a single point with publish_and_respond action.""" - test_point_name = 'DHVT.ModEna.BO12' - run_master.send_single_point(pdefs, test_point_name, True) - assert self.get_point(agent, test_point_name) == True - assert messages['mesa/point']['message'] == {test_point_name: True, - 'response': 'DHVT.ModEna.BI64'} - - def test_point_definition(self, agent, reset): - """Confirm whether the agent has a point def for a given name.""" - point_name = 'DCTE.VHiLim.AO6' - point_def = self.get_point_definitions(agent, [point_name]).get(point_name, None) - assert point_def is not None, 'Agent has no point definition for {}'.format(point_name) - - def test_simple_function(self, run_master, agent, reset): - """Test a simple function (not array or selector block).""" - self.send_function_and_confirm(run_master, agent, 'connect_and_disconnect.json') - - def test_curve(self, run_master, agent, reset): - """Test curve function.""" - assert self.get_selector_block(agent, 'DGSMn.InCrv.AO244', 2) is None - self.send_function_and_confirm(run_master, agent, 'watt_var_curve.json') - dict_compare(self.get_selector_block(agent, 'DGSMn.InCrv.AO244', 2), - self.convert_json_file_to_dict('watt_var_curve.json')) - - def test_enable_curve(self, run_master, agent, reset): - """Test curve function reference.""" - self.send_function_and_confirm(run_master, agent, 'watt_var_curve.json') - func_ref = { - 'name': 'DGSMn.InCrv.AO244', - 'index': 2.0 - } - self.send_function_and_confirm(run_master, agent, 'enable_watt_var_power_mode.json', func_ref) - assert messages['mesa/point']['message'] == {'DWVR.ModEna.BO30': True, - 'response': 'DWVR.BI49'} - - def test_schedule(self, run_master, agent, reset): - """Test schedule function.""" - assert self.get_selector_block(agent, 'FSCC.Schd.AO461', 2) is None - self.send_function_and_confirm(run_master, agent, 'watt_var_schedule.json') - dict_compare(self.get_selector_block(agent, 'FSCC.Schd.AO461', 2), - self.convert_json_file_to_dict('watt_var_schedule.json')) - - def test_enable_schedule(self, run_master, agent, reset): - """Test schedule function reference""" - self.send_function_and_confirm(run_master, agent, 'watt_var_schedule.json') - func_ref = { - 'name': 'FSCC.Schd.AO461', - 'index': 2.0 - } - self.send_function_and_confirm(run_master, agent, 'enable_watt_var_schedule.json', func_ref) - - def test_function_reference_fail(self, run_master, agent, reset): - """Test edit selector with Selector Block value have not set""" - send_function = self.convert_json_file_to_dict('enable_watt_var_schedule.json') - self.send_points(run_master, send_function) - assert messages == {} - - def test_invalid_function(self, run_master, agent, reset): - """Test send an invalid function, confirm getting exception error.""" - send_function = { - 'function_id': 'Invalid Function', - 'function_name': 'Testing Invalid Function', - 'point_1': 1, - 'point_2': 2 - } - exceptions = self.send_points(run_master, send_function) - assert exceptions == { - 'key': 'FunctionTestException', - 'error': 'Validation Error: Function definition not found: Invalid Function' - } - assert messages == {} - - def test_invalid_point_value(self, run_master, agent, reset): - """Test send a function with an invalid data type for a point, confirm getting exception error.""" - # Set the function support point to True - send_function = self.convert_json_file_to_dict('connect_and_disconnect.json') - - # Change the analog value to binary - send_function['DCTE.WinTms.AO16'] = True - - exceptions = self.send_points(run_master, send_function) - assert exceptions == { - 'key': 'FunctionTestException', - 'error': 'Validation Error: Invalid point value: DCTE.WinTms.AO16' - } - assert messages == {} - - # Change back to the valid point value - send_function['DCTE.WinTms.AO16'] = 10 - - # Change the binary value to analog - send_function['CSWI.Pos.BO5'] = 1 - - exceptions = self.send_points(run_master, send_function) - assert exceptions == { - 'key': 'FunctionTestException', - 'error': 'Validation Error: Invalid point value: CSWI.Pos.BO5' - } - assert messages == {} - - def test_invalid_array_value(self, run_master, agent, reset): - """Test send a function with an invalid data type for a point, confirm getting exception error.""" - send_function = self.convert_json_file_to_dict('watt_var_curve.json') - - # Change the analog array value to binary - send_function['FMARn.PairArr.CrvPts.AO249'] = [ - {'FMARn.PairArr.CrvPts.AO249.xVal': 1, - 'FMARn.PairArr.CrvPts.AO249.yVal': 2}, - {'FMARn.PairArr.CrvPts.AO249.xVal': 3, - 'FMARn.PairArr.CrvPts.AO249.yVal': 4}, - {'FMARn.PairArr.CrvPts.AO249.xVal': 5, - 'FMARn.PairArr.CrvPts.AO249.yVal': 6}, - {'FMARn.PairArr.CrvPts.AO249.xVal': 7, - 'FMARn.PairArr.CrvPts.AO249.yVal': 8}, - {'FMARn.PairArr.CrvPts.AO249.xVal': 9, - 'FMARn.PairArr.CrvPts.AO249.yVal': True} - ] - exceptions = self.send_points(run_master, send_function) - assert exceptions == { - 'key': 'FunctionTestException', - 'error': 'Validation Error: Invalid point value: FMARn.PairArr.CrvPts.AO249' - } - assert messages == {} - - def test_missing_mandatory_step(self, run_master, agent, reset): - """Test send a function missing its mandatory step, confirm getting exception error.""" - send_function = self.convert_json_file_to_dict('connect_and_disconnect.json') - - # Remove mandatory step - del send_function['DCTE.RvrtTms.AO17'] - - exceptions = self.send_points(run_master, send_function) - assert exceptions == { - 'key': 'FunctionTestException', - 'error': "Validation Error: Function Test missing mandatory steps: ['DCTE.RvrtTms.AO17']" - } - assert messages == {} - - def test_missing_point_definition(self, run_master, agent, reset): - """Test send a function with a point not defined in point definitions, confirm getting exception error.""" - send_function = self.convert_json_file_to_dict('connect_and_disconnect.json') - - # Add a point for testing - send_function['test point'] = 5 - - exceptions = self.send_points(run_master, send_function) - assert exceptions == { - 'key': 'FunctionTestException', - 'error': 'Validation Error: Not all points resolve' - } - assert messages == {} - - def test_wrong_step_order(self, run_master, agent, reset): - """Test send a function in wrong step order, confirm getting exception error.""" - connect_and_disconnect_dict = { - 'function_id': 'connect_and_disconnect', - 'name': 'Connect and Disconnect', - 'DCTE.RvrtTms.AO17': 12, # In wrong order: suppose to be step 2 instead of step 1 - 'DCTE.WinTms.AO16': 10, # In wrong order: suppose to be step 1 instead of step 2 - 'CSWI.Pos.BO5': True - } - - exceptions = self.send_points(run_master, connect_and_disconnect_dict, send_in_step_order=False) - assert exceptions == { - 'key': 'MesaMasterTestException', - 'error': 'Step not in order: 1' - } - assert messages == {} - - # ********** - # ********** INPUT TESTS (send data from ControlAgent to Agent to Master) ************ - # ********** - - def test_set_point(self, run_master, agent, reset): - """Test set an input point and confirm getting the same value for that point.""" - point_name = 'DCTE.WinTms.AI55' - self.set_point(agent, point_name, 45) - received_val = self.get_value_from_master(run_master, point_name) - assert received_val == 45, 'Expected {} = {}, got {}'.format(point_name, 45, received_val) - - def test_set_invalid_point(self, agent, reset): - """Test set an invalid input point and confirm getting exception error.""" - point_name = 'Invalid Point' - try: - self.set_point(agent, point_name, 45) - assert False, 'Input point with invalid name failed to cause an exception' - except Exception as err: - assert str(err) == "dnp3.points.DNP3Exception('No point named {}')".format(point_name) - - def test_set_invalid_point_value(self, agent, reset): - """Test set an invalid input point and confirm getting exception error.""" - point_name = 'DCTE.WinTms.AI55' - try: - self.set_point(agent, point_name, True) - assert False, 'Input point with invalid value failed to cause an exception' - except Exception as err: - assert str(err) == "dnp3.points.DNP3Exception(\"Received value for PointDefinition " \ - "{} (event_class=2, index=55, type=AI).\")".format(point_name) - - def test_set_points(self, run_master, agent, reset): - """Test set a set of points and confirm getting the correct values for all point that are set.""" - - set_points_dict = { - 'AI0': 0, - 'AI1': 1, - 'DGEN.VMinRtg.AI2': 2, - 'DGEN.VMaxRtg.AI3': 3, - 'DGEN.WMaxRtg.AI4': 4, - 'DSTO.ChaWMaxRtg.AI5': 5, - 'DGEN.WOvPFRtg.AI6': 6, - 'DSTO.ChaWOvPFRtg.AI7': 7, - 'DGEN.OvPFRtg.AI8': 8, - 'DGEN.WUnPFRtg.AI9': 9, - 'DHVT.ModEna.BI64': True - } - - self.set_points(agent, set_points_dict) - - for point_name in set_points_dict.keys(): - assert self.get_value_from_master(run_master, point_name) == set_points_dict[point_name] - - def test_set_points_array(self, run_master, agent, reset): - """Test set a set of points of an array and confirm getting the correct values for all point that are set.""" - - self.set_points(agent, { - 'FMARn.PairArr.CrvPts.AI333': [ - {'FMARn.PairArr.CrvPts.AI333.xVal': 1, - 'FMARn.PairArr.CrvPts.AI333.yVal': 2}, - {'FMARn.PairArr.CrvPts.AI333.xVal': 3, - 'FMARn.PairArr.CrvPts.AI333.yVal': 4}, - {'FMARn.PairArr.CrvPts.AI333.xVal': 5, - 'FMARn.PairArr.CrvPts.AI333.yVal': 6} - ] - }) - - pdef = pdefs.point_named('FMARn.PairArr.CrvPts.AI333') - group = input_group_map[pdef.group] - - assert run_master.soe_handler.result[group][333] == 1.0 - assert run_master.soe_handler.result[group][334] == 2.0 - assert run_master.soe_handler.result[group][335] == 3.0 - assert run_master.soe_handler.result[group][336] == 4.0 - assert run_master.soe_handler.result[group][337] == 5.0 - assert run_master.soe_handler.result[group][338] == 6.0 - - def test_wrong_database_size(self, run_master, agent, reset): - """Test set point for an index out of database size range, confirm receiving None for that point.""" - - try: - # This Input Test Point index is 800, but database size is only 700 - self.set_point(agent, 'TestPoint.BI900', True) - assert False, 'Wrong database size failed to cause an exception' - except Exception as err: - assert str(err) == "dnp3.points.DNP3Exception('Attempt to set a value for index 900 " \ - "which exceeds database size 800')" diff --git a/services/core/DNP3Agent/tests/test_points.py b/services/core/DNP3Agent/tests/test_points.py deleted file mode 100644 index 0f9e5126e4..0000000000 --- a/services/core/DNP3Agent/tests/test_points.py +++ /dev/null @@ -1,177 +0,0 @@ -import pytest -try: - import dnp3 -except ImportError: - pytest.skip("pydnp3 not found!", allow_module_level=True) - -import copy - -from dnp3.points import PointDefinition, ArrayHeadPointDefinition, PointDefinitions, PointValue - -from test_mesa_agent import POINT_DEFINITIONS_PATH - - -AO_4 = { - 'index': 4, - 'description': 'Power Factor Sign convention', - 'data_type': 'AO', - 'common_data_class': 'ENG', - 'maximum': 2, - 'ln_class': 'MMXU', - 'units': 'None', - 'minimum': 1, - 'data_object': 'PFSign', - 'allowed_values': { - '1': 'IEC active power', - '2': 'IEEE lead/lag' - }, - 'type': 'enumerated', - 'name': 'MMXU.PFSign.AO4' -} - -AO_244 = { - 'index': 244, - 'description': 'Curve Edit Selector. Writing to this point selects ' - 'which of the curves can currently be viewed and changed.', - 'data_type': 'AO', - 'common_data_class': 'ORG', - 'ln_class': 'DGSM', - 'minimum': 1, - 'data_object': 'InCrv', - 'name': 'DGSMn.InCrv.AO244', - 'type': 'selector_block', - 'selector_block_start': 244, - 'selector_block_end': 448 - } - - -class TestPointDefinition: - - @property - def point_json(self): - return copy.deepcopy(AO_4) - - @staticmethod - def validate_point_definition(point_json): - exception = {} - try: - PointDefinition(point_json) - except Exception as err: - exception['key'] = type(err).__name__ - exception['error'] = str(err) - return exception - - def test_valid_point_definition(self): - exception = self.validate_point_definition(self.point_json) - assert exception == {} - - def test_missing_point_name(self): - """Test raising exception if point definition missing point name""" - point_json = self.point_json - point_json.pop('name') - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Missing point name' - } - - def test_missing_index(self): - """Test raising exception if point definition missing point index""" - point_json = self.point_json - point_json.pop('index') - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Missing index for point {}'.format(self.point_json['name']) - } - - def test_missing_data_type(self): - """Test raising exception if point definition missing data_type""" - point_json = self.point_json - point_json.pop('data_type') - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Missing data type for point {}'.format(self.point_json['name']) - } - - def test_invalid_event_class(self): - """Test raising exception if event_class is not 0, 1, 2, or 3""" - point_json = self.point_json - point_json.update({ - 'event_class': 4 - }) - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Invalid event class 4 for point {}'.format(self.point_json['name']) - } - - def test_invalid_type(self): - """Test raising exception if type is not array, selector_block, or enumerated""" - point_json = self.point_json - point_json.update({ - 'type': 'regular' - }) - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Invalid type regular for point {}'.format(self.point_json['name']) - } - - def test_missing_response(self): - """Test raising exception if the point action is publish_and_respond but missing response field""" - point_json = self.point_json - point_json.update({ - 'action': 'publish_and_respond' - }) - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Missing response point name for point {}'.format(self.point_json['name']) - } - - def test_missing_allowed_values(self): - """Test raising exception if the enumerated type missing allowed_values map""" - point_json = self.point_json - point_json.pop('allowed_values') - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'Missing allowed values mapping for point {}'.format(self.point_json['name']) - } - - def test_invalid_defined_selector_block_start(self): - """Test raising exception if selector_block_start defined for non-selector-block point""" - point_json = self.point_json - point_json.update({ - 'selector_block_start': 244 - }) - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'selector_block_start defined for non-selector-block point {}'.format(self.point_json['name']) - } - - def test_invalid_defined_selector_block_end(self): - """Test raising exception if selector_block_end defined for non-selector-block point""" - point_json = self.point_json - point_json.update({ - 'selector_block_end': 448 - }) - exception = self.validate_point_definition(point_json) - assert exception == { - 'key': 'ValueError', - 'error': 'selector_block_end defined for non-selector-block point {}'.format(self.point_json['name']) - } - - -class TestPointDefinitions: - """Regression tests for the Mesa Agent.""" - - def test_load_points_from_json_file(self): - try: - PointDefinitions(point_definitions_path=POINT_DEFINITIONS_PATH) - assert True - except ValueError: - assert False \ No newline at end of file diff --git a/services/core/DNP3Agent/tests/unit_test_point_definitions.py b/services/core/DNP3Agent/tests/unit_test_point_definitions.py deleted file mode 100644 index 896dffe088..0000000000 --- a/services/core/DNP3Agent/tests/unit_test_point_definitions.py +++ /dev/null @@ -1,212 +0,0 @@ -# -*- coding: utf-8 -*- {{{ -# vim: set fenc=utf-8 ft=python sw=4 ts=4 sts=4 et: -# -# Copyright 2018, 8minutenergy / Kisensum. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. -# -# Neither 8minutenergy nor Kisensum, nor any of their -# employees, nor any jurisdiction or organization that has cooperated in the -# development of these materials, makes any warranty, express or -# implied, or assumes any legal liability or responsibility for the accuracy, -# completeness, or usefulness or any information, apparatus, product, -# software, or process disclosed, or represents that its use would not infringe -# privately owned rights. Reference herein to any specific commercial product, -# process, or service by trade name, trademark, manufacturer, or otherwise -# does not necessarily constitute or imply its endorsement, recommendation, or -# favoring by 8minutenergy or Kisensum. -# }}} - -import pytest -try: - import dnp3 -except ImportError: - pytest.skip("pydnp3 not found!", allow_module_level=True) - -from dnp3.points import ArrayHeadPointDefinition, PointDefinitions, PointValue -from dnp3.mesa.agent import MesaAgent -from dnp3.mesa.functions import FunctionDefinitions - -from test_mesa_agent import POINT_DEFINITIONS_PATH, FUNCTION_DEFINITIONS_PATH - - -def test_point_definition_load(): - point_defs = PointDefinitions(point_definitions_path=POINT_DEFINITIONS_PATH) - import pprint - pprint.pprint(point_defs._points) - pprint.pprint(point_defs._point_name_dict) - print("_point_variations_dict") - pprint.pprint(point_defs._point_variation_dict) - - -def test_point_definition(): - - test_dict = { - "name": "CurveStart-X", - "type": "array", # Start of the curve's X/Y array - "array_times_repeated": 100, - "group": 40, - "variation": 1, - "index": 207, - "description": "Starting index for a curve of up to 99 X/Y points", - "array_points": [ - { - "name": "Curve-X" - }, - { - "name": "Curve-Y" - } - ] - } - test_def = ArrayHeadPointDefinition(test_dict) - print(test_def) - - -def send_points(mesa_agent, some_points): - - for name, value, index in some_points: - pdef = mesa_agent.point_definitions.get_point_named(name,index) - point_value = PointValue('Operate', - None, - value, - pdef, - pdef.index, - None) # What is op_type used for? - - print(point_value) - mesa_agent._process_point_value(point_value) - - -def test_mesa_agent(): - mesa_agent = MesaAgent(point_topic='points_foobar', local_ip='127.0.0.1', port=8999, outstation_config={}, - function_topic='functions_foobar', outstation_status_topic='', - local_point_definitions_path=POINT_DEFINITIONS_PATH, - local_function_definitions_path=FUNCTION_DEFINITIONS_PATH) - - mesa_agent._configure('', '', {}) - point_definitions = mesa_agent.point_definitions - supported_pdef = point_definitions.get_point_named("Supports Charge/Discharge Mode") - mesa_agent.update_input_point(supported_pdef, True) - - test_points = ( - # ("DCHD.WinTms (out)", 1.0), - # ("DCHD.RmpTms (out)", 2.0), - # ("DCHD.RevtTms (out)", 3.0), - ("CurveStart-X", 1.0, None), - ("CurveStart-X", 2.0, 208), - - ) - send_points(mesa_agent, test_points) - - -def test_mesa_agent_2(): - mesa_agent = MesaAgent(point_topic='points_foobar', local_ip='127.0.0.1', port=8999, outstation_config={}, - function_topic='functions_foobar', outstation_status_topic='', - local_point_definitions_path=POINT_DEFINITIONS_PATH, - local_function_definitions_path=FUNCTION_DEFINITIONS_PATH) - - mesa_agent._configure('', '', {}) - point_definitions = mesa_agent.point_definitions - supported_pdef = point_definitions.get_point_named("Supports Charge/Discharge Mode") - mesa_agent.update_input_point(supported_pdef, True) - - test_points = ( - ("DCHD.WinTms (out)", 1.0, None), - #("DCHD.RmpTms (out)", 2.0, None), - ("DCHD.RevtTms (out)", 3.0, None), - - ) - send_points(mesa_agent, test_points) - - -def test_function_definitions(): - point_definitions = PointDefinitions(point_definitions_path=POINT_DEFINITIONS_PATH) - fdefs = FunctionDefinitions(point_definitions, function_definitions_path=FUNCTION_DEFINITIONS_PATH) - - fd = fdefs.function_for_id("curve") - print(fd) - - pdef = point_definitions.get_point_named("DCHD.WinTms (out)") - print(pdef) - print(fdefs.step_definition_for_point(pdef)) - - -def test_selector_block(): - """ - Test send a Curve function / selector block (including an array of points) to MesaAgent. - Get MesaAgent's selector block and confirm that it has the correct contents. - Do this for a variety of Edit Selectors and array contents. - """ - - def process_block_points(agt, block_points, edit_selector): - """Send each point value in block_points to the MesaAgent.""" - # print('Processing {}'.format(block_points)) - for name, value, index in block_points: - point_definitions = agt.point_definitions - pdef = point_definitions.get_point_named(name, index) - point_value = PointValue('Operate', None, value, pdef, pdef.index, None) - agt._process_point_value(point_value) - returned_block = mesa_agent.get_selector_block('Curve Edit Selector', edit_selector) - # print('get_selector_block returned {}'.format(returned_block)) - return returned_block - - mesa_agent = MesaAgent(point_topic='points_foobar', local_ip='127.0.0.1', port=8999, outstation_config={}, - function_topic='functions_foobar', outstation_status_topic='', - local_point_definitions_path=POINT_DEFINITIONS_PATH, - local_function_definitions_path=FUNCTION_DEFINITIONS_PATH) - mesa_agent._configure('', '', {}) - - block_1_points = [('Curve Edit Selector', 1, None), # index 191 - Function and SelectorBlock start - ('CurveStart-X', 1.0, None), # Point #1-X: index 207 - Array start - ('CurveStart-X', 2.0, 208), # Point #1-Y - ('Curve Number of Points', 1, None)] # index 196 - Curve function end - block_2_points = [('Curve Edit Selector', 2, None), # index 191 - Function and SelectorBlock start - ('CurveStart-X', 1.0, None), # Point #1-X: index 207 - Array start - ('CurveStart-X', 2.0, 208), # Point #1-Y - ('CurveStart-X', 3.0, 209), # Point #2-X - ('CurveStart-X', 4.0, 210), # Point #2-Y - ('Curve Number of Points', 2, None)] # index 196 - Curve function end - block_2a_points = [('Curve Edit Selector', 2, None), # index 191 - Function and SelectorBlock start - ('CurveStart-X', 1.0, None), # Point #1-X: index 207 - Array start - ('CurveStart-X', 2.0, 208), # Point #1-Y - ('CurveStart-X', 5.0, 211), # Point #3-X - ('CurveStart-X', 6.0, 212), # Point #3-Y - ('Curve Number of Points', 3, None)] # index 196 - Curve function end - - # Send block #1. Confirm that its array has a point with Y=2.0. - block = process_block_points(mesa_agent, block_1_points, 1) - assert block['CurveStart-X'][0]['Curve-Y'] == 2.0 - - # Send block #2. Confirm that its array has a point #2 with Y=4.0. - block = process_block_points(mesa_agent, block_2_points, 2) - assert block['CurveStart-X'][1]['Curve-Y'] == 4.0 - - # Send an updated block #2 with no point #2 and a new point #3. - block = process_block_points(mesa_agent, block_2a_points, 2) - # Confirm that its array still has a point #2 with Y=4.0, even though it wasn't just sent. - assert block['CurveStart-X'][1]['Curve-Y'] == 4.0 - # Confirm that its array now has a point #3 with Y=6.0. - assert block['CurveStart-X'][2]['Curve-Y'] == 6.0 - - # Re-send block #1. Confirm that selector block initialization reset the point cache: the array has no second point. - block = process_block_points(mesa_agent, block_1_points, 1) - assert len(block['CurveStart-X']) == 1 - - -if __name__ == "__main__": - # test_mesa_agent() - # test_mesa_agent_2() - # test_function_definitions() - # test_point_definition() - test_point_definition_load() - # test_selector_block() From b0dd71d618021eca443c8593855052c5c836de95 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 14 Sep 2023 13:24:39 -0700 Subject: [PATCH 19/36] updated to latest mongo and pymongo version --- services/core/MongodbTaggingService/README.md | 13 +++-- .../mongotagging/tagging.py | 53 +++++++++---------- .../MongodbTaggingService/requirements.txt | 2 +- 3 files changed, 34 insertions(+), 34 deletions(-) diff --git a/services/core/MongodbTaggingService/README.md b/services/core/MongodbTaggingService/README.md index 449dbe7488..0136e3551c 100644 --- a/services/core/MongodbTaggingService/README.md +++ b/services/core/MongodbTaggingService/README.md @@ -21,11 +21,16 @@ keyword AND and OR, and use the keyword NOT to negate a conditions. ## Requirements -This historian requires a mongodb connector installed in your activated -volttron environment to talk to mongodb. Please execute the following -from an activated shell in order to install it. +This historian requires: - pip install pymongo +1. Mongodb server: Version tested - 7.0.1 + This agent requires mongodb server installed and running on the system. In addition create a database user and + database that can be used by this agent. +2. mongodb connector: Tested version - 4.5.0 + This agent requires a python mongo connected to be installed in your activated volttron environment to talk to + mongodb. Please execute the following from an activated shell in order to install it. + + pip install pymongo==4.5.0 ## Dependencies and Limitations diff --git a/services/core/MongodbTaggingService/mongotagging/tagging.py b/services/core/MongodbTaggingService/mongotagging/tagging.py index ed0c787098..34de203028 100644 --- a/services/core/MongodbTaggingService/mongotagging/tagging.py +++ b/services/core/MongodbTaggingService/mongotagging/tagging.py @@ -44,7 +44,7 @@ import pymongo import re -from pkg_resources import resource_string, resource_exists +from pymongo import InsertOne, UpdateOne from pymongo.errors import BulkWriteError from volttron.platform.agent import utils from volttron.platform.agent.base_tagging import BaseTaggingService @@ -133,9 +133,9 @@ def setup(self): collections = [] db = None try: - db = self._client.get_default_database() - collections = db.collection_names(include_system_collections=False) - _log.debug(collections) + db = self._client.get_database() + collections = db.list_collection_names() + _log.debug(f"GOT collections as {collections}") except Exception as e: err_message = "Unable to query list of existing tables from the " \ "database. Exception in init of tagging service: {}. " \ @@ -181,6 +181,8 @@ def setup(self): # _log.debug("status:{}".format(status)) self.vip.health.send_alert(TAGGING_SERVICE_SETUP_FAILED, status) self.core.stop() + else: + _log.info("Initialization complete") @doc_inherit def load_valid_tags(self): @@ -210,12 +212,11 @@ def _init_tags(self, db): # csv.DictReader uses first line in file for column headings # by default dr = csv.DictReader(csv_str.splitlines()) - bulk_tags = db[self.tags_collection].initialize_ordered_bulk_op() + inserts = [] for i in dr: - bulk_tags.insert({"_id":i['name'], - "kind":i['kind'], - "description":i['description']}) - bulk_tags.execute() + inserts.append(InsertOne( + {"_id": i['name'], "kind": i['kind'], "description": i['description']})) + db[self.tags_collection].bulk_write(inserts) else: raise ValueError( "Unable to load list of reference tags and its parent. No " @@ -231,18 +232,15 @@ def _init_tag_refs(self, db): # csv.DictReader uses first line in file for column headings # by default dr = csv.DictReader(csv_str.splitlines()) - bulk_tags = db[ - self.tag_refs_collection].initialize_ordered_bulk_op() + inserts = [] for i in dr: - bulk_tags.insert({"_id":i['tag'], - "parent":i['parent_tag']}) - bulk_tags.execute() + inserts.append(InsertOne({"_id": i['tag'], "parent": i['parent_tag']})) + db[self.tag_refs_collection].bulk_write(inserts) else: raise ValueError( "Unable to load list of reference tags and its parent. No " "such file: {}".format(file_path)) - def _init_categories(self, db): file_path = self.resource_sub_dir + '/categories.csv' _log.debug("Loading file :" + file_path) @@ -250,12 +248,10 @@ def _init_categories(self, db): csv_str = content_file.read() if csv_str: dr = csv.DictReader(csv_str.splitlines()) - bulk = db[ - self.categories_collection].initialize_ordered_bulk_op() + inserts = [] for i in dr: - bulk.insert({"_id": i['name'], - "description": i['description']}) - bulk.execute() + inserts.append(InsertOne({"_id": i['name'], "description": i['description']})) + db[self.categories_collection].bulk_write(inserts) else: _log.warning("No categories to initialize. No such file " + file_path) @@ -265,7 +261,7 @@ def _init_category_tags(self, db): with open(file_path, 'r') as content_file: txt_str = content_file.read() - bulk_tags = db[self.tags_collection].initialize_ordered_bulk_op() + updates = [] if txt_str: current_category = "" tags = set() @@ -283,15 +279,14 @@ def _init_category_tags(self, db): else: temp= line.split(":") # ignore description tags.update(re.split(" +", temp[0])) - if len(tags)>0: + if len(tags) > 0: for tag in tags: mapping[tag].add(current_category) for tag in mapping.keys(): - bulk_tags.find({"_id": tag}).update( - {'$set': {"categories": list(mapping[tag])}}) + updates.append(UpdateOne({"_id": tag}, {'$set': {"categories": list(mapping[tag])}})) - bulk_tags.execute() + db[self.tags_collection].bulk_write(updates) db[self.tags_collection].create_index( [('categories', pymongo.ASCENDING)], background=True) @@ -370,7 +365,7 @@ def query_tags_by_category(self, category, include_kind=False, @doc_inherit def insert_topic_tags(self, tags, update_version=False): db = self._client.get_default_database() - bulk = db[self.topic_tags_collection].initialize_unordered_bulk_op() + updates = [] result = dict() result['info'] = dict() result['error'] = dict() @@ -400,9 +395,9 @@ def insert_topic_tags(self, tags, update_version=False): temp['_id'] = prefix temp['id'] = prefix execute = True - bulk.find({'_id': prefix}).upsert().update_one( - {'$set': temp}) + updates.append(UpdateOne({'_id': prefix}, {'$set': temp}, upsert=True)) result['info'][topic_pattern].append(prefix) + if len(result['info'][topic_pattern]) == 1 and \ topic_pattern == result['info'][topic_pattern][0]: # means value sent was actually some pattern so add @@ -413,7 +408,7 @@ def insert_topic_tags(self, tags, update_version=False): result['info'].pop(topic_pattern) if execute: try: - bulk.execute() + db[self.topic_tags_collection].bulk_write(updates) except BulkWriteError as bwe: errors = bwe.details['writeErrors'] _log.error("bwe error count {}".format(len(errors))) diff --git a/services/core/MongodbTaggingService/requirements.txt b/services/core/MongodbTaggingService/requirements.txt index 891fc9d356..78cf745f08 100644 --- a/services/core/MongodbTaggingService/requirements.txt +++ b/services/core/MongodbTaggingService/requirements.txt @@ -1 +1 @@ -pymongo==3.7.2 +pymongo==4.5.0 From ecfcdb50288925d866a9b51434697e6daa81440a Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 14 Sep 2023 13:27:08 -0700 Subject: [PATCH 20/36] minor - py.test to pytest --- ci-integration/run-tests.sh | 6 +++--- .../developing-agents/agent-development.rst | 2 +- .../development-environment/pycharm/index.rst | 6 +++--- .../PlatformDriverAgent/tests/test_device_groups.py | 2 +- .../PlatformDriverAgent/tests/test_device_groups_p2.py | 2 +- .../PlatformDriverAgent/tests/test_global_override.py | 2 +- .../PlatformDriverAgent/tests/test_global_settings.py | 2 +- volttrontesting/README.md | 10 +++++----- 8 files changed, 16 insertions(+), 16 deletions(-) diff --git a/ci-integration/run-tests.sh b/ci-integration/run-tests.sh index 26b83297e9..e0ede38058 100755 --- a/ci-integration/run-tests.sh +++ b/ci-integration/run-tests.sh @@ -51,7 +51,7 @@ echo "rabbitmq status" echo "TestDirs" for dir in $testdirs; do echo "*********TESTDIR: $dir" - py.test -s -v "$dir" + pytest -s -v "$dir" tmp_code=$? exit_code=$tmp_code @@ -79,7 +79,7 @@ for dir in $splitdirs; do if [ -d "${D}" ]; then echo "*********SPLITDIR: $D" - py.test -s -v "${D}" + pytest -s -v "${D}" tmp_code=$? if [ $tmp_code -ne 0 ]; then if [ $tmp_code -ne 5 ]; then @@ -100,7 +100,7 @@ for dir in $filedirs; do for testfile in "$dir"/*.py; do echo "Using testfile: $testfile" if [ "$testfile" != "volttrontesting/platform/packaging-tests.py" ]; then - py.test -s -v "$testfile" + pytest -s -v "$testfile" tmp_code=$? exit_code=$tmp_code diff --git a/docs/source/developing-volttron/developing-agents/agent-development.rst b/docs/source/developing-volttron/developing-agents/agent-development.rst index 69b87b78ca..92cec9a8f7 100644 --- a/docs/source/developing-volttron/developing-agents/agent-development.rst +++ b/docs/source/developing-volttron/developing-agents/agent-development.rst @@ -918,7 +918,7 @@ VOLTTRON uses *pytest* as a framework for executing tests. All unit tests shoul For instructions on writing unit and integration tests with *pytest*, refer to the :ref:`Writing Agent Tests ` documentation. -*pytest* is not installed with the distribution by default. To install py.test and it's dependencies execute the +*pytest* is not installed with the distribution by default. To install pytest and it's dependencies execute the following: .. code-block:: bash diff --git a/docs/source/developing-volttron/development-environment/pycharm/index.rst b/docs/source/developing-volttron/development-environment/pycharm/index.rst index c2044d04d0..1001ff61eb 100644 --- a/docs/source/developing-volttron/development-environment/pycharm/index.rst +++ b/docs/source/developing-volttron/development-environment/pycharm/index.rst @@ -6,7 +6,7 @@ Pycharm Development Environment Pycharm is an IDE dedicated to developing python projects. It provides coding assistance and easy access to debugging tools as well as integration with -py.test. It is a popular tool for working with VOLTTRON. +pytest. It is a popular tool for working with VOLTTRON. Jetbrains provides a free community version that can be downloaded from https://www.jetbrains.com/pycharm/ @@ -98,8 +98,8 @@ top level source directory; git will ignore changes to these files. Testing an Agent ---------------- -Agent tests written in py.test can be run simply by right-clicking the tests -directory and selecting `Run 'py.test in tests`, so long as the root directory +Agent tests written in pytest can be run simply by right-clicking the tests +directory and selecting `Run 'pytest in tests`, so long as the root directory is set as the VOLTTRON source root. |Run Tests| diff --git a/services/core/PlatformDriverAgent/tests/test_device_groups.py b/services/core/PlatformDriverAgent/tests/test_device_groups.py index aa35fc055f..ec9d73ba7e 100644 --- a/services/core/PlatformDriverAgent/tests/test_device_groups.py +++ b/services/core/PlatformDriverAgent/tests/test_device_groups.py @@ -37,7 +37,7 @@ # }}} """ -py.test cases for global platform driver settings. +pytest cases for global platform driver settings. """ import pytest diff --git a/services/core/PlatformDriverAgent/tests/test_device_groups_p2.py b/services/core/PlatformDriverAgent/tests/test_device_groups_p2.py index 9a519b3604..51ee93dec4 100644 --- a/services/core/PlatformDriverAgent/tests/test_device_groups_p2.py +++ b/services/core/PlatformDriverAgent/tests/test_device_groups_p2.py @@ -37,7 +37,7 @@ # }}} """ -a single py.test case for global platform driver settings. +a single pytest case for global platform driver settings. """ import pytest diff --git a/services/core/PlatformDriverAgent/tests/test_global_override.py b/services/core/PlatformDriverAgent/tests/test_global_override.py index 0bcb5956f2..6f5db74948 100644 --- a/services/core/PlatformDriverAgent/tests/test_global_override.py +++ b/services/core/PlatformDriverAgent/tests/test_global_override.py @@ -37,7 +37,7 @@ # }}} """ -py.test cases for global override settings. +pytest cases for global override settings. """ import pytest diff --git a/services/core/PlatformDriverAgent/tests/test_global_settings.py b/services/core/PlatformDriverAgent/tests/test_global_settings.py index 780035e39c..f1b83b24e1 100644 --- a/services/core/PlatformDriverAgent/tests/test_global_settings.py +++ b/services/core/PlatformDriverAgent/tests/test_global_settings.py @@ -37,7 +37,7 @@ # }}} """ -py.test cases for global platform driver settings. +pytest cases for global platform driver settings. """ import pytest diff --git a/volttrontesting/README.md b/volttrontesting/README.md index 0659841aca..dcb5eaabea 100644 --- a/volttrontesting/README.md +++ b/volttrontesting/README.md @@ -13,20 +13,20 @@ the VOLTTRON repository. ``` # Execute all tests throughout the repository -py.test +pytest # Execute a specific directory of tests recursively from the # specified directory. -py.test examples/ListenerAgent +pytest examples/ListenerAgent # Execute only tests that are marked as slow -py.test -m slow +pytest -m slow # Execute tests that are not marked as slow -py.test -m "not slow" +pytest -m "not slow" # Execute only zmq tests -py.test -m zmq +pytest -m zmq ``` ## Notes From 69ae460f946158f0c37e96aa0da4f1bc584ecaf2 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 14 Sep 2023 13:30:58 -0700 Subject: [PATCH 21/36] updated to latest mongo and pymongo version --- requirements.py | 4 ++-- volttrontesting/services/tagging/test_tagging.py | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/requirements.py b/requirements.py index 77ad9b8efa..1aea9ee560 100644 --- a/requirements.py +++ b/requirements.py @@ -66,7 +66,7 @@ extras_require = {'crate': ['crate==0.27.1'], 'databases': ['mysql-connector-python==8.0.30', - 'pymongo==4.2.0', + 'pymongo==4.5.0', 'crate==0.27.1', 'influxdb==5.3.1', 'psycopg2-binary==2.9.7'], @@ -81,7 +81,7 @@ 'pyserial==3.5'], 'influxdb': ['influxdb==5.3.1'], 'market': ['numpy==1.23.1', 'transitions==0.8.11'], - 'mongo': ['pymongo==4.2.0'], + 'mongo': ['pymongo==4.5.0'], 'mysql': ['mysql-connector-python==8.0.30'], 'pandas': ['numpy==1.23.1', 'pandas==1.4.3'], 'postgres': ['psycopg2-binary==2.9.7'], diff --git a/volttrontesting/services/tagging/test_tagging.py b/volttrontesting/services/tagging/test_tagging.py index c038ad7c8b..d0524b4480 100644 --- a/volttrontesting/services/tagging/test_tagging.py +++ b/volttrontesting/services/tagging/test_tagging.py @@ -161,7 +161,7 @@ def cleanup_mysql(db_connection, truncate_tables): def cleanup_mongodb(db_connection, truncate_tables): for collection in truncate_tables: - db_connection[collection].remove() + db_connection[collection].drop() print("Finished removing {}".format(truncate_tables)) @@ -245,7 +245,7 @@ def test_init_failure(volttron_instance, tagging_service, query_agent): callback=query_agent.callback).get() new_config = copy.copy(tagging_service) new_config['connection'] = {"params": - {"host": "localhost", + {"host": "localhost2", "port": 27017, "database": "mongo_test", "user": "invalid_user", @@ -259,7 +259,7 @@ def test_init_failure(volttron_instance, tagging_service, query_agent): volttron_instance.start_agent(agent_id) except: pass - gevent.sleep(1) + gevent.sleep(3) print("Call back count {}".format(query_agent.callback.call_count)) assert query_agent.callback.call_count == 1 print("Call args {}".format(query_agent.callback.call_args)) From d746634a24cec7bb27962f8a7c69e23d6cc0d0d0 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Thu, 14 Sep 2023 13:31:48 -0700 Subject: [PATCH 22/36] minor updates based on testing --- .gitlab-ci.yml | 71 ++++++++----------- .../fixtures/volttron_platform_fixtures.py | 15 ++-- .../multiplatform/test_federation.py | 2 + .../services/weather/test_base_weather.py | 5 +- .../testutils/test_getinstance_1.py | 4 +- 5 files changed, 43 insertions(+), 54 deletions(-) diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index d0b7229eba..40ba57ee61 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -23,30 +23,37 @@ stages: - services/core/ActuatorAgent/tests - services/core/DataMover/tests/ - services/core/DNP3OutstationAgent/tests - - services/core/ForwardHistorian/tests - -# build 22.04: -# stage: build -# tags: -# - ubuntu2204 - -# before_script: -# #- killall -9 volttron beam.smp python -# - rm -rf dist ~/.volttron ~/.volttron_instances -# - rm -rf /tmp/tmp* -# - rm -rf ~/rabbitmq_server - -# script: -# - python3 bootstrap.py --all -# - source env/bin/activate -# - python3 bootstrap.py --rabbitmq -# - echo "BUILD_DIR_22_04=`pwd`" >> build.env -# - echo "$BUILD_DIR_22_04" -# - echo `pwd` - -# artifacts: -# reports: -# dotenv: build.env + - services/core/OpenADRVenAgent/tests + - services/core/PlatformDriverAgent/tests + - services/core/SQLHistorian/tests + - services/core/VolttronCentral/tests + - services/core/VolttronCentralPlatform/tests + - services/core/WeatherDotGov/tests + - services/ops + - volttrontesting/gevent/yield_test.py + - volttrontesting/platform/auth_tests + - volttrontesting/platform/control_tests + - volttrontesting/platform/dbutils + - volttrontesting/platform/web + - volttrontesting/platform/test_basehistorian.py + - volttrontesting/platform/test_connection.py + - volttrontesting/platform/test_core_agent.py + - volttrontesting/platform/test_instance_setup.py + - volttrontesting/platform/test_keystore.py + - volttrontesting/platform/test_packaging.py + - volttrontesting/platform/test_platform_init.py + - volttrontesting/platform/test_platform_rmq.py + - volttrontesting/platform/test_platform_web.py + - volttrontesting/platform/test_rmq_platform_shutdown.py + - volttrontesting/platform/test_sqlite3_fix.py + - volttrontesting/services/historian + - volttrontesting/services/aggregate_historian + - volttrontesting/services/tagging + - volttrontesting/services/weather + - volttrontesting/services/test_pubsub_service.py + - volttrontesting/subsystems + - volttrontesting/testutils + - volttrontesting/zmq build 20.04: stage: build @@ -71,22 +78,6 @@ build 20.04: reports: dotenv: build.env - -# test 22.04: -# stage: test -# needs: [build 22.04] -# variables: -# GIT_CHECKOUT: "false" -# tags: -# - ubuntu2204 -# extends: .parallel-tests -# script: -# - cd $BUILD_DIR_22_04 -# - echo `pwd` -# - source env/bin/activate -# - pytest $TEST - - test 20.04: stage: test needs: [build 20.04] diff --git a/volttrontesting/fixtures/volttron_platform_fixtures.py b/volttrontesting/fixtures/volttron_platform_fixtures.py index 3fc606e850..5264c4b4fd 100644 --- a/volttrontesting/fixtures/volttron_platform_fixtures.py +++ b/volttrontesting/fixtures/volttron_platform_fixtures.py @@ -62,6 +62,8 @@ def cleanup_wrapper(wrapper): # if wrapper.is_running(): # wrapper.remove_all_agents() # Shutdown handles case where the platform hasn't started. + if not wrapper.is_running(): + return wrapper_pid = wrapper.p_process.pid wrapper.shutdown_platform() if wrapper.p_process is not None: @@ -200,17 +202,10 @@ def get_n_volttron_instances(n, should_start=True, **kwargs): def cleanup(): nonlocal instances - print(f"My instances: {get_n_volttron_instances.count}") - if isinstance(get_n_volttron_instances.instances, PlatformWrapper): + for i in range(0, len(instances)): print('Shutting down instance: {}'.format( - get_n_volttron_instances.instances)) - cleanup_wrapper(get_n_volttron_instances.instances) - return - - for i in range(0, get_n_volttron_instances.count): - print('Shutting down instance: {}'.format( - get_n_volttron_instances.instances[i].volttron_home)) - cleanup_wrapper(get_n_volttron_instances.instances[i]) + instances[i].volttron_home)) + cleanup_wrapper(instances[i]) try: yield get_n_volttron_instances diff --git a/volttrontesting/multiplatform/test_federation.py b/volttrontesting/multiplatform/test_federation.py index 46243aa25f..838b4e2c2e 100644 --- a/volttrontesting/multiplatform/test_federation.py +++ b/volttrontesting/multiplatform/test_federation.py @@ -51,6 +51,8 @@ if not is_rabbitmq_available(): pytest.skip("Pika is not installed", allow_module_level=True) + +@pytest.mark.timeout(600) @pytest.mark.federation def test_federation_pubsub(federated_rmq_instances): upstream, downstream = federated_rmq_instances diff --git a/volttrontesting/services/weather/test_base_weather.py b/volttrontesting/services/weather/test_base_weather.py index d394d9576d..b52b05e3bc 100644 --- a/volttrontesting/services/weather/test_base_weather.py +++ b/volttrontesting/services/weather/test_base_weather.py @@ -40,7 +40,7 @@ import datetime import os import sqlite3 - +import logging import gevent import pytest from mock import MagicMock @@ -49,6 +49,8 @@ from volttron.platform.agent.base_weather import BaseWeatherAgent from volttron.platform.agent.utils import get_fq_identity from volttron.platform.messaging.health import STATUS_BAD, STATUS_GOOD +from volttron.platform import jsonapi +from volttron.platform.agent.utils import format_timestamp utils.setup_logging() _log = logging.getLogger(__name__) @@ -524,6 +526,7 @@ def test_manage_unit_conversion_fail(weather, from_units, start, to_units, [{"location": "fake_location1"}, {"location": "fake_location2"}] ]) def test_get_current_valid_locations(weather, fake_locations): + clear_api_calls(weather) conn = weather._cache._sqlite_conn cursor = conn.cursor() weather.set_update_interval("get_current_weather", diff --git a/volttrontesting/testutils/test_getinstance_1.py b/volttrontesting/testutils/test_getinstance_1.py index a445d0fc2a..eaaca45102 100644 --- a/volttrontesting/testutils/test_getinstance_1.py +++ b/volttrontesting/testutils/test_getinstance_1.py @@ -5,11 +5,9 @@ @pytest.mark.wrapper def test_fixture_returns_correct_number_of_instances(get_volttron_instances): - num_instances = 4 + num_instances = 2 wrappers = get_volttron_instances(num_instances, should_start=False) - assert num_instances == len(wrappers) for w in wrappers: assert isinstance(w, PlatformWrapper) - assert not w.is_running() From 42ea7c86137725861bf17717246f7d8a52f5adca Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 11:48:36 -0700 Subject: [PATCH 23/36] utility script to install mysql, postgres, mongodb and create test user and test database for volttron testing on Ubuntu 22.04 --- .../install-dbs-ubuntu-2204.sh | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100755 scripts/historian-scripts/install-dbs-ubuntu-2204.sh diff --git a/scripts/historian-scripts/install-dbs-ubuntu-2204.sh b/scripts/historian-scripts/install-dbs-ubuntu-2204.sh new file mode 100755 index 0000000000..694d5b7b6f --- /dev/null +++ b/scripts/historian-scripts/install-dbs-ubuntu-2204.sh @@ -0,0 +1,110 @@ +#! /bin/bash + + # Utility script for installing mysql, mongodb, and postgresql on Ubuntu 22.04 and creates test data base and test + # db user for testing volttron agents that use these databases. Installs databases on a /databases + # folder and assumes the unix user running VOLTTRON is "volttron" + # You can use this as a reference, update database versions and user name as needed to install database environment for + # testing volttron agents + # To run provide execute permissions and pass one or more database names as input + # For example + # ./install-dbs-ubuntu-2204.sh mongodb mysql postgresql + # ./install-dbs-ubuntu-2204.sh mongodb + # ./install-dbs-ubuntu-2204.sh mysql + +function install_mongodb(){ + mkdir -p /databases/mongodb + cd /databases/mongodb + sudo apt-get install -y libcurl4 libgssapi-krb5-2 libldap-2.5-0 libwrap0 libsasl2-2 libsasl2-modules libsasl2-modules-gssapi-mit openssl liblzma5 + wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-7.0.1.tgz + tar -xvzf mongodb-linux-x86_64-ubuntu2204-7.0.1.tgz + ln -s mongodb-linux-x86_64-ubuntu2204-7.0.1 mongodb + mkdir data + mkdir log + chown -R volttron /databases/mongodb + export PATH=$PATH:/databases/mongodb/mongodb/bin + echo 'export PATH=$PATH:/databases/mongodb/mongodb/bin' >> /home/volttron/.bashrc + echo "alias start_mongo='mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --fork'" >> /home/volttron/.bash_aliases + echo "alias stop_mongo='mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --shutdown'" >> /home/volttron/.bash_aliases + su volttron -c "/databases/mongodb/mongodb/bin/mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --fork" + wget https://downloads.mongodb.com/compass/mongosh-1.10.6-linux-x64-openssl3.tgz + tar -xvzf mongosh-1.10.6-linux-x64-openssl3.tgz + mv mongosh-1.10.6-linux-x64-openssl3/bin/* /databases/mongodb/mongodb/bin + chmod a+x /databases/mongodb/mongodb/bin/mongosh + mongosh admin --eval 'db.createUser( {user: "admin", pwd: "volttron", roles: [ { role: "userAdminAnyDatabase", db: "admin" }]});' + mongosh test_historian -u admin -p volttron --authenticationDatabase admin --eval 'db.createUser( {user: "historian", pwd: "historian", roles: [ { role: "readWrite", db: "test_historian" }]});' + su volttron -c "/databases/mongodb/mongodb/bin/mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --shutdown" +} + + +function install_mysql(){ + apt-get install -y libaio1 libncurses5 libnuma1 + mkdir -p /databases/mysql + cd /databases/mysql + wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.25-linux-glibc2.12-x86_64.tar.xz + tar -xvf mysql-8.0.25-linux-glibc2.12-x86_64.tar.xz + ln -s mysql-8.0.25-linux-glibc2.12-x86_64 mysql + groupadd mysql + useradd -r -g mysql -s /bin/false mysql + mkdir mysql-files data etc log + chmod 750 mysql-files data etc log + echo "[mysqld]" > etc/my.cnf + echo "basedir=/databases/mysql/mysql" >> etc/my.cnf + echo "datadir=/databases/mysql/data" >> etc/my.cnf + echo "log-error=/databases/mysql/log/mysql.err" >> etc/my.cnf + cd /databases/mysql + cp mysql/support-files/mysql.server mysql/bin + chown -R mysql:mysql /databases/mysql + export PATH=/databases/mysql/mysql/bin:$PATH + echo 'export PATH=/databases/mysql/mysql/bin:$PATH' >> /root/.bashrc + echo 'export PATH=/databases/mysql/mysql/bin:$PATH' >> /home/volttron/.bashrc + echo "alias start_mysql='sudo /databases/mysql/mysql/bin/mysql.server start'" >> /home/volttron/.bash_aliases + echo "alias stop_mysql='sudo /databases/mysql/mysql/bin/mysql.server stop'" >> /home/volttron/.bash_aliases + mysqld --defaults-file=/databases/mysql/etc/my.cnf --initialize-insecure --user=mysql + sed -i 's/^basedir=/basedir=\/databases\/mysql\/mysql/' /databases/mysql/mysql/bin/mysql.server + sed -i 's/^datadir=/datadir=\/databases\/mysql\/data/' /databases/mysql/mysql/bin/mysql.server + mysql.server start + mysql -u root -e "CREATE DATABASE test_historian;" + mysql -u root -e "CREATE USER 'historian'@'localhost' IDENTIFIED BY 'historian';" + mysql -u root -e "GRANT SELECT, INSERT, DELETE, CREATE, INDEX, UPDATE, DROP ON test_historian.* TO 'historian'@'localhost';" + mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'volttron';" + mysql.server stop +} + + +function install_postgresql(){ + apt-get install -y libreadline8 libreadline-dev zlib1g-dev + mkdir -p /databases/postgresql + cd /databases/postgresql + wget https://ftp.postgresql.org/pub/source/v10.16/postgresql-10.16.tar.gz + tar -xvzf postgresql-10.16.tar.gz + ln -s postgresql-10.16 postgresql_source + cd postgresql_source + ./configure --prefix=/databases/postgresql/pgsql + make + make install + echo 'export LD_LIBRARY_PATH=/databases/postgresql/pgsql/lib' >> /home/volttron/.bashrc + export LD_LIBRARY_PATH=/databases/postgresql/pgsql/lib + echo 'export PATH=/databases/postgresql/pgsql/bin:$PATH' >> /home/volttron/.bashrc + export PATH=/databases/postgresql/pgsql/bin:$PATH + export LD_LIBRARY_PATH=/databases/postgresql/pgsql/lib + ln -s /databases/postgresql/pgsql/lib/libpq.so.5 /usr/lib/libpq.so.5 + adduser --disabled-password --gecos "" postgres + mkdir /databases/postgresql/pgsql/data + chown -R postgres /databases/postgresql + su postgres -c "/databases/postgresql/pgsql/bin/initdb -D /databases/postgresql/pgsql/data" + echo "alias start_postgres='sudo su postgres -c \"/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile start\"'" >> /home/volttron/.bash_aliases + echo "alias stop_postgres='sudo su postgres -c \"/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile stop\"'" >> /home/volttron/.bash_aliases + sudo su postgres -c "/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile start" + psql -U postgres -c 'CREATE DATABASE test_historian;' + psql -U postgres -c "CREATE USER historian with encrypted password 'historian';" + psql -U postgres -c "GRANT ALL PRIVILEGES on database test_historian to historian;" + sudo su postgres -c "/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile stop" +} + +echo "Configured to install dbs: $@" +v=( "$@" ) +for i in ${v[@]} +do + echo "Calling install_$i" + install_$i +done From f8a57527c03b37d596c41bc23bdc169db9536213 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 12:13:21 -0700 Subject: [PATCH 24/36] minor documentation update --- README.md | 3 ++- docs/source/introduction/platform-install.rst | 3 ++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 5da7b8d078..f44c25242e 100644 --- a/README.md +++ b/README.md @@ -159,7 +159,8 @@ connect to empd (port 4369) on ." Note: RabbitMQ startup error would s and not in RabbitMQ logs (/var/log/rabbitmq/rabbitmq@hostname.log) ##### 3. Bootstrap -Remove older version of rabbitmq_server directory. Defaults to /rabbitmq_server/rabbitmq_server-3.9.7 +Remove older version of rabbitmq_server directory if you are upgrading from a older version. +Defaults to /rabbitmq_server/rabbitmq_server-3.9.7 Run the rabbitmq boostrap command within an activated VOLTTRON environment diff --git a/docs/source/introduction/platform-install.rst b/docs/source/introduction/platform-install.rst index 3f806339b6..0e98705726 100644 --- a/docs/source/introduction/platform-install.rst +++ b/docs/source/introduction/platform-install.rst @@ -247,7 +247,8 @@ to connect to empd (port 4369) on ." Step 4 - Bootstrap the environment ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ -Remove older version of rabbitmq_server directory. Defaults to /rabbitmq_server/rabbitmq_server-3.9.7 +Remove older version of rabbitmq_server directory if you are upgrading from a older version. Defaults to +/rabbitmq_server/rabbitmq_server-3.9.7 Run the rabbitmq bootstrap step from within an VOLTTRON activated environment. .. code-block:: bash From b4e62ccfc3c7cea06aa8719112caf03a700fa3ee Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 12:17:30 -0700 Subject: [PATCH 25/36] changed 'urllib3.connectionpool' log level to warning --- volttron/platform/main.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/volttron/platform/main.py b/volttron/platform/main.py index 9df02431b1..ed3b62415b 100644 --- a/volttron/platform/main.py +++ b/volttron/platform/main.py @@ -135,7 +135,6 @@ log_level_info = ( #'volttron.platform.main', 'volttron.platform.vip.zmq_connection', - 'urllib3.connectionpool', 'watchdog.observers.inotify_buffer', 'volttron.platform.auth', 'volttron.platform.store', @@ -148,6 +147,8 @@ for log_name in log_level_info: logging.getLogger(log_name).setLevel(logging.INFO) +logging.getLogger('urllib3.connectionpool').setLevel(logging.WARNING) + VOLTTRON_INSTANCES = '~/.volttron_instances' From c23e2a3161fc389043cb7e011183983991638db1 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 13:55:54 -0700 Subject: [PATCH 26/36] updated auth test on github --- .github/workflows/pytest-auth.yml | 20 ++++++++------------ 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index 6bbd6b0795..ee8764a01e 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -23,29 +23,25 @@ jobs: # https://docs.github.com/en/free-pro-team@l.atest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategy strategy: fail-fast: false - matrix: - # Each entry in the os and python-version matrix will be run so for the 3 x 4 there will be 12 jobs run - os: [ ubuntu-20.04 ] - python-version: [ 3.8 ] # Run-on determines the operating system available to run on # - At the current time there is only ubuntu machines between 16.04 and 20.04 available # - This uses the matrix os from the strategy above - runs-on: ${{ matrix.os }} + runs-on: ${{ ubuntu-20.04, ubuntu-22.04 }} # Each step will be run in order of listing. steps: # checkout the volttron repository and set current direectory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # setup the python environment for the operating system - - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 - with: - python-version: ${{ matrix.python-version }} +# - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} +# uses: actions/setup-python@v2 +# with: +# python-version: ${{ matrix.python-version }} # Run the specified tests and save the results to a unique file that can be archived for later analysis. - - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} + - name: Run pytest on ${{ env.RUNNER_OS }} uses: volttron/volttron-build-action@v4 with: python_version: ${{ matrix.python-version }} @@ -59,7 +55,7 @@ jobs: if: always() with: name: pytest-report - path: output/test-auth-${{matrix.os}}-${{ matrix.python-version }}-results.xml + path: output/test-auth-${{ env.RUNNER_OS }}-results.xml # - name: Publish Unit Test Results # uses: EnricoMi/publish-unit-test-result-action@v1.5 From 4828102521a30d12986bc7fe2b11c9d959333543 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 14:08:51 -0700 Subject: [PATCH 27/36] updated auth test on github --- .github/workflows/pytest-auth.yml | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index ee8764a01e..af8f8ed246 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -56,23 +56,3 @@ jobs: with: name: pytest-report path: output/test-auth-${{ env.RUNNER_OS }}-results.xml - -# - name: Publish Unit Test Results -# uses: EnricoMi/publish-unit-test-result-action@v1.5 -# if: always() -# with: -# github_token: ${{ secrets.WORKFLOW_ACCESS_TOKEN }} -# files: output/test-testutils*.xml - - -#-cov=com --cov-report=xml --cov-report=html -# pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html -# - name: Lint with flake8 -# run: | -# # stop the build if there are Python syntax errors or undefined names -# flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics -# # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide -# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics -# - name: Test with pytest -# run: | -# pytest --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html From c8a685765669c72f580ae74f59309a6d2a1d6b5e Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 14:16:23 -0700 Subject: [PATCH 28/36] fixed runner name --- .github/workflows/pytest-auth.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index af8f8ed246..171e42a2c9 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -27,7 +27,7 @@ jobs: # Run-on determines the operating system available to run on # - At the current time there is only ubuntu machines between 16.04 and 20.04 available # - This uses the matrix os from the strategy above - runs-on: ${{ ubuntu-20.04, ubuntu-22.04 }} + runs-on: ['ubuntu-20.04','ubuntu-22.04'] # Each step will be run in order of listing. steps: From a7ada4d8ab3309d969f4d4b98a3bcfc2ca815a30 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 14:47:08 -0700 Subject: [PATCH 29/36] fixed runner name --- .github/workflows/pytest-auth.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index 171e42a2c9..6a07801287 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -27,7 +27,7 @@ jobs: # Run-on determines the operating system available to run on # - At the current time there is only ubuntu machines between 16.04 and 20.04 available # - This uses the matrix os from the strategy above - runs-on: ['ubuntu-20.04','ubuntu-22.04'] + runs-on: [ubuntu-20.04, ubuntu-22.04] # Each step will be run in order of listing. steps: From 25872090591077fc1035c03e61659c6777b49065 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Fri, 15 Sep 2023 16:15:38 -0700 Subject: [PATCH 30/36] reverting runner name change --- .github/workflows/pytest-auth.yml | 38 +++++++++++++++++++++++++------ 1 file changed, 31 insertions(+), 7 deletions(-) diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index 6a07801287..c28937a06d 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -23,11 +23,15 @@ jobs: # https://docs.github.com/en/free-pro-team@l.atest/actions/reference/workflow-syntax-for-github-actions#jobsjob_idstrategy strategy: fail-fast: false + matrix: + # Each entry in the os and python-version matrix will be run so for the 3 x 4 there will be 12 jobs run + os: [ ubuntu-20.04 ] + python-version: [ 3.8 ] # Run-on determines the operating system available to run on # - At the current time there is only ubuntu machines between 16.04 and 20.04 available # - This uses the matrix os from the strategy above - runs-on: [ubuntu-20.04, ubuntu-22.04] + runs-on: ${{ matrix.os }} # Each step will be run in order of listing. steps: @@ -35,13 +39,13 @@ jobs: - uses: actions/checkout@v4 # setup the python environment for the operating system -# - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} -# uses: actions/setup-python@v2 -# with: -# python-version: ${{ matrix.python-version }} + - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} + uses: actions/setup-python@v2 + with: + python-version: ${{ matrix.python-version }} # Run the specified tests and save the results to a unique file that can be archived for later analysis. - - name: Run pytest on ${{ env.RUNNER_OS }} + - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} uses: volttron/volttron-build-action@v4 with: python_version: ${{ matrix.python-version }} @@ -55,4 +59,24 @@ jobs: if: always() with: name: pytest-report - path: output/test-auth-${{ env.RUNNER_OS }}-results.xml + path: output/test-auth-${{matrix.os}}-${{ matrix.python-version }}-results.xml + +# - name: Publish Unit Test Results +# uses: EnricoMi/publish-unit-test-result-action@v1.5 +# if: always() +# with: +# github_token: ${{ secrets.WORKFLOW_ACCESS_TOKEN }} +# files: output/test-testutils*.xml + + +#-cov=com --cov-report=xml --cov-report=html +# pytest tests.py --doctest-modules --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html +# - name: Lint with flake8 +# run: | +# # stop the build if there are Python syntax errors or undefined names +# flake8 . --count --select=E9,F63,F7,F82 --show-source --statistics +# # exit-zero treats all errors as warnings. The GitHub editor is 127 chars wide +# flake8 . --count --exit-zero --max-complexity=10 --max-line-length=127 --statistics +# - name: Test with pytest +# run: | +# pytest --junitxml=junit/test-results.xml --cov=com --cov-report=xml --cov-report=html From f5fbaf5b0436fce3b23afa80292329161fd48964 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Sat, 16 Sep 2023 17:11:16 -0700 Subject: [PATCH 31/36] using newer version of actions --- .github/workflows/code_analysis.yml | 2 +- .github/workflows/pytest-auth.yml | 6 +++--- .github/workflows/pytest-dbutils-backup_db.yml | 6 +++--- .github/workflows/pytest-dbutils-influxdbfuncts.yml | 6 +++--- .github/workflows/pytest-dbutils-mysqlfuncts.yml | 6 +++--- .github/workflows/pytest-dbutils-postgresqlfuncts.yml | 6 +++--- .github/workflows/pytest-dbutils-sqlitefuncts.yml | 6 +++--- .github/workflows/pytest-dbutils-timescaldbfuncts.yml | 6 +++--- .github/workflows/pytest-miscellaneous-tests.yml | 6 +++--- .github/workflows/pytest-testutils.yml | 6 +++--- .github/workflows/pytest-vctl.yml | 6 +++--- .github/workflows/pytest-web.yml | 6 +++--- 12 files changed, 34 insertions(+), 34 deletions(-) diff --git a/.github/workflows/code_analysis.yml b/.github/workflows/code_analysis.yml index f7704d8e7a..c944c9a1bc 100644 --- a/.github/workflows/code_analysis.yml +++ b/.github/workflows/code_analysis.yml @@ -38,7 +38,7 @@ jobs: steps: - name: Checkout repository - uses: actions/checkout@v2 + uses: actions/checkout@v4 # Initializes the CodeQL tools for scanning. - name: Initialize CodeQL diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index 6bbd6b0795..518e2a8350 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -36,17 +36,17 @@ jobs: # Each step will be run in order of listing. steps: # checkout the volttron repository and set current direectory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # setup the python environment for the operating system - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-dbutils-backup_db.yml b/.github/workflows/pytest-dbutils-backup_db.yml index 5094808140..b901847ee4 100644 --- a/.github/workflows/pytest-dbutils-backup_db.yml +++ b/.github/workflows/pytest-dbutils-backup_db.yml @@ -46,11 +46,11 @@ jobs: steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # setup the python environment for the operating system - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -60,7 +60,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-influxdbfuncts.yml b/.github/workflows/pytest-dbutils-influxdbfuncts.yml index 74b34d8386..3d0f8e526d 100644 --- a/.github/workflows/pytest-dbutils-influxdbfuncts.yml +++ b/.github/workflows/pytest-dbutils-influxdbfuncts.yml @@ -35,12 +35,12 @@ jobs: steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Attempt to restore the cache from the build-dependency-cache workflow if present then # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-mysqlfuncts.yml b/.github/workflows/pytest-dbutils-mysqlfuncts.yml index 3feab4f759..d12726329d 100644 --- a/.github/workflows/pytest-dbutils-mysqlfuncts.yml +++ b/.github/workflows/pytest-dbutils-mysqlfuncts.yml @@ -35,12 +35,12 @@ jobs: steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Attempt to restore the cache from the build-dependency-cache workflow if present then # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-postgresqlfuncts.yml b/.github/workflows/pytest-dbutils-postgresqlfuncts.yml index 27d4e44e9a..d27eaaeb32 100644 --- a/.github/workflows/pytest-dbutils-postgresqlfuncts.yml +++ b/.github/workflows/pytest-dbutils-postgresqlfuncts.yml @@ -35,12 +35,12 @@ jobs: steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Attempt to restore the cache from the build-dependency-cache workflow if present then # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-sqlitefuncts.yml b/.github/workflows/pytest-dbutils-sqlitefuncts.yml index 9849b05a1c..4ac6dbf553 100644 --- a/.github/workflows/pytest-dbutils-sqlitefuncts.yml +++ b/.github/workflows/pytest-dbutils-sqlitefuncts.yml @@ -35,12 +35,12 @@ jobs: steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Attempt to restore the cache from the build-dependency-cache workflow if present then # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -51,7 +51,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-timescaldbfuncts.yml b/.github/workflows/pytest-dbutils-timescaldbfuncts.yml index fe0ed71700..959df3a72e 100644 --- a/.github/workflows/pytest-dbutils-timescaldbfuncts.yml +++ b/.github/workflows/pytest-dbutils-timescaldbfuncts.yml @@ -35,12 +35,12 @@ jobs: steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Attempt to restore the cache from the build-dependency-cache workflow if present then # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-miscellaneous-tests.yml b/.github/workflows/pytest-miscellaneous-tests.yml index 7fdf36ed5b..3a14f4c8de 100644 --- a/.github/workflows/pytest-miscellaneous-tests.yml +++ b/.github/workflows/pytest-miscellaneous-tests.yml @@ -44,17 +44,17 @@ jobs: # Each step will be run in order of listing. steps: # Checkout the volttron repository and set current direectory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Setup the python environment for the operating system - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} # Run the specified tests and save the results to a unique file that can be archived for later analysis - name: Run certs test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-testutils.yml b/.github/workflows/pytest-testutils.yml index fc66ffc531..35d3171800 100644 --- a/.github/workflows/pytest-testutils.yml +++ b/.github/workflows/pytest-testutils.yml @@ -34,18 +34,18 @@ jobs: steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Attempt to restore the cache from the build-dependency-cache workflow if present then # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-vctl.yml b/.github/workflows/pytest-vctl.yml index 22b2f165c1..5dce16a0b7 100644 --- a/.github/workflows/pytest-vctl.yml +++ b/.github/workflows/pytest-vctl.yml @@ -45,18 +45,18 @@ jobs: # Each step will be run in order of listing. steps: # checkout the volttron repository and set current directory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # Attempt to restore the cache from the build-dependency-cache workflow if present then # the output value steps.check_files.outputs.files_exists will be set (see the next step for usage) - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-web.yml b/.github/workflows/pytest-web.yml index 89045fe67a..71e81986e4 100644 --- a/.github/workflows/pytest-web.yml +++ b/.github/workflows/pytest-web.yml @@ -44,17 +44,17 @@ jobs: # Each step will be run in order of listing. steps: # checkout the volttron repository and set current direectory to it - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 # setup the python environment for the operating system - name: Set up Python ${{matrix.os}} ${{ matrix.python-version }} - uses: actions/setup-python@v2 + uses: actions/setup-python@v4 with: python-version: ${{ matrix.python-version }} # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} From 5ac18d2a16f3bdab66840de5de415fd84b28c4de Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Sat, 16 Sep 2023 17:28:46 -0700 Subject: [PATCH 32/36] using newer version of actions --- .github/workflows/pytest-miscellaneous-tests.yml | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/pytest-miscellaneous-tests.yml b/.github/workflows/pytest-miscellaneous-tests.yml index 3a14f4c8de..be8762d002 100644 --- a/.github/workflows/pytest-miscellaneous-tests.yml +++ b/.github/workflows/pytest-miscellaneous-tests.yml @@ -62,7 +62,7 @@ jobs: test_output_suffix: misc - name: Run core agent test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} @@ -70,7 +70,7 @@ jobs: test_output_suffix: misc - name: Run packaging test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} @@ -78,7 +78,7 @@ jobs: test_output_suffix: misc - name: Run platform init test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} @@ -86,7 +86,7 @@ jobs: test_output_suffix: misc - name: Run sqlite3 test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@v4 + uses: volttron/volttron-build-action@erlang_update with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} From 5f2b23aef015c7cbd7c9d80bef24b0536ebda50e Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Mon, 18 Sep 2023 14:45:27 -0700 Subject: [PATCH 33/36] testing only on mysql 8 --- volttrontesting/platform/dbutils/test_mysqlfuncts.py | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/volttrontesting/platform/dbutils/test_mysqlfuncts.py b/volttrontesting/platform/dbutils/test_mysqlfuncts.py index 67c78bb978..17d4ddc524 100644 --- a/volttrontesting/platform/dbutils/test_mysqlfuncts.py +++ b/volttrontesting/platform/dbutils/test_mysqlfuncts.py @@ -23,9 +23,7 @@ IMAGES = [ - "mysql:8.0", - "mysql:5.7.35", - "mysql:5.6" + "mysql:8.0" ] CONNECTION_HOST = "localhost" From e5125b913b55453bc3a8013e3936ef2a627a127f Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Tue, 19 Sep 2023 10:19:19 -0700 Subject: [PATCH 34/36] Updated upload artifact version --- .github/workflows/pytest-auth.yml | 2 +- .github/workflows/pytest-dbutils-backup_db.yml | 2 +- .github/workflows/pytest-dbutils-influxdbfuncts.yml | 2 +- .github/workflows/pytest-dbutils-mysqlfuncts.yml | 2 +- .github/workflows/pytest-dbutils-postgresqlfuncts.yml | 2 +- .github/workflows/pytest-dbutils-sqlitefuncts.yml | 2 +- .github/workflows/pytest-dbutils-timescaldbfuncts.yml | 2 +- .github/workflows/pytest-miscellaneous-tests.yml | 2 +- .github/workflows/pytest-testutils.yml | 2 +- .github/workflows/pytest-vctl.yml | 2 +- .github/workflows/pytest-web.yml | 2 +- 11 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index fab87f0f2e..0aa8321f8e 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -55,7 +55,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-dbutils-backup_db.yml b/.github/workflows/pytest-dbutils-backup_db.yml index b901847ee4..44835c2505 100644 --- a/.github/workflows/pytest-dbutils-backup_db.yml +++ b/.github/workflows/pytest-dbutils-backup_db.yml @@ -70,7 +70,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-dbutils-influxdbfuncts.yml b/.github/workflows/pytest-dbutils-influxdbfuncts.yml index 3d0f8e526d..e3808c98d3 100644 --- a/.github/workflows/pytest-dbutils-influxdbfuncts.yml +++ b/.github/workflows/pytest-dbutils-influxdbfuncts.yml @@ -60,7 +60,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-dbutils-mysqlfuncts.yml b/.github/workflows/pytest-dbutils-mysqlfuncts.yml index d12726329d..11b9bd1691 100644 --- a/.github/workflows/pytest-dbutils-mysqlfuncts.yml +++ b/.github/workflows/pytest-dbutils-mysqlfuncts.yml @@ -60,7 +60,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-dbutils-postgresqlfuncts.yml b/.github/workflows/pytest-dbutils-postgresqlfuncts.yml index d27eaaeb32..60e914d81c 100644 --- a/.github/workflows/pytest-dbutils-postgresqlfuncts.yml +++ b/.github/workflows/pytest-dbutils-postgresqlfuncts.yml @@ -60,7 +60,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-dbutils-sqlitefuncts.yml b/.github/workflows/pytest-dbutils-sqlitefuncts.yml index 4ac6dbf553..806f377f4e 100644 --- a/.github/workflows/pytest-dbutils-sqlitefuncts.yml +++ b/.github/workflows/pytest-dbutils-sqlitefuncts.yml @@ -60,7 +60,7 @@ jobs: test_output_suffix: ${{ env.OUTPUT_SUFFIX }} - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-dbutils-timescaldbfuncts.yml b/.github/workflows/pytest-dbutils-timescaldbfuncts.yml index 959df3a72e..5cc15f1e28 100644 --- a/.github/workflows/pytest-dbutils-timescaldbfuncts.yml +++ b/.github/workflows/pytest-dbutils-timescaldbfuncts.yml @@ -60,7 +60,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-miscellaneous-tests.yml b/.github/workflows/pytest-miscellaneous-tests.yml index be8762d002..f1a8c86755 100644 --- a/.github/workflows/pytest-miscellaneous-tests.yml +++ b/.github/workflows/pytest-miscellaneous-tests.yml @@ -95,7 +95,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-testutils.yml b/.github/workflows/pytest-testutils.yml index 35d3171800..a56a559f2b 100644 --- a/.github/workflows/pytest-testutils.yml +++ b/.github/workflows/pytest-testutils.yml @@ -54,7 +54,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-vctl.yml b/.github/workflows/pytest-vctl.yml index 5dce16a0b7..00d04c9043 100644 --- a/.github/workflows/pytest-vctl.yml +++ b/.github/workflows/pytest-vctl.yml @@ -65,7 +65,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report diff --git a/.github/workflows/pytest-web.yml b/.github/workflows/pytest-web.yml index 71e81986e4..da3b52d0a9 100644 --- a/.github/workflows/pytest-web.yml +++ b/.github/workflows/pytest-web.yml @@ -63,7 +63,7 @@ jobs: # Archive the results from the pytest to storage. - name: Archive test results - uses: actions/upload-artifact@v2 + uses: actions/upload-artifact@v3 if: always() with: name: pytest-report From f1459a83cabe3e4861225cdfac1a9977a66f4509 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Tue, 19 Sep 2023 13:01:36 -0700 Subject: [PATCH 35/36] install-script for dbs on ubuntu 20.04 --- .../install-dbs-ubuntu-2004.sh | 110 ++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100755 scripts/historian-scripts/install-dbs-ubuntu-2004.sh diff --git a/scripts/historian-scripts/install-dbs-ubuntu-2004.sh b/scripts/historian-scripts/install-dbs-ubuntu-2004.sh new file mode 100755 index 0000000000..91cbe97564 --- /dev/null +++ b/scripts/historian-scripts/install-dbs-ubuntu-2004.sh @@ -0,0 +1,110 @@ +#! /bin/bash + + # Utility script for installing mysql, mongodb, and postgresql on Ubuntu 22.04 and creates test data base and test + # db user for testing volttron agents that use these databases. Installs databases on a /databases + # folder and assumes the unix user running VOLTTRON is "volttron" + # You can use this as a reference, update database versions and user name as needed to install database environment for + # testing volttron agents + # To run provide execute permissions and pass one or more database names as input + # For example + # ./install-dbs-ubuntu-2204.sh mongodb mysql postgresql + # ./install-dbs-ubuntu-2204.sh mongodb + # ./install-dbs-ubuntu-2204.sh mysql + +function install_mongodb(){ + mkdir -p /databases/mongodb + cd /databases/mongodb + sudo apt-get install -y libcurl4 openssl liblzma5 + wget https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-7.0.1.tgz + tar -xvzf mongodb-linux-x86_64-ubuntu2004-7.0.1.tgz + ln -s mongodb-linux-x86_64-ubuntu2004-7.0.1 mongodb + mkdir data + mkdir log + chown -R volttron /databases/mongodb + export PATH=$PATH:/databases/mongodb/mongodb/bin + echo 'export PATH=$PATH:/databases/mongodb/mongodb/bin' >> /home/volttron/.bashrc + echo "alias start_mongo='mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --fork'" >> /home/volttron/.bash_aliases + echo "alias stop_mongo='mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --shutdown'" >> /home/volttron/.bash_aliases + su volttron -c "/databases/mongodb/mongodb/bin/mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --fork" + wget https://downloads.mongodb.com/compass/mongosh-1.10.6-linux-x64-openssl11.tgz + tar -xvzf mongosh-1.10.6-linux-x64-openssl11.tgz + mv mongosh-1.10.6-linux-x64-openssl11/bin/* /databases/mongodb/mongodb/bin + chmod a+x /databases/mongodb/mongodb/bin/mongosh + mongosh admin --eval 'db.createUser( {user: "admin", pwd: "volttron", roles: [ { role: "userAdminAnyDatabase", db: "admin" }]});' + mongosh test_historian -u admin -p volttron --authenticationDatabase admin --eval 'db.createUser( {user: "historian", pwd: "historian", roles: [ { role: "readWrite", db: "test_historian" }]});' + su volttron -c "/databases/mongodb/mongodb/bin/mongod --dbpath /databases/mongodb/data --logpath /databases/mongodb/log/mongod.log --shutdown" +} + + +function install_mysql(){ + apt-get install -y libaio1 libncurses5 libnuma1 + mkdir -p /databases/mysql + cd /databases/mysql + wget https://downloads.mysql.com/archives/get/p/23/file/mysql-8.0.25-linux-glibc2.12-x86_64.tar.xz + tar -xvf mysql-8.0.25-linux-glibc2.12-x86_64.tar.xz + ln -s mysql-8.0.25-linux-glibc2.12-x86_64 mysql + groupadd mysql + useradd -r -g mysql -s /bin/false mysql + mkdir mysql-files data etc log + chmod 750 mysql-files data etc log + echo "[mysqld]" > etc/my.cnf + echo "basedir=/databases/mysql/mysql" >> etc/my.cnf + echo "datadir=/databases/mysql/data" >> etc/my.cnf + echo "log-error=/databases/mysql/log/mysql.err" >> etc/my.cnf + cd /databases/mysql + cp mysql/support-files/mysql.server mysql/bin + chown -R mysql:mysql /databases/mysql + export PATH=/databases/mysql/mysql/bin:$PATH + echo 'export PATH=/databases/mysql/mysql/bin:$PATH' >> /root/.bashrc + echo 'export PATH=/databases/mysql/mysql/bin:$PATH' >> /home/volttron/.bashrc + echo "alias start_mysql='sudo /databases/mysql/mysql/bin/mysql.server start'" >> /home/volttron/.bash_aliases + echo "alias stop_mysql='sudo /databases/mysql/mysql/bin/mysql.server stop'" >> /home/volttron/.bash_aliases + mysqld --defaults-file=/databases/mysql/etc/my.cnf --initialize-insecure --user=mysql + sed -i 's/^basedir=/basedir=\/databases\/mysql\/mysql/' /databases/mysql/mysql/bin/mysql.server + sed -i 's/^datadir=/datadir=\/databases\/mysql\/data/' /databases/mysql/mysql/bin/mysql.server + mysql.server start + mysql -u root -e "CREATE DATABASE test_historian;" + mysql -u root -e "CREATE USER 'historian'@'localhost' IDENTIFIED BY 'historian';" + mysql -u root -e "GRANT SELECT, INSERT, DELETE, CREATE, INDEX, UPDATE, DROP ON test_historian.* TO 'historian'@'localhost';" + mysql -u root -e "ALTER USER 'root'@'localhost' IDENTIFIED BY 'volttron';" + mysql.server stop +} + + +function install_postgresql(){ + apt-get install -y libreadline8 libreadline-dev zlib1g-dev + mkdir -p /databases/postgresql + cd /databases/postgresql + wget https://ftp.postgresql.org/pub/source/v10.16/postgresql-10.16.tar.gz + tar -xvzf postgresql-10.16.tar.gz + ln -s postgresql-10.16 postgresql_source + cd postgresql_source + ./configure --prefix=/databases/postgresql/pgsql + make + make install + echo 'export LD_LIBRARY_PATH=/databases/postgresql/pgsql/lib' >> /home/volttron/.bashrc + export LD_LIBRARY_PATH=/databases/postgresql/pgsql/lib + echo 'export PATH=/databases/postgresql/pgsql/bin:$PATH' >> /home/volttron/.bashrc + export PATH=/databases/postgresql/pgsql/bin:$PATH + export LD_LIBRARY_PATH=/databases/postgresql/pgsql/lib + ln -s /databases/postgresql/pgsql/lib/libpq.so.5 /usr/lib/libpq.so.5 + adduser --disabled-password --gecos "" postgres + mkdir /databases/postgresql/pgsql/data + chown -R postgres /databases/postgresql + su postgres -c "/databases/postgresql/pgsql/bin/initdb -D /databases/postgresql/pgsql/data" + echo "alias start_postgres='sudo su postgres -c \"/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile start\"'" >> /home/volttron/.bash_aliases + echo "alias stop_postgres='sudo su postgres -c \"/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile stop\"'" >> /home/volttron/.bash_aliases + sudo su postgres -c "/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile start" + psql -U postgres -c 'CREATE DATABASE test_historian;' + psql -U postgres -c "CREATE USER historian with encrypted password 'historian';" + psql -U postgres -c "GRANT ALL PRIVILEGES on database test_historian to historian;" + sudo su postgres -c "/databases/postgresql/pgsql/bin/pg_ctl -D /databases/postgresql/pgsql/data -l /databases/postgresql/logfile stop" +} + +echo "Configured to install dbs: $@" +v=( "$@" ) +for i in ${v[@]} +do + echo "Calling install_$i" + install_$i +done From dc63d9bf90be7e65478dbfd10d1eb73dfb535a91 Mon Sep 17 00:00:00 2001 From: Chandrika Sivaramakrishnan Date: Wed, 20 Sep 2023 14:38:20 -0700 Subject: [PATCH 36/36] pointing to v5 version of volttron-build-action instead of branch erlang_update --- .github/workflows/pytest-auth.yml | 2 +- .github/workflows/pytest-dbutils-backup_db.yml | 2 +- .github/workflows/pytest-dbutils-influxdbfuncts.yml | 2 +- .github/workflows/pytest-dbutils-mysqlfuncts.yml | 2 +- .github/workflows/pytest-dbutils-postgresqlfuncts.yml | 2 +- .github/workflows/pytest-dbutils-sqlitefuncts.yml | 2 +- .github/workflows/pytest-dbutils-timescaldbfuncts.yml | 2 +- .github/workflows/pytest-miscellaneous-tests.yml | 10 +++++----- .github/workflows/pytest-testutils.yml | 2 +- .github/workflows/pytest-vctl.yml | 2 +- .github/workflows/pytest-web.yml | 2 +- 11 files changed, 15 insertions(+), 15 deletions(-) diff --git a/.github/workflows/pytest-auth.yml b/.github/workflows/pytest-auth.yml index 0aa8321f8e..e285dd6593 100644 --- a/.github/workflows/pytest-auth.yml +++ b/.github/workflows/pytest-auth.yml @@ -46,7 +46,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-dbutils-backup_db.yml b/.github/workflows/pytest-dbutils-backup_db.yml index 44835c2505..94fb96e338 100644 --- a/.github/workflows/pytest-dbutils-backup_db.yml +++ b/.github/workflows/pytest-dbutils-backup_db.yml @@ -60,7 +60,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-influxdbfuncts.yml b/.github/workflows/pytest-dbutils-influxdbfuncts.yml index e3808c98d3..2ce37659e3 100644 --- a/.github/workflows/pytest-dbutils-influxdbfuncts.yml +++ b/.github/workflows/pytest-dbutils-influxdbfuncts.yml @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-mysqlfuncts.yml b/.github/workflows/pytest-dbutils-mysqlfuncts.yml index 11b9bd1691..4219c12f1a 100644 --- a/.github/workflows/pytest-dbutils-mysqlfuncts.yml +++ b/.github/workflows/pytest-dbutils-mysqlfuncts.yml @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-postgresqlfuncts.yml b/.github/workflows/pytest-dbutils-postgresqlfuncts.yml index 60e914d81c..ce833e6888 100644 --- a/.github/workflows/pytest-dbutils-postgresqlfuncts.yml +++ b/.github/workflows/pytest-dbutils-postgresqlfuncts.yml @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-sqlitefuncts.yml b/.github/workflows/pytest-dbutils-sqlitefuncts.yml index 806f377f4e..8a6969308e 100644 --- a/.github/workflows/pytest-dbutils-sqlitefuncts.yml +++ b/.github/workflows/pytest-dbutils-sqlitefuncts.yml @@ -51,7 +51,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-dbutils-timescaldbfuncts.yml b/.github/workflows/pytest-dbutils-timescaldbfuncts.yml index 5cc15f1e28..8a82239a96 100644 --- a/.github/workflows/pytest-dbutils-timescaldbfuncts.yml +++ b/.github/workflows/pytest-dbutils-timescaldbfuncts.yml @@ -50,7 +50,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 timeout-minutes: 600 with: python_version: ${{ matrix.python-version }} diff --git a/.github/workflows/pytest-miscellaneous-tests.yml b/.github/workflows/pytest-miscellaneous-tests.yml index f1a8c86755..e1756d414b 100644 --- a/.github/workflows/pytest-miscellaneous-tests.yml +++ b/.github/workflows/pytest-miscellaneous-tests.yml @@ -54,7 +54,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis - name: Run certs test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} @@ -62,7 +62,7 @@ jobs: test_output_suffix: misc - name: Run core agent test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} @@ -70,7 +70,7 @@ jobs: test_output_suffix: misc - name: Run packaging test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} @@ -78,7 +78,7 @@ jobs: test_output_suffix: misc - name: Run platform init test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} @@ -86,7 +86,7 @@ jobs: test_output_suffix: misc - name: Run sqlite3 test on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-testutils.yml b/.github/workflows/pytest-testutils.yml index a56a559f2b..a1c2923458 100644 --- a/.github/workflows/pytest-testutils.yml +++ b/.github/workflows/pytest-testutils.yml @@ -45,7 +45,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-vctl.yml b/.github/workflows/pytest-vctl.yml index 00d04c9043..a36a881740 100644 --- a/.github/workflows/pytest-vctl.yml +++ b/.github/workflows/pytest-vctl.yml @@ -56,7 +56,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }} diff --git a/.github/workflows/pytest-web.yml b/.github/workflows/pytest-web.yml index da3b52d0a9..36fcb8905f 100644 --- a/.github/workflows/pytest-web.yml +++ b/.github/workflows/pytest-web.yml @@ -54,7 +54,7 @@ jobs: # Run the specified tests and save the results to a unique file that can be archived for later analysis. - name: Run pytest on ${{ matrix.python-version }}, ${{ matrix.os }} - uses: volttron/volttron-build-action@erlang_update + uses: volttron/volttron-build-action@v5 with: python_version: ${{ matrix.python-version }} os: ${{ matrix.os }}